1 //===- unittest/AST/ASTContextParentMapTest.cpp - AST parent map test -----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Tests for the getParents(...) methods of ASTContext. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/AST/ASTContext.h" 15 #include "MatchVerifier.h" 16 #include "clang/ASTMatchers/ASTMatchFinder.h" 17 #include "clang/ASTMatchers/ASTMatchers.h" 18 #include "clang/Tooling/Tooling.h" 19 #include "gtest/gtest.h" 20 #include "gmock/gmock.h" 21 22 using testing::ElementsAre; 23 24 namespace clang { 25 namespace ast_matchers { 26 27 TEST(GetParents, ReturnsParentForDecl) { 28 MatchVerifier<Decl> Verifier; 29 EXPECT_TRUE( 30 Verifier.match("class C { void f(); };", 31 cxxMethodDecl(hasParent(recordDecl(hasName("C")))))); 32 } 33 34 TEST(GetParents, ReturnsParentForStmt) { 35 MatchVerifier<Stmt> Verifier; 36 EXPECT_TRUE(Verifier.match("class C { void f() { if (true) {} } };", 37 ifStmt(hasParent(compoundStmt())))); 38 } 39 40 TEST(GetParents, ReturnsParentForTypeLoc) { 41 MatchVerifier<TypeLoc> Verifier; 42 EXPECT_TRUE( 43 Verifier.match("namespace a { class b {}; } void f(a::b) {}", 44 typeLoc(hasParent(typeLoc(hasParent(functionDecl())))))); 45 } 46 47 TEST(GetParents, ReturnsParentForNestedNameSpecifierLoc) { 48 MatchVerifier<NestedNameSpecifierLoc> Verifier; 49 EXPECT_TRUE(Verifier.match("namespace a { class b {}; } void f(a::b) {}", 50 nestedNameSpecifierLoc(hasParent(typeLoc())))); 51 } 52 53 TEST(GetParents, ReturnsParentInsideTemplateInstantiations) { 54 MatchVerifier<Decl> DeclVerifier; 55 EXPECT_TRUE(DeclVerifier.match( 56 "template<typename T> struct C { void f() {} };" 57 "void g() { C<int> c; c.f(); }", 58 cxxMethodDecl(hasName("f"), 59 hasParent(cxxRecordDecl(isTemplateInstantiation()))))); 60 EXPECT_TRUE(DeclVerifier.match( 61 "template<typename T> struct C { void f() {} };" 62 "void g() { C<int> c; c.f(); }", 63 cxxMethodDecl(hasName("f"), 64 hasParent(cxxRecordDecl(unless(isTemplateInstantiation())))))); 65 EXPECT_FALSE(DeclVerifier.match( 66 "template<typename T> struct C { void f() {} };" 67 "void g() { C<int> c; c.f(); }", 68 cxxMethodDecl( 69 hasName("f"), 70 allOf(hasParent(cxxRecordDecl(unless(isTemplateInstantiation()))), 71 hasParent(cxxRecordDecl(isTemplateInstantiation())))))); 72 } 73 74 TEST(GetParents, ReturnsMultipleParentsInTemplateInstantiations) { 75 MatchVerifier<Stmt> TemplateVerifier; 76 EXPECT_TRUE(TemplateVerifier.match( 77 "template<typename T> struct C { void f() {} };" 78 "void g() { C<int> c; c.f(); }", 79 compoundStmt(allOf( 80 hasAncestor(cxxRecordDecl(isTemplateInstantiation())), 81 hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation()))))))); 82 } 83 84 TEST(GetParents, RespectsTraversalScope) { 85 auto AST = 86 tooling::buildASTFromCode("struct foo { int bar; };", "foo.cpp", 87 std::make_shared<PCHContainerOperations>()); 88 auto &Ctx = AST->getASTContext(); 89 auto &TU = *Ctx.getTranslationUnitDecl(); 90 auto &Foo = *TU.lookup(&Ctx.Idents.get("foo")).front(); 91 auto &Bar = *cast<DeclContext>(Foo).lookup(&Ctx.Idents.get("bar")).front(); 92 93 using ast_type_traits::DynTypedNode; 94 // Initially, scope is the whole TU. 95 EXPECT_THAT(Ctx.getParents(Bar), ElementsAre(DynTypedNode::create(Foo))); 96 EXPECT_THAT(Ctx.getParents(Foo), 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()); 102 103 // Reset the scope, we get back the original results. 104 Ctx.setTraversalScope({&TU}); 105 EXPECT_THAT(Ctx.getParents(Bar), ElementsAre(DynTypedNode::create(Foo))); 106 EXPECT_THAT(Ctx.getParents(Foo), ElementsAre(DynTypedNode::create(TU))); 107 } 108 109 } // end namespace ast_matchers 110 } // end namespace clang 111