diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index b2c53cbb610e2..7eb7eb1370180 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -76,6 +76,8 @@ class SubprogramDetails : public WithBindName { bool isFunction() const { return result_ != nullptr; } bool isInterface() const { return isInterface_; } void set_isInterface(bool value = true) { isInterface_ = value; } + bool isDummy() const { return isDummy_; } + void set_isDummy(bool value = true) { isDummy_ = value; } Scope *entryScope() { return entryScope_; } const Scope *entryScope() const { return entryScope_; } void set_entryScope(Scope &scope) { entryScope_ = &scope; } @@ -95,6 +97,7 @@ class SubprogramDetails : public WithBindName { private: bool isInterface_{false}; // true if this represents an interface-body + bool isDummy_{false}; // true when interface of dummy procedure std::vector dummyArgs_; // nullptr -> alternate return indicator Symbol *result_{nullptr}; Scope *entryScope_{nullptr}; // if ENTRY, points to subprogram's scope diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp index af7adf54204a2..570aad6636443 100644 --- a/flang/lib/Evaluate/check-expression.cpp +++ b/flang/lib/Evaluate/check-expression.cpp @@ -301,7 +301,9 @@ bool IsInitialProcedureTarget(const semantics::Symbol &symbol) { const auto &ultimate{symbol.GetUltimate()}; return std::visit( common::visitors{ - [](const semantics::SubprogramDetails &) { return true; }, + [](const semantics::SubprogramDetails &subp) { + return !subp.isDummy(); + }, [](const semantics::SubprogramNameDetails &) { return true; }, [&](const semantics::ProcEntityDetails &proc) { return !semantics::IsPointer(ultimate) && !proc.isDummy(); diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index 80b1cdaf078aa..122502123f038 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -1136,6 +1136,7 @@ bool IsDummy(const Symbol &symbol) { common::visitors{[](const EntityDetails &x) { return x.isDummy(); }, [](const ObjectEntityDetails &x) { return x.isDummy(); }, [](const ProcEntityDetails &x) { return x.isDummy(); }, + [](const SubprogramDetails &x) { return x.isDummy(); }, [](const auto &) { return false; }}, ResolveAssociations(symbol).details()); } diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index e27000d3e9975..3b6d589ba2973 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -845,6 +845,10 @@ void CheckHelper::CheckSubprogram( } } } + // See comment on the similar check in CheckProcEntity() + if (details.isDummy() && symbol.attrs().test(Attr::ELEMENTAL)) { + messages_.Say("A dummy procedure may not be ELEMENTAL"_err_en_US); + } } void CheckHelper::CheckDerivedType( diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index b7db7d4018e73..5582bd727aa38 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -564,6 +564,10 @@ class ScopeHandler : public ImplicitRulesVisitor { if (symbol->CanReplaceDetails(details)) { // update the existing symbol symbol->attrs() |= attrs; + if constexpr (std::is_same_v) { + // Dummy argument defined by explicit interface + details.set_isDummy(IsDummy(*symbol)); + } symbol->set_details(std::move(details)); return *symbol; } else if constexpr (std::is_same_v) { @@ -2972,7 +2976,7 @@ void SubprogramVisitor::Post(const parser::SubroutineStmt &stmt) { auto &details{PostSubprogramStmt(name)}; for (const auto &dummyArg : std::get>(stmt.t)) { if (const auto *dummyName{std::get_if(&dummyArg.u)}) { - Symbol &dummy{MakeSymbol(*dummyName, EntityDetails(true))}; + Symbol &dummy{MakeSymbol(*dummyName, EntityDetails{true})}; details.add_dummyArg(dummy); } else { details.add_alternateReturn(); @@ -2984,7 +2988,7 @@ void SubprogramVisitor::Post(const parser::FunctionStmt &stmt) { const auto &name{std::get(stmt.t)}; auto &details{PostSubprogramStmt(name)}; for (const auto &dummyName : std::get>(stmt.t)) { - Symbol &dummy{MakeSymbol(dummyName, EntityDetails(true))}; + Symbol &dummy{MakeSymbol(dummyName, EntityDetails{true})}; details.add_dummyArg(dummy); } const parser::Name *funcResultName; @@ -3126,6 +3130,7 @@ void SubprogramVisitor::Post(const parser::EntryStmt &stmt) { common::visitors{[](EntityDetails &x) { x.set_isDummy(); }, [](ObjectEntityDetails &x) { x.set_isDummy(); }, [](ProcEntityDetails &x) { x.set_isDummy(); }, + [](SubprogramDetails &x) { x.set_isDummy(); }, [&](const auto &) { Say2(dummyName->source, "ENTRY dummy argument '%s' is previously declared as an item that may not be used as a dummy argument"_err_en_US, @@ -5842,12 +5847,13 @@ const parser::Name *DeclarationVisitor::ResolveDataRef( [&](const Indirection &y) { Walk(y.value().subscripts); const parser::Name *name{ResolveDataRef(y.value().base)}; - if (!name) { - } else if (!name->symbol->has()) { - ConvertToObjectEntity(*name->symbol); - } else if (!context().HasError(*name->symbol)) { - SayWithDecl(*name, *name->symbol, - "Cannot reference function '%s' as data"_err_en_US); + if (name && name->symbol) { + if (!IsProcedure(*name->symbol)) { + ConvertToObjectEntity(*name->symbol); + } else if (!context().HasError(*name->symbol)) { + SayWithDecl(*name, *name->symbol, + "Cannot reference function '%s' as data"_err_en_US); + } } return name; }, diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp index 7d439df75c2ef..8236e96ec1203 100644 --- a/flang/lib/Semantics/symbol.cpp +++ b/flang/lib/Semantics/symbol.cpp @@ -85,6 +85,7 @@ void ModuleDetails::set_scope(const Scope *scope) { llvm::raw_ostream &operator<<( llvm::raw_ostream &os, const SubprogramDetails &x) { DumpBool(os, "isInterface", x.isInterface_); + DumpBool(os, "dummy", x.isDummy_); DumpOptional(os, "bindName", x.bindName()); if (x.result_) { DumpType(os << " result:", x.result()); diff --git a/flang/test/Semantics/call02.f90 b/flang/test/Semantics/call02.f90 index 2922f5a6168d6..bc0ee974aabdd 100644 --- a/flang/test/Semantics/call02.f90 +++ b/flang/test/Semantics/call02.f90 @@ -4,6 +4,7 @@ subroutine s01(elem, subr) interface + !ERROR: A dummy procedure may not be ELEMENTAL elemental real function elem(x) real, intent(in), value :: x end function