Skip to content

Commit ed5ec76

Browse files
committed
[flang][OpenMP] Fix regression in !$ continuation
A recent patch that obviated the need to use -fopenmp when using the compiler to preprocess in -E mode broke a case of Fortran line continuation when using OpenMP conditional compilation lines (!$) when *not* in -E mode. Fix.
1 parent 5942f02 commit ed5ec76

File tree

2 files changed

+90
-34
lines changed

2 files changed

+90
-34
lines changed

flang/lib/Parser/prescan.cpp

Lines changed: 80 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,11 @@ void Prescanner::Statement() {
150150
CHECK(*at_ == '!');
151151
}
152152
std::optional<int> condOffset;
153-
bool isFFOpenMPCondCompilation{false};
154-
if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') {
153+
bool isOpenMPCondCompilation{
154+
directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0'};
155+
if (isOpenMPCondCompilation) {
155156
// OpenMP conditional compilation line.
156157
condOffset = 2;
157-
isFFOpenMPCondCompilation = inFixedForm_;
158158
} else if (directiveSentinel_[0] == '@' && directiveSentinel_[1] == 'c' &&
159159
directiveSentinel_[2] == 'u' && directiveSentinel_[3] == 'f' &&
160160
directiveSentinel_[4] == '\0') {
@@ -166,10 +166,19 @@ void Prescanner::Statement() {
166166
if (auto payload{IsIncludeLine(at_)}) {
167167
FortranInclude(at_ + *payload);
168168
return;
169-
} else if (inFixedForm_) {
170-
LabelField(tokens);
171-
} else {
172-
SkipSpaces();
169+
}
170+
while (true) {
171+
if (auto n{IsSpace(at_)}) {
172+
at_ += n, ++column_;
173+
} else if (*at_ == '\t') {
174+
++at_, ++column_;
175+
tabInCurrentLine_ = true;
176+
} else if (inFixedForm_ && column_ == 6 && !tabInCurrentLine_ &&
177+
*at_ == '0') {
178+
++at_, ++column_;
179+
} else {
180+
break;
181+
}
173182
}
174183
} else {
175184
// Compiler directive. Emit normalized sentinel, squash following spaces.
@@ -183,12 +192,16 @@ void Prescanner::Statement() {
183192
}
184193
if (IsSpaceOrTab(at_)) {
185194
while (int n{IsSpaceOrTab(at_)}) {
186-
if (isFFOpenMPCondCompilation) {
195+
if (isOpenMPCondCompilation && inFixedForm_) {
187196
EmitChar(tokens, ' ');
188197
}
198+
tabInCurrentLine_ |= *at_ == '\t';
189199
at_ += n, ++column_;
200+
if (inFixedForm_ && column_ > fixedFormColumnLimit_) {
201+
break;
202+
}
190203
}
191-
if (isFFOpenMPCondCompilation && column_ == 6) {
204+
if (isOpenMPCondCompilation && inFixedForm_ && column_ == 6) {
192205
if (*at_ == '0') {
193206
EmitChar(tokens, ' ');
194207
} else {
@@ -202,6 +215,11 @@ void Prescanner::Statement() {
202215
}
203216
tokens.CloseToken();
204217
}
218+
if (*at_ == '!' || *at_ == '\n' ||
219+
(inFixedForm_ && column_ > fixedFormColumnLimit_ &&
220+
!tabInCurrentLine_)) {
221+
return; // Directive without payload
222+
}
205223
break;
206224
}
207225
case LineClassification::Kind::Source: {
@@ -1278,17 +1296,28 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
12781296
tabInCurrentLine_ = false;
12791297
char col1{*nextLine_};
12801298
if (InCompilerDirective()) {
1281-
if (preprocessingOnly_ && directiveSentinel_[0] == '$' &&
1282-
directiveSentinel_[1] == '\0') {
1283-
// in -E mode, don't treat "!$ &" as a continuation
1299+
if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') {
1300+
// !$ OpenMP conditional compilation
1301+
if (preprocessingOnly_) {
1302+
// in -E mode, don't treat "!$ &" as a continuation
1303+
return nullptr;
1304+
} else if (IsFixedFormCommentChar(col1)) {
1305+
if (nextLine_[1] == '$') {
1306+
// accept but do not require a matching sentinel
1307+
if (!(nextLine_[2] == '&' || IsSpaceOrTab(&nextLine_[2]))) {
1308+
return nullptr;
1309+
}
1310+
} else {
1311+
return nullptr; // distinct directive
1312+
}
1313+
}
12841314
} else if (IsFixedFormCommentChar(col1)) {
12851315
int j{1};
12861316
for (; j < 5; ++j) {
12871317
char ch{directiveSentinel_[j - 1]};
12881318
if (ch == '\0') {
12891319
break;
1290-
}
1291-
if (ch != ToLowerCaseLetter(nextLine_[j])) {
1320+
} else if (ch != ToLowerCaseLetter(nextLine_[j])) {
12921321
return nullptr;
12931322
}
12941323
}
@@ -1297,13 +1326,15 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
12971326
return nullptr;
12981327
}
12991328
}
1300-
const char *col6{nextLine_ + 5};
1301-
if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
1302-
if (mightNeedSpace && !IsSpace(nextLine_ + 6)) {
1303-
insertASpace_ = true;
1304-
}
1305-
return nextLine_ + 6;
1329+
} else {
1330+
return nullptr;
1331+
}
1332+
const char *col6{nextLine_ + 5};
1333+
if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
1334+
if (mightNeedSpace && !IsSpace(nextLine_ + 6)) {
1335+
insertASpace_ = true;
13061336
}
1337+
return nextLine_ + 6;
13071338
}
13081339
} else {
13091340
// Normal case: not in a compiler directive.
@@ -1351,26 +1382,37 @@ const char *Prescanner::FreeFormContinuationLine(bool ampersand) {
13511382
}
13521383
p = SkipWhiteSpaceIncludingEmptyMacros(p);
13531384
if (InCompilerDirective()) {
1354-
if (preprocessingOnly_ && directiveSentinel_[0] == '$' &&
1355-
directiveSentinel_[1] == '\0') {
1356-
// in -E mode, don't treat !$ as a continuation
1385+
if (directiveSentinel_[0] == '$' && directiveSentinel_[1] == '\0') {
1386+
if (preprocessingOnly_) {
1387+
// in -E mode, don't treat !$ as a continuation
1388+
return nullptr;
1389+
} else if (p[0] == '!' && p[1] == '$') {
1390+
// accept but do not require a matching sentinel
1391+
if (!(p[2] == '&' || IsSpaceOrTab(&p[2]))) {
1392+
return nullptr; // not !$
1393+
}
1394+
p += 2;
1395+
}
13571396
} else if (*p++ == '!') {
13581397
for (const char *s{directiveSentinel_}; *s != '\0'; ++p, ++s) {
13591398
if (*s != ToLowerCaseLetter(*p)) {
13601399
return nullptr; // not the same directive class
13611400
}
13621401
}
1363-
p = SkipWhiteSpace(p);
1364-
if (*p == '&') {
1365-
if (!ampersand) {
1366-
insertASpace_ = true;
1367-
}
1368-
return p + 1;
1369-
} else if (ampersand) {
1370-
return p;
1402+
} else {
1403+
return nullptr;
1404+
}
1405+
p = SkipWhiteSpace(p);
1406+
if (*p == '&') {
1407+
if (!ampersand) {
1408+
insertASpace_ = true;
13711409
}
1410+
return p + 1;
1411+
} else if (ampersand) {
1412+
return p;
1413+
} else {
1414+
return nullptr;
13721415
}
1373-
return nullptr;
13741416
}
13751417
if (p[0] == '!' && p[1] == '$' && !preprocessingOnly_ &&
13761418
features_.IsEnabled(LanguageFeature::OpenMP)) {
@@ -1593,8 +1635,13 @@ Prescanner::IsCompilerDirectiveSentinel(const char *p) const {
15931635
if (int n{IsSpaceOrTab(p)};
15941636
n || !(IsLetter(*p) || *p == '$' || *p == '@')) {
15951637
if (j > 0) {
1638+
if (j == 1 && sentinel[0] == '$' && n == 0 && *p != '&') {
1639+
// OpenMP conditional compilation line sentinels have to
1640+
// be immediately followed by a space or &, not a digit
1641+
// or anything else.
1642+
break;
1643+
}
15961644
sentinel[j] = '\0';
1597-
p = SkipWhiteSpaceIncludingEmptyMacros(p + n);
15981645
if (*p != '!') {
15991646
if (const char *sp{IsCompilerDirectiveSentinel(sentinel, j)}) {
16001647
return std::make_pair(sp, p);

flang/test/Parser/OpenMP/compiler-directive-continuation.f90

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
! CHECK-NO-OMP: i=1010011_4
1616
subroutine mixed_form1()
1717
i = 1 &
18-
!$+100&
18+
!$ +100&
1919
!$&+ 1000&
2020
&+ 10 + 1&
2121
!$& +100000&
@@ -53,3 +53,12 @@ subroutine mixed_form3()
5353
!$ +1000
5454
end subroutine
5555

56+
! CHECK-LABEL: subroutine regression
57+
! CHECK-E:{{^}}!$ real x, &
58+
! CHECK-E:{{^}} stop
59+
! CHECK-OMP: REAL x, stop
60+
! CHECK-NO-OMP-NOT: REAL x,
61+
subroutine regression
62+
!$ real x, &
63+
stop
64+
end

0 commit comments

Comments
 (0)