11588c087SYitzhak Mandelbaum //===- unittest/Tooling/SourceCodeBuildersTest.cpp ------------------------===//
21588c087SYitzhak Mandelbaum //
31588c087SYitzhak Mandelbaum // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41588c087SYitzhak Mandelbaum // See https://llvm.org/LICENSE.txt for license information.
51588c087SYitzhak Mandelbaum // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61588c087SYitzhak Mandelbaum //
71588c087SYitzhak Mandelbaum //===----------------------------------------------------------------------===//
81588c087SYitzhak Mandelbaum 
9fbdf8352SYitzhak Mandelbaum #include "clang/Tooling/Transformer/SourceCodeBuilders.h"
10*0944c196SYitzhak Mandelbaum #include "clang/AST/Type.h"
111588c087SYitzhak Mandelbaum #include "clang/ASTMatchers/ASTMatchFinder.h"
121588c087SYitzhak Mandelbaum #include "clang/ASTMatchers/ASTMatchers.h"
131588c087SYitzhak Mandelbaum #include "clang/Tooling/Tooling.h"
141588c087SYitzhak Mandelbaum #include "llvm/Testing/Support/SupportHelpers.h"
151588c087SYitzhak Mandelbaum #include "gmock/gmock.h"
161588c087SYitzhak Mandelbaum #include "gtest/gtest.h"
171588c087SYitzhak Mandelbaum 
181588c087SYitzhak Mandelbaum using namespace clang;
191588c087SYitzhak Mandelbaum using namespace tooling;
201588c087SYitzhak Mandelbaum using namespace ast_matchers;
211588c087SYitzhak Mandelbaum 
221588c087SYitzhak Mandelbaum namespace {
231588c087SYitzhak Mandelbaum using MatchResult = MatchFinder::MatchResult;
241588c087SYitzhak Mandelbaum using llvm::ValueIs;
251588c087SYitzhak Mandelbaum 
261588c087SYitzhak Mandelbaum // Create a valid translation unit from a statement.
wrapSnippet(StringRef StatementCode)271588c087SYitzhak Mandelbaum static std::string wrapSnippet(StringRef StatementCode) {
28*0944c196SYitzhak Mandelbaum   return ("namespace std {\n"
29*0944c196SYitzhak Mandelbaum           "template <typename T> struct unique_ptr {\n"
30*0944c196SYitzhak Mandelbaum           "  T* operator->() const;\n"
31*0944c196SYitzhak Mandelbaum           "  T& operator*() const;\n"
32*0944c196SYitzhak Mandelbaum           "};\n"
33*0944c196SYitzhak Mandelbaum           "template <typename T> struct shared_ptr {\n"
34*0944c196SYitzhak Mandelbaum           "  T* operator->() const;\n"
35*0944c196SYitzhak Mandelbaum           "  T& operator*() const;\n"
36*0944c196SYitzhak Mandelbaum           "};\n"
37*0944c196SYitzhak Mandelbaum           "}\n"
38*0944c196SYitzhak Mandelbaum           "struct A { void super(); };\n"
39*0944c196SYitzhak Mandelbaum           "struct S : public A { S(); S(int); int Field; };\n"
401588c087SYitzhak Mandelbaum           "S operator+(const S &a, const S &b);\n"
41*0944c196SYitzhak Mandelbaum           "struct Smart {\n"
42*0944c196SYitzhak Mandelbaum           "  S* operator->() const;\n"
43*0944c196SYitzhak Mandelbaum           "  S& operator*() const;\n"
44*0944c196SYitzhak Mandelbaum           "};\n"
451588c087SYitzhak Mandelbaum           "auto test_snippet = []{" +
461588c087SYitzhak Mandelbaum           StatementCode + "};")
471588c087SYitzhak Mandelbaum       .str();
481588c087SYitzhak Mandelbaum }
491588c087SYitzhak Mandelbaum 
wrapMatcher(const StatementMatcher & Matcher)501588c087SYitzhak Mandelbaum static DeclarationMatcher wrapMatcher(const StatementMatcher &Matcher) {
511588c087SYitzhak Mandelbaum   return varDecl(hasName("test_snippet"),
521588c087SYitzhak Mandelbaum                  hasDescendant(compoundStmt(hasAnySubstatement(Matcher))));
531588c087SYitzhak Mandelbaum }
541588c087SYitzhak Mandelbaum 
551588c087SYitzhak Mandelbaum struct TestMatch {
561588c087SYitzhak Mandelbaum   // The AST unit from which `result` is built. We bundle it because it backs
571588c087SYitzhak Mandelbaum   // the result. Users are not expected to access it.
581588c087SYitzhak Mandelbaum   std::unique_ptr<ASTUnit> AstUnit;
591588c087SYitzhak Mandelbaum   // The result to use in the test. References `ast_unit`.
601588c087SYitzhak Mandelbaum   MatchResult Result;
611588c087SYitzhak Mandelbaum };
621588c087SYitzhak Mandelbaum 
631588c087SYitzhak Mandelbaum // Matches `Matcher` against the statement `StatementCode` and returns the
641588c087SYitzhak Mandelbaum // result. Handles putting the statement inside a function and modifying the
651588c087SYitzhak Mandelbaum // matcher correspondingly. `Matcher` should match one of the statements in
661588c087SYitzhak Mandelbaum // `StatementCode` exactly -- that is, produce exactly one match. However,
671588c087SYitzhak Mandelbaum // `StatementCode` may contain other statements not described by `Matcher`.
matchStmt(StringRef StatementCode,StatementMatcher Matcher)681588c087SYitzhak Mandelbaum static llvm::Optional<TestMatch> matchStmt(StringRef StatementCode,
691588c087SYitzhak Mandelbaum                                            StatementMatcher Matcher) {
70*0944c196SYitzhak Mandelbaum   auto AstUnit = buildASTFromCodeWithArgs(wrapSnippet(StatementCode),
71*0944c196SYitzhak Mandelbaum                                           {"-Wno-unused-value"});
721588c087SYitzhak Mandelbaum   if (AstUnit == nullptr) {
731588c087SYitzhak Mandelbaum     ADD_FAILURE() << "AST construction failed";
741588c087SYitzhak Mandelbaum     return llvm::None;
751588c087SYitzhak Mandelbaum   }
761588c087SYitzhak Mandelbaum   ASTContext &Context = AstUnit->getASTContext();
771588c087SYitzhak Mandelbaum   auto Matches = ast_matchers::match(wrapMatcher(Matcher), Context);
781588c087SYitzhak Mandelbaum   // We expect a single, exact match for the statement.
791588c087SYitzhak Mandelbaum   if (Matches.size() != 1) {
801588c087SYitzhak Mandelbaum     ADD_FAILURE() << "Wrong number of matches: " << Matches.size();
811588c087SYitzhak Mandelbaum     return llvm::None;
821588c087SYitzhak Mandelbaum   }
831588c087SYitzhak Mandelbaum   return TestMatch{std::move(AstUnit), MatchResult(Matches[0], &Context)};
841588c087SYitzhak Mandelbaum }
851588c087SYitzhak Mandelbaum 
testPredicate(bool (* Pred)(const Expr &),StringRef Snippet,bool Expected)861588c087SYitzhak Mandelbaum static void testPredicate(bool (*Pred)(const Expr &), StringRef Snippet,
871588c087SYitzhak Mandelbaum                           bool Expected) {
881588c087SYitzhak Mandelbaum   auto StmtMatch = matchStmt(Snippet, expr().bind("expr"));
891588c087SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
901588c087SYitzhak Mandelbaum   EXPECT_EQ(Expected, Pred(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr")))
911588c087SYitzhak Mandelbaum       << "Snippet: " << Snippet;
921588c087SYitzhak Mandelbaum }
931588c087SYitzhak Mandelbaum 
941588c087SYitzhak Mandelbaum // Tests the predicate on the call argument, assuming `Snippet` is a function
951588c087SYitzhak Mandelbaum // call.
testPredicateOnArg(bool (* Pred)(const Expr &),StringRef Snippet,bool Expected)961588c087SYitzhak Mandelbaum static void testPredicateOnArg(bool (*Pred)(const Expr &), StringRef Snippet,
971588c087SYitzhak Mandelbaum                                bool Expected) {
981588c087SYitzhak Mandelbaum   auto StmtMatch = matchStmt(
991588c087SYitzhak Mandelbaum       Snippet, expr(ignoringImplicit(callExpr(hasArgument(
1001588c087SYitzhak Mandelbaum                    0, ignoringElidableConstructorCall(expr().bind("arg")))))));
1011588c087SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
1021588c087SYitzhak Mandelbaum   EXPECT_EQ(Expected, Pred(*StmtMatch->Result.Nodes.getNodeAs<Expr>("arg")))
1031588c087SYitzhak Mandelbaum       << "Snippet: " << Snippet;
1041588c087SYitzhak Mandelbaum }
1051588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,needParensAfterUnaryOperator)1061588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, needParensAfterUnaryOperator) {
1071588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "3 + 5;", true);
1081588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "true ? 3 : 5;", true);
1091588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "S(3) + S(5);", true);
1101588c087SYitzhak Mandelbaum 
1111588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "int x; x;", false);
1121588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "int(3.0);", false);
1131588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "void f(); f();", false);
1141588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "int a[3]; a[0];", false);
115*0944c196SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "S x; x.Field;", false);
1161588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "int x = 1; --x;", false);
1171588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "int x = 1; -x;", false);
1181588c087SYitzhak Mandelbaum }
1191588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,needParensAfterUnaryOperatorInImplicitConversion)1201588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, needParensAfterUnaryOperatorInImplicitConversion) {
1211588c087SYitzhak Mandelbaum   // The binary operation will be embedded in various implicit
1221588c087SYitzhak Mandelbaum   // expressions. Verify they are ignored.
1231588c087SYitzhak Mandelbaum   testPredicateOnArg(needParensAfterUnaryOperator, "void f(S); f(3 + 5);",
1241588c087SYitzhak Mandelbaum                      true);
1251588c087SYitzhak Mandelbaum }
1261588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,mayEverNeedParens)1271588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, mayEverNeedParens) {
1281588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "3 + 5;", true);
1291588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "true ? 3 : 5;", true);
1301588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "int x = 1; --x;", true);
1311588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "int x = 1; -x;", true);
1321588c087SYitzhak Mandelbaum 
1331588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "int x; x;", false);
1341588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "int(3.0);", false);
1351588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "void f(); f();", false);
1361588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "int a[3]; a[0];", false);
137*0944c196SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "S x; x.Field;", false);
1381588c087SYitzhak Mandelbaum }
1391588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,mayEverNeedParensInImplictConversion)1401588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, mayEverNeedParensInImplictConversion) {
1411588c087SYitzhak Mandelbaum   // The binary operation will be embedded in various implicit
1421588c087SYitzhak Mandelbaum   // expressions. Verify they are ignored.
1431588c087SYitzhak Mandelbaum   testPredicateOnArg(mayEverNeedParens, "void f(S); f(3 + 5);", true);
1441588c087SYitzhak Mandelbaum }
1451588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeUniquePtr)146*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeUniquePtr) {
147*0944c196SYitzhak Mandelbaum   std::string Snippet = "std::unique_ptr<int> P; P;";
148*0944c196SYitzhak Mandelbaum   auto StmtMatch =
149*0944c196SYitzhak Mandelbaum       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
150*0944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
151*0944c196SYitzhak Mandelbaum   EXPECT_TRUE(
152*0944c196SYitzhak Mandelbaum       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
153*0944c196SYitzhak Mandelbaum                              *StmtMatch->Result.Context))
154*0944c196SYitzhak Mandelbaum       << "Snippet: " << Snippet;
155*0944c196SYitzhak Mandelbaum }
156*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeSharedPtr)157*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeSharedPtr) {
158*0944c196SYitzhak Mandelbaum   std::string Snippet = "std::shared_ptr<int> P; P;";
159*0944c196SYitzhak Mandelbaum   auto StmtMatch =
160*0944c196SYitzhak Mandelbaum       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
161*0944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
162*0944c196SYitzhak Mandelbaum   EXPECT_TRUE(
163*0944c196SYitzhak Mandelbaum       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
164*0944c196SYitzhak Mandelbaum                              *StmtMatch->Result.Context))
165*0944c196SYitzhak Mandelbaum       << "Snippet: " << Snippet;
166*0944c196SYitzhak Mandelbaum }
167*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeUnknownTypeFalse)168*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeUnknownTypeFalse) {
169*0944c196SYitzhak Mandelbaum   std::string Snippet = "Smart P; P;";
170*0944c196SYitzhak Mandelbaum   auto StmtMatch =
171*0944c196SYitzhak Mandelbaum       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
172*0944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
173*0944c196SYitzhak Mandelbaum   EXPECT_FALSE(
174*0944c196SYitzhak Mandelbaum       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
175*0944c196SYitzhak Mandelbaum                              *StmtMatch->Result.Context))
176*0944c196SYitzhak Mandelbaum       << "Snippet: " << Snippet;
177*0944c196SYitzhak Mandelbaum }
178*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeNormalTypeFalse)179*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeNormalTypeFalse) {
180*0944c196SYitzhak Mandelbaum   std::string Snippet = "int *P; P;";
181*0944c196SYitzhak Mandelbaum   auto StmtMatch =
182*0944c196SYitzhak Mandelbaum       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
183*0944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
184*0944c196SYitzhak Mandelbaum   EXPECT_FALSE(
185*0944c196SYitzhak Mandelbaum       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
186*0944c196SYitzhak Mandelbaum                              *StmtMatch->Result.Context))
187*0944c196SYitzhak Mandelbaum       << "Snippet: " << Snippet;
188*0944c196SYitzhak Mandelbaum }
189*0944c196SYitzhak Mandelbaum 
testBuilder(llvm::Optional<std::string> (* Builder)(const Expr &,const ASTContext &),StringRef Snippet,StringRef Expected)1901588c087SYitzhak Mandelbaum static void testBuilder(
1911588c087SYitzhak Mandelbaum     llvm::Optional<std::string> (*Builder)(const Expr &, const ASTContext &),
1921588c087SYitzhak Mandelbaum     StringRef Snippet, StringRef Expected) {
1931588c087SYitzhak Mandelbaum   auto StmtMatch = matchStmt(Snippet, expr().bind("expr"));
1941588c087SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
1951588c087SYitzhak Mandelbaum   EXPECT_THAT(Builder(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
1961588c087SYitzhak Mandelbaum                       *StmtMatch->Result.Context),
197adcd0268SBenjamin Kramer               ValueIs(std::string(Expected)));
1981588c087SYitzhak Mandelbaum }
1991588c087SYitzhak Mandelbaum 
testBuildAccess(StringRef Snippet,StringRef Expected,PLTClass C=PLTClass::Pointer)200*0944c196SYitzhak Mandelbaum static void testBuildAccess(StringRef Snippet, StringRef Expected,
201*0944c196SYitzhak Mandelbaum                             PLTClass C = PLTClass::Pointer) {
202*0944c196SYitzhak Mandelbaum   auto StmtMatch = matchStmt(Snippet, expr().bind("expr"));
203*0944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
204*0944c196SYitzhak Mandelbaum   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
205*0944c196SYitzhak Mandelbaum                           *StmtMatch->Result.Context, C),
206*0944c196SYitzhak Mandelbaum               ValueIs(std::string(Expected)));
207*0944c196SYitzhak Mandelbaum }
208*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildParensUnaryOp)2091588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildParensUnaryOp) {
2101588c087SYitzhak Mandelbaum   testBuilder(buildParens, "-4;", "(-4)");
2111588c087SYitzhak Mandelbaum }
2121588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildParensBinOp)2131588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildParensBinOp) {
2141588c087SYitzhak Mandelbaum   testBuilder(buildParens, "4 + 4;", "(4 + 4)");
2151588c087SYitzhak Mandelbaum }
2161588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildParensValue)2171588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildParensValue) {
2181588c087SYitzhak Mandelbaum   testBuilder(buildParens, "4;", "4");
2191588c087SYitzhak Mandelbaum }
2201588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildParensSubscript)2211588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildParensSubscript) {
2221588c087SYitzhak Mandelbaum   testBuilder(buildParens, "int a[3]; a[0];", "a[0]");
2231588c087SYitzhak Mandelbaum }
2241588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildParensCall)2251588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildParensCall) {
2261588c087SYitzhak Mandelbaum   testBuilder(buildParens, "int f(int); f(4);", "f(4)");
2271588c087SYitzhak Mandelbaum }
2281588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAddressOfValue)2291588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAddressOfValue) {
2301588c087SYitzhak Mandelbaum   testBuilder(buildAddressOf, "S x; x;", "&x");
2311588c087SYitzhak Mandelbaum }
2321588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAddressOfPointerDereference)2331588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAddressOfPointerDereference) {
2341588c087SYitzhak Mandelbaum   testBuilder(buildAddressOf, "S *x; *x;", "x");
2351588c087SYitzhak Mandelbaum }
2361588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAddressOfPointerDereferenceIgnoresParens)2371588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAddressOfPointerDereferenceIgnoresParens) {
2381588c087SYitzhak Mandelbaum   testBuilder(buildAddressOf, "S *x; *(x);", "x");
2391588c087SYitzhak Mandelbaum }
2401588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAddressOfBinaryOperation)2411588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAddressOfBinaryOperation) {
2421588c087SYitzhak Mandelbaum   testBuilder(buildAddressOf, "S x; x + x;", "&(x + x)");
2431588c087SYitzhak Mandelbaum }
2441588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAddressOfImplicitThis)245d2e32fa4SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAddressOfImplicitThis) {
246d2e32fa4SYitzhak Mandelbaum   StringRef Snippet = R"cc(
247d2e32fa4SYitzhak Mandelbaum     struct Struct {
248d2e32fa4SYitzhak Mandelbaum       void foo() {}
249d2e32fa4SYitzhak Mandelbaum       void bar() {
250d2e32fa4SYitzhak Mandelbaum         foo();
251d2e32fa4SYitzhak Mandelbaum       }
252d2e32fa4SYitzhak Mandelbaum     };
253d2e32fa4SYitzhak Mandelbaum   )cc";
254d2e32fa4SYitzhak Mandelbaum   auto StmtMatch = matchStmt(
255d2e32fa4SYitzhak Mandelbaum       Snippet,
256d2e32fa4SYitzhak Mandelbaum       cxxMemberCallExpr(onImplicitObjectArgument(cxxThisExpr().bind("expr"))));
257d2e32fa4SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
258d2e32fa4SYitzhak Mandelbaum   EXPECT_THAT(buildAddressOf(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
259d2e32fa4SYitzhak Mandelbaum                              *StmtMatch->Result.Context),
260d2e32fa4SYitzhak Mandelbaum               ValueIs(std::string("this")));
261d2e32fa4SYitzhak Mandelbaum }
262d2e32fa4SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDereferencePointer)2631588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDereferencePointer) {
2641588c087SYitzhak Mandelbaum   testBuilder(buildDereference, "S *x; x;", "*x");
2651588c087SYitzhak Mandelbaum }
2661588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDereferenceValueAddress)2671588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDereferenceValueAddress) {
2681588c087SYitzhak Mandelbaum   testBuilder(buildDereference, "S x; &x;", "x");
2691588c087SYitzhak Mandelbaum }
2701588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDereferenceValueAddressIgnoresParens)2711588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDereferenceValueAddressIgnoresParens) {
2721588c087SYitzhak Mandelbaum   testBuilder(buildDereference, "S x; &(x);", "x");
2731588c087SYitzhak Mandelbaum }
2741588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDereferenceBinaryOperation)2751588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDereferenceBinaryOperation) {
2761588c087SYitzhak Mandelbaum   testBuilder(buildDereference, "S *x; x + 1;", "*(x + 1)");
2771588c087SYitzhak Mandelbaum }
2781588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDotValue)2791588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDotValue) {
2801588c087SYitzhak Mandelbaum   testBuilder(buildDot, "S x; x;", "x.");
2811588c087SYitzhak Mandelbaum }
2821588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDotPointerDereference)2831588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDotPointerDereference) {
2841588c087SYitzhak Mandelbaum   testBuilder(buildDot, "S *x; *x;", "x->");
2851588c087SYitzhak Mandelbaum }
2861588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDotPointerDereferenceIgnoresParens)2871588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDotPointerDereferenceIgnoresParens) {
2881588c087SYitzhak Mandelbaum   testBuilder(buildDot, "S *x; *(x);", "x->");
2891588c087SYitzhak Mandelbaum }
2901588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDotBinaryOperation)2911588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDotBinaryOperation) {
2921588c087SYitzhak Mandelbaum   testBuilder(buildDot, "S x; x + x;", "(x + x).");
2931588c087SYitzhak Mandelbaum }
2941588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDotPointerDereferenceExprWithParens)2951588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDotPointerDereferenceExprWithParens) {
2961588c087SYitzhak Mandelbaum   testBuilder(buildDot, "S *x; *(x + 1);", "(x + 1)->");
2971588c087SYitzhak Mandelbaum }
2981588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildArrowPointer)2991588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildArrowPointer) {
3001588c087SYitzhak Mandelbaum   testBuilder(buildArrow, "S *x; x;", "x->");
3011588c087SYitzhak Mandelbaum }
3021588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildArrowValueAddress)3031588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildArrowValueAddress) {
3041588c087SYitzhak Mandelbaum   testBuilder(buildArrow, "S x; &x;", "x.");
3051588c087SYitzhak Mandelbaum }
3061588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildArrowValueAddressIgnoresParens)3071588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildArrowValueAddressIgnoresParens) {
3081588c087SYitzhak Mandelbaum   testBuilder(buildArrow, "S x; &(x);", "x.");
3091588c087SYitzhak Mandelbaum }
3101588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildArrowBinaryOperation)3111588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildArrowBinaryOperation) {
3121588c087SYitzhak Mandelbaum   testBuilder(buildArrow, "S *x; x + 1;", "(x + 1)->");
3131588c087SYitzhak Mandelbaum }
3141588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildArrowValueAddressWithParens)3151588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildArrowValueAddressWithParens) {
3161588c087SYitzhak Mandelbaum   testBuilder(buildArrow, "S x; &(true ? x : x);", "(true ? x : x).");
3171588c087SYitzhak Mandelbaum }
318*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessValue)319*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessValue) {
320*0944c196SYitzhak Mandelbaum   testBuildAccess("S x; x;", "x.");
321*0944c196SYitzhak Mandelbaum }
322*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessPointerDereference)323*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessPointerDereference) {
324*0944c196SYitzhak Mandelbaum   testBuildAccess("S *x; *x;", "x->");
325*0944c196SYitzhak Mandelbaum }
326*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessPointerDereferenceIgnoresParens)327*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessPointerDereferenceIgnoresParens) {
328*0944c196SYitzhak Mandelbaum   testBuildAccess("S *x; *(x);", "x->");
329*0944c196SYitzhak Mandelbaum }
330*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessValueBinaryOperation)331*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessValueBinaryOperation) {
332*0944c196SYitzhak Mandelbaum   testBuildAccess("S x; x + x;", "(x + x).");
333*0944c196SYitzhak Mandelbaum }
334*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessPointerDereferenceExprWithParens)335*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessPointerDereferenceExprWithParens) {
336*0944c196SYitzhak Mandelbaum   testBuildAccess("S *x; *(x + 1);", "(x + 1)->");
337*0944c196SYitzhak Mandelbaum }
338*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessPointer)339*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessPointer) {
340*0944c196SYitzhak Mandelbaum   testBuildAccess("S *x; x;", "x->");
341*0944c196SYitzhak Mandelbaum }
342*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessValueAddress)343*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessValueAddress) {
344*0944c196SYitzhak Mandelbaum   testBuildAccess("S x; &x;", "x.");
345*0944c196SYitzhak Mandelbaum }
346*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessValueAddressIgnoresParens)347*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessValueAddressIgnoresParens) {
348*0944c196SYitzhak Mandelbaum   testBuildAccess("S x; &(x);", "x.");
349*0944c196SYitzhak Mandelbaum }
350*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessPointerBinaryOperation)351*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessPointerBinaryOperation) {
352*0944c196SYitzhak Mandelbaum   testBuildAccess("S *x; x + 1;", "(x + 1)->");
353*0944c196SYitzhak Mandelbaum }
354*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessValueAddressWithParens)355*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessValueAddressWithParens) {
356*0944c196SYitzhak Mandelbaum   testBuildAccess("S x; &(true ? x : x);", "(true ? x : x).");
357*0944c196SYitzhak Mandelbaum }
358*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointer)359*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessSmartPointer) {
360*0944c196SYitzhak Mandelbaum   testBuildAccess("std::unique_ptr<int> x; x;", "x->");
361*0944c196SYitzhak Mandelbaum }
362*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerAsValue)363*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessSmartPointerAsValue) {
364*0944c196SYitzhak Mandelbaum   testBuildAccess("std::unique_ptr<int> x; x;", "x.", PLTClass::Value);
365*0944c196SYitzhak Mandelbaum }
366*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerDeref)367*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessSmartPointerDeref) {
368*0944c196SYitzhak Mandelbaum   testBuildAccess("std::unique_ptr<int> x; *x;", "x->");
369*0944c196SYitzhak Mandelbaum }
370*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerDerefAsValue)371*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessSmartPointerDerefAsValue) {
372*0944c196SYitzhak Mandelbaum   testBuildAccess("std::unique_ptr<int> x; *x;", "(*x).", PLTClass::Value);
373*0944c196SYitzhak Mandelbaum }
374*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerMemberCall)375*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessSmartPointerMemberCall) {
376*0944c196SYitzhak Mandelbaum   StringRef Snippet = R"cc(
377*0944c196SYitzhak Mandelbaum     Smart x;
378*0944c196SYitzhak Mandelbaum     x->Field;
379*0944c196SYitzhak Mandelbaum   )cc";
380*0944c196SYitzhak Mandelbaum   auto StmtMatch =
381*0944c196SYitzhak Mandelbaum       matchStmt(Snippet, memberExpr(hasObjectExpression(expr().bind("expr"))));
382*0944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
383*0944c196SYitzhak Mandelbaum   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
384*0944c196SYitzhak Mandelbaum                           *StmtMatch->Result.Context),
385*0944c196SYitzhak Mandelbaum               ValueIs(std::string("x->")));
386*0944c196SYitzhak Mandelbaum }
387*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessIgnoreImplicit)388*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessIgnoreImplicit) {
389*0944c196SYitzhak Mandelbaum   StringRef Snippet = R"cc(
390*0944c196SYitzhak Mandelbaum     S x;
391*0944c196SYitzhak Mandelbaum     A *a;
392*0944c196SYitzhak Mandelbaum     a = &x;
393*0944c196SYitzhak Mandelbaum   )cc";
394*0944c196SYitzhak Mandelbaum   auto StmtMatch =
395*0944c196SYitzhak Mandelbaum       matchStmt(Snippet, binaryOperator(isAssignmentOperator(),
396*0944c196SYitzhak Mandelbaum                                         hasRHS(expr().bind("expr"))));
397*0944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
398*0944c196SYitzhak Mandelbaum   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
399*0944c196SYitzhak Mandelbaum                           *StmtMatch->Result.Context),
400*0944c196SYitzhak Mandelbaum               ValueIs(std::string("x.")));
401*0944c196SYitzhak Mandelbaum }
402*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessImplicitThis)403*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessImplicitThis) {
404*0944c196SYitzhak Mandelbaum   StringRef Snippet = R"cc(
405*0944c196SYitzhak Mandelbaum     struct Struct {
406*0944c196SYitzhak Mandelbaum       void foo() {}
407*0944c196SYitzhak Mandelbaum       void bar() {
408*0944c196SYitzhak Mandelbaum         foo();
409*0944c196SYitzhak Mandelbaum       }
410*0944c196SYitzhak Mandelbaum     };
411*0944c196SYitzhak Mandelbaum   )cc";
412*0944c196SYitzhak Mandelbaum   auto StmtMatch = matchStmt(
413*0944c196SYitzhak Mandelbaum       Snippet,
414*0944c196SYitzhak Mandelbaum       cxxMemberCallExpr(onImplicitObjectArgument(cxxThisExpr().bind("expr"))));
415*0944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
416*0944c196SYitzhak Mandelbaum   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
417*0944c196SYitzhak Mandelbaum                           *StmtMatch->Result.Context),
418*0944c196SYitzhak Mandelbaum               ValueIs(std::string()));
419*0944c196SYitzhak Mandelbaum }
420*0944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessImplicitThisIgnoreImplicitCasts)421*0944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessImplicitThisIgnoreImplicitCasts) {
422*0944c196SYitzhak Mandelbaum   StringRef Snippet = "struct B : public A { void f() { super(); } };";
423*0944c196SYitzhak Mandelbaum   auto StmtMatch = matchStmt(
424*0944c196SYitzhak Mandelbaum       Snippet,
425*0944c196SYitzhak Mandelbaum       cxxMemberCallExpr(onImplicitObjectArgument(expr().bind("expr"))));
426*0944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
427*0944c196SYitzhak Mandelbaum   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
428*0944c196SYitzhak Mandelbaum                           *StmtMatch->Result.Context),
429*0944c196SYitzhak Mandelbaum               ValueIs(std::string()));
430*0944c196SYitzhak Mandelbaum }
4311588c087SYitzhak Mandelbaum } // namespace
432