Skip to content

Conversation

@klausler
Copy link
Contributor

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.

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.
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:semantics labels Jan 21, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 21, 2025

@llvm/pr-subscribers-flang-semantics

Author: Peter Klausler (klausler)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/123822.diff

2 Files Affected:

  • (modified) flang/lib/Semantics/resolve-labels.cpp (+14-9)
  • (added) flang/test/Semantics/label19.f90 (+19)
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

Copy link
Contributor

@clementval clementval left a 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
Copy link
Contributor

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?

Copy link
Contributor Author

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.

@klausler klausler merged commit 210e675 into llvm:main Jan 27, 2025
11 checks passed
@klausler klausler deleted the fix478 branch January 27, 2025 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flang:semantics flang Flang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants