@@ -371,7 +371,7 @@ void Prescanner::CheckAndEmitLine(
371
371
// nor before or after conditional source.
372
372
// Applications play shenanigans with line continuation before and
373
373
// after #include'd subprogram argument lists and conditional source.
374
- if (!isNestedInIncludeDirective_ && !omitNewline_ &&
374
+ if (!preprocessingOnly_ && ! isNestedInIncludeDirective_ && !omitNewline_ &&
375
375
!afterPreprocessingDirective_ && tokens.BadlyNestedParentheses () &&
376
376
!preprocessor_.InConditional ()) {
377
377
if (nextLine_ < limit_ && IsPreprocessorDirectiveLine (nextLine_)) {
@@ -975,17 +975,22 @@ void Prescanner::QuotedCharacterLiteral(
975
975
} else {
976
976
isEscaped = false ;
977
977
}
978
- EmitQuotedChar (static_cast <unsigned char >(*at_), emit, insert, false ,
979
- Encoding::LATIN_1);
980
- while (PadOutCharacterLiteral (tokens)) {
981
- }
982
978
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 {
984
985
Say (GetProvenanceRange (start, end),
985
986
" Incomplete character literal" _err_en_US);
986
987
}
987
988
break ;
988
989
}
990
+ EmitQuotedChar (static_cast <unsigned char >(*at_), emit, insert, false ,
991
+ Encoding::LATIN_1);
992
+ while (PadOutCharacterLiteral (tokens)) {
993
+ }
989
994
// Here's a weird edge case. When there's a two or more following
990
995
// continuation lines at this point, and the entire significant part of
991
996
// the next continuation line is the name of a keyword macro, replace
@@ -1314,23 +1319,30 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
1314
1319
}
1315
1320
tabInCurrentLine_ = false ;
1316
1321
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 ] == ' ' };
1317
1328
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
1329
1339
}
1330
- } else {
1331
- return nullptr ; // distinct directive
1340
+ } else if (!canBeNonDirectiveContinuation) {
1341
+ return nullptr ;
1332
1342
}
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
1334
1346
int j{1 };
1335
1347
for (; j < 5 ; ++j) {
1336
1348
char ch{directiveSentinel_[j - 1 ]};
@@ -1355,6 +1367,22 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
1355
1367
}
1356
1368
} else {
1357
1369
// 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
+ }
1358
1386
if (col1 == ' &' &&
1359
1387
features_.IsEnabled (
1360
1388
LanguageFeature::FixedFormContinuationWithColumn1Ampersand)) {
@@ -1370,15 +1398,11 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
1370
1398
tabInCurrentLine_ = true ;
1371
1399
return nextLine_ + 2 ; // VAX extension
1372
1400
}
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) {
1378
1402
const char *col6{nextLine_ + 5 };
1379
1403
if (*col6 != ' \n ' && *col6 != ' 0' && !IsSpaceOrTab (col6)) {
1380
1404
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
1382
1406
} else {
1383
1407
return nextLine_ + 6 ;
1384
1408
}
0 commit comments