[flang-commits] [flang] [flang][openacc] Diagnose a construct name on the END DO of an ACC labeled DO (PR #230308)
Eugene Epshteyn via flang-commits
flang-commits at lists.llvm.org
Fri Oct 9 03:47:55 PDT 2026
https://github.com/eugeneepshteyn updated https://github.com/llvm/llvm-project/pull/230308
>From f62e1c25aa6ed8198c6be834e3d1d8ed6bac457a Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Thu, 8 Oct 2026 14:02:53 -0700
Subject: [PATCH 1/2] [flang][openacc] Diagnose a construct name on the END DO
of an ACC labeled DO
When an OpenACC loop or combined construct is associated with a labeled DO
loop, AccNonBlockDoConstruct turns a terminating END DO statement into a
labeled CONTINUE statement, which silently dropped any construct name on the
END DO. A labeled DO statement has no construct name, so the name is not
allowed (C1135), and it is already diagnosed when the loop is not associated
with a directive:
!$acc parallel loop
do 10 i = 1, n
a(i) = 0
10 end do foo
Report "Unexpected DO construct name" at the name before it is dropped.
Also add tests for labeled END DO forms that are accepted: a branch to the
END DO from inside the loop, END DO followed by an end directive, and the
kernels and serial loop constructs.
---
flang/lib/Parser/openacc-parsers.cpp | 8 +++-
flang/test/Parser/acc-label-do-end-name.f90 | 41 +++++++++++++++++++
flang/test/Semantics/OpenACC/acc-label-do.f90 | 40 ++++++++++++++++++
3 files changed, 88 insertions(+), 1 deletion(-)
create mode 100644 flang/test/Parser/acc-label-do-end-name.f90
diff --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp
index d39196dc4f0ce9..3b2c3826403fb3 100644
--- a/flang/lib/Parser/openacc-parsers.cpp
+++ b/flang/lib/Parser/openacc-parsers.cpp
@@ -237,11 +237,17 @@ struct AccNonBlockDoConstruct {
// The terminating statement may be an END DO statement; the DO construct
// built below has its own synthetic one, so turn it into a CONTINUE
- // statement to keep its label and source.
+ // statement to keep its label and source. A labeled DO statement has no
+ // construct name, so diagnose a name on the END DO statement before it is
+ // lost (C1135).
if (auto *last{std::get_if<ExecutableConstruct>(&body.back().u)}) {
if (auto *endDoStmt{
std::get_if<Statement<common::Indirection<EndDoStmt>>>(
&last->u)}) {
+ if (const auto &name{endDoStmt->statement.value().v}) {
+ state.Say(name->source, "Unexpected DO construct name '%s'"_err_en_US,
+ name->source);
+ }
Statement<ActionStmt> continueStmt{
std::optional<Label>{endDoStmt->label}, ContinueStmt{}};
continueStmt.source = endDoStmt->source;
diff --git a/flang/test/Parser/acc-label-do-end-name.f90 b/flang/test/Parser/acc-label-do-end-name.f90
new file mode 100644
index 00000000000000..5199fb60ced331
--- /dev/null
+++ b/flang/test/Parser/acc-label-do-end-name.f90
@@ -0,0 +1,41 @@
+! RUN: not %flang_fc1 -fopenacc -fsyntax-only %s 2>&1 | FileCheck %s --implicit-check-not="Unexpected DO construct name"
+
+! A labeled DO statement has no construct name, so the END DO statement that
+! terminates it must not specify one, also when the loop is associated with an
+! OpenACC loop or combined construct.
+
+subroutine combined(a, n)
+ integer :: n, i
+ real :: a(n)
+ !$acc parallel loop
+ do 10 i = 1, n
+ a(i) = 0
+10 end do foo
+! CHECK: :[[@LINE-1]]:11: error: Unexpected DO construct name 'foo'
+end subroutine
+
+subroutine nested(a, n, m)
+ integer :: n, m, i, j
+ real :: a(n, m)
+ !$acc parallel
+ !$acc loop collapse(2)
+ do 20 j = 1, m
+ do 30 i = 1, n
+ a(i, j) = 0
+30 end do inner
+! CHECK: :[[@LINE-1]]:12: error: Unexpected DO construct name 'inner'
+20 end do outer
+! CHECK: :[[@LINE-1]]:11: error: Unexpected DO construct name 'outer'
+ !$acc end parallel
+end subroutine
+
+subroutine shared(a, n, m)
+ integer :: n, m, i, j
+ real :: a(n, m)
+ !$acc parallel loop collapse(2)
+ do 40 j = 1, m
+ do 40 i = 1, n
+ a(i, j) = 0
+40 end do bar
+! CHECK: :[[@LINE-1]]:11: error: Unexpected DO construct name 'bar'
+end subroutine
diff --git a/flang/test/Semantics/OpenACC/acc-label-do.f90 b/flang/test/Semantics/OpenACC/acc-label-do.f90
index dc758e29b70f5c..3517e5d3797024 100644
--- a/flang/test/Semantics/OpenACC/acc-label-do.f90
+++ b/flang/test/Semantics/OpenACC/acc-label-do.f90
@@ -86,3 +86,43 @@ subroutine shared_end_do(a, n, m)
a(i, j) = 1.0
100 end do
end subroutine
+
+subroutine goto_end_do(c, np)
+ integer :: np, n
+ real :: c(np)
+ !$acc parallel loop
+ do 100 n = 1, np
+ if (c(n) > 0) goto 100
+ c(n) = 0
+100 end do
+end subroutine
+
+subroutine end_directives(c, np)
+ integer :: np, n
+ real :: c(np)
+ !$acc parallel loop
+ do 100 n = 1, np
+ c(n) = 0
+100 end do
+ !$acc end parallel loop
+ !$acc parallel
+ !$acc loop
+ do 200 n = 1, np
+ c(n) = 1
+200 end do
+ !$acc end loop
+ !$acc end parallel
+end subroutine
+
+subroutine kernels_serial(c, np)
+ integer :: np, n
+ real :: c(np)
+ !$acc kernels loop
+ do 100 n = 1, np
+ c(n) = 0
+100 end do
+ !$acc serial loop
+ do 200 n = 1, np
+ c(n) = 1
+200 end do
+end subroutine
>From 9aa2c0bf274e1296d01d58abaceaf3b2ce8169d3 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Thu, 8 Oct 2026 20:38:07 -0700
Subject: [PATCH 2/2] [flang][openacc] Add a named labeled DO test; reword to
unnamed labeled DO
Only an unnamed labeled DO statement reaches AccNonBlockDoConstruct; a
named one is parsed as a DO construct. Say so in the comment and the test,
and add a test that a named labeled DO loop associated with an OpenACC
construct may be terminated by an END DO statement with the same name.
---
flang/lib/Parser/openacc-parsers.cpp | 7 ++++---
flang/test/Parser/acc-label-do-end-name.f90 | 16 ++++++++++++++--
flang/test/Semantics/OpenACC/acc-label-do.f90 | 9 +++++++++
3 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp
index 3b2c3826403fb3..bed9f3f8327727 100644
--- a/flang/lib/Parser/openacc-parsers.cpp
+++ b/flang/lib/Parser/openacc-parsers.cpp
@@ -237,9 +237,10 @@ struct AccNonBlockDoConstruct {
// The terminating statement may be an END DO statement; the DO construct
// built below has its own synthetic one, so turn it into a CONTINUE
- // statement to keep its label and source. A labeled DO statement has no
- // construct name, so diagnose a name on the END DO statement before it is
- // lost (C1135).
+ // statement to keep its label and source. Only an unnamed labeled DO
+ // statement is parsed here (a named one is parsed as a DO construct), so
+ // a construct name on the END DO statement is not allowed (C1135);
+ // diagnose it before it is lost.
if (auto *last{std::get_if<ExecutableConstruct>(&body.back().u)}) {
if (auto *endDoStmt{
std::get_if<Statement<common::Indirection<EndDoStmt>>>(
diff --git a/flang/test/Parser/acc-label-do-end-name.f90 b/flang/test/Parser/acc-label-do-end-name.f90
index 5199fb60ced331..71e352a46505a0 100644
--- a/flang/test/Parser/acc-label-do-end-name.f90
+++ b/flang/test/Parser/acc-label-do-end-name.f90
@@ -1,7 +1,7 @@
! RUN: not %flang_fc1 -fopenacc -fsyntax-only %s 2>&1 | FileCheck %s --implicit-check-not="Unexpected DO construct name"
-! A labeled DO statement has no construct name, so the END DO statement that
-! terminates it must not specify one, also when the loop is associated with an
+! The END DO statement that terminates an unnamed labeled DO loop must not
+! specify a construct name (C1135), also when the loop is associated with an
! OpenACC loop or combined construct.
subroutine combined(a, n)
@@ -39,3 +39,15 @@ subroutine shared(a, n, m)
40 end do bar
! CHECK: :[[@LINE-1]]:11: error: Unexpected DO construct name 'bar'
end subroutine
+
+! A named labeled DO loop may be terminated by an END DO statement with the
+! same name.
+
+subroutine named(a, n)
+ integer :: n, i
+ real :: a(n)
+ !$acc parallel loop
+ foo: do 50 i = 1, n
+ a(i) = 0
+50 end do foo
+end subroutine
diff --git a/flang/test/Semantics/OpenACC/acc-label-do.f90 b/flang/test/Semantics/OpenACC/acc-label-do.f90
index 3517e5d3797024..a732d637d8587f 100644
--- a/flang/test/Semantics/OpenACC/acc-label-do.f90
+++ b/flang/test/Semantics/OpenACC/acc-label-do.f90
@@ -126,3 +126,12 @@ subroutine kernels_serial(c, np)
c(n) = 1
200 end do
end subroutine
+
+subroutine named_label_do(c, np)
+ integer :: np, n
+ real :: c(np)
+ !$acc parallel loop
+ foo: do 100 n = 1, np
+ c(n) = 0
+100 end do foo
+end subroutine
More information about the flang-commits
mailing list