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 = 85 tooling::buildASTFromCode("struct foo { int bar; };", "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 92 // Initially, scope is the whole TU. 93 EXPECT_THAT(Ctx.getParents(Bar), ElementsAre(DynTypedNode::create(Foo))); 94 EXPECT_THAT(Ctx.getParents(Foo), ElementsAre(DynTypedNode::create(TU))); 95 96 // Restrict the scope, now some parents are gone. 97 Ctx.setTraversalScope({&Foo}); 98 EXPECT_THAT(Ctx.getParents(Bar), ElementsAre(DynTypedNode::create(Foo))); 99 EXPECT_THAT(Ctx.getParents(Foo), ElementsAre()); 100 101 // Reset the scope, we get back the original results. 102 Ctx.setTraversalScope({&TU}); 103 EXPECT_THAT(Ctx.getParents(Bar), ElementsAre(DynTypedNode::create(Foo))); 104 EXPECT_THAT(Ctx.getParents(Foo), ElementsAre(DynTypedNode::create(TU))); 105 } 106 107 TEST(GetParents, ImplicitLambdaNodes) { 108 MatchVerifier<Decl> LambdaVerifier; 109 EXPECT_TRUE(LambdaVerifier.match( 110 "auto x = []{int y;};", 111 varDecl(hasName("y"), hasAncestor(functionDecl( 112 hasOverloadedOperatorName("()"), 113 hasParent(cxxRecordDecl( 114 isImplicit(), hasParent(lambdaExpr())))))), 115 Lang_CXX11)); 116 } 117 118 } // end namespace ast_matchers 119 } // end namespace clang 120