ASTContextParentMapTest.cpp 4.5 KB

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