[flang-commits] [flang] 73c3530 - [flang] Catch errors in function calls instead of crashing

peter klausler via flang-commits flang-commits at lists.llvm.org
Thu Jun 3 15:25:23 PDT 2021


Author: peter klausler
Date: 2021-06-03T15:20:39-07:00
New Revision: 73c3530f5e057333eeac300b9d9925a13c55c9a6

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

LOG: [flang] Catch errors in function calls instead of crashing

Add some missing error messages, and permit the appearance
of EntityDetails symbols in dummy argument type characterization.

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

Added: 
    

Modified: 
    flang/lib/Evaluate/characteristics.cpp
    flang/lib/Semantics/check-declarations.cpp
    flang/lib/Semantics/expression.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp
index c0824ae2f5cd..4930f936fbaf 100644
--- a/flang/lib/Evaluate/characteristics.cpp
+++ b/flang/lib/Evaluate/characteristics.cpp
@@ -71,18 +71,6 @@ std::optional<TypeAndShape> TypeAndShape::Characterize(
   const auto &ultimate{symbol.GetUltimate()};
   return std::visit(
       common::visitors{
-          [&](const semantics::ObjectEntityDetails &object)
-              -> std::optional<TypeAndShape> {
-            if (auto type{DynamicType::From(object.type())}) {
-              TypeAndShape result{
-                  std::move(*type), GetShape(context, ultimate)};
-              result.AcquireAttrs(ultimate);
-              result.AcquireLEN(ultimate);
-              return std::move(result.Rewrite(context));
-            } else {
-              return std::nullopt;
-            }
-          },
           [&](const semantics::ProcEntityDetails &proc) {
             const semantics::ProcInterface &interface{proc.interface()};
             if (interface.type()) {
@@ -93,20 +81,29 @@ std::optional<TypeAndShape> TypeAndShape::Characterize(
               return std::optional<TypeAndShape>{};
             }
           },
-          [&](const semantics::TypeParamDetails &tp) {
-            if (auto type{DynamicType::From(tp.type())}) {
-              return std::optional<TypeAndShape>{std::move(*type)};
-            } else {
-              return std::optional<TypeAndShape>{};
-            }
-          },
           [&](const semantics::AssocEntityDetails &assoc) {
             return Characterize(assoc, context);
           },
           [&](const semantics::ProcBindingDetails &binding) {
             return Characterize(binding.symbol(), context);
           },
-          [](const auto &) { return std::optional<TypeAndShape>{}; },
+          [&](const auto &x) -> std::optional<TypeAndShape> {
+            using Ty = std::decay_t<decltype(x)>;
+            if constexpr (std::is_same_v<Ty, semantics::EntityDetails> ||
+                std::is_same_v<Ty, semantics::ObjectEntityDetails> ||
+                std::is_same_v<Ty, semantics::TypeParamDetails>) {
+              if (const semantics::DeclTypeSpec * type{ultimate.GetType()}) {
+                if (auto dyType{DynamicType::From(*type)}) {
+                  TypeAndShape result{
+                      std::move(*dyType), GetShape(context, ultimate)};
+                  result.AcquireAttrs(ultimate);
+                  result.AcquireLEN(ultimate);
+                  return std::move(result.Rewrite(context));
+                }
+              }
+            }
+            return std::nullopt;
+          },
       },
       // GetUltimate() used here, not ResolveAssociations(), because
       // we need the type/rank of an associate entity from TYPE IS,
@@ -272,7 +269,8 @@ static common::Intent GetIntent(const semantics::Attrs &attrs) {
 
 std::optional<DummyDataObject> DummyDataObject::Characterize(
     const semantics::Symbol &symbol, FoldingContext &context) {
-  if (symbol.has<semantics::ObjectEntityDetails>()) {
+  if (symbol.has<semantics::ObjectEntityDetails>() ||
+      symbol.has<semantics::EntityDetails>()) {
     if (auto type{TypeAndShape::Characterize(symbol, context)}) {
       std::optional<DummyDataObject> result{std::move(*type)};
       using semantics::Attr;
@@ -399,7 +397,11 @@ static std::optional<Procedure> CharacterizeProcedure(
             }
             for (const semantics::Symbol *arg : subp.dummyArgs()) {
               if (!arg) {
-                result.dummyArguments.emplace_back(AlternateReturn{});
+                if (subp.isFunction()) {
+                  return std::nullopt;
+                } else {
+                  result.dummyArguments.emplace_back(AlternateReturn{});
+                }
               } else if (auto argCharacteristics{CharacterizeDummyArgument(
                              *arg, context, seenProcs)}) {
                 result.dummyArguments.emplace_back(
@@ -518,7 +520,8 @@ static std::optional<DummyArgument> CharacterizeDummyArgument(
     const semantics::Symbol &symbol, FoldingContext &context,
     semantics::UnorderedSymbolSet &seenProcs) {
   auto name{symbol.name().ToString()};
-  if (symbol.has<semantics::ObjectEntityDetails>()) {
+  if (symbol.has<semantics::ObjectEntityDetails>() ||
+      symbol.has<semantics::EntityDetails>()) {
     if (auto obj{DummyDataObject::Characterize(symbol, context)}) {
       return DummyArgument{std::move(name), std::move(obj.value())};
     }

diff  --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index faeaff5ad778..0aaf5fe789c0 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -1505,19 +1505,26 @@ void CheckHelper::CheckProcBinding(
     const Symbol &symbol, const ProcBindingDetails &binding) {
   const Scope &dtScope{symbol.owner()};
   CHECK(dtScope.kind() == Scope::Kind::DerivedType);
-  if (const Symbol * dtSymbol{dtScope.symbol()}) {
-    if (symbol.attrs().test(Attr::DEFERRED)) {
+  if (symbol.attrs().test(Attr::DEFERRED)) {
+    if (const Symbol * dtSymbol{dtScope.symbol()}) {
       if (!dtSymbol->attrs().test(Attr::ABSTRACT)) { // C733
         SayWithDeclaration(*dtSymbol,
             "Procedure bound to non-ABSTRACT derived type '%s' may not be DEFERRED"_err_en_US,
             dtSymbol->name());
       }
-      if (symbol.attrs().test(Attr::NON_OVERRIDABLE)) {
-        messages_.Say(
-            "Type-bound procedure '%s' may not be both DEFERRED and NON_OVERRIDABLE"_err_en_US,
-            symbol.name());
-      }
     }
+    if (symbol.attrs().test(Attr::NON_OVERRIDABLE)) {
+      messages_.Say(
+          "Type-bound procedure '%s' may not be both DEFERRED and NON_OVERRIDABLE"_err_en_US,
+          symbol.name());
+    }
+  }
+  if (binding.symbol().attrs().test(Attr::INTRINSIC) &&
+      !context_.intrinsics().IsSpecificIntrinsicFunction(
+          binding.symbol().name().ToString())) {
+    messages_.Say(
+        "Intrinsic procedure '%s' is not a specific intrinsic permitted for use in the definition of binding '%s'"_err_en_US,
+        binding.symbol().name(), symbol.name());
   }
   if (const Symbol * overridden{FindOverriddenBinding(symbol)}) {
     if (overridden->attrs().test(Attr::NON_OVERRIDABLE)) {

diff  --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 33a1b0c72c61..80a180442498 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -2226,15 +2226,15 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::FunctionReference &funcRef,
     if (auto *proc{std::get_if<ProcedureDesignator>(&callee->u)}) {
       return MakeFunctionRef(
           call.source, std::move(*proc), std::move(callee->arguments));
-    } else if (structureConstructor) {
+    }
+    CHECK(std::holds_alternative<semantics::SymbolRef>(callee->u));
+    const Symbol &symbol{*std::get<semantics::SymbolRef>(callee->u)};
+    if (structureConstructor) {
       // Structure constructor misparsed as function reference?
-      CHECK(std::holds_alternative<semantics::SymbolRef>(callee->u));
-      const Symbol &derivedType{*std::get<semantics::SymbolRef>(callee->u)};
       const auto &designator{std::get<parser::ProcedureDesignator>(call.t)};
       if (const auto *name{std::get_if<parser::Name>(&designator.u)}) {
         semantics::Scope &scope{context_.FindScope(name->source)};
-        semantics::DerivedTypeSpec dtSpec{
-            name->source, derivedType.GetUltimate()};
+        semantics::DerivedTypeSpec dtSpec{name->source, symbol.GetUltimate()};
         if (!CheckIsValidForwardReference(dtSpec)) {
           return std::nullopt;
         }
@@ -2246,6 +2246,13 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::FunctionReference &funcRef,
         return Analyze(structureConstructor->value());
       }
     }
+    if (!context_.HasError(symbol)) {
+      AttachDeclaration(
+          Say("'%s' is called like a function but is not a procedure"_err_en_US,
+              symbol.name()),
+          symbol);
+      context_.SetError(symbol);
+    }
   }
   return std::nullopt;
 }


        


More information about the flang-commits mailing list