diff options
author | Yitzhak Mandelbaum <yitzhakm@google.com> | 2019-09-27 15:26:04 +0000 |
---|---|---|
committer | Yitzhak Mandelbaum <yitzhakm@google.com> | 2019-09-27 15:26:04 +0000 |
commit | 03bc7eb123db247215352c11ffd8569ea2770d11 (patch) | |
tree | e11e743af14f645909eb9a13a418bfbd8c26db0e /unittests | |
parent | 1a6bed77c7bab29e82b40c05f3ff89b97b05a027 (diff) | |
download | clang-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.cpp | 51 |
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 |