diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp --- a/flang/lib/Evaluate/characteristics.cpp +++ b/flang/lib/Evaluate/characteristics.cpp @@ -71,18 +71,6 @@ const auto &ultimate{symbol.GetUltimate()}; return std::visit( common::visitors{ - [&](const semantics::ObjectEntityDetails &object) - -> std::optional { - 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 @@ return std::optional{}; } }, - [&](const semantics::TypeParamDetails &tp) { - if (auto type{DynamicType::From(tp.type())}) { - return std::optional{std::move(*type)}; - } else { - return std::optional{}; - } - }, [&](const semantics::AssocEntityDetails &assoc) { return Characterize(assoc, context); }, [&](const semantics::ProcBindingDetails &binding) { return Characterize(binding.symbol(), context); }, - [](const auto &) { return std::optional{}; }, + [&](const auto &x) -> std::optional { + using Ty = std::decay_t; + if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v) { + 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 @@ std::optional DummyDataObject::Characterize( const semantics::Symbol &symbol, FoldingContext &context) { - if (symbol.has()) { + if (symbol.has() || + symbol.has()) { if (auto type{TypeAndShape::Characterize(symbol, context)}) { std::optional result{std::move(*type)}; using semantics::Attr; @@ -399,7 +397,11 @@ } 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 @@ const semantics::Symbol &symbol, FoldingContext &context, semantics::UnorderedSymbolSet &seenProcs) { auto name{symbol.name().ToString()}; - if (symbol.has()) { + if (symbol.has() || + symbol.has()) { 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 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -1505,19 +1505,26 @@ 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 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -2226,15 +2226,15 @@ if (auto *proc{std::get_if(&callee->u)}) { return MakeFunctionRef( call.source, std::move(*proc), std::move(callee->arguments)); - } else if (structureConstructor) { + } + CHECK(std::holds_alternative(callee->u)); + const Symbol &symbol{*std::get(callee->u)}; + if (structureConstructor) { // Structure constructor misparsed as function reference? - CHECK(std::holds_alternative(callee->u)); - const Symbol &derivedType{*std::get(callee->u)}; const auto &designator{std::get(call.t)}; if (const auto *name{std::get_if(&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 @@ 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; }