xref: /llvm-project/clang/unittests/Tooling/SourceCodeBuildersTest.cpp (revision 6ad0788c332bb2043142954d300c49ac3e537f34)
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"
100944c196SYitzhak 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"
17a1580d7bSKazu Hirata #include <optional>
181588c087SYitzhak Mandelbaum 
191588c087SYitzhak Mandelbaum using namespace clang;
201588c087SYitzhak Mandelbaum using namespace tooling;
211588c087SYitzhak Mandelbaum using namespace ast_matchers;
221588c087SYitzhak Mandelbaum 
231588c087SYitzhak Mandelbaum namespace {
241588c087SYitzhak Mandelbaum using MatchResult = MatchFinder::MatchResult;
251588c087SYitzhak Mandelbaum using llvm::ValueIs;
261588c087SYitzhak Mandelbaum 
271588c087SYitzhak Mandelbaum // Create a valid translation unit from a statement.
wrapSnippet(StringRef StatementCode)281588c087SYitzhak Mandelbaum static std::string wrapSnippet(StringRef StatementCode) {
290944c196SYitzhak Mandelbaum   return ("namespace std {\n"
300944c196SYitzhak Mandelbaum           "template <typename T> struct unique_ptr {\n"
310944c196SYitzhak Mandelbaum           "  T* operator->() const;\n"
320944c196SYitzhak Mandelbaum           "  T& operator*() const;\n"
330944c196SYitzhak Mandelbaum           "};\n"
340944c196SYitzhak Mandelbaum           "template <typename T> struct shared_ptr {\n"
350944c196SYitzhak Mandelbaum           "  T* operator->() const;\n"
360944c196SYitzhak Mandelbaum           "  T& operator*() const;\n"
370944c196SYitzhak Mandelbaum           "};\n"
380944c196SYitzhak Mandelbaum           "}\n"
390944c196SYitzhak Mandelbaum           "struct A { void super(); };\n"
400944c196SYitzhak Mandelbaum           "struct S : public A { S(); S(int); int Field; };\n"
411588c087SYitzhak Mandelbaum           "S operator+(const S &a, const S &b);\n"
420944c196SYitzhak Mandelbaum           "struct Smart {\n"
430944c196SYitzhak Mandelbaum           "  S* operator->() const;\n"
440944c196SYitzhak Mandelbaum           "  S& operator*() const;\n"
450944c196SYitzhak Mandelbaum           "};\n"
461588c087SYitzhak Mandelbaum           "auto test_snippet = []{" +
471588c087SYitzhak Mandelbaum           StatementCode + "};")
481588c087SYitzhak Mandelbaum       .str();
491588c087SYitzhak Mandelbaum }
501588c087SYitzhak Mandelbaum 
wrapMatcher(const StatementMatcher & Matcher)511588c087SYitzhak Mandelbaum static DeclarationMatcher wrapMatcher(const StatementMatcher &Matcher) {
521588c087SYitzhak Mandelbaum   return varDecl(hasName("test_snippet"),
531588c087SYitzhak Mandelbaum                  hasDescendant(compoundStmt(hasAnySubstatement(Matcher))));
541588c087SYitzhak Mandelbaum }
551588c087SYitzhak Mandelbaum 
561588c087SYitzhak Mandelbaum struct TestMatch {
571588c087SYitzhak Mandelbaum   // The AST unit from which `result` is built. We bundle it because it backs
581588c087SYitzhak Mandelbaum   // the result. Users are not expected to access it.
591588c087SYitzhak Mandelbaum   std::unique_ptr<ASTUnit> AstUnit;
601588c087SYitzhak Mandelbaum   // The result to use in the test. References `ast_unit`.
611588c087SYitzhak Mandelbaum   MatchResult Result;
621588c087SYitzhak Mandelbaum };
631588c087SYitzhak Mandelbaum 
641588c087SYitzhak Mandelbaum // Matches `Matcher` against the statement `StatementCode` and returns the
651588c087SYitzhak Mandelbaum // result. Handles putting the statement inside a function and modifying the
661588c087SYitzhak Mandelbaum // matcher correspondingly. `Matcher` should match one of the statements in
671588c087SYitzhak Mandelbaum // `StatementCode` exactly -- that is, produce exactly one match. However,
681588c087SYitzhak Mandelbaum // `StatementCode` may contain other statements not described by `Matcher`.
matchStmt(StringRef StatementCode,StatementMatcher Matcher)69*6ad0788cSKazu Hirata static std::optional<TestMatch> matchStmt(StringRef StatementCode,
701588c087SYitzhak Mandelbaum                                           StatementMatcher Matcher) {
710944c196SYitzhak Mandelbaum   auto AstUnit = buildASTFromCodeWithArgs(wrapSnippet(StatementCode),
720944c196SYitzhak Mandelbaum                                           {"-Wno-unused-value"});
731588c087SYitzhak Mandelbaum   if (AstUnit == nullptr) {
741588c087SYitzhak Mandelbaum     ADD_FAILURE() << "AST construction failed";
75a41fbb1fSKazu Hirata     return std::nullopt;
761588c087SYitzhak Mandelbaum   }
771588c087SYitzhak Mandelbaum   ASTContext &Context = AstUnit->getASTContext();
781588c087SYitzhak Mandelbaum   auto Matches = ast_matchers::match(wrapMatcher(Matcher), Context);
791588c087SYitzhak Mandelbaum   // We expect a single, exact match for the statement.
801588c087SYitzhak Mandelbaum   if (Matches.size() != 1) {
811588c087SYitzhak Mandelbaum     ADD_FAILURE() << "Wrong number of matches: " << Matches.size();
82a41fbb1fSKazu Hirata     return std::nullopt;
831588c087SYitzhak Mandelbaum   }
841588c087SYitzhak Mandelbaum   return TestMatch{std::move(AstUnit), MatchResult(Matches[0], &Context)};
851588c087SYitzhak Mandelbaum }
861588c087SYitzhak Mandelbaum 
testPredicate(bool (* Pred)(const Expr &),StringRef Snippet,bool Expected)871588c087SYitzhak Mandelbaum static void testPredicate(bool (*Pred)(const Expr &), StringRef Snippet,
881588c087SYitzhak Mandelbaum                           bool Expected) {
891588c087SYitzhak Mandelbaum   auto StmtMatch = matchStmt(Snippet, expr().bind("expr"));
901588c087SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
911588c087SYitzhak Mandelbaum   EXPECT_EQ(Expected, Pred(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr")))
921588c087SYitzhak Mandelbaum       << "Snippet: " << Snippet;
931588c087SYitzhak Mandelbaum }
941588c087SYitzhak Mandelbaum 
951588c087SYitzhak Mandelbaum // Tests the predicate on the call argument, assuming `Snippet` is a function
961588c087SYitzhak Mandelbaum // call.
testPredicateOnArg(bool (* Pred)(const Expr &),StringRef Snippet,bool Expected)971588c087SYitzhak Mandelbaum static void testPredicateOnArg(bool (*Pred)(const Expr &), StringRef Snippet,
981588c087SYitzhak Mandelbaum                                bool Expected) {
991588c087SYitzhak Mandelbaum   auto StmtMatch = matchStmt(
1001588c087SYitzhak Mandelbaum       Snippet, expr(ignoringImplicit(callExpr(hasArgument(
1011588c087SYitzhak Mandelbaum                    0, ignoringElidableConstructorCall(expr().bind("arg")))))));
1021588c087SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
1031588c087SYitzhak Mandelbaum   EXPECT_EQ(Expected, Pred(*StmtMatch->Result.Nodes.getNodeAs<Expr>("arg")))
1041588c087SYitzhak Mandelbaum       << "Snippet: " << Snippet;
1051588c087SYitzhak Mandelbaum }
1061588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,needParensAfterUnaryOperator)1071588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, needParensAfterUnaryOperator) {
1081588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "3 + 5;", true);
1091588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "true ? 3 : 5;", true);
1101588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "S(3) + S(5);", true);
1111588c087SYitzhak Mandelbaum 
1121588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "int x; x;", false);
1131588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "int(3.0);", false);
1141588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "void f(); f();", false);
1151588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "int a[3]; a[0];", false);
1160944c196SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "S x; x.Field;", false);
1171588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "int x = 1; --x;", false);
1181588c087SYitzhak Mandelbaum   testPredicate(needParensAfterUnaryOperator, "int x = 1; -x;", false);
1191588c087SYitzhak Mandelbaum }
1201588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,needParensAfterUnaryOperatorInImplicitConversion)1211588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, needParensAfterUnaryOperatorInImplicitConversion) {
1221588c087SYitzhak Mandelbaum   // The binary operation will be embedded in various implicit
1231588c087SYitzhak Mandelbaum   // expressions. Verify they are ignored.
1241588c087SYitzhak Mandelbaum   testPredicateOnArg(needParensAfterUnaryOperator, "void f(S); f(3 + 5);",
1251588c087SYitzhak Mandelbaum                      true);
1261588c087SYitzhak Mandelbaum }
1271588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,mayEverNeedParens)1281588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, mayEverNeedParens) {
1291588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "3 + 5;", true);
1301588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "true ? 3 : 5;", true);
1311588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "int x = 1; --x;", true);
1321588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "int x = 1; -x;", true);
1331588c087SYitzhak Mandelbaum 
1341588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "int x; x;", false);
1351588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "int(3.0);", false);
1361588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "void f(); f();", false);
1371588c087SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "int a[3]; a[0];", false);
1380944c196SYitzhak Mandelbaum   testPredicate(mayEverNeedParens, "S x; x.Field;", false);
1391588c087SYitzhak Mandelbaum }
1401588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,mayEverNeedParensInImplictConversion)1411588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, mayEverNeedParensInImplictConversion) {
1421588c087SYitzhak Mandelbaum   // The binary operation will be embedded in various implicit
1431588c087SYitzhak Mandelbaum   // expressions. Verify they are ignored.
1441588c087SYitzhak Mandelbaum   testPredicateOnArg(mayEverNeedParens, "void f(S); f(3 + 5);", true);
1451588c087SYitzhak Mandelbaum }
1461588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeUniquePtr)1470944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeUniquePtr) {
1480944c196SYitzhak Mandelbaum   std::string Snippet = "std::unique_ptr<int> P; P;";
1490944c196SYitzhak Mandelbaum   auto StmtMatch =
1500944c196SYitzhak Mandelbaum       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
1510944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
1520944c196SYitzhak Mandelbaum   EXPECT_TRUE(
1530944c196SYitzhak Mandelbaum       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
1540944c196SYitzhak Mandelbaum                              *StmtMatch->Result.Context))
1550944c196SYitzhak Mandelbaum       << "Snippet: " << Snippet;
1560944c196SYitzhak Mandelbaum }
1570944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeSharedPtr)1580944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeSharedPtr) {
1590944c196SYitzhak Mandelbaum   std::string Snippet = "std::shared_ptr<int> P; P;";
1600944c196SYitzhak Mandelbaum   auto StmtMatch =
1610944c196SYitzhak Mandelbaum       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
1620944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
1630944c196SYitzhak Mandelbaum   EXPECT_TRUE(
1640944c196SYitzhak Mandelbaum       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
1650944c196SYitzhak Mandelbaum                              *StmtMatch->Result.Context))
1660944c196SYitzhak Mandelbaum       << "Snippet: " << Snippet;
1670944c196SYitzhak Mandelbaum }
1680944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeUnknownTypeFalse)1690944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeUnknownTypeFalse) {
1700944c196SYitzhak Mandelbaum   std::string Snippet = "Smart P; P;";
1710944c196SYitzhak Mandelbaum   auto StmtMatch =
1720944c196SYitzhak Mandelbaum       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
1730944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
1740944c196SYitzhak Mandelbaum   EXPECT_FALSE(
1750944c196SYitzhak Mandelbaum       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
1760944c196SYitzhak Mandelbaum                              *StmtMatch->Result.Context))
1770944c196SYitzhak Mandelbaum       << "Snippet: " << Snippet;
1780944c196SYitzhak Mandelbaum }
1790944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeNormalTypeFalse)1800944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeNormalTypeFalse) {
1810944c196SYitzhak Mandelbaum   std::string Snippet = "int *P; P;";
1820944c196SYitzhak Mandelbaum   auto StmtMatch =
1830944c196SYitzhak Mandelbaum       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
1840944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
1850944c196SYitzhak Mandelbaum   EXPECT_FALSE(
1860944c196SYitzhak Mandelbaum       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
1870944c196SYitzhak Mandelbaum                              *StmtMatch->Result.Context))
1880944c196SYitzhak Mandelbaum       << "Snippet: " << Snippet;
1890944c196SYitzhak Mandelbaum }
1900944c196SYitzhak Mandelbaum 
testBuilder(std::optional<std::string> (* Builder)(const Expr &,const ASTContext &),StringRef Snippet,StringRef Expected)1911588c087SYitzhak Mandelbaum static void testBuilder(
192b0de3630SFangrui Song     std::optional<std::string> (*Builder)(const Expr &, const ASTContext &),
1931588c087SYitzhak Mandelbaum     StringRef Snippet, StringRef Expected) {
1941588c087SYitzhak Mandelbaum   auto StmtMatch = matchStmt(Snippet, expr().bind("expr"));
1951588c087SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
1961588c087SYitzhak Mandelbaum   EXPECT_THAT(Builder(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
1971588c087SYitzhak Mandelbaum                       *StmtMatch->Result.Context),
198adcd0268SBenjamin Kramer               ValueIs(std::string(Expected)));
1991588c087SYitzhak Mandelbaum }
2001588c087SYitzhak Mandelbaum 
testBuildAccess(StringRef Snippet,StringRef Expected,PLTClass C=PLTClass::Pointer)2010944c196SYitzhak Mandelbaum static void testBuildAccess(StringRef Snippet, StringRef Expected,
2020944c196SYitzhak Mandelbaum                             PLTClass C = PLTClass::Pointer) {
2030944c196SYitzhak Mandelbaum   auto StmtMatch = matchStmt(Snippet, expr().bind("expr"));
2040944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
2050944c196SYitzhak Mandelbaum   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
2060944c196SYitzhak Mandelbaum                           *StmtMatch->Result.Context, C),
2070944c196SYitzhak Mandelbaum               ValueIs(std::string(Expected)));
2080944c196SYitzhak Mandelbaum }
2090944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildParensUnaryOp)2101588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildParensUnaryOp) {
2111588c087SYitzhak Mandelbaum   testBuilder(buildParens, "-4;", "(-4)");
2121588c087SYitzhak Mandelbaum }
2131588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildParensBinOp)2141588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildParensBinOp) {
2151588c087SYitzhak Mandelbaum   testBuilder(buildParens, "4 + 4;", "(4 + 4)");
2161588c087SYitzhak Mandelbaum }
2171588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildParensValue)2181588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildParensValue) {
2191588c087SYitzhak Mandelbaum   testBuilder(buildParens, "4;", "4");
2201588c087SYitzhak Mandelbaum }
2211588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildParensSubscript)2221588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildParensSubscript) {
2231588c087SYitzhak Mandelbaum   testBuilder(buildParens, "int a[3]; a[0];", "a[0]");
2241588c087SYitzhak Mandelbaum }
2251588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildParensCall)2261588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildParensCall) {
2271588c087SYitzhak Mandelbaum   testBuilder(buildParens, "int f(int); f(4);", "f(4)");
2281588c087SYitzhak Mandelbaum }
2291588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAddressOfValue)2301588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAddressOfValue) {
2311588c087SYitzhak Mandelbaum   testBuilder(buildAddressOf, "S x; x;", "&x");
2321588c087SYitzhak Mandelbaum }
2331588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAddressOfPointerDereference)2341588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAddressOfPointerDereference) {
2351588c087SYitzhak Mandelbaum   testBuilder(buildAddressOf, "S *x; *x;", "x");
2361588c087SYitzhak Mandelbaum }
2371588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAddressOfPointerDereferenceIgnoresParens)2381588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAddressOfPointerDereferenceIgnoresParens) {
2391588c087SYitzhak Mandelbaum   testBuilder(buildAddressOf, "S *x; *(x);", "x");
2401588c087SYitzhak Mandelbaum }
2411588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAddressOfBinaryOperation)2421588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAddressOfBinaryOperation) {
2431588c087SYitzhak Mandelbaum   testBuilder(buildAddressOf, "S x; x + x;", "&(x + x)");
2441588c087SYitzhak Mandelbaum }
2451588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAddressOfImplicitThis)246d2e32fa4SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAddressOfImplicitThis) {
247d2e32fa4SYitzhak Mandelbaum   StringRef Snippet = R"cc(
248d2e32fa4SYitzhak Mandelbaum     struct Struct {
249d2e32fa4SYitzhak Mandelbaum       void foo() {}
250d2e32fa4SYitzhak Mandelbaum       void bar() {
251d2e32fa4SYitzhak Mandelbaum         foo();
252d2e32fa4SYitzhak Mandelbaum       }
253d2e32fa4SYitzhak Mandelbaum     };
254d2e32fa4SYitzhak Mandelbaum   )cc";
255d2e32fa4SYitzhak Mandelbaum   auto StmtMatch = matchStmt(
256d2e32fa4SYitzhak Mandelbaum       Snippet,
257d2e32fa4SYitzhak Mandelbaum       cxxMemberCallExpr(onImplicitObjectArgument(cxxThisExpr().bind("expr"))));
258d2e32fa4SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
259d2e32fa4SYitzhak Mandelbaum   EXPECT_THAT(buildAddressOf(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
260d2e32fa4SYitzhak Mandelbaum                              *StmtMatch->Result.Context),
261d2e32fa4SYitzhak Mandelbaum               ValueIs(std::string("this")));
262d2e32fa4SYitzhak Mandelbaum }
263d2e32fa4SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDereferencePointer)2641588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDereferencePointer) {
2651588c087SYitzhak Mandelbaum   testBuilder(buildDereference, "S *x; x;", "*x");
2661588c087SYitzhak Mandelbaum }
2671588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDereferenceValueAddress)2681588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDereferenceValueAddress) {
2691588c087SYitzhak Mandelbaum   testBuilder(buildDereference, "S x; &x;", "x");
2701588c087SYitzhak Mandelbaum }
2711588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDereferenceValueAddressIgnoresParens)2721588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDereferenceValueAddressIgnoresParens) {
2731588c087SYitzhak Mandelbaum   testBuilder(buildDereference, "S x; &(x);", "x");
2741588c087SYitzhak Mandelbaum }
2751588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDereferenceBinaryOperation)2761588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDereferenceBinaryOperation) {
2771588c087SYitzhak Mandelbaum   testBuilder(buildDereference, "S *x; x + 1;", "*(x + 1)");
2781588c087SYitzhak Mandelbaum }
2791588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDotValue)2801588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDotValue) {
2811588c087SYitzhak Mandelbaum   testBuilder(buildDot, "S x; x;", "x.");
2821588c087SYitzhak Mandelbaum }
2831588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDotPointerDereference)2841588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDotPointerDereference) {
2851588c087SYitzhak Mandelbaum   testBuilder(buildDot, "S *x; *x;", "x->");
2861588c087SYitzhak Mandelbaum }
2871588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDotPointerDereferenceIgnoresParens)2881588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDotPointerDereferenceIgnoresParens) {
2891588c087SYitzhak Mandelbaum   testBuilder(buildDot, "S *x; *(x);", "x->");
2901588c087SYitzhak Mandelbaum }
2911588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDotBinaryOperation)2921588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDotBinaryOperation) {
2931588c087SYitzhak Mandelbaum   testBuilder(buildDot, "S x; x + x;", "(x + x).");
2941588c087SYitzhak Mandelbaum }
2951588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildDotPointerDereferenceExprWithParens)2961588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildDotPointerDereferenceExprWithParens) {
2971588c087SYitzhak Mandelbaum   testBuilder(buildDot, "S *x; *(x + 1);", "(x + 1)->");
2981588c087SYitzhak Mandelbaum }
2991588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildArrowPointer)3001588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildArrowPointer) {
3011588c087SYitzhak Mandelbaum   testBuilder(buildArrow, "S *x; x;", "x->");
3021588c087SYitzhak Mandelbaum }
3031588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildArrowValueAddress)3041588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildArrowValueAddress) {
3051588c087SYitzhak Mandelbaum   testBuilder(buildArrow, "S x; &x;", "x.");
3061588c087SYitzhak Mandelbaum }
3071588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildArrowValueAddressIgnoresParens)3081588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildArrowValueAddressIgnoresParens) {
3091588c087SYitzhak Mandelbaum   testBuilder(buildArrow, "S x; &(x);", "x.");
3101588c087SYitzhak Mandelbaum }
3111588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildArrowBinaryOperation)3121588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildArrowBinaryOperation) {
3131588c087SYitzhak Mandelbaum   testBuilder(buildArrow, "S *x; x + 1;", "(x + 1)->");
3141588c087SYitzhak Mandelbaum }
3151588c087SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildArrowValueAddressWithParens)3161588c087SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildArrowValueAddressWithParens) {
3171588c087SYitzhak Mandelbaum   testBuilder(buildArrow, "S x; &(true ? x : x);", "(true ? x : x).");
3181588c087SYitzhak Mandelbaum }
3190944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessValue)3200944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessValue) {
3210944c196SYitzhak Mandelbaum   testBuildAccess("S x; x;", "x.");
3220944c196SYitzhak Mandelbaum }
3230944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessPointerDereference)3240944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessPointerDereference) {
3250944c196SYitzhak Mandelbaum   testBuildAccess("S *x; *x;", "x->");
3260944c196SYitzhak Mandelbaum }
3270944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessPointerDereferenceIgnoresParens)3280944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessPointerDereferenceIgnoresParens) {
3290944c196SYitzhak Mandelbaum   testBuildAccess("S *x; *(x);", "x->");
3300944c196SYitzhak Mandelbaum }
3310944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessValueBinaryOperation)3320944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessValueBinaryOperation) {
3330944c196SYitzhak Mandelbaum   testBuildAccess("S x; x + x;", "(x + x).");
3340944c196SYitzhak Mandelbaum }
3350944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessPointerDereferenceExprWithParens)3360944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessPointerDereferenceExprWithParens) {
3370944c196SYitzhak Mandelbaum   testBuildAccess("S *x; *(x + 1);", "(x + 1)->");
3380944c196SYitzhak Mandelbaum }
3390944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessPointer)3400944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessPointer) {
3410944c196SYitzhak Mandelbaum   testBuildAccess("S *x; x;", "x->");
3420944c196SYitzhak Mandelbaum }
3430944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessValueAddress)3440944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessValueAddress) {
3450944c196SYitzhak Mandelbaum   testBuildAccess("S x; &x;", "x.");
3460944c196SYitzhak Mandelbaum }
3470944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessValueAddressIgnoresParens)3480944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessValueAddressIgnoresParens) {
3490944c196SYitzhak Mandelbaum   testBuildAccess("S x; &(x);", "x.");
3500944c196SYitzhak Mandelbaum }
3510944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessPointerBinaryOperation)3520944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessPointerBinaryOperation) {
3530944c196SYitzhak Mandelbaum   testBuildAccess("S *x; x + 1;", "(x + 1)->");
3540944c196SYitzhak Mandelbaum }
3550944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessValueAddressWithParens)3560944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessValueAddressWithParens) {
3570944c196SYitzhak Mandelbaum   testBuildAccess("S x; &(true ? x : x);", "(true ? x : x).");
3580944c196SYitzhak Mandelbaum }
3590944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointer)3600944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessSmartPointer) {
3610944c196SYitzhak Mandelbaum   testBuildAccess("std::unique_ptr<int> x; x;", "x->");
3620944c196SYitzhak Mandelbaum }
3630944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerAsValue)3640944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessSmartPointerAsValue) {
3650944c196SYitzhak Mandelbaum   testBuildAccess("std::unique_ptr<int> x; x;", "x.", PLTClass::Value);
3660944c196SYitzhak Mandelbaum }
3670944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerDeref)3680944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessSmartPointerDeref) {
3690944c196SYitzhak Mandelbaum   testBuildAccess("std::unique_ptr<int> x; *x;", "x->");
3700944c196SYitzhak Mandelbaum }
3710944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerDerefAsValue)3720944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessSmartPointerDerefAsValue) {
3730944c196SYitzhak Mandelbaum   testBuildAccess("std::unique_ptr<int> x; *x;", "(*x).", PLTClass::Value);
3740944c196SYitzhak Mandelbaum }
3750944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerMemberCall)3760944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessSmartPointerMemberCall) {
3770944c196SYitzhak Mandelbaum   StringRef Snippet = R"cc(
3780944c196SYitzhak Mandelbaum     Smart x;
3790944c196SYitzhak Mandelbaum     x->Field;
3800944c196SYitzhak Mandelbaum   )cc";
3810944c196SYitzhak Mandelbaum   auto StmtMatch =
3820944c196SYitzhak Mandelbaum       matchStmt(Snippet, memberExpr(hasObjectExpression(expr().bind("expr"))));
3830944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
3840944c196SYitzhak Mandelbaum   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
3850944c196SYitzhak Mandelbaum                           *StmtMatch->Result.Context),
3860944c196SYitzhak Mandelbaum               ValueIs(std::string("x->")));
3870944c196SYitzhak Mandelbaum }
3880944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessIgnoreImplicit)3890944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessIgnoreImplicit) {
3900944c196SYitzhak Mandelbaum   StringRef Snippet = R"cc(
3910944c196SYitzhak Mandelbaum     S x;
3920944c196SYitzhak Mandelbaum     A *a;
3930944c196SYitzhak Mandelbaum     a = &x;
3940944c196SYitzhak Mandelbaum   )cc";
3950944c196SYitzhak Mandelbaum   auto StmtMatch =
3960944c196SYitzhak Mandelbaum       matchStmt(Snippet, binaryOperator(isAssignmentOperator(),
3970944c196SYitzhak Mandelbaum                                         hasRHS(expr().bind("expr"))));
3980944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
3990944c196SYitzhak Mandelbaum   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
4000944c196SYitzhak Mandelbaum                           *StmtMatch->Result.Context),
4010944c196SYitzhak Mandelbaum               ValueIs(std::string("x.")));
4020944c196SYitzhak Mandelbaum }
4030944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessImplicitThis)4040944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessImplicitThis) {
4050944c196SYitzhak Mandelbaum   StringRef Snippet = R"cc(
4060944c196SYitzhak Mandelbaum     struct Struct {
4070944c196SYitzhak Mandelbaum       void foo() {}
4080944c196SYitzhak Mandelbaum       void bar() {
4090944c196SYitzhak Mandelbaum         foo();
4100944c196SYitzhak Mandelbaum       }
4110944c196SYitzhak Mandelbaum     };
4120944c196SYitzhak Mandelbaum   )cc";
4130944c196SYitzhak Mandelbaum   auto StmtMatch = matchStmt(
4140944c196SYitzhak Mandelbaum       Snippet,
4150944c196SYitzhak Mandelbaum       cxxMemberCallExpr(onImplicitObjectArgument(cxxThisExpr().bind("expr"))));
4160944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
4170944c196SYitzhak Mandelbaum   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
4180944c196SYitzhak Mandelbaum                           *StmtMatch->Result.Context),
4190944c196SYitzhak Mandelbaum               ValueIs(std::string()));
4200944c196SYitzhak Mandelbaum }
4210944c196SYitzhak Mandelbaum 
TEST(SourceCodeBuildersTest,BuildAccessImplicitThisIgnoreImplicitCasts)4220944c196SYitzhak Mandelbaum TEST(SourceCodeBuildersTest, BuildAccessImplicitThisIgnoreImplicitCasts) {
4230944c196SYitzhak Mandelbaum   StringRef Snippet = "struct B : public A { void f() { super(); } };";
4240944c196SYitzhak Mandelbaum   auto StmtMatch = matchStmt(
4250944c196SYitzhak Mandelbaum       Snippet,
4260944c196SYitzhak Mandelbaum       cxxMemberCallExpr(onImplicitObjectArgument(expr().bind("expr"))));
4270944c196SYitzhak Mandelbaum   ASSERT_TRUE(StmtMatch);
4280944c196SYitzhak Mandelbaum   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
4290944c196SYitzhak Mandelbaum                           *StmtMatch->Result.Context),
4300944c196SYitzhak Mandelbaum               ValueIs(std::string()));
4310944c196SYitzhak Mandelbaum }
4321588c087SYitzhak Mandelbaum } // namespace
433