aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Semantics/program-tree.cpp
diff options
context:
space:
mode:
authorPeter Klausler <pklausler@nvidia.com>2022-02-08 13:39:59 -0800
committerPeter Klausler <pklausler@nvidia.com>2022-02-11 16:55:05 -0800
commitfc510998f7c287df2bc1304673e0cd8452d50b31 (patch)
tree23dd19181f66e904692b25244d8d00697d43f3cb /flang/lib/Semantics/program-tree.cpp
parentdafe4c0b5cd07fa97c1954e0cf21aa90d558578f (diff)
downloadllvm-fc510998f7c287df2bc1304673e0cd8452d50b31.zip
llvm-fc510998f7c287df2bc1304673e0cd8452d50b31.tar.gz
llvm-fc510998f7c287df2bc1304673e0cd8452d50b31.tar.bz2
[flang] Fix edge case in USE-associated generics
It is generally an error when a USE-associated name clashes with a name defined locally, but not in all cases; a generic interface can be both USE-associated and locally defined. This works, but not when there is also a local subprogram with the same name, which is valid when that subprogram is a specific of the local generic. A bogus error issues at the point of the USE because name resolution will have already defined a symbol for the local subprogram. The solution is to collect the names of local generics when creating the program tree, and then create their symbols as well if their names are also local subprograms, prior to any USE association processing. Differential Revision: https://reviews.llvm.org/D119566
Diffstat (limited to 'flang/lib/Semantics/program-tree.cpp')
-rw-r--r--flang/lib/Semantics/program-tree.cpp37
1 files changed, 37 insertions, 0 deletions
diff --git a/flang/lib/Semantics/program-tree.cpp b/flang/lib/Semantics/program-tree.cpp
index e20299b..9d76cfa 100644
--- a/flang/lib/Semantics/program-tree.cpp
+++ b/flang/lib/Semantics/program-tree.cpp
@@ -44,6 +44,37 @@ static void GetEntryStmts(
}
}
+// Collects generics that define simple names that could include
+// identically-named subprograms as specific procedures.
+static void GetGenerics(
+ ProgramTree &node, const parser::SpecificationPart &spec) {
+ for (const auto &decl :
+ std::get<std::list<parser::DeclarationConstruct>>(spec.t)) {
+ if (const auto *spec{
+ std::get_if<parser::SpecificationConstruct>(&decl.u)}) {
+ if (const auto *generic{std::get_if<
+ parser::Statement<common::Indirection<parser::GenericStmt>>>(
+ &spec->u)}) {
+ const parser::GenericStmt &genericStmt{generic->statement.value()};
+ const auto &genericSpec{std::get<parser::GenericSpec>(genericStmt.t)};
+ node.AddGeneric(genericSpec);
+ } else if (const auto *interface{
+ std::get_if<common::Indirection<parser::InterfaceBlock>>(
+ &spec->u)}) {
+ const parser::InterfaceBlock &interfaceBlock{interface->value()};
+ const parser::InterfaceStmt &interfaceStmt{
+ std::get<parser::Statement<parser::InterfaceStmt>>(interfaceBlock.t)
+ .statement};
+ const auto *genericSpec{
+ std::get_if<std::optional<parser::GenericSpec>>(&interfaceStmt.u)};
+ if (genericSpec && genericSpec->has_value()) {
+ node.AddGeneric(**genericSpec);
+ }
+ }
+ }
+ }
+}
+
template <typename T>
static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) {
const auto &spec{std::get<parser::SpecificationPart>(x.t)};
@@ -53,6 +84,7 @@ static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) {
ProgramTree node{name, spec, &exec};
GetEntryStmts(node, spec);
GetEntryStmts(node, exec);
+ GetGenerics(node, spec);
if (subps) {
for (const auto &subp :
std::get<std::list<parser::InternalSubprogram>>(subps->t)) {
@@ -75,6 +107,7 @@ static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) {
const auto &spec{std::get<parser::SpecificationPart>(x.t)};
const auto &subps{std::get<std::optional<parser::ModuleSubprogramPart>>(x.t)};
ProgramTree node{name, spec};
+ GetGenerics(node, spec);
if (subps) {
for (const auto &subp :
std::get<std::list<parser::ModuleSubprogram>>(subps->t)) {
@@ -230,4 +263,8 @@ void ProgramTree::AddEntry(const parser::EntryStmt &entryStmt) {
entryStmts_.emplace_back(entryStmt);
}
+void ProgramTree::AddGeneric(const parser::GenericSpec &generic) {
+ genericSpecs_.emplace_back(generic);
+}
+
} // namespace Fortran::semantics