RecursiveASTVisitorTestExprVisitor.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. //===- unittest/Tooling/RecursiveASTVisitorTestExprVisitor.cpp ------------===//
  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. #include "TestVisitor.h"
  10. #include <stack>
  11. using namespace clang;
  12. namespace {
  13. class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
  14. public:
  15. bool VisitParenExpr(ParenExpr *Parens) {
  16. Match("", Parens->getExprLoc());
  17. return true;
  18. }
  19. };
  20. TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
  21. ParenExprVisitor Visitor;
  22. Visitor.ExpectMatch("", 1, 9);
  23. EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
  24. }
  25. class TemplateArgumentLocTraverser
  26. : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
  27. public:
  28. bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
  29. std::string ArgStr;
  30. llvm::raw_string_ostream Stream(ArgStr);
  31. const TemplateArgument &Arg = ArgLoc.getArgument();
  32. Arg.print(Context->getPrintingPolicy(), Stream);
  33. Match(Stream.str(), ArgLoc.getLocation());
  34. return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
  35. TraverseTemplateArgumentLoc(ArgLoc);
  36. }
  37. };
  38. TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
  39. TemplateArgumentLocTraverser Visitor;
  40. Visitor.ExpectMatch("X", 2, 40);
  41. EXPECT_TRUE(Visitor.runOver(
  42. "template<typename T> class X;\n"
  43. "template<template <typename> class T = X> class Y;\n"
  44. "template<template <typename> class T> class Y {};\n"));
  45. }
  46. class CXXBoolLiteralExprVisitor
  47. : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
  48. public:
  49. bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) {
  50. if (BE->getValue())
  51. Match("true", BE->getLocation());
  52. else
  53. Match("false", BE->getLocation());
  54. return true;
  55. }
  56. };
  57. TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) {
  58. CXXBoolLiteralExprVisitor Visitor;
  59. Visitor.ExpectMatch("true", 2, 19);
  60. EXPECT_TRUE(Visitor.runOver(
  61. "template<bool B> class X;\n"
  62. "template<bool B = true> class Y;\n"
  63. "template<bool B> class Y {};\n"));
  64. }
  65. // A visitor that visits implicit declarations and matches constructors.
  66. class ImplicitCtorVisitor
  67. : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
  68. public:
  69. bool shouldVisitImplicitCode() const { return true; }
  70. bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
  71. if (Ctor->isImplicit()) { // Was not written in source code
  72. if (const CXXRecordDecl* Class = Ctor->getParent()) {
  73. Match(Class->getName(), Ctor->getLocation());
  74. }
  75. }
  76. return true;
  77. }
  78. };
  79. TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) {
  80. ImplicitCtorVisitor Visitor;
  81. Visitor.ExpectMatch("Simple", 2, 8);
  82. // Note: Clang lazily instantiates implicit declarations, so we need
  83. // to use them in order to force them to appear in the AST.
  84. EXPECT_TRUE(Visitor.runOver(
  85. "struct WithCtor { WithCtor(); }; \n"
  86. "struct Simple { Simple(); WithCtor w; }; \n"
  87. "int main() { Simple s; Simple t(s); }\n"));
  88. }
  89. /// \brief A visitor that optionally includes implicit code and matches
  90. /// CXXConstructExpr.
  91. ///
  92. /// The name recorded for the match is the name of the class whose constructor
  93. /// is invoked by the CXXConstructExpr, not the name of the class whose
  94. /// constructor the CXXConstructExpr is contained in.
  95. class ConstructExprVisitor
  96. : public ExpectedLocationVisitor<ConstructExprVisitor> {
  97. public:
  98. ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
  99. bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
  100. void setShouldVisitImplicitCode(bool NewValue) {
  101. ShouldVisitImplicitCode = NewValue;
  102. }
  103. bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
  104. if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
  105. if (const CXXRecordDecl* Class = Ctor->getParent()) {
  106. Match(Class->getName(), Expr->getLocation());
  107. }
  108. }
  109. return true;
  110. }
  111. private:
  112. bool ShouldVisitImplicitCode;
  113. };
  114. TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
  115. ConstructExprVisitor Visitor;
  116. Visitor.setShouldVisitImplicitCode(true);
  117. Visitor.ExpectMatch("WithCtor", 2, 8);
  118. // Simple has a constructor that implicitly initializes 'w'. Test
  119. // that a visitor that visits implicit code visits that initialization.
  120. // Note: Clang lazily instantiates implicit declarations, so we need
  121. // to use them in order to force them to appear in the AST.
  122. EXPECT_TRUE(Visitor.runOver(
  123. "struct WithCtor { WithCtor(); }; \n"
  124. "struct Simple { WithCtor w; }; \n"
  125. "int main() { Simple s; }\n"));
  126. }
  127. // The same as CanVisitImplicitMemberInitializations, but checking that the
  128. // visits are omitted when the visitor does not include implicit code.
  129. TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
  130. ConstructExprVisitor Visitor;
  131. Visitor.setShouldVisitImplicitCode(false);
  132. Visitor.DisallowMatch("WithCtor", 2, 8);
  133. // Simple has a constructor that implicitly initializes 'w'. Test
  134. // that a visitor that skips implicit code skips that initialization.
  135. // Note: Clang lazily instantiates implicit declarations, so we need
  136. // to use them in order to force them to appear in the AST.
  137. EXPECT_TRUE(Visitor.runOver(
  138. "struct WithCtor { WithCtor(); }; \n"
  139. "struct Simple { WithCtor w; }; \n"
  140. "int main() { Simple s; }\n"));
  141. }
  142. class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
  143. public:
  144. bool VisitDeclRefExpr(DeclRefExpr *Reference) {
  145. Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
  146. return true;
  147. }
  148. };
  149. TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
  150. DeclRefExprVisitor Visitor;
  151. Visitor.ExpectMatch("x", 2, 3);
  152. EXPECT_TRUE(Visitor.runOver(
  153. "void x(); template <void (*T)()> class X {};\nX<x> y;"));
  154. }
  155. TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
  156. DeclRefExprVisitor Visitor;
  157. Visitor.ExpectMatch("x", 2, 25);
  158. Visitor.ExpectMatch("x", 2, 30);
  159. EXPECT_TRUE(Visitor.runOver(
  160. "int x[5];\n"
  161. "void f() { for (int i : x) { x[0] = 1; } }",
  162. DeclRefExprVisitor::Lang_CXX11));
  163. }
  164. TEST(RecursiveASTVisitor, VisitsCallExpr) {
  165. DeclRefExprVisitor Visitor;
  166. Visitor.ExpectMatch("x", 1, 22);
  167. EXPECT_TRUE(Visitor.runOver(
  168. "void x(); void y() { x(); }"));
  169. }
  170. /* FIXME: According to Richard Smith this is a bug in the AST.
  171. TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
  172. DeclRefExprVisitor Visitor;
  173. Visitor.ExpectMatch("x", 3, 43);
  174. EXPECT_TRUE(Visitor.runOver(
  175. "template <typename T> void x();\n"
  176. "template <void (*T)()> class X {};\n"
  177. "template <typename T> class Y : public X< x<T> > {};\n"
  178. "Y<int> y;"));
  179. }
  180. */
  181. TEST(RecursiveASTVisitor, VisitsExtension) {
  182. DeclRefExprVisitor Visitor;
  183. Visitor.ExpectMatch("s", 1, 24);
  184. EXPECT_TRUE(Visitor.runOver(
  185. "int s = __extension__ (s);\n"));
  186. }
  187. TEST(RecursiveASTVisitor, VisitsCopyExprOfBlockDeclCapture) {
  188. DeclRefExprVisitor Visitor;
  189. Visitor.ExpectMatch("x", 3, 24);
  190. EXPECT_TRUE(Visitor.runOver("void f(int(^)(int)); \n"
  191. "void g() { \n"
  192. " f([&](int x){ return x; }); \n"
  193. "}",
  194. DeclRefExprVisitor::Lang_OBJCXX11));
  195. }
  196. } // end anonymous namespace