[flang-commits] [flang] c4a6543 - [flang] Symbol representation for dummy SubprogramDetails
peter klausler via flang-commits
flang-commits at lists.llvm.org
Mon Aug 2 10:44:38 PDT 2021
Author: peter klausler
Date: 2021-08-02T10:44:27-07:00
New Revision: c4a65434d894ca6f8ba1dcf338824b369c67f01b
URL: https://github.com/llvm/llvm-project/commit/c4a65434d894ca6f8ba1dcf338824b369c67f01b
DIFF: https://github.com/llvm/llvm-project/commit/c4a65434d894ca6f8ba1dcf338824b369c67f01b.diff
LOG: [flang] Symbol representation for dummy SubprogramDetails
Dummy procedures can be defined as subprograms with explicit
interfaces, e.g.
subroutine subr(dummy)
interface
subroutine dummy(x)
real :: x
end subroutine
end interface
! ...
end subroutine
but the symbol table had no means of marking such symbols as dummy
arguments, so predicates like IsDummy(dummy) would fail. Add an
isDummy_ flag to SubprogramNameDetails, analogous to the corresponding
flag in EntityDetails, and set/test it as needed.
Differential Revision: https://reviews.llvm.org/D106697
Added:
Modified:
flang/include/flang/Semantics/symbol.h
flang/lib/Evaluate/check-expression.cpp
flang/lib/Evaluate/tools.cpp
flang/lib/Semantics/check-declarations.cpp
flang/lib/Semantics/resolve-names.cpp
flang/lib/Semantics/symbol.cpp
flang/test/Semantics/call02.f90
Removed:
################################################################################
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<Symbol *> 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<SubprogramDetails, D>) {
+ // 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<UnknownDetails, D>) {
@@ -2972,7 +2976,7 @@ void SubprogramVisitor::Post(const parser::SubroutineStmt &stmt) {
auto &details{PostSubprogramStmt(name)};
for (const auto &dummyArg : std::get<std::list<parser::DummyArg>>(stmt.t)) {
if (const auto *dummyName{std::get_if<parser::Name>(&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<parser::Name>(stmt.t)};
auto &details{PostSubprogramStmt(name)};
for (const auto &dummyName : std::get<std::list<parser::Name>>(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<parser::ArrayElement> &y) {
Walk(y.value().subscripts);
const parser::Name *name{ResolveDataRef(y.value().base)};
- if (!name) {
- } else if (!name->symbol->has<ProcEntityDetails>()) {
- 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
More information about the flang-commits
mailing list