-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[flang] Accept CHANGE TEAM/END TEAM as branch target #123822
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
|
@llvm/pr-subscribers-flang-semantics Author: Peter Klausler (klausler) ChangesIt 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. Full diff: https://github.com/llvm/llvm-project/pull/123822.diff 2 Files Affected:
diff --git a/flang/lib/Semantics/resolve-labels.cpp b/flang/lib/Semantics/resolve-labels.cpp
index 04e4b142efedf8..b0cbc4b56e8896 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 @@ class ParseTreeAnalyzer {
// 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 @@ class ParseTreeAnalyzer {
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 @@ class ParseTreeAnalyzer {
// 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 00000000000000..f8ad05335d0700
--- /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
|
clementval
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, isn't parser::EndChangeTeamStmt now a valid branch target?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only for branches within the CHANGE TEAM/END TEAM construct. It's not a valid branch target for branches coming from outside the construct.
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.