//===--- Registry.cpp - Matcher registry -------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===------------------------------------------------------------===// /// /// \file /// \brief Registry map populated at static initialization time. /// //===------------------------------------------------------------===// #include "clang/ASTMatchers/Dynamic/Registry.h" #include #include "Marshallers.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ManagedStatic.h" namespace clang { namespace ast_matchers { namespace dynamic { namespace { using internal::MatcherCreateCallback; typedef llvm::StringMap ConstructorMap; class RegistryMaps { public: RegistryMaps(); ~RegistryMaps(); const ConstructorMap &constructors() const { return Constructors; } private: void registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback); ConstructorMap Constructors; }; void RegistryMaps::registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback) { assert(Constructors.find(MatcherName) == Constructors.end()); Constructors[MatcherName] = Callback; } /// \brief MatcherCreateCallback that wraps multiple "overloads" of the same /// matcher. /// /// It will try every overload and generate appropriate errors for when none or /// more than one overloads match the arguments. class OverloadedMatcherCreateCallback : public MatcherCreateCallback { public: OverloadedMatcherCreateCallback(ArrayRef Callbacks) : Overloads(Callbacks) {} virtual ~OverloadedMatcherCreateCallback() { for (size_t i = 0, e = Overloads.size(); i != e; ++i) delete Overloads[i]; } virtual VariantMatcher run(const SourceRange &NameRange, ArrayRef Args, Diagnostics *Error) const { std::vector Constructed; Diagnostics::OverloadContext Ctx(Error); for (size_t i = 0, e = Overloads.size(); i != e; ++i) { VariantMatcher SubMatcher = Overloads[i]->run(NameRange, Args, Error); if (!SubMatcher.isNull()) { Constructed.push_back(SubMatcher); } } if (Constructed.empty()) return VariantMatcher(); // No overload matched. // We ignore the errors if any matcher succeeded. Ctx.revertErrors(); if (Constructed.size() > 1) { // More than one constructed. It is ambiguous. Error->addError(NameRange, Error->ET_RegistryAmbiguousOverload); return VariantMatcher(); } return Constructed[0]; } private: std::vector Overloads; }; #define REGISTER_MATCHER(name) \ registerMatcher(#name, internal::makeMatcherAutoMarshall( \ ::clang::ast_matchers::name, #name)); #define SPECIFIC_MATCHER_OVERLOAD(name, Id) \ static_cast< ::clang::ast_matchers::name##_Type##Id>( \ ::clang::ast_matchers::name) #define REGISTER_OVERLOADED_2(name) \ do { \ MatcherCreateCallback *Callbacks[] = { \ internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 0), \ #name), \ internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 1), \ #name) \ }; \ registerMatcher(#name, new OverloadedMatcherCreateCallback(Callbacks)); \ } while (0) /// \brief Class that allows us to bind to the constructor of an /// \c ArgumentAdaptingMatcher. /// This class, together with \c collectAdaptativeMatcherOverloads below, help /// us detect the Adapter class and create overload functions for the /// appropriate To/From types. /// We instantiate the \c createAdatingMatcher function for every type in /// \c FromTypes. \c ToTypes is handled on the marshaller side by using the /// \c ReturnTypes typedef in \c ArgumentAdaptingMatcher. template