diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp index b2b3d7fcfe786..2db9fa0a937f3 100644 --- a/flang/lib/Parser/prescan.cpp +++ b/flang/lib/Parser/prescan.cpp @@ -371,7 +371,7 @@ void Prescanner::CheckAndEmitLine( // nor before or after conditional source. // Applications play shenanigans with line continuation before and // after #include'd subprogram argument lists and conditional source. - if (!isNestedInIncludeDirective_ && !omitNewline_ && + if (!preprocessingOnly_ && !isNestedInIncludeDirective_ && !omitNewline_ && !afterPreprocessingDirective_ && tokens.BadlyNestedParentheses() && !preprocessor_.InConditional()) { if (nextLine_ < limit_ && IsPreprocessorDirectiveLine(nextLine_)) { @@ -975,17 +975,22 @@ void Prescanner::QuotedCharacterLiteral( } else { isEscaped = false; } - EmitQuotedChar(static_cast(*at_), emit, insert, false, - Encoding::LATIN_1); - while (PadOutCharacterLiteral(tokens)) { - } if (*at_ == '\n') { - if (!inPreprocessorDirective_) { + if (inPreprocessorDirective_) { + EmitQuotedChar(static_cast(*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), "Incomplete character literal"_err_en_US); } break; } + EmitQuotedChar(static_cast(*at_), emit, insert, false, + Encoding::LATIN_1); + while (PadOutCharacterLiteral(tokens)) { + } // 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 // the next continuation line is the name of a keyword macro, replace @@ -1314,23 +1319,30 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) { } tabInCurrentLine_ = false; 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 (!IsFixedFormCommentChar(col1)) { - return nullptr; - } else if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') { - // !$ OpenMP conditional compilation - if (preprocessingOnly_) { - // in -E mode, don't treat "!$ &" as a continuation - return nullptr; - } else if (nextLine_[1] == '$') { - // accept but do not require a matching sentinel - if (!(nextLine_[2] == '&' || IsSpaceOrTab(&nextLine_[2]))) { - return nullptr; + if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') { + if (IsFixedFormCommentChar(col1)) { + if (nextLine_[1] == '$' && + (nextLine_[2] == '&' || IsSpaceOrTab(&nextLine_[2]))) { + // Next line is also !$ conditional compilation, might be continuation + if (preprocessingOnly_) { + return nullptr; + } + } else { + return nullptr; // comment, or distinct directive } - } else { - return nullptr; // distinct directive + } else if (!canBeNonDirectiveContinuation) { + 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}; for (; j < 5; ++j) { char ch{directiveSentinel_[j - 1]}; @@ -1355,6 +1367,22 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) { } } else { // 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 == '&' && features_.IsEnabled( LanguageFeature::FixedFormContinuationWithColumn1Ampersand)) { @@ -1370,15 +1398,11 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) { tabInCurrentLine_ = true; return nextLine_ + 2; // VAX extension } - if ((col1 == ' ' || - ((col1 == 'D' || col1 == 'd') && - features_.IsEnabled(LanguageFeature::OldDebugLines))) && - nextLine_[1] == ' ' && nextLine_[2] == ' ' && nextLine_[3] == ' ' && - nextLine_[4] == ' ') { + if (canBeNonDirectiveContinuation) { const char *col6{nextLine_ + 5}; if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) { if ((*col6 == 'i' || *col6 == 'I') && IsIncludeLine(nextLine_)) { - // It's An INCLUDE line, not a continuation + // It's an INCLUDE line, not a continuation } else { return nextLine_ + 6; } diff --git a/flang/test/Parser/continuation-in-conditional-compilation.f b/flang/test/Parser/continuation-in-conditional-compilation.f index 35525b4fda582..57b69de657348 100644 --- a/flang/test/Parser/continuation-in-conditional-compilation.f +++ b/flang/test/Parser/continuation-in-conditional-compilation.f @@ -5,6 +5,12 @@ program main k01=1+ !$ & 1 +! CHECK: !$ k02=23 +! CHECK: !$ &4 +!$ k02=2 + +3 +!$ +4 + ! CHECK: !$omp parallel private(k01) !$omp parallel !$omp+ private(k01) diff --git a/flang/test/Parser/unmatched-parens.f90 b/flang/test/Parser/unmatched-parens.f90 index c0a3e843f4f72..ad8c37cf60af4 100644 --- a/flang/test/Parser/unmatched-parens.f90 +++ b/flang/test/Parser/unmatched-parens.f90 @@ -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 ! CHECK: Unmatched '(' if (i != 0) then diff --git a/flang/test/Preprocessing/implicit-contin3.F90 b/flang/test/Preprocessing/implicit-contin3.F90 index 8c1829d55eee7..4c31d076aa681 100644 --- a/flang/test/Preprocessing/implicit-contin3.F90 +++ b/flang/test/Preprocessing/implicit-contin3.F90 @@ -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 #define flm(x) x call notamacro(3