1 //===--- Marshallers.h - Generic matcher function marshallers -*- 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 /// \file 11 /// \brief Functions templates and classes to wrap matcher construct functions. 12 /// 13 /// A collection of template function and classes that provide a generic 14 /// marshalling layer on top of matcher construct functions. 15 /// These are used by the registry to export all marshaller constructors with 16 /// the same generic interface. 17 /// 18 //===----------------------------------------------------------------------===// 19 20 #ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H 21 #define LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H 22 23 #include <string> 24 25 #include "clang/ASTMatchers/ASTMatchers.h" 26 #include "clang/ASTMatchers/Dynamic/Diagnostics.h" 27 #include "clang/ASTMatchers/Dynamic/VariantValue.h" 28 #include "clang/Basic/LLVM.h" 29 #include "llvm/Support/type_traits.h" 30 31 namespace clang { 32 namespace ast_matchers { 33 namespace dynamic { 34 35 namespace internal { 36 37 /// \brief Helper template class to just from argument type to the right is/get 38 /// functions in VariantValue. 39 /// Used to verify and extract the matcher arguments below. 40 template <class T> struct ArgTypeTraits; 41 template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> { 42 }; 43 44 template <> struct ArgTypeTraits<std::string> { 45 static StringRef asString() { return "String"; } 46 static bool is(const VariantValue &Value) { return Value.isString(); } 47 static const std::string &get(const VariantValue &Value) { 48 return Value.getString(); 49 } 50 }; 51 52 template <> 53 struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> { 54 }; 55 56 template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > { 57 static std::string asString() { 58 return (Twine("Matcher<") + 59 ast_type_traits::ASTNodeKind::getFromNodeKind<T>().asStringRef() + 60 ">").str(); 61 } 62 static bool is(const VariantValue &Value) { 63 return Value.hasTypedMatcher<T>(); 64 } 65 static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) { 66 return Value.getTypedMatcher<T>(); 67 } 68 }; 69 70 template <> struct ArgTypeTraits<unsigned> { 71 static std::string asString() { return "Unsigned"; } 72 static bool is(const VariantValue &Value) { return Value.isUnsigned(); } 73 static unsigned get(const VariantValue &Value) { 74 return Value.getUnsigned(); 75 } 76 }; 77 78 /// \brief Generic MatcherCreate interface. 79 /// 80 /// Provides a \c run() method that constructs the matcher from the provided 81 /// arguments. 82 class MatcherCreateCallback { 83 public: 84 virtual ~MatcherCreateCallback() {} 85 virtual MatcherList run(const SourceRange &NameRange, 86 ArrayRef<ParserValue> Args, 87 Diagnostics *Error) const = 0; 88 }; 89 90 /// \brief Simple callback implementation. Marshaller and function are provided. 91 /// 92 /// This class wraps a function of arbitrary signature and a marshaller 93 /// function into a MatcherCreateCallback. 94 /// The marshaller is in charge of taking the VariantValue arguments, checking 95 /// their types, unpacking them and calling the underlying function. 96 template <typename FuncType> 97 class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback { 98 public: 99 /// FIXME: Use void(*)() as FuncType on this interface to remove the template 100 /// argument of this class. The marshaller can cast the function pointer back 101 /// to the original type. 102 typedef MatcherList (*MarshallerType)(FuncType, StringRef, 103 const SourceRange &, 104 ArrayRef<ParserValue>, 105 Diagnostics *); 106 107 /// \param Marshaller Function to unpack the arguments and call \c Func 108 /// \param Func Matcher construct function. This is the function that 109 /// compile-time matcher expressions would use to create the matcher. 110 FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, FuncType Func, 111 StringRef MatcherName) 112 : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {} 113 114 MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args, 115 Diagnostics *Error) const { 116 return Marshaller(Func, MatcherName, NameRange, Args, Error); 117 } 118 119 private: 120 const MarshallerType Marshaller; 121 const FuncType Func; 122 const std::string MatcherName; 123 }; 124 125 /// \brief Simple callback implementation. Free function is wrapped. 126 /// 127 /// This class simply wraps a free function with the right signature to export 128 /// it as a MatcherCreateCallback. 129 /// This allows us to have one implementation of the interface for as many free 130 /// functions as we want, reducing the number of symbols and size of the 131 /// object file. 132 class FreeFuncMatcherCreateCallback : public MatcherCreateCallback { 133 public: 134 typedef MatcherList (*RunFunc)(StringRef MatcherName, 135 const SourceRange &NameRange, 136 ArrayRef<ParserValue> Args, 137 Diagnostics *Error); 138 139 FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName) 140 : Func(Func), MatcherName(MatcherName.str()) {} 141 142 MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args, 143 Diagnostics *Error) const { 144 return Func(MatcherName, NameRange, Args, Error); 145 } 146 147 private: 148 const RunFunc Func; 149 const std::string MatcherName; 150 }; 151 152 /// \brief Helper macros to check the arguments on all marshaller functions. 153 #define CHECK_ARG_COUNT(count) \ 154 if (Args.size() != count) { \ 155 Error->addError(NameRange, Error->ET_RegistryWrongArgCount) \ 156 << count << Args.size(); \ 157 return MatcherList(); \ 158 } 159 160 #define CHECK_ARG_TYPE(index, type) \ 161 if (!ArgTypeTraits<type>::is(Args[index].Value)) { \ 162 Error->addError(Args[index].Range, Error->ET_RegistryWrongArgType) \ 163 << (index + 1) << ArgTypeTraits<type>::asString() \ 164 << Args[index].Value.getTypeAsString(); \ 165 return MatcherList(); \ 166 } 167 168 /// \brief Helper methods to extract and merge all possible typed matchers 169 /// out of the polymorphic object. 170 template <class PolyMatcher> 171 static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out, 172 ast_matchers::internal::EmptyTypeList) {} 173 174 template <class PolyMatcher, class TypeList> 175 static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out, 176 TypeList) { 177 Out->add(ast_matchers::internal::Matcher<typename TypeList::head>(Poly)); 178 mergePolyMatchers(Poly, Out, typename TypeList::tail()); 179 } 180 181 /// \brief Convert the return values of the functions into a MatcherList. 182 /// 183 /// There are 2 cases right now: The return value is a Matcher<T> or is a 184 /// polymorphic matcher. For the former, we just construct the MatcherList. For 185 /// the latter, we instantiate all the possible Matcher<T> of the poly matcher. 186 template <typename T> 187 static MatcherList 188 outvalueToMatcherList(const ast_matchers::internal::Matcher<T> &Matcher) { 189 return MatcherList(Matcher); 190 } 191 192 template <typename T> 193 static MatcherList 194 outvalueToMatcherList(const T& PolyMatcher, typename T::ReturnTypes* = NULL) { 195 MatcherList Matchers; 196 mergePolyMatchers(PolyMatcher, &Matchers, typename T::ReturnTypes()); 197 return Matchers; 198 } 199 200 /// \brief 0-arg marshaller function. 201 template <typename ReturnType> 202 static MatcherList matcherMarshall0(ReturnType (*Func)(), 203 StringRef MatcherName, 204 const SourceRange &NameRange, 205 ArrayRef<ParserValue> Args, 206 Diagnostics *Error) { 207 CHECK_ARG_COUNT(0); 208 return outvalueToMatcherList(Func()); 209 } 210 211 /// \brief 1-arg marshaller function. 212 template <typename ReturnType, typename ArgType1> 213 static MatcherList matcherMarshall1(ReturnType (*Func)(ArgType1), 214 StringRef MatcherName, 215 const SourceRange &NameRange, 216 ArrayRef<ParserValue> Args, 217 Diagnostics *Error) { 218 CHECK_ARG_COUNT(1); 219 CHECK_ARG_TYPE(0, ArgType1); 220 return outvalueToMatcherList( 221 Func(ArgTypeTraits<ArgType1>::get(Args[0].Value))); 222 } 223 224 /// \brief 2-arg marshaller function. 225 template <typename ReturnType, typename ArgType1, typename ArgType2> 226 static MatcherList matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2), 227 StringRef MatcherName, 228 const SourceRange &NameRange, 229 ArrayRef<ParserValue> Args, 230 Diagnostics *Error) { 231 CHECK_ARG_COUNT(2); 232 CHECK_ARG_TYPE(0, ArgType1); 233 CHECK_ARG_TYPE(1, ArgType2); 234 return outvalueToMatcherList( 235 Func(ArgTypeTraits<ArgType1>::get(Args[0].Value), 236 ArgTypeTraits<ArgType2>::get(Args[1].Value))); 237 } 238 239 #undef CHECK_ARG_COUNT 240 #undef CHECK_ARG_TYPE 241 242 /// \brief Variadic marshaller function. 243 template <typename ResultT, typename ArgT, 244 ResultT (*Func)(ArrayRef<const ArgT *>)> 245 MatcherList variadicMatcherCreateCallback(StringRef MatcherName, 246 const SourceRange &NameRange, 247 ArrayRef<ParserValue> Args, 248 Diagnostics *Error) { 249 ArgT **InnerArgs = new ArgT *[Args.size()](); 250 251 bool HasError = false; 252 for (size_t i = 0, e = Args.size(); i != e; ++i) { 253 typedef ArgTypeTraits<ArgT> ArgTraits; 254 const ParserValue &Arg = Args[i]; 255 const VariantValue &Value = Arg.Value; 256 if (!ArgTraits::is(Value)) { 257 Error->addError(Arg.Range, Error->ET_RegistryWrongArgType) 258 << (i + 1) << ArgTraits::asString() << Value.getTypeAsString(); 259 HasError = true; 260 break; 261 } 262 InnerArgs[i] = new ArgT(ArgTraits::get(Value)); 263 } 264 265 MatcherList Out; 266 if (!HasError) { 267 Out = outvalueToMatcherList( 268 Func(ArrayRef<const ArgT *>(InnerArgs, Args.size()))); 269 } 270 271 for (size_t i = 0, e = Args.size(); i != e; ++i) { 272 delete InnerArgs[i]; 273 } 274 delete[] InnerArgs; 275 return Out; 276 } 277 278 /// Helper functions to select the appropriate marshaller functions. 279 /// They detect the number of arguments, arguments types and return type. 280 281 /// \brief 0-arg overload 282 template <typename ReturnType> 283 MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(), 284 StringRef MatcherName) { 285 return new FixedArgCountMatcherCreateCallback<ReturnType (*)()>( 286 matcherMarshall0, Func, MatcherName); 287 } 288 289 /// \brief 1-arg overload 290 template <typename ReturnType, typename ArgType1> 291 MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), 292 StringRef MatcherName) { 293 return new FixedArgCountMatcherCreateCallback<ReturnType (*)(ArgType1)>( 294 matcherMarshall1, Func, MatcherName); 295 } 296 297 /// \brief 2-arg overload 298 template <typename ReturnType, typename ArgType1, typename ArgType2> 299 MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, 300 ArgType2), 301 StringRef MatcherName) { 302 return new FixedArgCountMatcherCreateCallback< 303 ReturnType (*)(ArgType1, ArgType2)>(matcherMarshall2, Func, MatcherName); 304 } 305 306 /// \brief Variadic overload. 307 template <typename ResultT, typename ArgT, 308 ResultT (*Func)(ArrayRef<const ArgT *>)> 309 MatcherCreateCallback * 310 makeMatcherAutoMarshall(llvm::VariadicFunction<ResultT, ArgT, Func> VarFunc, 311 StringRef MatcherName) { 312 return new FreeFuncMatcherCreateCallback( 313 &variadicMatcherCreateCallback<ResultT, ArgT, Func>, MatcherName); 314 } 315 316 } // namespace internal 317 } // namespace dynamic 318 } // namespace ast_matchers 319 } // namespace clang 320 321 #endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H 322