Skip to content

Commit b8f029c

Browse files
committed
[flang] Accept legacy aliases for intrinsic function names
Support the names AND, OR, and XOR for the generic intrinsic functions IAND, IOR, and IEOR respectively. Differential Revision: https://reviews.llvm.org/D122034
1 parent 251d062 commit b8f029c

File tree

3 files changed

+39
-10
lines changed

3 files changed

+39
-10
lines changed

flang/docs/Extensions.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ end
223223
as if they were comment lines, even if not begun with `!`.
224224
* Commas are required in FORMAT statements and character variables
225225
only when they prevent ambiguity.
226+
* Legacy names `AND`, `OR`, and `XOR` are accepted as aliases for
227+
the standard intrinsic functions `IAND`, `IOR`, and `IEOR`
228+
respectively.
226229

227230
### Extensions supported when enabled by options
228231

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -793,16 +793,11 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
793793
DefaultingKIND},
794794
KINDInt},
795795
{"__builtin_ieee_is_nan", {{"a", AnyFloating}}, DefaultLogical},
796-
{"__builtin_ieee_is_normal", {{"a", AnyFloating}}, DefaultLogical},
797796
{"__builtin_ieee_is_negative", {{"a", AnyFloating}}, DefaultLogical},
797+
{"__builtin_ieee_is_normal", {{"a", AnyFloating}}, DefaultLogical},
798798
{"__builtin_ieee_next_after", {{"x", SameReal}, {"y", AnyReal}}, SameReal},
799799
{"__builtin_ieee_next_down", {{"x", SameReal}}, SameReal},
800800
{"__builtin_ieee_next_up", {{"x", SameReal}}, SameReal},
801-
{"__builtin_ieee_selected_real_kind", // alias for selected_real_kind
802-
{{"p", AnyInt, Rank::scalar},
803-
{"r", AnyInt, Rank::scalar, Optionality::optional},
804-
{"radix", AnyInt, Rank::scalar, Optionality::optional}},
805-
DefaultInt, Rank::scalar, IntrinsicClass::transformationalFunction},
806801
{"__builtin_ieee_support_datatype",
807802
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
808803
DefaultLogical},
@@ -839,7 +834,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
839834
// LCOBOUND, UCOBOUND, FAILED_IMAGES, IMAGE_INDEX,
840835
// STOPPED_IMAGES, COSHAPE
841836
// TODO: Non-standard intrinsic functions
842-
// AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
837+
// LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
843838
// COMPL, EQV, NEQV, INT8, JINT, JNINT, KNINT,
844839
// QCMPLX, QEXT, QFLOAT, QREAL, DNUM,
845840
// INUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN,
@@ -851,6 +846,15 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
851846
// LOC, probably others
852847
// TODO: Optionally warn on operand promotion extension
853848

849+
// Aliases for a few generic intrinsic functions for legacy
850+
// compatibility and builtins.
851+
static const std::pair<const char *, const char *> genericAlias[]{
852+
{"and", "iand"},
853+
{"or", "ior"},
854+
{"xor", "ieor"},
855+
{"__builtin_ieee_selected_real_kind", "selected_real_kind"},
856+
};
857+
854858
// The following table contains the intrinsic functions listed in
855859
// Tables 16.2 and 16.3 in Fortran 2018. The "unrestricted" functions
856860
// in Table 16.2 can be used as actual arguments, PROCEDURE() interfaces,
@@ -1897,6 +1901,10 @@ class IntrinsicProcTable::Implementation {
18971901
for (const IntrinsicInterface &f : genericIntrinsicFunction) {
18981902
genericFuncs_.insert(std::make_pair(std::string{f.name}, &f));
18991903
}
1904+
for (const std::pair<const char *, const char *> &a : genericAlias) {
1905+
aliases_.insert(
1906+
std::make_pair(std::string{a.first}, std::string{a.second}));
1907+
}
19001908
for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
19011909
specificFuncs_.insert(std::make_pair(std::string{f.name}, &f));
19021910
}
@@ -1929,16 +1937,22 @@ class IntrinsicProcTable::Implementation {
19291937
SpecificCall HandleNull(ActualArguments &, FoldingContext &) const;
19301938
std::optional<SpecificCall> HandleC_F_Pointer(
19311939
ActualArguments &, FoldingContext &) const;
1940+
const std::string &ResolveAlias(const std::string &name) const {
1941+
auto iter{aliases_.find(name)};
1942+
return iter == aliases_.end() ? name : iter->second;
1943+
}
19321944

19331945
common::IntrinsicTypeDefaultKinds defaults_;
19341946
std::multimap<std::string, const IntrinsicInterface *> genericFuncs_;
19351947
std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs_;
19361948
std::multimap<std::string, const IntrinsicInterface *> subroutines_;
19371949
const semantics::Scope *builtinsScope_{nullptr};
1950+
std::map<std::string, std::string> aliases_;
19381951
};
19391952

19401953
bool IntrinsicProcTable::Implementation::IsIntrinsicFunction(
1941-
const std::string &name) const {
1954+
const std::string &name0) const {
1955+
const std::string &name{ResolveAlias(name0)};
19421956
auto specificRange{specificFuncs_.equal_range(name)};
19431957
if (specificRange.first != specificRange.second) {
19441958
return true;
@@ -2427,9 +2441,11 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
24272441
return std::nullopt;
24282442
}};
24292443

2430-
// Probe the generic intrinsic function table first.
2444+
// Probe the generic intrinsic function table first; allow for
2445+
// the use of a legacy alias.
24312446
parser::Messages genericBuffer;
2432-
auto genericRange{genericFuncs_.equal_range(call.name)};
2447+
const std::string &name{ResolveAlias(call.name)};
2448+
auto genericRange{genericFuncs_.equal_range(name)};
24332449
for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
24342450
if (auto specificCall{
24352451
matchOrBufferMessages(*iter->second, genericBuffer)}) {

flang/test/Semantics/boz-literal-constants.f90

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ subroutine explicit(n, x, c)
3636
! B) Argument to intrinsics listed from 16.9 below
3737
! BGE, BGT, BLE, BLT, CMPLX, DBLE, DSHIFTL,
3838
! DSHIFTR, IAND, IEOR, INT, IOR, MERGE_BITS, REAL
39+
! and legacy aliases AND, OR, XOR
3940

4041
! part A
4142
data f / Z"AA" / ! OK
@@ -63,16 +64,25 @@ subroutine explicit(n, x, c)
6364
!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
6465
resint = IAND(B"0001", B"0011")
6566
resint = IAND(B"0001", 3)
67+
!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
68+
resint = AND(B"0001", B"0011")
69+
resint = AND(B"0001", 3)
6670

6771
!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
6872
resint = IEOR(B"0001", B"0011")
6973
resint = IEOR(B"0001", 3)
74+
!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
75+
resint = XOR(B"0001", B"0011")
76+
resint = XOR(B"0001", 3)
7077

7178
resint = INT(B"1010")
7279

7380
!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
7481
res = IOR(B"0101", B"0011")
7582
res = IOR(B"0101", 3)
83+
!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
84+
res = OR(B"0101", B"0011")
85+
res = OR(B"0101", 3)
7686

7787
res = MERGE_BITS(13,3,11)
7888
res = MERGE_BITS(B"1101",3,11)

0 commit comments

Comments
 (0)