Skip to content

Commit f75033a

Browse files
committed
[flang] Add nested scoping to label distinctness checking
Fortran defines derived type definitions and explicit interface blocks for subroutines and functions to be nestable scopes for statement labels, even though such labels are useless for all purposes. Handle these scopes in label resolution so that bogus errors about conflicting labels in "real" code don't come out. Note that BLOCK constructs could have also been defined as scopes for statement labeling, but were not. Differential Revision: https://reviews.llvm.org/D132679
1 parent b1c960f commit f75033a

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

flang/lib/Semantics/resolve-labels.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,12 @@ class ParseTreeAnalyzer {
374374
std::get<parser::Statement<parser::EndBlockDataStmt>>(blockData.t));
375375
}
376376

377+
bool Pre(const parser::InterfaceBody &) {
378+
PushDisposableMap();
379+
return true;
380+
}
381+
void Post(const parser::InterfaceBody &) { PopDisposableMap(); }
382+
377383
// C1564
378384
void Post(const parser::InterfaceBody::Function &func) {
379385
CheckOptionalName<parser::FunctionStmt>("FUNCTION", func,
@@ -492,10 +498,15 @@ class ParseTreeAnalyzer {
492498
}
493499

494500
// C739
501+
bool Pre(const parser::DerivedTypeDef &) {
502+
PushDisposableMap();
503+
return true;
504+
}
495505
void Post(const parser::DerivedTypeDef &derivedTypeDef) {
496506
CheckOptionalName<parser::DerivedTypeStmt>("derived type definition",
497507
derivedTypeDef,
498508
std::get<parser::Statement<parser::EndTypeStmt>>(derivedTypeDef.t));
509+
PopDisposableMap();
499510
}
500511

501512
void Post(const parser::LabelDoStmt &labelDoStmt) {
@@ -779,7 +790,10 @@ class ParseTreeAnalyzer {
779790
LabeledStmtClassificationSet labeledStmtClassificationSet,
780791
ProxyForScope scope, bool isExecutableConstructEndStmt = false) {
781792
CheckLabelInRange(label);
782-
const auto pair{programUnits_.back().targetStmts.emplace(label,
793+
TargetStmtMap &targetStmtMap{disposableMaps_.empty()
794+
? programUnits_.back().targetStmts
795+
: disposableMaps_.back()};
796+
const auto pair{targetStmtMap.emplace(label,
783797
LabeledStatementInfoTuplePOD{scope, currentPosition_,
784798
labeledStmtClassificationSet, isExecutableConstructEndStmt})};
785799
if (!pair.second) {
@@ -818,11 +832,19 @@ class ParseTreeAnalyzer {
818832
}
819833
}
820834

835+
void PushDisposableMap() { disposableMaps_.emplace_back(); }
836+
void PopDisposableMap() { disposableMaps_.pop_back(); }
837+
821838
std::vector<UnitAnalysis> programUnits_;
822839
SemanticsContext &context_;
823840
parser::CharBlock currentPosition_;
824841
ProxyForScope currentScope_;
825842
std::vector<std::string> constructNames_;
843+
// For labels in derived type definitions and procedure
844+
// interfaces, which are their own inclusive scopes. None
845+
// of these labels can be used as a branch target, but they
846+
// should be pairwise distinct.
847+
std::vector<TargetStmtMap> disposableMaps_;
826848
};
827849

828850
bool InInclusiveScope(const std::vector<ScopeInfo> &scopes, ProxyForScope tail,

flang/test/Semantics/label17.f90

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
1 program main
3+
1 type one
4+
2 real x
5+
3 end type one
6+
1 type two
7+
2 real x
8+
!ERROR: Label '2' is not distinct
9+
2 real y
10+
3 end type two
11+
2 interface
12+
2 subroutine sub1(p, q)
13+
3 interface
14+
3 subroutine p
15+
4 end subroutine
16+
3 subroutine q
17+
4 end subroutine
18+
4 end interface
19+
5 end subroutine
20+
2 subroutine sub2(p, q)
21+
3 interface
22+
3 subroutine p
23+
4 end subroutine
24+
3 subroutine q
25+
4 end subroutine
26+
4 end interface
27+
5 end subroutine
28+
3 end interface
29+
4 call sub3
30+
5 contains
31+
1 subroutine sub3
32+
2 continue
33+
3 block
34+
!ERROR: Label '2' is not distinct
35+
2 continue
36+
4 end block
37+
5 end subroutine
38+
6 end program

0 commit comments

Comments
 (0)