[flang-commits] [flang] b8f029c - [flang] Accept legacy aliases for intrinsic function names

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Fri Mar 18 17:24:06 PDT 2022


Author: Peter Klausler
Date: 2022-03-18T16:53:13-07:00
New Revision: b8f029c3a4e2bfc5e2afbbe0c14bdb01ec3f2087

URL: https://github.com/llvm/llvm-project/commit/b8f029c3a4e2bfc5e2afbbe0c14bdb01ec3f2087
DIFF: https://github.com/llvm/llvm-project/commit/b8f029c3a4e2bfc5e2afbbe0c14bdb01ec3f2087.diff

LOG: [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

Added: 
    

Modified: 
    flang/docs/Extensions.md
    flang/lib/Evaluate/intrinsics.cpp
    flang/test/Semantics/boz-literal-constants.f90

Removed: 
    


################################################################################
diff  --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 8b84045d20116..5e3d4dd092844 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -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
 

diff  --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index dff34f491a080..42b1a89da9183 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -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},
@@ -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,
@@ -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,
@@ -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));
     }
@@ -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;
@@ -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)}) {

diff  --git a/flang/test/Semantics/boz-literal-constants.f90 b/flang/test/Semantics/boz-literal-constants.f90
index ca1676a696461..7c4e5928ca517 100644
--- a/flang/test/Semantics/boz-literal-constants.f90
+++ b/flang/test/Semantics/boz-literal-constants.f90
@@ -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
@@ -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)


        


More information about the flang-commits mailing list