From 13cc256e404620c1de0cbcc4e43ce1e2dbbc4898 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 2 Dec 2012 13:20:44 +0000 Subject: Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2): http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974 --- include/clang/ASTMatchers/ASTMatchFinder.h | 29 +- include/clang/ASTMatchers/ASTMatchers.h | 1445 +++++++++++++++++++---- include/clang/ASTMatchers/ASTMatchersInternal.h | 621 +++++++--- include/clang/ASTMatchers/ASTMatchersMacros.h | 65 + include/clang/ASTMatchers/ASTTypeTraits.h | 209 ++++ 5 files changed, 1963 insertions(+), 406 deletions(-) create mode 100644 include/clang/ASTMatchers/ASTTypeTraits.h (limited to 'include/clang/ASTMatchers') diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h index dd237eece3e4..30b4050e1c81 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -85,7 +85,14 @@ public: class MatchCallback { public: virtual ~MatchCallback(); + + /// \brief Called on every match by the \c MatchFinder. virtual void run(const MatchResult &Result) = 0; + + /// \brief Called at the start of each translation unit. + /// + /// Optionally override to do per translation unit tasks. + virtual void onStartOfTranslationUnit() {} }; /// \brief Called when parsing is finished. Intended for testing only. @@ -112,11 +119,24 @@ public: MatchCallback *Action); void addMatcher(const StatementMatcher &NodeMatch, MatchCallback *Action); + void addMatcher(const NestedNameSpecifierMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const TypeLocMatcher &NodeMatch, + MatchCallback *Action); /// @} /// \brief Creates a clang ASTConsumer that finds all matches. clang::ASTConsumer *newASTConsumer(); + /// \brief Finds all matches on the given \c Node. + /// + /// @{ + void findAll(const Decl &Node, ASTContext &Context); + void findAll(const Stmt &Node, ASTContext &Context); + /// @} + /// \brief Registers a callback to notify the end of parsing. /// /// The provided closure is called after parsing is done, before the AST is @@ -125,11 +145,10 @@ public: void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); private: - /// \brief The MatchCallback*'s will be called every time the - /// UntypedBaseMatcher matches on the AST. - std::vector< std::pair< - const internal::UntypedBaseMatcher*, - MatchCallback*> > Triggers; + /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called + /// when it matches. + std::vector > + MatcherCallbackPairs; /// \brief Called when parsing is done. ParsingDoneTestCallback *ParsingDone; diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 33ef3dc8d6e0..a70dd5c378bd 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -14,7 +14,7 @@ // a functional in-language DSL to express queries over the C++ AST. // // For example, to match a class with a certain name, one would call: -// record(hasName("MyClass")) +// recordDecl(hasName("MyClass")) // which returns a matcher that can be used to find all AST nodes that declare // a class named 'MyClass'. // @@ -25,7 +25,7 @@ // // For example, when we're interested in child classes of a certain class, we // would write: -// record(hasName("MyClass"), hasChild(id("child", record()))) +// recordDecl(hasName("MyClass"), hasChild(id("child", recordDecl()))) // When the match is found via the MatchFinder, a user provided callback will // be called with a BoundNodes instance that contains a mapping from the // strings that we provided for the id(...) calls to the nodes that were @@ -57,52 +57,47 @@ namespace ast_matchers { /// \brief Maps string IDs to AST nodes matched by parts of a matcher. /// -/// The bound nodes are generated by adding id(...) matchers into the -/// match expression around the matchers for the nodes we want to access later. +/// The bound nodes are generated by calling \c bind("id") on the node matchers +/// of the nodes we want to access later. /// -/// The instances of BoundNodes are created by MatchFinder when the user's +/// The instances of BoundNodes are created by \c MatchFinder when the user's /// callbacks are executed every time a match is found. class BoundNodes { public: - /// \brief Returns the AST node bound to 'ID'. - /// Returns NULL if there was no node bound to 'ID' or if there is a node but + /// \brief Returns the AST node bound to \c ID. + /// + /// Returns NULL if there was no node bound to \c ID or if there is a node but /// it cannot be converted to the specified type. - /// FIXME: We'll need one of those for every base type. + template + const T *getNodeAs(StringRef ID) const { + return MyBoundNodes.getNodeAs(ID); + } + + /// \brief Deprecated. Please use \c getNodeAs instead. /// @{ template const T *getDeclAs(StringRef ID) const { - return getNodeAs(DeclBindings, ID); + return getNodeAs(ID); } template const T *getStmtAs(StringRef ID) const { - return getNodeAs(StmtBindings, ID); + return getNodeAs(ID); } /// @} private: /// \brief Create BoundNodes from a pre-filled map of bindings. - BoundNodes(const std::map &DeclBindings, - const std::map &StmtBindings) - : DeclBindings(DeclBindings), StmtBindings(StmtBindings) {} - - template - const T *getNodeAs(const MapT &Bindings, StringRef ID) const { - typename MapT::const_iterator It = Bindings.find(ID); - if (It == Bindings.end()) { - return NULL; - } - return llvm::dyn_cast(It->second); - } + BoundNodes(internal::BoundNodesMap &MyBoundNodes) + : MyBoundNodes(MyBoundNodes) {} - std::map DeclBindings; - std::map StmtBindings; + internal::BoundNodesMap MyBoundNodes; friend class internal::BoundNodesTree; }; -/// \brief If the provided matcher matches a node, binds the node to 'ID'. +/// \brief If the provided matcher matches a node, binds the node to \c ID. /// -/// FIXME: Add example for accessing it. +/// FIXME: Do we want to support this now that we have bind()? template internal::Matcher id(const std::string &ID, const internal::BindableMatcher &InnerMatcher) { @@ -113,20 +108,27 @@ internal::Matcher id(const std::string &ID, /// hierarchy. /// @{ typedef internal::Matcher DeclarationMatcher; -typedef internal::Matcher TypeMatcher; typedef internal::Matcher StatementMatcher; +typedef internal::Matcher TypeMatcher; +typedef internal::Matcher TypeLocMatcher; +typedef internal::Matcher NestedNameSpecifierMatcher; +typedef internal::Matcher NestedNameSpecifierLocMatcher; /// @} /// \brief Matches any node. /// /// Useful when another matcher requires a child matcher, but there's no /// additional constraint. This will often be used with an explicit conversion -/// to a internal::Matcher<> type such as TypeMatcher. +/// to an \c internal::Matcher<> type such as \c TypeMatcher. /// -/// Example: DeclarationMatcher(anything()) matches all declarations, e.g., +/// Example: \c DeclarationMatcher(anything()) matches all declarations, e.g., +/// \code /// "int* p" and "void f()" in /// int* p; /// void f(); +/// \endcode +/// +/// Usable as: Any Matcher inline internal::PolymorphicMatcherWithParam0 anything() { return internal::PolymorphicMatcherWithParam0(); } @@ -144,53 +146,69 @@ const internal::VariadicDynCastAllOfMatcher decl; /// \brief Matches a declaration of anything that could have a name. /// -/// Example matches X, S, the anonymous union type, i, and U; +/// Example matches \c X, \c S, the anonymous union type, \c i, and \c U; +/// \code /// typedef int X; /// struct S { /// union { /// int i; /// } U; /// }; -const internal::VariadicDynCastAllOfMatcher< - Decl, - NamedDecl> nameableDeclaration; +/// \endcode +const internal::VariadicDynCastAllOfMatcher namedDecl; /// \brief Matches C++ class declarations. /// -/// Example matches X, Z +/// Example matches \c X, \c Z +/// \code /// class X; /// template class Z {}; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + CXXRecordDecl> recordDecl; + +/// \brief Matches C++ class template declarations. +/// +/// Example matches \c Z +/// \code +/// template class Z {}; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Decl, - CXXRecordDecl> record; + ClassTemplateDecl> classTemplateDecl; /// \brief Matches C++ class template specializations. /// /// Given +/// \code /// template class A {}; /// template<> class A {}; /// A a; -/// classTemplateSpecialization() +/// \endcode +/// classTemplateSpecializationDecl() /// matches the specializations \c A and \c A const internal::VariadicDynCastAllOfMatcher< Decl, - ClassTemplateSpecializationDecl> classTemplateSpecialization; + ClassTemplateSpecializationDecl> classTemplateSpecializationDecl; /// \brief Matches classTemplateSpecializations that have at least one -/// TemplateArgument matching the given Matcher. +/// TemplateArgument matching the given InnerMatcher. /// /// Given +/// \code /// template class A {}; /// template<> class A {}; /// A a; -/// classTemplateSpecialization(hasAnyTemplateArgument( +/// \endcode +/// classTemplateSpecializationDecl(hasAnyTemplateArgument( /// refersToType(asString("int")))) /// matches the specialization \c A AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument, - internal::Matcher, Matcher) { + internal::Matcher, InnerMatcher) { const TemplateArgumentList &List = Node.getTemplateArgs(); for (unsigned i = 0; i < List.size(); ++i) { - if (Matcher.matches(List.get(i), Finder, Builder)) + if (InnerMatcher.matches(List.get(i), Finder, Builder)) return true; } return false; @@ -201,19 +219,25 @@ AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument, /// /// Parentheses and explicit casts are not discarded. /// Given +/// \code /// int arr[5]; /// int a = 0; /// char b = 0; /// const int c = a; /// int *d = arr; /// long e = (long) 0l; +/// \endcode /// The matchers -/// variable(hasInitializer(ignoringImpCasts(integerLiteral()))) -/// variable(hasInitializer(ignoringImpCasts(declarationReference()))) +/// \code +/// varDecl(hasInitializer(ignoringImpCasts(integerLiteral()))) +/// varDecl(hasInitializer(ignoringImpCasts(declRefExpr()))) +/// \endcode /// would match the declarations for a, b, c, and d, but not e. -/// while -/// variable(hasInitializer(integerLiteral())) -/// variable(hasInitializer(declarationReference())) +/// While +/// \code +/// varDecl(hasInitializer(integerLiteral())) +/// varDecl(hasInitializer(declRefExpr())) +/// \endcode /// only match the declarations for b, c, and d. AST_MATCHER_P(Expr, ignoringImpCasts, internal::Matcher, InnerMatcher) { @@ -225,15 +249,17 @@ AST_MATCHER_P(Expr, ignoringImpCasts, /// /// Implicit and non-C Style casts are also discarded. /// Given +/// \code /// int a = 0; /// char b = (0); /// void* c = reinterpret_cast(0); /// char d = char(0); +/// \endcode /// The matcher -/// variable(hasInitializer(ignoringParenCasts(integerLiteral()))) +/// varDecl(hasInitializer(ignoringParenCasts(integerLiteral()))) /// would match the declarations for a, b, c, and d. /// while -/// variable(hasInitializer(integerLiteral())) +/// varDecl(hasInitializer(integerLiteral())) /// only match the declaration for a. AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher, InnerMatcher) { return InnerMatcher.matches(*Node.IgnoreParenCasts(), Finder, Builder); @@ -244,21 +270,21 @@ AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher, InnerMatcher) { /// /// Explicit casts are not discarded. /// Given +/// \code /// int arr[5]; /// int a = 0; /// char b = (0); /// const int c = a; /// int *d = (arr); /// long e = ((long) 0l); +/// \endcode /// The matchers -/// variable(hasInitializer(ignoringParenImpCasts( -/// integerLiteral()))) -/// variable(hasInitializer(ignoringParenImpCasts( -/// declarationReference()))) +/// varDecl(hasInitializer(ignoringParenImpCasts(integerLiteral()))) +/// varDecl(hasInitializer(ignoringParenImpCasts(declRefExpr()))) /// would match the declarations for a, b, c, and d, but not e. /// while -/// variable(hasInitializer(integerLiteral())) -/// variable(hasInitializer(declarationReference())) +/// varDecl(hasInitializer(integerLiteral())) +/// varDecl(hasInitializer(declRefExpr())) /// would only match the declaration for a. AST_MATCHER_P(Expr, ignoringParenImpCasts, internal::Matcher, InnerMatcher) { @@ -266,101 +292,119 @@ AST_MATCHER_P(Expr, ignoringParenImpCasts, } /// \brief Matches classTemplateSpecializations where the n'th TemplateArgument -/// matches the given Matcher. +/// matches the given InnerMatcher. /// /// Given +/// \code /// template class A {}; /// A b; /// A c; -/// classTemplateSpecialization(hasTemplateArgument( +/// \endcode +/// classTemplateSpecializationDecl(hasTemplateArgument( /// 1, refersToType(asString("int")))) /// matches the specialization \c A AST_MATCHER_P2(ClassTemplateSpecializationDecl, hasTemplateArgument, - unsigned, N, internal::Matcher, Matcher) { + unsigned, N, internal::Matcher, InnerMatcher) { const TemplateArgumentList &List = Node.getTemplateArgs(); if (List.size() <= N) return false; - return Matcher.matches(List.get(N), Finder, Builder); + return InnerMatcher.matches(List.get(N), Finder, Builder); } /// \brief Matches a TemplateArgument that refers to a certain type. /// /// Given +/// \code /// struct X {}; /// template struct A {}; /// A a; -/// classTemplateSpecialization(hasAnyTemplateArgument( +/// \endcode +/// classTemplateSpecializationDecl(hasAnyTemplateArgument( /// refersToType(class(hasName("X"))))) /// matches the specialization \c A AST_MATCHER_P(TemplateArgument, refersToType, - internal::Matcher, Matcher) { + internal::Matcher, InnerMatcher) { if (Node.getKind() != TemplateArgument::Type) return false; - return Matcher.matches(Node.getAsType(), Finder, Builder); + return InnerMatcher.matches(Node.getAsType(), Finder, Builder); } /// \brief Matches a TemplateArgument that refers to a certain declaration. /// /// Given +/// \code /// template struct A {}; /// struct B { B* next; }; /// A<&B::next> a; -/// classTemplateSpecialization(hasAnyTemplateArgument( -/// refersToDeclaration(field(hasName("next")))) -/// matches the specialization \c A<&B::next> with \c field(...) matching +/// \endcode +/// classTemplateSpecializationDecl(hasAnyTemplateArgument( +/// refersToDeclaration(fieldDecl(hasName("next")))) +/// matches the specialization \c A<&B::next> with \c fieldDecl(...) matching /// \c B::next AST_MATCHER_P(TemplateArgument, refersToDeclaration, - internal::Matcher, Matcher) { - if (const Decl *Declaration = Node.getAsDecl()) - return Matcher.matches(*Declaration, Finder, Builder); + internal::Matcher, InnerMatcher) { + if (Node.getKind() == TemplateArgument::Declaration) + return InnerMatcher.matches(*Node.getAsDecl(), Finder, Builder); return false; } /// \brief Matches C++ constructor declarations. /// /// Example matches Foo::Foo() and Foo::Foo(int) +/// \code /// class Foo { /// public: /// Foo(); /// Foo(int); /// int DoSomething(); /// }; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Decl, - CXXConstructorDecl> constructor; + CXXConstructorDecl> constructorDecl; /// \brief Matches explicit C++ destructor declarations. /// /// Example matches Foo::~Foo() +/// \code /// class Foo { /// public: /// virtual ~Foo(); /// }; -const internal::VariadicDynCastAllOfMatcher destructor; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + CXXDestructorDecl> destructorDecl; /// \brief Matches enum declarations. /// /// Example matches X +/// \code /// enum X { /// A, B, C /// }; +/// \endcode const internal::VariadicDynCastAllOfMatcher enumDecl; /// \brief Matches enum constants. /// /// Example matches A, B, C +/// \code /// enum X { /// A, B, C /// }; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Decl, - EnumConstantDecl> enumConstant; + EnumConstantDecl> enumConstantDecl; /// \brief Matches method declarations. /// /// Example matches y +/// \code /// class X { void y() }; -const internal::VariadicDynCastAllOfMatcher method; +/// \endcode +const internal::VariadicDynCastAllOfMatcher methodDecl; /// \brief Matches variable declarations. /// @@ -368,76 +412,111 @@ const internal::VariadicDynCastAllOfMatcher method; /// "field" declarations in Clang parlance. /// /// Example matches a +/// \code /// int a; -const internal::VariadicDynCastAllOfMatcher variable; +/// \endcode +const internal::VariadicDynCastAllOfMatcher varDecl; /// \brief Matches field declarations. /// /// Given +/// \code /// class X { int m; }; -/// field() +/// \endcode +/// fieldDecl() /// matches 'm'. -const internal::VariadicDynCastAllOfMatcher field; +const internal::VariadicDynCastAllOfMatcher fieldDecl; /// \brief Matches function declarations. /// /// Example matches f +/// \code /// void f(); -const internal::VariadicDynCastAllOfMatcher function; +/// \endcode +const internal::VariadicDynCastAllOfMatcher functionDecl; +/// \brief Matches C++ function template declarations. +/// +/// Example matches f +/// \code +/// template void f(T t) {} +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + FunctionTemplateDecl> functionTemplateDecl; /// \brief Matches statements. /// /// Given +/// \code /// { ++a; } -/// statement() +/// \endcode +/// stmt() /// matches both the compound statement '{ ++a; }' and '++a'. -const internal::VariadicDynCastAllOfMatcher statement; +const internal::VariadicDynCastAllOfMatcher stmt; /// \brief Matches declaration statements. /// /// Given +/// \code /// int a; -/// declarationStatement() +/// \endcode +/// declStmt() /// matches 'int a'. const internal::VariadicDynCastAllOfMatcher< Stmt, - DeclStmt> declarationStatement; + DeclStmt> declStmt; /// \brief Matches member expressions. /// /// Given +/// \code /// class Y { /// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } /// int a; static int b; /// }; -/// memberExpression() +/// \endcode +/// memberExpr() /// matches this->x, x, y.x, a, this->b -const internal::VariadicDynCastAllOfMatcher< - Stmt, - MemberExpr> memberExpression; +const internal::VariadicDynCastAllOfMatcher memberExpr; /// \brief Matches call expressions. /// /// Example matches x.y() and y() +/// \code /// X x; /// x.y(); /// y(); -const internal::VariadicDynCastAllOfMatcher call; +/// \endcode +const internal::VariadicDynCastAllOfMatcher callExpr; + +/// \brief Matches lambda expressions. +/// +/// Example matches [&](){return 5;} +/// \code +/// [&](){return 5;} +/// \endcode +const internal::VariadicDynCastAllOfMatcher lambdaExpr; /// \brief Matches member call expressions. /// /// Example matches x.y() +/// \code /// X x; /// x.y(); -const internal::VariadicDynCastAllOfMatcher memberCall; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXMemberCallExpr> memberCallExpr; /// \brief Matches init list expressions. /// /// Given +/// \code /// int a[] = { 1, 2 }; /// struct B { int x, y; }; /// B b = { 5, 6 }; +/// \endcode /// initList() /// matches "{ 1, 2 }" and "{ 5, 6 }" const internal::VariadicDynCastAllOfMatcher initListExpr; @@ -445,8 +524,10 @@ const internal::VariadicDynCastAllOfMatcher initListExpr; /// \brief Matches using declarations. /// /// Given +/// \code /// namespace X { int x; } /// using X::x; +/// \endcode /// usingDecl() /// matches \code using X::x \endcode const internal::VariadicDynCastAllOfMatcher usingDecl; @@ -454,49 +535,89 @@ const internal::VariadicDynCastAllOfMatcher usingDecl; /// \brief Matches constructor call expressions (including implicit ones). /// /// Example matches string(ptr, n) and ptr within arguments of f -/// (matcher = constructorCall()) +/// (matcher = constructExpr()) +/// \code /// void f(const string &a, const string &b); /// char *ptr; /// int n; /// f(string(ptr, n), ptr); +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXConstructExpr> constructorCall; + CXXConstructExpr> constructExpr; + +/// \brief Matches implicit and explicit this expressions. +/// +/// Example matches the implicit this expression in "return i". +/// (matcher = thisExpr()) +/// \code +/// struct foo { +/// int i; +/// int f() { return i; } +/// }; +/// \endcode +const internal::VariadicDynCastAllOfMatcher thisExpr; /// \brief Matches nodes where temporaries are created. /// /// Example matches FunctionTakesString(GetStringByValue()) -/// (matcher = bindTemporaryExpression()) +/// (matcher = bindTemporaryExpr()) +/// \code /// FunctionTakesString(GetStringByValue()); /// FunctionTakesStringByPointer(GetStringPointer()); +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXBindTemporaryExpr> bindTemporaryExpression; + CXXBindTemporaryExpr> bindTemporaryExpr; + +/// \brief Matches nodes where temporaries are materialized. +/// +/// Example: Given +/// \code +/// struct T {void func()}; +/// T f(); +/// void g(T); +/// \endcode +/// materializeTemporaryExpr() matches 'f()' in these statements +/// \code +/// T u(f()); +/// g(f()); +/// \endcode +/// but does not match +/// \code +/// f(); +/// f().func(); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + MaterializeTemporaryExpr> materializeTemporaryExpr; /// \brief Matches new expressions. /// /// Given +/// \code /// new X; -/// newExpression() +/// \endcode +/// newExpr() /// matches 'new X'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXNewExpr> newExpression; +const internal::VariadicDynCastAllOfMatcher newExpr; /// \brief Matches delete expressions. /// /// Given +/// \code /// delete X; -/// deleteExpression() +/// \endcode +/// deleteExpr() /// matches 'delete X'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXDeleteExpr> deleteExpression; +const internal::VariadicDynCastAllOfMatcher deleteExpr; /// \brief Matches array subscript expressions. /// /// Given +/// \code /// int i = a[1]; +/// \endcode /// arraySubscriptExpr() /// matches "a[1]" const internal::VariadicDynCastAllOfMatcher< @@ -507,12 +628,14 @@ const internal::VariadicDynCastAllOfMatcher< /// /// Example matches the CXXDefaultArgExpr placeholder inserted for the /// default value of the second parameter in the call expression f(42) -/// (matcher = defaultArgument()) +/// (matcher = defaultArgExpr()) +/// \code /// void f(int x, int y = 0); /// f(42); +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXDefaultArgExpr> defaultArgument; + CXXDefaultArgExpr> defaultArgExpr; /// \brief Matches overloaded operator calls. /// @@ -522,50 +645,67 @@ const internal::VariadicDynCastAllOfMatcher< /// FIXME: figure out why these do not match? /// /// Example matches both operator<<((o << b), c) and operator<<(o, b) -/// (matcher = overloadedOperatorCall()) +/// (matcher = operatorCallExpr()) +/// \code /// ostream &operator<< (ostream &out, int i) { }; /// ostream &o; int b = 1, c = 1; /// o << b << c; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXOperatorCallExpr> overloadedOperatorCall; + CXXOperatorCallExpr> operatorCallExpr; /// \brief Matches expressions. /// /// Example matches x() +/// \code /// void f() { x(); } -const internal::VariadicDynCastAllOfMatcher< - Stmt, - Expr> expression; +/// \endcode +const internal::VariadicDynCastAllOfMatcher expr; /// \brief Matches expressions that refer to declarations. /// /// Example matches x in if (x) +/// \code /// bool x; /// if (x) {} -const internal::VariadicDynCastAllOfMatcher< - Stmt, - DeclRefExpr> declarationReference; +/// \endcode +const internal::VariadicDynCastAllOfMatcher declRefExpr; /// \brief Matches if statements. /// /// Example matches 'if (x) {}' +/// \code /// if (x) {} +/// \endcode const internal::VariadicDynCastAllOfMatcher ifStmt; /// \brief Matches for statements. /// /// Example matches 'for (;;) {}' +/// \code /// for (;;) {} -const internal::VariadicDynCastAllOfMatcher< - Stmt, ForStmt> forStmt; +/// int i[] = {1, 2, 3}; for (auto a : i); +/// \endcode +const internal::VariadicDynCastAllOfMatcher forStmt; + +/// \brief Matches range-based for statements. +/// +/// forRangeStmt() matches 'for (auto a : i)' +/// \code +/// int i[] = {1, 2, 3}; for (auto a : i); +/// for(int j = 0; j < 5; ++j); +/// \endcode +const internal::VariadicDynCastAllOfMatcher forRangeStmt; /// \brief Matches the increment statement of a for loop. /// /// Example: /// forStmt(hasIncrement(unaryOperator(hasOperatorName("++")))) /// matches '++x' in +/// \code /// for (x; x < N; ++x) { } +/// \endcode AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher, InnerMatcher) { const Stmt *const Increment = Node.getInc(); @@ -576,9 +716,11 @@ AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher, /// \brief Matches the initialization statement of a for loop. /// /// Example: -/// forStmt(hasLoopInit(declarationStatement())) +/// forStmt(hasLoopInit(declStmt())) /// matches 'int x = 0' in +/// \code /// for (int x = 0; x < N; ++x) { } +/// \endcode AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher, InnerMatcher) { const Stmt *const Init = Node.getInit(); @@ -588,53 +730,167 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher, /// \brief Matches while statements. /// /// Given +/// \code /// while (true) {} +/// \endcode /// whileStmt() /// matches 'while (true) {}'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - WhileStmt> whileStmt; +const internal::VariadicDynCastAllOfMatcher whileStmt; /// \brief Matches do statements. /// /// Given +/// \code /// do {} while (true); +/// \endcode /// doStmt() /// matches 'do {} while(true)' const internal::VariadicDynCastAllOfMatcher doStmt; +/// \brief Matches break statements. +/// +/// Given +/// \code +/// while (true) { break; } +/// \endcode +/// breakStmt() +/// matches 'break' +const internal::VariadicDynCastAllOfMatcher breakStmt; + +/// \brief Matches continue statements. +/// +/// Given +/// \code +/// while (true) { continue; } +/// \endcode +/// continueStmt() +/// matches 'continue' +const internal::VariadicDynCastAllOfMatcher continueStmt; + +/// \brief Matches return statements. +/// +/// Given +/// \code +/// return 1; +/// \endcode +/// returnStmt() +/// matches 'return 1' +const internal::VariadicDynCastAllOfMatcher returnStmt; + +/// \brief Matches goto statements. +/// +/// Given +/// \code +/// goto FOO; +/// FOO: bar(); +/// \endcode +/// gotoStmt() +/// matches 'goto FOO' +const internal::VariadicDynCastAllOfMatcher gotoStmt; + +/// \brief Matches label statements. +/// +/// Given +/// \code +/// goto FOO; +/// FOO: bar(); +/// \endcode +/// labelStmt() +/// matches 'FOO:' +const internal::VariadicDynCastAllOfMatcher labelStmt; + +/// \brief Matches switch statements. +/// +/// Given +/// \code +/// switch(a) { case 42: break; default: break; } +/// \endcode +/// switchStmt() +/// matches 'switch(a)'. +const internal::VariadicDynCastAllOfMatcher switchStmt; + /// \brief Matches case and default statements inside switch statements. /// /// Given +/// \code /// switch(a) { case 42: break; default: break; } +/// \endcode /// switchCase() /// matches 'case 42: break;' and 'default: break;'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - SwitchCase> switchCase; +const internal::VariadicDynCastAllOfMatcher switchCase; /// \brief Matches compound statements. /// /// Example matches '{}' and '{{}}'in 'for (;;) {{}}' +/// \code /// for (;;) {{}} -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CompoundStmt> compoundStatement; +/// \endcode +const internal::VariadicDynCastAllOfMatcher compoundStmt; + +/// \brief Matches catch statements. +/// +/// \code +/// try {} catch(int i) {} +/// \endcode +/// catchStmt() +/// matches 'catch(int i)' +const internal::VariadicDynCastAllOfMatcher catchStmt; + +/// \brief Matches try statements. +/// +/// \code +/// try {} catch(int i) {} +/// \endcode +/// tryStmt() +/// matches 'try {}' +const internal::VariadicDynCastAllOfMatcher tryStmt; + +/// \brief Matches throw expressions. +/// +/// \code +/// try { throw 5; } catch(int i) {} +/// \endcode +/// throwExpr() +/// matches 'throw 5' +const internal::VariadicDynCastAllOfMatcher throwExpr; + +/// \brief Matches null statements. +/// +/// \code +/// foo();; +/// \endcode +/// nullStmt() +/// matches the second ';' +const internal::VariadicDynCastAllOfMatcher nullStmt; + +/// \brief Matches asm statements. +/// +/// \code +/// int i = 100; +/// __asm("mov al, 2"); +/// \endcode +/// asmStmt() +/// matches '__asm("mov al, 2")' +const internal::VariadicDynCastAllOfMatcher asmStmt; /// \brief Matches bool literals. /// /// Example matches true +/// \code /// true +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, CXXBoolLiteralExpr> boolLiteral; /// \brief Matches string literals (also matches wide string literals). /// /// Example matches "abcd", L"abcd" +/// \code /// char *s = "abcd"; wchar_t *ws = L"abcd" +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, StringLiteral> stringLiteral; /// \brief Matches character literals (also matches wchar_t). @@ -643,9 +899,11 @@ const internal::VariadicDynCastAllOfMatcher< /// though. /// /// Example matches 'a', L'a' +/// \code /// char ch = 'a'; wchar_t chw = L'a'; +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, CharacterLiteral> characterLiteral; /// \brief Matches integer literals of all sizes / encodings. @@ -654,13 +912,27 @@ const internal::VariadicDynCastAllOfMatcher< /// /// Example matches 1, 1L, 0x1, 1U const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, IntegerLiteral> integerLiteral; +/// \brief Matches user defined literal operator call. +/// +/// Example match: "foo"_suffix +const internal::VariadicDynCastAllOfMatcher< + Stmt, + UserDefinedLiteral> userDefinedLiteral; + +/// \brief Matches nullptr literal. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXNullPtrLiteralExpr> nullPtrLiteralExpr; + /// \brief Matches binary operator expressions. /// /// Example matches a || b +/// \code /// !(a || b) +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, BinaryOperator> binaryOperator; @@ -668,7 +940,9 @@ const internal::VariadicDynCastAllOfMatcher< /// \brief Matches unary operator expressions. /// /// Example matches !a +/// \code /// !a || b +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, UnaryOperator> unaryOperator; @@ -676,7 +950,9 @@ const internal::VariadicDynCastAllOfMatcher< /// \brief Matches conditional operator expressions. /// /// Example matches a ? b : c +/// \code /// (a ? b : c) + 42 +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, ConditionalOperator> conditionalOperator; @@ -688,10 +964,12 @@ const internal::VariadicDynCastAllOfMatcher< /// more readable. /// /// Example matches reinterpret_cast(&p) in +/// \code /// void* p = reinterpret_cast(&p); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXReinterpretCastExpr> reinterpretCast; + Stmt, + CXXReinterpretCastExpr> reinterpretCastExpr; /// \brief Matches a C++ static_cast expression. /// @@ -699,38 +977,54 @@ const internal::VariadicDynCastAllOfMatcher< /// \see reinterpretCast /// /// Example: -/// staticCast() +/// staticCastExpr() /// matches /// static_cast(8) /// in +/// \code /// long eight(static_cast(8)); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXStaticCastExpr> staticCast; + Stmt, + CXXStaticCastExpr> staticCastExpr; /// \brief Matches a dynamic_cast expression. /// /// Example: -/// dynamicCast() +/// dynamicCastExpr() /// matches /// dynamic_cast(&b); /// in +/// \code /// struct B { virtual ~B() {} }; struct D : B {}; /// B b; /// D* p = dynamic_cast(&b); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXDynamicCastExpr> dynamicCast; + Stmt, + CXXDynamicCastExpr> dynamicCastExpr; /// \brief Matches a const_cast expression. /// /// Example: Matches const_cast(&r) in +/// \code /// int n = 42; -/// const int& r(n); +/// const int &r(n); /// int* p = const_cast(&r); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXConstCastExpr> constCast; + Stmt, + CXXConstCastExpr> constCastExpr; + +/// \brief Matches a C-style cast expression. +/// +/// Example: Matches (int*) 2.2f in +/// \code +/// int i = (int) 2.2f; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CStyleCastExpr> cStyleCastExpr; /// \brief Matches explicit cast expressions. /// @@ -746,98 +1040,127 @@ const internal::VariadicDynCastAllOfMatcher< /// \see hasDestinationType. /// /// Example: matches all five of the casts in +/// \code /// int((int)(reinterpret_cast(static_cast(const_cast(42))))) +/// \endcode /// but does not match the implicit conversion in +/// \code /// long ell = 42; +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - ExplicitCastExpr> explicitCast; + Stmt, + ExplicitCastExpr> explicitCastExpr; /// \brief Matches the implicit cast nodes of Clang's AST. /// /// This matches many different places, including function call return value /// eliding, as well as any type conversions. const internal::VariadicDynCastAllOfMatcher< - Expr, - ImplicitCastExpr> implicitCast; + Stmt, + ImplicitCastExpr> implicitCastExpr; /// \brief Matches any cast nodes of Clang's AST. /// /// Example: castExpr() matches each of the following: +/// \code /// (int) 3; /// const_cast(SubExpr); /// char c = 0; +/// \endcode /// but does not match +/// \code /// int i = (0); /// int k = 0; -const internal::VariadicDynCastAllOfMatcher< - Expr, - CastExpr> castExpr; +/// \endcode +const internal::VariadicDynCastAllOfMatcher castExpr; /// \brief Matches functional cast expressions /// /// Example: Matches Foo(bar); +/// \code /// Foo f = bar; /// Foo g = (Foo) bar; /// Foo h = Foo(bar); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXFunctionalCastExpr> functionalCast; + Stmt, + CXXFunctionalCastExpr> functionalCastExpr; + +/// \brief Matches \c QualTypes in the clang AST. +const internal::VariadicAllOfMatcher qualType; + +/// \brief Matches \c Types in the clang AST. +const internal::VariadicDynCastAllOfMatcher type; + +/// \brief Matches \c TypeLocs in the clang AST. +const internal::VariadicDynCastAllOfMatcher typeLoc; /// \brief Various overloads for the anyOf matcher. /// @{ -template -internal::PolymorphicMatcherWithParam2 -anyOf(const C1 &P1, const C2 &P2) { + +/// \brief Matches if any of the given matchers matches. +/// +/// Usable as: Any Matcher +template +internal::PolymorphicMatcherWithParam2 +anyOf(const M1 &P1, const M2 &P2) { return internal::PolymorphicMatcherWithParam2(P1, P2); + M1, M2 >(P1, P2); } -template -internal::PolymorphicMatcherWithParam2 > -anyOf(const C1 &P1, const C2 &P2, const C3 &P3) { +template +internal::PolymorphicMatcherWithParam2 > +anyOf(const M1 &P1, const M2 &P2, const M3 &P3) { return anyOf(P1, anyOf(P2, P3)); } -template -internal::PolymorphicMatcherWithParam2 +internal::PolymorphicMatcherWithParam2 > > -anyOf(const C1 &P1, const C2 &P2, const C3 &P3, const C4 &P4) { + M3, M4> > > +anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) { return anyOf(P1, anyOf(P2, anyOf(P3, P4))); } -template -internal::PolymorphicMatcherWithParam2 +internal::PolymorphicMatcherWithParam2 > > > -anyOf(const C1& P1, const C2& P2, const C3& P3, const C4& P4, const C5& P5) { + M4, M5> > > > +anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) { return anyOf(P1, anyOf(P2, anyOf(P3, anyOf(P4, P5)))); } + /// @} /// \brief Various overloads for the allOf matcher. /// @{ -template -internal::PolymorphicMatcherWithParam2 -allOf(const C1 &P1, const C2 &P2) { + +/// \brief Matches if all given matchers match. +/// +/// Usable as: Any Matcher +template +internal::PolymorphicMatcherWithParam2 +allOf(const M1 &P1, const M2 &P2) { return internal::PolymorphicMatcherWithParam2(P1, P2); + M1, M2>(P1, P2); } -template -internal::PolymorphicMatcherWithParam2 > -allOf(const C1& P1, const C2& P2, const C3& P3) { +template +internal::PolymorphicMatcherWithParam2 > +allOf(const M1 &P1, const M2 &P2, const M3 &P3) { return allOf(P1, allOf(P2, P3)); } + /// @} /// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL) /// /// Given +/// \code /// Foo x = bar; /// int y = sizeof(x) + alignof(x); +/// \endcode /// unaryExprOrTypeTraitExpr() /// matches \c sizeof(x) and \c alignof(x) const internal::VariadicDynCastAllOfMatcher< @@ -847,20 +1170,24 @@ const internal::VariadicDynCastAllOfMatcher< /// \brief Matches unary expressions that have a specific type of argument. /// /// Given +/// \code /// int a, c; float b; int s = sizeof(a) + sizeof(b) + alignof(c); +/// \endcode /// unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int")) /// matches \c sizeof(a) and \c alignof(c) AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType, - internal::Matcher, Matcher) { + internal::Matcher, InnerMatcher) { const QualType ArgumentType = Node.getTypeOfArgument(); - return Matcher.matches(ArgumentType, Finder, Builder); + return InnerMatcher.matches(ArgumentType, Finder, Builder); } /// \brief Matches unary expressions of a certain kind. /// /// Given +/// \code /// int x; /// int s = sizeof(x) + alignof(x) +/// \endcode /// unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf)) /// matches \c sizeof(x) AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { @@ -870,17 +1197,17 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { /// \brief Same as unaryExprOrTypeTraitExpr, but only matching /// alignof. inline internal::Matcher alignOfExpr( - const internal::Matcher &Matcher) { + const internal::Matcher &InnerMatcher) { return internal::Matcher(unaryExprOrTypeTraitExpr(allOf( - ofKind(UETT_AlignOf), Matcher))); + ofKind(UETT_AlignOf), InnerMatcher))); } /// \brief Same as unaryExprOrTypeTraitExpr, but only matching /// sizeof. inline internal::Matcher sizeOfExpr( - const internal::Matcher &Matcher) { + const internal::Matcher &InnerMatcher) { return internal::Matcher(unaryExprOrTypeTraitExpr(allOf( - ofKind(UETT_SizeOf), Matcher))); + ofKind(UETT_SizeOf), InnerMatcher))); } /// \brief Matches NamedDecl nodes that have the specified name. @@ -890,10 +1217,14 @@ inline internal::Matcher sizeOfExpr( /// Does not match typedefs of an underlying type with the given name. /// /// Example matches X (Name == "X") +/// \code /// class X; +/// \endcode /// /// Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X") -/// namespace a { namespace b { class X; } } +/// \code +/// namespace a { namespace b { class X; } } +/// \endcode AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { assert(!Name.empty()); const std::string FullNameString = "::" + Node.getQualifiedNameAsString(); @@ -914,10 +1245,14 @@ AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { /// of an underlying type with the given name. /// /// Example matches X (regexp == "::X") +/// \code /// class X; +/// \endcode /// /// Example matches X (regexp is one of "::X", "^foo::.*X", among others) -/// namespace foo { namespace bar { class X; } } +/// \code +/// namespace foo { namespace bar { class X; } } +/// \endcode AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { assert(!RegExp.empty()); std::string FullNameString = "::" + Node.getQualifiedNameAsString(); @@ -931,10 +1266,12 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { /// "operator" prefix, such as "<<", for OverloadedOperatorCall's. /// /// Example matches a << b -/// (matcher == overloadedOperatorCall(hasOverloadedOperatorName("<<"))) +/// (matcher == operatorCallExpr(hasOverloadedOperatorName("<<"))) +/// \code /// a << b; /// c && d; // assuming both operator<< /// // and operator&& are overloaded somewhere. +/// \endcode AST_MATCHER_P(CXXOperatorCallExpr, hasOverloadedOperatorName, std::string, Name) { return getOperatorSpelling(Node.getOperator()) == Name; @@ -943,20 +1280,24 @@ AST_MATCHER_P(CXXOperatorCallExpr, /// \brief Matches C++ classes that are directly or indirectly derived from /// a class matching \c Base. /// -/// Note that a class is considered to be also derived from itself. +/// Note that a class is not considered to be derived from itself. /// -/// Example matches X, Y, Z, C (Base == hasName("X")) -/// class X; // A class is considered to be derived from itself +/// Example matches Y, Z, C (Base == hasName("X")) +/// \code +/// class X; /// class Y : public X {}; // directly derived /// class Z : public Y {}; // indirectly derived /// typedef X A; /// typedef A B; /// class C : public B {}; // derived from a typedef of X +/// \endcode /// /// In the following example, Bar matches isDerivedFrom(hasName("X")): +/// \code /// class Foo; /// typedef Foo X; /// class Bar : public Foo {}; // derived from a type that X is a typedef of +/// \endcode AST_MATCHER_P(CXXRecordDecl, isDerivedFrom, internal::Matcher, Base) { return Finder->classIsDerivedFrom(&Node, Base, Builder); @@ -968,15 +1309,34 @@ inline internal::Matcher isDerivedFrom(StringRef BaseName) { return isDerivedFrom(hasName(BaseName)); } +/// \brief Similar to \c isDerivedFrom(), but also matches classes that directly +/// match \c Base. +inline internal::Matcher isSameOrDerivedFrom( + internal::Matcher Base) { + return anyOf(Base, isDerivedFrom(Base)); +} + +/// \brief Overloaded method as shortcut for +/// \c isSameOrDerivedFrom(hasName(...)). +inline internal::Matcher isSameOrDerivedFrom( + StringRef BaseName) { + assert(!BaseName.empty()); + return isSameOrDerivedFrom(hasName(BaseName)); +} + /// \brief Matches AST nodes that have child AST nodes that match the /// provided matcher. /// -/// Example matches X, Y (matcher = record(has(record(hasName("X"))) +/// Example matches X, Y (matcher = recordDecl(has(recordDecl(hasName("X"))) +/// \code /// class X {}; // Matches X, because X::X is a class of name X inside X. /// class Y { class X {}; }; /// class Z { class Y { class X {}; }; }; // Does not match Z. +/// \endcode /// /// ChildT must be an AST base type. +/// +/// Usable as: Any Matcher template internal::ArgumentAdaptingMatcher has( const internal::Matcher &ChildMatcher) { @@ -988,12 +1348,16 @@ internal::ArgumentAdaptingMatcher has( /// provided matcher. /// /// Example matches X, Y, Z -/// (matcher = record(hasDescendant(record(hasName("X"))))) +/// (matcher = recordDecl(hasDescendant(recordDecl(hasName("X"))))) +/// \code /// class X {}; // Matches X, because X::X is a class of name X inside X. /// class Y { class X {}; }; /// class Z { class Y { class X {}; }; }; +/// \endcode /// /// DescendantT must be an AST base type. +/// +/// Usable as: Any Matcher template internal::ArgumentAdaptingMatcher hasDescendant(const internal::Matcher &DescendantMatcher) { @@ -1002,22 +1366,25 @@ hasDescendant(const internal::Matcher &DescendantMatcher) { DescendantT>(DescendantMatcher); } - /// \brief Matches AST nodes that have child AST nodes that match the /// provided matcher. /// -/// Example matches X, Y (matcher = record(forEach(record(hasName("X"))) +/// Example matches X, Y (matcher = recordDecl(forEach(recordDecl(hasName("X"))) +/// \code /// class X {}; // Matches X, because X::X is a class of name X inside X. /// class Y { class X {}; }; /// class Z { class Y { class X {}; }; }; // Does not match Z. +/// \endcode /// /// ChildT must be an AST base type. /// /// As opposed to 'has', 'forEach' will cause a match for each result that /// matches instead of only on the first one. +/// +/// Usable as: Any Matcher template internal::ArgumentAdaptingMatcher forEach( - const internal::Matcher& ChildMatcher) { + const internal::Matcher &ChildMatcher) { return internal::ArgumentAdaptingMatcher< internal::ForEachMatcher, ChildT>(ChildMatcher); @@ -1027,10 +1394,12 @@ internal::ArgumentAdaptingMatcher forEach( /// provided matcher. /// /// Example matches X, A, B, C -/// (matcher = record(forEachDescendant(record(hasName("X"))))) +/// (matcher = recordDecl(forEachDescendant(recordDecl(hasName("X"))))) +/// \code /// class X {}; // Matches X, because X::X is a class of name X inside X. /// class A { class X {}; }; /// class B { class C { class X {}; }; }; +/// \endcode /// /// DescendantT must be an AST base type. /// @@ -1038,25 +1407,72 @@ internal::ArgumentAdaptingMatcher forEach( /// each result that matches instead of only on the first one. /// /// Note: Recursively combined ForEachDescendant can cause many matches: -/// record(forEachDescendant(record(forEachDescendant(record())))) +/// recordDecl(forEachDescendant(recordDecl(forEachDescendant(recordDecl())))) /// will match 10 times (plus injected class name matches) on: +/// \code /// class A { class B { class C { class D { class E {}; }; }; }; }; +/// \endcode +/// +/// Usable as: Any Matcher template -internal::ArgumentAdaptingMatcher +internal::ArgumentAdaptingMatcher forEachDescendant( - const internal::Matcher& DescendantMatcher) { + const internal::Matcher &DescendantMatcher) { return internal::ArgumentAdaptingMatcher< internal::ForEachDescendantMatcher, DescendantT>(DescendantMatcher); } +/// \brief Matches AST nodes that have a parent that matches the provided +/// matcher. +/// +/// Given +/// \code +/// void f() { for (;;) { int x = 42; if (true) { int x = 43; } } } +/// \endcode +/// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }". +/// +/// Usable as: Any Matcher +template +internal::ArgumentAdaptingMatcher +hasParent(const internal::Matcher &ParentMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::HasParentMatcher, + ParentT>(ParentMatcher); +} + +/// \brief Matches AST nodes that have an ancestor that matches the provided +/// matcher. +/// +/// Given +/// \code +/// void f() { if (true) { int x = 42; } } +/// void g() { for (;;) { int x = 43; } } +/// \endcode +/// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43. +/// +/// Usable as: Any Matcher +template +internal::ArgumentAdaptingMatcher +hasAncestor(const internal::Matcher &AncestorMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::HasAncestorMatcher, + AncestorT>(AncestorMatcher); +} + /// \brief Matches if the provided matcher does not match. /// -/// Example matches Y (matcher = record(unless(hasName("X")))) +/// Example matches Y (matcher = recordDecl(unless(hasName("X")))) +/// \code /// class X {}; /// class Y {}; +/// \endcode +/// +/// Usable as: Any Matcher template -internal::PolymorphicMatcherWithParam1 unless(const M &InnerMatcher) { +internal::PolymorphicMatcherWithParam1 +unless(const M &InnerMatcher) { return internal::PolymorphicMatcherWithParam1< internal::NotMatcher, M>(InnerMatcher); } @@ -1064,7 +1480,8 @@ internal::PolymorphicMatcherWithParam1 unless(const M & /// \brief Matches a type if the declaration of the type matches the given /// matcher. /// -/// Usable as: Matcher, Matcher, Matcher +/// Usable as: Matcher, Matcher, Matcher, +/// Matcher inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher > hasDeclaration(const internal::Matcher &InnerMatcher) { @@ -1075,9 +1492,11 @@ inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, /// \brief Matches on the implicit object argument of a member call expression. /// -/// Example matches y.x() (matcher = call(on(hasType(record(hasName("Y")))))) +/// Example matches y.x() (matcher = callExpr(on(hasType(recordDecl(hasName("Y")))))) +/// \code /// class Y { public: void x(); }; /// void z() { Y y; y.x(); }", +/// \endcode /// /// FIXME: Overload to allow directly matching types? AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher, @@ -1092,9 +1511,11 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher, /// \brief Matches if the call expression's callee expression matches. /// /// Given +/// \code /// class Y { void x() { this->x(); x(); Y y; y.x(); } }; /// void f() { f(); } -/// call(callee(expression())) +/// \endcode +/// callExpr(callee(expr())) /// matches this->x(), x(), y.x(), f() /// with callee(...) /// matching this->x, x, y.x, f respectively @@ -1113,9 +1534,11 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher, /// \brief Matches if the call expression's callee's declaration matches the /// given matcher. /// -/// Example matches y.x() (matcher = call(callee(method(hasName("x"))))) +/// Example matches y.x() (matcher = callExpr(callee(methodDecl(hasName("x"))))) +/// \code /// class Y { public: void x(); }; /// void z() { Y y; y.x(); +/// \endcode inline internal::Matcher callee( const internal::Matcher &InnerMatcher) { return internal::Matcher(hasDeclaration(InnerMatcher)); @@ -1124,12 +1547,12 @@ inline internal::Matcher callee( /// \brief Matches if the expression's or declaration's type matches a type /// matcher. /// -/// Example matches x (matcher = expression(hasType( -/// hasDeclaration(record(hasName("X")))))) -/// and z (matcher = variable(hasType( -/// hasDeclaration(record(hasName("X")))))) +/// Example matches x (matcher = expr(hasType(recordDecl(hasName("X"))))) +/// and z (matcher = varDecl(hasType(recordDecl(hasName("X"))))) +/// \code /// class X {}; /// void y(X &x) { x; X z; } +/// \endcode AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher, InnerMatcher) { TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || @@ -1143,14 +1566,16 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher, /// /// In case of a value declaration (for example a variable declaration), /// this resolves one layer of indirection. For example, in the value -/// declaration "X x;", record(hasName("X")) matches the declaration of X, -/// while variable(hasType(record(hasName("X")))) matches the declaration +/// declaration "X x;", recordDecl(hasName("X")) matches the declaration of X, +/// while varDecl(hasType(recordDecl(hasName("X")))) matches the declaration /// of x." /// -/// Example matches x (matcher = expression(hasType(record(hasName("X"))))) -/// and z (matcher = variable(hasType(record(hasName("X"))))) +/// Example matches x (matcher = expr(hasType(recordDecl(hasName("X"))))) +/// and z (matcher = varDecl(hasType(recordDecl(hasName("X"))))) +/// \code /// class X {}; /// void y(X &x) { x; X z; } +/// \endcode /// /// Usable as: Matcher, Matcher inline internal::PolymorphicMatcherWithParam1< @@ -1164,9 +1589,11 @@ hasType(const internal::Matcher &InnerMatcher) { /// \brief Matches if the matched type is represented by the given string. /// /// Given +/// \code /// class Y { public: void x(); }; /// void z() { Y* y; y->x(); } -/// call(on(hasType(asString("class Y *")))) +/// \endcode +/// callExpr(on(hasType(asString("class Y *")))) /// matches y->x() AST_MATCHER_P(QualType, asString, std::string, Name) { return Name == Node.getAsString(); @@ -1176,9 +1603,11 @@ AST_MATCHER_P(QualType, asString, std::string, Name) { /// matches the specified matcher. /// /// Example matches y->x() -/// (matcher = call(on(hasType(pointsTo(record(hasName("Y"))))))) +/// (matcher = callExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))))) +/// \code /// class Y { public: void x(); }; /// void z() { Y *y; y->x(); } +/// \endcode AST_MATCHER_P( QualType, pointsTo, internal::Matcher, InnerMatcher) { @@ -1197,12 +1626,14 @@ inline internal::Matcher pointsTo( /// type matches the specified matcher. /// /// Example matches X &x and const X &y -/// (matcher = variable(hasType(references(record(hasName("X")))))) +/// (matcher = varDecl(hasType(references(recordDecl(hasName("X")))))) +/// \code /// class X { /// void a(X b) { /// X &x = b; /// const X &y = b; /// }; +/// \endcode AST_MATCHER_P(QualType, references, internal::Matcher, InnerMatcher) { return (!Node.isNull() && Node->isReferenceType() && @@ -1243,9 +1674,11 @@ inline internal::Matcher thisPointerType( /// specified matcher. /// /// Example matches x in if(x) -/// (matcher = declarationReference(to(variable(hasName("x"))))) +/// (matcher = declRefExpr(to(varDecl(hasName("x"))))) +/// \code /// bool x; /// if (x) {} +/// \endcode AST_MATCHER_P(DeclRefExpr, to, internal::Matcher, InnerMatcher) { const Decl *DeclNode = Node.getDecl(); @@ -1259,29 +1692,33 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher, /// FIXME: This currently only works for functions. Fix. /// /// Given +/// \code /// namespace a { void f() {} } /// using a::f; /// void g() { /// f(); // Matches this .. /// a::f(); // .. but not this. /// } -/// declarationReference(throughUsingDeclaration(anything())) +/// \endcode +/// declRefExpr(throughUsingDeclaration(anything())) /// matches \c f() AST_MATCHER_P(DeclRefExpr, throughUsingDecl, - internal::Matcher, Matcher) { + internal::Matcher, InnerMatcher) { const NamedDecl *FoundDecl = Node.getFoundDecl(); if (const UsingShadowDecl *UsingDecl = llvm::dyn_cast(FoundDecl)) - return Matcher.matches(*UsingDecl, Finder, Builder); + return InnerMatcher.matches(*UsingDecl, Finder, Builder); return false; } /// \brief Matches the Decl of a DeclStmt which has a single declaration. /// /// Given +/// \code /// int a, b; /// int c; -/// declarationStatement(hasSingleDecl(anything())) +/// \endcode +/// declStmt(hasSingleDecl(anything())) /// matches 'int c;' but not 'int a, b;'. AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher, InnerMatcher) { if (Node.isSingleDecl()) { @@ -1294,9 +1731,11 @@ AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher, InnerMatcher) { /// \brief Matches a variable declaration that has an initializer expression /// that matches the given matcher. /// -/// Example matches x (matcher = variable(hasInitializer(call()))) +/// Example matches x (matcher = varDecl(hasInitializer(callExpr()))) +/// \code /// bool y() { return true; } /// bool x = y(); +/// \endcode AST_MATCHER_P( VarDecl, hasInitializer, internal::Matcher, InnerMatcher) { @@ -1308,9 +1747,11 @@ AST_MATCHER_P( /// \brief Checks that a call expression or a constructor call expression has /// a specific number of arguments (including absent default arguments). /// -/// Example matches f(0, 0) (matcher = call(argumentCountIs(2))) +/// Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2))) +/// \code /// void f(int x, int y); /// f(0, 0); +/// \endcode AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) { TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || llvm::is_base_of, InnerMatcher) { TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || @@ -1340,13 +1783,15 @@ AST_POLYMORPHIC_MATCHER_P2( /// declarations. /// /// Example: Given +/// \code /// int a, b; /// int c; /// int d = 2, e; +/// \endcode /// declCountIs(2) /// matches 'int a, b;' and 'int d = 2, e;', but not 'int c;'. AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) { - return std::distance(Node.decl_begin(), Node.decl_end()) == N; + return std::distance(Node.decl_begin(), Node.decl_end()) == (ptrdiff_t)N; } /// \brief Matches the n'th declaration of a declaration statement. @@ -1355,15 +1800,19 @@ AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) { /// breaks up multiple-declaration DeclStmt's into multiple single-declaration /// DeclStmt's. /// Example: Given non-global declarations +/// \code /// int a, b = 0; /// int c; /// int d = 2, e; -/// declarationStatement(containsDeclaration( -/// 0, variable(hasInitializer(anything())))) +/// \endcode +/// declStmt(containsDeclaration( +/// 0, varDecl(hasInitializer(anything())))) /// matches only 'int d = 2, e;', and -/// declarationStatement(containsDeclaration(1, variable())) +/// declStmt(containsDeclaration(1, varDecl())) +/// \code /// matches 'int a, b = 0' as well as 'int d = 2, e;' /// but 'int c;' is not matched. +/// \endcode AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N, internal::Matcher, InnerMatcher) { const unsigned NumDecls = std::distance(Node.decl_begin(), Node.decl_end()); @@ -1377,11 +1826,13 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N, /// \brief Matches a constructor initializer. /// /// Given +/// \code /// struct Foo { /// Foo() : foo_(1) { } /// int foo_; /// }; -/// record(has(constructor(hasAnyConstructorInitializer(anything())))) +/// \endcode +/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer(anything())))) /// record matches Foo, hasAnyConstructorInitializer matches foo_(1) AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, internal::Matcher, InnerMatcher) { @@ -1397,11 +1848,13 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, /// \brief Matches the field declaration of a constructor initializer. /// /// Given +/// \code /// struct Foo { /// Foo() : foo_(1) { } /// int foo_; /// }; -/// record(has(constructor(hasAnyConstructorInitializer( +/// \endcode +/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer( /// forField(hasName("foo_")))))) /// matches Foo /// with forField matching foo_ @@ -1415,11 +1868,13 @@ AST_MATCHER_P(CXXCtorInitializer, forField, /// \brief Matches the initializer expression of a constructor initializer. /// /// Given +/// \code /// struct Foo { /// Foo() : foo_(1) { } /// int foo_; /// }; -/// record(has(constructor(hasAnyConstructorInitializer( +/// \endcode +/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer( /// withInitializer(integerLiteral(equals(1))))))) /// matches Foo /// with withInitializer matching (1) @@ -1434,12 +1889,14 @@ AST_MATCHER_P(CXXCtorInitializer, withInitializer, /// code (as opposed to implicitly added by the compiler). /// /// Given +/// \code /// struct Foo { /// Foo() { } /// Foo(int) : foo_("A") { } /// string foo_; /// }; -/// constructor(hasAnyConstructorInitializer(isWritten())) +/// \endcode +/// constructorDecl(hasAnyConstructorInitializer(isWritten())) /// will match Foo(int), but not Foo() AST_MATCHER(CXXCtorInitializer, isWritten) { return Node.isWritten(); @@ -1455,8 +1912,10 @@ AST_MATCHER(CXXConstructorDecl, isImplicit) { /// expression. /// /// Given +/// \code /// void x(int, int, int) { int y; x(1, y, 42); } -/// call(hasAnyArgument(declarationReference())) +/// \endcode +/// callExpr(hasAnyArgument(declRefExpr())) /// matches x(1, y, 42) /// with hasAnyArgument(...) /// matching y @@ -1478,8 +1937,10 @@ AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher, /// \brief Matches the n'th parameter of a function declaration. /// /// Given +/// \code /// class X { void f(int x) {} }; -/// method(hasParameter(0, hasType(variable()))) +/// \endcode +/// methodDecl(hasParameter(0, hasType(varDecl()))) /// matches f(int x) {} /// with hasParameter(...) /// matching int x @@ -1496,8 +1957,10 @@ AST_MATCHER_P2(FunctionDecl, hasParameter, /// Does not match the 'this' parameter of a method. /// /// Given +/// \code /// class X { void f(int x, int y, int z) {} }; -/// method(hasAnyParameter(hasName("y"))) +/// \endcode +/// methodDecl(hasAnyParameter(hasName("y"))) /// matches f(int x, int y, int z) {} /// with hasAnyParameter(...) /// matching int y @@ -1514,20 +1977,25 @@ AST_MATCHER_P(FunctionDecl, hasAnyParameter, /// \brief Matches the return type of a function declaration. /// /// Given: +/// \code /// class X { int f() { return 1; } }; -/// method(returns(asString("int"))) +/// \endcode +/// methodDecl(returns(asString("int"))) /// matches int f() { return 1; } -AST_MATCHER_P(FunctionDecl, returns, internal::Matcher, Matcher) { - return Matcher.matches(Node.getResultType(), Finder, Builder); +AST_MATCHER_P(FunctionDecl, returns, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(Node.getResultType(), Finder, Builder); } /// \brief Matches extern "C" function declarations. /// /// Given: +/// \code /// extern "C" void f() {} /// extern "C" { void g() {} } /// void h() {} -/// function(isExternC()) +/// \endcode +/// functionDecl(isExternC()) /// matches the declaration of f and g, but not the declaration h AST_MATCHER(FunctionDecl, isExternC) { return Node.isExternC(); @@ -1537,7 +2005,9 @@ AST_MATCHER(FunctionDecl, isExternC) { /// or conditional operator. /// /// Example matches true (matcher = hasCondition(boolLiteral(equals(true)))) +/// \code /// if (true) {} +/// \endcode AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher, InnerMatcher) { TOOLING_COMPILE_ASSERT( @@ -1555,7 +2025,9 @@ AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher, /// \brief Matches the condition variable statement in an if statement. /// /// Given +/// \code /// if (A* a = GetAPointer()) {} +/// \endcode /// hasConditionVariableStatment(...) /// matches 'A* a = GetAPointer()'. AST_MATCHER_P(IfStmt, hasConditionVariableStatement, @@ -1569,29 +2041,33 @@ AST_MATCHER_P(IfStmt, hasConditionVariableStatement, /// \brief Matches the index expression of an array subscript expression. /// /// Given +/// \code /// int i[5]; /// void f() { i[1] = 42; } +/// \endcode /// arraySubscriptExpression(hasIndex(integerLiteral())) /// matches \c i[1] with the \c integerLiteral() matching \c 1 AST_MATCHER_P(ArraySubscriptExpr, hasIndex, - internal::Matcher, matcher) { + internal::Matcher, InnerMatcher) { if (const Expr* Expression = Node.getIdx()) - return matcher.matches(*Expression, Finder, Builder); + return InnerMatcher.matches(*Expression, Finder, Builder); return false; } /// \brief Matches the base expression of an array subscript expression. /// /// Given +/// \code /// int i[5]; /// void f() { i[1] = 42; } -/// arraySubscriptExpression(hasBase(implicitCast( -/// hasSourceExpression(declarationReference())))) -/// matches \c i[1] with the \c declarationReference() matching \c i +/// \endcode +/// arraySubscriptExpression(hasBase(implicitCastExpr( +/// hasSourceExpression(declRefExpr())))) +/// matches \c i[1] with the \c declRefExpr() matching \c i AST_MATCHER_P(ArraySubscriptExpr, hasBase, - internal::Matcher, matcher) { + internal::Matcher, InnerMatcher) { if (const Expr* Expression = Node.getBase()) - return matcher.matches(*Expression, Finder, Builder); + return InnerMatcher.matches(*Expression, Finder, Builder); return false; } @@ -1599,10 +2075,12 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase, /// a given body. /// /// Given +/// \code /// for (;;) {} -/// hasBody(compoundStatement()) +/// \endcode +/// hasBody(compoundStmt()) /// matches 'for (;;) {}' -/// with compoundStatement() +/// with compoundStmt() /// matching '{}' AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher, InnerMatcher) { @@ -1620,10 +2098,12 @@ AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher, /// a given matcher. /// /// Given +/// \code /// { {}; 1+2; } -/// hasAnySubstatement(compoundStatement()) +/// \endcode +/// hasAnySubstatement(compoundStmt()) /// matches '{ {}; 1+2; }' -/// with compoundStatement() +/// with compoundStmt() /// matching '{}' AST_MATCHER_P(CompoundStmt, hasAnySubstatement, internal::Matcher, InnerMatcher) { @@ -1639,8 +2119,10 @@ AST_MATCHER_P(CompoundStmt, hasAnySubstatement, /// child statements. /// /// Example: Given +/// \code /// { for (;;) {} } -/// compoundStatement(statementCountIs(0))) +/// \endcode +/// compoundStmt(statementCountIs(0))) /// matches '{}' /// but does not match the outer compound statement. AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) { @@ -1650,7 +2132,9 @@ AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) { /// \brief Matches literals that are equal to the given value. /// /// Example matches true (matcher = boolLiteral(equals(true))) +/// \code /// true +/// \endcode /// /// Usable as: Matcher, Matcher, /// Matcher, Matcher @@ -1666,7 +2150,9 @@ equals(const ValueT &Value) { /// unary). /// /// Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) +/// \code /// !(a || b) +/// \endcode AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) { TOOLING_COMPILE_ASSERT( (llvm::is_base_of::value) || @@ -1678,7 +2164,9 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) { /// \brief Matches the left hand side of binary operator expressions. /// /// Example matches a (matcher = binaryOperator(hasLHS())) +/// \code /// a || b +/// \endcode AST_MATCHER_P(BinaryOperator, hasLHS, internal::Matcher, InnerMatcher) { Expr *LeftHandSide = Node.getLHS(); @@ -1689,7 +2177,9 @@ AST_MATCHER_P(BinaryOperator, hasLHS, /// \brief Matches the right hand side of binary operator expressions. /// /// Example matches b (matcher = binaryOperator(hasRHS())) +/// \code /// a || b +/// \endcode AST_MATCHER_P(BinaryOperator, hasRHS, internal::Matcher, InnerMatcher) { Expr *RightHandSide = Node.getRHS(); @@ -1706,8 +2196,10 @@ inline internal::Matcher hasEitherOperand( /// \brief Matches if the operand of a unary operator matches. /// -/// Example matches true (matcher = hasOperand(boolLiteral(equals(true)))) +/// Example matches true (matcher = hasUnaryOperand(boolLiteral(equals(true)))) +/// \code /// !true +/// \endcode AST_MATCHER_P(UnaryOperator, hasUnaryOperand, internal::Matcher, InnerMatcher) { const Expr * const Operand = Node.getSubExpr(); @@ -1718,8 +2210,8 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand, /// \brief Matches if the cast's source expression matches the given matcher. /// /// Example: matches "a string" (matcher = -/// hasSourceExpression(constructorCall())) -/// +/// hasSourceExpression(constructExpr())) +/// \code /// class URL { URL(string); }; /// URL url = "a string"; AST_MATCHER_P(CastExpr, hasSourceExpression, @@ -1751,7 +2243,9 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType, /// \brief Matches the true branch expression of a conditional operator. /// /// Example matches a +/// \code /// condition ? a : b +/// \endcode AST_MATCHER_P(ConditionalOperator, hasTrueExpression, internal::Matcher, InnerMatcher) { Expr *Expression = Node.getTrueExpr(); @@ -1762,7 +2256,9 @@ AST_MATCHER_P(ConditionalOperator, hasTrueExpression, /// \brief Matches the false branch expression of a conditional operator. /// /// Example matches b +/// \code /// condition ? a : b +/// \endcode AST_MATCHER_P(ConditionalOperator, hasFalseExpression, internal::Matcher, InnerMatcher) { Expr *Expression = Node.getFalseExpr(); @@ -1773,12 +2269,14 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression, /// \brief Matches if a declaration has a body attached. /// /// Example matches A, va, fa +/// \code /// class A {}; /// class B; // Doesn't match, as it has no body. /// int va; /// extern int vb; // Doesn't match, as it doesn't define the variable. /// void fa() {} /// void fb(); // Doesn't match, as it has no body. +/// \endcode /// /// Usable as: Matcher, Matcher, Matcher inline internal::PolymorphicMatcherWithParam0 @@ -1795,13 +2293,15 @@ isDefinition() { /// this to? /// /// Example matches A() in the last line -/// (matcher = constructorCall(hasDeclaration(method( +/// (matcher = constructExpr(hasDeclaration(methodDecl( /// ofClass(hasName("A")))))) +/// \code /// class A { /// public: /// A(); /// }; /// A a = A(); +/// \endcode AST_MATCHER_P(CXXMethodDecl, ofClass, internal::Matcher, InnerMatcher) { const CXXRecordDecl *Parent = Node.getParent(); @@ -1815,12 +2315,14 @@ AST_MATCHER_P(CXXMethodDecl, ofClass, /// Member calls on the implicit this pointer match as called with '->'. /// /// Given +/// \code /// class Y { /// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } /// int a; /// static int b; /// }; -/// memberExpression(isArrow()) +/// \endcode +/// memberExpr(isArrow()) /// matches this->x, x, y.x, a, this->b inline internal::Matcher isArrow() { return makeMatcher(new internal::IsArrowMatcher()); @@ -1829,10 +2331,12 @@ inline internal::Matcher isArrow() { /// \brief Matches QualType nodes that are of integer type. /// /// Given +/// \code /// void a(int); /// void b(long); /// void c(double); -/// function(hasAnyParameter(hasType(isInteger()))) +/// \endcode +/// functionDecl(hasAnyParameter(hasType(isInteger()))) /// matches "a(int)", "b(long)", but not "c(double)". AST_MATCHER(QualType, isInteger) { return Node->isIntegerType(); @@ -1842,12 +2346,14 @@ AST_MATCHER(QualType, isInteger) { /// include "top-level" const. /// /// Given +/// \code /// void a(int); /// void b(int const); /// void c(const int); /// void d(const int*); /// void e(int const) {}; -/// function(hasAnyParameter(hasType(isConstQualified()))) +/// \endcode +/// functionDecl(hasAnyParameter(hasType(isConstQualified()))) /// matches "void b(int const)", "void c(const int)" and /// "void e(int const) {}". It does not match d as there /// is no top-level const on the parameter type "const int *". @@ -1859,10 +2365,12 @@ inline internal::Matcher isConstQualified() { /// given matcher. /// /// Given +/// \code /// struct { int first, second; } first, second; /// int i(second.first); /// int j(first.second); -/// memberExpression(member(hasName("first"))) +/// \endcode +/// memberExpr(member(hasName("first"))) /// matches second.first /// but not first.second (because the member name there is "second"). AST_MATCHER_P(MemberExpr, member, @@ -1874,9 +2382,11 @@ AST_MATCHER_P(MemberExpr, member, /// matched by a given matcher. /// /// Given +/// \code /// struct X { int m; }; /// void f(X x) { x.m; m; } -/// memberExpression(hasObjectExpression(hasType(record(hasName("X"))))))) +/// \endcode +/// memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X"))))))) /// matches "x.m" and "m" /// with hasObjectExpression(...) /// matching "x" and the implicit object expression of "m" which has type X*. @@ -1888,15 +2398,17 @@ AST_MATCHER_P(MemberExpr, hasObjectExpression, /// \brief Matches any using shadow declaration. /// /// Given +/// \code /// namespace X { void b(); } /// using X::b; +/// \endcode /// usingDecl(hasAnyUsingShadowDecl(hasName("b")))) /// matches \code using X::b \endcode AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl, - internal::Matcher, Matcher) { + internal::Matcher, InnerMatcher) { for (UsingDecl::shadow_iterator II = Node.shadow_begin(); II != Node.shadow_end(); ++II) { - if (Matcher.matches(**II, Finder, Builder)) + if (InnerMatcher.matches(**II, Finder, Builder)) return true; } return false; @@ -1906,31 +2418,39 @@ AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl, /// matched by the given matcher. /// /// Given +/// \code /// namespace X { int a; void b(); } /// using X::a; /// using X::b; -/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(function()))) +/// \endcode +/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl()))) /// matches \code using X::b \endcode /// but not \code using X::a \endcode AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, - internal::Matcher, Matcher) { - return Matcher.matches(*Node.getTargetDecl(), Finder, Builder); + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(*Node.getTargetDecl(), Finder, Builder); } /// \brief Matches template instantiations of function, class, or static /// member variable template instantiations. /// /// Given +/// \code /// template class X {}; class A {}; X x; +/// \endcode /// or +/// \code /// template class X {}; class A {}; template class X; -/// record(hasName("::X"), isTemplateInstantiation()) +/// \endcode +/// recordDecl(hasName("::X"), isTemplateInstantiation()) /// matches the template instantiation of X. /// /// But given -/// template class X {}; class A {}; +/// \code +/// template class X {}; class A {}; /// template <> class X {}; X x; -/// record(hasName("::X"), isTemplateInstantiation()) +/// \endcode +/// recordDecl(hasName("::X"), isTemplateInstantiation()) /// does not match, as X is an explicit template specialization. /// /// Usable as: Matcher, Matcher, Matcher @@ -1941,6 +2461,411 @@ isTemplateInstantiation() { internal::IsTemplateInstantiationMatcher>(); } +/// \brief Matches explicit template specializations of function, class, or +/// static member variable template instantiations. +/// +/// Given +/// \code +/// template void A(T t) { } +/// template<> void A(int N) { } +/// \endcode +/// functionDecl(isExplicitTemplateSpecialization()) +/// matches the specialization A(). +/// +/// Usable as: Matcher, Matcher, Matcher +inline internal::PolymorphicMatcherWithParam0< + internal::IsExplicitTemplateSpecializationMatcher> +isExplicitTemplateSpecialization() { + return internal::PolymorphicMatcherWithParam0< + internal::IsExplicitTemplateSpecializationMatcher>(); +} + +/// \brief Matches \c TypeLocs for which the given inner +/// QualType-matcher matches. +inline internal::BindableMatcher loc( + const internal::Matcher &InnerMatcher) { + return internal::BindableMatcher( + new internal::TypeLocTypeMatcher(InnerMatcher)); +} + +/// \brief Matches builtin Types. +/// +/// Given +/// \code +/// struct A {}; +/// A a; +/// int b; +/// float c; +/// bool d; +/// \endcode +/// builtinType() +/// matches "int b", "float c" and "bool d" +AST_TYPE_MATCHER(BuiltinType, builtinType); + +/// \brief Matches all kinds of arrays. +/// +/// Given +/// \code +/// int a[] = { 2, 3 }; +/// int b[4]; +/// void f() { int c[a[0]]; } +/// \endcode +/// arrayType() +/// matches "int a[]", "int b[4]" and "int c[a[0]]"; +AST_TYPE_MATCHER(ArrayType, arrayType); + +/// \brief Matches C99 complex types. +/// +/// Given +/// \code +/// _Complex float f; +/// \endcode +/// complexType() +/// matches "_Complex float f" +AST_TYPE_MATCHER(ComplexType, complexType); + +/// \brief Matches arrays and C99 complex types that have a specific element +/// type. +/// +/// Given +/// \code +/// struct A {}; +/// A a[7]; +/// int b[7]; +/// \endcode +/// arrayType(hasElementType(builtinType())) +/// matches "int b[7]" +/// +/// Usable as: Matcher, Matcher +AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement); + +/// \brief Matches C arrays with a specified constant size. +/// +/// Given +/// \code +/// void() { +/// int a[2]; +/// int b[] = { 2, 3 }; +/// int c[b[0]]; +/// } +/// \endcode +/// constantArrayType() +/// matches "int a[2]" +AST_TYPE_MATCHER(ConstantArrayType, constantArrayType); + +/// \brief Matches \c ConstantArrayType nodes that have the specified size. +/// +/// Given +/// \code +/// int a[42]; +/// int b[2 * 21]; +/// int c[41], d[43]; +/// \endcode +/// constantArrayType(hasSize(42)) +/// matches "int a[42]" and "int b[2 * 21]" +AST_MATCHER_P(ConstantArrayType, hasSize, unsigned, N) { + return Node.getSize() == N; +} + +/// \brief Matches C++ arrays whose size is a value-dependent expression. +/// +/// Given +/// \code +/// template +/// class array { +/// T data[Size]; +/// }; +/// \endcode +/// dependentSizedArrayType +/// matches "T data[Size]" +AST_TYPE_MATCHER(DependentSizedArrayType, dependentSizedArrayType); + +/// \brief Matches C arrays with unspecified size. +/// +/// Given +/// \code +/// int a[] = { 2, 3 }; +/// int b[42]; +/// void f(int c[]) { int d[a[0]]; }; +/// \endcode +/// incompleteArrayType() +/// matches "int a[]" and "int c[]" +AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType); + +/// \brief Matches C arrays with a specified size that is not an +/// integer-constant-expression. +/// +/// Given +/// \code +/// void f() { +/// int a[] = { 2, 3 } +/// int b[42]; +/// int c[a[0]]; +/// \endcode +/// variableArrayType() +/// matches "int c[a[0]]" +AST_TYPE_MATCHER(VariableArrayType, variableArrayType); + +/// \brief Matches \c VariableArrayType nodes that have a specific size +/// expression. +/// +/// Given +/// \code +/// void f(int b) { +/// int a[b]; +/// } +/// \endcode +/// variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to( +/// varDecl(hasName("b"))))))) +/// matches "int a[b]" +AST_MATCHER_P(VariableArrayType, hasSizeExpr, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(*Node.getSizeExpr(), Finder, Builder); +} + +/// \brief Matches atomic types. +/// +/// Given +/// \code +/// _Atomic(int) i; +/// \endcode +/// atomicType() +/// matches "_Atomic(int) i" +AST_TYPE_MATCHER(AtomicType, atomicType); + +/// \brief Matches atomic types with a specific value type. +/// +/// Given +/// \code +/// _Atomic(int) i; +/// _Atomic(float) f; +/// \endcode +/// atomicType(hasValueType(isInteger())) +/// matches "_Atomic(int) i" +/// +/// Usable as: Matcher +AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue); + +/// \brief Matches types nodes representing C++11 auto types. +/// +/// Given: +/// \code +/// auto n = 4; +/// int v[] = { 2, 3 } +/// for (auto i : v) { } +/// \endcode +/// autoType() +/// matches "auto n" and "auto i" +AST_TYPE_MATCHER(AutoType, autoType); + +/// \brief Matches \c AutoType nodes where the deduced type is a specific type. +/// +/// Note: There is no \c TypeLoc for the deduced type and thus no +/// \c getDeducedLoc() matcher. +/// +/// Given +/// \code +/// auto a = 1; +/// auto b = 2.0; +/// \endcode +/// autoType(hasDeducedType(isInteger())) +/// matches "auto a" +/// +/// Usable as: Matcher +AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType); + +/// \brief Matches \c FunctionType nodes. +/// +/// Given +/// \code +/// int (*f)(int); +/// void g(); +/// \endcode +/// functionType() +/// matches "int (*f)(int)" and the type of "g". +AST_TYPE_MATCHER(FunctionType, functionType); + +/// \brief Matches block pointer types, i.e. types syntactically represented as +/// "void (^)(int)". +/// +/// The \c pointee is always required to be a \c FunctionType. +AST_TYPE_MATCHER(BlockPointerType, blockPointerType); + +/// \brief Matches member pointer types. +/// Given +/// \code +/// struct A { int i; } +/// A::* ptr = A::i; +/// \endcode +/// memberPointerType() +/// matches "A::* ptr" +AST_TYPE_MATCHER(MemberPointerType, memberPointerType); + +/// \brief Matches pointer types. +/// +/// Given +/// \code +/// int *a; +/// int &b = *a; +/// int c = 5; +/// \endcode +/// pointerType() +/// matches "int *a" +AST_TYPE_MATCHER(PointerType, pointerType); + +/// \brief Matches reference types. +/// +/// Given +/// \code +/// int *a; +/// int &b = *a; +/// int c = 5; +/// \endcode +/// pointerType() +/// matches "int &b" +AST_TYPE_MATCHER(ReferenceType, referenceType); + +/// \brief Narrows PointerType (and similar) matchers to those where the +/// \c pointee matches a given matcher. +/// +/// Given +/// \code +/// int *a; +/// int const *b; +/// float const *f; +/// \endcode +/// pointerType(pointee(isConstQualified(), isInteger())) +/// matches "int const *b" +/// +/// Usable as: Matcher, Matcher, +/// Matcher, Matcher +AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee); + +/// \brief Matches typedef types. +/// +/// Given +/// \code +/// typedef int X; +/// \endcode +/// typedefType() +/// matches "typedef int X" +AST_TYPE_MATCHER(TypedefType, typedefType); + +/// \brief Matches \c TypedefTypes referring to a specific +/// \c TypedefNameDecl. +AST_MATCHER_P(TypedefType, hasDecl, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(*Node.getDecl(), Finder, Builder); +} + +/// \brief Matches nested name specifiers. +/// +/// Given +/// \code +/// namespace ns { +/// struct A { static void f(); }; +/// void A::f() {} +/// void g() { A::f(); } +/// } +/// ns::A a; +/// \endcode +/// nestedNameSpecifier() +/// matches "ns::" and both "A::" +const internal::VariadicAllOfMatcher nestedNameSpecifier; + +/// \brief Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc. +const internal::VariadicAllOfMatcher< + NestedNameSpecifierLoc> nestedNameSpecifierLoc; + +/// \brief Matches \c NestedNameSpecifierLocs for which the given inner +/// NestedNameSpecifier-matcher matches. +inline internal::BindableMatcher loc( + const internal::Matcher &InnerMatcher) { + return internal::BindableMatcher( + new internal::LocMatcher( + InnerMatcher)); +} + +/// \brief Matches nested name specifiers that specify a type matching the +/// given \c QualType matcher without qualifiers. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifier(specifiesType(hasDeclaration(recordDecl(hasName("A"))))) +/// matches "A::" +AST_MATCHER_P(NestedNameSpecifier, specifiesType, + internal::Matcher, InnerMatcher) { + if (Node.getAsType() == NULL) + return false; + return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder); +} + +/// \brief Matches nested name specifier locs that specify a type matching the +/// given \c TypeLoc. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifierLoc(specifiesTypeLoc(loc(type( +/// hasDeclaration(recordDecl(hasName("A"))))))) +/// matches "A::" +AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); +} + +/// \brief Matches on the prefix of a \c NestedNameSpecifier. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and +/// matches "A::" +inline internal::Matcher hasPrefix( + const internal::Matcher &InnerMatcher) { + return internal::makeMatcher( + new internal::NestedNameSpecifierPrefixMatcher(InnerMatcher)); +} + +/// \brief Matches on the prefix of a \c NestedNameSpecifierLoc. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A"))))) +/// matches "A::" +inline internal::Matcher hasPrefix( + const internal::Matcher &InnerMatcher) { + return internal::makeMatcher( + new internal::NestedNameSpecifierLocPrefixMatcher(InnerMatcher)); +} + +/// \brief Matches nested name specifiers that specify a namespace matching the +/// given namespace matcher. +/// +/// Given +/// \code +/// namespace ns { struct A {}; } +/// ns::A a; +/// \endcode +/// nestedNameSpecifier(specifiesNamespace(hasName("ns"))) +/// matches "ns::" +AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, + internal::Matcher, InnerMatcher) { + if (Node.getAsNamespace() == NULL) + return false; + return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder); +} + } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index 3f5568521c0e..e5365ff89d72 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -39,7 +39,11 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/Type.h" +#include "clang/ASTMatchers/ASTTypeTraits.h" #include "llvm/ADT/VariadicFunction.h" +#include "llvm/Support/type_traits.h" #include #include #include @@ -57,6 +61,45 @@ class BoundNodes; namespace internal { class BoundNodesTreeBuilder; +/// \brief Internal version of BoundNodes. Holds all the bound nodes. +class BoundNodesMap { +public: + /// \brief Adds \c Node to the map with key \c ID. + /// + /// The node's base type should be in NodeBaseType or it will be unaccessible. + template + void addNode(StringRef ID, const T* Node) { + NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node); + } + void addNode(StringRef ID, ast_type_traits::DynTypedNode Node) { + NodeMap[ID] = Node; + } + + /// \brief Returns the AST node bound to \c ID. + /// + /// Returns NULL if there was no node bound to \c ID or if there is a node but + /// it cannot be converted to the specified type. + template + const T *getNodeAs(StringRef ID) const { + IDToNodeMap::const_iterator It = NodeMap.find(ID); + if (It == NodeMap.end()) { + return NULL; + } + return It->second.get(); + } + + /// \brief Copies all ID/Node pairs to BoundNodesTreeBuilder \c Builder. + void copyTo(BoundNodesTreeBuilder *Builder) const; + + /// \brief Copies all ID/Node pairs to BoundNodesMap \c Other. + void copyTo(BoundNodesMap *Other) const; + +private: + /// \brief A map from IDs to the bound nodes. + typedef std::map IDToNodeMap; + + IDToNodeMap NodeMap; +}; /// \brief A tree of bound nodes in match results. /// @@ -84,11 +127,10 @@ public: BoundNodesTree(); /// \brief Create a BoundNodesTree from pre-filled maps of bindings. - BoundNodesTree(const std::map& DeclBindings, - const std::map& StmtBindings, + BoundNodesTree(const BoundNodesMap& Bindings, const std::vector RecursiveBindings); - /// \brief Adds all bound nodes to bound_nodes_builder. + /// \brief Adds all bound nodes to \c Builder. void copyTo(BoundNodesTreeBuilder* Builder) const; /// \brief Visits all matches that this BoundNodesTree represents. @@ -99,17 +141,12 @@ public: private: void visitMatchesRecursively( Visitor* ResultVistior, - std::map DeclBindings, - std::map StmtBindings); - - template - void copyBindingsTo(const T& bindings, BoundNodesTreeBuilder* Builder) const; + const BoundNodesMap& AggregatedBindings); // FIXME: Find out whether we want to use different data structures here - // first benchmarks indicate that it doesn't matter though. - std::map DeclBindings; - std::map StmtBindings; + BoundNodesMap Bindings; std::vector RecursiveBindings; }; @@ -123,12 +160,13 @@ public: BoundNodesTreeBuilder(); /// \brief Add a binding from an id to a node. - /// - /// FIXME: Add overloads for all AST base types. - /// @{ - void setBinding(const std::string &Id, const Decl *Node); - void setBinding(const std::string &Id, const Stmt *Node); - /// @} + template + void setBinding(const std::string &Id, const T *Node) { + Bindings.addNode(Id, Node); + } + void setBinding(const std::string &Id, ast_type_traits::DynTypedNode Node) { + Bindings.addNode(Id, Node); + } /// \brief Adds a branch in the tree. void addMatch(const BoundNodesTree& Bindings); @@ -137,11 +175,10 @@ public: BoundNodesTree build() const; private: - BoundNodesTreeBuilder(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT - void operator=(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT + BoundNodesTreeBuilder(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION; + void operator=(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION; - std::map DeclBindings; - std::map StmtBindings; + BoundNodesMap Bindings; std::vector RecursiveBindings; }; @@ -169,7 +206,8 @@ public: BoundNodesTreeBuilder *Builder) const = 0; }; -/// \brief Interface for matchers that only evaluate properties on a single node. +/// \brief Interface for matchers that only evaluate properties on a single +/// node. template class SingleNodeMatcherInterface : public MatcherInterface { public: @@ -187,6 +225,24 @@ private: } }; +/// \brief Base class for all matchers that works on a \c DynTypedNode. +/// +/// Matcher implementations will check whether the \c DynTypedNode is +/// convertible into the respecitve types and then do the actual match +/// on the actual node, or return false if it is not convertible. +class DynTypedMatcher { +public: + virtual ~DynTypedMatcher() {} + + /// \brief Returns true if the matcher matches the given \c DynNode. + virtual bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const = 0; + + /// \brief Returns a unique ID for the matcher. + virtual uint64_t getID() const = 0; +}; + /// \brief Wrapper of a MatcherInterface *that allows copying. /// /// A Matcher can be used anywhere a Matcher is @@ -196,12 +252,32 @@ private: /// operator rather than a type hierarchy to be able to templatize the /// type hierarchy instead of spelling it out. template -class Matcher { +class Matcher : public DynTypedMatcher { public: /// \brief Takes ownership of the provided implementation pointer. explicit Matcher(MatcherInterface *Implementation) : Implementation(Implementation) {} + /// \brief Implicitly converts \c Other to a Matcher. + /// + /// Requires \c T to be derived from \c From. + template + Matcher(const Matcher &Other, + typename llvm::enable_if_c< + llvm::is_base_of::value && + !llvm::is_same::value >::type* = 0) + : Implementation(new ImplicitCastMatcher(Other)) {} + + /// \brief Implicitly converts \c Matcher to \c Matcher. + /// + /// The resulting matcher is not strict, i.e. ignores qualifiers. + template + Matcher(const Matcher &Other, + typename llvm::enable_if_c< + llvm::is_same::value && + llvm::is_same::value >::type* = 0) + : Implementation(new TypeToQualType(Other)) {} + /// \brief Forwards the call to the underlying MatcherInterface pointer. bool matches(const T &Node, ASTMatchFinder *Finder, @@ -209,14 +285,6 @@ public: return Implementation->matches(Node, Finder, Builder); } - /// \brief Implicitly converts this object to a Matcher. - /// - /// Requires Derived to be derived from T. - template - operator Matcher() const { - return Matcher(new ImplicitCastMatcher(*this)); - } - /// \brief Returns an ID that uniquely identifies the matcher. uint64_t getID() const { /// FIXME: Document the requirements this imposes on matcher @@ -224,23 +292,55 @@ public: return reinterpret_cast(Implementation.getPtr()); } + /// \brief Returns whether the matcher matches on the given \c DynNode. + virtual bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + const T *Node = DynNode.get(); + if (!Node) return false; + return matches(*Node, Finder, Builder); + } + + /// \brief Allows the conversion of a \c Matcher to a \c + /// Matcher. + /// + /// Depending on the constructor argument, the matcher is either strict, i.e. + /// does only matches in the absence of qualifiers, or not, i.e. simply + /// ignores any qualifiers. + template + class TypeToQualType : public MatcherInterface { + public: + TypeToQualType(const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const QualType &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + if (Node.isNull()) + return false; + return InnerMatcher.matches(*Node, Finder, Builder); + } + private: + const Matcher InnerMatcher; + }; + private: - /// \brief Allows conversion from Matcher to Matcher if Derived - /// is derived from T. - template - class ImplicitCastMatcher : public MatcherInterface { + /// \brief Allows conversion from Matcher to Matcher if T + /// is derived from Base. + template + class ImplicitCastMatcher : public MatcherInterface { public: - explicit ImplicitCastMatcher(const Matcher &From) + explicit ImplicitCastMatcher(const Matcher &From) : From(From) {} - virtual bool matches(const Derived &Node, + virtual bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return From.matches(Node, Finder, Builder); } private: - const Matcher From; + const Matcher From; }; llvm::IntrusiveRefCntPtr< MatcherInterface > Implementation; @@ -280,18 +380,14 @@ private: /// FIXME: Add other ways to convert... if (Node.isNull()) return false; - CXXRecordDecl *NodeAsRecordDecl = Node->getAsCXXRecordDecl(); - return NodeAsRecordDecl != NULL && - InnerMatcher.matches(*NodeAsRecordDecl, Finder, Builder); + return matchesDecl(Node->getAsCXXRecordDecl(), Finder, Builder); } /// \brief Extracts the Decl of the callee of a CallExpr and returns whether /// the inner matcher matches on it. bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - const Decl *NodeAsDecl = Node.getCalleeDecl(); - return NodeAsDecl != NULL && - InnerMatcher.matches(*NodeAsDecl, Finder, Builder); + return matchesDecl(Node.getCalleeDecl(), Finder, Builder); } /// \brief Extracts the Decl of the constructor call and returns whether the @@ -299,96 +395,63 @@ private: bool matchesSpecialized(const CXXConstructExpr &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - const Decl *NodeAsDecl = Node.getConstructor(); - return NodeAsDecl != NULL && - InnerMatcher.matches(*NodeAsDecl, Finder, Builder); + return matchesDecl(Node.getConstructor(), Finder, Builder); + } + + /// \brief Extracts the \c ValueDecl a \c MemberExpr refers to and returns + /// whether the inner matcher matches on it. + bool matchesSpecialized(const MemberExpr &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesDecl(Node.getMemberDecl(), Finder, Builder); + } + + /// \brief Returns whether the inner matcher \c Node. Returns false if \c Node + /// is \c NULL. + bool matchesDecl(const Decl *Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Node != NULL && InnerMatcher.matches(*Node, Finder, Builder); } const Matcher InnerMatcher; }; /// \brief IsBaseType::value is true if T is a "base" type in the AST -/// node class hierarchies (i.e. if T is Decl, Stmt, or QualType). +/// node class hierarchies. template struct IsBaseType { static const bool value = (llvm::is_same::value || llvm::is_same::value || llvm::is_same::value || + llvm::is_same::value || + llvm::is_same::value || + llvm::is_same::value || + llvm::is_same::value || llvm::is_same::value); }; template const bool IsBaseType::value; -/// \brief Interface that can match any AST base node type and contains default -/// implementations returning false. -class UntypedBaseMatcher : public llvm::RefCountedBaseVPTR { -public: - virtual ~UntypedBaseMatcher() {} - - virtual bool matches(const Decl &DeclNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const QualType &TypeNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const Stmt &StmtNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const CXXCtorInitializer &CtorInitNode, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - - /// \brief Returns a unique ID for the matcher. - virtual uint64_t getID() const = 0; -}; - -/// \brief An UntypedBaseMatcher that overwrites the Matches(...) method for -/// node type T. T must be an AST base type. -template -class TypedBaseMatcher : public UntypedBaseMatcher { - TOOLING_COMPILE_ASSERT(IsBaseType::value, - typed_base_matcher_can_only_be_used_with_base_type); -public: - explicit TypedBaseMatcher(const Matcher &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - using UntypedBaseMatcher::matches; - /// \brief Implements UntypedBaseMatcher::Matches. - /// - /// Since T is guaranteed to be a "base" AST node type, this method is - /// guaranteed to override one of the matches() methods from - /// UntypedBaseMatcher. - virtual bool matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return InnerMatcher.matches(Node, Finder, Builder); - } - - /// \brief Implements UntypedBaseMatcher::getID. - virtual uint64_t getID() const { - return InnerMatcher.getID(); - } - -private: - Matcher InnerMatcher; -}; - /// \brief Interface that allows matchers to traverse the AST. /// FIXME: Find a better name. /// -/// This provides two entry methods for each base node type in the AST: -/// - matchesChildOf: +/// This provides three entry methods for each base node type in the AST: +/// - \c matchesChildOf: /// Matches a matcher on every child node of the given node. Returns true /// if at least one child node could be matched. -/// - matchesDescendantOf: +/// - \c matchesDescendantOf: /// Matches a matcher on all descendant nodes of the given node. Returns true /// if at least one descendant matched. +/// - \c matchesAncestorOf: +/// Matches a matcher on all ancestors of the given node. Returns true if +/// at least one ancestor matched. +/// +/// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal. +/// In the future, we wan to implement this for all nodes for which it makes +/// sense. In the case of matchesAncestorOf, we'll want to implement it for +/// all nodes, as all nodes have ancestors. class ASTMatchFinder { public: /// \brief Defines how we descend a level in the AST when we pass @@ -408,6 +471,14 @@ public: BK_All }; + /// \brief Defines which ancestors are considered for a match. + enum AncestorMatchMode { + /// All ancestors. + AMM_All, + /// Direct parent only. + AMM_ParentOnly + }; + virtual ~ASTMatchFinder() {} /// \brief Returns true if the given class is directly or indirectly derived @@ -418,26 +489,70 @@ public: const Matcher &Base, BoundNodesTreeBuilder *Builder) = 0; - // FIXME: Implement for other base nodes. - virtual bool matchesChildOf(const Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesTreeBuilder *Builder, - TraversalKind Traverse, - BindKind Bind) = 0; - virtual bool matchesChildOf(const Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, + template + bool matchesChildOf(const T &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + TraversalKind Traverse, + BindKind Bind) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value), + unsupported_type_for_recursive_matching); + return matchesChildOf(ast_type_traits::DynTypedNode::create(Node), + Matcher, Builder, Traverse, Bind); + } + + template + bool matchesDescendantOf(const T &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + BindKind Bind) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value), + unsupported_type_for_recursive_matching); + return matchesDescendantOf(ast_type_traits::DynTypedNode::create(Node), + Matcher, Builder, Bind); + } + + // FIXME: Implement support for BindKind. + template + bool matchesAncestorOf(const T &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + AncestorMatchMode MatchMode) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || + llvm::is_base_of::value), + only_Decl_or_Stmt_allowed_for_recursive_matching); + return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node), + Matcher, Builder, MatchMode); + } + +protected: + virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, TraversalKind Traverse, BindKind Bind) = 0; - virtual bool matchesDescendantOf(const Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesTreeBuilder *Builder, - BindKind Bind) = 0; - virtual bool matchesDescendantOf(const Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, + virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, BindKind Bind) = 0; + + virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + AncestorMatchMode MatchMode) = 0; }; /// \brief Converts a \c Matcher to a matcher of desired type \c To by @@ -606,9 +721,6 @@ public: /// The returned matcher is equivalent to this matcher, but will /// bind the matched node on a match. Matcher bind(StringRef ID) const { - TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || - llvm::is_base_of::value), - trying_to_bind_unsupported_node_type__only_decl_and_stmt_supported); return Matcher(new IdMatcher(ID, *this)); } }; @@ -635,7 +747,7 @@ public: } private: - const TypedBaseMatcher ChildMatcher; + const Matcher ChildMatcher; }; /// \brief Matches nodes of type T that have child nodes of type ChildT for @@ -661,7 +773,7 @@ class ForEachMatcher : public MatcherInterface { } private: - const TypedBaseMatcher ChildMatcher; + const Matcher ChildMatcher; }; /// \brief Matches nodes of type T if the given Matcher does not match. @@ -733,6 +845,20 @@ private: const Matcher InnertMatcher2; }; +/// \brief Creates a Matcher that matches if all inner matchers match. +template +BindableMatcher makeAllOfComposite( + ArrayRef *> InnerMatchers) { + if (InnerMatchers.empty()) + return BindableMatcher(new TrueMatcher); + MatcherInterface *InnerMatcher = new TrueMatcher; + for (int i = InnerMatchers.size() - 1; i >= 0; --i) { + InnerMatcher = new AllOfMatcher, Matcher >( + *InnerMatchers[i], makeMatcher(InnerMatcher)); + } + return BindableMatcher(InnerMatcher); +} + /// \brief Creates a Matcher that matches if /// T is dyn_cast'able into InnerT and all inner matchers match. /// @@ -742,17 +868,8 @@ private: template BindableMatcher makeDynCastAllOfComposite( ArrayRef *> InnerMatchers) { - if (InnerMatchers.empty()) { - Matcher InnerMatcher = makeMatcher(new TrueMatcher); - return BindableMatcher(new DynCastMatcher(InnerMatcher)); - } - Matcher InnerMatcher = *InnerMatchers.back(); - for (int i = InnerMatchers.size() - 2; i >= 0; --i) { - InnerMatcher = makeMatcher( - new AllOfMatcher, Matcher >( - *InnerMatchers[i], InnerMatcher)); - } - return BindableMatcher(new DynCastMatcher(InnerMatcher)); + return BindableMatcher(new DynCastMatcher( + makeAllOfComposite(InnerMatchers))); } /// \brief Matches nodes of type T that have at least one descendant node of @@ -775,7 +892,53 @@ public: } private: - const TypedBaseMatcher DescendantMatcher; + const Matcher DescendantMatcher; +}; + +/// \brief Matches nodes of type \c T that have a parent node of type \c ParentT +/// for which the given inner matcher matches. +/// +/// \c ParentT must be an AST base type. +template +class HasParentMatcher : public MatcherInterface { + TOOLING_COMPILE_ASSERT(IsBaseType::value, + has_parent_only_accepts_base_type_matcher); +public: + explicit HasParentMatcher(const Matcher &ParentMatcher) + : ParentMatcher(ParentMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Finder->matchesAncestorOf( + Node, ParentMatcher, Builder, ASTMatchFinder::AMM_ParentOnly); + } + + private: + const Matcher ParentMatcher; +}; + +/// \brief Matches nodes of type \c T that have at least one ancestor node of +/// type \c AncestorT for which the given inner matcher matches. +/// +/// \c AncestorT must be an AST base type. +template +class HasAncestorMatcher : public MatcherInterface { + TOOLING_COMPILE_ASSERT(IsBaseType::value, + has_ancestor_only_accepts_base_type_matcher); +public: + explicit HasAncestorMatcher(const Matcher &AncestorMatcher) + : AncestorMatcher(AncestorMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Finder->matchesAncestorOf( + Node, AncestorMatcher, Builder, ASTMatchFinder::AMM_All); + } + + private: + const Matcher AncestorMatcher; }; /// \brief Matches nodes of type T that have at least one descendant node of @@ -801,7 +964,7 @@ class ForEachDescendantMatcher : public MatcherInterface { } private: - const TypedBaseMatcher DescendantMatcher; + const Matcher DescendantMatcher; }; /// \brief Matches on nodes that have a getValue() method if getValue() equals @@ -858,6 +1021,22 @@ class IsTemplateInstantiationMatcher : public MatcherInterface { } }; +/// \brief Matches on explicit template specializations for FunctionDecl, +/// VarDecl or CXXRecordDecl nodes. +template +class IsExplicitTemplateSpecializationMatcher : public MatcherInterface { + TOOLING_COMPILE_ASSERT((llvm::is_base_of::value) || + (llvm::is_base_of::value) || + (llvm::is_base_of::value), + requires_getTemplateSpecializationKind_method); + public: + virtual bool matches(const T& Node, + ASTMatchFinder* Finder, + BoundNodesTreeBuilder* Builder) const { + return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization); + } +}; + class IsArrowMatcher : public SingleNodeMatcherInterface { public: virtual bool matchesNode(const MemberExpr &Node) const { @@ -894,6 +1073,166 @@ public: VariadicDynCastAllOfMatcher() {} }; +/// \brief A \c VariadicAllOfMatcher object is a variadic functor that takes +/// a number of \c Matcher and returns a \c Matcher that matches \c T +/// nodes that are matched by all of the given matchers. +/// +/// For example: +/// const VariadicAllOfMatcher nestedNameSpecifier; +/// Creates a functor nestedNameSpecifier(...) that creates a +/// \c Matcher given a variable number of arguments of type +/// \c Matcher. +/// The returned matcher matches if all given matchers match. +template +class VariadicAllOfMatcher : public llvm::VariadicFunction< + BindableMatcher, Matcher, + makeAllOfComposite > { +public: + VariadicAllOfMatcher() {} +}; + +/// \brief Matches nodes of type \c TLoc for which the inner +/// \c Matcher matches. +template +class LocMatcher : public MatcherInterface { +public: + explicit LocMatcher(const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const TLoc &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + if (!Node) + return false; + return InnerMatcher.matches(*extract(Node), Finder, Builder); + } + +private: + const NestedNameSpecifier *extract(const NestedNameSpecifierLoc &Loc) const { + return Loc.getNestedNameSpecifier(); + } + + const Matcher InnerMatcher; +}; + +/// \brief Matches \c NestedNameSpecifiers with a prefix matching another +/// \c Matcher. +class NestedNameSpecifierPrefixMatcher + : public MatcherInterface { +public: + explicit NestedNameSpecifierPrefixMatcher( + const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const NestedNameSpecifier &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + NestedNameSpecifier *NextNode = Node.getPrefix(); + if (NextNode == NULL) + return false; + return InnerMatcher.matches(*NextNode, Finder, Builder); + } + +private: + const Matcher InnerMatcher; +}; + +/// \brief Matches \c NestedNameSpecifierLocs with a prefix matching another +/// \c Matcher. +class NestedNameSpecifierLocPrefixMatcher + : public MatcherInterface { +public: + explicit NestedNameSpecifierLocPrefixMatcher( + const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const NestedNameSpecifierLoc &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + NestedNameSpecifierLoc NextNode = Node.getPrefix(); + if (!NextNode) + return false; + return InnerMatcher.matches(NextNode, Finder, Builder); + } + +private: + const Matcher InnerMatcher; +}; + +/// \brief Matches \c TypeLocs based on an inner matcher matching a certain +/// \c QualType. +/// +/// Used to implement the \c loc() matcher. +class TypeLocTypeMatcher : public MatcherInterface { +public: + explicit TypeLocTypeMatcher(const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const TypeLoc &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + if (!Node) + return false; + return InnerMatcher.matches(Node.getType(), Finder, Builder); + } + +private: + const Matcher InnerMatcher; +}; + +/// \brief Matches nodes of type \c T for which the inner matcher matches on a +/// another node of type \c T that can be reached using a given traverse +/// function. +template +class TypeTraverseMatcher : public MatcherInterface { +public: + explicit TypeTraverseMatcher(const Matcher &InnerMatcher, + QualType (T::*TraverseFunction)() const) + : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + QualType NextNode = (Node.*TraverseFunction)(); + if (NextNode.isNull()) + return false; + return InnerMatcher.matches(NextNode, Finder, Builder); + } + +private: + const Matcher InnerMatcher; + QualType (T::*TraverseFunction)() const; +}; + +/// \brief Matches nodes of type \c T in a ..Loc hierarchy, for which the inner +/// matcher matches on a another node of type \c T that can be reached using a +/// given traverse function. +template +class TypeLocTraverseMatcher : public MatcherInterface { +public: + explicit TypeLocTraverseMatcher(const Matcher &InnerMatcher, + TypeLoc (T::*TraverseFunction)() const) + : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + TypeLoc NextNode = (Node.*TraverseFunction)(); + if (!NextNode) + return false; + return InnerMatcher.matches(NextNode, Finder, Builder); + } + +private: + const Matcher InnerMatcher; + TypeLoc (T::*TraverseFunction)() const; +}; + +template +T makeTypeAllOfComposite(ArrayRef *> InnerMatchers) { + return T(makeAllOfComposite(InnerMatchers)); +} + } // end namespace internal } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h index c68534acae35..953abc2a2ec9 100644 --- a/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -221,4 +221,69 @@ const NodeType &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const +/// \brief Creates a variadic matcher for both a specific \c Type as well as +/// the corresponding \c TypeLoc. +#define AST_TYPE_MATCHER(NodeType, MatcherName) \ + const internal::VariadicDynCastAllOfMatcher MatcherName; \ + const internal::VariadicDynCastAllOfMatcher MatcherName##Loc + +/// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines +/// the matcher \c MatcherName that can be used to traverse from one \c Type +/// to another. +/// +/// For a specific \c SpecificType, the traversal is done using +/// \c SpecificType::FunctionName. The existance of such a function determines +/// whether a corresponding matcher can be used on \c SpecificType. +#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) \ +class Polymorphic##MatcherName##TypeMatcher { \ +public: \ + Polymorphic##MatcherName##TypeMatcher( \ + const internal::Matcher &InnerMatcher) \ + : InnerMatcher(InnerMatcher) {} \ + template operator internal::Matcher() { \ + return internal::Matcher(new internal::TypeTraverseMatcher( \ + InnerMatcher, &T::FunctionName)); \ + } \ +private: \ + const internal::Matcher InnerMatcher; \ +}; \ +class Variadic##MatcherName##TypeTraverseMatcher \ + : public llvm::VariadicFunction< \ + Polymorphic##MatcherName##TypeMatcher, \ + internal::Matcher, \ + internal::makeTypeAllOfComposite< \ + Polymorphic##MatcherName##TypeMatcher, QualType> > { \ +public: \ + Variadic##MatcherName##TypeTraverseMatcher() {} \ +}; \ +const Variadic##MatcherName##TypeTraverseMatcher MatcherName + +/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works +/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs. +#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) \ +class Polymorphic##MatcherName##TypeLocMatcher { \ +public: \ + Polymorphic##MatcherName##TypeLocMatcher( \ + const internal::Matcher &InnerMatcher) \ + : InnerMatcher(InnerMatcher) {} \ + template operator internal::Matcher() { \ + return internal::Matcher(new internal::TypeLocTraverseMatcher( \ + InnerMatcher, &T::FunctionName##Loc)); \ + } \ +private: \ + const internal::Matcher InnerMatcher; \ +}; \ +class Variadic##MatcherName##TypeLocTraverseMatcher \ + : public llvm::VariadicFunction< \ + Polymorphic##MatcherName##TypeLocMatcher, \ + internal::Matcher, \ + internal::makeTypeAllOfComposite< \ + Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \ +public: \ + Variadic##MatcherName##TypeLocTraverseMatcher() {} \ +}; \ +const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \ +AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type) + #endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H diff --git a/include/clang/ASTMatchers/ASTTypeTraits.h b/include/clang/ASTMatchers/ASTTypeTraits.h new file mode 100644 index 000000000000..bda53eaf70f6 --- /dev/null +++ b/include/clang/ASTMatchers/ASTTypeTraits.h @@ -0,0 +1,209 @@ +//===--- ASTMatchersTypeTraits.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Provides a dynamically typed node container that can be used to store +// an AST base node at runtime in the same storage in a type safe way. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H +#define LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H + +#include "clang/AST/Decl.h" +#include "clang/AST/Stmt.h" +#include "llvm/Support/AlignOf.h" + +namespace clang { +namespace ast_type_traits { + +/// \brief A dynamically typed AST node container. +/// +/// Stores an AST node in a type safe way. This allows writing code that +/// works with different kinds of AST nodes, despite the fact that they don't +/// have a common base class. +/// +/// Use \c create(Node) to create a \c DynTypedNode from an AST node, +/// and \c get() to retrieve the node as type T if the types match. +/// +/// See \c NodeTypeTag for which node base types are currently supported; +/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of +/// the supported base types. +class DynTypedNode { +public: + /// \brief Creates a \c DynTypedNode from \c Node. + template + static DynTypedNode create(const T &Node) { + return BaseConverter::create(Node); + } + + /// \brief Retrieve the stored node as type \c T. + /// + /// Returns NULL if the stored node does not have a type that is + /// convertible to \c T. + /// + /// For types that have identity via their pointer in the AST + /// (like \c Stmt and \c Decl) the returned pointer points to the + /// referenced AST node. + /// For other types (like \c QualType) the value is stored directly + /// in the \c DynTypedNode, and the returned pointer points at + /// the storage inside DynTypedNode. For those nodes, do not + /// use the pointer outside the scope of the DynTypedNode. + template + const T *get() const { + return BaseConverter::get(Tag, Storage.buffer); + } + + /// \brief Returns a pointer that identifies the stored AST node. + /// + /// Note that this is not supported by all AST nodes. For AST nodes + /// that don't have a pointer-defined identity inside the AST, this + /// method returns NULL. + const void *getMemoizationData() const; + +private: + /// \brief Takes care of converting from and to \c T. + template struct BaseConverter; + + /// \brief Supported base node types. + enum NodeTypeTag { + NT_Decl, + NT_Stmt, + NT_NestedNameSpecifier, + NT_NestedNameSpecifierLoc, + NT_QualType, + NT_Type, + NT_TypeLoc + } Tag; + + /// \brief Stores the data of the node. + /// + /// Note that we can store \c Decls and \c Stmts by pointer as they are + /// guaranteed to be unique pointers pointing to dedicated storage in the + /// AST. \c QualTypes on the other hand do not have storage or unique + /// pointers and thus need to be stored by value. + llvm::AlignedCharArrayUnion + Storage; +}; + +// FIXME: Pull out abstraction for the following. +template struct DynTypedNode::BaseConverter >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Decl) + return dyn_cast(*reinterpret_cast(Storage)); + return NULL; + } + static DynTypedNode create(const Decl &Node) { + DynTypedNode Result; + Result.Tag = NT_Decl; + new (Result.Storage.buffer) const Decl*(&Node); + return Result; + } +}; +template struct DynTypedNode::BaseConverter >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Stmt) + return dyn_cast(*reinterpret_cast(Storage)); + return NULL; + } + static DynTypedNode create(const Stmt &Node) { + DynTypedNode Result; + Result.Tag = NT_Stmt; + new (Result.Storage.buffer) const Stmt*(&Node); + return Result; + } +}; +template struct DynTypedNode::BaseConverter >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Type) + return dyn_cast(*reinterpret_cast(Storage)); + return NULL; + } + static DynTypedNode create(const Type &Node) { + DynTypedNode Result; + Result.Tag = NT_Type; + new (Result.Storage.buffer) const Type*(&Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const NestedNameSpecifier *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_NestedNameSpecifier) + return *reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const NestedNameSpecifier &Node) { + DynTypedNode Result; + Result.Tag = NT_NestedNameSpecifier; + new (Result.Storage.buffer) const NestedNameSpecifier*(&Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const NestedNameSpecifierLoc *get(NodeTypeTag Tag, + const char Storage[]) { + if (Tag == NT_NestedNameSpecifierLoc) + return reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const NestedNameSpecifierLoc &Node) { + DynTypedNode Result; + Result.Tag = NT_NestedNameSpecifierLoc; + new (Result.Storage.buffer) NestedNameSpecifierLoc(Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const QualType *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_QualType) + return reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const QualType &Node) { + DynTypedNode Result; + Result.Tag = NT_QualType; + new (Result.Storage.buffer) QualType(Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const TypeLoc *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_TypeLoc) + return reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const TypeLoc &Node) { + DynTypedNode Result; + Result.Tag = NT_TypeLoc; + new (Result.Storage.buffer) TypeLoc(Node); + return Result; + } +}; +// The only operation we allow on unsupported types is \c get. +// This allows to conveniently use \c DynTypedNode when having an arbitrary +// AST node that is not supported, but prevents misuse - a user cannot create +// a DynTypedNode from arbitrary types. +template struct DynTypedNode::BaseConverter { + static const T *get(NodeTypeTag Tag, const char Storage[]) { return NULL; } +}; + +inline const void *DynTypedNode::getMemoizationData() const { + switch (Tag) { + case NT_Decl: return BaseConverter::get(Tag, Storage.buffer); + case NT_Stmt: return BaseConverter::get(Tag, Storage.buffer); + default: return NULL; + }; +} + +} // end namespace ast_type_traits +} // end namespace clang + +#endif // LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H -- cgit v1.2.3