1 //===- unittest/AST/ASTContextParentMapTest.cpp - AST parent map test -----===// 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 // Tests for the getParents(...) methods of ASTContext. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/AST/ASTContext.h" 14 #include "MatchVerifier.h" 15 #include "clang/ASTMatchers/ASTMatchFinder.h" 16 #include "clang/ASTMatchers/ASTMatchers.h" 17 #include "clang/Tooling/Tooling.h" 18 #include "gtest/gtest.h" 19 #include "gmock/gmock.h" 20 21 using testing::ElementsAre; 22 23 namespace clang { 24 namespace ast_matchers { 25 26 TEST(GetParents, ReturnsParentForDecl) { 27 MatchVerifier<Decl> Verifier; 28 EXPECT_TRUE( 29 Verifier.match("class C { void f(); };", 30 cxxMethodDecl(hasParent(recordDecl(hasName("C")))))); 31 } 32 33 TEST(GetParents, ReturnsParentForStmt) { 34 MatchVerifier<Stmt> Verifier; 35 EXPECT_TRUE(Verifier.match("class C { void f() { if (true) {} } };", 36 ifStmt(hasParent(compoundStmt())))); 37 } 38 39 TEST(GetParents, ReturnsParentForTypeLoc) { 40 MatchVerifier<TypeLoc> Verifier; 41 EXPECT_TRUE( 42 Verifier.match("namespace a { class b {}; } void f(a::b) {}", 43 typeLoc(hasParent(typeLoc(hasParent(functionDecl())))))); 44 } 45 46 TEST(GetParents, ReturnsParentForNestedNameSpecifierLoc) { 47 MatchVerifier<NestedNameSpecifierLoc> Verifier; 48 EXPECT_TRUE(Verifier.match("namespace a { class b {}; } void f(a::b) {}", 49 nestedNameSpecifierLoc(hasParent(typeLoc())))); 50 } 51 52 TEST(GetParents, ReturnsParentInsideTemplateInstantiations) { 53 MatchVerifier<Decl> DeclVerifier; 54 EXPECT_TRUE(DeclVerifier.match( 55 "template<typename T> struct C { void f() {} };" 56 "void g() { C<int> c; c.f(); }", 57 cxxMethodDecl(hasName("f"), 58 hasParent(cxxRecordDecl(isTemplateInstantiation()))))); 59 EXPECT_TRUE(DeclVerifier.match( 60 "template<typename T> struct C { void f() {} };" 61 "void g() { C<int> c; c.f(); }", 62 cxxMethodDecl(hasName("f"), 63 hasParent(cxxRecordDecl(unless(isTemplateInstantiation())))))); 64 EXPECT_FALSE(DeclVerifier.match( 65 "template<typename T> struct C { void f() {} };" 66 "void g() { C<int> c; c.f(); }", 67 cxxMethodDecl( 68 hasName("f"), 69 allOf(hasParent(cxxRecordDecl(unless(isTemplateInstantiation()))), 70 hasParent(cxxRecordDecl(isTemplateInstantiation())))))); 71 } 72 73 TEST(GetParents, ReturnsMultipleParentsInTemplateInstantiations) { 74 MatchVerifier<Stmt> TemplateVerifier; 75 EXPECT_TRUE(TemplateVerifier.match( 76 "template<typename T> struct C { void f() {} };" 77 "void g() { C<int> c; c.f(); }", 78 compoundStmt(allOf( 79 hasAncestor(cxxRecordDecl(isTemplateInstantiation())), 80 hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation()))))))); 81 } 82 83 TEST(GetParents, RespectsTraversalScope) { 84 auto AST = tooling::buildASTFromCode( 85 "struct foo { int bar; }; struct baz{};", "foo.cpp", 86 std::make_shared<PCHContainerOperations>()); 87 auto &Ctx = AST->getASTContext(); 88 auto &TU = *Ctx.getTranslationUnitDecl(); 89 auto &Foo = *TU.lookup(&Ctx.Idents.get("foo")).front(); 90 auto &Bar = *cast<DeclContext>(Foo).lookup(&Ctx.Idents.get("bar")).front(); 91 auto &Baz = *TU.lookup(&Ctx.Idents.get("baz")).front(); 92 93 // Initially, scope is the whole TU. 94 EXPECT_THAT(Ctx.getParents(Bar), ElementsAre(DynTypedNode::create(Foo))); 95 EXPECT_THAT(Ctx.getParents(Foo), ElementsAre(DynTypedNode::create(TU))); 96 EXPECT_THAT(Ctx.getParents(Baz), ElementsAre(DynTypedNode::create(TU))); 97 98 // Restrict the scope, now some parents are gone. 99 Ctx.setTraversalScope({&Foo}); 100 EXPECT_THAT(Ctx.getParents(Bar), ElementsAre(DynTypedNode::create(Foo))); 101 EXPECT_THAT(Ctx.getParents(Foo), ElementsAre(DynTypedNode::create(TU))); 102 EXPECT_THAT(Ctx.getParents(Baz), ElementsAre()); 103 104 // Reset the scope, we get back the original results. 105 Ctx.setTraversalScope({&TU}); 106 EXPECT_THAT(Ctx.getParents(Bar), ElementsAre(DynTypedNode::create(Foo))); 107 EXPECT_THAT(Ctx.getParents(Foo), ElementsAre(DynTypedNode::create(TU))); 108 EXPECT_THAT(Ctx.getParents(Baz), ElementsAre(DynTypedNode::create(TU))); 109 } 110 111 TEST(GetParents, ImplicitLambdaNodes) { 112 MatchVerifier<Decl> LambdaVerifier; 113 EXPECT_TRUE(LambdaVerifier.match( 114 "auto x = []{int y;};", 115 varDecl(hasName("y"), hasAncestor(functionDecl( 116 hasOverloadedOperatorName("()"), 117 hasParent(cxxRecordDecl( 118 isImplicit(), hasParent(lambdaExpr())))))), 119 Lang_CXX11)); 120 } 121 122 } // end namespace ast_matchers 123 } // end namespace clang 124