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 31namespace clang { 32namespace ast_matchers { 33namespace dynamic { 34 35namespace 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. 40template <class T> struct ArgTypeTraits; 41template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> { 42}; 43 44template <> 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 52template <> 53struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> { 54}; 55 56template <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 70template <> 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. 82class MatcherCreateCallback { 83public: 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. 96template <typename FuncType> 97class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback { 98public: 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 119private: 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. 132class FreeFuncMatcherCreateCallback : public MatcherCreateCallback { 133public: 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 147private: 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. 170template <class PolyMatcher> 171static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out, 172 ast_matchers::internal::EmptyTypeList) {} 173 174template <class PolyMatcher, class TypeList> 175static 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. 186template <typename T> 187static MatcherList 188outvalueToMatcherList(const ast_matchers::internal::Matcher<T> &Matcher) { 189 return MatcherList(Matcher); 190} 191 192template <typename T> 193static MatcherList 194outvalueToMatcherList(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. 201template <typename ReturnType> 202static 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. 212template <typename ReturnType, typename ArgType1> 213static 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. 225template <typename ReturnType, typename ArgType1, typename ArgType2> 226static 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. 243template <typename ResultT, typename ArgT, 244 ResultT (*Func)(ArrayRef<const ArgT *>)> 245MatcherList 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 282template <typename ReturnType> 283MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(), 284 StringRef MatcherName) { 285 return new FixedArgCountMatcherCreateCallback<ReturnType (*)()>( 286 matcherMarshall0, Func, MatcherName); 287} 288 289/// \brief 1-arg overload 290template <typename ReturnType, typename ArgType1> 291MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), 292 StringRef MatcherName) { 293 return new FixedArgCountMatcherCreateCallback<ReturnType (*)(ArgType1)>( 294 matcherMarshall1, Func, MatcherName); 295} 296 297/// \brief 2-arg overload 298template <typename ReturnType, typename ArgType1, typename ArgType2> 299MatcherCreateCallback *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. 307template <typename ResultT, typename ArgT, 308 ResultT (*Func)(ArrayRef<const ArgT *>)> 309MatcherCreateCallback * 310makeMatcherAutoMarshall(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