Skip to content

Commit 8e93ac7

Browse files
authored
Revert "[flang] Recognize compiler directives after expansion in comm… (llvm#180982)
…ent (llvm#180062)" This reverts commit 0d64801. Lines like "!MACRO ... &" in which MACRO expands to a compiler directive are now failing because they are not being recognized as having line continuations. Will fix and try again.
1 parent 601364f commit 8e93ac7

File tree

5 files changed

+82
-149
lines changed

5 files changed

+82
-149
lines changed

flang/include/flang/Parser/preprocessor.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ class Definition {
4949

5050
bool set_isDisabled(bool disable);
5151

52-
TokenSequence Apply(const std::vector<TokenSequence> &args,
53-
const Prescanner &, bool inIfExpression = false) const;
52+
TokenSequence Apply(const std::vector<TokenSequence> &args, Prescanner &,
53+
bool inIfExpression = false);
5454

5555
void Print(llvm::raw_ostream &out, const char *macroName = "") const;
5656

@@ -95,7 +95,7 @@ class Preprocessor {
9595
// that result and try again. All other Fortran preprocessors share this
9696
// behavior.
9797
std::optional<TokenSequence> MacroReplacement(const TokenSequence &,
98-
const Prescanner &,
98+
Prescanner &,
9999
std::optional<std::size_t> *partialFunctionLikeMacro = nullptr,
100100
bool inIfExpression = false);
101101

@@ -109,7 +109,7 @@ class Preprocessor {
109109
enum class CanDeadElseAppear { No, Yes };
110110

111111
CharBlock SaveTokenAsName(const CharBlock &);
112-
TokenSequence ReplaceMacros(const TokenSequence &, const Prescanner &,
112+
TokenSequence ReplaceMacros(const TokenSequence &, Prescanner &,
113113
std::optional<std::size_t> *partialFunctionLikeMacro = nullptr,
114114
bool inIfExpression = false);
115115
void SkipDisabledConditionalCode(

flang/lib/Parser/preprocessor.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ constexpr bool IsDefinedKeyword(CharBlock token) {
214214
}
215215

216216
TokenSequence Definition::Apply(const std::vector<TokenSequence> &args,
217-
const Prescanner &prescanner, bool inIfExpression) const {
217+
Prescanner &prescanner, bool inIfExpression) {
218218
TokenSequence result;
219219
bool skipping{false};
220220
int parenthesesNesting{0};
@@ -254,9 +254,7 @@ TokenSequence Definition::Apply(const std::vector<TokenSequence> &args,
254254
CHECK(resultSize > 0 &&
255255
result.TokenAt(resultSize - 1) == replacement_.TokenAt(prev - 1));
256256
result.pop_back();
257-
AllSources &allSources{
258-
*const_cast<AllSources *>(&prescanner.allSources())};
259-
result.CopyAll(Stringify(args[index], allSources));
257+
result.CopyAll(Stringify(args[index], prescanner.allSources()));
260258
} else {
261259
const TokenSequence *arg{&args[index]};
262260
std::optional<TokenSequence> replaced;
@@ -269,9 +267,7 @@ TokenSequence Definition::Apply(const std::vector<TokenSequence> &args,
269267
auto next{replacement_.SkipBlanks(j + 1)};
270268
if (next >= tokens || !IsTokenPasting(replacement_.TokenAt(next))) {
271269
// Apply macro replacement to the actual argument
272-
Preprocessor &preprocessor{
273-
*const_cast<Preprocessor *>(&prescanner.preprocessor())};
274-
replaced = preprocessor.MacroReplacement(
270+
replaced = prescanner.preprocessor().MacroReplacement(
275271
*arg, prescanner, nullptr, inIfExpression);
276272
if (replaced) {
277273
arg = &*replaced;
@@ -282,9 +278,9 @@ TokenSequence Definition::Apply(const std::vector<TokenSequence> &args,
282278
}
283279
} else if (bytes == 11 && isVariadic_ &&
284280
token.ToString() == "__VA_ARGS__") {
285-
AllSources &allSources{
286-
*const_cast<AllSources *>(&prescanner.allSources())};
287-
Provenance commaProvenance{allSources.CompilerInsertionProvenance(',')};
281+
Provenance commaProvenance{
282+
prescanner.preprocessor().allSources().CompilerInsertionProvenance(
283+
',')};
288284
for (std::size_t k{argumentCount()}; k < args.size(); ++k) {
289285
if (k > argumentCount()) {
290286
result.Put(","s, commaProvenance);
@@ -444,7 +440,7 @@ void Preprocessor::Define(const std::string &macro, const std::string &value) {
444440
void Preprocessor::Undefine(std::string macro) { definitions_.erase(macro); }
445441

446442
std::optional<TokenSequence> Preprocessor::MacroReplacement(
447-
const TokenSequence &input, const Prescanner &prescanner,
443+
const TokenSequence &input, Prescanner &prescanner,
448444
std::optional<std::size_t> *partialFunctionLikeMacro, bool inIfExpression) {
449445
// Do quick scan for any use of a defined name.
450446
if (!inIfExpression && definitions_.empty()) {
@@ -667,7 +663,7 @@ std::optional<TokenSequence> Preprocessor::MacroReplacement(
667663
}
668664

669665
TokenSequence Preprocessor::ReplaceMacros(const TokenSequence &tokens,
670-
const Prescanner &prescanner,
666+
Prescanner &prescanner,
671667
std::optional<std::size_t> *partialFunctionLikeMacro, bool inIfExpression) {
672668
if (std::optional<TokenSequence> repl{MacroReplacement(
673669
tokens, prescanner, partialFunctionLikeMacro, inIfExpression)}) {

flang/lib/Parser/prescan.cpp

Lines changed: 67 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -212,14 +212,6 @@ void Prescanner::Statement() {
212212
}
213213
break;
214214
}
215-
case LineClassification::Kind::CompilerDirectiveAfterMacroExpansion:
216-
BeginStatementAndAdvance();
217-
SkipSpaces();
218-
if (*at_ == '!') {
219-
tokens.Put(at_++, 1, GetCurrentProvenance());
220-
++column_;
221-
}
222-
break;
223215
case LineClassification::Kind::Source: {
224216
BeginStatementAndAdvance();
225217
bool checkLabelField{false};
@@ -246,17 +238,30 @@ void Prescanner::Statement() {
246238
// a comment marker or directive sentinel. If so, disable line
247239
// continuation, so that NextToken() won't consume anything from
248240
// following lines.
249-
if (auto kwName{GetKeywordMacroName(at_)}) {
250-
checkLabelField = false;
251-
Provenance here{GetCurrentProvenance()};
252-
TokenSequence replacement{ExpandKeywordMacro(*kwName, here)};
253-
auto newLineClass{ClassifyLine(replacement, here)};
254-
if (newLineClass.kind == LineClassification::Kind::CompilerDirective) {
255-
directiveSentinel_ = newLineClass.sentinel;
256-
disableSourceContinuation_ = false;
257-
} else {
258-
disableSourceContinuation_ = !replacement.empty() &&
259-
newLineClass.kind != LineClassification::Kind::Source;
241+
if (IsLegalIdentifierStart(*at_)) {
242+
// TODO: Only bother with these cases when any keyword macro has
243+
// been defined with replacement text that could begin a comment
244+
// or directive sentinel.
245+
const char *p{at_};
246+
while (IsLegalInIdentifier(*++p)) {
247+
}
248+
CharBlock id{at_, static_cast<std::size_t>(p - at_)};
249+
if (preprocessor_.IsNameDefined(id) &&
250+
!preprocessor_.IsFunctionLikeDefinition(id)) {
251+
checkLabelField = false;
252+
TokenSequence toks;
253+
toks.Put(id, GetProvenance(at_));
254+
if (auto replaced{preprocessor_.MacroReplacement(toks, *this)}) {
255+
auto newLineClass{ClassifyLine(*replaced, GetCurrentProvenance())};
256+
if (newLineClass.kind ==
257+
LineClassification::Kind::CompilerDirective) {
258+
directiveSentinel_ = newLineClass.sentinel;
259+
disableSourceContinuation_ = false;
260+
} else {
261+
disableSourceContinuation_ = !replaced->empty() &&
262+
newLineClass.kind != LineClassification::Kind::Source;
263+
}
264+
}
260265
}
261266
}
262267
if (checkLabelField) {
@@ -299,7 +304,6 @@ void Prescanner::Statement() {
299304
CheckAndEmitLine(preprocessed->ToLowerCase(), newlineProvenance);
300305
break;
301306
case LineClassification::Kind::CompilerDirective:
302-
case LineClassification::Kind::CompilerDirectiveAfterMacroExpansion:
303307
if (preprocessed->HasRedundantBlanks()) {
304308
preprocessed->RemoveRedundantBlanks();
305309
}
@@ -331,39 +335,40 @@ void Prescanner::Statement() {
331335
preprocessed->ToLowerCase().ClipComment(*this), newlineProvenance);
332336
break;
333337
}
334-
} else if (line.kind == LineClassification::Kind::CompilerDirective) {
335-
while (CompilerDirectiveContinuation(tokens, line.sentinel)) {
336-
newlineProvenance = GetCurrentProvenance();
337-
}
338-
if (preprocessingOnly_ && inFixedForm_ && InConditionalLine() &&
339-
nextLine_ < limit_) {
340-
// In -E mode, when the line after !$ conditional compilation is a
341-
// regular fixed form continuation line, append a '&' to the line.
342-
const char *p{nextLine_};
343-
int col{1};
344-
while (int n{IsSpace(p)}) {
345-
if (*p == '\t') {
346-
break;
338+
} else { // no macro replacement
339+
if (line.kind == LineClassification::Kind::CompilerDirective) {
340+
while (CompilerDirectiveContinuation(tokens, line.sentinel)) {
341+
newlineProvenance = GetCurrentProvenance();
342+
}
343+
if (preprocessingOnly_ && inFixedForm_ && InConditionalLine() &&
344+
nextLine_ < limit_) {
345+
// In -E mode, when the line after !$ conditional compilation is a
346+
// regular fixed form continuation line, append a '&' to the line.
347+
const char *p{nextLine_};
348+
int col{1};
349+
while (int n{IsSpace(p)}) {
350+
if (*p == '\t') {
351+
break;
352+
}
353+
p += n;
354+
++col;
355+
}
356+
if (col == 6 && *p != '0' && *p != '\t' && *p != '\n') {
357+
EmitChar(tokens, '&');
358+
tokens.CloseToken();
347359
}
348-
p += n;
349-
++col;
350360
}
351-
if (col == 6 && *p != '0' && *p != '\t' && *p != '\n') {
352-
EmitChar(tokens, '&');
353-
tokens.CloseToken();
361+
tokens.ToLowerCase();
362+
if (!SourceFormChange(tokens.ToString())) {
363+
CheckAndEmitLine(tokens, newlineProvenance);
364+
}
365+
} else { // Kind::Source
366+
tokens.ToLowerCase();
367+
if (inFixedForm_) {
368+
EnforceStupidEndStatementRules(tokens);
354369
}
355-
}
356-
tokens.ToLowerCase();
357-
if (!SourceFormChange(tokens.ToString())) {
358370
CheckAndEmitLine(tokens, newlineProvenance);
359371
}
360-
} else {
361-
CHECK(line.kind == LineClassification::Kind::Source);
362-
tokens.ToLowerCase();
363-
if (inFixedForm_) {
364-
EnforceStupidEndStatementRules(tokens);
365-
}
366-
CheckAndEmitLine(tokens, newlineProvenance);
367372
}
368373
directiveSentinel_ = nullptr;
369374
}
@@ -562,8 +567,7 @@ bool Prescanner::MustSkipToEndOfLine() const {
562567
return true; // skip over ignored columns in right margin (73:80)
563568
} else if (*at_ == '!' && !inCharLiteral_ &&
564569
(!inFixedForm_ || tabInCurrentLine_ || column_ != 6)) {
565-
return InCompilerDirective() ||
566-
!IsCompilerDirectiveSentinelAfterKeywordMacro(at_ + 1);
570+
return InCompilerDirective() || !IsCompilerDirectiveSentinel(at_ + 1);
567571
} else {
568572
return false;
569573
}
@@ -1612,9 +1616,6 @@ Prescanner::IsFixedFormCompilerDirectiveLine(const char *start) const {
16121616
if (!IsFixedFormCommentChar(col1)) {
16131617
return std::nullopt;
16141618
}
1615-
// TODO: Handle keyword macros that expand to directives in fixed form.
1616-
// The comment character can't be 'c' or 'C'. Need to figure out whether
1617-
// fixed form continuation should apply to the expansions.
16181619
char sentinel[5], *sp{sentinel};
16191620
int column{2};
16201621
for (; column < 6; ++column) {
@@ -1677,28 +1678,20 @@ Prescanner::IsFixedFormCompilerDirectiveLine(const char *start) const {
16771678
std::optional<Prescanner::LineClassification>
16781679
Prescanner::IsFreeFormCompilerDirectiveLine(const char *start) const {
16791680
if (const char *p{SkipWhiteSpaceIncludingEmptyMacros(start)};
1680-
p && *p == '!') {
1681-
if (auto lnClass{IsCompilerDirectiveSentinelAfterKeywordMacro(p + 1)}) {
1682-
if (lnClass->kind == LineClassification::Kind::CompilerDirective) {
1683-
const char *sentinel{lnClass->sentinel};
1684-
CHECK(sentinel != nullptr);
1685-
const char *payload{nullptr};
1686-
if (sentinel[0] == '$' && sentinel[1] == '\0') {
1687-
payload = p + 2; // !$
1688-
} else if (sentinel[1] == '@') {
1689-
payload = p + 5; // !@acc or !@cuf
1690-
}
1691-
if (payload) {
1692-
if (const char *comment{IsFreeFormComment(payload)}) {
1693-
if (*comment == '!') { // !$ !blah or !@acc !blah
1694-
// Conditional line comment - treat as comment
1695-
return std::nullopt;
1696-
}
1681+
p && *p++ == '!') {
1682+
if (auto maybePair{IsCompilerDirectiveSentinel(p)}) {
1683+
auto offset{static_cast<std::size_t>(p - start - 1)};
1684+
const char *sentinel{maybePair->first};
1685+
if ((sentinel[0] == '$' && sentinel[1] == '\0') || sentinel[1] == '@') {
1686+
if (const char *comment{IsFreeFormComment(maybePair->second)}) {
1687+
if (*comment == '!') {
1688+
// Conditional line comment - treat as comment
1689+
return std::nullopt;
16971690
}
16981691
}
1699-
lnClass->payloadOffset = static_cast<std::size_t>(p - start);
17001692
}
1701-
return lnClass;
1693+
return {LineClassification{
1694+
LineClassification::Kind::CompilerDirective, offset, sentinel}};
17021695
}
17031696
}
17041697
return std::nullopt;
@@ -1715,31 +1708,6 @@ Prescanner &Prescanner::AddCompilerDirectiveSentinel(const std::string &dir) {
17151708
return *this;
17161709
}
17171710

1718-
std::optional<CharBlock> Prescanner::GetKeywordMacroName(
1719-
const char *start) const {
1720-
if (IsLegalIdentifierStart(*start)) {
1721-
// TODO: Only bother with these cases when any keyword macro has
1722-
// been defined with replacement text that could begin a comment
1723-
// or directive sentinel.
1724-
const char *p{start};
1725-
while (IsLegalInIdentifier(*++p)) {
1726-
}
1727-
CharBlock name{start, static_cast<std::size_t>(p - start)};
1728-
if (preprocessor_.IsNameDefined(name) &&
1729-
!preprocessor_.IsFunctionLikeDefinition(name)) {
1730-
return name;
1731-
}
1732-
}
1733-
return std::nullopt;
1734-
}
1735-
1736-
TokenSequence Prescanner::ExpandKeywordMacro(
1737-
CharBlock name, Provenance provenance) const {
1738-
TokenSequence toks;
1739-
toks.Put(name, provenance);
1740-
return preprocessor_.MacroReplacement(toks, *this).value();
1741-
}
1742-
17431711
const char *Prescanner::IsCompilerDirectiveSentinel(
17441712
const char *sentinel, std::size_t len) const {
17451713
std::uint64_t packed{0};
@@ -1797,26 +1765,8 @@ Prescanner::IsCompilerDirectiveSentinel(const char *p) const {
17971765
return std::nullopt;
17981766
}
17991767

1800-
auto Prescanner::IsCompilerDirectiveSentinelAfterKeywordMacro(
1801-
const char *p) const -> std::optional<LineClassification> {
1802-
if (auto name{GetKeywordMacroName(p)}) {
1803-
Provenance provenance{GetProvenance(p)};
1804-
TokenSequence expansion{ExpandKeywordMacro(*name, provenance)};
1805-
expansion.Put("\n", 1, provenance); // termination
1806-
CharBlock block{expansion.ToLowerCase().ToCharBlock()};
1807-
if (auto maybePair{IsCompilerDirectiveSentinel(block.begin())}) {
1808-
return LineClassification{
1809-
LineClassification::Kind::CompilerDirectiveAfterMacroExpansion,
1810-
name->size(), maybePair->first};
1811-
}
1812-
} else if (auto maybePair{IsCompilerDirectiveSentinel(p)}) {
1813-
return LineClassification{LineClassification::Kind::CompilerDirective,
1814-
static_cast<std::size_t>(maybePair->second - p), maybePair->first};
1815-
}
1816-
return std::nullopt;
1817-
}
1818-
1819-
auto Prescanner::ClassifyLine(const char *start) const -> LineClassification {
1768+
Prescanner::LineClassification Prescanner::ClassifyLine(
1769+
const char *start) const {
18201770
if (inFixedForm_) {
18211771
if (std::optional<LineClassification> lc{
18221772
IsFixedFormCompilerDirectiveLine(start)}) {

flang/lib/Parser/prescan.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,6 @@ class Prescanner {
8181
TokenSequence TokenizePreprocessorDirective();
8282
Provenance GetCurrentProvenance() const { return GetProvenance(at_); }
8383

84-
std::optional<CharBlock> GetKeywordMacroName(const char *) const;
85-
TokenSequence ExpandKeywordMacro(CharBlock, Provenance) const;
86-
8784
const char *IsCompilerDirectiveSentinel(const char *, std::size_t) const;
8885
const char *IsCompilerDirectiveSentinel(CharBlock) const;
8986
// 'first' is the sentinel, 'second' is beginning of payload
@@ -112,7 +109,6 @@ class Prescanner {
112109
PreprocessorDirective,
113110
IncludeLine, // Fortran INCLUDE
114111
CompilerDirective,
115-
CompilerDirectiveAfterMacroExpansion, // !MACRO -> !$OMP ...
116112
Source
117113
};
118114
LineClassification(Kind k, std::size_t po = 0, const char *s = nullptr)
@@ -160,7 +156,7 @@ class Prescanner {
160156
}
161157

162158
void EmitInsertedChar(TokenSequence &tokens, char ch) {
163-
Provenance provenance{allSources().CompilerInsertionProvenance(ch)};
159+
Provenance provenance{allSources_.CompilerInsertionProvenance(ch)};
164160
tokens.PutNextTokenChar(ch, provenance);
165161
}
166162

@@ -244,8 +240,6 @@ class Prescanner {
244240
bool SourceFormChange(std::string &&);
245241
bool CompilerDirectiveContinuation(TokenSequence &, const char *sentinel);
246242
bool SourceLineContinuation(TokenSequence &);
247-
std::optional<LineClassification>
248-
IsCompilerDirectiveSentinelAfterKeywordMacro(const char *p) const;
249243

250244
Messages &messages_;
251245
CookedSource &cooked_;
@@ -304,9 +298,9 @@ class Prescanner {
304298
const std::size_t firstCookedCharacterOffset_{cooked_.BufferedBytes()};
305299

306300
const Provenance spaceProvenance_{
307-
allSources().CompilerInsertionProvenance(' ')};
301+
allSources_.CompilerInsertionProvenance(' ')};
308302
const Provenance backslashProvenance_{
309-
allSources().CompilerInsertionProvenance('\\')};
303+
allSources_.CompilerInsertionProvenance('\\')};
310304

311305
// To avoid probing the set of active compiler directive sentinel strings
312306
// on every comment line, they're checked first with a cheap Bloom filter.

0 commit comments

Comments
 (0)