diff options
Diffstat (limited to 'clang/lib/ASTMatchers')
| -rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Marshallers.h | 92 | ||||
| -rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Registry.cpp | 116 |
2 files changed, 100 insertions, 108 deletions
diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/clang/lib/ASTMatchers/Dynamic/Marshallers.h index abd5d402f15..94b95b10d56 100644 --- a/clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -280,6 +280,74 @@ variadicMatcherCreateCallback(StringRef MatcherName, return Out; } +/// \brief Helper class used to collect all the possible overloads of an +/// argument adaptative matcher function. +template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, + typename FromTypes, typename ToTypes> +class AdaptativeOverloadCollector { +public: + AdaptativeOverloadCollector(StringRef Name, + std::vector<MatcherCreateCallback *> &Out) + : Name(Name), Out(Out) { + collect(FromTypes()); + } + +private: + typedef ast_matchers::internal::ArgumentAdaptingMatcherFunc< + ArgumentAdapterT, FromTypes, ToTypes> AdaptativeFunc; + + /// \brief End case for the recursion + static void collect(ast_matchers::internal::EmptyTypeList) {} + + /// \brief Recursive case. Get the overload for the head of the list, and + /// recurse to the tail. + template <typename FromTypeList> inline void collect(FromTypeList); + + const StringRef Name; + std::vector<MatcherCreateCallback *> &Out; +}; + +/// \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<MatcherCreateCallback *> Callbacks) + : Overloads(Callbacks) {} + + virtual ~OverloadedMatcherCreateCallback() { + llvm::DeleteContainerPointers(Overloads); + } + + virtual VariantMatcher run(const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error) const { + std::vector<VariantMatcher> 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<MatcherCreateCallback *> Overloads; +}; + /// Helper functions to select the appropriate marshaller functions. /// They detect the number of arguments, arguments types and return type. @@ -318,6 +386,30 @@ makeMatcherAutoMarshall(llvm::VariadicFunction<ResultT, ArgT, Func> VarFunc, &variadicMatcherCreateCallback<ResultT, ArgT, Func>, MatcherName); } +/// \brief Argument adaptative overload. +template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, + typename FromTypes, typename ToTypes> +MatcherCreateCallback * +makeMatcherAutoMarshall(ast_matchers::internal::ArgumentAdaptingMatcherFunc< + ArgumentAdapterT, FromTypes, ToTypes>, + StringRef MatcherName) { + std::vector<MatcherCreateCallback *> Overloads; + AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, ToTypes>(MatcherName, + Overloads); + return new OverloadedMatcherCreateCallback(Overloads); +} + +template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, + typename FromTypes, typename ToTypes> +template <typename FromTypeList> +inline void +AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, ToTypes>::collect( + FromTypeList) { + Out.push_back(makeMatcherAutoMarshall( + &AdaptativeFunc::template create<typename FromTypeList::head>, Name)); + collect(typename FromTypeList::tail()); +} + } // namespace internal } // namespace dynamic } // namespace ast_matchers diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 51d7bd856e6..55763b0efec 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -48,48 +48,6 @@ void RegistryMaps::registerMatcher(StringRef MatcherName, 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<MatcherCreateCallback *> 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<ParserValue> Args, - Diagnostics *Error) const { - std::vector<VariantMatcher> 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<MatcherCreateCallback*> Overloads; -}; - #define REGISTER_MATCHER(name) \ registerMatcher(#name, internal::makeMatcherAutoMarshall( \ ::clang::ast_matchers::name, #name)); @@ -106,65 +64,8 @@ class OverloadedMatcherCreateCallback : public MatcherCreateCallback { 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 <template <typename ToArg, typename FromArg> class ArgumentAdapterT, - typename FromTypes, typename ToTypes> -struct AdaptativeMatcherWrapper { - template <typename FromArg> - static ast_matchers::internal::ArgumentAdaptingMatcher< - ArgumentAdapterT, FromArg, FromTypes, ToTypes> - createAdatingMatcher( - const ast_matchers::internal::Matcher<FromArg> &InnerMatcher) { - return ast_matchers::internal::ArgumentAdaptingMatcher< - ArgumentAdapterT, FromArg, FromTypes, ToTypes>(InnerMatcher); - } - - static void collectOverloads(StringRef Name, - std::vector<MatcherCreateCallback *> &Out, - ast_matchers::internal::EmptyTypeList) {} - - template <typename FromTypeList> - static void collectOverloads(StringRef Name, - std::vector<MatcherCreateCallback *> &Out, - FromTypeList TypeList) { - Out.push_back(internal::makeMatcherAutoMarshall( - &createAdatingMatcher<typename FromTypeList::head>, Name)); - collectOverloads(Name, Out, typename FromTypeList::tail()); - } - - static void collectOverloads(StringRef Name, - std::vector<MatcherCreateCallback *> &Out) { - collectOverloads(Name, Out, FromTypes()); - } -}; - -template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, - typename DummyArg, typename FromTypes, typename ToTypes> -void collectAdaptativeMatcherOverloads( - StringRef Name, - ast_matchers::internal::ArgumentAdaptingMatcher<ArgumentAdapterT, DummyArg, - FromTypes, ToTypes>( - *func)(const ast_matchers::internal::Matcher<DummyArg> &), - std::vector<MatcherCreateCallback *> &Out) { - AdaptativeMatcherWrapper<ArgumentAdapterT, FromTypes, - ToTypes>::collectOverloads(Name, Out); -} - -#define REGISTER_ADAPTATIVE(name) \ - do { \ - std::vector<MatcherCreateCallback *> Overloads; \ - collectAdaptativeMatcherOverloads(#name, &name<Decl>, Overloads); \ - registerMatcher(#name, new OverloadedMatcherCreateCallback(Overloads)); \ + registerMatcher(#name, \ + new internal::OverloadedMatcherCreateCallback(Callbacks)); \ } while (0) /// \brief Generate a registry map with all the known matchers. @@ -196,13 +97,6 @@ RegistryMaps::RegistryMaps() { REGISTER_OVERLOADED_2(references); REGISTER_OVERLOADED_2(thisPointerType); - REGISTER_ADAPTATIVE(forEach); - REGISTER_ADAPTATIVE(forEachDescendant); - REGISTER_ADAPTATIVE(has); - REGISTER_ADAPTATIVE(hasAncestor); - REGISTER_ADAPTATIVE(hasDescendant); - REGISTER_ADAPTATIVE(hasParent); - REGISTER_MATCHER(accessSpecDecl); REGISTER_MATCHER(alignOfExpr); REGISTER_MATCHER(anything); @@ -254,6 +148,8 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(expr); REGISTER_MATCHER(fieldDecl); REGISTER_MATCHER(floatLiteral); + REGISTER_MATCHER(forEach); + REGISTER_MATCHER(forEachDescendant); REGISTER_MATCHER(forField); REGISTER_MATCHER(forRangeStmt); REGISTER_MATCHER(forStmt); @@ -262,6 +158,8 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(functionType); REGISTER_MATCHER(functionalCastExpr); REGISTER_MATCHER(gotoStmt); + REGISTER_MATCHER(has); + REGISTER_MATCHER(hasAncestor); REGISTER_MATCHER(hasAnyArgument); REGISTER_MATCHER(hasAnyConstructorInitializer); REGISTER_MATCHER(hasAnyParameter); @@ -277,6 +175,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasConditionVariableStatement); REGISTER_MATCHER(hasDeclContext); REGISTER_MATCHER(hasDeducedType); + REGISTER_MATCHER(hasDescendant); REGISTER_MATCHER(hasDestinationType); REGISTER_MATCHER(hasEitherOperand); REGISTER_MATCHER(hasElementType); @@ -294,6 +193,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasOperatorName); REGISTER_MATCHER(hasOverloadedOperatorName); REGISTER_MATCHER(hasParameter); + REGISTER_MATCHER(hasParent); REGISTER_MATCHER(hasQualifier); REGISTER_MATCHER(hasRHS); REGISTER_MATCHER(hasSingleDecl); |

