[flang-commits] [flang] 0ae9bb9 - [flang][OpenMP] Fix regression in !$ continuation (#134756)
via flang-commits
flang-commits at lists.llvm.org
Wed Apr 9 12:30:36 PDT 2025
Author: Peter Klausler
Date: 2025-04-09T12:30:33-07:00
New Revision: 0ae9bb96d5af47a2426596dbd0c35e3ff0cdddcc
URL: https://github.com/llvm/llvm-project/commit/0ae9bb96d5af47a2426596dbd0c35e3ff0cdddcc
DIFF: https://github.com/llvm/llvm-project/commit/0ae9bb96d5af47a2426596dbd0c35e3ff0cdddcc.diff
LOG: [flang][OpenMP] Fix regression in !$ continuation (#134756)
A recent patch that obviated the need to use -fopenmp when using the
compiler to preprocess in -E mode broke a case of Fortran line
continuation when using OpenMP conditional compilation lines (!$) when
*not* in -E mode. Fix.
Added:
Modified:
flang/lib/Parser/prescan.cpp
flang/test/Parser/OpenMP/compiler-directive-continuation.f90
Removed:
################################################################################
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 005cf51fd5438..43a6d8c76f067 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -150,11 +150,11 @@ void Prescanner::Statement() {
CHECK(*at_ == '!');
}
std::optional<int> condOffset;
- bool isFFOpenMPCondCompilation{false};
- if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') {
+ bool isOpenMPCondCompilation{
+ directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0'};
+ if (isOpenMPCondCompilation) {
// OpenMP conditional compilation line.
condOffset = 2;
- isFFOpenMPCondCompilation = inFixedForm_;
} else if (directiveSentinel_[0] == '@' && directiveSentinel_[1] == 'c' &&
directiveSentinel_[2] == 'u' && directiveSentinel_[3] == 'f' &&
directiveSentinel_[4] == '\0') {
@@ -166,10 +166,19 @@ void Prescanner::Statement() {
if (auto payload{IsIncludeLine(at_)}) {
FortranInclude(at_ + *payload);
return;
- } else if (inFixedForm_) {
- LabelField(tokens);
- } else {
- SkipSpaces();
+ }
+ while (true) {
+ if (auto n{IsSpace(at_)}) {
+ at_ += n, ++column_;
+ } else if (*at_ == '\t') {
+ ++at_, ++column_;
+ tabInCurrentLine_ = true;
+ } else if (inFixedForm_ && column_ == 6 && !tabInCurrentLine_ &&
+ *at_ == '0') {
+ ++at_, ++column_;
+ } else {
+ break;
+ }
}
} else {
// Compiler directive. Emit normalized sentinel, squash following spaces.
@@ -183,12 +192,16 @@ void Prescanner::Statement() {
}
if (IsSpaceOrTab(at_)) {
while (int n{IsSpaceOrTab(at_)}) {
- if (isFFOpenMPCondCompilation) {
+ if (isOpenMPCondCompilation && inFixedForm_) {
EmitChar(tokens, ' ');
}
+ tabInCurrentLine_ |= *at_ == '\t';
at_ += n, ++column_;
+ if (inFixedForm_ && column_ > fixedFormColumnLimit_) {
+ break;
+ }
}
- if (isFFOpenMPCondCompilation && column_ == 6) {
+ if (isOpenMPCondCompilation && inFixedForm_ && column_ == 6) {
if (*at_ == '0') {
EmitChar(tokens, ' ');
} else {
@@ -202,6 +215,11 @@ void Prescanner::Statement() {
}
tokens.CloseToken();
}
+ if (*at_ == '!' || *at_ == '\n' ||
+ (inFixedForm_ && column_ > fixedFormColumnLimit_ &&
+ !tabInCurrentLine_)) {
+ return; // Directive without payload
+ }
break;
}
case LineClassification::Kind::Source: {
@@ -1291,17 +1309,28 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
tabInCurrentLine_ = false;
char col1{*nextLine_};
if (InCompilerDirective()) {
- if (preprocessingOnly_ && directiveSentinel_[0] == '$' &&
- directiveSentinel_[1] == '\0') {
- // in -E mode, don't treat "!$ &" as a continuation
+ if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') {
+ // !$ OpenMP conditional compilation
+ if (preprocessingOnly_) {
+ // in -E mode, don't treat "!$ &" as a continuation
+ return nullptr;
+ } else if (IsFixedFormCommentChar(col1)) {
+ if (nextLine_[1] == '$') {
+ // accept but do not require a matching sentinel
+ if (!(nextLine_[2] == '&' || IsSpaceOrTab(&nextLine_[2]))) {
+ return nullptr;
+ }
+ } else {
+ return nullptr; // distinct directive
+ }
+ }
} else if (IsFixedFormCommentChar(col1)) {
int j{1};
for (; j < 5; ++j) {
char ch{directiveSentinel_[j - 1]};
if (ch == '\0') {
break;
- }
- if (ch != ToLowerCaseLetter(nextLine_[j])) {
+ } else if (ch != ToLowerCaseLetter(nextLine_[j])) {
return nullptr;
}
}
@@ -1310,13 +1339,15 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
return nullptr;
}
}
- const char *col6{nextLine_ + 5};
- if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
- if (mightNeedSpace && !IsSpace(nextLine_ + 6)) {
- insertASpace_ = true;
- }
- return nextLine_ + 6;
+ } else {
+ return nullptr;
+ }
+ const char *col6{nextLine_ + 5};
+ if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
+ if (mightNeedSpace && !IsSpace(nextLine_ + 6)) {
+ insertASpace_ = true;
}
+ return nextLine_ + 6;
}
} else {
// Normal case: not in a compiler directive.
@@ -1364,26 +1395,37 @@ const char *Prescanner::FreeFormContinuationLine(bool ampersand) {
}
p = SkipWhiteSpaceIncludingEmptyMacros(p);
if (InCompilerDirective()) {
- if (preprocessingOnly_ && directiveSentinel_[0] == '$' &&
- directiveSentinel_[1] == '\0') {
- // in -E mode, don't treat !$ as a continuation
+ if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') {
+ 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 !$
+ }
+ p += 2;
+ }
} else if (*p++ == '!') {
for (const char *s{directiveSentinel_}; *s != '\0'; ++p, ++s) {
if (*s != ToLowerCaseLetter(*p)) {
return nullptr; // not the same directive class
}
}
- p = SkipWhiteSpace(p);
- if (*p == '&') {
- if (!ampersand) {
- insertASpace_ = true;
- }
- return p + 1;
- } else if (ampersand) {
- return p;
+ } else {
+ return nullptr;
+ }
+ p = SkipWhiteSpace(p);
+ if (*p == '&') {
+ if (!ampersand) {
+ insertASpace_ = true;
}
+ return p + 1;
+ } else if (ampersand) {
+ return p;
+ } else {
+ return nullptr;
}
- return nullptr;
}
if (p[0] == '!' && p[1] == '$' && !preprocessingOnly_ &&
features_.IsEnabled(LanguageFeature::OpenMP)) {
@@ -1606,8 +1648,13 @@ Prescanner::IsCompilerDirectiveSentinel(const char *p) const {
if (int n{IsSpaceOrTab(p)};
n || !(IsLetter(*p) || *p == '$' || *p == '@')) {
if (j > 0) {
+ if (j == 1 && sentinel[0] == '$' && n == 0 && *p != '&') {
+ // OpenMP conditional compilation line sentinels have to
+ // be immediately followed by a space or &, not a digit
+ // or anything else.
+ break;
+ }
sentinel[j] = '\0';
- p = SkipWhiteSpaceIncludingEmptyMacros(p + n);
if (*p != '!') {
if (const char *sp{IsCompilerDirectiveSentinel(sentinel, j)}) {
return std::make_pair(sp, p);
diff --git a/flang/test/Parser/OpenMP/compiler-directive-continuation.f90 b/flang/test/Parser/OpenMP/compiler-directive-continuation.f90
index 7ace109272302..169976d74c0bf 100644
--- a/flang/test/Parser/OpenMP/compiler-directive-continuation.f90
+++ b/flang/test/Parser/OpenMP/compiler-directive-continuation.f90
@@ -15,7 +15,7 @@
! CHECK-NO-OMP: i=1010011_4
subroutine mixed_form1()
i = 1 &
- !$+100&
+ !$ +100&
!$&+ 1000&
&+ 10 + 1&
!$& +100000&
@@ -53,3 +53,12 @@ subroutine mixed_form3()
!$ +1000
end subroutine
+! CHECK-LABEL: subroutine regression
+! CHECK-E:{{^}}!$ real x, &
+! CHECK-E:{{^}} stop
+! CHECK-OMP: REAL x, stop
+! CHECK-NO-OMP-NOT: REAL x,
+subroutine regression
+!$ real x, &
+ stop
+end
More information about the flang-commits
mailing list