Skip to content

Conversation

@klausler
Copy link
Contributor

OpenMP conditional compilation lines (!$) work as continuation lines, but OpenACC and CUDA conditional lines do not.

Fixes #164727 and #164708.

OpenMP conditional compilation lines (!$) work as continuation lines,
but OpenACC and CUDA conditional lines do not.

Fixes llvm#164727 and
llvm#164708.
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:parser labels Oct 23, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 23, 2025

@llvm/pr-subscribers-flang-parser

Author: Peter Klausler (klausler)

Changes

OpenMP conditional compilation lines (!$) work as continuation lines, but OpenACC and CUDA conditional lines do not.

Fixes #164727 and #164708.


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

2 Files Affected:

  • (modified) flang/lib/Parser/prescan.cpp (+46-29)
  • (added) flang/test/Preprocessing/bug164727.cuf (+6)
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index df0372bbe554a..4739da0676fa9 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -1380,19 +1380,23 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
       }
     }
   } else { // Normal case: not in a compiler directive.
-    // !$ conditional compilation lines may be continuations when not
+    // Conditional compilation lines may be continuations when not
     // just preprocessing.
-    if (!preprocessingOnly_ && IsFixedFormCommentChar(col1) &&
-        nextLine_[1] == '$' && nextLine_[2] == ' ' && nextLine_[3] == ' ' &&
-        nextLine_[4] == ' ' && IsCompilerDirectiveSentinel(&nextLine_[1], 1)) {
-      if (const char *col6{nextLine_ + 5};
-          *col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
-        if (atNewline && !IsSpace(nextLine_ + 6)) {
-          brokenToken_ = true;
+    if (!preprocessingOnly_ && IsFixedFormCommentChar(col1)) {
+      if ((nextLine_[1] == '$' && nextLine_[2] == ' ' && nextLine_[3] == ' ' &&
+              nextLine_[4] == ' ' &&
+              IsCompilerDirectiveSentinel(&nextLine_[1], 1)) ||
+          (nextLine_[1] == '@' &&
+              IsCompilerDirectiveSentinel(&nextLine_[1], 4))) {
+        if (const char *col6{nextLine_ + 5};
+            *col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
+          if (atNewline && !IsSpace(nextLine_ + 6)) {
+            brokenToken_ = true;
+          }
+          return nextLine_ + 6;
+        } else {
+          return nullptr;
         }
-        return nextLine_ + 6;
-      } else {
-        return nullptr;
       }
     }
     if (col1 == '&' &&
@@ -1427,6 +1431,15 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
   return nullptr; // not a continuation line
 }
 
+constexpr bool IsDirective(const char *match, const char *dir) {
+  for (; *match; ++match) {
+    if (*match != ToLowerCaseLetter(*dir++)) {
+      return false;
+    }
+  }
+  return true;
+}
+
 const char *Prescanner::FreeFormContinuationLine(bool ampersand) {
   const char *lineStart{nextLine_};
   const char *p{lineStart};
@@ -1439,12 +1452,18 @@ const char *Prescanner::FreeFormContinuationLine(bool ampersand) {
       if (preprocessingOnly_) {
         // in -E mode, don't treat !$ as a continuation
         return nullptr;
-      } else if (p[0] == '!' && p[1] == '$') {
-        // accept but do not require a matching sentinel
-        if (p[2] != '&' && !IsSpaceOrTab(&p[2])) {
-          return nullptr; // not !$
-        }
+      } else if (p[0] == '!' && (p[1] == '$' || p[1] == '@')) {
         p += 2;
+        if (InOpenACCOrCUDAConditionalLine()) {
+          if (IsDirective("acc", p) || IsDirective("cuf", p)) {
+            p += 3;
+          } else {
+            return nullptr;
+          }
+        }
+        if (*p != '&' && !IsSpaceOrTab(p)) {
+          return nullptr;
+        }
       }
     } else if (*p++ == '!') {
       for (const char *s{directiveSentinel_}; *s != '\0'; ++p, ++s) {
@@ -1467,10 +1486,17 @@ const char *Prescanner::FreeFormContinuationLine(bool ampersand) {
       return nullptr;
     }
   }
-  if (p[0] == '!' && p[1] == '$' && !preprocessingOnly_ &&
-      features_.IsEnabled(LanguageFeature::OpenMP)) {
-    // !$ conditional line can be a continuation
-    p = lineStart = SkipWhiteSpace(p + 2);
+  if (p[0] == '!' && !preprocessingOnly_) {
+    // Conditional lines can be continuations
+    if (p[1] == '$' && features_.IsEnabled(LanguageFeature::OpenMP)) {
+      p = lineStart = SkipWhiteSpace(p + 2);
+    } else if (IsDirective("@acc", p + 1) &&
+        features_.IsEnabled(LanguageFeature::OpenACC)) {
+      p = lineStart = SkipWhiteSpace(p + 5);
+    } else if (IsDirective("@cuf", p + 1) &&
+        features_.IsEnabled(LanguageFeature::CUDA)) {
+      p = lineStart = SkipWhiteSpace(p + 5);
+    }
   }
   if (*p == '&') {
     return p + 1;
@@ -1706,15 +1732,6 @@ Prescanner::IsCompilerDirectiveSentinel(const char *p) const {
   return std::nullopt;
 }
 
-constexpr bool IsDirective(const char *match, const char *dir) {
-  for (; *match; ++match) {
-    if (*match != ToLowerCaseLetter(*dir++)) {
-      return false;
-    }
-  }
-  return true;
-}
-
 Prescanner::LineClassification Prescanner::ClassifyLine(
     const char *start) const {
   if (inFixedForm_) {
diff --git a/flang/test/Preprocessing/bug164727.cuf b/flang/test/Preprocessing/bug164727.cuf
new file mode 100644
index 0000000000000..89c846d25bb22
--- /dev/null
+++ b/flang/test/Preprocessing/bug164727.cuf
@@ -0,0 +1,6 @@
+!RUN: %flang_fc1 -fdebug-unparse -x cuda %s 2>&1 | FileCheck %s
+!CHECK: REAL, MANAGED, ALLOCATABLE :: x
+real, &
+  !@cuf managed, &
+  allocatable :: x
+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.

Thanks for the quick fix! LGTM

@klausler klausler merged commit af34890 into llvm:main Oct 24, 2025
13 checks passed
@klausler klausler deleted the bug164708 branch October 24, 2025 19:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[flang][cuda] Conditional compilation line in derived type component definition

3 participants