[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