[clang] Allow usage of applyFirst with rewriteDescendants (PR #117658)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 25 17:54:56 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: None (SherAndrei)
<details>
<summary>Changes</summary>
Without these changes a clash appears between a Tag, which is bound to enclosing match, and a Tag, which is associated with first Case of applyFirst in rewriteDescendands.
We fix this by making sure that associated Tags are unique and deterministic as they are intend to be.
---
Full diff: https://github.com/llvm/llvm-project/pull/117658.diff
2 Files Affected:
- (modified) clang/lib/Tooling/Transformer/RewriteRule.cpp (+4-2)
- (modified) clang/unittests/Tooling/TransformerTest.cpp (+43)
``````````diff
diff --git a/clang/lib/Tooling/Transformer/RewriteRule.cpp b/clang/lib/Tooling/Transformer/RewriteRule.cpp
index eefddc34940487..196249260ec8b4 100644
--- a/clang/lib/Tooling/Transformer/RewriteRule.cpp
+++ b/clang/lib/Tooling/Transformer/RewriteRule.cpp
@@ -382,9 +382,10 @@ static std::vector<DynTypedMatcher> taggedMatchers(
std::vector<DynTypedMatcher> Matchers;
Matchers.reserve(Cases.size());
for (const auto &Case : Cases) {
- std::string Tag = (TagBase + Twine(Case.first)).str();
// HACK: Many matchers are not bindable, so ensure that tryBind will work.
DynTypedMatcher BoundMatcher(Case.second.Matcher);
+ const auto [_, ID] = BoundMatcher.getID();
+ std::string Tag = (TagBase + Twine(ID)).str();
BoundMatcher.setAllowBind(true);
auto M = *BoundMatcher.tryBind(Tag);
Matchers.push_back(!M.getTraversalKind()
@@ -469,7 +470,8 @@ size_t transformer::detail::findSelectedCase(const MatchResult &Result,
auto &NodesMap = Result.Nodes.getMap();
for (size_t i = 0, N = Rule.Cases.size(); i < N; ++i) {
- std::string Tag = ("Tag" + Twine(i)).str();
+ const auto [_, ID] = Rule.Cases[i].Matcher.getID();
+ std::string Tag = ("Tag" + Twine(ID)).str();
if (NodesMap.find(Tag) != NodesMap.end())
return i;
}
diff --git a/clang/unittests/Tooling/TransformerTest.cpp b/clang/unittests/Tooling/TransformerTest.cpp
index cbd84ab794a49a..0404c81862468f 100644
--- a/clang/unittests/Tooling/TransformerTest.cpp
+++ b/clang/unittests/Tooling/TransformerTest.cpp
@@ -605,6 +605,49 @@ TEST_F(TransformerTest, RewriteDescendantsReferToParentBinding) {
Input, Expected);
}
+TEST_F(TransformerTest, RewriteDescendantsApplyFirstOrderedRuleUnrelated) {
+ std::string Input = "int f(int x) { int y = x; return x; }";
+ std::string Expected = "int f(int x) { char y = 3; return 3; }";
+ auto IntToChar = makeRule(typeLoc(loc(qualType(isInteger(), builtinType()))),
+ changeTo(cat("char")));
+ auto InlineX =
+ makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
+ testRule(
+ makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))),
+ rewriteDescendants("body", applyFirst({InlineX, IntToChar}))),
+ Input, Expected);
+}
+
+TEST_F(TransformerTest, RewriteDescendantsApplyFirstOrderedRuleRelated) {
+ std::string Input = "int f(int x) { int y = x; return x; }";
+ std::string Expected = "int f(int x) { int y = 3; return y; }";
+ auto ReturnY = makeRule(
+ traverse(TK_IgnoreUnlessSpelledInSource,
+ declRefExpr(to(varDecl(hasName("x"))), hasParent(returnStmt()))),
+ changeTo(cat("y")));
+ auto InlineX = makeRule(traverse(TK_IgnoreUnlessSpelledInSource,
+ declRefExpr(to(varDecl(hasName("x"))))),
+ changeTo(cat("3")));
+ testRule(makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))),
+ rewriteDescendants("body", applyFirst({ReturnY, InlineX}))),
+ Input, Expected);
+}
+
+TEST_F(TransformerTest, RewriteDescendantsApplyFirstOrderedRuleRelatedSwapped) {
+ std::string Input = "int f(int x) { int y = x; return x; }";
+ std::string Expected = "int f(int x) { int y = 3; return 3; }";
+ auto ReturnY = makeRule(
+ traverse(TK_IgnoreUnlessSpelledInSource,
+ declRefExpr(to(varDecl(hasName("x"))), hasParent(returnStmt()))),
+ changeTo(cat("y")));
+ auto InlineX = makeRule(traverse(TK_IgnoreUnlessSpelledInSource,
+ declRefExpr(to(varDecl(hasName("x"))))),
+ changeTo(cat("3")));
+ testRule(makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))),
+ rewriteDescendants("body", applyFirst({InlineX, ReturnY}))),
+ Input, Expected);
+}
+
TEST_F(TransformerTest, RewriteDescendantsUnboundNode) {
std::string Input =
"int f(int x) { int y = x; { int z = x * x; } return x; }";
``````````
</details>
https://github.com/llvm/llvm-project/pull/117658
More information about the cfe-commits
mailing list