diff --git a/flang/lib/Semantics/resolve-labels.cpp b/flang/lib/Semantics/resolve-labels.cpp --- a/flang/lib/Semantics/resolve-labels.cpp +++ b/flang/lib/Semantics/resolve-labels.cpp @@ -60,7 +60,7 @@ std::is_same_v) { // Executable construct end statements are also supported as // an extension but they need special care because the associated - // construct create there own scope. + // construct create their own scope. return Legality::formerly; } else { return Legality::never; @@ -224,10 +224,10 @@ parser::BlockStmt, parser::ChangeTeamStmt, parser::CriticalStmt, parser::IfThenStmt, parser::NonLabelDoStmt, parser::SelectCaseStmt, parser::SelectRankStmt, parser::SelectTypeStmt>; - using LabeledConstructEndStmts = - std::tuple; + using LabeledConstructEndStmts = std::tuple; using LabeledProgramUnitEndStmts = std::tuple; @@ -294,10 +294,10 @@ return SwitchToNewScope(); } bool Pre(const parser::WhereConstruct &whereConstruct) { - return PushConstructNameWithoutBlock(whereConstruct); + return PushConstructName(whereConstruct); } bool Pre(const parser::ForallConstruct &forallConstruct) { - return PushConstructNameWithoutBlock(forallConstruct); + return PushConstructName(forallConstruct); } void Post(const parser::AssociateConstruct &associateConstruct) { @@ -327,12 +327,11 @@ void Post(const parser::SelectTypeConstruct &selectTypeConstruct) { PopConstructName(selectTypeConstruct); } - void Post(const parser::WhereConstruct &whereConstruct) { - PopConstructNameWithoutBlock(whereConstruct); + PopConstructName(whereConstruct); } void Post(const parser::ForallConstruct &forallConstruct) { - PopConstructNameWithoutBlock(forallConstruct); + PopConstructName(forallConstruct); } // Checks for missing or mismatching names on various constructs (e.g., IF) @@ -570,18 +569,6 @@ } return PushSubscope(); } - template bool PushConstructNameWithoutBlock(const A &a) { - const auto &optionalName{std::get<0>(std::get<0>(a.t).statement.t)}; - if (optionalName) { - constructNames_.emplace_back(optionalName->ToString()); - } - return true; - } - - template void PopConstructNameWithoutBlock(const A &a) { - CheckName(a); - PopConstructNameIfPresent(a); - } template void PopConstructNameIfPresent(const A &a) { const auto &optionalName{std::get<0>(std::get<0>(a.t).statement.t)}; if (optionalName) { @@ -962,12 +949,15 @@ } else if (!InInclusiveScope(scopes, scope, target.proxyForScope)) { // Clause 11.1.2.1 prohibits transfer of control to the interior of a // block from outside the block, but this does not apply to formats. + // C1038 and C1034 forbid statements in FORALL and WHERE constructs + // (resp.) from being branch targets. if (target.labeledStmtClassificationSet.test( TargetStatementEnum::Format)) { continue; } - context.Say( - position, "Label '%u' is not in scope"_en_US, SayLabel(label)); + context.Say(position, + "Label '%u' is in a construct that prevents its use as a branch target here"_en_US, + SayLabel(label)); } } } diff --git a/flang/test/Semantics/label05.f90 b/flang/test/Semantics/label05.f90 --- a/flang/test/Semantics/label05.f90 +++ b/flang/test/Semantics/label05.f90 @@ -1,9 +1,12 @@ - ! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: Label '50' was not found -! CHECK: Label '55' is not in scope +! CHECK: Label '55' is in a construct that prevents its use as a branch target here ! CHECK: Label '70' is not a branch target ! CHECK: Control flow use of '70' +! CHECK: Label '80' is in a construct that prevents its use as a branch target here +! CHECK: Label '90' is in a construct that prevents its use as a branch target here +! CHECK: Label '91' is in a construct that prevents its use as a branch target here +! CHECK: Label '92' is in a construct that prevents its use as a branch target here subroutine sub00(a,b,n,m) real a(n,m) @@ -35,3 +38,23 @@ end if 70 FORMAT (1x,i6) end subroutine sub02 + +subroutine sub03(a,n) + real a(n) + forall (j=1:n) +80 a(n) = j + end forall + go to 80 +end subroutine sub03 + +subroutine sub04(a,n) + real a(n) + where (a > 0) +90 a = 1 + elsewhere (a < 0) +91 a = 2 + elsewhere +92 a = 3 + end where + if (n - 3) 90, 91, 92 +end subroutine sub04 diff --git a/flang/test/Semantics/label06.f90 b/flang/test/Semantics/label06.f90 --- a/flang/test/Semantics/label06.f90 +++ b/flang/test/Semantics/label06.f90 @@ -1,11 +1,10 @@ - ! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s -! CHECK: Label '10' is not in scope +! CHECK: Label '10' is in a construct that prevents its use as a branch target here ! CHECK: Label '20' was not found ! CHECK: Label '30' is not a branch target ! CHECK: Control flow use of '30' -! CHECK: Label '40' is not in scope -! CHECK: Label '50' is not in scope +! CHECK: Label '40' is in a construct that prevents its use as a branch target here +! CHECK: Label '50' is in a construct that prevents its use as a branch target here subroutine sub00(n) GOTO (10,20,30) n diff --git a/flang/test/Semantics/label07.f90 b/flang/test/Semantics/label07.f90 --- a/flang/test/Semantics/label07.f90 +++ b/flang/test/Semantics/label07.f90 @@ -1,8 +1,7 @@ - ! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: Label '30' is not a branch target ! CHECK: Control flow use of '30' -! CHECK: Label '10' is not in scope +! CHECK: Label '10' is in a construct that prevents its use as a branch target here ! CHECK: Label '20' was not found ! CHECK: Label '60' was not found diff --git a/flang/test/Semantics/label14.f90 b/flang/test/Semantics/label14.f90 --- a/flang/test/Semantics/label14.f90 +++ b/flang/test/Semantics/label14.f90 @@ -3,7 +3,7 @@ ! Block Construct ! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s -! CHECK: Label '20' is not in scope +! CHECK: Label '20' is in a construct that prevents its use as a branch target here subroutine s1 block