mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-03 07:36:07 +00:00
[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
This commit is contained in:
parent
869f8363c4
commit
4e90cad6a6
@ -597,6 +597,7 @@ protected:
|
||||
|
||||
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));
|
||||
|
@ -197,3 +197,20 @@ subroutine s16
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user