[flang-commits] [flang] [flang][openacc] Ignore bare acc routine in module subprogram part instead of erroring out (PR #205450)
Valentin Clement バレンタイン クレメン via flang-commits
flang-commits at lists.llvm.org
Wed Jun 24 14:51:00 PDT 2026
https://github.com/clementval updated https://github.com/llvm/llvm-project/pull/205450
>From eaced713de403fed0784efb16078d97dcee50190 Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Tue, 23 Jun 2026 16:15:14 -0700
Subject: [PATCH 1/5] [flang][openacc] Ignore bare acc routine in module
subprogram part instead of erroring out
---
flang/lib/Parser/program-parsers.cpp | 8 ++++++++
flang/test/Lower/OpenACC/acc-routine-bad.f90 | 11 +++++++++++
2 files changed, 19 insertions(+)
create mode 100644 flang/test/Lower/OpenACC/acc-routine-bad.f90
diff --git a/flang/lib/Parser/program-parsers.cpp b/flang/lib/Parser/program-parsers.cpp
index da8cd6fa27b65..a73dde8f5c81c 100644
--- a/flang/lib/Parser/program-parsers.cpp
+++ b/flang/lib/Parser/program-parsers.cpp
@@ -88,6 +88,13 @@ static constexpr auto globalOpenACCCompilerDirective{
construct<ProgramUnit>(indirect(skipStuffBeforeStatement >>
"!$ACC "_sptok >> Parser<OpenACCRoutineConstruct>{} / endOfLine))};
+// In a module-subprogram-part, a bare `!$ACC ROUTINE` line (without a name)
+// cannot be attached to a specific routine. Accept and ignore it so parsing
+// can continue to the following subprogram.
+static constexpr auto ignoredBareRoutineOpenACCDirective{
+ (skipStuffBeforeStatement >> "!$ACC "_sptok >> "ROUTINE"_tok / endOfLine) >>
+ construct<CompilerDirective>(pure<CompilerDirective::Unrecognized>())};
+
// R501 program -> program-unit [program-unit]...
// This is the top-level production for the Fortran language.
TYPE_PARSER(construct<Program>(skipStuffBeforeStatement >>
@@ -294,6 +301,7 @@ TYPE_CONTEXT_PARSER("module subprogram part"_en_US,
TYPE_PARSER(construct<ModuleSubprogram>(indirect(functionSubprogram)) ||
construct<ModuleSubprogram>(indirect(subroutineSubprogram)) ||
construct<ModuleSubprogram>(indirect(Parser<SeparateModuleSubprogram>{})) ||
+ construct<ModuleSubprogram>(indirect(ignoredBareRoutineOpenACCDirective)) ||
construct<ModuleSubprogram>(indirect(compilerDirective)))
// R1410 module-nature -> INTRINSIC | NON_INTRINSIC
diff --git a/flang/test/Lower/OpenACC/acc-routine-bad.f90 b/flang/test/Lower/OpenACC/acc-routine-bad.f90
new file mode 100644
index 0000000000000..1d9b73c12ac7d
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-routine-bad.f90
@@ -0,0 +1,11 @@
+! RUN: bbc -fopenacc -emit-hlfir %s -o - 2>&1 | FileCheck %s
+
+module acc_routine_bad
+
+contains
+!$acc routine
+subroutine acc_routine20()
+end subroutine
+end module
+
+!CHECK: {{.*}}warning: Compiler directive ignored here{{.*}}
>From bd271e03b9c8e5b90825df4136493845c7f40ddf Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Tue, 23 Jun 2026 16:54:43 -0700
Subject: [PATCH 2/5] Add more precise warning
---
flang/lib/Parser/program-parsers.cpp | 15 ++++++++++++++-
flang/test/Lower/OpenACC/acc-routine-bad.f90 | 2 +-
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/flang/lib/Parser/program-parsers.cpp b/flang/lib/Parser/program-parsers.cpp
index a73dde8f5c81c..dcef0a6742db7 100644
--- a/flang/lib/Parser/program-parsers.cpp
+++ b/flang/lib/Parser/program-parsers.cpp
@@ -88,11 +88,24 @@ static constexpr auto globalOpenACCCompilerDirective{
construct<ProgramUnit>(indirect(skipStuffBeforeStatement >>
"!$ACC "_sptok >> Parser<OpenACCRoutineConstruct>{} / endOfLine))};
+struct WarnUnnamedOpenACCRoutineDirective {
+ using resultType = Success;
+ std::optional<Success> Parse(ParseState &state) const {
+ state.Say("OpenACC routine directive without name must be placed in a "
+ "subroutine or function"_warn_en_US);
+ return {Success{}};
+ }
+};
+static constexpr WarnUnnamedOpenACCRoutineDirective
+ warnUnnamedOpenACCRoutineDirective;
+
// In a module-subprogram-part, a bare `!$ACC ROUTINE` line (without a name)
// cannot be attached to a specific routine. Accept and ignore it so parsing
// can continue to the following subprogram.
static constexpr auto ignoredBareRoutineOpenACCDirective{
- (skipStuffBeforeStatement >> "!$ACC "_sptok >> "ROUTINE"_tok / endOfLine) >>
+ ((skipStuffBeforeStatement >> "!$ACC "_sptok >>
+ "ROUTINE"_tok / endOfLine) >>
+ warnUnnamedOpenACCRoutineDirective) >>
construct<CompilerDirective>(pure<CompilerDirective::Unrecognized>())};
// R501 program -> program-unit [program-unit]...
diff --git a/flang/test/Lower/OpenACC/acc-routine-bad.f90 b/flang/test/Lower/OpenACC/acc-routine-bad.f90
index 1d9b73c12ac7d..f1cead6633a65 100644
--- a/flang/test/Lower/OpenACC/acc-routine-bad.f90
+++ b/flang/test/Lower/OpenACC/acc-routine-bad.f90
@@ -8,4 +8,4 @@ subroutine acc_routine20()
end subroutine
end module
-!CHECK: {{.*}}warning: Compiler directive ignored here{{.*}}
+!CHECK: {{.*}}warning: OpenACC routine directive without name must be placed in a subroutine or function
>From fd59dd28f569ce03646814439d72485b47a7887c Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Tue, 23 Jun 2026 20:40:17 -0700
Subject: [PATCH 3/5] Move test to semantic
---
flang/test/Lower/OpenACC/acc-routine-bad.f90 | 11 -----------
flang/test/Semantics/OpenACC/acc-routine-bad.f90 | 10 ++++++++++
2 files changed, 10 insertions(+), 11 deletions(-)
delete mode 100644 flang/test/Lower/OpenACC/acc-routine-bad.f90
create mode 100644 flang/test/Semantics/OpenACC/acc-routine-bad.f90
diff --git a/flang/test/Lower/OpenACC/acc-routine-bad.f90 b/flang/test/Lower/OpenACC/acc-routine-bad.f90
deleted file mode 100644
index f1cead6633a65..0000000000000
--- a/flang/test/Lower/OpenACC/acc-routine-bad.f90
+++ /dev/null
@@ -1,11 +0,0 @@
-! RUN: bbc -fopenacc -emit-hlfir %s -o - 2>&1 | FileCheck %s
-
-module acc_routine_bad
-
-contains
-!$acc routine
-subroutine acc_routine20()
-end subroutine
-end module
-
-!CHECK: {{.*}}warning: OpenACC routine directive without name must be placed in a subroutine or function
diff --git a/flang/test/Semantics/OpenACC/acc-routine-bad.f90 b/flang/test/Semantics/OpenACC/acc-routine-bad.f90
new file mode 100644
index 0000000000000..92ab7bdcf15b9
--- /dev/null
+++ b/flang/test/Semantics/OpenACC/acc-routine-bad.f90
@@ -0,0 +1,10 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenacc -Werror
+
+module acc_routine_bad
+
+contains
+!$acc routine
+!WARNING: OpenACC routine directive without name must be placed in a subroutine or function
+subroutine acc_routine20()
+end subroutine
+end module
>From 50969f6bb8b5d6fbfc6cca6413ea1d36a3d92f09 Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Wed, 24 Jun 2026 11:33:09 -0700
Subject: [PATCH 4/5] Use existing diagnostic for acc routine
---
flang/include/flang/Parser/parse-tree.h | 1 +
flang/include/flang/Semantics/program-tree.h | 2 ++
flang/lib/Parser/program-parsers.cpp | 22 +------------------
flang/lib/Semantics/program-tree.cpp | 5 +++++
.../Semantics/OpenACC/acc-routine-bad.f90 | 2 +-
5 files changed, 10 insertions(+), 22 deletions(-)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index ee6288539395c..26b1379606793 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -2986,6 +2986,7 @@ struct ModuleSubprogram {
std::variant<common::Indirection<FunctionSubprogram>,
common::Indirection<SubroutineSubprogram>,
common::Indirection<SeparateModuleSubprogram>,
+ common::Indirection<OpenACCDeclarativeConstruct>,
common::Indirection<CompilerDirective>>
u;
};
diff --git a/flang/include/flang/Semantics/program-tree.h b/flang/include/flang/Semantics/program-tree.h
index 1c89e6c175b96..ce53476511bfb 100644
--- a/flang/include/flang/Semantics/program-tree.h
+++ b/flang/include/flang/Semantics/program-tree.h
@@ -52,6 +52,8 @@ class ProgramTree {
const parser::BlockData &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::CompilerDirective &, SemanticsContext &);
+ static std::optional<ProgramTree> Build(
+ const parser::OpenACCDeclarativeConstruct &, SemanticsContext &);
static std::optional<ProgramTree> Build(
const parser::OpenACCRoutineConstruct &, SemanticsContext &);
diff --git a/flang/lib/Parser/program-parsers.cpp b/flang/lib/Parser/program-parsers.cpp
index dcef0a6742db7..1c9380d77d48f 100644
--- a/flang/lib/Parser/program-parsers.cpp
+++ b/flang/lib/Parser/program-parsers.cpp
@@ -88,26 +88,6 @@ static constexpr auto globalOpenACCCompilerDirective{
construct<ProgramUnit>(indirect(skipStuffBeforeStatement >>
"!$ACC "_sptok >> Parser<OpenACCRoutineConstruct>{} / endOfLine))};
-struct WarnUnnamedOpenACCRoutineDirective {
- using resultType = Success;
- std::optional<Success> Parse(ParseState &state) const {
- state.Say("OpenACC routine directive without name must be placed in a "
- "subroutine or function"_warn_en_US);
- return {Success{}};
- }
-};
-static constexpr WarnUnnamedOpenACCRoutineDirective
- warnUnnamedOpenACCRoutineDirective;
-
-// In a module-subprogram-part, a bare `!$ACC ROUTINE` line (without a name)
-// cannot be attached to a specific routine. Accept and ignore it so parsing
-// can continue to the following subprogram.
-static constexpr auto ignoredBareRoutineOpenACCDirective{
- ((skipStuffBeforeStatement >> "!$ACC "_sptok >>
- "ROUTINE"_tok / endOfLine) >>
- warnUnnamedOpenACCRoutineDirective) >>
- construct<CompilerDirective>(pure<CompilerDirective::Unrecognized>())};
-
// R501 program -> program-unit [program-unit]...
// This is the top-level production for the Fortran language.
TYPE_PARSER(construct<Program>(skipStuffBeforeStatement >>
@@ -314,7 +294,7 @@ TYPE_CONTEXT_PARSER("module subprogram part"_en_US,
TYPE_PARSER(construct<ModuleSubprogram>(indirect(functionSubprogram)) ||
construct<ModuleSubprogram>(indirect(subroutineSubprogram)) ||
construct<ModuleSubprogram>(indirect(Parser<SeparateModuleSubprogram>{})) ||
- construct<ModuleSubprogram>(indirect(ignoredBareRoutineOpenACCDirective)) ||
+ construct<ModuleSubprogram>(indirect(openaccDeclarativeConstruct)) ||
construct<ModuleSubprogram>(indirect(compilerDirective)))
// R1410 module-nature -> INTRINSIC | NON_INTRINSIC
diff --git a/flang/lib/Semantics/program-tree.cpp b/flang/lib/Semantics/program-tree.cpp
index 89517982de67c..214d285c6bc4f 100644
--- a/flang/lib/Semantics/program-tree.cpp
+++ b/flang/lib/Semantics/program-tree.cpp
@@ -232,6 +232,11 @@ std::optional<ProgramTree> ProgramTree::Build(
return std::nullopt;
}
+std::optional<ProgramTree> ProgramTree::Build(
+ const parser::OpenACCDeclarativeConstruct &, SemanticsContext &) {
+ return std::nullopt;
+}
+
std::optional<ProgramTree> ProgramTree::Build(
const parser::OpenACCRoutineConstruct &, SemanticsContext &) {
DIE("ProgramTree::Build() called for OpenACCRoutineConstruct");
diff --git a/flang/test/Semantics/OpenACC/acc-routine-bad.f90 b/flang/test/Semantics/OpenACC/acc-routine-bad.f90
index 92ab7bdcf15b9..2481f0a7923c4 100644
--- a/flang/test/Semantics/OpenACC/acc-routine-bad.f90
+++ b/flang/test/Semantics/OpenACC/acc-routine-bad.f90
@@ -3,8 +3,8 @@
module acc_routine_bad
contains
+!ERROR: ROUTINE directive without name must appear within the specification part of a subroutine or function definition, or within an interface body for a subroutine or function in an interface block
!$acc routine
-!WARNING: OpenACC routine directive without name must be placed in a subroutine or function
subroutine acc_routine20()
end subroutine
end module
>From a5b02b2d8b4ecfc63f4a5439cb8a60204939e29e Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Wed, 24 Jun 2026 14:50:33 -0700
Subject: [PATCH 5/5] Add test for acc declare and remove -Werror
---
flang/lib/Semantics/check-acc-structure.cpp | 7 +++++--
flang/test/Semantics/OpenACC/acc-declare-validity.f90 | 9 +++++++++
flang/test/Semantics/OpenACC/acc-routine-bad.f90 | 2 +-
3 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp
index ad8da4e9436a2..de4489932d37a 100644
--- a/flang/lib/Semantics/check-acc-structure.cpp
+++ b/flang/lib/Semantics/check-acc-structure.cpp
@@ -819,7 +819,8 @@ void AccStructureChecker::CheckMultipleOccurrenceInDeclare(
[&](const parser::Designator &designator) {
if (const auto *name =
parser::GetDesignatorNameIfDataRef(designator)) {
- if (declareSymbols.contains(&name->symbol->GetUltimate())) {
+ if (name->symbol &&
+ declareSymbols.contains(&name->symbol->GetUltimate())) {
if (declareSymbols[&name->symbol->GetUltimate()] == clause) {
context_.Warn(common::UsageWarning::OpenAccUsage,
GetContext().clauseSource,
@@ -840,7 +841,9 @@ void AccStructureChecker::CheckMultipleOccurrenceInDeclare(
.str()));
}
}
- declareSymbols.insert({&name->symbol->GetUltimate(), clause});
+ if (name->symbol) {
+ declareSymbols.insert({&name->symbol->GetUltimate(), clause});
+ }
}
},
[&](const parser::Name &name) {
diff --git a/flang/test/Semantics/OpenACC/acc-declare-validity.f90 b/flang/test/Semantics/OpenACC/acc-declare-validity.f90
index 3e40c964b002e..784ca0a01845a 100644
--- a/flang/test/Semantics/OpenACC/acc-declare-validity.f90
+++ b/flang/test/Semantics/OpenACC/acc-declare-validity.f90
@@ -84,3 +84,12 @@ subroutine sub3()
end subroutine
end module openacc_declare_validity
+
+
+module m
+ integer :: x
+contains
+ !$acc declare copyin(x)
+ subroutine s()
+ end subroutine
+end module
diff --git a/flang/test/Semantics/OpenACC/acc-routine-bad.f90 b/flang/test/Semantics/OpenACC/acc-routine-bad.f90
index 2481f0a7923c4..3557495b1d9f0 100644
--- a/flang/test/Semantics/OpenACC/acc-routine-bad.f90
+++ b/flang/test/Semantics/OpenACC/acc-routine-bad.f90
@@ -1,4 +1,4 @@
-! RUN: %python %S/../test_errors.py %s %flang -fopenacc -Werror
+! RUN: %python %S/../test_errors.py %s %flang -fopenacc
module acc_routine_bad
More information about the flang-commits
mailing list