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