1 //===- unittest/Tooling/TransformerTest.cpp -------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Tooling/Transformer/Transformer.h"
10 #include "clang/ASTMatchers/ASTMatchers.h"
11 #include "clang/Tooling/Tooling.h"
12 #include "clang/Tooling/Transformer/RangeSelector.h"
13 #include "clang/Tooling/Transformer/RewriteRule.h"
14 #include "clang/Tooling/Transformer/Stencil.h"
15 #include "llvm/Support/Errc.h"
16 #include "llvm/Support/Error.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19 
20 using namespace clang;
21 using namespace tooling;
22 using namespace ast_matchers;
23 namespace {
24 using ::clang::transformer::addInclude;
25 using ::clang::transformer::applyFirst;
26 using ::clang::transformer::before;
27 using ::clang::transformer::cat;
28 using ::clang::transformer::changeTo;
29 using ::clang::transformer::makeRule;
30 using ::clang::transformer::member;
31 using ::clang::transformer::name;
32 using ::clang::transformer::node;
33 using ::clang::transformer::remove;
34 using ::clang::transformer::rewriteDescendants;
35 using ::clang::transformer::RewriteRule;
36 using ::clang::transformer::statement;
37 using ::testing::ElementsAre;
38 using ::testing::IsEmpty;
39 
40 constexpr char KHeaderContents[] = R"cc(
41   struct string {
42     string(const char*);
43     char* c_str();
44     int size();
45   };
46   int strlen(const char*);
47 
48   namespace proto {
49   struct PCFProto {
50     int foo();
51   };
52   struct ProtoCommandLineFlag : PCFProto {
53     PCFProto& GetProto();
54   };
55   }  // namespace proto
56   class Logger {};
57   void operator<<(Logger& l, string msg);
58   Logger& log(int level);
59 )cc";
60 
61 static ast_matchers::internal::Matcher<clang::QualType>
isOrPointsTo(const clang::ast_matchers::DeclarationMatcher & TypeMatcher)62 isOrPointsTo(const clang::ast_matchers::DeclarationMatcher &TypeMatcher) {
63   return anyOf(hasDeclaration(TypeMatcher), pointsTo(TypeMatcher));
64 }
65 
format(StringRef Code)66 static std::string format(StringRef Code) {
67   const std::vector<Range> Ranges(1, Range(0, Code.size()));
68   auto Style = format::getLLVMStyle();
69   const auto Replacements = format::reformat(Style, Code, Ranges);
70   auto Formatted = applyAllReplacements(Code, Replacements);
71   if (!Formatted) {
72     ADD_FAILURE() << "Could not format code: "
73                   << llvm::toString(Formatted.takeError());
74     return std::string();
75   }
76   return *Formatted;
77 }
78 
compareSnippets(StringRef Expected,const llvm::Optional<std::string> & MaybeActual)79 static void compareSnippets(StringRef Expected,
80                      const llvm::Optional<std::string> &MaybeActual) {
81   ASSERT_TRUE(MaybeActual) << "Rewrite failed. Expecting: " << Expected;
82   auto Actual = *MaybeActual;
83   std::string HL = "#include \"header.h\"\n";
84   auto I = Actual.find(HL);
85   if (I != std::string::npos)
86     Actual.erase(I, HL.size());
87   EXPECT_EQ(format(Expected), format(Actual));
88 }
89 
90 // FIXME: consider separating this class into its own file(s).
91 class ClangRefactoringTestBase : public testing::Test {
92 protected:
appendToHeader(StringRef S)93   void appendToHeader(StringRef S) { FileContents[0].second += S; }
94 
addFile(StringRef Filename,StringRef Content)95   void addFile(StringRef Filename, StringRef Content) {
96     FileContents.emplace_back(std::string(Filename), std::string(Content));
97   }
98 
rewrite(StringRef Input)99   llvm::Optional<std::string> rewrite(StringRef Input) {
100     std::string Code = ("#include \"header.h\"\n" + Input).str();
101     auto Factory = newFrontendActionFactory(&MatchFinder);
102     if (!runToolOnCodeWithArgs(
103             Factory->create(), Code, std::vector<std::string>(), "input.cc",
104             "clang-tool", std::make_shared<PCHContainerOperations>(),
105             FileContents)) {
106       llvm::errs() << "Running tool failed.\n";
107       return None;
108     }
109     if (ErrorCount != 0) {
110       llvm::errs() << "Generating changes failed.\n";
111       return None;
112     }
113     auto ChangedCode =
114         applyAtomicChanges("input.cc", Code, Changes, ApplyChangesSpec());
115     if (!ChangedCode) {
116       llvm::errs() << "Applying changes failed: "
117                    << llvm::toString(ChangedCode.takeError()) << "\n";
118       return None;
119     }
120     return *ChangedCode;
121   }
122 
consumer()123   Transformer::ChangeConsumer consumer() {
124     return [this](Expected<AtomicChange> C) {
125       if (C) {
126         Changes.push_back(std::move(*C));
127       } else {
128         // FIXME: stash this error rather then printing.
129         llvm::errs() << "Error generating changes: "
130                      << llvm::toString(C.takeError()) << "\n";
131         ++ErrorCount;
132       }
133     };
134   }
135 
136   template <typename R>
testRule(R Rule,StringRef Input,StringRef Expected)137   void testRule(R Rule, StringRef Input, StringRef Expected) {
138     Transformers.push_back(
139         std::make_unique<Transformer>(std::move(Rule), consumer()));
140     Transformers.back()->registerMatchers(&MatchFinder);
141     compareSnippets(Expected, rewrite(Input));
142   }
143 
testRuleFailure(R Rule,StringRef Input)144   template <typename R> void testRuleFailure(R Rule, StringRef Input) {
145     Transformers.push_back(
146         std::make_unique<Transformer>(std::move(Rule), consumer()));
147     Transformers.back()->registerMatchers(&MatchFinder);
148     ASSERT_FALSE(rewrite(Input)) << "Expected failure to rewrite code";
149   }
150 
151   // Transformers are referenced by MatchFinder.
152   std::vector<std::unique_ptr<Transformer>> Transformers;
153   clang::ast_matchers::MatchFinder MatchFinder;
154   // Records whether any errors occurred in individual changes.
155   int ErrorCount = 0;
156   AtomicChanges Changes;
157 
158 private:
159   FileContentMappings FileContents = {{"header.h", ""}};
160 };
161 
162 class TransformerTest : public ClangRefactoringTestBase {
163 protected:
TransformerTest()164   TransformerTest() { appendToHeader(KHeaderContents); }
165 };
166 
167 // Given string s, change strlen($s.c_str()) to REPLACED.
ruleStrlenSize()168 static RewriteRule ruleStrlenSize() {
169   StringRef StringExpr = "strexpr";
170   auto StringType = namedDecl(hasAnyName("::basic_string", "::string"));
171   auto R = makeRule(
172       callExpr(callee(functionDecl(hasName("strlen"))),
173                hasArgument(0, cxxMemberCallExpr(
174                                   on(expr(hasType(isOrPointsTo(StringType)))
175                                          .bind(StringExpr)),
176                                   callee(cxxMethodDecl(hasName("c_str")))))),
177       changeTo(cat("REPLACED")), cat("Use size() method directly on string."));
178   return R;
179 }
180 
TEST_F(TransformerTest,StrlenSize)181 TEST_F(TransformerTest, StrlenSize) {
182   std::string Input = "int f(string s) { return strlen(s.c_str()); }";
183   std::string Expected = "int f(string s) { return REPLACED; }";
184   testRule(ruleStrlenSize(), Input, Expected);
185 }
186 
187 // Tests that no change is applied when a match is not expected.
TEST_F(TransformerTest,NoMatch)188 TEST_F(TransformerTest, NoMatch) {
189   std::string Input = "int f(string s) { return s.size(); }";
190   testRule(ruleStrlenSize(), Input, Input);
191 }
192 
193 // Tests replacing an expression.
TEST_F(TransformerTest,Flag)194 TEST_F(TransformerTest, Flag) {
195   StringRef Flag = "flag";
196   RewriteRule Rule = makeRule(
197       cxxMemberCallExpr(on(expr(hasType(cxxRecordDecl(
198                                     hasName("proto::ProtoCommandLineFlag"))))
199                                .bind(Flag)),
200                         unless(callee(cxxMethodDecl(hasName("GetProto"))))),
201       changeTo(node(std::string(Flag)), cat("EXPR")));
202 
203   std::string Input = R"cc(
204     proto::ProtoCommandLineFlag flag;
205     int x = flag.foo();
206     int y = flag.GetProto().foo();
207   )cc";
208   std::string Expected = R"cc(
209     proto::ProtoCommandLineFlag flag;
210     int x = EXPR.foo();
211     int y = flag.GetProto().foo();
212   )cc";
213 
214   testRule(std::move(Rule), Input, Expected);
215 }
216 
TEST_F(TransformerTest,AddIncludeQuoted)217 TEST_F(TransformerTest, AddIncludeQuoted) {
218   RewriteRule Rule =
219       makeRule(callExpr(callee(functionDecl(hasName("f")))),
220                {addInclude("clang/OtherLib.h"), changeTo(cat("other()"))});
221 
222   std::string Input = R"cc(
223     int f(int x);
224     int h(int x) { return f(x); }
225   )cc";
226   std::string Expected = R"cc(#include "clang/OtherLib.h"
227 
228     int f(int x);
229     int h(int x) { return other(); }
230   )cc";
231 
232   testRule(Rule, Input, Expected);
233 }
234 
TEST_F(TransformerTest,AddIncludeAngled)235 TEST_F(TransformerTest, AddIncludeAngled) {
236   RewriteRule Rule = makeRule(
237       callExpr(callee(functionDecl(hasName("f")))),
238       {addInclude("clang/OtherLib.h", transformer::IncludeFormat::Angled),
239        changeTo(cat("other()"))});
240 
241   std::string Input = R"cc(
242     int f(int x);
243     int h(int x) { return f(x); }
244   )cc";
245   std::string Expected = R"cc(#include <clang/OtherLib.h>
246 
247     int f(int x);
248     int h(int x) { return other(); }
249   )cc";
250 
251   testRule(Rule, Input, Expected);
252 }
253 
TEST_F(TransformerTest,AddIncludeQuotedForRule)254 TEST_F(TransformerTest, AddIncludeQuotedForRule) {
255   RewriteRule Rule = makeRule(callExpr(callee(functionDecl(hasName("f")))),
256                               changeTo(cat("other()")));
257   addInclude(Rule, "clang/OtherLib.h");
258 
259   std::string Input = R"cc(
260     int f(int x);
261     int h(int x) { return f(x); }
262   )cc";
263   std::string Expected = R"cc(#include "clang/OtherLib.h"
264 
265     int f(int x);
266     int h(int x) { return other(); }
267   )cc";
268 
269   testRule(Rule, Input, Expected);
270 }
271 
TEST_F(TransformerTest,AddIncludeAngledForRule)272 TEST_F(TransformerTest, AddIncludeAngledForRule) {
273   RewriteRule Rule = makeRule(callExpr(callee(functionDecl(hasName("f")))),
274                               changeTo(cat("other()")));
275   addInclude(Rule, "clang/OtherLib.h", transformer::IncludeFormat::Angled);
276 
277   std::string Input = R"cc(
278     int f(int x);
279     int h(int x) { return f(x); }
280   )cc";
281   std::string Expected = R"cc(#include <clang/OtherLib.h>
282 
283     int f(int x);
284     int h(int x) { return other(); }
285   )cc";
286 
287   testRule(Rule, Input, Expected);
288 }
289 
TEST_F(TransformerTest,NodePartNameNamedDecl)290 TEST_F(TransformerTest, NodePartNameNamedDecl) {
291   StringRef Fun = "fun";
292   RewriteRule Rule = makeRule(functionDecl(hasName("bad")).bind(Fun),
293                               changeTo(name(std::string(Fun)), cat("good")));
294 
295   std::string Input = R"cc(
296     int bad(int x);
297     int bad(int x) { return x * x; }
298   )cc";
299   std::string Expected = R"cc(
300     int good(int x);
301     int good(int x) { return x * x; }
302   )cc";
303 
304   testRule(Rule, Input, Expected);
305 }
306 
TEST_F(TransformerTest,NodePartNameDeclRef)307 TEST_F(TransformerTest, NodePartNameDeclRef) {
308   std::string Input = R"cc(
309     template <typename T>
310     T bad(T x) {
311       return x;
312     }
313     int neutral(int x) { return bad<int>(x) * x; }
314   )cc";
315   std::string Expected = R"cc(
316     template <typename T>
317     T bad(T x) {
318       return x;
319     }
320     int neutral(int x) { return good<int>(x) * x; }
321   )cc";
322 
323   StringRef Ref = "ref";
324   testRule(makeRule(declRefExpr(to(functionDecl(hasName("bad")))).bind(Ref),
325                     changeTo(name(std::string(Ref)), cat("good"))),
326            Input, Expected);
327 }
328 
TEST_F(TransformerTest,NodePartNameDeclRefFailure)329 TEST_F(TransformerTest, NodePartNameDeclRefFailure) {
330   std::string Input = R"cc(
331     struct Y {
332       int operator*();
333     };
334     int neutral(int x) {
335       Y y;
336       int (Y::*ptr)() = &Y::operator*;
337       return *y + x;
338     }
339   )cc";
340 
341   StringRef Ref = "ref";
342   Transformer T(makeRule(declRefExpr(to(functionDecl())).bind(Ref),
343                          changeTo(name(std::string(Ref)), cat("good"))),
344                 consumer());
345   T.registerMatchers(&MatchFinder);
346   EXPECT_FALSE(rewrite(Input));
347 }
348 
TEST_F(TransformerTest,NodePartMember)349 TEST_F(TransformerTest, NodePartMember) {
350   StringRef E = "expr";
351   RewriteRule Rule =
352       makeRule(memberExpr(clang::ast_matchers::member(hasName("bad"))).bind(E),
353                changeTo(member(std::string(E)), cat("good")));
354 
355   std::string Input = R"cc(
356     struct S {
357       int bad;
358     };
359     int g() {
360       S s;
361       return s.bad;
362     }
363   )cc";
364   std::string Expected = R"cc(
365     struct S {
366       int bad;
367     };
368     int g() {
369       S s;
370       return s.good;
371     }
372   )cc";
373 
374   testRule(Rule, Input, Expected);
375 }
376 
TEST_F(TransformerTest,NodePartMemberQualified)377 TEST_F(TransformerTest, NodePartMemberQualified) {
378   std::string Input = R"cc(
379     struct S {
380       int bad;
381       int good;
382     };
383     struct T : public S {
384       int bad;
385     };
386     int g() {
387       T t;
388       return t.S::bad;
389     }
390   )cc";
391   std::string Expected = R"cc(
392     struct S {
393       int bad;
394       int good;
395     };
396     struct T : public S {
397       int bad;
398     };
399     int g() {
400       T t;
401       return t.S::good;
402     }
403   )cc";
404 
405   StringRef E = "expr";
406   testRule(makeRule(memberExpr().bind(E),
407                     changeTo(member(std::string(E)), cat("good"))),
408            Input, Expected);
409 }
410 
TEST_F(TransformerTest,NodePartMemberMultiToken)411 TEST_F(TransformerTest, NodePartMemberMultiToken) {
412   std::string Input = R"cc(
413     struct Y {
414       int operator*();
415       int good();
416       template <typename T> void foo(T t);
417     };
418     int neutral(int x) {
419       Y y;
420       y.template foo<int>(3);
421       return y.operator *();
422     }
423   )cc";
424   std::string Expected = R"cc(
425     struct Y {
426       int operator*();
427       int good();
428       template <typename T> void foo(T t);
429     };
430     int neutral(int x) {
431       Y y;
432       y.template good<int>(3);
433       return y.good();
434     }
435   )cc";
436 
437   StringRef MemExpr = "member";
438   testRule(makeRule(memberExpr().bind(MemExpr),
439                     changeTo(member(std::string(MemExpr)), cat("good"))),
440            Input, Expected);
441 }
442 
TEST_F(TransformerTest,NoEdits)443 TEST_F(TransformerTest, NoEdits) {
444   using transformer::noEdits;
445   std::string Input = "int f(int x) { return x; }";
446   testRule(makeRule(returnStmt().bind("return"), noEdits()), Input, Input);
447 }
448 
TEST_F(TransformerTest,NoopEdit)449 TEST_F(TransformerTest, NoopEdit) {
450   using transformer::node;
451   using transformer::noopEdit;
452   std::string Input = "int f(int x) { return x; }";
453   testRule(makeRule(returnStmt().bind("return"), noopEdit(node("return"))),
454            Input, Input);
455 }
456 
TEST_F(TransformerTest,IfBound2Args)457 TEST_F(TransformerTest, IfBound2Args) {
458   using transformer::ifBound;
459   std::string Input = "int f(int x) { return x; }";
460   std::string Expected = "int f(int x) { CHANGE; }";
461   testRule(makeRule(returnStmt().bind("return"),
462                     ifBound("return", changeTo(cat("CHANGE;")))),
463            Input, Expected);
464 }
465 
TEST_F(TransformerTest,IfBound3Args)466 TEST_F(TransformerTest, IfBound3Args) {
467   using transformer::ifBound;
468   std::string Input = "int f(int x) { return x; }";
469   std::string Expected = "int f(int x) { CHANGE; }";
470   testRule(makeRule(returnStmt().bind("return"),
471                     ifBound("nothing", changeTo(cat("ERROR")),
472                             changeTo(cat("CHANGE;")))),
473            Input, Expected);
474 }
475 
TEST_F(TransformerTest,ShrinkTo)476 TEST_F(TransformerTest, ShrinkTo) {
477   using transformer::shrinkTo;
478   std::string Input = "int f(int x) { return x; }";
479   std::string Expected = "return x;";
480   testRule(makeRule(functionDecl(hasDescendant(returnStmt().bind("return")))
481                         .bind("function"),
482                     shrinkTo(node("function"), node("return"))),
483            Input, Expected);
484 }
485 
486 // Rewrite various Stmts inside a Decl.
TEST_F(TransformerTest,RewriteDescendantsDeclChangeStmt)487 TEST_F(TransformerTest, RewriteDescendantsDeclChangeStmt) {
488   std::string Input =
489       "int f(int x) { int y = x; { int z = x * x; } return x; }";
490   std::string Expected =
491       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
492   auto InlineX =
493       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
494   testRule(makeRule(functionDecl(hasName("f")).bind("fun"),
495                     rewriteDescendants("fun", InlineX)),
496            Input, Expected);
497 }
498 
499 // Rewrite various TypeLocs inside a Decl.
TEST_F(TransformerTest,RewriteDescendantsDeclChangeTypeLoc)500 TEST_F(TransformerTest, RewriteDescendantsDeclChangeTypeLoc) {
501   std::string Input = "int f(int *x) { return *x; }";
502   std::string Expected = "char f(char *x) { return *x; }";
503   auto IntToChar = makeRule(typeLoc(loc(qualType(isInteger(), builtinType()))),
504                             changeTo(cat("char")));
505   testRule(makeRule(functionDecl(hasName("f")).bind("fun"),
506                     rewriteDescendants("fun", IntToChar)),
507            Input, Expected);
508 }
509 
TEST_F(TransformerTest,RewriteDescendantsStmt)510 TEST_F(TransformerTest, RewriteDescendantsStmt) {
511   // Add an unrelated definition to the header that also has a variable named
512   // "x", to test that the rewrite is limited to the scope we intend.
513   appendToHeader(R"cc(int g(int x) { return x; })cc");
514   std::string Input =
515       "int f(int x) { int y = x; { int z = x * x; } return x; }";
516   std::string Expected =
517       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
518   auto InlineX =
519       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
520   testRule(makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))),
521                     rewriteDescendants("body", InlineX)),
522            Input, Expected);
523 }
524 
TEST_F(TransformerTest,RewriteDescendantsStmtWithAdditionalChange)525 TEST_F(TransformerTest, RewriteDescendantsStmtWithAdditionalChange) {
526   std::string Input =
527       "int f(int x) { int y = x; { int z = x * x; } return x; }";
528   std::string Expected =
529       "int newName(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
530   auto InlineX =
531       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
532   testRule(
533       makeRule(
534           functionDecl(hasName("f"), hasBody(stmt().bind("body"))).bind("f"),
535           flatten(changeTo(name("f"), cat("newName")),
536                   rewriteDescendants("body", InlineX))),
537       Input, Expected);
538 }
539 
TEST_F(TransformerTest,RewriteDescendantsTypeLoc)540 TEST_F(TransformerTest, RewriteDescendantsTypeLoc) {
541   std::string Input = "int f(int *x) { return *x; }";
542   std::string Expected = "int f(char *x) { return *x; }";
543   auto IntToChar =
544       makeRule(typeLoc(loc(qualType(isInteger(), builtinType()))).bind("loc"),
545                changeTo(cat("char")));
546   testRule(
547       makeRule(functionDecl(hasName("f"),
548                             hasParameter(0, varDecl(hasTypeLoc(
549                                                 typeLoc().bind("parmType"))))),
550                rewriteDescendants("parmType", IntToChar)),
551       Input, Expected);
552 }
553 
TEST_F(TransformerTest,RewriteDescendantsReferToParentBinding)554 TEST_F(TransformerTest, RewriteDescendantsReferToParentBinding) {
555   std::string Input =
556       "int f(int p) { int y = p; { int z = p * p; } return p; }";
557   std::string Expected =
558       "int f(int p) { int y = 3; { int z = 3 * 3; } return 3; }";
559   std::string VarId = "var";
560   auto InlineVar = makeRule(declRefExpr(to(varDecl(equalsBoundNode(VarId)))),
561                             changeTo(cat("3")));
562   testRule(makeRule(functionDecl(hasName("f"),
563                                  hasParameter(0, varDecl().bind(VarId)))
564                         .bind("fun"),
565                     rewriteDescendants("fun", InlineVar)),
566            Input, Expected);
567 }
568 
TEST_F(TransformerTest,RewriteDescendantsUnboundNode)569 TEST_F(TransformerTest, RewriteDescendantsUnboundNode) {
570   std::string Input =
571       "int f(int x) { int y = x; { int z = x * x; } return x; }";
572   auto InlineX =
573       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
574   Transformer T(makeRule(functionDecl(hasName("f")),
575                          rewriteDescendants("UNBOUND", InlineX)),
576                 consumer());
577   T.registerMatchers(&MatchFinder);
578   EXPECT_FALSE(rewrite(Input));
579   EXPECT_THAT(Changes, IsEmpty());
580   EXPECT_EQ(ErrorCount, 1);
581 }
582 
TEST_F(TransformerTest,RewriteDescendantsInvalidNodeType)583 TEST_F(TransformerTest, RewriteDescendantsInvalidNodeType) {
584   std::string Input =
585       "int f(int x) { int y = x; { int z = x * x; } return x; }";
586   auto IntToChar =
587       makeRule(qualType(isInteger(), builtinType()), changeTo(cat("char")));
588   Transformer T(
589       makeRule(functionDecl(
590                    hasName("f"),
591                    hasParameter(0, varDecl(hasType(qualType().bind("type"))))),
592                rewriteDescendants("type", IntToChar)),
593       consumer());
594   T.registerMatchers(&MatchFinder);
595   EXPECT_FALSE(rewrite(Input));
596   EXPECT_THAT(Changes, IsEmpty());
597   EXPECT_EQ(ErrorCount, 1);
598 }
599 
600 //
601 // We include one test per typed overload. We don't test extensively since that
602 // is already covered by the tests above.
603 //
604 
TEST_F(TransformerTest,RewriteDescendantsTypedStmt)605 TEST_F(TransformerTest, RewriteDescendantsTypedStmt) {
606   // Add an unrelated definition to the header that also has a variable named
607   // "x", to test that the rewrite is limited to the scope we intend.
608   appendToHeader(R"cc(int g(int x) { return x; })cc");
609   std::string Input =
610       "int f(int x) { int y = x; { int z = x * x; } return x; }";
611   std::string Expected =
612       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
613   auto InlineX =
614       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
615   testRule(makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))),
616                     [&InlineX](const MatchFinder::MatchResult &R) {
617                       const auto *Node = R.Nodes.getNodeAs<Stmt>("body");
618                       assert(Node != nullptr && "body must be bound");
619                       return transformer::detail::rewriteDescendants(
620                           *Node, InlineX, R);
621                     }),
622            Input, Expected);
623 }
624 
TEST_F(TransformerTest,RewriteDescendantsTypedDecl)625 TEST_F(TransformerTest, RewriteDescendantsTypedDecl) {
626   std::string Input =
627       "int f(int x) { int y = x; { int z = x * x; } return x; }";
628   std::string Expected =
629       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
630   auto InlineX =
631       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
632   testRule(makeRule(functionDecl(hasName("f")).bind("fun"),
633                     [&InlineX](const MatchFinder::MatchResult &R) {
634                       const auto *Node = R.Nodes.getNodeAs<Decl>("fun");
635                       assert(Node != nullptr && "fun must be bound");
636                       return transformer::detail::rewriteDescendants(
637                           *Node, InlineX, R);
638                     }),
639            Input, Expected);
640 }
641 
TEST_F(TransformerTest,RewriteDescendantsTypedTypeLoc)642 TEST_F(TransformerTest, RewriteDescendantsTypedTypeLoc) {
643   std::string Input = "int f(int *x) { return *x; }";
644   std::string Expected = "int f(char *x) { return *x; }";
645   auto IntToChar =
646       makeRule(typeLoc(loc(qualType(isInteger(), builtinType()))).bind("loc"),
647                changeTo(cat("char")));
648   testRule(
649       makeRule(
650           functionDecl(
651               hasName("f"),
652               hasParameter(0, varDecl(hasTypeLoc(typeLoc().bind("parmType"))))),
653           [&IntToChar](const MatchFinder::MatchResult &R) {
654             const auto *Node = R.Nodes.getNodeAs<TypeLoc>("parmType");
655             assert(Node != nullptr && "parmType must be bound");
656             return transformer::detail::rewriteDescendants(*Node, IntToChar, R);
657           }),
658       Input, Expected);
659 }
660 
TEST_F(TransformerTest,RewriteDescendantsTypedDynTyped)661 TEST_F(TransformerTest, RewriteDescendantsTypedDynTyped) {
662   // Add an unrelated definition to the header that also has a variable named
663   // "x", to test that the rewrite is limited to the scope we intend.
664   appendToHeader(R"cc(int g(int x) { return x; })cc");
665   std::string Input =
666       "int f(int x) { int y = x; { int z = x * x; } return x; }";
667   std::string Expected =
668       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
669   auto InlineX =
670       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
671   testRule(
672       makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))),
673                [&InlineX](const MatchFinder::MatchResult &R) {
674                  auto It = R.Nodes.getMap().find("body");
675                  assert(It != R.Nodes.getMap().end() && "body must be bound");
676                  return transformer::detail::rewriteDescendants(It->second,
677                                                                 InlineX, R);
678                }),
679       Input, Expected);
680 }
681 
TEST_F(TransformerTest,InsertBeforeEdit)682 TEST_F(TransformerTest, InsertBeforeEdit) {
683   std::string Input = R"cc(
684     int f() {
685       return 7;
686     }
687   )cc";
688   std::string Expected = R"cc(
689     int f() {
690       int y = 3;
691       return 7;
692     }
693   )cc";
694 
695   StringRef Ret = "return";
696   testRule(
697       makeRule(returnStmt().bind(Ret),
698                insertBefore(statement(std::string(Ret)), cat("int y = 3;"))),
699       Input, Expected);
700 }
701 
TEST_F(TransformerTest,InsertAfterEdit)702 TEST_F(TransformerTest, InsertAfterEdit) {
703   std::string Input = R"cc(
704     int f() {
705       int x = 5;
706       return 7;
707     }
708   )cc";
709   std::string Expected = R"cc(
710     int f() {
711       int x = 5;
712       int y = 3;
713       return 7;
714     }
715   )cc";
716 
717   StringRef Decl = "decl";
718   testRule(
719       makeRule(declStmt().bind(Decl),
720                insertAfter(statement(std::string(Decl)), cat("int y = 3;"))),
721       Input, Expected);
722 }
723 
TEST_F(TransformerTest,RemoveEdit)724 TEST_F(TransformerTest, RemoveEdit) {
725   std::string Input = R"cc(
726     int f() {
727       int x = 5;
728       return 7;
729     }
730   )cc";
731   std::string Expected = R"cc(
732     int f() {
733       return 7;
734     }
735   )cc";
736 
737   StringRef Decl = "decl";
738   testRule(
739       makeRule(declStmt().bind(Decl), remove(statement(std::string(Decl)))),
740       Input, Expected);
741 }
742 
TEST_F(TransformerTest,WithMetadata)743 TEST_F(TransformerTest, WithMetadata) {
744   auto makeMetadata = [](const MatchFinder::MatchResult &R) -> llvm::Any {
745     int N =
746         R.Nodes.getNodeAs<IntegerLiteral>("int")->getValue().getLimitedValue();
747     return N;
748   };
749 
750   std::string Input = R"cc(
751     int f() {
752       int x = 5;
753       return 7;
754     }
755   )cc";
756 
757   Transformer T(
758       makeRule(
759           declStmt(containsDeclaration(0, varDecl(hasInitializer(
760                                               integerLiteral().bind("int")))))
761               .bind("decl"),
762           withMetadata(remove(statement(std::string("decl"))), makeMetadata)),
763       consumer());
764   T.registerMatchers(&MatchFinder);
765   auto Factory = newFrontendActionFactory(&MatchFinder);
766   EXPECT_TRUE(runToolOnCodeWithArgs(
767       Factory->create(), Input, std::vector<std::string>(), "input.cc",
768       "clang-tool", std::make_shared<PCHContainerOperations>(), {}));
769   ASSERT_EQ(Changes.size(), 1u);
770   const llvm::Any &Metadata = Changes[0].getMetadata();
771   ASSERT_TRUE(llvm::any_isa<int>(Metadata));
772   EXPECT_THAT(llvm::any_cast<int>(Metadata), 5);
773 }
774 
TEST_F(TransformerTest,MultiChange)775 TEST_F(TransformerTest, MultiChange) {
776   std::string Input = R"cc(
777     void foo() {
778       if (10 > 1.0)
779         log(1) << "oh no!";
780       else
781         log(0) << "ok";
782     }
783   )cc";
784   std::string Expected = R"(
785     void foo() {
786       if (true) { /* then */ }
787       else { /* else */ }
788     }
789   )";
790 
791   StringRef C = "C", T = "T", E = "E";
792   testRule(
793       makeRule(ifStmt(hasCondition(expr().bind(C)), hasThen(stmt().bind(T)),
794                       hasElse(stmt().bind(E))),
795                {changeTo(node(std::string(C)), cat("true")),
796                 changeTo(statement(std::string(T)), cat("{ /* then */ }")),
797                 changeTo(statement(std::string(E)), cat("{ /* else */ }"))}),
798       Input, Expected);
799 }
800 
TEST_F(TransformerTest,EditList)801 TEST_F(TransformerTest, EditList) {
802   using clang::transformer::editList;
803   std::string Input = R"cc(
804     void foo() {
805       if (10 > 1.0)
806         log(1) << "oh no!";
807       else
808         log(0) << "ok";
809     }
810   )cc";
811   std::string Expected = R"(
812     void foo() {
813       if (true) { /* then */ }
814       else { /* else */ }
815     }
816   )";
817 
818   StringRef C = "C", T = "T", E = "E";
819   testRule(makeRule(ifStmt(hasCondition(expr().bind(C)),
820                            hasThen(stmt().bind(T)), hasElse(stmt().bind(E))),
821                     editList({changeTo(node(std::string(C)), cat("true")),
822                               changeTo(statement(std::string(T)),
823                                        cat("{ /* then */ }")),
824                               changeTo(statement(std::string(E)),
825                                        cat("{ /* else */ }"))})),
826            Input, Expected);
827 }
828 
TEST_F(TransformerTest,Flatten)829 TEST_F(TransformerTest, Flatten) {
830   using clang::transformer::editList;
831   std::string Input = R"cc(
832     void foo() {
833       if (10 > 1.0)
834         log(1) << "oh no!";
835       else
836         log(0) << "ok";
837     }
838   )cc";
839   std::string Expected = R"(
840     void foo() {
841       if (true) { /* then */ }
842       else { /* else */ }
843     }
844   )";
845 
846   StringRef C = "C", T = "T", E = "E";
847   testRule(
848       makeRule(
849           ifStmt(hasCondition(expr().bind(C)), hasThen(stmt().bind(T)),
850                  hasElse(stmt().bind(E))),
851           flatten(changeTo(node(std::string(C)), cat("true")),
852                   changeTo(statement(std::string(T)), cat("{ /* then */ }")),
853                   changeTo(statement(std::string(E)), cat("{ /* else */ }")))),
854       Input, Expected);
855 }
856 
TEST_F(TransformerTest,FlattenWithMixedArgs)857 TEST_F(TransformerTest, FlattenWithMixedArgs) {
858   using clang::transformer::editList;
859   std::string Input = R"cc(
860     void foo() {
861       if (10 > 1.0)
862         log(1) << "oh no!";
863       else
864         log(0) << "ok";
865     }
866   )cc";
867   std::string Expected = R"(
868     void foo() {
869       if (true) { /* then */ }
870       else { /* else */ }
871     }
872   )";
873 
874   StringRef C = "C", T = "T", E = "E";
875   testRule(makeRule(ifStmt(hasCondition(expr().bind(C)),
876                            hasThen(stmt().bind(T)), hasElse(stmt().bind(E))),
877                     flatten(changeTo(node(std::string(C)), cat("true")),
878                             edit(changeTo(statement(std::string(T)),
879                                           cat("{ /* then */ }"))),
880                             editList({changeTo(statement(std::string(E)),
881                                                cat("{ /* else */ }"))}))),
882            Input, Expected);
883 }
884 
TEST_F(TransformerTest,OrderedRuleUnrelated)885 TEST_F(TransformerTest, OrderedRuleUnrelated) {
886   StringRef Flag = "flag";
887   RewriteRule FlagRule = makeRule(
888       cxxMemberCallExpr(on(expr(hasType(cxxRecordDecl(
889                                     hasName("proto::ProtoCommandLineFlag"))))
890                                .bind(Flag)),
891                         unless(callee(cxxMethodDecl(hasName("GetProto"))))),
892       changeTo(node(std::string(Flag)), cat("PROTO")));
893 
894   std::string Input = R"cc(
895     proto::ProtoCommandLineFlag flag;
896     int x = flag.foo();
897     int y = flag.GetProto().foo();
898     int f(string s) { return strlen(s.c_str()); }
899   )cc";
900   std::string Expected = R"cc(
901     proto::ProtoCommandLineFlag flag;
902     int x = PROTO.foo();
903     int y = flag.GetProto().foo();
904     int f(string s) { return REPLACED; }
905   )cc";
906 
907   testRule(applyFirst({ruleStrlenSize(), FlagRule}), Input, Expected);
908 }
909 
TEST_F(TransformerTest,OrderedRuleRelated)910 TEST_F(TransformerTest, OrderedRuleRelated) {
911   std::string Input = R"cc(
912     void f1();
913     void f2();
914     void call_f1() { f1(); }
915     void call_f2() { f2(); }
916   )cc";
917   std::string Expected = R"cc(
918     void f1();
919     void f2();
920     void call_f1() { REPLACE_F1; }
921     void call_f2() { REPLACE_F1_OR_F2; }
922   )cc";
923 
924   RewriteRule ReplaceF1 =
925       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
926                changeTo(cat("REPLACE_F1")));
927   RewriteRule ReplaceF1OrF2 =
928       makeRule(callExpr(callee(functionDecl(hasAnyName("f1", "f2")))),
929                changeTo(cat("REPLACE_F1_OR_F2")));
930   testRule(applyFirst({ReplaceF1, ReplaceF1OrF2}), Input, Expected);
931 }
932 
933 // Change the order of the rules to get a different result. When `ReplaceF1OrF2`
934 // comes first, it applies for both uses, so `ReplaceF1` never applies.
TEST_F(TransformerTest,OrderedRuleRelatedSwapped)935 TEST_F(TransformerTest, OrderedRuleRelatedSwapped) {
936   std::string Input = R"cc(
937     void f1();
938     void f2();
939     void call_f1() { f1(); }
940     void call_f2() { f2(); }
941   )cc";
942   std::string Expected = R"cc(
943     void f1();
944     void f2();
945     void call_f1() { REPLACE_F1_OR_F2; }
946     void call_f2() { REPLACE_F1_OR_F2; }
947   )cc";
948 
949   RewriteRule ReplaceF1 =
950       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
951                changeTo(cat("REPLACE_F1")));
952   RewriteRule ReplaceF1OrF2 =
953       makeRule(callExpr(callee(functionDecl(hasAnyName("f1", "f2")))),
954                changeTo(cat("REPLACE_F1_OR_F2")));
955   testRule(applyFirst({ReplaceF1OrF2, ReplaceF1}), Input, Expected);
956 }
957 
958 // Verify that a set of rules whose matchers have different base kinds works
959 // properly, including that `applyFirst` produces multiple matchers.  We test
960 // two different kinds of rules: Expr and Decl. We place the Decl rule in the
961 // middle to test that `buildMatchers` works even when the kinds aren't grouped
962 // together.
TEST_F(TransformerTest,OrderedRuleMultipleKinds)963 TEST_F(TransformerTest, OrderedRuleMultipleKinds) {
964   std::string Input = R"cc(
965     void f1();
966     void f2();
967     void call_f1() { f1(); }
968     void call_f2() { f2(); }
969   )cc";
970   std::string Expected = R"cc(
971     void f1();
972     void DECL_RULE();
973     void call_f1() { REPLACE_F1; }
974     void call_f2() { REPLACE_F1_OR_F2; }
975   )cc";
976 
977   RewriteRule ReplaceF1 =
978       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
979                changeTo(cat("REPLACE_F1")));
980   RewriteRule ReplaceF1OrF2 =
981       makeRule(callExpr(callee(functionDecl(hasAnyName("f1", "f2")))),
982                changeTo(cat("REPLACE_F1_OR_F2")));
983   RewriteRule DeclRule = makeRule(functionDecl(hasName("f2")).bind("fun"),
984                                   changeTo(name("fun"), cat("DECL_RULE")));
985 
986   RewriteRule Rule = applyFirst({ReplaceF1, DeclRule, ReplaceF1OrF2});
987   EXPECT_EQ(transformer::detail::buildMatchers(Rule).size(), 2UL);
988   testRule(Rule, Input, Expected);
989 }
990 
991 // Verifies that a rule with a top-level matcher for an implicit node (like
992 // `implicitCastExpr`) works correctly -- the implicit nodes are not skipped.
TEST_F(TransformerTest,OrderedRuleImplicitMatched)993 TEST_F(TransformerTest, OrderedRuleImplicitMatched) {
994   std::string Input = R"cc(
995     void f1();
996     int f2();
997     void call_f1() { f1(); }
998     float call_f2() { return f2(); }
999   )cc";
1000   std::string Expected = R"cc(
1001     void f1();
1002     int f2();
1003     void call_f1() { REPLACE_F1; }
1004     float call_f2() { return REPLACE_F2; }
1005   )cc";
1006 
1007   RewriteRule ReplaceF1 =
1008       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
1009                changeTo(cat("REPLACE_F1")));
1010   RewriteRule ReplaceF2 =
1011       makeRule(implicitCastExpr(hasSourceExpression(callExpr())),
1012                changeTo(cat("REPLACE_F2")));
1013   testRule(applyFirst({ReplaceF1, ReplaceF2}), Input, Expected);
1014 }
1015 
1016 //
1017 // Negative tests (where we expect no transformation to occur).
1018 //
1019 
1020 // Tests for a conflict in edits from a single match for a rule.
TEST_F(TransformerTest,TextGeneratorFailure)1021 TEST_F(TransformerTest, TextGeneratorFailure) {
1022   std::string Input = "int conflictOneRule() { return 3 + 7; }";
1023   // Try to change the whole binary-operator expression AND one its operands:
1024   StringRef O = "O";
1025   class AlwaysFail : public transformer::MatchComputation<std::string> {
1026     llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &,
1027                      std::string *) const override {
1028       return llvm::createStringError(llvm::errc::invalid_argument, "ERROR");
1029     }
1030     std::string toString() const override { return "AlwaysFail"; }
1031   };
1032   Transformer T(
1033       makeRule(binaryOperator().bind(O),
1034                changeTo(node(std::string(O)), std::make_shared<AlwaysFail>())),
1035       consumer());
1036   T.registerMatchers(&MatchFinder);
1037   EXPECT_FALSE(rewrite(Input));
1038   EXPECT_THAT(Changes, IsEmpty());
1039   EXPECT_EQ(ErrorCount, 1);
1040 }
1041 
1042 // Tests for a conflict in edits from a single match for a rule.
TEST_F(TransformerTest,OverlappingEditsInRule)1043 TEST_F(TransformerTest, OverlappingEditsInRule) {
1044   std::string Input = "int conflictOneRule() { return 3 + 7; }";
1045   // Try to change the whole binary-operator expression AND one its operands:
1046   StringRef O = "O", L = "L";
1047   Transformer T(makeRule(binaryOperator(hasLHS(expr().bind(L))).bind(O),
1048                          {changeTo(node(std::string(O)), cat("DELETE_OP")),
1049                           changeTo(node(std::string(L)), cat("DELETE_LHS"))}),
1050                 consumer());
1051   T.registerMatchers(&MatchFinder);
1052   EXPECT_FALSE(rewrite(Input));
1053   EXPECT_THAT(Changes, IsEmpty());
1054   EXPECT_EQ(ErrorCount, 1);
1055 }
1056 
1057 // Tests for a conflict in edits across multiple matches (of the same rule).
TEST_F(TransformerTest,OverlappingEditsMultipleMatches)1058 TEST_F(TransformerTest, OverlappingEditsMultipleMatches) {
1059   std::string Input = "int conflictOneRule() { return -7; }";
1060   // Try to change the whole binary-operator expression AND one its operands:
1061   StringRef E = "E";
1062   Transformer T(makeRule(expr().bind(E),
1063                          changeTo(node(std::string(E)), cat("DELETE_EXPR"))),
1064                 consumer());
1065   T.registerMatchers(&MatchFinder);
1066   // The rewrite process fails because the changes conflict with each other...
1067   EXPECT_FALSE(rewrite(Input));
1068   // ... but two changes were produced.
1069   EXPECT_EQ(Changes.size(), 2u);
1070   EXPECT_EQ(ErrorCount, 0);
1071 }
1072 
TEST_F(TransformerTest,ErrorOccurredMatchSkipped)1073 TEST_F(TransformerTest, ErrorOccurredMatchSkipped) {
1074   // Syntax error in the function body:
1075   std::string Input = "void errorOccurred() { 3 }";
1076   Transformer T(makeRule(functionDecl(hasName("errorOccurred")),
1077                          changeTo(cat("DELETED;"))),
1078                 consumer());
1079   T.registerMatchers(&MatchFinder);
1080   // The rewrite process itself fails...
1081   EXPECT_FALSE(rewrite(Input));
1082   // ... and no changes or errors are produced in the process.
1083   EXPECT_THAT(Changes, IsEmpty());
1084   EXPECT_EQ(ErrorCount, 0);
1085 }
1086 
TEST_F(TransformerTest,ImplicitNodes_ConstructorDecl)1087 TEST_F(TransformerTest, ImplicitNodes_ConstructorDecl) {
1088 
1089   std::string OtherStructPrefix = R"cpp(
1090 struct Other {
1091 )cpp";
1092   std::string OtherStructSuffix = "};";
1093 
1094   std::string CopyableStructName = "struct Copyable";
1095   std::string BrokenStructName = "struct explicit Copyable";
1096 
1097   std::string CodeSuffix = R"cpp(
1098 {
1099     Other m_i;
1100     Copyable();
1101 };
1102 )cpp";
1103 
1104   std::string CopyCtor = "Other(const Other&) = default;";
1105   std::string ExplicitCopyCtor = "explicit Other(const Other&) = default;";
1106   std::string BrokenExplicitCopyCtor =
1107       "explicit explicit explicit Other(const Other&) = default;";
1108 
1109   std::string RewriteInput = OtherStructPrefix + CopyCtor + OtherStructSuffix +
1110                              CopyableStructName + CodeSuffix;
1111   std::string ExpectedRewriteOutput = OtherStructPrefix + ExplicitCopyCtor +
1112                                       OtherStructSuffix + CopyableStructName +
1113                                       CodeSuffix;
1114   std::string BrokenRewriteOutput = OtherStructPrefix + BrokenExplicitCopyCtor +
1115                                     OtherStructSuffix + BrokenStructName +
1116                                     CodeSuffix;
1117 
1118   auto MatchedRecord =
1119       cxxConstructorDecl(isCopyConstructor()).bind("copyConstructor");
1120 
1121   auto RewriteRule =
1122       changeTo(before(node("copyConstructor")), cat("explicit "));
1123 
1124   testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedRecord),
1125                     RewriteRule),
1126            RewriteInput, ExpectedRewriteOutput);
1127 
1128   testRule(makeRule(traverse(TK_AsIs, MatchedRecord), RewriteRule),
1129            RewriteInput, BrokenRewriteOutput);
1130 }
1131 
TEST_F(TransformerTest,ImplicitNodes_RangeFor)1132 TEST_F(TransformerTest, ImplicitNodes_RangeFor) {
1133 
1134   std::string CodePrefix = R"cpp(
1135 struct Container
1136 {
1137     int* begin() const;
1138     int* end() const;
1139     int* cbegin() const;
1140     int* cend() const;
1141 };
1142 
1143 void foo()
1144 {
1145   const Container c;
1146 )cpp";
1147 
1148   std::string BeginCallBefore = "  c.begin();";
1149   std::string BeginCallAfter = "  c.cbegin();";
1150 
1151   std::string ForLoop = "for (auto i : c)";
1152   std::string BrokenForLoop = "for (auto i :.cbegin() c)";
1153 
1154   std::string CodeSuffix = R"cpp(
1155   {
1156   }
1157 }
1158 )cpp";
1159 
1160   std::string RewriteInput =
1161       CodePrefix + BeginCallBefore + ForLoop + CodeSuffix;
1162   std::string ExpectedRewriteOutput =
1163       CodePrefix + BeginCallAfter + ForLoop + CodeSuffix;
1164   std::string BrokenRewriteOutput =
1165       CodePrefix + BeginCallAfter + BrokenForLoop + CodeSuffix;
1166 
1167   auto MatchedRecord =
1168       cxxMemberCallExpr(on(expr(hasType(qualType(isConstQualified(),
1169                                                  hasDeclaration(cxxRecordDecl(
1170                                                      hasName("Container"))))))
1171                                .bind("callTarget")),
1172                         callee(cxxMethodDecl(hasName("begin"))))
1173           .bind("constBeginCall");
1174 
1175   auto RewriteRule =
1176       changeTo(node("constBeginCall"), cat(name("callTarget"), ".cbegin()"));
1177 
1178   testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedRecord),
1179                     RewriteRule),
1180            RewriteInput, ExpectedRewriteOutput);
1181 
1182   testRule(makeRule(traverse(TK_AsIs, MatchedRecord), RewriteRule),
1183            RewriteInput, BrokenRewriteOutput);
1184 }
1185 
TEST_F(TransformerTest,ImplicitNodes_ForStmt)1186 TEST_F(TransformerTest, ImplicitNodes_ForStmt) {
1187 
1188   std::string CodePrefix = R"cpp(
1189 struct NonTrivial {
1190     NonTrivial() {}
1191     NonTrivial(NonTrivial&) {}
1192     NonTrivial& operator=(NonTrivial const&) { return *this; }
1193 
1194     ~NonTrivial() {}
1195 };
1196 
1197 struct ContainsArray {
1198     NonTrivial arr[2];
1199     ContainsArray& operator=(ContainsArray const&) = default;
1200 };
1201 
1202 void testIt()
1203 {
1204     ContainsArray ca1;
1205     ContainsArray ca2;
1206     ca2 = ca1;
1207 )cpp";
1208 
1209   auto CodeSuffix = "}";
1210 
1211   auto LoopBody = R"cpp(
1212     {
1213 
1214     }
1215 )cpp";
1216 
1217   auto RawLoop = "for (auto i = 0; i != 5; ++i)";
1218 
1219   auto RangeLoop = "for (auto i : boost::irange(5))";
1220 
1221   // Expect to rewrite the raw loop to the ranged loop.
1222   // This works in TK_IgnoreUnlessSpelledInSource mode, but TK_AsIs
1223   // mode also matches the hidden for loop generated in the copy assignment
1224   // operator of ContainsArray. Transformer then fails to transform the code at
1225   // all.
1226 
1227   auto RewriteInput =
1228       CodePrefix + RawLoop + LoopBody + RawLoop + LoopBody + CodeSuffix;
1229 
1230   auto RewriteOutput =
1231       CodePrefix + RangeLoop + LoopBody + RangeLoop + LoopBody + CodeSuffix;
1232 
1233     auto MatchedLoop = forStmt(
1234         has(declStmt(
1235             hasSingleDecl(varDecl(hasInitializer(integerLiteral(equals(0))))
1236                               .bind("loopVar")))),
1237         has(binaryOperator(hasOperatorName("!="),
1238                            hasLHS(ignoringImplicit(declRefExpr(
1239                                to(varDecl(equalsBoundNode("loopVar")))))),
1240                            hasRHS(expr().bind("upperBoundExpr")))),
1241         has(unaryOperator(hasOperatorName("++"),
1242                           hasUnaryOperand(declRefExpr(
1243                               to(varDecl(equalsBoundNode("loopVar"))))))
1244                 .bind("incrementOp")));
1245 
1246     auto RewriteRule =
1247         changeTo(transformer::enclose(node("loopVar"), node("incrementOp")),
1248                  cat("auto ", name("loopVar"), " : boost::irange(",
1249                      node("upperBoundExpr"), ")"));
1250 
1251     testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedLoop),
1252                       RewriteRule),
1253              RewriteInput, RewriteOutput);
1254 
1255     testRuleFailure(makeRule(traverse(TK_AsIs, MatchedLoop), RewriteRule),
1256                     RewriteInput);
1257 
1258 }
1259 
TEST_F(TransformerTest,ImplicitNodes_ForStmt2)1260 TEST_F(TransformerTest, ImplicitNodes_ForStmt2) {
1261 
1262   std::string CodePrefix = R"cpp(
1263 struct NonTrivial {
1264     NonTrivial() {}
1265     NonTrivial(NonTrivial&) {}
1266     NonTrivial& operator=(NonTrivial const&) { return *this; }
1267 
1268     ~NonTrivial() {}
1269 };
1270 
1271 struct ContainsArray {
1272     NonTrivial arr[2];
1273     ContainsArray& operator=(ContainsArray const&) = default;
1274 };
1275 
1276 void testIt()
1277 {
1278     ContainsArray ca1;
1279     ContainsArray ca2;
1280     ca2 = ca1;
1281 )cpp";
1282 
1283   auto CodeSuffix = "}";
1284 
1285   auto LoopBody = R"cpp(
1286     {
1287 
1288     }
1289 )cpp";
1290 
1291   auto RawLoop = "for (auto i = 0; i != 5; ++i)";
1292 
1293   auto RangeLoop = "for (auto i : boost::irange(5))";
1294 
1295   // Expect to rewrite the raw loop to the ranged loop.
1296   // This works in TK_IgnoreUnlessSpelledInSource mode, but TK_AsIs
1297   // mode also matches the hidden for loop generated in the copy assignment
1298   // operator of ContainsArray. Transformer then fails to transform the code at
1299   // all.
1300 
1301   auto RewriteInput =
1302       CodePrefix + RawLoop + LoopBody + RawLoop + LoopBody + CodeSuffix;
1303 
1304   auto RewriteOutput =
1305       CodePrefix + RangeLoop + LoopBody + RangeLoop + LoopBody + CodeSuffix;
1306     auto MatchedLoop = forStmt(
1307         hasLoopInit(declStmt(
1308             hasSingleDecl(varDecl(hasInitializer(integerLiteral(equals(0))))
1309                               .bind("loopVar")))),
1310         hasCondition(binaryOperator(hasOperatorName("!="),
1311                                     hasLHS(ignoringImplicit(declRefExpr(to(
1312                                         varDecl(equalsBoundNode("loopVar")))))),
1313                                     hasRHS(expr().bind("upperBoundExpr")))),
1314         hasIncrement(unaryOperator(hasOperatorName("++"),
1315                                    hasUnaryOperand(declRefExpr(to(
1316                                        varDecl(equalsBoundNode("loopVar"))))))
1317                          .bind("incrementOp")));
1318 
1319     auto RewriteRule =
1320         changeTo(transformer::enclose(node("loopVar"), node("incrementOp")),
1321                  cat("auto ", name("loopVar"), " : boost::irange(",
1322                      node("upperBoundExpr"), ")"));
1323 
1324     testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedLoop),
1325                       RewriteRule),
1326              RewriteInput, RewriteOutput);
1327 
1328     testRuleFailure(makeRule(traverse(TK_AsIs, MatchedLoop), RewriteRule),
1329                     RewriteInput);
1330 
1331 }
1332 
TEST_F(TransformerTest,TemplateInstantiation)1333 TEST_F(TransformerTest, TemplateInstantiation) {
1334 
1335   std::string NonTemplatesInput = R"cpp(
1336 struct S {
1337   int m_i;
1338 };
1339 )cpp";
1340   std::string NonTemplatesExpected = R"cpp(
1341 struct S {
1342   safe_int m_i;
1343 };
1344 )cpp";
1345 
1346   std::string TemplatesInput = R"cpp(
1347 template<typename T>
1348 struct TemplStruct {
1349   TemplStruct() {}
1350   ~TemplStruct() {}
1351 
1352 private:
1353   T m_t;
1354 };
1355 
1356 void instantiate()
1357 {
1358   TemplStruct<int> ti;
1359 }
1360 )cpp";
1361 
1362   auto MatchedField = fieldDecl(hasType(asString("int"))).bind("theField");
1363 
1364   // Changes the 'int' in 'S', but not the 'T' in 'TemplStruct':
1365   testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedField),
1366                     changeTo(cat("safe_int ", name("theField"), ";"))),
1367            NonTemplatesInput + TemplatesInput,
1368            NonTemplatesExpected + TemplatesInput);
1369 
1370   // In AsIs mode, template instantiations are modified, which is
1371   // often not desired:
1372 
1373   std::string IncorrectTemplatesExpected = R"cpp(
1374 template<typename T>
1375 struct TemplStruct {
1376   TemplStruct() {}
1377   ~TemplStruct() {}
1378 
1379 private:
1380   safe_int m_t;
1381 };
1382 
1383 void instantiate()
1384 {
1385   TemplStruct<int> ti;
1386 }
1387 )cpp";
1388 
1389   // Changes the 'int' in 'S', and (incorrectly) the 'T' in 'TemplStruct':
1390   testRule(makeRule(traverse(TK_AsIs, MatchedField),
1391                     changeTo(cat("safe_int ", name("theField"), ";"))),
1392 
1393            NonTemplatesInput + TemplatesInput,
1394            NonTemplatesExpected + IncorrectTemplatesExpected);
1395 }
1396 
1397 // Transformation of macro source text when the change encompasses the entirety
1398 // of the expanded text.
TEST_F(TransformerTest,SimpleMacro)1399 TEST_F(TransformerTest, SimpleMacro) {
1400   std::string Input = R"cc(
1401 #define ZERO 0
1402     int f(string s) { return ZERO; }
1403   )cc";
1404   std::string Expected = R"cc(
1405 #define ZERO 0
1406     int f(string s) { return 999; }
1407   )cc";
1408 
1409   StringRef zero = "zero";
1410   RewriteRule R = makeRule(integerLiteral(equals(0)).bind(zero),
1411                            changeTo(node(std::string(zero)), cat("999")));
1412   testRule(R, Input, Expected);
1413 }
1414 
1415 // Transformation of macro source text when the change encompasses the entirety
1416 // of the expanded text, for the case of function-style macros.
TEST_F(TransformerTest,FunctionMacro)1417 TEST_F(TransformerTest, FunctionMacro) {
1418   std::string Input = R"cc(
1419 #define MACRO(str) strlen((str).c_str())
1420     int f(string s) { return MACRO(s); }
1421   )cc";
1422   std::string Expected = R"cc(
1423 #define MACRO(str) strlen((str).c_str())
1424     int f(string s) { return REPLACED; }
1425   )cc";
1426 
1427   testRule(ruleStrlenSize(), Input, Expected);
1428 }
1429 
1430 // Tests that expressions in macro arguments can be rewritten.
TEST_F(TransformerTest,MacroArg)1431 TEST_F(TransformerTest, MacroArg) {
1432   std::string Input = R"cc(
1433 #define PLUS(e) e + 1
1434     int f(string s) { return PLUS(strlen(s.c_str())); }
1435   )cc";
1436   std::string Expected = R"cc(
1437 #define PLUS(e) e + 1
1438     int f(string s) { return PLUS(REPLACED); }
1439   )cc";
1440 
1441   testRule(ruleStrlenSize(), Input, Expected);
1442 }
1443 
1444 // Tests that expressions in macro arguments can be rewritten, even when the
1445 // macro call occurs inside another macro's definition.
TEST_F(TransformerTest,MacroArgInMacroDef)1446 TEST_F(TransformerTest, MacroArgInMacroDef) {
1447   std::string Input = R"cc(
1448 #define NESTED(e) e
1449 #define MACRO(str) NESTED(strlen((str).c_str()))
1450     int f(string s) { return MACRO(s); }
1451   )cc";
1452   std::string Expected = R"cc(
1453 #define NESTED(e) e
1454 #define MACRO(str) NESTED(strlen((str).c_str()))
1455     int f(string s) { return REPLACED; }
1456   )cc";
1457 
1458   testRule(ruleStrlenSize(), Input, Expected);
1459 }
1460 
1461 // Tests the corner case of the identity macro, specifically that it is
1462 // discarded in the rewrite rather than preserved (like PLUS is preserved in the
1463 // previous test).  This behavior is of dubious value (and marked with a FIXME
1464 // in the code), but we test it to verify (and demonstrate) how this case is
1465 // handled.
TEST_F(TransformerTest,IdentityMacro)1466 TEST_F(TransformerTest, IdentityMacro) {
1467   std::string Input = R"cc(
1468 #define ID(e) e
1469     int f(string s) { return ID(strlen(s.c_str())); }
1470   )cc";
1471   std::string Expected = R"cc(
1472 #define ID(e) e
1473     int f(string s) { return REPLACED; }
1474   )cc";
1475 
1476   testRule(ruleStrlenSize(), Input, Expected);
1477 }
1478 
1479 // Tests that two changes in a single macro expansion do not lead to conflicts
1480 // in applying the changes.
TEST_F(TransformerTest,TwoChangesInOneMacroExpansion)1481 TEST_F(TransformerTest, TwoChangesInOneMacroExpansion) {
1482   std::string Input = R"cc(
1483 #define PLUS(a,b) (a) + (b)
1484     int f() { return PLUS(3, 4); }
1485   )cc";
1486   std::string Expected = R"cc(
1487 #define PLUS(a,b) (a) + (b)
1488     int f() { return PLUS(LIT, LIT); }
1489   )cc";
1490 
1491   testRule(makeRule(integerLiteral(), changeTo(cat("LIT"))), Input, Expected);
1492 }
1493 
1494 // Tests case where the rule's match spans both source from the macro and its
1495 // arg, with the begin location (the "anchor") being the arg.
TEST_F(TransformerTest,MatchSpansMacroTextButChangeDoesNot)1496 TEST_F(TransformerTest, MatchSpansMacroTextButChangeDoesNot) {
1497   std::string Input = R"cc(
1498 #define PLUS_ONE(a) a + 1
1499     int f() { return PLUS_ONE(3); }
1500   )cc";
1501   std::string Expected = R"cc(
1502 #define PLUS_ONE(a) a + 1
1503     int f() { return PLUS_ONE(LIT); }
1504   )cc";
1505 
1506   StringRef E = "expr";
1507   testRule(makeRule(binaryOperator(hasLHS(expr().bind(E))),
1508                     changeTo(node(std::string(E)), cat("LIT"))),
1509            Input, Expected);
1510 }
1511 
1512 // Tests case where the rule's match spans both source from the macro and its
1513 // arg, with the begin location (the "anchor") being inside the macro.
TEST_F(TransformerTest,MatchSpansMacroTextButChangeDoesNotAnchoredInMacro)1514 TEST_F(TransformerTest, MatchSpansMacroTextButChangeDoesNotAnchoredInMacro) {
1515   std::string Input = R"cc(
1516 #define PLUS_ONE(a) 1 + a
1517     int f() { return PLUS_ONE(3); }
1518   )cc";
1519   std::string Expected = R"cc(
1520 #define PLUS_ONE(a) 1 + a
1521     int f() { return PLUS_ONE(LIT); }
1522   )cc";
1523 
1524   StringRef E = "expr";
1525   testRule(makeRule(binaryOperator(hasRHS(expr().bind(E))),
1526                     changeTo(node(std::string(E)), cat("LIT"))),
1527            Input, Expected);
1528 }
1529 
1530 // No rewrite is applied when the changed text does not encompass the entirety
1531 // of the expanded text. That is, the edit would have to be applied to the
1532 // macro's definition to succeed and editing the expansion point would not
1533 // suffice.
TEST_F(TransformerTest,NoPartialRewriteOMacroExpansion)1534 TEST_F(TransformerTest, NoPartialRewriteOMacroExpansion) {
1535   std::string Input = R"cc(
1536 #define ZERO_PLUS 0 + 3
1537     int f(string s) { return ZERO_PLUS; })cc";
1538 
1539   StringRef zero = "zero";
1540   RewriteRule R = makeRule(integerLiteral(equals(0)).bind(zero),
1541                            changeTo(node(std::string(zero)), cat("0")));
1542   testRule(R, Input, Input);
1543 }
1544 
1545 // This test handles the corner case where a macro expands within another macro
1546 // to matching code, but that code is an argument to the nested macro call.  A
1547 // simple check of isMacroArgExpansion() vs. isMacroBodyExpansion() will get
1548 // this wrong, and transform the code.
TEST_F(TransformerTest,NoPartialRewriteOfMacroExpansionForMacroArgs)1549 TEST_F(TransformerTest, NoPartialRewriteOfMacroExpansionForMacroArgs) {
1550   std::string Input = R"cc(
1551 #define NESTED(e) e
1552 #define MACRO(str) 1 + NESTED(strlen((str).c_str()))
1553     int f(string s) { return MACRO(s); }
1554   )cc";
1555 
1556   testRule(ruleStrlenSize(), Input, Input);
1557 }
1558 
1559 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1560 // Verifies that `Type` and `QualType` are not allowed as top-level matchers in
1561 // rules.
TEST(TransformerDeathTest,OrderedRuleTypes)1562 TEST(TransformerDeathTest, OrderedRuleTypes) {
1563   RewriteRule QualTypeRule = makeRule(qualType(), changeTo(cat("Q")));
1564   EXPECT_DEATH(transformer::detail::buildMatchers(QualTypeRule),
1565                "Matcher must be.*node matcher");
1566 
1567   RewriteRule TypeRule = makeRule(arrayType(), changeTo(cat("T")));
1568   EXPECT_DEATH(transformer::detail::buildMatchers(TypeRule),
1569                "Matcher must be.*node matcher");
1570 }
1571 #endif
1572 
1573 // Edits are able to span multiple files; in this case, a header and an
1574 // implementation file.
TEST_F(TransformerTest,MultipleFiles)1575 TEST_F(TransformerTest, MultipleFiles) {
1576   std::string Header = R"cc(void RemoveThisFunction();)cc";
1577   std::string Source = R"cc(#include "input.h"
1578                             void RemoveThisFunction();)cc";
1579   Transformer T(
1580       makeRule(functionDecl(hasName("RemoveThisFunction")), changeTo(cat(""))),
1581       consumer());
1582   T.registerMatchers(&MatchFinder);
1583   auto Factory = newFrontendActionFactory(&MatchFinder);
1584   EXPECT_TRUE(runToolOnCodeWithArgs(
1585       Factory->create(), Source, std::vector<std::string>(), "input.cc",
1586       "clang-tool", std::make_shared<PCHContainerOperations>(),
1587       {{"input.h", Header}}));
1588 
1589   std::sort(Changes.begin(), Changes.end(),
1590             [](const AtomicChange &L, const AtomicChange &R) {
1591               return L.getFilePath() < R.getFilePath();
1592             });
1593 
1594   ASSERT_EQ(Changes[0].getFilePath(), "./input.h");
1595   EXPECT_THAT(Changes[0].getInsertedHeaders(), IsEmpty());
1596   EXPECT_THAT(Changes[0].getRemovedHeaders(), IsEmpty());
1597   llvm::Expected<std::string> UpdatedCode =
1598       clang::tooling::applyAllReplacements(Header,
1599                                            Changes[0].getReplacements());
1600   ASSERT_TRUE(static_cast<bool>(UpdatedCode))
1601       << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
1602   EXPECT_EQ(format(*UpdatedCode), "");
1603 
1604   ASSERT_EQ(Changes[1].getFilePath(), "input.cc");
1605   EXPECT_THAT(Changes[1].getInsertedHeaders(), IsEmpty());
1606   EXPECT_THAT(Changes[1].getRemovedHeaders(), IsEmpty());
1607   UpdatedCode = clang::tooling::applyAllReplacements(
1608       Source, Changes[1].getReplacements());
1609   ASSERT_TRUE(static_cast<bool>(UpdatedCode))
1610       << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
1611   EXPECT_EQ(format(*UpdatedCode), format("#include \"input.h\"\n"));
1612 }
1613 
TEST_F(TransformerTest,AddIncludeMultipleFiles)1614 TEST_F(TransformerTest, AddIncludeMultipleFiles) {
1615   std::string Header = R"cc(void RemoveThisFunction();)cc";
1616   std::string Source = R"cc(#include "input.h"
1617                             void Foo() {RemoveThisFunction();})cc";
1618   Transformer T(
1619       makeRule(callExpr(callee(
1620                    functionDecl(hasName("RemoveThisFunction")).bind("fun"))),
1621                addInclude(node("fun"), "header.h")),
1622       consumer());
1623   T.registerMatchers(&MatchFinder);
1624   auto Factory = newFrontendActionFactory(&MatchFinder);
1625   EXPECT_TRUE(runToolOnCodeWithArgs(
1626       Factory->create(), Source, std::vector<std::string>(), "input.cc",
1627       "clang-tool", std::make_shared<PCHContainerOperations>(),
1628       {{"input.h", Header}}));
1629 
1630   ASSERT_EQ(Changes.size(), 1U);
1631   ASSERT_EQ(Changes[0].getFilePath(), "./input.h");
1632   EXPECT_THAT(Changes[0].getInsertedHeaders(), ElementsAre("header.h"));
1633   EXPECT_THAT(Changes[0].getRemovedHeaders(), IsEmpty());
1634   llvm::Expected<std::string> UpdatedCode =
1635       clang::tooling::applyAllReplacements(Header,
1636                                            Changes[0].getReplacements());
1637   ASSERT_TRUE(static_cast<bool>(UpdatedCode))
1638       << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
1639   EXPECT_EQ(format(*UpdatedCode), format(Header));
1640 }
1641 } // namespace
1642