Skip to content

Commit 259ce11

Browse files
authored
[flang] Accept a compiler directive sentinel after a semicolon (#96966)
Don't treat !DIR$ or an active !$ACC, !$OMP, &c. as a comment when they appear after a semicolon, but instead treat them as a compiler directive sentinel.
1 parent cddbcd1 commit 259ce11

File tree

4 files changed

+42
-33
lines changed

4 files changed

+42
-33
lines changed

flang/lib/Parser/prescan.cpp

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ bool Prescanner::MustSkipToEndOfLine() const {
471471
if (inFixedForm_ && column_ > fixedFormColumnLimit_ && !tabInCurrentLine_) {
472472
return true; // skip over ignored columns in right margin (73:80)
473473
} else if (*at_ == '!' && !inCharLiteral_) {
474-
return true; // inline comment goes to end of source line
474+
return !IsCompilerDirectiveSentinel(at_);
475475
} else {
476476
return false;
477477
}
@@ -1380,32 +1380,12 @@ Prescanner::IsFixedFormCompilerDirectiveLine(const char *start) const {
13801380

13811381
std::optional<Prescanner::LineClassification>
13821382
Prescanner::IsFreeFormCompilerDirectiveLine(const char *start) const {
1383-
char sentinel[8];
1384-
const char *p{SkipWhiteSpace(start)};
1385-
if (*p++ != '!') {
1386-
return std::nullopt;
1387-
}
1388-
for (std::size_t j{0}; j + 1 < sizeof sentinel; ++p, ++j) {
1389-
if (*p == '\n') {
1390-
break;
1391-
}
1392-
if (*p == ' ' || *p == '\t' || *p == '&') {
1393-
if (j == 0) {
1394-
break;
1395-
}
1396-
sentinel[j] = '\0';
1397-
p = SkipWhiteSpace(p + 1);
1398-
if (*p == '!') {
1399-
break;
1400-
}
1401-
if (const char *sp{IsCompilerDirectiveSentinel(sentinel, j)}) {
1402-
std::size_t offset = p - start;
1403-
return {LineClassification{
1404-
LineClassification::Kind::CompilerDirective, offset, sp}};
1405-
}
1406-
break;
1383+
if (const char *p{SkipWhiteSpace(start)}; p && *p++ == '!') {
1384+
if (auto maybePair{IsCompilerDirectiveSentinel(p)}) {
1385+
auto offset{static_cast<std::size_t>(maybePair->second - start)};
1386+
return {LineClassification{LineClassification::Kind::CompilerDirective,
1387+
offset, maybePair->first}};
14071388
}
1408-
sentinel[j] = ToLowerCaseLetter(*p);
14091389
}
14101390
return std::nullopt;
14111391
}
@@ -1450,6 +1430,28 @@ const char *Prescanner::IsCompilerDirectiveSentinel(CharBlock token) const {
14501430
return end > p && IsCompilerDirectiveSentinel(p, end - p) ? p : nullptr;
14511431
}
14521432

1433+
std::optional<std::pair<const char *, const char *>>
1434+
Prescanner::IsCompilerDirectiveSentinel(const char *p) const {
1435+
char sentinel[8];
1436+
for (std::size_t j{0}; j + 1 < sizeof sentinel && *p != '\n'; ++p, ++j) {
1437+
if (*p == ' ' || *p == '\t' || *p == '&') {
1438+
if (j > 0) {
1439+
sentinel[j] = '\0';
1440+
p = SkipWhiteSpace(p + 1);
1441+
if (*p != '!') {
1442+
if (const char *sp{IsCompilerDirectiveSentinel(sentinel, j)}) {
1443+
return std::make_pair(sp, p);
1444+
}
1445+
}
1446+
}
1447+
break;
1448+
} else {
1449+
sentinel[j] = ToLowerCaseLetter(*p);
1450+
}
1451+
}
1452+
return std::nullopt;
1453+
}
1454+
14531455
constexpr bool IsDirective(const char *match, const char *dir) {
14541456
for (; *match; ++match) {
14551457
if (*match != ToLowerCaseLetter(*dir++)) {

flang/lib/Parser/prescan.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ class Prescanner {
7474

7575
const char *IsCompilerDirectiveSentinel(const char *, std::size_t) const;
7676
const char *IsCompilerDirectiveSentinel(CharBlock) const;
77+
// 'first' is the sentinel, 'second' is beginning of payload
78+
std::optional<std::pair<const char *, const char *>>
79+
IsCompilerDirectiveSentinel(const char *p) const;
7780

7881
template <typename... A> Message &Say(A &&...a) {
7982
return messages_.Say(std::forward<A>(a)...);

flang/lib/Parser/token-sequence.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -266,20 +266,17 @@ TokenSequence &TokenSequence::ClipComment(
266266
if (std::size_t blanks{tok.CountLeadingBlanks()};
267267
blanks < tok.size() && tok[blanks] == '!') {
268268
// Retain active compiler directive sentinels (e.g. "!dir$")
269-
for (std::size_t k{j + 1}; k < tokens && tok.size() < blanks + 5; ++k) {
269+
for (std::size_t k{j + 1}; k < tokens && tok.size() <= blanks + 5; ++k) {
270270
if (tok.begin() + tok.size() == TokenAt(k).begin()) {
271271
tok.ExtendToCover(TokenAt(k));
272272
} else {
273273
break;
274274
}
275275
}
276276
bool isSentinel{false};
277-
if (tok.size() == blanks + 5) {
278-
char sentinel[4];
279-
for (int k{0}; k < 4; ++k) {
280-
sentinel[k] = ToLowerCaseLetter(tok[blanks + k + 1]);
281-
}
282-
isSentinel = prescanner.IsCompilerDirectiveSentinel(sentinel, 4);
277+
if (tok.size() > blanks + 5) {
278+
isSentinel = prescanner.IsCompilerDirectiveSentinel(&tok[blanks + 1])
279+
.has_value();
283280
}
284281
if (isSentinel) {
285282
} else if (skipFirst) {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
! RUN: %flang_fc1 -fdebug-unparse -fopenacc %s 2>&1 | FileCheck %s
2+
! CHECK: !$ACC DECLARE COPYIN(var)
3+
#define ACCDECLARE(var) integer :: var; \
4+
!$acc declare copyin(var)
5+
program main
6+
ACCDECLARE(var)
7+
end program

0 commit comments

Comments
 (0)