Skip to content

Commit c189852

Browse files
authored
[flang] Ignore empty keyword macros before directives (#130333)
Ignore any keyword macros with empty directives that might appear before a compiler directive. Fixes #126459.
1 parent 8227f2a commit c189852

File tree

5 files changed

+48
-9
lines changed

5 files changed

+48
-9
lines changed

flang/include/flang/Parser/preprocessor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class Preprocessor {
8181
void Define(const std::string &macro, const std::string &value);
8282
void Undefine(std::string macro);
8383
bool IsNameDefined(const CharBlock &);
84+
bool IsNameDefinedEmpty(const CharBlock &);
8485
bool IsFunctionLikeDefinition(const CharBlock &);
8586
bool AnyDefinitions() const { return !definitions_.empty(); }
8687
bool InConditional() const { return !ifStack_.empty(); }

flang/lib/Parser/preprocessor.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,15 @@ bool Preprocessor::IsNameDefined(const CharBlock &token) {
842842
return definitions_.find(token) != definitions_.end();
843843
}
844844

845+
bool Preprocessor::IsNameDefinedEmpty(const CharBlock &token) {
846+
if (auto it{definitions_.find(token)}; it != definitions_.end()) {
847+
const Definition &def{it->second};
848+
return !def.isFunctionLike() && def.replacement().SizeInChars() == 0;
849+
} else {
850+
return false;
851+
}
852+
}
853+
845854
bool Preprocessor::IsFunctionLikeDefinition(const CharBlock &token) {
846855
auto it{definitions_.find(token)};
847856
return it != definitions_.end() && it->second.isFunctionLike();

flang/lib/Parser/prescan.cpp

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,8 @@ void Prescanner::Statement() {
145145
if (inFixedForm_) {
146146
CHECK(IsFixedFormCommentChar(*at_));
147147
} else {
148-
while (int n{IsSpaceOrTab(at_)}) {
149-
at_ += n, ++column_;
150-
}
148+
at_ += line.payloadOffset;
149+
column_ += line.payloadOffset;
151150
CHECK(*at_ == '!');
152151
}
153152
std::optional<int> condOffset;
@@ -597,6 +596,30 @@ const char *Prescanner::SkipWhiteSpace(const char *p) {
597596
return p;
598597
}
599598

599+
const char *Prescanner::SkipWhiteSpaceIncludingEmptyMacros(
600+
const char *p) const {
601+
while (true) {
602+
if (int n{IsSpaceOrTab(p)}) {
603+
p += n;
604+
} else if (preprocessor_.AnyDefinitions() && IsLegalIdentifierStart(*p)) {
605+
// Skip keyword macros with empty definitions
606+
const char *q{p + 1};
607+
while (IsLegalInIdentifier(*q)) {
608+
++q;
609+
}
610+
if (preprocessor_.IsNameDefinedEmpty(
611+
CharBlock{p, static_cast<std::size_t>(q - p)})) {
612+
p = q;
613+
} else {
614+
break;
615+
}
616+
} else {
617+
break;
618+
}
619+
}
620+
return p;
621+
}
622+
600623
const char *Prescanner::SkipWhiteSpaceAndCComments(const char *p) const {
601624
while (true) {
602625
if (int n{IsSpaceOrTab(p)}) {
@@ -1463,18 +1486,18 @@ Prescanner::IsFixedFormCompilerDirectiveLine(const char *start) const {
14631486
*sp = '\0';
14641487
if (const char *ss{IsCompilerDirectiveSentinel(
14651488
sentinel, static_cast<std::size_t>(sp - sentinel))}) {
1466-
std::size_t payloadOffset = p - start;
1467-
return {LineClassification{
1468-
LineClassification::Kind::CompilerDirective, payloadOffset, ss}};
1489+
return {
1490+
LineClassification{LineClassification::Kind::CompilerDirective, 0, ss}};
14691491
}
14701492
return std::nullopt;
14711493
}
14721494

14731495
std::optional<Prescanner::LineClassification>
14741496
Prescanner::IsFreeFormCompilerDirectiveLine(const char *start) const {
1475-
if (const char *p{SkipWhiteSpace(start)}; p && *p++ == '!') {
1497+
if (const char *p{SkipWhiteSpaceIncludingEmptyMacros(start)};
1498+
p && *p++ == '!') {
14761499
if (auto maybePair{IsCompilerDirectiveSentinel(p)}) {
1477-
auto offset{static_cast<std::size_t>(maybePair->second - start)};
1500+
auto offset{static_cast<std::size_t>(p - start - 1)};
14781501
return {LineClassification{LineClassification::Kind::CompilerDirective,
14791502
offset, maybePair->first}};
14801503
}
@@ -1529,7 +1552,7 @@ Prescanner::IsCompilerDirectiveSentinel(const char *p) const {
15291552
if (int n{*p == '&' ? 1 : IsSpaceOrTab(p)}) {
15301553
if (j > 0) {
15311554
sentinel[j] = '\0';
1532-
p = SkipWhiteSpace(p + n);
1555+
p = SkipWhiteSpaceIncludingEmptyMacros(p + n);
15331556
if (*p != '!') {
15341557
if (const char *sp{IsCompilerDirectiveSentinel(sentinel, j)}) {
15351558
return std::make_pair(sp, p);

flang/lib/Parser/prescan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ class Prescanner {
182182
void SkipCComments();
183183
void SkipSpaces();
184184
static const char *SkipWhiteSpace(const char *);
185+
const char *SkipWhiteSpaceIncludingEmptyMacros(const char *) const;
185186
const char *SkipWhiteSpaceAndCComments(const char *) const;
186187
const char *SkipCComment(const char *) const;
187188
bool NextToken(TokenSequence &);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
! RUN: %flang -E -fopenmp %s 2>&1 | FileCheck %s
2+
!CHECK: NDIR=0
3+
#define BLANKMACRO
4+
BLANKMACRO !$ NDIR=0
5+
end

0 commit comments

Comments
 (0)