[flang] Auto conversion of integer scalar actual argument exprs
authorpeter klausler <pklausler@nvidia.com>
Fri, 20 Dec 2019 03:13:16 +0000 (19:13 -0800)
committerpeter klausler <pklausler@nvidia.com>
Fri, 20 Dec 2019 18:01:49 +0000 (10:01 -0800)
Add documentation

Original-commit: flang-compiler/f18@c1b200d23891cff4eca1991deec58c1adf65842e
Reviewed-on: https://github.com/flang-compiler/f18/pull/884

flang/documentation/Extensions.md
flang/lib/parser/unparse.cc
flang/lib/semantics/check-call.cc

index 03f7cfa..62f09e9 100644 (file)
@@ -23,6 +23,13 @@ Intentional violations of the standard
   `SIZE`, `LBOUND`, `UBOUND`, `SHAPE`, and the location reductions
   `FINDLOC`, `MAXLOC`, and `MINLOC`.  We return `INTEGER(KIND=8)` by
   default in these cases.
+* Scalar `INTEGER` actual argument expressions (not variables!)
+  are converted to the kinds of scalar `INTEGER` dummy arguments
+  when the interface is explicit and the kinds differ.
+  This conversion allows the results of the intrinsics like
+  `SIZE` that (as mentioned above) no longer return default
+  `INTEGER` results by default to be passed.  A warning is
+  emitted when truncation is possible.
 
 Extensions, deletions, and legacy features supported by default
 ===============================================================
index e131189..451e9c5 100644 (file)
@@ -1646,7 +1646,9 @@ public:
   }
   void Unparse(const CallStmt &x) {  // R1521
     if (asFortran_ && x.typedCall.get()) {
+      Put(' ');
       asFortran_->call(out_, *x.typedCall);
+      Put('\n');
     } else {
       const auto &pd{std::get<ProcedureDesignator>(x.v.t)};
       const auto &args{std::get<std::list<ActualArgSpec>>(x.v.t)};
index 5b323f2..a927260 100644 (file)
@@ -101,6 +101,33 @@ static void PadShortCharacterActual(evaluate::Expr<evaluate::SomeType> &actual,
   }
 }
 
+// Automatic conversion of different-kind INTEGER scalar actual
+// argument expressions (not variables) to INTEGER scalar dummies.
+// We return nonstandard INTEGER(8) results from intrinsic functions
+// like SIZE() by default in order to facilitate the use of large
+// arrays.  Emit a warning when downconverting.
+static void ConvertIntegerActual(evaluate::Expr<evaluate::SomeType> &actual,
+    const characteristics::TypeAndShape &dummyType,
+    characteristics::TypeAndShape &actualType,
+    parser::ContextualMessages &messages) {
+  if (dummyType.type().category() == TypeCategory::Integer &&
+      actualType.type().category() == TypeCategory::Integer &&
+      dummyType.type().kind() != actualType.type().kind() &&
+      GetRank(dummyType.shape()) == 0 && GetRank(actualType.shape()) == 0 &&
+      !evaluate::IsVariable(actual)) {
+    auto converted{
+        evaluate::ConvertToType(dummyType.type(), std::move(actual))};
+    CHECK(converted);
+    actual = std::move(*converted);
+    if (dummyType.type().kind() < actualType.type().kind()) {
+      messages.Say(
+          "Actual argument scalar expression of type INTEGER(%d) was converted to smaller dummy argument type INTEGER(%d)"_en_US,
+          actualType.type().kind(), dummyType.type().kind());
+    }
+    actualType = dummyType;
+  }
+}
+
 static bool DefersSameTypeParameters(
     const DerivedTypeSpec &actual, const DerivedTypeSpec &dummy) {
   for (const auto &pair : actual.parameters()) {
@@ -115,12 +142,13 @@ static bool DefersSameTypeParameters(
 
 static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
     const std::string &dummyName, evaluate::Expr<evaluate::SomeType> &actual,
-    const characteristics::TypeAndShape &actualType, bool isElemental,
+    characteristics::TypeAndShape &actualType, bool isElemental,
     evaluate::FoldingContext &context, const Scope *scope) {
 
   // Basic type & rank checking
   parser::ContextualMessages &messages{context.messages()};
   PadShortCharacterActual(actual, dummy.type, actualType, messages);
+  ConvertIntegerActual(actual, dummy.type, actualType, messages);
   bool typesCompatible{dummy.type.IsCompatibleWith(
       messages, actualType, "dummy argument", "actual argument", isElemental)};
   bool actualIsPolymorphic{actualType.type().IsPolymorphic()};