[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.
This commit is contained in:
Peter Klausler
2025-04-09 12:30:33 -07:00
committed by GitHub
parent be133ff4c4
commit 0ae9bb96d5
2 changed files with 91 additions and 35 deletions

View File

@@ -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);

View File

@@ -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