[llvm-branch-commits] [flang] 4e90cad - [flang] Handle undeclared names in EQUIVALENCE statements
Peter Steinfeld via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Dec 16 11:08:57 PST 2020
Author: Peter Steinfeld
Date: 2020-12-16T11:04:27-08:00
New Revision: 4e90cad6a6b5504f11b7876e26e80c2a079e04b0
URL: https://github.com/llvm/llvm-project/commit/4e90cad6a6b5504f11b7876e26e80c2a079e04b0
DIFF: https://github.com/llvm/llvm-project/commit/4e90cad6a6b5504f11b7876e26e80c2a079e04b0.diff
LOG: [flang] Handle undeclared names in EQUIVALENCE statements
Names in EQUIVALENCE statements are only allowed to indicate local
objects as per 19.5.1.4, paragraph 2, item (10). Thus, a name appearing
in an EQUIVALENCE statement with no corresponding declaration in the
same scope is an implicit declaration of the name. If that scope
contains an IMPLICIT NONE, it's an error.
I implemented this by adding a state variable to ScopeHandler to
indicate if we're resolving the names in an EQUIVALENCE statement and
then checked this state when resolving names. I also added a test to
the existing tests for EQUIVALENCE statements.
Differential Revision: https://reviews.llvm.org/D93345
Added:
Modified:
flang/lib/Semantics/resolve-names.cpp
flang/test/Semantics/equivalence01.f90
Removed:
################################################################################
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 1288b11a7727..495d7d0f8584 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -597,6 +597,7 @@ class ScopeHandler : public ImplicitRulesVisitor {
bool inExecutionPart_{false};
bool inSpecificationPart_{false};
+ bool inEquivalenceStmt_{false};
std::set<SourceName> specPartForwardRefs_;
private:
@@ -2021,7 +2022,11 @@ Symbol *ScopeHandler::FindSymbol(const Scope &scope, const parser::Name &name) {
}
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,
+ inEquivalenceStmt_ ? FindInScope(scope, name)
+ : scope.FindSymbol(name.source));
}
}
@@ -4347,15 +4352,17 @@ void DeclarationVisitor::Post(const parser::CommonBlockObject &x) {
bool DeclarationVisitor::Pre(const parser::EquivalenceStmt &x) {
// save equivalence sets to be processed after specification part
- CheckNotInBlock("EQUIVALENCE"); // C1107
- for (const std::list<parser::EquivalenceObject> &set : x.v) {
- equivalenceSets_.push_back(&set);
+ if (CheckNotInBlock("EQUIVALENCE")) { // C1107
+ for (const std::list<parser::EquivalenceObject> &set : x.v) {
+ equivalenceSets_.push_back(&set);
+ }
}
return false; // don't implicitly declare names yet
}
void DeclarationVisitor::CheckEquivalenceSets() {
EquivalenceSets equivSets{context()};
+ inEquivalenceStmt_ = true;
for (const auto *set : equivalenceSets_) {
const auto &source{set->front().v.value().source};
if (set->size() <= 1) { // R871
@@ -4372,6 +4379,7 @@ void DeclarationVisitor::CheckEquivalenceSets() {
}
equivSets.FinishSet(source);
}
+ inEquivalenceStmt_ = false;
for (auto &set : equivSets.sets()) {
if (!set.empty()) {
currScope().add_equivalenceSet(std::move(set));
diff --git a/flang/test/Semantics/equivalence01.f90 b/flang/test/Semantics/equivalence01.f90
index 234c42744ee9..e75d954001d7 100644
--- a/flang/test/Semantics/equivalence01.f90
+++ b/flang/test/Semantics/equivalence01.f90
@@ -197,3 +197,20 @@ end subroutine interfaceSub
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
More information about the llvm-branch-commits
mailing list