diff --git a/flang/include/flang/Semantics/scope.h b/flang/include/flang/Semantics/scope.h --- a/flang/include/flang/Semantics/scope.h +++ b/flang/include/flang/Semantics/scope.h @@ -130,6 +130,9 @@ size_type erase(const SourceName &); bool empty() const { return symbols_.empty(); } + // Look for symbol by name only in this scope (for EQUIVALENCE statements) + Symbol *FindLocalSymbol(const SourceName &) const; + // Look for symbol by name in this scope and host (depending on imports). Symbol *FindSymbol(const SourceName &) const; diff --git a/flang/include/flang/Semantics/semantics.h b/flang/include/flang/Semantics/semantics.h --- a/flang/include/flang/Semantics/semantics.h +++ b/flang/include/flang/Semantics/semantics.h @@ -85,6 +85,7 @@ bool warnOnNonstandardUsage() const { return warnOnNonstandardUsage_; } bool warningsAreErrors() const { return warningsAreErrors_; } bool debugModuleWriter() const { return debugModuleWriter_; } + bool inEquivalenceStmt() { return inEquivalenceStmt_; } const evaluate::IntrinsicProcTable &intrinsics() const { return intrinsics_; } Scope &globalScope() { return globalScope_; } parser::Messages &messages() { return messages_; } @@ -116,6 +117,10 @@ warningsAreErrors_ = x; return *this; } + SemanticsContext &set_inEquivalenceStmt(bool x) { + inEquivalenceStmt_ = x; + return *this; + } SemanticsContext &set_debugModuleWriter(bool x) { debugModuleWriter_ = x; @@ -196,6 +201,7 @@ parser::CharBlock location; IndexVarKind kind; }; + bool inEquivalenceStmt_{false}; std::map activeIndexVars_; std::set errorSymbols_; std::vector tempNames_; diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -2018,7 +2018,11 @@ } return FindSymbol(scope.parent(), name); } else { - return Resolve(name, scope.FindSymbol(name.source)); + // In EQUIVALENCE statements only resolve names in the local scope, see + // 19.5.1.4, paragraph 2, item (10) + return Resolve(name, + context().inEquivalenceStmt() ? scope.FindLocalSymbol(name.source) + : scope.FindSymbol(name.source)); } } @@ -4341,15 +4345,17 @@ bool DeclarationVisitor::Pre(const parser::EquivalenceStmt &x) { // save equivalence sets to be processed after specification part - CheckNotInBlock("EQUIVALENCE"); // C1107 - for (const std::list &set : x.v) { - equivalenceSets_.push_back(&set); + if (CheckNotInBlock("EQUIVALENCE")) { // C1107 + for (const std::list &set : x.v) { + equivalenceSets_.push_back(&set); + } } return false; // don't implicitly declare names yet } void DeclarationVisitor::CheckEquivalenceSets() { EquivalenceSets equivSets{context()}; + context().set_inEquivalenceStmt(true); for (const auto *set : equivalenceSets_) { const auto &source{set->front().v.value().source}; if (set->size() <= 1) { // R871 @@ -4366,6 +4372,7 @@ } equivSets.FinishSet(source); } + context().set_inEquivalenceStmt(false); for (auto &set : equivSets.sets()) { if (!set.empty()) { currScope().add_equivalenceSet(std::move(set)); diff --git a/flang/lib/Semantics/scope.cpp b/flang/lib/Semantics/scope.cpp --- a/flang/lib/Semantics/scope.cpp +++ b/flang/lib/Semantics/scope.cpp @@ -75,6 +75,7 @@ Scope::iterator Scope::find(const SourceName &name) { return symbols_.find(name); } + Scope::size_type Scope::erase(const SourceName &name) { auto it{symbols_.find(name)}; if (it != end()) { @@ -84,10 +85,19 @@ return 0; } } -Symbol *Scope::FindSymbol(const SourceName &name) const { + +Symbol *Scope::FindLocalSymbol(const SourceName &name) const { auto it{find(name)}; if (it != end()) { return &*it->second; + } else { + return nullptr; + } +} + +Symbol *Scope::FindSymbol(const SourceName &name) const { + if (Symbol * local{FindLocalSymbol(name)}) { + return local; } else if (CanImport(name)) { return parent_.FindSymbol(name); } else { diff --git a/flang/test/Semantics/equivalence01.f90 b/flang/test/Semantics/equivalence01.f90 --- a/flang/test/Semantics/equivalence01.f90 +++ b/flang/test/Semantics/equivalence01.f90 @@ -197,3 +197,20 @@ end interface end subroutine s16 + +module m17 + real :: dupName +contains + real function f17a() + implicit none + real :: y + !ERROR: No explicit type declared for 'dupname' + equivalence (dupName, y) + end function f17a + real function f17b() + real :: y + ! The following implicitly declares an object called "dupName" local to + ! the function f17b(). OK since there's no "implicit none + equivalence (dupName, y) + end function f17b +end module m17