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 @@ -15,6 +15,7 @@ #include "flang/Common/idioms.h" #include "flang/Common/reference.h" #include "flang/Parser/message.h" +#include "flang/Parser/parse-tree.h" #include "flang/Parser/provenance.h" #include #include @@ -155,6 +156,14 @@ // Make a copy of a symbol in this scope; nullptr if one is already there Symbol *CopySymbol(const Symbol &); + std::vector *> & + parsedEquivalenceSets() { + return parsedEquivalenceSets_; + } + const std::vector *> + parsedEequivalenceSets() const { + return parsedEquivalenceSets_; + } std::list &equivalenceSets() { return equivalenceSets_; } const std::list &equivalenceSets() const { return equivalenceSets_; @@ -242,6 +251,10 @@ std::list children_; mapType symbols_; mapType commonBlocks_; + // Equivalence sets as they appear in the source + std::vector *> + parsedEquivalenceSets_; + // Equivalence sets after initial processing std::list equivalenceSets_; mapType crayPointers_; std::map> submodules_; 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 @@ -891,8 +891,6 @@ bool sequence{false}; // is a sequence type const Symbol *type{nullptr}; // derived type being defined } derivedTypeInfo_; - // Collect equivalence sets and process at end of specification part - std::vector *> equivalenceSets_; // Names of all common block objects in the scope std::set commonBlockObjects_; // Info about about SAVE statements and attributes in current scope @@ -4341,14 +4339,14 @@ // save equivalence sets to be processed after specification part CheckNotInBlock("EQUIVALENCE"); // C1107 for (const std::list &set : x.v) { - equivalenceSets_.push_back(&set); + currScope().parsedEquivalenceSets().push_back(&set); } return false; // don't implicitly declare names yet } void DeclarationVisitor::CheckEquivalenceSets() { EquivalenceSets equivSets{context()}; - for (const auto *set : equivalenceSets_) { + for (const auto *set : currScope().parsedEquivalenceSets()) { const auto &source{set->front().v.value().source}; if (set->size() <= 1) { // R871 Say(source, "Equivalence set must have more than one object"_err_en_US); @@ -4369,7 +4367,7 @@ currScope().add_equivalenceSet(std::move(set)); } } - equivalenceSets_.clear(); + currScope().parsedEquivalenceSets().clear(); } bool DeclarationVisitor::Pre(const parser::SaveStmt &x) { 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 @@ -1,4 +1,4 @@ -! RUN: %S/test_errors.sh %s %t %f18 +!RUN: %S/test_errors.sh %s %t %f18 subroutine s1 integer i, j real r(2) @@ -182,3 +182,26 @@ !ERROR: 'a(3_8)' and 'a(1_8)' cannot have the same first storage unit equivalence(b(2),a(1)) end module + +subroutine s16 + + integer var, dupName + + ! There should be no error message for the following + equivalence (dupName, var) + + interface + subroutine interfaceSub (dupName) + integer dupName + type derived + integer:: field + end type derived + type(derived) :: dvar + integer :: ivar + !Verify that we're checking equivalence sets in interfaces + !ERROR: Derived type component 'dvar%field' is not allowed in an equivalence set + equivalence(dvar%field, ivar) + end subroutine interfaceSub + end interface + +end subroutine s16