@@ -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 }
0 commit comments