brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.2 KiB · 545eaf3 Raw
201 lines · cpp
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-exception6//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 21using testing::ElementsAre;22 23namespace clang {24namespace ast_matchers {25 26TEST(GetParents, ReturnsParentForDecl) {27  MatchVerifier<Decl> Verifier;28  EXPECT_TRUE(29      Verifier.match("class C { void f(); };",30                     cxxMethodDecl(hasParent(recordDecl(hasName("C"))))));31}32 33TEST(GetParents, ReturnsParentForStmt) {34  MatchVerifier<Stmt> Verifier;35  EXPECT_TRUE(Verifier.match("class C { void f() { if (true) {} } };",36                             ifStmt(hasParent(compoundStmt()))));37}38 39TEST(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 46TEST(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 52TEST(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 73TEST(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 83TEST(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 111TEST(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 122TEST(GetParents, FriendTypeLoc) {123  auto AST = tooling::buildASTFromCode("struct A { friend struct Fr; };"124                                       "struct B { friend struct Fr; };"125                                       "struct Fr;");126  auto &Ctx = AST->getASTContext();127  auto &TU = *Ctx.getTranslationUnitDecl();128  auto &A = *TU.lookup(&Ctx.Idents.get("A")).front();129  auto &B = *TU.lookup(&Ctx.Idents.get("B")).front();130  auto &FrA = *cast<FriendDecl>(*++(cast<CXXRecordDecl>(A).decls_begin()));131  auto &FrB = *cast<FriendDecl>(*++(cast<CXXRecordDecl>(B).decls_begin()));132  TypeLoc FrALoc = FrA.getFriendType()->getTypeLoc();133  TypeLoc FrBLoc = FrB.getFriendType()->getTypeLoc();134  bool FrAOwnsTag = FrALoc.getTypePtr()->getAs<TagType>()->isTagOwned();135  TagDecl *FrATagDecl = FrALoc.getTypePtr()->getAs<TagType>()->getDecl();136  bool FrBOwnsTag = FrBLoc.getTypePtr()->getAs<TagType>()->isTagOwned();137 138  EXPECT_THAT(Ctx.getParents(A), ElementsAre(DynTypedNode::create(TU)));139  EXPECT_THAT(Ctx.getParents(B), ElementsAre(DynTypedNode::create(TU)));140  EXPECT_THAT(Ctx.getParents(FrA), ElementsAre(DynTypedNode::create(A)));141  EXPECT_THAT(Ctx.getParents(FrB), ElementsAre(DynTypedNode::create(B)));142  EXPECT_THAT(Ctx.getParents(FrALoc), ElementsAre(DynTypedNode::create(FrA)));143  EXPECT_THAT(Ctx.getParents(FrBLoc), ElementsAre(DynTypedNode::create(FrB)));144  EXPECT_TRUE(FrAOwnsTag);145  EXPECT_FALSE(FrBOwnsTag);146  EXPECT_THAT(Ctx.getParents(*FrATagDecl),147              ElementsAre(DynTypedNode::create(FrA)));148}149 150TEST(GetParents, UserDefinedTupleLikeTypes) {151  MatchVerifier<VarDecl> Verifier;152  EXPECT_TRUE(Verifier.match(153      R"(154namespace std {155 156using size_t = __typeof(sizeof(int));157 158template <typename T>159struct tuple_size;160 161template <typename T>162struct tuple_size<T&> : tuple_size<T>{};163 164template <typename T>165requires requires { tuple_size<T>::value; }166struct tuple_size<const T> : tuple_size<T>{};167 168 169template<size_t i, typename T>170struct tuple_element;171 172 173}  // namespace std174 175struct Decomposable {};176 177template<> struct std::tuple_size<Decomposable> {178  static constexpr size_t value = 2;179};180 181template<std::size_t i> struct std::tuple_element<i, Decomposable> {182  using type = int;183};184 185template<std::size_t i> struct std::tuple_element<i, const Decomposable> {186  using type = const int;187};188 189template<std::size_t i>190const int& get(const Decomposable& d);191 192void F(const Decomposable& d) {193    const auto& [x, y] = d;194}195)",196      varDecl(hasName("x"), hasAncestor(decompositionDecl())), Lang_CXX20));197}198 199} // end namespace ast_matchers200} // end namespace clang201