[flang] Accept & fold IEEE_SELECTED_REAL_KIND

F18 supports the standard intrinsic function SELECTED_REAL_KIND
but not its synonym in the standard module IEEE_ARITHMETIC
named IEEE_SELECTED_REAL_KIND until this patch.

Differential Revision: https://reviews.llvm.org/D100066

GitOrigin-RevId: 8f16101c703e7d9995dc238ba0f03be52bdf4528
diff --git a/lib/Evaluate/fold-integer.cpp b/lib/Evaluate/fold-integer.cpp
index d780df5..8f18a06 100644
--- a/lib/Evaluate/fold-integer.cpp
+++ b/lib/Evaluate/fold-integer.cpp
@@ -579,7 +579,8 @@
     if (auto p{GetInt64Arg(args[0])}) {
       return Expr<T>{SelectedIntKind(*p)};
     }
-  } else if (name == "selected_real_kind") {
+  } else if (name == "selected_real_kind" ||
+      name == "__builtin_ieee_selected_real_kind") {
     if (auto p{GetInt64ArgOr(args[0], 0)}) {
       if (auto r{GetInt64ArgOr(args[1], 0)}) {
         if (auto radix{GetInt64ArgOr(args[2], 2)}) {
diff --git a/lib/Evaluate/intrinsics.cpp b/lib/Evaluate/intrinsics.cpp
index 8636c9e..26889a6 100644
--- a/lib/Evaluate/intrinsics.cpp
+++ b/lib/Evaluate/intrinsics.cpp
@@ -772,6 +772,11 @@
             {"back", AnyLogical, Rank::elemental, Optionality::optional},
             DefaultingKIND},
         KINDInt},
+    {"__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},
diff --git a/lib/Semantics/mod-file.cpp b/lib/Semantics/mod-file.cpp
index a60c8dd..0053420 100644
--- a/lib/Semantics/mod-file.cpp
+++ b/lib/Semantics/mod-file.cpp
@@ -561,6 +561,9 @@
 void PutProcEntity(llvm::raw_ostream &os, const Symbol &symbol) {
   if (symbol.attrs().test(Attr::INTRINSIC)) {
     os << "intrinsic::" << symbol.name() << '\n';
+    if (symbol.attrs().test(Attr::PRIVATE)) {
+      os << "private::" << symbol.name() << '\n';
+    }
     return;
   }
   const auto &details{symbol.get<ProcEntityDetails>()};
diff --git a/module/__fortran_builtins.f90 b/module/__fortran_builtins.f90
index c9cf111..d7e73f8 100644
--- a/module/__fortran_builtins.f90
+++ b/module/__fortran_builtins.f90
@@ -13,11 +13,14 @@
 module __Fortran_builtins
 
   use __Fortran_type_info, only: __builtin_c_ptr, __builtin_c_funptr
-  integer, parameter, private :: int64 = selected_int_kind(18)
 
   intrinsic :: __builtin_c_f_pointer
   intrinsic :: sizeof ! extension
 
+  intrinsic :: selected_int_kind
+  private :: selected_int_kind
+  integer, parameter, private :: int64 = selected_int_kind(18)
+
   type :: __builtin_event_type
     integer(kind=int64) :: __count
   end type
@@ -32,10 +35,12 @@
 
   procedure(type(__builtin_c_ptr)) :: __builtin_c_loc
 
+  intrinsic :: __builtin_ieee_selected_real_kind
   intrinsic :: __builtin_ieee_support_datatype, &
     __builtin_ieee_support_denormal, __builtin_ieee_support_divide, &
     __builtin_ieee_support_inf, __builtin_ieee_support_io, &
     __builtin_ieee_support_nan, __builtin_ieee_support_sqrt, &
     __builtin_ieee_support_standard, __builtin_ieee_support_subnormal, &
     __builtin_ieee_support_underflow_control
+
 end module
diff --git a/module/ieee_arithmetic.f90 b/module/ieee_arithmetic.f90
index 488a950..bd73c24 100644
--- a/module/ieee_arithmetic.f90
+++ b/module/ieee_arithmetic.f90
@@ -19,7 +19,8 @@
     ieee_support_sqrt => __builtin_ieee_support_sqrt, &
     ieee_support_standard => __builtin_ieee_support_standard, &
     ieee_support_subnormal => __builtin_ieee_support_subnormal, &
-    ieee_support_underflow_control => __builtin_ieee_support_underflow_control
+    ieee_support_underflow_control => __builtin_ieee_support_underflow_control, &
+    ieee_selected_real_kind => __builtin_ieee_selected_real_kind
 
   type :: ieee_class_type
     private
diff --git a/test/Semantics/modfile40.f90 b/test/Semantics/modfile40.f90
new file mode 100644
index 0000000..392b320
--- /dev/null
+++ b/test/Semantics/modfile40.f90
@@ -0,0 +1,58 @@
+! RUN: %S/test_modfile.sh %s %t %f18
+! Ensure that intrinsics in module files retain their 'private' attribute,
+! if they are private.
+
+module m1
+  intrinsic :: selected_real_kind
+  public :: selected_real_kind
+end module
+!Expect: m1.mod
+!module m1
+!intrinsic::selected_real_kind
+!end
+
+module m2
+  use m1, only: foo => selected_real_kind
+  real(foo(5,10)) :: x
+end module
+!Expect: m2.mod
+!module m2
+!use m1,only:foo=>selected_real_kind
+!real(4)::x
+!end
+
+module m3
+  intrinsic :: selected_real_kind
+  private :: selected_real_kind
+end module
+!Expect: m3.mod
+!module m3
+!intrinsic::selected_real_kind
+!private::selected_real_kind
+!end
+
+module m4
+  use m3
+  external :: selected_real_kind
+end module
+!Expect: m4.mod
+!module m4
+!procedure()::selected_real_kind
+!end
+
+module m5
+  private
+  intrinsic :: selected_real_kind
+end module
+!Expect: m5.mod
+!module m5
+!intrinsic::selected_real_kind
+!private::selected_real_kind
+!end
+
+use m2
+use m4
+use m5
+print *, kind(x)
+end
+