[flang-commits] [flang] [flang] Line continuation for !@acc and !@cuf conditional lines (PR #164475)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Tue Oct 21 11:44:21 PDT 2025
https://github.com/klausler created https://github.com/llvm/llvm-project/pull/164475
Some Fortran source-level features that work for OpenMP !$ conditional lines, such as free form line continuation, don't work for OpenACC !@acc or CUDA !@cuf conditional lines. Make them less particular.
Fixes https://github.com/llvm/llvm-project/issues/164470.
>From 55ed3bbb386a47a5977a0ba897407dd8b1059d81 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Tue, 21 Oct 2025 11:41:25 -0700
Subject: [PATCH] [flang] Line continuation for !@acc and !@cuf conditional
lines
Some Fortran source-level features that work for OpenMP !$ conditional
lines, such as free form line continuation, don't work for OpenACC
!@acc or CUDA !@cuf conditional lines. Make them less particular.
Fixes https://github.com/llvm/llvm-project/issues/164470.
---
flang/lib/Parser/prescan.cpp | 26 +++++++++-----------------
flang/lib/Parser/prescan.h | 12 +++++++++++-
flang/test/Preprocessing/bug164470.cuf | 6 ++++++
3 files changed, 26 insertions(+), 18 deletions(-)
create mode 100644 flang/test/Preprocessing/bug164470.cuf
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 66e5b2cbd5c7f..df0372bbe554a 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -140,17 +140,9 @@ void Prescanner::Statement() {
CHECK(*at_ == '!');
}
std::optional<int> condOffset;
- if (InOpenMPConditionalLine()) {
+ if (InOpenMPConditionalLine()) { // !$
condOffset = 2;
- } else if (directiveSentinel_[0] == '@' && directiveSentinel_[1] == 'c' &&
- directiveSentinel_[2] == 'u' && directiveSentinel_[3] == 'f' &&
- directiveSentinel_[4] == '\0') {
- // CUDA conditional compilation line.
- condOffset = 5;
- } else if (directiveSentinel_[0] == '@' && directiveSentinel_[1] == 'a' &&
- directiveSentinel_[2] == 'c' && directiveSentinel_[3] == 'c' &&
- directiveSentinel_[4] == '\0') {
- // OpenACC conditional compilation line.
+ } else if (InOpenACCOrCUDAConditionalLine()) { // !@acc or !@cuf
condOffset = 5;
}
if (condOffset && !preprocessingOnly_) {
@@ -166,7 +158,8 @@ void Prescanner::Statement() {
} else {
// Compiler directive. Emit normalized sentinel, squash following spaces.
// Conditional compilation lines (!$) take this path in -E mode too
- // so that -fopenmp only has to appear on the later compilation.
+ // so that -fopenmp only has to appear on the later compilation
+ // (ditto for !@cuf and !@acc).
EmitChar(tokens, '!');
++at_, ++column_;
for (const char *sp{directiveSentinel_}; *sp != '\0';
@@ -202,7 +195,7 @@ void Prescanner::Statement() {
}
tokens.CloseToken();
SkipSpaces();
- if (InOpenMPConditionalLine() && inFixedForm_ && !tabInCurrentLine_ &&
+ if (InConditionalLine() && inFixedForm_ && !tabInCurrentLine_ &&
column_ == 6 && *at_ != '\n') {
// !$ 0 - turn '0' into a space
// !$ 1 - turn '1' into '&'
@@ -347,7 +340,7 @@ void Prescanner::Statement() {
while (CompilerDirectiveContinuation(tokens, line.sentinel)) {
newlineProvenance = GetCurrentProvenance();
}
- if (preprocessingOnly_ && inFixedForm_ && InOpenMPConditionalLine() &&
+ if (preprocessingOnly_ && inFixedForm_ && InConditionalLine() &&
nextLine_ < limit_) {
// In -E mode, when the line after !$ conditional compilation is a
// regular fixed form continuation line, append a '&' to the line.
@@ -1360,11 +1353,10 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
features_.IsEnabled(LanguageFeature::OldDebugLines))) &&
nextLine_[1] == ' ' && nextLine_[2] == ' ' && nextLine_[3] == ' ' &&
nextLine_[4] == ' '};
- if (InCompilerDirective() &&
- !(InOpenMPConditionalLine() && !preprocessingOnly_)) {
+ if (InCompilerDirective() && !(InConditionalLine() && !preprocessingOnly_)) {
// !$ under -E is not continued, but deferred to later compilation
if (IsFixedFormCommentChar(col1) &&
- !(InOpenMPConditionalLine() && preprocessingOnly_)) {
+ !(InConditionalLine() && preprocessingOnly_)) {
int j{1};
for (; j < 5; ++j) {
char ch{directiveSentinel_[j - 1]};
@@ -1443,7 +1435,7 @@ const char *Prescanner::FreeFormContinuationLine(bool ampersand) {
}
p = SkipWhiteSpaceIncludingEmptyMacros(p);
if (InCompilerDirective()) {
- if (InOpenMPConditionalLine()) {
+ if (InConditionalLine()) {
if (preprocessingOnly_) {
// in -E mode, don't treat !$ as a continuation
return nullptr;
diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h
index fc38adb926530..5e7481781d944 100644
--- a/flang/lib/Parser/prescan.h
+++ b/flang/lib/Parser/prescan.h
@@ -171,7 +171,17 @@ class Prescanner {
bool InOpenMPConditionalLine() const {
return directiveSentinel_ && directiveSentinel_[0] == '$' &&
!directiveSentinel_[1];
- ;
+ }
+ bool InOpenACCOrCUDAConditionalLine() const {
+ return directiveSentinel_ && directiveSentinel_[0] == '@' &&
+ ((directiveSentinel_[1] == 'a' && directiveSentinel_[2] == 'c' &&
+ directiveSentinel_[3] == 'c') ||
+ (directiveSentinel_[1] == 'c' && directiveSentinel_[2] == 'u' &&
+ directiveSentinel_[3] == 'f')) &&
+ directiveSentinel_[4] == '\0';
+ }
+ bool InConditionalLine() const {
+ return InOpenMPConditionalLine() || InOpenACCOrCUDAConditionalLine();
}
bool InFixedFormSource() const {
return inFixedForm_ && !inPreprocessorDirective_ && !InCompilerDirective();
diff --git a/flang/test/Preprocessing/bug164470.cuf b/flang/test/Preprocessing/bug164470.cuf
new file mode 100644
index 0000000000000..3e959f40d2e3f
--- /dev/null
+++ b/flang/test/Preprocessing/bug164470.cuf
@@ -0,0 +1,6 @@
+!RUN: %flang_fc1 -x cuda -fdebug-unparse %s 2>&1 | FileCheck %s
+!CHECK: ATTRIBUTES(DEVICE) FUNCTION foo()
+!@cuf attributes(device) &
+function foo()
+ foo = 1.
+end
More information about the flang-commits
mailing list