Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 50 additions & 26 deletions flang/lib/Parser/prescan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_)) {
Expand Down Expand Up @@ -975,17 +975,22 @@ void Prescanner::QuotedCharacterLiteral(
} else {
isEscaped = false;
}
EmitQuotedChar(static_cast<unsigned char>(*at_), emit, insert, false,
Encoding::LATIN_1);
while (PadOutCharacterLiteral(tokens)) {
}
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),
"Incomplete character literal"_err_en_US);
}
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
// continuation lines at this point, and the entire significant part of
// the next continuation line is the name of a keyword macro, replace
Expand Down Expand Up @@ -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]};
Expand All @@ -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)) {
Expand All @@ -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;
}
Expand Down
6 changes: 6 additions & 0 deletions flang/test/Parser/continuation-in-conditional-compilation.f
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Parser/unmatched-parens.f90
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Preprocessing/implicit-contin3.F90
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Loading