@@ -1573,8 +1573,7 @@ class ResolveNamesVisitor : public virtual ScopeHandler,
1573
1573
llvm_unreachable("This node is handled in ProgramUnit");
1574
1574
}
1575
1575
1576
- void NoteExecutablePartCall (
1577
- Symbol::Flag, const parser::Call &, bool hasCUDAChevrons);
1576
+ void NoteExecutablePartCall(Symbol::Flag, SourceName, bool hasCUDAChevrons);
1578
1577
1579
1578
friend void ResolveSpecificationParts(SemanticsContext &, const Symbol &);
1580
1579
@@ -7711,27 +7710,24 @@ bool ResolveNamesVisitor::CheckImplicitNoneExternal(
7711
7710
// of the subprogram's interface, and to mark as procedures any symbols
7712
7711
// that might otherwise have been miscategorized as objects.
7713
7712
void ResolveNamesVisitor::NoteExecutablePartCall(
7714
- Symbol::Flag flag, const parser::Call &call, bool hasCUDAChevrons) {
7715
- auto &designator{std::get<parser::ProcedureDesignator>(call.t )};
7716
- if (const auto *name{std::get_if<parser::Name>(&designator.u )}) {
7717
- // Subtlety: The symbol pointers in the parse tree are not set, because
7718
- // they might end up resolving elsewhere (e.g., construct entities in
7719
- // SELECT TYPE).
7720
- if (Symbol * symbol{currScope ().FindSymbol (name->source )}) {
7721
- Symbol::Flag other{flag == Symbol::Flag::Subroutine
7722
- ? Symbol::Flag::Function
7723
- : Symbol::Flag::Subroutine};
7724
- if (!symbol->test (other)) {
7725
- ConvertToProcEntity (*symbol);
7726
- if (auto *details{symbol->detailsIf <ProcEntityDetails>()}) {
7727
- symbol->set (flag);
7728
- if (IsDummy (*symbol)) {
7729
- SetImplicitAttr (*symbol, Attr::EXTERNAL);
7730
- }
7731
- ApplyImplicitRules (*symbol);
7732
- if (hasCUDAChevrons) {
7733
- details->set_isCUDAKernel ();
7734
- }
7713
+ Symbol::Flag flag, SourceName name, bool hasCUDAChevrons) {
7714
+ // Subtlety: The symbol pointers in the parse tree are not set, because
7715
+ // they might end up resolving elsewhere (e.g., construct entities in
7716
+ // SELECT TYPE).
7717
+ if (Symbol * symbol{currScope().FindSymbol(name)}) {
7718
+ Symbol::Flag other{flag == Symbol::Flag::Subroutine
7719
+ ? Symbol::Flag::Function
7720
+ : Symbol::Flag::Subroutine};
7721
+ if (!symbol->test(other)) {
7722
+ ConvertToProcEntity(*symbol);
7723
+ if (auto *details{symbol->detailsIf<ProcEntityDetails>()}) {
7724
+ symbol->set(flag);
7725
+ if (IsDummy(*symbol)) {
7726
+ SetImplicitAttr(*symbol, Attr::EXTERNAL);
7727
+ }
7728
+ ApplyImplicitRules(*symbol);
7729
+ if (hasCUDAChevrons) {
7730
+ details->set_isCUDAKernel();
7735
7731
}
7736
7732
}
7737
7733
}
@@ -8451,21 +8447,130 @@ class ExecutionPartSkimmer {
8451
8447
void Walk(const parser::ExecutionPart *exec) {
8452
8448
if (exec) {
8453
8449
parser::Walk(*exec, *this);
8450
+ CHECK(nestedScopes_.empty());
8454
8451
}
8455
8452
}
8456
8453
8457
8454
template <typename A> bool Pre(const A &) { return true; }
8458
8455
template <typename A> void Post(const A &) {}
8459
8456
void Post(const parser::FunctionReference &fr) {
8460
- resolver_. NoteExecutablePartCall (Symbol::Flag::Function, fr.v , false );
8457
+ NoteCall (Symbol::Flag::Function, fr.v, false);
8461
8458
}
8462
8459
void Post(const parser::CallStmt &cs) {
8463
- resolver_.NoteExecutablePartCall (
8464
- Symbol::Flag::Subroutine, cs.call , cs.chevrons .has_value ());
8460
+ NoteCall(Symbol::Flag::Subroutine, cs.call, cs.chevrons.has_value());
8461
+ }
8462
+ bool Pre(const parser::AssociateConstruct &) {
8463
+ PushScope();
8464
+ return true;
8465
+ }
8466
+ void Post(const parser::AssociateConstruct &) { PopScope(); }
8467
+ bool Pre(const parser::Association &x) {
8468
+ Hide(std::get<parser::Name>(x.t));
8469
+ return true;
8470
+ }
8471
+ bool Pre(const parser::BlockConstruct &) {
8472
+ PushScope();
8473
+ return true;
8474
+ }
8475
+ void Post(const parser::BlockConstruct &) { PopScope(); }
8476
+ bool Pre(const parser::EntityDecl &x) {
8477
+ Hide(std::get<parser::ObjectName>(x.t));
8478
+ return true;
8479
+ }
8480
+ void Post(const parser::ImportStmt &x) {
8481
+ if (x.kind == common::ImportKind::None ||
8482
+ x.kind == common::ImportKind::Only) {
8483
+ if (!nestedScopes_.front().importOnly.has_value()) {
8484
+ nestedScopes_.front().importOnly.emplace();
8485
+ }
8486
+ for (const auto &name : x.names) {
8487
+ nestedScopes_.front().importOnly->emplace(name.source);
8488
+ }
8489
+ } else {
8490
+ // no special handling needed for explicit names or IMPORT, ALL
8491
+ }
8492
+ }
8493
+ void Post(const parser::UseStmt &x) {
8494
+ if (const auto *onlyList{std::get_if<std::list<parser::Only>>(&x.u)}) {
8495
+ for (const auto &only : *onlyList) {
8496
+ if (const auto *name{std::get_if<parser::Name>(&only.u)}) {
8497
+ Hide(*name);
8498
+ } else if (const auto *rename{std::get_if<parser::Rename>(&only.u)}) {
8499
+ if (const auto *names{
8500
+ std::get_if<parser::Rename::Names>(&rename->u)}) {
8501
+ Hide(std::get<0>(names->t));
8502
+ }
8503
+ }
8504
+ }
8505
+ } else {
8506
+ // USE may or may not shadow symbols in host scopes
8507
+ nestedScopes_.front().hasUseWithoutOnly = true;
8508
+ }
8509
+ }
8510
+ bool Pre(const parser::DerivedTypeStmt &x) {
8511
+ Hide(std::get<parser::Name>(x.t));
8512
+ PushScope();
8513
+ return true;
8514
+ }
8515
+ void Post(const parser::DerivedTypeDef &) { PopScope(); }
8516
+ bool Pre(const parser::SelectTypeConstruct &) {
8517
+ PushScope();
8518
+ return true;
8519
+ }
8520
+ void Post(const parser::SelectTypeConstruct &) { PopScope(); }
8521
+ bool Pre(const parser::SelectTypeStmt &x) {
8522
+ if (const auto &maybeName{std::get<1>(x.t)}) {
8523
+ Hide(*maybeName);
8524
+ }
8525
+ return true;
8526
+ }
8527
+ bool Pre(const parser::SelectRankConstruct &) {
8528
+ PushScope();
8529
+ return true;
8530
+ }
8531
+ void Post(const parser::SelectRankConstruct &) { PopScope(); }
8532
+ bool Pre(const parser::SelectRankStmt &x) {
8533
+ if (const auto &maybeName{std::get<1>(x.t)}) {
8534
+ Hide(*maybeName);
8535
+ }
8536
+ return true;
8465
8537
}
8466
8538
8467
8539
private:
8540
+ void NoteCall(
8541
+ Symbol::Flag flag, const parser::Call &call, bool hasCUDAChevrons) {
8542
+ auto &designator{std::get<parser::ProcedureDesignator>(call.t)};
8543
+ if (const auto *name{std::get_if<parser::Name>(&designator.u)}) {
8544
+ for (const auto &scope : nestedScopes_) {
8545
+ if (scope.locals.find(name->source) != scope.locals.end()) {
8546
+ return; // shadowed by nested declaration
8547
+ }
8548
+ if (scope.hasUseWithoutOnly) {
8549
+ break;
8550
+ }
8551
+ if (scope.importOnly &&
8552
+ scope.importOnly->find(name->source) == scope.importOnly->end()) {
8553
+ return; // not imported
8554
+ }
8555
+ }
8556
+ resolver_.NoteExecutablePartCall(flag, name->source, hasCUDAChevrons);
8557
+ }
8558
+ }
8559
+
8560
+ void PushScope() { nestedScopes_.emplace_front(); }
8561
+ void PopScope() { nestedScopes_.pop_front(); }
8562
+ void Hide(const parser::Name &name) {
8563
+ nestedScopes_.front().locals.emplace(name.source);
8564
+ }
8565
+
8468
8566
ResolveNamesVisitor &resolver_;
8567
+
8568
+ struct NestedScopeInfo {
8569
+ bool hasUseWithoutOnly{false};
8570
+ std::set<SourceName> locals;
8571
+ std::optional<std::set<SourceName>> importOnly;
8572
+ };
8573
+ std::list<NestedScopeInfo> nestedScopes_;
8469
8574
};
8470
8575
8471
8576
// Build the scope tree and resolve names in the specification parts of this
0 commit comments