Skip to content

Commit

Permalink
[flang] Accept legacy aliases for intrinsic function names
Browse files Browse the repository at this point in the history
Support the names AND, OR, and XOR for the generic intrinsic
functions IAND, IOR, and IEOR respectively.

Differential Revision: https://reviews.llvm.org/D122034
  • Loading branch information
klausler committed Mar 18, 2022
1 parent 251d062 commit b8f029c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 10 deletions.
3 changes: 3 additions & 0 deletions flang/docs/Extensions.md
Expand Up @@ -223,6 +223,9 @@ end
as if they were comment lines, even if not begun with `!`.
* Commas are required in FORMAT statements and character variables
only when they prevent ambiguity.
* Legacy names `AND`, `OR`, and `XOR` are accepted as aliases for
the standard intrinsic functions `IAND`, `IOR`, and `IEOR`
respectively.

### Extensions supported when enabled by options

Expand Down
36 changes: 26 additions & 10 deletions flang/lib/Evaluate/intrinsics.cpp
Expand Up @@ -793,16 +793,11 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
DefaultingKIND},
KINDInt},
{"__builtin_ieee_is_nan", {{"a", AnyFloating}}, DefaultLogical},
{"__builtin_ieee_is_normal", {{"a", AnyFloating}}, DefaultLogical},
{"__builtin_ieee_is_negative", {{"a", AnyFloating}}, DefaultLogical},
{"__builtin_ieee_is_normal", {{"a", AnyFloating}}, DefaultLogical},
{"__builtin_ieee_next_after", {{"x", SameReal}, {"y", AnyReal}}, SameReal},
{"__builtin_ieee_next_down", {{"x", SameReal}}, SameReal},
{"__builtin_ieee_next_up", {{"x", SameReal}}, SameReal},
{"__builtin_ieee_selected_real_kind", // alias for selected_real_kind
{{"p", AnyInt, Rank::scalar},
{"r", AnyInt, Rank::scalar, Optionality::optional},
{"radix", AnyInt, Rank::scalar, Optionality::optional}},
DefaultInt, Rank::scalar, IntrinsicClass::transformationalFunction},
{"__builtin_ieee_support_datatype",
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
DefaultLogical},
Expand Down Expand Up @@ -839,7 +834,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
// LCOBOUND, UCOBOUND, FAILED_IMAGES, IMAGE_INDEX,
// STOPPED_IMAGES, COSHAPE
// TODO: Non-standard intrinsic functions
// AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
// LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
// COMPL, EQV, NEQV, INT8, JINT, JNINT, KNINT,
// QCMPLX, QEXT, QFLOAT, QREAL, DNUM,
// INUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN,
Expand All @@ -851,6 +846,15 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
// LOC, probably others
// TODO: Optionally warn on operand promotion extension

// Aliases for a few generic intrinsic functions for legacy
// compatibility and builtins.
static const std::pair<const char *, const char *> genericAlias[]{
{"and", "iand"},
{"or", "ior"},
{"xor", "ieor"},
{"__builtin_ieee_selected_real_kind", "selected_real_kind"},
};

// The following table contains the intrinsic functions listed in
// Tables 16.2 and 16.3 in Fortran 2018. The "unrestricted" functions
// in Table 16.2 can be used as actual arguments, PROCEDURE() interfaces,
Expand Down Expand Up @@ -1897,6 +1901,10 @@ class IntrinsicProcTable::Implementation {
for (const IntrinsicInterface &f : genericIntrinsicFunction) {
genericFuncs_.insert(std::make_pair(std::string{f.name}, &f));
}
for (const std::pair<const char *, const char *> &a : genericAlias) {
aliases_.insert(
std::make_pair(std::string{a.first}, std::string{a.second}));
}
for (const SpecificIntrinsicInterface &f : specificIntrinsicFunction) {
specificFuncs_.insert(std::make_pair(std::string{f.name}, &f));
}
Expand Down Expand Up @@ -1929,16 +1937,22 @@ class IntrinsicProcTable::Implementation {
SpecificCall HandleNull(ActualArguments &, FoldingContext &) const;
std::optional<SpecificCall> HandleC_F_Pointer(
ActualArguments &, FoldingContext &) const;
const std::string &ResolveAlias(const std::string &name) const {
auto iter{aliases_.find(name)};
return iter == aliases_.end() ? name : iter->second;
}

common::IntrinsicTypeDefaultKinds defaults_;
std::multimap<std::string, const IntrinsicInterface *> genericFuncs_;
std::multimap<std::string, const SpecificIntrinsicInterface *> specificFuncs_;
std::multimap<std::string, const IntrinsicInterface *> subroutines_;
const semantics::Scope *builtinsScope_{nullptr};
std::map<std::string, std::string> aliases_;
};

bool IntrinsicProcTable::Implementation::IsIntrinsicFunction(
const std::string &name) const {
const std::string &name0) const {
const std::string &name{ResolveAlias(name0)};
auto specificRange{specificFuncs_.equal_range(name)};
if (specificRange.first != specificRange.second) {
return true;
Expand Down Expand Up @@ -2427,9 +2441,11 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
return std::nullopt;
}};

// Probe the generic intrinsic function table first.
// Probe the generic intrinsic function table first; allow for
// the use of a legacy alias.
parser::Messages genericBuffer;
auto genericRange{genericFuncs_.equal_range(call.name)};
const std::string &name{ResolveAlias(call.name)};
auto genericRange{genericFuncs_.equal_range(name)};
for (auto iter{genericRange.first}; iter != genericRange.second; ++iter) {
if (auto specificCall{
matchOrBufferMessages(*iter->second, genericBuffer)}) {
Expand Down
10 changes: 10 additions & 0 deletions flang/test/Semantics/boz-literal-constants.f90
Expand Up @@ -36,6 +36,7 @@ subroutine explicit(n, x, c)
! B) Argument to intrinsics listed from 16.9 below
! BGE, BGT, BLE, BLT, CMPLX, DBLE, DSHIFTL,
! DSHIFTR, IAND, IEOR, INT, IOR, MERGE_BITS, REAL
! and legacy aliases AND, OR, XOR

! part A
data f / Z"AA" / ! OK
Expand Down Expand Up @@ -63,16 +64,25 @@ subroutine explicit(n, x, c)
!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
resint = IAND(B"0001", B"0011")
resint = IAND(B"0001", 3)
!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
resint = AND(B"0001", B"0011")
resint = AND(B"0001", 3)

!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
resint = IEOR(B"0001", B"0011")
resint = IEOR(B"0001", 3)
!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
resint = XOR(B"0001", B"0011")
resint = XOR(B"0001", 3)

resint = INT(B"1010")

!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
res = IOR(B"0101", B"0011")
res = IOR(B"0101", 3)
!ERROR: Typeless (BOZ) not allowed for both 'i=' & 'j=' arguments
res = OR(B"0101", B"0011")
res = OR(B"0101", 3)

res = MERGE_BITS(13,3,11)
res = MERGE_BITS(B"1101",3,11)
Expand Down

0 comments on commit b8f029c

Please sign in to comment.