diff options
author | Peter Klausler <pklausler@nvidia.com> | 2023-05-22 13:56:32 -0700 |
---|---|---|
committer | Peter Klausler <pklausler@nvidia.com> | 2023-05-22 14:43:45 -0700 |
commit | 9efe1581502f1433811ea479345f84ca5008c754 (patch) | |
tree | 8264eeec829106cfd253c98942abf4e945b79d43 /flang/lib/Parser/preprocessor.cpp | |
parent | d54ad0b6cd7c7be24062014367fcd0c3f525c7ec (diff) | |
download | llvm-9efe1581502f1433811ea479345f84ca5008c754.zip llvm-9efe1581502f1433811ea479345f84ca5008c754.tar.gz llvm-9efe1581502f1433811ea479345f84ca5008c754.tar.bz2 |
[flang][preprocessing] Allow keyword macro to rename a function-like macro
#define FOO(x) ((x)+1)
#define BAR FOO
print *, BAR(1)
should work as one would expect.
Fixes https://github.com/llvm/llvm-project/issues/47162.
Differential Revision: https://reviews.llvm.org/D151154
Diffstat (limited to 'flang/lib/Parser/preprocessor.cpp')
-rw-r--r-- | flang/lib/Parser/preprocessor.cpp | 67 |
1 files changed, 44 insertions, 23 deletions
diff --git a/flang/lib/Parser/preprocessor.cpp b/flang/lib/Parser/preprocessor.cpp index 58b54f4..6dea129 100644 --- a/flang/lib/Parser/preprocessor.cpp +++ b/flang/lib/Parser/preprocessor.cpp @@ -273,7 +273,7 @@ std::optional<TokenSequence> Preprocessor::MacroReplacement( } TokenSequence result{input, 0, j}; for (; j < tokens; ++j) { - const CharBlock &token{input.TokenAt(j)}; + CharBlock token{input.TokenAt(j)}; if (token.IsBlank() || !IsLegalIdentifierStart(token[0])) { result.Put(input, j); continue; @@ -283,14 +283,15 @@ std::optional<TokenSequence> Preprocessor::MacroReplacement( result.Put(input, j); continue; } - Definition &def{it->second}; - if (def.isDisabled()) { + Definition *def{&it->second}; + if (def->isDisabled()) { result.Put(input, j); continue; } - if (!def.isFunctionLike()) { - if (def.isPredefined()) { - std::string name{def.replacement().TokenAt(0).ToString()}; + if (!def->isFunctionLike()) { + bool isRenaming{false}; + if (def->isPredefined()) { + std::string name{def->replacement().TokenAt(0).ToString()}; std::string repl; if (name == "__FILE__") { repl = "\""s + @@ -309,18 +310,38 @@ std::optional<TokenSequence> Preprocessor::MacroReplacement( continue; } } - def.set_isDisabled(true); + def->set_isDisabled(true); TokenSequence replaced{ - TokenPasting(ReplaceMacros(def.replacement(), prescanner))}; - def.set_isDisabled(false); - if (!replaced.empty()) { - ProvenanceRange from{def.replacement().GetProvenanceRange()}; - ProvenanceRange use{input.GetTokenProvenanceRange(j)}; - ProvenanceRange newRange{ - allSources_.AddMacroCall(from, use, replaced.ToString())}; - result.Put(replaced, newRange); + TokenPasting(ReplaceMacros(def->replacement(), prescanner))}; + def->set_isDisabled(false); + // Allow a keyword-like macro replacement to be the name of + // a function-like macro, possibly surrounded by blanks. + std::size_t k{0}, repTokens{replaced.SizeInTokens()}; + for (; k < repTokens && replaced.TokenAt(k).IsBlank(); ++k) { + } + if (k < repTokens) { + token = replaced.TokenAt(k); + for (++k; k < repTokens && replaced.TokenAt(k).IsBlank(); ++k) { + } + if (k == repTokens && IsLegalIdentifierStart(token[0])) { + auto it{definitions_.find(token)}; + if (it != definitions_.end() && !it->second.isDisabled() && + it->second.isFunctionLike()) { + def = &it->second; + isRenaming = true; + } + } + } + if (!isRenaming) { + if (!replaced.empty()) { + ProvenanceRange from{def->replacement().GetProvenanceRange()}; + ProvenanceRange use{input.GetTokenProvenanceRange(j)}; + ProvenanceRange newRange{ + allSources_.AddMacroCall(from, use, replaced.ToString())}; + result.Put(replaced, newRange); + } + continue; } - continue; } // Possible function-like macro call. Skip spaces and newlines to see // whether '(' is next. @@ -354,13 +375,13 @@ std::optional<TokenSequence> Preprocessor::MacroReplacement( } } } - if (argStart.size() == 1 && k == argStart[0] && def.argumentCount() == 0) { + if (argStart.size() == 1 && k == argStart[0] && def->argumentCount() == 0) { // Subtle: () is zero arguments, not one empty argument, // unless one argument was expected. argStart.clear(); } - if (k >= tokens || argStart.size() < def.argumentCount() || - (argStart.size() > def.argumentCount() && !def.isVariadic())) { + if (k >= tokens || argStart.size() < def->argumentCount() || + (argStart.size() > def->argumentCount() && !def->isVariadic())) { result.Put(input, j); continue; } @@ -371,12 +392,12 @@ std::optional<TokenSequence> Preprocessor::MacroReplacement( (n + 1 == argStart.size() ? k : argStart[n + 1] - 1) - at}; args.emplace_back(TokenSequence(input, at, count)); } - def.set_isDisabled(true); + def->set_isDisabled(true); TokenSequence replaced{ - ReplaceMacros(def.Apply(args, prescanner), prescanner)}; - def.set_isDisabled(false); + ReplaceMacros(def->Apply(args, prescanner), prescanner)}; + def->set_isDisabled(false); if (!replaced.empty()) { - ProvenanceRange from{def.replacement().GetProvenanceRange()}; + ProvenanceRange from{def->replacement().GetProvenanceRange()}; ProvenanceRange use{input.GetIntervalProvenanceRange(j, k - j)}; ProvenanceRange newRange{ allSources_.AddMacroCall(from, use, replaced.ToString())}; |