diff --git a/flang/include/flang/Evaluate/intrinsics.h b/flang/include/flang/Evaluate/intrinsics.h --- a/flang/include/flang/Evaluate/intrinsics.h +++ b/flang/include/flang/Evaluate/intrinsics.h @@ -76,6 +76,11 @@ // Inquiry intrinsics are defined in section 16.7, table 16.1 IntrinsicClass GetIntrinsicClass(const std::string &) const; + // Return the generic name of a specific intrinsic name. + // The name provided is returned if it is a generic intrinsic name or is + // not known to be an intrinsic. + std::string GetGenericIntrinsicName(const std::string &) const; + // Probe the intrinsics for a match against a specific call. // On success, the actual arguments are transferred to the result // in dummy argument order; on failure, the actual arguments remain diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -1568,6 +1568,7 @@ bool IsIntrinsic(const std::string &) const; IntrinsicClass GetIntrinsicClass(const std::string &) const; + std::string GetGenericIntrinsicName(const std::string &) const; std::optional Probe(const CallCharacteristics &, ActualArguments &, FoldingContext &, const IntrinsicProcTable &) const; @@ -1625,6 +1626,17 @@ return IntrinsicClass::noClass; } +std::string IntrinsicProcTable::Implementation::GetGenericIntrinsicName( + const std::string &name) const { + auto specificIntrinsic{specificFuncs_.find(name)}; + if (specificIntrinsic != specificFuncs_.end()) { + if (const char *genericName{specificIntrinsic->second->generic}) { + return {genericName}; + } + } + return name; +} + bool CheckAndRearrangeArguments(ActualArguments &arguments, parser::ContextualMessages &messages, const char *const dummyKeywords[], std::size_t trailingOptionals) { @@ -2075,6 +2087,11 @@ return DEREF(impl_).GetIntrinsicClass(name); } +std::string IntrinsicProcTable::GetGenericIntrinsicName( + const std::string &name) const { + return DEREF(impl_).GetGenericIntrinsicName(name); +} + std::optional IntrinsicProcTable::Probe( const CallCharacteristics &call, ActualArguments &arguments, FoldingContext &context) const { diff --git a/flang/unittests/Evaluate/intrinsics.cpp b/flang/unittests/Evaluate/intrinsics.cpp --- a/flang/unittests/Evaluate/intrinsics.cpp +++ b/flang/unittests/Evaluate/intrinsics.cpp @@ -292,6 +292,43 @@ .DoCall(); // bad type // TODO: test other intrinsics + + // Test unrestricted specific to generic name mapping (table 16.2). + TEST(table.GetGenericIntrinsicName("alog") == "log"); + TEST(table.GetGenericIntrinsicName("alog10") == "log10"); + TEST(table.GetGenericIntrinsicName("amod") == "mod"); + TEST(table.GetGenericIntrinsicName("cabs") == "abs"); + TEST(table.GetGenericIntrinsicName("ccos") == "cos"); + TEST(table.GetGenericIntrinsicName("cexp") == "exp"); + TEST(table.GetGenericIntrinsicName("clog") == "log"); + TEST(table.GetGenericIntrinsicName("csin") == "sin"); + TEST(table.GetGenericIntrinsicName("csqrt") == "sqrt"); + TEST(table.GetGenericIntrinsicName("dabs") == "abs"); + TEST(table.GetGenericIntrinsicName("dacos") == "acos"); + TEST(table.GetGenericIntrinsicName("dasin") == "asin"); + TEST(table.GetGenericIntrinsicName("datan") == "atan"); + TEST(table.GetGenericIntrinsicName("datan2") == "atan2"); + TEST(table.GetGenericIntrinsicName("dcos") == "cos"); + TEST(table.GetGenericIntrinsicName("dcosh") == "cosh"); + TEST(table.GetGenericIntrinsicName("ddim") == "dim"); + TEST(table.GetGenericIntrinsicName("dexp") == "exp"); + TEST(table.GetGenericIntrinsicName("dint") == "aint"); + TEST(table.GetGenericIntrinsicName("dlog") == "log"); + TEST(table.GetGenericIntrinsicName("dlog10") == "log10"); + TEST(table.GetGenericIntrinsicName("dmod") == "mod"); + TEST(table.GetGenericIntrinsicName("dnint") == "anint"); + TEST(table.GetGenericIntrinsicName("dsign") == "sign"); + TEST(table.GetGenericIntrinsicName("dsin") == "sin"); + TEST(table.GetGenericIntrinsicName("dsinh") == "sinh"); + TEST(table.GetGenericIntrinsicName("dsqrt") == "sqrt"); + TEST(table.GetGenericIntrinsicName("dtan") == "tan"); + TEST(table.GetGenericIntrinsicName("dtanh") == "tanh"); + TEST(table.GetGenericIntrinsicName("iabs") == "abs"); + TEST(table.GetGenericIntrinsicName("idim") == "dim"); + TEST(table.GetGenericIntrinsicName("idnint") == "nint"); + TEST(table.GetGenericIntrinsicName("isign") == "sign"); + // Test a case where specific and generic name are the same. + TEST(table.GetGenericIntrinsicName("acos") == "acos"); } } // namespace Fortran::evaluate