[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
This commit is contained in:
parent
5a865b0b1e
commit
c4a65434d8
|
@ -76,6 +76,8 @@ public:
|
|||
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 @@ public:
|
|||
|
||||
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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -564,6 +564,10 @@ public:
|
|||
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;
|
||||
},
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue