[flang-commits] [flang] [flang] Accept a compiler directive sentinel after a semicolon (PR #96966)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Thu Jun 27 13:55:37 PDT 2024
https://github.com/klausler created https://github.com/llvm/llvm-project/pull/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.
>From 60af0eac53e13ac60d2de5cfe79805dec4e3f45f Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Thu, 27 Jun 2024 13:52:40 -0700
Subject: [PATCH] [flang] Accept a compiler directive sentinel after a
semicolon
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.
---
flang/lib/Parser/prescan.cpp | 54 ++++++++++---------
flang/lib/Parser/prescan.h | 3 ++
flang/lib/Parser/token-sequence.cpp | 11 ++--
.../Preprocessing/sentinel-after-semi.F90 | 7 +++
4 files changed, 42 insertions(+), 33 deletions(-)
create mode 100644 flang/test/Preprocessing/sentinel-after-semi.F90
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 42aa829e0ed5b..d44bdde70f380 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -471,7 +471,7 @@ bool Prescanner::MustSkipToEndOfLine() const {
if (inFixedForm_ && column_ > fixedFormColumnLimit_ && !tabInCurrentLine_) {
return true; // skip over ignored columns in right margin (73:80)
} else if (*at_ == '!' && !inCharLiteral_) {
- return true; // inline comment goes to end of source line
+ return !IsCompilerDirectiveSentinel(at_);
} else {
return false;
}
@@ -1345,32 +1345,12 @@ Prescanner::IsFixedFormCompilerDirectiveLine(const char *start) const {
std::optional<Prescanner::LineClassification>
Prescanner::IsFreeFormCompilerDirectiveLine(const char *start) const {
- char sentinel[8];
- const char *p{SkipWhiteSpace(start)};
- if (*p++ != '!') {
- return std::nullopt;
- }
- for (std::size_t j{0}; j + 1 < sizeof sentinel; ++p, ++j) {
- if (*p == '\n') {
- break;
- }
- if (*p == ' ' || *p == '\t' || *p == '&') {
- if (j == 0) {
- break;
- }
- sentinel[j] = '\0';
- p = SkipWhiteSpace(p + 1);
- if (*p == '!') {
- break;
- }
- if (const char *sp{IsCompilerDirectiveSentinel(sentinel, j)}) {
- std::size_t offset = p - start;
- return {LineClassification{
- LineClassification::Kind::CompilerDirective, offset, sp}};
- }
- break;
+ if (const char *p{SkipWhiteSpace(start)}; p && *p++ == '!') {
+ if (auto maybePair{IsCompilerDirectiveSentinel(p)}) {
+ auto offset{static_cast<std::size_t>(maybePair->second - start)};
+ return {LineClassification{LineClassification::Kind::CompilerDirective,
+ offset, maybePair->first}};
}
- sentinel[j] = ToLowerCaseLetter(*p);
}
return std::nullopt;
}
@@ -1415,6 +1395,28 @@ const char *Prescanner::IsCompilerDirectiveSentinel(CharBlock token) const {
return end > p && IsCompilerDirectiveSentinel(p, end - p) ? p : nullptr;
}
+std::optional<std::pair<const char *, const char *>>
+Prescanner::IsCompilerDirectiveSentinel(const char *p) const {
+ char sentinel[8];
+ for (std::size_t j{0}; j + 1 < sizeof sentinel && *p != '\n'; ++p, ++j) {
+ if (*p == ' ' || *p == '\t' || *p == '&') {
+ if (j > 0) {
+ sentinel[j] = '\0';
+ p = SkipWhiteSpace(p + 1);
+ if (*p != '!') {
+ if (const char *sp{IsCompilerDirectiveSentinel(sentinel, j)}) {
+ return std::make_pair(sp, p);
+ }
+ }
+ }
+ break;
+ } else {
+ sentinel[j] = ToLowerCaseLetter(*p);
+ }
+ }
+ return std::nullopt;
+}
+
constexpr bool IsDirective(const char *match, const char *dir) {
for (; *match; ++match) {
if (*match != ToLowerCaseLetter(*dir++)) {
diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h
index 421ba97d324c9..a64df5377e7e0 100644
--- a/flang/lib/Parser/prescan.h
+++ b/flang/lib/Parser/prescan.h
@@ -74,6 +74,9 @@ class Prescanner {
const char *IsCompilerDirectiveSentinel(const char *, std::size_t) const;
const char *IsCompilerDirectiveSentinel(CharBlock) const;
+ // 'first' is the sentinel, 'second' is beginning of payload
+ std::optional<std::pair<const char *, const char *>>
+ IsCompilerDirectiveSentinel(const char *p) const;
template <typename... A> Message &Say(A &&...a) {
return messages_.Say(std::forward<A>(a)...);
diff --git a/flang/lib/Parser/token-sequence.cpp b/flang/lib/Parser/token-sequence.cpp
index 133e60ba4f009..394ac79ea3283 100644
--- a/flang/lib/Parser/token-sequence.cpp
+++ b/flang/lib/Parser/token-sequence.cpp
@@ -266,7 +266,7 @@ TokenSequence &TokenSequence::ClipComment(
if (std::size_t blanks{tok.CountLeadingBlanks()};
blanks < tok.size() && tok[blanks] == '!') {
// Retain active compiler directive sentinels (e.g. "!dir$")
- for (std::size_t k{j + 1}; k < tokens && tok.size() < blanks + 5; ++k) {
+ for (std::size_t k{j + 1}; k < tokens && tok.size() <= blanks + 5; ++k) {
if (tok.begin() + tok.size() == TokenAt(k).begin()) {
tok.ExtendToCover(TokenAt(k));
} else {
@@ -274,12 +274,9 @@ TokenSequence &TokenSequence::ClipComment(
}
}
bool isSentinel{false};
- if (tok.size() == blanks + 5) {
- char sentinel[4];
- for (int k{0}; k < 4; ++k) {
- sentinel[k] = ToLowerCaseLetter(tok[blanks + k + 1]);
- }
- isSentinel = prescanner.IsCompilerDirectiveSentinel(sentinel, 4);
+ if (tok.size() >= blanks + 5) {
+ isSentinel = prescanner.IsCompilerDirectiveSentinel(&tok[blanks + 1])
+ .has_value();
}
if (isSentinel) {
} else if (skipFirst) {
diff --git a/flang/test/Preprocessing/sentinel-after-semi.F90 b/flang/test/Preprocessing/sentinel-after-semi.F90
new file mode 100644
index 0000000000000..75060ac1db032
--- /dev/null
+++ b/flang/test/Preprocessing/sentinel-after-semi.F90
@@ -0,0 +1,7 @@
+! RUN: %flang_fc1 -fdebug-unparse -fopenacc %s 2>&1 | FileCheck %s
+! CHECK: !$ACC DECLARE COPYIN(var)
+#define ACCDECLARE(var) integer :: var; \
+ !$acc declare copyin(var)
+program main
+ ACCDECLARE(var)
+end program
More information about the flang-commits
mailing list