summaryrefslogtreecommitdiff
path: root/unittests
diff options
context:
space:
mode:
authorYitzhak Mandelbaum <yitzhakm@google.com>2019-09-27 15:26:04 +0000
committerYitzhak Mandelbaum <yitzhakm@google.com>2019-09-27 15:26:04 +0000
commit03bc7eb123db247215352c11ffd8569ea2770d11 (patch)
treee11e743af14f645909eb9a13a418bfbd8c26db0e /unittests
parent1a6bed77c7bab29e82b40c05f3ff89b97b05a027 (diff)
downloadclang-03bc7eb123db247215352c11ffd8569ea2770d11.tar.gz
[libTooling] Transformer: refine `SourceLocation` specified as anchor of changes.
Summary: Every change triggered by a rewrite rule is anchored at a particular location in the source code. This patch refines how that location is chosen and defines it as an explicit function so it can be shared by other Transformer implementations. This patch was inspired by a bug found by a clang tidy, wherein two changes were anchored at the same location (the expansion loc of the macro) resulting in the discarding of the second change. Reviewers: gribozavr Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66652 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@373093 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests')
-rw-r--r--unittests/Tooling/TransformerTest.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/unittests/Tooling/TransformerTest.cpp b/unittests/Tooling/TransformerTest.cpp
index 554e586c3c..5d55182f82 100644
--- a/unittests/Tooling/TransformerTest.cpp
+++ b/unittests/Tooling/TransformerTest.cpp
@@ -710,6 +710,57 @@ TEST_F(TransformerTest, IdentityMacro) {
testRule(ruleStrlenSize(), Input, Expected);
}
+// Tests that two changes in a single macro expansion do not lead to conflicts
+// in applying the changes.
+TEST_F(TransformerTest, TwoChangesInOneMacroExpansion) {
+ std::string Input = R"cc(
+#define PLUS(a,b) (a) + (b)
+ int f() { return PLUS(3, 4); }
+ )cc";
+ std::string Expected = R"cc(
+#define PLUS(a,b) (a) + (b)
+ int f() { return PLUS(LIT, LIT); }
+ )cc";
+
+ testRule(makeRule(integerLiteral(), change(text("LIT"))), Input, Expected);
+}
+
+// Tests case where the rule's match spans both source from the macro and its
+// arg, with the begin location (the "anchor") being the arg.
+TEST_F(TransformerTest, MatchSpansMacroTextButChangeDoesNot) {
+ std::string Input = R"cc(
+#define PLUS_ONE(a) a + 1
+ int f() { return PLUS_ONE(3); }
+ )cc";
+ std::string Expected = R"cc(
+#define PLUS_ONE(a) a + 1
+ int f() { return PLUS_ONE(LIT); }
+ )cc";
+
+ StringRef E = "expr";
+ testRule(makeRule(binaryOperator(hasLHS(expr().bind(E))),
+ change(node(E), text("LIT"))),
+ Input, Expected);
+}
+
+// Tests case where the rule's match spans both source from the macro and its
+// arg, with the begin location (the "anchor") being inside the macro.
+TEST_F(TransformerTest, MatchSpansMacroTextButChangeDoesNotAnchoredInMacro) {
+ std::string Input = R"cc(
+#define PLUS_ONE(a) 1 + a
+ int f() { return PLUS_ONE(3); }
+ )cc";
+ std::string Expected = R"cc(
+#define PLUS_ONE(a) 1 + a
+ int f() { return PLUS_ONE(LIT); }
+ )cc";
+
+ StringRef E = "expr";
+ testRule(makeRule(binaryOperator(hasRHS(expr().bind(E))),
+ change(node(E), text("LIT"))),
+ Input, Expected);
+}
+
// No rewrite is applied when the changed text does not encompass the entirety
// of the expanded text. That is, the edit would have to be applied to the
// macro's definition to succeed and editing the expansion point would not