Home | History | Annotate | Download | only in ASTMatchers
      1 //===--- ASTMatchersMacros.h - Structural query framework -------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  Defines macros that enable us to define new matchers in a single place.
     11 //  Since a matcher is a function which returns a Matcher<T> object, where
     12 //  T is the type of the actual implementation of the matcher, the macros allow
     13 //  us to write matchers like functions and take care of the definition of the
     14 //  class boilerplate.
     15 //
     16 //  Note that when you define a matcher with an AST_MATCHER* macro, only the
     17 //  function which creates the matcher goes into the current namespace - the
     18 //  class that implements the actual matcher, which gets returned by the
     19 //  generator function, is put into the 'internal' namespace. This allows us
     20 //  to only have the functions (which is all the user cares about) in the
     21 //  'ast_matchers' namespace and hide the boilerplate.
     22 //
     23 //  To define a matcher in user code, always put it into the clang::ast_matchers
     24 //  namespace and refer to the internal types via the 'internal::':
     25 //
     26 //  namespace clang {
     27 //  namespace ast_matchers {
     28 //  AST_MATCHER_P(MemberExpr, Member,
     29 //                internal::Matcher<ValueDecl>, InnerMatcher) {
     30 //    return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
     31 //  }
     32 //  } // end namespace ast_matchers
     33 //  } // end namespace clang
     34 //
     35 //===----------------------------------------------------------------------===//
     36 
     37 #ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
     38 #define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
     39 
     40 /// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
     41 /// defines a single-parameter function named DefineMatcher() that returns a
     42 /// ReturnType object.
     43 ///
     44 /// The code between the curly braces has access to the following variables:
     45 ///
     46 ///   Param:                 the parameter passed to the function; its type
     47 ///                          is ParamType.
     48 ///
     49 /// The code should return an instance of ReturnType.
     50 #define AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param)    \
     51   AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, Param, \
     52                                   0)
     53 #define AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType,  \
     54                                         Param, OverloadId)                     \
     55   inline ReturnType DefineMatcher(ParamType const &Param);                     \
     56   typedef ReturnType (&DefineMatcher##_Type##OverloadId)(ParamType const &);   \
     57   inline ReturnType DefineMatcher(ParamType const &Param)
     58 
     59 /// \brief AST_MATCHER(Type, DefineMatcher) { ... }
     60 /// defines a zero parameter function named DefineMatcher() that returns a
     61 /// Matcher<Type> object.
     62 ///
     63 /// The code between the curly braces has access to the following variables:
     64 ///
     65 ///   Node:                  the AST node being matched; its type is Type.
     66 ///   Finder:                an ASTMatchFinder*.
     67 ///   Builder:               a BoundNodesTreeBuilder*.
     68 ///
     69 /// The code should return true if 'Node' matches.
     70 #define AST_MATCHER(Type, DefineMatcher)                                       \
     71   namespace internal {                                                         \
     72   class matcher_##DefineMatcher##Matcher : public MatcherInterface<Type> {     \
     73   public:                                                                      \
     74     explicit matcher_##DefineMatcher##Matcher() {}                             \
     75     bool matches(const Type &Node, ASTMatchFinder *Finder,                     \
     76                  BoundNodesTreeBuilder *Builder) const override;               \
     77   };                                                                           \
     78   }                                                                            \
     79   inline internal::Matcher<Type> DefineMatcher() {                             \
     80     return internal::makeMatcher(                                              \
     81         new internal::matcher_##DefineMatcher##Matcher());                     \
     82   }                                                                            \
     83   inline bool internal::matcher_##DefineMatcher##Matcher::matches(             \
     84       const Type &Node, ASTMatchFinder *Finder,                                \
     85       BoundNodesTreeBuilder *Builder) const
     86 
     87 /// \brief AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... }
     88 /// defines a single-parameter function named DefineMatcher() that returns a
     89 /// Matcher<Type> object.
     90 ///
     91 /// The code between the curly braces has access to the following variables:
     92 ///
     93 ///   Node:                  the AST node being matched; its type is Type.
     94 ///   Param:                 the parameter passed to the function; its type
     95 ///                          is ParamType.
     96 ///   Finder:                an ASTMatchFinder*.
     97 ///   Builder:               a BoundNodesTreeBuilder*.
     98 ///
     99 /// The code should return true if 'Node' matches.
    100 #define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param)                   \
    101   AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, 0)
    102 
    103 #define AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param,          \
    104                                OverloadId)                                     \
    105   namespace internal {                                                         \
    106   class matcher_##DefineMatcher##OverloadId##Matcher                           \
    107       : public MatcherInterface<Type> {                                        \
    108   public:                                                                      \
    109     explicit matcher_##DefineMatcher##OverloadId##Matcher(                     \
    110         ParamType const &A##Param)                                             \
    111         : Param(A##Param) {}                                                   \
    112     bool matches(const Type &Node, ASTMatchFinder *Finder,                     \
    113                  BoundNodesTreeBuilder *Builder) const override;               \
    114                                                                                \
    115   private:                                                                     \
    116     ParamType const Param;                                                     \
    117   };                                                                           \
    118   }                                                                            \
    119   inline internal::Matcher<Type> DefineMatcher(ParamType const &Param) {       \
    120     return internal::makeMatcher(                                              \
    121         new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param));    \
    122   }                                                                            \
    123   typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)(          \
    124       ParamType const &Param);                                                 \
    125   inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
    126       const Type &Node, ASTMatchFinder *Finder,                                \
    127       BoundNodesTreeBuilder *Builder) const
    128 
    129 /// \brief AST_MATCHER_P2(
    130 ///     Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
    131 /// defines a two-parameter function named DefineMatcher() that returns a
    132 /// Matcher<Type> object.
    133 ///
    134 /// The code between the curly braces has access to the following variables:
    135 ///
    136 ///   Node:                  the AST node being matched; its type is Type.
    137 ///   Param1, Param2:        the parameters passed to the function; their types
    138 ///                          are ParamType1 and ParamType2.
    139 ///   Finder:                an ASTMatchFinder*.
    140 ///   Builder:               a BoundNodesTreeBuilder*.
    141 ///
    142 /// The code should return true if 'Node' matches.
    143 #define AST_MATCHER_P2(Type, DefineMatcher, ParamType1, Param1, ParamType2,    \
    144                        Param2)                                                 \
    145   AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, ParamType2, \
    146                           Param2, 0)
    147 
    148 #define AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1,       \
    149                                 ParamType2, Param2, OverloadId)                \
    150   namespace internal {                                                         \
    151   class matcher_##DefineMatcher##OverloadId##Matcher                           \
    152       : public MatcherInterface<Type> {                                        \
    153   public:                                                                      \
    154     matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1,  \
    155                                                  ParamType2 const &A##Param2)  \
    156         : Param1(A##Param1), Param2(A##Param2) {}                              \
    157     bool matches(const Type &Node, ASTMatchFinder *Finder,                     \
    158                  BoundNodesTreeBuilder *Builder) const override;               \
    159                                                                                \
    160   private:                                                                     \
    161     ParamType1 const Param1;                                                   \
    162     ParamType2 const Param2;                                                   \
    163   };                                                                           \
    164   }                                                                            \
    165   inline internal::Matcher<Type> DefineMatcher(ParamType1 const &Param1,       \
    166                                                ParamType2 const &Param2) {     \
    167     return internal::makeMatcher(                                              \
    168         new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1,     \
    169                                                                    Param2));   \
    170   }                                                                            \
    171   typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)(          \
    172       ParamType1 const &Param1, ParamType2 const &Param2);                     \
    173   inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
    174       const Type &Node, ASTMatchFinder *Finder,                                \
    175       BoundNodesTreeBuilder *Builder) const
    176 
    177 /// \brief Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER*
    178 ///   macros.
    179 ///
    180 /// You can't pass something like \c TypeList<Foo, Bar> to a macro, because it
    181 /// will look at that as two arguments. However, you can pass
    182 /// \c void(TypeList<Foo, Bar>), which works thanks to the parenthesis.
    183 /// The \c PolymorphicMatcherWithParam* classes will unpack the function type to
    184 /// extract the TypeList object.
    185 #define AST_POLYMORPHIC_SUPPORTED_TYPES_1(t1) void(internal::TypeList<t1>)
    186 #define AST_POLYMORPHIC_SUPPORTED_TYPES_2(t1, t2)                              \
    187   void(internal::TypeList<t1, t2>)
    188 #define AST_POLYMORPHIC_SUPPORTED_TYPES_3(t1, t2, t3)                          \
    189   void(internal::TypeList<t1, t2, t3>)
    190 #define AST_POLYMORPHIC_SUPPORTED_TYPES_4(t1, t2, t3, t4)                      \
    191   void(internal::TypeList<t1, t2, t3, t4>)
    192 #define AST_POLYMORPHIC_SUPPORTED_TYPES_5(t1, t2, t3, t4, t5)                  \
    193   void(internal::TypeList<t1, t2, t3, internal::TypeList<t4, t5> >)
    194 
    195 /// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
    196 /// defines a single-parameter function named DefineMatcher() that is
    197 /// polymorphic in the return type.
    198 ///
    199 /// The variables are the same as for AST_MATCHER, but NodeType will be deduced
    200 /// from the calling context.
    201 #define AST_POLYMORPHIC_MATCHER(DefineMatcher, ReturnTypesF)                   \
    202   namespace internal {                                                         \
    203   template <typename NodeType>                                                 \
    204   class matcher_##DefineMatcher##Matcher : public MatcherInterface<NodeType> { \
    205   public:                                                                      \
    206     bool matches(const NodeType &Node, ASTMatchFinder *Finder,                 \
    207                  BoundNodesTreeBuilder *Builder) const override;               \
    208   };                                                                           \
    209   }                                                                            \
    210   inline internal::PolymorphicMatcherWithParam0<                               \
    211       internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>                \
    212   DefineMatcher() {                                                            \
    213     return internal::PolymorphicMatcherWithParam0<                             \
    214         internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>();           \
    215   }                                                                            \
    216   template <typename NodeType>                                                 \
    217   bool internal::matcher_##DefineMatcher##Matcher<NodeType>::matches(          \
    218       const NodeType &Node, ASTMatchFinder *Finder,                            \
    219       BoundNodesTreeBuilder *Builder) const
    220 
    221 /// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... }
    222 /// defines a single-parameter function named DefineMatcher() that is
    223 /// polymorphic in the return type.
    224 ///
    225 /// The variables are the same as for
    226 /// AST_MATCHER_P, with the addition of NodeType, which specifies the node type
    227 /// of the matcher Matcher<NodeType> returned by the function matcher().
    228 ///
    229 /// FIXME: Pull out common code with above macro?
    230 #define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ReturnTypesF, ParamType,      \
    231                                   Param)                                       \
    232   AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType,   \
    233                                      Param, 0)
    234 
    235 #define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF,        \
    236                                            ParamType, Param, OverloadId)       \
    237   namespace internal {                                                         \
    238   template <typename NodeType, typename ParamT>                                \
    239   class matcher_##DefineMatcher##OverloadId##Matcher                           \
    240       : public MatcherInterface<NodeType> {                                    \
    241   public:                                                                      \
    242     explicit matcher_##DefineMatcher##OverloadId##Matcher(                     \
    243         ParamType const &A##Param)                                             \
    244         : Param(A##Param) {}                                                   \
    245     bool matches(const NodeType &Node, ASTMatchFinder *Finder,                 \
    246                  BoundNodesTreeBuilder *Builder) const override;               \
    247                                                                                \
    248   private:                                                                     \
    249     ParamType const Param;                                                     \
    250   };                                                                           \
    251   }                                                                            \
    252   inline internal::PolymorphicMatcherWithParam1<                               \
    253       internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType,       \
    254       ReturnTypesF> DefineMatcher(ParamType const &Param) {                    \
    255     return internal::PolymorphicMatcherWithParam1<                             \
    256         internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType,     \
    257         ReturnTypesF>(Param);                                                  \
    258   }                                                                            \
    259   typedef internal::PolymorphicMatcherWithParam1<                              \
    260       internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType,       \
    261       ReturnTypesF>(&DefineMatcher##_Type##OverloadId)(                        \
    262       ParamType const &Param);                                                 \
    263   template <typename NodeType, typename ParamT>                                \
    264   bool internal::matcher_##DefineMatcher##OverloadId##Matcher<                 \
    265       NodeType, ParamT>::matches(const NodeType &Node, ASTMatchFinder *Finder, \
    266                                  BoundNodesTreeBuilder *Builder) const
    267 
    268 /// \brief AST_POLYMORPHIC_MATCHER_P2(
    269 ///     DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
    270 /// defines a two-parameter function named matcher() that is polymorphic in
    271 /// the return type.
    272 ///
    273 /// The variables are the same as for AST_MATCHER_P2, with the
    274 /// addition of NodeType, which specifies the node type of the matcher
    275 /// Matcher<NodeType> returned by the function DefineMatcher().
    276 #define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ReturnTypesF, ParamType1,    \
    277                                    Param1, ParamType2, Param2)                 \
    278   AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType1, \
    279                                       Param1, ParamType2, Param2, 0)
    280 
    281 #define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF,       \
    282                                             ParamType1, Param1, ParamType2,    \
    283                                             Param2, OverloadId)                \
    284   namespace internal {                                                         \
    285   template <typename NodeType, typename ParamT1, typename ParamT2>             \
    286   class matcher_##DefineMatcher##OverloadId##Matcher                           \
    287       : public MatcherInterface<NodeType> {                                    \
    288   public:                                                                      \
    289     matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1,  \
    290                                                  ParamType2 const &A##Param2)  \
    291         : Param1(A##Param1), Param2(A##Param2) {}                              \
    292      bool matches(const NodeType &Node, ASTMatchFinder *Finder,                \
    293                   BoundNodesTreeBuilder *Builder) const override;              \
    294                                                                                \
    295   private:                                                                     \
    296     ParamType1 const Param1;                                                   \
    297     ParamType2 const Param2;                                                   \
    298   };                                                                           \
    299   }                                                                            \
    300   inline internal::PolymorphicMatcherWithParam2<                               \
    301       internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,      \
    302       ParamType2, ReturnTypesF> DefineMatcher(ParamType1 const &Param1,        \
    303                                               ParamType2 const &Param2) {      \
    304     return internal::PolymorphicMatcherWithParam2<                             \
    305         internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,    \
    306         ParamType2, ReturnTypesF>(Param1, Param2);                             \
    307   }                                                                            \
    308   typedef internal::PolymorphicMatcherWithParam2<                              \
    309       internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,      \
    310       ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)(            \
    311       ParamType1 const &Param1, ParamType2 const &Param2);                     \
    312   template <typename NodeType, typename ParamT1, typename ParamT2>             \
    313   bool internal::matcher_##DefineMatcher##OverloadId##Matcher<                 \
    314       NodeType, ParamT1, ParamT2>::matches(                                    \
    315       const NodeType &Node, ASTMatchFinder *Finder,                            \
    316       BoundNodesTreeBuilder *Builder) const
    317 
    318 /// \brief Creates a variadic matcher for both a specific \c Type as well as
    319 /// the corresponding \c TypeLoc.
    320 #define AST_TYPE_MATCHER(NodeType, MatcherName)                                \
    321   const internal::VariadicDynCastAllOfMatcher<Type, NodeType> MatcherName
    322 // FIXME: add a matcher for TypeLoc derived classes using its custom casting
    323 // API (no longer dyn_cast) if/when we need such matching
    324 
    325 /// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines
    326 /// the matcher \c MatcherName that can be used to traverse from one \c Type
    327 /// to another.
    328 ///
    329 /// For a specific \c SpecificType, the traversal is done using
    330 /// \c SpecificType::FunctionName. The existence of such a function determines
    331 /// whether a corresponding matcher can be used on \c SpecificType.
    332 #define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF)     \
    333   namespace internal {                                                         \
    334   template <typename T> struct TypeMatcher##MatcherName##Getter {              \
    335     static QualType (T::*value())() const { return &T::FunctionName; }         \
    336   };                                                                           \
    337   }                                                                            \
    338   const internal::TypeTraversePolymorphicMatcher<                              \
    339       QualType, internal::TypeMatcher##MatcherName##Getter,                    \
    340       internal::TypeTraverseMatcher, ReturnTypesF>::Func MatcherName
    341 
    342 /// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works
    343 /// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs.
    344 #define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF)  \
    345   namespace internal {                                                         \
    346   template <typename T> struct TypeLocMatcher##MatcherName##Getter {           \
    347     static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; }     \
    348   };                                                                           \
    349   }                                                                            \
    350   const internal::TypeTraversePolymorphicMatcher<                              \
    351       TypeLoc, internal::TypeLocMatcher##MatcherName##Getter,                  \
    352       internal::TypeLocTraverseMatcher, ReturnTypesF>::Func MatcherName##Loc;  \
    353   AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
    354 
    355 #endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
    356