Skip to content

Commit b4ff435

Browse files
authored
[flang] Fix fixed-form continuations of !$ OpenMP conditional lines (#135852)
I broke fixed-form line continuation (without !$) for OpenMP !$ conditional compilation lines. Fix it.
1 parent 46387cd commit b4ff435

File tree

4 files changed

+58
-28
lines changed

4 files changed

+58
-28
lines changed

flang/lib/Parser/prescan.cpp

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ void Prescanner::CheckAndEmitLine(
371371
// nor before or after conditional source.
372372
// Applications play shenanigans with line continuation before and
373373
// after #include'd subprogram argument lists and conditional source.
374-
if (!isNestedInIncludeDirective_ && !omitNewline_ &&
374+
if (!preprocessingOnly_ && !isNestedInIncludeDirective_ && !omitNewline_ &&
375375
!afterPreprocessingDirective_ && tokens.BadlyNestedParentheses() &&
376376
!preprocessor_.InConditional()) {
377377
if (nextLine_ < limit_ && IsPreprocessorDirectiveLine(nextLine_)) {
@@ -975,17 +975,22 @@ void Prescanner::QuotedCharacterLiteral(
975975
} else {
976976
isEscaped = false;
977977
}
978-
EmitQuotedChar(static_cast<unsigned char>(*at_), emit, insert, false,
979-
Encoding::LATIN_1);
980-
while (PadOutCharacterLiteral(tokens)) {
981-
}
982978
if (*at_ == '\n') {
983-
if (!inPreprocessorDirective_) {
979+
if (inPreprocessorDirective_) {
980+
EmitQuotedChar(static_cast<unsigned char>(*at_), emit, insert, false,
981+
Encoding::LATIN_1);
982+
} else if (InCompilerDirective() && preprocessingOnly_) {
983+
// don't complain about -E output of !$, do it in later compilation
984+
} else {
984985
Say(GetProvenanceRange(start, end),
985986
"Incomplete character literal"_err_en_US);
986987
}
987988
break;
988989
}
990+
EmitQuotedChar(static_cast<unsigned char>(*at_), emit, insert, false,
991+
Encoding::LATIN_1);
992+
while (PadOutCharacterLiteral(tokens)) {
993+
}
989994
// Here's a weird edge case. When there's a two or more following
990995
// continuation lines at this point, and the entire significant part of
991996
// the next continuation line is the name of a keyword macro, replace
@@ -1314,23 +1319,30 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
13141319
}
13151320
tabInCurrentLine_ = false;
13161321
char col1{*nextLine_};
1322+
bool canBeNonDirectiveContinuation{
1323+
(col1 == ' ' ||
1324+
((col1 == 'D' || col1 == 'd') &&
1325+
features_.IsEnabled(LanguageFeature::OldDebugLines))) &&
1326+
nextLine_[1] == ' ' && nextLine_[2] == ' ' && nextLine_[3] == ' ' &&
1327+
nextLine_[4] == ' '};
13171328
if (InCompilerDirective()) {
1318-
if (!IsFixedFormCommentChar(col1)) {
1319-
return nullptr;
1320-
} else if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') {
1321-
// !$ OpenMP conditional compilation
1322-
if (preprocessingOnly_) {
1323-
// in -E mode, don't treat "!$ &" as a continuation
1324-
return nullptr;
1325-
} else if (nextLine_[1] == '$') {
1326-
// accept but do not require a matching sentinel
1327-
if (!(nextLine_[2] == '&' || IsSpaceOrTab(&nextLine_[2]))) {
1328-
return nullptr;
1329+
if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') {
1330+
if (IsFixedFormCommentChar(col1)) {
1331+
if (nextLine_[1] == '$' &&
1332+
(nextLine_[2] == '&' || IsSpaceOrTab(&nextLine_[2]))) {
1333+
// Next line is also !$ conditional compilation, might be continuation
1334+
if (preprocessingOnly_) {
1335+
return nullptr;
1336+
}
1337+
} else {
1338+
return nullptr; // comment, or distinct directive
13291339
}
1330-
} else {
1331-
return nullptr; // distinct directive
1340+
} else if (!canBeNonDirectiveContinuation) {
1341+
return nullptr;
13321342
}
1333-
} else { // all other directives
1343+
} else if (!IsFixedFormCommentChar(col1)) {
1344+
return nullptr; // in directive other than !$, but next line is not
1345+
} else { // in directive other than !$, next line might be continuation
13341346
int j{1};
13351347
for (; j < 5; ++j) {
13361348
char ch{directiveSentinel_[j - 1]};
@@ -1355,6 +1367,22 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
13551367
}
13561368
} else {
13571369
// Normal case: not in a compiler directive.
1370+
if (IsFixedFormCommentChar(col1)) {
1371+
if (nextLine_[1] == '$' && nextLine_[2] == ' ' && nextLine_[3] == ' ' &&
1372+
nextLine_[4] == ' ' &&
1373+
IsCompilerDirectiveSentinel(&nextLine_[1], 1) &&
1374+
!preprocessingOnly_) {
1375+
// !$ conditional compilation line as a continuation
1376+
const char *col6{nextLine_ + 5};
1377+
if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
1378+
if (mightNeedSpace && !IsSpace(nextLine_ + 6)) {
1379+
insertASpace_ = true;
1380+
}
1381+
return nextLine_ + 6;
1382+
}
1383+
}
1384+
return nullptr;
1385+
}
13581386
if (col1 == '&' &&
13591387
features_.IsEnabled(
13601388
LanguageFeature::FixedFormContinuationWithColumn1Ampersand)) {
@@ -1370,15 +1398,11 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
13701398
tabInCurrentLine_ = true;
13711399
return nextLine_ + 2; // VAX extension
13721400
}
1373-
if ((col1 == ' ' ||
1374-
((col1 == 'D' || col1 == 'd') &&
1375-
features_.IsEnabled(LanguageFeature::OldDebugLines))) &&
1376-
nextLine_[1] == ' ' && nextLine_[2] == ' ' && nextLine_[3] == ' ' &&
1377-
nextLine_[4] == ' ') {
1401+
if (canBeNonDirectiveContinuation) {
13781402
const char *col6{nextLine_ + 5};
13791403
if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
13801404
if ((*col6 == 'i' || *col6 == 'I') && IsIncludeLine(nextLine_)) {
1381-
// It's An INCLUDE line, not a continuation
1405+
// It's an INCLUDE line, not a continuation
13821406
} else {
13831407
return nextLine_ + 6;
13841408
}

flang/test/Parser/continuation-in-conditional-compilation.f

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ program main
55
k01=1+
66
!$ & 1
77

8+
! CHECK: !$ k02=23
9+
! CHECK: !$ &4
10+
!$ k02=2
11+
+3
12+
!$ +4
13+
814
! CHECK: !$omp parallel private(k01)
915
!$omp parallel
1016
!$omp+ private(k01)

flang/test/Parser/unmatched-parens.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
! RUN: not %flang_fc1 -E %s 2>&1 | FileCheck %s
1+
! RUN: not %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
22
do i = 1,10
33
! CHECK: Unmatched '('
44
if (i != 0) then

flang/test/Preprocessing/implicit-contin3.F90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
! RUN: not %flang -E %s 2>&1 | FileCheck %s
1+
! RUN: not %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
22
! Test implicit continuation for possible function-like macro calls only
33
#define flm(x) x
44
call notamacro(3

0 commit comments

Comments
 (0)