[flang-commits] [PATCH] D159040: [flang] Allow GOTO to containing END IF after ELSE

Peter Klausler via Phabricator via flang-commits flang-commits at lists.llvm.org
Mon Aug 28 16:55:24 PDT 2023


klausler created this revision.
klausler added a reviewer: clementval.
klausler added a project: Flang.
Herald added a subscriber: jdoerfert.
Herald added a reviewer: sscalpone.
Herald added a project: All.
klausler requested review of this revision.

Label resolution gets into an infinite loop trying to emit an inappropriate
error or warning for a GOTO whose target is on an enclosing END IF
statement with an intervening ELSE or ELSE IF.  The scope tracking mechanism
viewed the END IF as being part of the ELSE block's scope.

Fix with the same means that was used to fix a similar bogus error
on GOTOs to END SELECT in SELECT CASE blocks: nest the THEN/ELSE IF/ELSE
blocks one level deeper than before, so that the END IF is in the IF
block but not in any of its parts.

Fixes https://github.com/llvm/llvm-project/issues/64654 for
llvm-test-suite/Fortran/gfortran/regression/goto_5.f90.


https://reviews.llvm.org/D159040

Files:
  flang/lib/Semantics/resolve-labels.cpp
  flang/test/Semantics/label18.f90


Index: flang/test/Semantics/label18.f90
===================================================================
--- /dev/null
+++ flang/test/Semantics/label18.f90
@@ -0,0 +1,18 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+program main
+  if (.true.) then
+    do j = 1, 2
+      goto 1 ! ok; used to cause looping in label resolution
+    end do
+  else
+    goto 1 ! ok
+1 end if
+  if (.true.) then
+    do j = 1, 2
+      !WARNING: Label '1' is in a construct that should not be used as a branch target here
+      goto 1
+    end do
+  end if
+  !WARNING: Label '1' is in a construct that should not be used as a branch target here
+  goto 1
+end
Index: flang/lib/Semantics/resolve-labels.cpp
===================================================================
--- flang/lib/Semantics/resolve-labels.cpp
+++ flang/lib/Semantics/resolve-labels.cpp
@@ -239,8 +239,9 @@
     auto targetFlags{ConstructBranchTargetFlags(statement)};
     if constexpr (common::HasMember<A, LabeledConstructStmts>) {
       AddTargetLabelDefinition(label.value(), targetFlags, ParentScope());
-    } else if constexpr (std::is_same_v<A, parser::EndSelectStmt>) {
-      // the label on an END SELECT is not in the last case
+    } 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);
     } else if constexpr (common::HasMember<A, LabeledConstructEndStmts>) {
       constexpr bool isExecutableConstructEndStmt{true};
@@ -279,12 +280,17 @@
   bool Pre(const parser::IfConstruct &ifConstruct) {
     return PushConstructName(ifConstruct);
   }
+  void Post(const parser::IfThenStmt &) { PushScope(); }
   bool Pre(const parser::IfConstruct::ElseIfBlock &) {
     return SwitchToNewScope();
   }
   bool Pre(const parser::IfConstruct::ElseBlock &) {
     return SwitchToNewScope();
   }
+  bool Pre(const parser::EndIfStmt &) {
+    PopScope();
+    return true;
+  }
   bool Pre(const parser::CaseConstruct &caseConstruct) {
     return PushConstructName(caseConstruct);
   }
@@ -1008,15 +1014,18 @@
       }
       bool isFatal{false};
       ProxyForScope fromScope{scope};
-      for (ProxyForScope toScope{target.proxyForScope}; fromScope != toScope;
+      for (ProxyForScope toScope{target.proxyForScope}; HasScope(toScope);
            toScope = scopes[toScope].parent) {
+        while (scopes[fromScope].depth > scopes[toScope].depth) {
+          fromScope = scopes[fromScope].parent;
+        }
+        if (toScope == fromScope) {
+          break;
+        }
         if (scopes[toScope].isExteriorGotoFatal) {
           isFatal = true;
           break;
         }
-        if (scopes[toScope].depth == scopes[fromScope].depth) {
-          fromScope = scopes[fromScope].parent;
-        }
       }
       context.Say(position,
           isFatal


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D159040.554106.patch
Type: text/x-patch
Size: 2956 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/flang-commits/attachments/20230828/61b98990/attachment-0001.bin>


More information about the flang-commits mailing list