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