diff options
author | Peter Klausler <pklausler@nvidia.com> | 2025-01-27 08:54:56 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-27 08:54:56 -0800 |
commit | 210e675cfd7be3d7e0d93c29368acd27b51f9a17 (patch) | |
tree | 6ec4c1357fe46edc167e453c13a7d779065880ba | |
parent | 73db9ee1e87b4cfccbc9d67d2b47d9476f92413f (diff) | |
download | llvm-210e675cfd7be3d7e0d93c29368acd27b51f9a17.zip llvm-210e675cfd7be3d7e0d93c29368acd27b51f9a17.tar.gz llvm-210e675cfd7be3d7e0d93c29368acd27b51f9a17.tar.bz2 |
[flang] Accept CHANGE TEAM/END TEAM as branch target (#123822)
It is valid to jump to a CHANGE TEAM statement from anywhere in the
containing executable part, and valid to jump to an END TEAM statement
from within the construct.
-rw-r--r-- | flang/lib/Semantics/resolve-labels.cpp | 23 | ||||
-rw-r--r-- | flang/test/Semantics/label19.f90 | 19 |
2 files changed, 33 insertions, 9 deletions
diff --git a/flang/lib/Semantics/resolve-labels.cpp b/flang/lib/Semantics/resolve-labels.cpp index 04e4b14..b0cbc4b 100644 --- a/flang/lib/Semantics/resolve-labels.cpp +++ b/flang/lib/Semantics/resolve-labels.cpp @@ -122,6 +122,8 @@ constexpr Legality IsLegalBranchTarget(const parser::Statement<A> &) { std::is_same_v<A, parser::EndCriticalStmt> || std::is_same_v<A, parser::ForallConstructStmt> || std::is_same_v<A, parser::WhereConstructStmt> || + std::is_same_v<A, parser::ChangeTeamStmt> || + std::is_same_v<A, parser::EndChangeTeamStmt> || std::is_same_v<A, parser::EndFunctionStmt> || std::is_same_v<A, parser::EndMpSubprogramStmt> || std::is_same_v<A, parser::EndProgramStmt> || @@ -210,8 +212,9 @@ public: // subprograms. Visit that statement in advance so that results // are placed in the correct programUnits_ slot. auto targetFlags{ConstructBranchTargetFlags(endStmt)}; - AddTargetLabelDefinition( - endStmt.label.value(), targetFlags, currentScope_); + AddTargetLabelDefinition(endStmt.label.value(), targetFlags, + currentScope_, + /*isExecutableConstructEndStmt=*/false); } } return true; @@ -238,18 +241,20 @@ public: parser::EndProgramStmt, parser::EndSubroutineStmt>; auto targetFlags{ConstructBranchTargetFlags(statement)}; if constexpr (common::HasMember<A, LabeledConstructStmts>) { - AddTargetLabelDefinition(label.value(), targetFlags, ParentScope()); + AddTargetLabelDefinition(label.value(), targetFlags, ParentScope(), + /*isExecutableConstructEndStmt=*/false); } else if constexpr (std::is_same_v<A, parser::EndIfStmt> || std::is_same_v<A, parser::EndSelectStmt>) { // the label on an END IF/SELECT is not in the last part/case - AddTargetLabelDefinition(label.value(), targetFlags, ParentScope(), true); + AddTargetLabelDefinition(label.value(), targetFlags, ParentScope(), + /*isExecutableConstructEndStmt=*/true); } else if constexpr (common::HasMember<A, LabeledConstructEndStmts>) { - constexpr bool isExecutableConstructEndStmt{true}; AddTargetLabelDefinition(label.value(), targetFlags, currentScope_, - isExecutableConstructEndStmt); + /*isExecutableConstructEndStmt=*/true); } else if constexpr (!common::HasMember<A, LabeledProgramUnitEndStmts>) { // Program unit END statements have already been processed. - AddTargetLabelDefinition(label.value(), targetFlags, currentScope_); + AddTargetLabelDefinition(label.value(), targetFlags, currentScope_, + /*isExecutableConstructEndStmt=*/false); } return true; } @@ -826,7 +831,7 @@ private: // 6.2.5., paragraph 2 void AddTargetLabelDefinition(parser::Label label, LabeledStmtClassificationSet labeledStmtClassificationSet, - ProxyForScope scope, bool isExecutableConstructEndStmt = false) { + ProxyForScope scope, bool isExecutableConstructEndStmt) { CheckLabelInRange(label); TargetStmtMap &targetStmtMap{disposableMaps_.empty() ? programUnits_.back().targetStmts @@ -912,7 +917,7 @@ bool InBody(const parser::CharBlock &position, return false; } -LabeledStatementInfoTuplePOD GetLabel( +static LabeledStatementInfoTuplePOD GetLabel( const TargetStmtMap &labels, const parser::Label &label) { const auto iter{labels.find(label)}; if (iter == labels.cend()) { diff --git a/flang/test/Semantics/label19.f90 b/flang/test/Semantics/label19.f90 new file mode 100644 index 0000000..f8ad053 --- /dev/null +++ b/flang/test/Semantics/label19.f90 @@ -0,0 +1,19 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +program main + use, intrinsic:: iso_fortran_env, only: team_type + type(team_type) team + logical :: p = false +1 change team(team) +2 if (p) goto 1 ! ok + if (p) goto 2 ! ok + if (p) goto 3 ! ok + if (p) goto 4 ! ok + if (p) goto 5 ! ok +3 end team +4 continue + if (p) goto 1 ! ok + !ERROR: Label '2' is in a construct that prevents its use as a branch target here + if (p) goto 2 + !ERROR: Label '3' is in a construct that prevents its use as a branch target here + if (p) goto 3 +5 end |