[flang-commits] [flang] [flang] Fix fixed-form continuations of !$ OpenMP conditional lines (PR #135852)
via flang-commits
flang-commits at lists.llvm.org
Tue Apr 15 13:48:22 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-parser
Author: Peter Klausler (klausler)
<details>
<summary>Changes</summary>
I broke fixed-form line continuation (without !$) for OpenMP !$ conditional compilation lines. Fix it.
---
Full diff: https://github.com/llvm/llvm-project/pull/135852.diff
4 Files Affected:
- (modified) flang/lib/Parser/prescan.cpp (+50-26)
- (modified) flang/test/Parser/continuation-in-conditional-compilation.f (+6)
- (modified) flang/test/Parser/unmatched-parens.f90 (+1-1)
- (modified) flang/test/Preprocessing/implicit-contin3.F90 (+1-1)
``````````diff
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index b2b3d7fcfe786..2db9fa0a937f3 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -371,7 +371,7 @@ void Prescanner::CheckAndEmitLine(
// nor before or after conditional source.
// Applications play shenanigans with line continuation before and
// after #include'd subprogram argument lists and conditional source.
- if (!isNestedInIncludeDirective_ && !omitNewline_ &&
+ if (!preprocessingOnly_ && !isNestedInIncludeDirective_ && !omitNewline_ &&
!afterPreprocessingDirective_ && tokens.BadlyNestedParentheses() &&
!preprocessor_.InConditional()) {
if (nextLine_ < limit_ && IsPreprocessorDirectiveLine(nextLine_)) {
@@ -975,17 +975,22 @@ void Prescanner::QuotedCharacterLiteral(
} else {
isEscaped = false;
}
- EmitQuotedChar(static_cast<unsigned char>(*at_), emit, insert, false,
- Encoding::LATIN_1);
- while (PadOutCharacterLiteral(tokens)) {
- }
if (*at_ == '\n') {
- if (!inPreprocessorDirective_) {
+ if (inPreprocessorDirective_) {
+ EmitQuotedChar(static_cast<unsigned char>(*at_), emit, insert, false,
+ Encoding::LATIN_1);
+ } else if (InCompilerDirective() && preprocessingOnly_) {
+ // don't complain about -E output of !$, do it in later compilation
+ } else {
Say(GetProvenanceRange(start, end),
"Incomplete character literal"_err_en_US);
}
break;
}
+ EmitQuotedChar(static_cast<unsigned char>(*at_), emit, insert, false,
+ Encoding::LATIN_1);
+ while (PadOutCharacterLiteral(tokens)) {
+ }
// Here's a weird edge case. When there's a two or more following
// continuation lines at this point, and the entire significant part of
// the next continuation line is the name of a keyword macro, replace
@@ -1314,23 +1319,30 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
}
tabInCurrentLine_ = false;
char col1{*nextLine_};
+ bool canBeNonDirectiveContinuation{
+ (col1 == ' ' ||
+ ((col1 == 'D' || col1 == 'd') &&
+ features_.IsEnabled(LanguageFeature::OldDebugLines))) &&
+ nextLine_[1] == ' ' && nextLine_[2] == ' ' && nextLine_[3] == ' ' &&
+ nextLine_[4] == ' '};
if (InCompilerDirective()) {
- if (!IsFixedFormCommentChar(col1)) {
- return nullptr;
- } else if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') {
- // !$ OpenMP conditional compilation
- if (preprocessingOnly_) {
- // in -E mode, don't treat "!$ &" as a continuation
- return nullptr;
- } else if (nextLine_[1] == '$') {
- // accept but do not require a matching sentinel
- if (!(nextLine_[2] == '&' || IsSpaceOrTab(&nextLine_[2]))) {
- return nullptr;
+ if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') {
+ if (IsFixedFormCommentChar(col1)) {
+ if (nextLine_[1] == '$' &&
+ (nextLine_[2] == '&' || IsSpaceOrTab(&nextLine_[2]))) {
+ // Next line is also !$ conditional compilation, might be continuation
+ if (preprocessingOnly_) {
+ return nullptr;
+ }
+ } else {
+ return nullptr; // comment, or distinct directive
}
- } else {
- return nullptr; // distinct directive
+ } else if (!canBeNonDirectiveContinuation) {
+ return nullptr;
}
- } else { // all other directives
+ } else if (!IsFixedFormCommentChar(col1)) {
+ return nullptr; // in directive other than !$, but next line is not
+ } else { // in directive other than !$, next line might be continuation
int j{1};
for (; j < 5; ++j) {
char ch{directiveSentinel_[j - 1]};
@@ -1355,6 +1367,22 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
}
} else {
// Normal case: not in a compiler directive.
+ if (IsFixedFormCommentChar(col1)) {
+ if (nextLine_[1] == '$' && nextLine_[2] == ' ' && nextLine_[3] == ' ' &&
+ nextLine_[4] == ' ' &&
+ IsCompilerDirectiveSentinel(&nextLine_[1], 1) &&
+ !preprocessingOnly_) {
+ // !$ conditional compilation line as a continuation
+ const char *col6{nextLine_ + 5};
+ if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
+ if (mightNeedSpace && !IsSpace(nextLine_ + 6)) {
+ insertASpace_ = true;
+ }
+ return nextLine_ + 6;
+ }
+ }
+ return nullptr;
+ }
if (col1 == '&' &&
features_.IsEnabled(
LanguageFeature::FixedFormContinuationWithColumn1Ampersand)) {
@@ -1370,15 +1398,11 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
tabInCurrentLine_ = true;
return nextLine_ + 2; // VAX extension
}
- if ((col1 == ' ' ||
- ((col1 == 'D' || col1 == 'd') &&
- features_.IsEnabled(LanguageFeature::OldDebugLines))) &&
- nextLine_[1] == ' ' && nextLine_[2] == ' ' && nextLine_[3] == ' ' &&
- nextLine_[4] == ' ') {
+ if (canBeNonDirectiveContinuation) {
const char *col6{nextLine_ + 5};
if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
if ((*col6 == 'i' || *col6 == 'I') && IsIncludeLine(nextLine_)) {
- // It's An INCLUDE line, not a continuation
+ // It's an INCLUDE line, not a continuation
} else {
return nextLine_ + 6;
}
diff --git a/flang/test/Parser/continuation-in-conditional-compilation.f b/flang/test/Parser/continuation-in-conditional-compilation.f
index 35525b4fda582..57b69de657348 100644
--- a/flang/test/Parser/continuation-in-conditional-compilation.f
+++ b/flang/test/Parser/continuation-in-conditional-compilation.f
@@ -5,6 +5,12 @@ program main
k01=1+
!$ & 1
+! CHECK: !$ k02=23
+! CHECK: !$ &4
+!$ k02=2
+ +3
+!$ +4
+
! CHECK: !$omp parallel private(k01)
!$omp parallel
!$omp+ private(k01)
diff --git a/flang/test/Parser/unmatched-parens.f90 b/flang/test/Parser/unmatched-parens.f90
index c0a3e843f4f72..ad8c37cf60af4 100644
--- a/flang/test/Parser/unmatched-parens.f90
+++ b/flang/test/Parser/unmatched-parens.f90
@@ -1,4 +1,4 @@
-! RUN: not %flang_fc1 -E %s 2>&1 | FileCheck %s
+! RUN: not %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
do i = 1,10
! CHECK: Unmatched '('
if (i != 0) then
diff --git a/flang/test/Preprocessing/implicit-contin3.F90 b/flang/test/Preprocessing/implicit-contin3.F90
index 8c1829d55eee7..4c31d076aa681 100644
--- a/flang/test/Preprocessing/implicit-contin3.F90
+++ b/flang/test/Preprocessing/implicit-contin3.F90
@@ -1,4 +1,4 @@
-! RUN: not %flang -E %s 2>&1 | FileCheck %s
+! RUN: not %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
! Test implicit continuation for possible function-like macro calls only
#define flm(x) x
call notamacro(3
``````````
</details>
https://github.com/llvm/llvm-project/pull/135852
More information about the flang-commits
mailing list