Skip to content

Commit ea3a3b2

Browse files
authored
[flang] Handle continuation line edge case (#74751)
For a character literal that is split over more than one source line with free form line continuation using '&' at the end of one line but missing the standard-required '&' on the continuation line, also handle the case of spaces at the beginning of the continuation line. For example, PRINT *, 'don'& 't poke the bear' now prints "don't poke the bear", like nearly all other Fortran compilers do. This is not strictly standard conforming behavior, and the compiler emits a portability warning with -pedantic. Fixes llvm-test-suite/Fortran/gfortran/regression/continuation_1.f90, .../continuation_12.f90, and .../continuation_13.f90.
1 parent 353d56d commit ea3a3b2

File tree

4 files changed

+25
-19
lines changed

4 files changed

+25
-19
lines changed

flang/lib/Parser/prescan.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ void Prescanner::QuotedCharacterLiteral(
706706
char quote{*at_};
707707
const char *end{at_ + 1};
708708
inCharLiteral_ = true;
709+
continuationInCharLiteral_ = true;
709710
const auto emit{[&](char ch) { EmitChar(tokens, ch); }};
710711
const auto insert{[&](char ch) { EmitInsertedChar(tokens, ch); }};
711712
bool isEscaped{false};
@@ -749,16 +750,9 @@ void Prescanner::QuotedCharacterLiteral(
749750
break;
750751
}
751752
inCharLiteral_ = true;
752-
if (insertASpace_) {
753-
if (features_.ShouldWarn(
754-
common::LanguageFeature::MiscSourceExtensions)) {
755-
Say(GetProvenanceRange(at_, end),
756-
"Repeated quote mark in character literal continuation line should have been preceded by '&'"_port_en_US);
757-
}
758-
insertASpace_ = false;
759-
}
760753
}
761754
}
755+
continuationInCharLiteral_ = false;
762756
inCharLiteral_ = false;
763757
}
764758

@@ -1122,7 +1116,15 @@ const char *Prescanner::FreeFormContinuationLine(bool ampersand) {
11221116
} else if (*p == '!' || *p == '\n' || *p == '#') {
11231117
return nullptr;
11241118
} else if (ampersand || IsImplicitContinuation()) {
1125-
if (p > nextLine_) {
1119+
if (continuationInCharLiteral_) {
1120+
// 'a'& -> 'a''b' == "a'b"
1121+
// 'b'
1122+
if (features_.ShouldWarn(
1123+
common::LanguageFeature::MiscSourceExtensions)) {
1124+
Say(GetProvenanceRange(p, p + 1),
1125+
"Character literal continuation line should have been preceded by '&'"_port_en_US);
1126+
}
1127+
} else if (p > nextLine_) {
11261128
--p;
11271129
} else {
11281130
insertASpace_ = true;

flang/lib/Parser/prescan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ class Prescanner {
218218
bool slashInCurrentStatement_{false};
219219
bool preventHollerith_{false}; // CHARACTER*4HIMOM not Hollerith
220220
bool inCharLiteral_{false};
221+
bool continuationInCharLiteral_{false};
221222
bool inPreprocessorDirective_{false};
222223

223224
// In some edge cases of compiler directive continuation lines, it

flang/test/Parser/continuation-before-quote.f90

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
! RUN: %flang_fc1 -fsyntax-only -pedantic %s 2>&1 | FileCheck %s
2+
! Continuation between repeated quotation marks
3+
subroutine test
4+
!CHECK: portability: Character literal continuation line should have been preceded by '&'
5+
print *, 'needs an '&
6+
'ampersand'''
7+
!CHECK: portability: Character literal continuation line should have been preceded by '&'
8+
print *, 'also needs an '&
9+
'ampersand'''
10+
!CHECK-NOT: portability: Character literal continuation line should have been preceded by '&'
11+
print *, 'has an '&
12+
&'ampersand'''
13+
end

0 commit comments

Comments
 (0)