1259701Sdim//===--- Marshallers.h - Generic matcher function marshallers -*- C++ -*-===// 2259701Sdim// 3259701Sdim// The LLVM Compiler Infrastructure 4259701Sdim// 5259701Sdim// This file is distributed under the University of Illinois Open Source 6259701Sdim// License. See LICENSE.TXT for details. 7259701Sdim// 8259701Sdim//===----------------------------------------------------------------------===// 9259701Sdim/// 10259701Sdim/// \file 11259701Sdim/// \brief Functions templates and classes to wrap matcher construct functions. 12259701Sdim/// 13259701Sdim/// A collection of template function and classes that provide a generic 14259701Sdim/// marshalling layer on top of matcher construct functions. 15259701Sdim/// These are used by the registry to export all marshaller constructors with 16259701Sdim/// the same generic interface. 17259701Sdim/// 18259701Sdim//===----------------------------------------------------------------------===// 19259701Sdim 20259701Sdim#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H 21259701Sdim#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H 22259701Sdim 23259701Sdim#include <string> 24259701Sdim 25259701Sdim#include "clang/ASTMatchers/ASTMatchers.h" 26259701Sdim#include "clang/ASTMatchers/Dynamic/Diagnostics.h" 27259701Sdim#include "clang/ASTMatchers/Dynamic/VariantValue.h" 28259701Sdim#include "clang/Basic/LLVM.h" 29259701Sdim#include "llvm/ADT/STLExtras.h" 30259701Sdim#include "llvm/Support/type_traits.h" 31259701Sdim 32259701Sdimnamespace clang { 33259701Sdimnamespace ast_matchers { 34259701Sdimnamespace dynamic { 35259701Sdim 36259701Sdimnamespace internal { 37259701Sdim 38259701Sdim/// \brief Helper template class to just from argument type to the right is/get 39259701Sdim/// functions in VariantValue. 40259701Sdim/// Used to verify and extract the matcher arguments below. 41259701Sdimtemplate <class T> struct ArgTypeTraits; 42259701Sdimtemplate <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> { 43259701Sdim}; 44259701Sdim 45259701Sdimtemplate <> struct ArgTypeTraits<std::string> { 46259701Sdim static StringRef asString() { return "String"; } 47259701Sdim static bool is(const VariantValue &Value) { return Value.isString(); } 48259701Sdim static const std::string &get(const VariantValue &Value) { 49259701Sdim return Value.getString(); 50259701Sdim } 51259701Sdim}; 52259701Sdim 53259701Sdimtemplate <> 54259701Sdimstruct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> { 55259701Sdim}; 56259701Sdim 57259701Sdimtemplate <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > { 58259701Sdim static std::string asString() { 59259701Sdim return (Twine("Matcher<") + 60259701Sdim ast_type_traits::ASTNodeKind::getFromNodeKind<T>().asStringRef() + 61259701Sdim ">").str(); 62259701Sdim } 63259701Sdim static bool is(const VariantValue &Value) { 64259701Sdim return Value.isMatcher() && Value.getMatcher().hasTypedMatcher<T>(); 65259701Sdim } 66259701Sdim static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) { 67259701Sdim return Value.getMatcher().getTypedMatcher<T>(); 68259701Sdim } 69259701Sdim}; 70259701Sdim 71259701Sdimtemplate <> struct ArgTypeTraits<unsigned> { 72259701Sdim static std::string asString() { return "Unsigned"; } 73259701Sdim static bool is(const VariantValue &Value) { return Value.isUnsigned(); } 74259701Sdim static unsigned get(const VariantValue &Value) { 75259701Sdim return Value.getUnsigned(); 76259701Sdim } 77259701Sdim}; 78259701Sdim 79259701Sdim/// \brief Generic MatcherCreate interface. 80259701Sdim/// 81259701Sdim/// Provides a \c run() method that constructs the matcher from the provided 82259701Sdim/// arguments. 83259701Sdimclass MatcherCreateCallback { 84259701Sdimpublic: 85259701Sdim virtual ~MatcherCreateCallback() {} 86259701Sdim virtual VariantMatcher run(const SourceRange &NameRange, 87259701Sdim ArrayRef<ParserValue> Args, 88259701Sdim Diagnostics *Error) const = 0; 89259701Sdim}; 90259701Sdim 91259701Sdim/// \brief Simple callback implementation. Marshaller and function are provided. 92259701Sdim/// 93259701Sdim/// This class wraps a function of arbitrary signature and a marshaller 94259701Sdim/// function into a MatcherCreateCallback. 95259701Sdim/// The marshaller is in charge of taking the VariantValue arguments, checking 96259701Sdim/// their types, unpacking them and calling the underlying function. 97259701Sdimclass FixedArgCountMatcherCreateCallback : public MatcherCreateCallback { 98259701Sdimpublic: 99259701Sdim typedef VariantMatcher (*MarshallerType)(void (*Func)(), 100259701Sdim StringRef MatcherName, 101259701Sdim const SourceRange &NameRange, 102259701Sdim ArrayRef<ParserValue> Args, 103259701Sdim Diagnostics *Error); 104259701Sdim 105259701Sdim /// \param Marshaller Function to unpack the arguments and call \c Func 106259701Sdim /// \param Func Matcher construct function. This is the function that 107259701Sdim /// compile-time matcher expressions would use to create the matcher. 108259701Sdim FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, void (*Func)(), 109259701Sdim StringRef MatcherName) 110259701Sdim : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName) {} 111259701Sdim 112259701Sdim VariantMatcher run(const SourceRange &NameRange, ArrayRef<ParserValue> Args, 113259701Sdim Diagnostics *Error) const { 114259701Sdim return Marshaller(Func, MatcherName, NameRange, Args, Error); 115259701Sdim } 116259701Sdim 117259701Sdimprivate: 118259701Sdim const MarshallerType Marshaller; 119259701Sdim void (* const Func)(); 120259701Sdim const std::string MatcherName; 121259701Sdim}; 122259701Sdim 123259701Sdim/// \brief Simple callback implementation. Free function is wrapped. 124259701Sdim/// 125259701Sdim/// This class simply wraps a free function with the right signature to export 126259701Sdim/// it as a MatcherCreateCallback. 127259701Sdim/// This allows us to have one implementation of the interface for as many free 128259701Sdim/// functions as we want, reducing the number of symbols and size of the 129259701Sdim/// object file. 130259701Sdimclass FreeFuncMatcherCreateCallback : public MatcherCreateCallback { 131259701Sdimpublic: 132259701Sdim typedef VariantMatcher (*RunFunc)(StringRef MatcherName, 133259701Sdim const SourceRange &NameRange, 134259701Sdim ArrayRef<ParserValue> Args, 135259701Sdim Diagnostics *Error); 136259701Sdim 137259701Sdim FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName) 138259701Sdim : Func(Func), MatcherName(MatcherName.str()) {} 139259701Sdim 140259701Sdim VariantMatcher run(const SourceRange &NameRange, ArrayRef<ParserValue> Args, 141259701Sdim Diagnostics *Error) const { 142259701Sdim return Func(MatcherName, NameRange, Args, Error); 143259701Sdim } 144259701Sdim 145259701Sdimprivate: 146259701Sdim const RunFunc Func; 147259701Sdim const std::string MatcherName; 148259701Sdim}; 149259701Sdim 150259701Sdim/// \brief Helper macros to check the arguments on all marshaller functions. 151259701Sdim#define CHECK_ARG_COUNT(count) \ 152259701Sdim if (Args.size() != count) { \ 153259701Sdim Error->addError(NameRange, Error->ET_RegistryWrongArgCount) \ 154259701Sdim << count << Args.size(); \ 155259701Sdim return VariantMatcher(); \ 156259701Sdim } 157259701Sdim 158259701Sdim#define CHECK_ARG_TYPE(index, type) \ 159259701Sdim if (!ArgTypeTraits<type>::is(Args[index].Value)) { \ 160259701Sdim Error->addError(Args[index].Range, Error->ET_RegistryWrongArgType) \ 161259701Sdim << (index + 1) << ArgTypeTraits<type>::asString() \ 162259701Sdim << Args[index].Value.getTypeAsString(); \ 163259701Sdim return VariantMatcher(); \ 164259701Sdim } 165259701Sdim 166259701Sdim/// \brief Helper methods to extract and merge all possible typed matchers 167259701Sdim/// out of the polymorphic object. 168259701Sdimtemplate <class PolyMatcher> 169259701Sdimstatic void mergePolyMatchers(const PolyMatcher &Poly, 170259701Sdim std::vector<DynTypedMatcher> &Out, 171259701Sdim ast_matchers::internal::EmptyTypeList) {} 172259701Sdim 173259701Sdimtemplate <class PolyMatcher, class TypeList> 174259701Sdimstatic void mergePolyMatchers(const PolyMatcher &Poly, 175259701Sdim std::vector<DynTypedMatcher> &Out, TypeList) { 176259701Sdim Out.push_back(ast_matchers::internal::Matcher<typename TypeList::head>(Poly)); 177259701Sdim mergePolyMatchers(Poly, Out, typename TypeList::tail()); 178259701Sdim} 179259701Sdim 180259701Sdim/// \brief Convert the return values of the functions into a VariantMatcher. 181259701Sdim/// 182259701Sdim/// There are 2 cases right now: The return value is a Matcher<T> or is a 183259701Sdim/// polymorphic matcher. For the former, we just construct the VariantMatcher. 184259701Sdim/// For the latter, we instantiate all the possible Matcher<T> of the poly 185259701Sdim/// matcher. 186259701Sdimstatic VariantMatcher outvalueToVariantMatcher(const DynTypedMatcher &Matcher) { 187259701Sdim return VariantMatcher::SingleMatcher(Matcher); 188259701Sdim} 189259701Sdim 190259701Sdimtemplate <typename T> 191259701Sdimstatic VariantMatcher outvalueToVariantMatcher(const T &PolyMatcher, 192259701Sdim typename T::ReturnTypes * = 193259701Sdim NULL) { 194259701Sdim std::vector<DynTypedMatcher> Matchers; 195259701Sdim mergePolyMatchers(PolyMatcher, Matchers, typename T::ReturnTypes()); 196259701Sdim VariantMatcher Out = VariantMatcher::PolymorphicMatcher(Matchers); 197259701Sdim return Out; 198259701Sdim} 199259701Sdim 200259701Sdim/// \brief 0-arg marshaller function. 201259701Sdimtemplate <typename ReturnType> 202259701Sdimstatic VariantMatcher matcherMarshall0(void (*Func)(), StringRef MatcherName, 203259701Sdim const SourceRange &NameRange, 204259701Sdim ArrayRef<ParserValue> Args, 205259701Sdim Diagnostics *Error) { 206259701Sdim typedef ReturnType (*FuncType)(); 207259701Sdim CHECK_ARG_COUNT(0); 208259701Sdim return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)()); 209259701Sdim} 210259701Sdim 211259701Sdim/// \brief 1-arg marshaller function. 212259701Sdimtemplate <typename ReturnType, typename ArgType1> 213259701Sdimstatic VariantMatcher matcherMarshall1(void (*Func)(), StringRef MatcherName, 214259701Sdim const SourceRange &NameRange, 215259701Sdim ArrayRef<ParserValue> Args, 216259701Sdim Diagnostics *Error) { 217259701Sdim typedef ReturnType (*FuncType)(ArgType1); 218259701Sdim CHECK_ARG_COUNT(1); 219259701Sdim CHECK_ARG_TYPE(0, ArgType1); 220259701Sdim return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)( 221259701Sdim ArgTypeTraits<ArgType1>::get(Args[0].Value))); 222259701Sdim} 223259701Sdim 224259701Sdim/// \brief 2-arg marshaller function. 225259701Sdimtemplate <typename ReturnType, typename ArgType1, typename ArgType2> 226259701Sdimstatic VariantMatcher matcherMarshall2(void (*Func)(), StringRef MatcherName, 227259701Sdim const SourceRange &NameRange, 228259701Sdim ArrayRef<ParserValue> Args, 229259701Sdim Diagnostics *Error) { 230259701Sdim typedef ReturnType (*FuncType)(ArgType1, ArgType2); 231259701Sdim CHECK_ARG_COUNT(2); 232259701Sdim CHECK_ARG_TYPE(0, ArgType1); 233259701Sdim CHECK_ARG_TYPE(1, ArgType2); 234259701Sdim return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)( 235259701Sdim ArgTypeTraits<ArgType1>::get(Args[0].Value), 236259701Sdim ArgTypeTraits<ArgType2>::get(Args[1].Value))); 237259701Sdim} 238259701Sdim 239259701Sdim#undef CHECK_ARG_COUNT 240259701Sdim#undef CHECK_ARG_TYPE 241259701Sdim 242259701Sdim/// \brief Variadic marshaller function. 243259701Sdimtemplate <typename ResultT, typename ArgT, 244259701Sdim ResultT (*Func)(ArrayRef<const ArgT *>)> 245259701SdimVariantMatcher 246259701SdimvariadicMatcherCreateCallback(StringRef MatcherName, 247259701Sdim const SourceRange &NameRange, 248259701Sdim ArrayRef<ParserValue> Args, Diagnostics *Error) { 249259701Sdim ArgT **InnerArgs = new ArgT *[Args.size()](); 250259701Sdim 251259701Sdim bool HasError = false; 252259701Sdim for (size_t i = 0, e = Args.size(); i != e; ++i) { 253259701Sdim typedef ArgTypeTraits<ArgT> ArgTraits; 254259701Sdim const ParserValue &Arg = Args[i]; 255259701Sdim const VariantValue &Value = Arg.Value; 256259701Sdim if (!ArgTraits::is(Value)) { 257259701Sdim Error->addError(Arg.Range, Error->ET_RegistryWrongArgType) 258259701Sdim << (i + 1) << ArgTraits::asString() << Value.getTypeAsString(); 259259701Sdim HasError = true; 260259701Sdim break; 261259701Sdim } 262259701Sdim InnerArgs[i] = new ArgT(ArgTraits::get(Value)); 263259701Sdim } 264259701Sdim 265259701Sdim VariantMatcher Out; 266259701Sdim if (!HasError) { 267259701Sdim Out = outvalueToVariantMatcher( 268259701Sdim Func(ArrayRef<const ArgT *>(InnerArgs, Args.size()))); 269259701Sdim } 270259701Sdim 271259701Sdim for (size_t i = 0, e = Args.size(); i != e; ++i) { 272259701Sdim delete InnerArgs[i]; 273259701Sdim } 274259701Sdim delete[] InnerArgs; 275259701Sdim return Out; 276259701Sdim} 277259701Sdim 278259701Sdim/// \brief Helper class used to collect all the possible overloads of an 279259701Sdim/// argument adaptative matcher function. 280259701Sdimtemplate <template <typename ToArg, typename FromArg> class ArgumentAdapterT, 281259701Sdim typename FromTypes, typename ToTypes> 282259701Sdimclass AdaptativeOverloadCollector { 283259701Sdimpublic: 284259701Sdim AdaptativeOverloadCollector(StringRef Name, 285259701Sdim std::vector<MatcherCreateCallback *> &Out) 286259701Sdim : Name(Name), Out(Out) { 287259701Sdim collect(FromTypes()); 288259701Sdim } 289259701Sdim 290259701Sdimprivate: 291259701Sdim typedef ast_matchers::internal::ArgumentAdaptingMatcherFunc< 292259701Sdim ArgumentAdapterT, FromTypes, ToTypes> AdaptativeFunc; 293259701Sdim 294259701Sdim /// \brief End case for the recursion 295259701Sdim static void collect(ast_matchers::internal::EmptyTypeList) {} 296259701Sdim 297259701Sdim /// \brief Recursive case. Get the overload for the head of the list, and 298259701Sdim /// recurse to the tail. 299259701Sdim template <typename FromTypeList> inline void collect(FromTypeList); 300259701Sdim 301259701Sdim const StringRef Name; 302259701Sdim std::vector<MatcherCreateCallback *> &Out; 303259701Sdim}; 304259701Sdim 305259701Sdim/// \brief MatcherCreateCallback that wraps multiple "overloads" of the same 306259701Sdim/// matcher. 307259701Sdim/// 308259701Sdim/// It will try every overload and generate appropriate errors for when none or 309259701Sdim/// more than one overloads match the arguments. 310259701Sdimclass OverloadedMatcherCreateCallback : public MatcherCreateCallback { 311259701Sdimpublic: 312259701Sdim OverloadedMatcherCreateCallback(ArrayRef<MatcherCreateCallback *> Callbacks) 313259701Sdim : Overloads(Callbacks) {} 314259701Sdim 315259701Sdim virtual ~OverloadedMatcherCreateCallback() { 316259701Sdim llvm::DeleteContainerPointers(Overloads); 317259701Sdim } 318259701Sdim 319259701Sdim virtual VariantMatcher run(const SourceRange &NameRange, 320259701Sdim ArrayRef<ParserValue> Args, 321259701Sdim Diagnostics *Error) const { 322259701Sdim std::vector<VariantMatcher> Constructed; 323259701Sdim Diagnostics::OverloadContext Ctx(Error); 324259701Sdim for (size_t i = 0, e = Overloads.size(); i != e; ++i) { 325259701Sdim VariantMatcher SubMatcher = Overloads[i]->run(NameRange, Args, Error); 326259701Sdim if (!SubMatcher.isNull()) { 327259701Sdim Constructed.push_back(SubMatcher); 328259701Sdim } 329259701Sdim } 330259701Sdim 331259701Sdim if (Constructed.empty()) return VariantMatcher(); // No overload matched. 332259701Sdim // We ignore the errors if any matcher succeeded. 333259701Sdim Ctx.revertErrors(); 334259701Sdim if (Constructed.size() > 1) { 335259701Sdim // More than one constructed. It is ambiguous. 336259701Sdim Error->addError(NameRange, Error->ET_RegistryAmbiguousOverload); 337259701Sdim return VariantMatcher(); 338259701Sdim } 339259701Sdim return Constructed[0]; 340259701Sdim } 341259701Sdim 342259701Sdimprivate: 343259701Sdim std::vector<MatcherCreateCallback *> Overloads; 344259701Sdim}; 345259701Sdim 346259701Sdim/// \brief Variadic operator marshaller function. 347259701Sdimclass VariadicOperatorMatcherCreateCallback : public MatcherCreateCallback { 348259701Sdimpublic: 349259701Sdim typedef ast_matchers::internal::VariadicOperatorFunction VarFunc; 350259701Sdim VariadicOperatorMatcherCreateCallback(VarFunc Func, StringRef MatcherName) 351259701Sdim : Func(Func), MatcherName(MatcherName) {} 352259701Sdim 353259701Sdim virtual VariantMatcher run(const SourceRange &NameRange, 354259701Sdim ArrayRef<ParserValue> Args, 355259701Sdim Diagnostics *Error) const { 356259701Sdim std::vector<VariantMatcher> InnerArgs; 357259701Sdim for (size_t i = 0, e = Args.size(); i != e; ++i) { 358259701Sdim const ParserValue &Arg = Args[i]; 359259701Sdim const VariantValue &Value = Arg.Value; 360259701Sdim if (!Value.isMatcher()) { 361259701Sdim Error->addError(Arg.Range, Error->ET_RegistryWrongArgType) 362259701Sdim << (i + 1) << "Matcher<>" << Value.getTypeAsString(); 363259701Sdim return VariantMatcher(); 364259701Sdim } 365259701Sdim InnerArgs.push_back(Value.getMatcher()); 366259701Sdim } 367259701Sdim return VariantMatcher::VariadicOperatorMatcher(Func, InnerArgs); 368259701Sdim } 369259701Sdim 370259701Sdimprivate: 371259701Sdim const VarFunc Func; 372259701Sdim const StringRef MatcherName; 373259701Sdim}; 374259701Sdim 375259701Sdim 376259701Sdim/// Helper functions to select the appropriate marshaller functions. 377259701Sdim/// They detect the number of arguments, arguments types and return type. 378259701Sdim 379259701Sdim/// \brief 0-arg overload 380259701Sdimtemplate <typename ReturnType> 381259701SdimMatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(), 382259701Sdim StringRef MatcherName) { 383259701Sdim return new FixedArgCountMatcherCreateCallback( 384259701Sdim matcherMarshall0<ReturnType>, reinterpret_cast<void (*)()>(Func), 385259701Sdim MatcherName); 386259701Sdim} 387259701Sdim 388259701Sdim/// \brief 1-arg overload 389259701Sdimtemplate <typename ReturnType, typename ArgType1> 390259701SdimMatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), 391259701Sdim StringRef MatcherName) { 392259701Sdim return new FixedArgCountMatcherCreateCallback( 393259701Sdim matcherMarshall1<ReturnType, ArgType1>, 394259701Sdim reinterpret_cast<void (*)()>(Func), MatcherName); 395259701Sdim} 396259701Sdim 397259701Sdim/// \brief 2-arg overload 398259701Sdimtemplate <typename ReturnType, typename ArgType1, typename ArgType2> 399259701SdimMatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, 400259701Sdim ArgType2), 401259701Sdim StringRef MatcherName) { 402259701Sdim return new FixedArgCountMatcherCreateCallback( 403259701Sdim matcherMarshall2<ReturnType, ArgType1, ArgType2>, 404259701Sdim reinterpret_cast<void (*)()>(Func), MatcherName); 405259701Sdim} 406259701Sdim 407259701Sdim/// \brief Variadic overload. 408259701Sdimtemplate <typename ResultT, typename ArgT, 409259701Sdim ResultT (*Func)(ArrayRef<const ArgT *>)> 410259701SdimMatcherCreateCallback * 411259701SdimmakeMatcherAutoMarshall(llvm::VariadicFunction<ResultT, ArgT, Func> VarFunc, 412259701Sdim StringRef MatcherName) { 413259701Sdim return new FreeFuncMatcherCreateCallback( 414259701Sdim &variadicMatcherCreateCallback<ResultT, ArgT, Func>, MatcherName); 415259701Sdim} 416259701Sdim 417259701Sdim/// \brief Argument adaptative overload. 418259701Sdimtemplate <template <typename ToArg, typename FromArg> class ArgumentAdapterT, 419259701Sdim typename FromTypes, typename ToTypes> 420259701SdimMatcherCreateCallback * 421259701SdimmakeMatcherAutoMarshall(ast_matchers::internal::ArgumentAdaptingMatcherFunc< 422259701Sdim ArgumentAdapterT, FromTypes, ToTypes>, 423259701Sdim StringRef MatcherName) { 424259701Sdim std::vector<MatcherCreateCallback *> Overloads; 425259701Sdim AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, ToTypes>(MatcherName, 426259701Sdim Overloads); 427259701Sdim return new OverloadedMatcherCreateCallback(Overloads); 428259701Sdim} 429259701Sdim 430259701Sdimtemplate <template <typename ToArg, typename FromArg> class ArgumentAdapterT, 431259701Sdim typename FromTypes, typename ToTypes> 432259701Sdimtemplate <typename FromTypeList> 433259701Sdiminline void 434259701SdimAdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, ToTypes>::collect( 435259701Sdim FromTypeList) { 436259701Sdim Out.push_back(makeMatcherAutoMarshall( 437259701Sdim &AdaptativeFunc::template create<typename FromTypeList::head>, Name)); 438259701Sdim collect(typename FromTypeList::tail()); 439259701Sdim} 440259701Sdim 441259701Sdim/// \brief Variadic operator overload. 442259701SdimMatcherCreateCallback *makeMatcherAutoMarshall( 443259701Sdim ast_matchers::internal::VariadicOperatorMatcherFunc Func, 444259701Sdim StringRef MatcherName) { 445259701Sdim return new VariadicOperatorMatcherCreateCallback(Func.Func, MatcherName); 446259701Sdim} 447259701Sdim 448259701Sdim} // namespace internal 449259701Sdim} // namespace dynamic 450259701Sdim} // namespace ast_matchers 451259701Sdim} // namespace clang 452259701Sdim 453259701Sdim#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H 454