[flang] Fix fixed-form continuations of !$ OpenMP conditional lines (#135852)

I broke fixed-form line continuation (without !$) for OpenMP !$
conditional compilation lines. Fix it.
This commit is contained in:
Peter Klausler 2025-04-18 12:50:34 -07:00 committed by GitHub
parent 46387cd184
commit b4ff435b84
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 58 additions and 28 deletions

View File

@ -371,7 +371,7 @@ void Prescanner::CheckAndEmitLine(
// nor before or after conditional source. // nor before or after conditional source.
// Applications play shenanigans with line continuation before and // Applications play shenanigans with line continuation before and
// after #include'd subprogram argument lists and conditional source. // after #include'd subprogram argument lists and conditional source.
if (!isNestedInIncludeDirective_ && !omitNewline_ && if (!preprocessingOnly_ && !isNestedInIncludeDirective_ && !omitNewline_ &&
!afterPreprocessingDirective_ && tokens.BadlyNestedParentheses() && !afterPreprocessingDirective_ && tokens.BadlyNestedParentheses() &&
!preprocessor_.InConditional()) { !preprocessor_.InConditional()) {
if (nextLine_ < limit_ && IsPreprocessorDirectiveLine(nextLine_)) { if (nextLine_ < limit_ && IsPreprocessorDirectiveLine(nextLine_)) {
@ -975,17 +975,22 @@ void Prescanner::QuotedCharacterLiteral(
} else { } else {
isEscaped = false; isEscaped = false;
} }
EmitQuotedChar(static_cast<unsigned char>(*at_), emit, insert, false,
Encoding::LATIN_1);
while (PadOutCharacterLiteral(tokens)) {
}
if (*at_ == '\n') { 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), Say(GetProvenanceRange(start, end),
"Incomplete character literal"_err_en_US); "Incomplete character literal"_err_en_US);
} }
break; 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 // 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 // continuation lines at this point, and the entire significant part of
// the next continuation line is the name of a keyword macro, replace // the next continuation line is the name of a keyword macro, replace
@ -1314,23 +1319,30 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
} }
tabInCurrentLine_ = false; tabInCurrentLine_ = false;
char col1{*nextLine_}; 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 (InCompilerDirective()) {
if (!IsFixedFormCommentChar(col1)) { if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') {
return nullptr; if (IsFixedFormCommentChar(col1)) {
} else if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') { if (nextLine_[1] == '$' &&
// !$ OpenMP conditional compilation (nextLine_[2] == '&' || IsSpaceOrTab(&nextLine_[2]))) {
if (preprocessingOnly_) { // Next line is also !$ conditional compilation, might be continuation
// in -E mode, don't treat "!$ &" as a continuation if (preprocessingOnly_) {
return nullptr; return nullptr;
} else if (nextLine_[1] == '$') { }
// accept but do not require a matching sentinel } else {
if (!(nextLine_[2] == '&' || IsSpaceOrTab(&nextLine_[2]))) { return nullptr; // comment, or distinct directive
return nullptr;
} }
} else { } else if (!canBeNonDirectiveContinuation) {
return nullptr; // distinct directive 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}; int j{1};
for (; j < 5; ++j) { for (; j < 5; ++j) {
char ch{directiveSentinel_[j - 1]}; char ch{directiveSentinel_[j - 1]};
@ -1355,6 +1367,22 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
} }
} else { } else {
// Normal case: not in a compiler directive. // 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 == '&' && if (col1 == '&' &&
features_.IsEnabled( features_.IsEnabled(
LanguageFeature::FixedFormContinuationWithColumn1Ampersand)) { LanguageFeature::FixedFormContinuationWithColumn1Ampersand)) {
@ -1370,15 +1398,11 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
tabInCurrentLine_ = true; tabInCurrentLine_ = true;
return nextLine_ + 2; // VAX extension return nextLine_ + 2; // VAX extension
} }
if ((col1 == ' ' || if (canBeNonDirectiveContinuation) {
((col1 == 'D' || col1 == 'd') &&
features_.IsEnabled(LanguageFeature::OldDebugLines))) &&
nextLine_[1] == ' ' && nextLine_[2] == ' ' && nextLine_[3] == ' ' &&
nextLine_[4] == ' ') {
const char *col6{nextLine_ + 5}; const char *col6{nextLine_ + 5};
if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) { if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
if ((*col6 == 'i' || *col6 == 'I') && IsIncludeLine(nextLine_)) { if ((*col6 == 'i' || *col6 == 'I') && IsIncludeLine(nextLine_)) {
// It's An INCLUDE line, not a continuation // It's an INCLUDE line, not a continuation
} else { } else {
return nextLine_ + 6; return nextLine_ + 6;
} }

View File

@ -5,6 +5,12 @@
k01=1+ k01=1+
!$ & 1 !$ & 1
! CHECK: !$ k02=23
! CHECK: !$ &4
!$ k02=2
+3
!$ +4
! CHECK: !$omp parallel private(k01) ! CHECK: !$omp parallel private(k01)
!$omp parallel !$omp parallel
!$omp+ private(k01) !$omp+ private(k01)

View File

@ -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 do i = 1,10
! CHECK: Unmatched '(' ! CHECK: Unmatched '('
if (i != 0) then if (i != 0) then

View File

@ -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 ! Test implicit continuation for possible function-like macro calls only
#define flm(x) x #define flm(x) x
call notamacro(3 call notamacro(3