[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.
This commit is contained in:
parent
73db9ee1e8
commit
210e675cfd
@ -122,6 +122,8 @@ constexpr Legality IsLegalBranchTarget(const parser::Statement<A> &) {
|
|||||||
std::is_same_v<A, parser::EndCriticalStmt> ||
|
std::is_same_v<A, parser::EndCriticalStmt> ||
|
||||||
std::is_same_v<A, parser::ForallConstructStmt> ||
|
std::is_same_v<A, parser::ForallConstructStmt> ||
|
||||||
std::is_same_v<A, parser::WhereConstructStmt> ||
|
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::EndFunctionStmt> ||
|
||||||
std::is_same_v<A, parser::EndMpSubprogramStmt> ||
|
std::is_same_v<A, parser::EndMpSubprogramStmt> ||
|
||||||
std::is_same_v<A, parser::EndProgramStmt> ||
|
std::is_same_v<A, parser::EndProgramStmt> ||
|
||||||
@ -210,8 +212,9 @@ public:
|
|||||||
// subprograms. Visit that statement in advance so that results
|
// subprograms. Visit that statement in advance so that results
|
||||||
// are placed in the correct programUnits_ slot.
|
// are placed in the correct programUnits_ slot.
|
||||||
auto targetFlags{ConstructBranchTargetFlags(endStmt)};
|
auto targetFlags{ConstructBranchTargetFlags(endStmt)};
|
||||||
AddTargetLabelDefinition(
|
AddTargetLabelDefinition(endStmt.label.value(), targetFlags,
|
||||||
endStmt.label.value(), targetFlags, currentScope_);
|
currentScope_,
|
||||||
|
/*isExecutableConstructEndStmt=*/false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -238,18 +241,20 @@ public:
|
|||||||
parser::EndProgramStmt, parser::EndSubroutineStmt>;
|
parser::EndProgramStmt, parser::EndSubroutineStmt>;
|
||||||
auto targetFlags{ConstructBranchTargetFlags(statement)};
|
auto targetFlags{ConstructBranchTargetFlags(statement)};
|
||||||
if constexpr (common::HasMember<A, LabeledConstructStmts>) {
|
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> ||
|
} else if constexpr (std::is_same_v<A, parser::EndIfStmt> ||
|
||||||
std::is_same_v<A, parser::EndSelectStmt>) {
|
std::is_same_v<A, parser::EndSelectStmt>) {
|
||||||
// the label on an END IF/SELECT is not in the last part/case
|
// 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>) {
|
} else if constexpr (common::HasMember<A, LabeledConstructEndStmts>) {
|
||||||
constexpr bool isExecutableConstructEndStmt{true};
|
|
||||||
AddTargetLabelDefinition(label.value(), targetFlags, currentScope_,
|
AddTargetLabelDefinition(label.value(), targetFlags, currentScope_,
|
||||||
isExecutableConstructEndStmt);
|
/*isExecutableConstructEndStmt=*/true);
|
||||||
} else if constexpr (!common::HasMember<A, LabeledProgramUnitEndStmts>) {
|
} else if constexpr (!common::HasMember<A, LabeledProgramUnitEndStmts>) {
|
||||||
// Program unit END statements have already been processed.
|
// Program unit END statements have already been processed.
|
||||||
AddTargetLabelDefinition(label.value(), targetFlags, currentScope_);
|
AddTargetLabelDefinition(label.value(), targetFlags, currentScope_,
|
||||||
|
/*isExecutableConstructEndStmt=*/false);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -826,7 +831,7 @@ private:
|
|||||||
// 6.2.5., paragraph 2
|
// 6.2.5., paragraph 2
|
||||||
void AddTargetLabelDefinition(parser::Label label,
|
void AddTargetLabelDefinition(parser::Label label,
|
||||||
LabeledStmtClassificationSet labeledStmtClassificationSet,
|
LabeledStmtClassificationSet labeledStmtClassificationSet,
|
||||||
ProxyForScope scope, bool isExecutableConstructEndStmt = false) {
|
ProxyForScope scope, bool isExecutableConstructEndStmt) {
|
||||||
CheckLabelInRange(label);
|
CheckLabelInRange(label);
|
||||||
TargetStmtMap &targetStmtMap{disposableMaps_.empty()
|
TargetStmtMap &targetStmtMap{disposableMaps_.empty()
|
||||||
? programUnits_.back().targetStmts
|
? programUnits_.back().targetStmts
|
||||||
@ -912,7 +917,7 @@ bool InBody(const parser::CharBlock &position,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LabeledStatementInfoTuplePOD GetLabel(
|
static LabeledStatementInfoTuplePOD GetLabel(
|
||||||
const TargetStmtMap &labels, const parser::Label &label) {
|
const TargetStmtMap &labels, const parser::Label &label) {
|
||||||
const auto iter{labels.find(label)};
|
const auto iter{labels.find(label)};
|
||||||
if (iter == labels.cend()) {
|
if (iter == labels.cend()) {
|
||||||
|
19
flang/test/Semantics/label19.f90
Normal file
19
flang/test/Semantics/label19.f90
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user