aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Parser/preprocessor.cpp
diff options
context:
space:
mode:
authorPeter Klausler <pklausler@nvidia.com>2023-05-22 13:56:32 -0700
committerPeter Klausler <pklausler@nvidia.com>2023-05-22 14:43:45 -0700
commit9efe1581502f1433811ea479345f84ca5008c754 (patch)
tree8264eeec829106cfd253c98942abf4e945b79d43 /flang/lib/Parser/preprocessor.cpp
parentd54ad0b6cd7c7be24062014367fcd0c3f525c7ec (diff)
downloadllvm-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.cpp67
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())};