Hi klimek,
Refactor ArgumentAdaptativeMatcher matchers to remove the template from their
declaration.
This facilitates dynamic registration. Change the registry code to use the
regular overload resolution mechanism for adaptative matchers.
http://llvm-reviews.chandlerc.com/D1402
Files:
include/clang/ASTMatchers/ASTMatchers.h
include/clang/ASTMatchers/ASTMatchersInternal.h
lib/ASTMatchers/Dynamic/Marshallers.h
lib/ASTMatchers/Dynamic/Registry.cpp
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -1597,12 +1597,7 @@
/// ChildT must be an AST base type.
///
/// Usable as: Any Matcher
-template <typename ChildT>
-internal::ArgumentAdaptingMatcher<internal::HasMatcher, ChildT> has(
- const internal::Matcher<ChildT> &ChildMatcher) {
- return internal::ArgumentAdaptingMatcher<internal::HasMatcher,
- ChildT>(ChildMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has = {};
/// \brief Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
@@ -1618,13 +1613,8 @@
/// DescendantT must be an AST base type.
///
/// Usable as: Any Matcher
-template <typename DescendantT>
-internal::ArgumentAdaptingMatcher<internal::HasDescendantMatcher, DescendantT>
-hasDescendant(const internal::Matcher<DescendantT> &DescendantMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::HasDescendantMatcher,
- DescendantT>(DescendantMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher>
+hasDescendant = {};
/// \brief Matches AST nodes that have child AST nodes that match the
/// provided matcher.
@@ -1642,13 +1632,8 @@
/// matches instead of only on the first one.
///
/// Usable as: Any Matcher
-template <typename ChildT>
-internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT> forEach(
- const internal::Matcher<ChildT> &ChildMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::ForEachMatcher,
- ChildT>(ChildMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher> forEach =
+ {};
/// \brief Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
@@ -1674,15 +1659,8 @@
/// \endcode
///
/// Usable as: Any Matcher
-template <typename DescendantT>
-internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher,
- DescendantT>
-forEachDescendant(
- const internal::Matcher<DescendantT> &DescendantMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::ForEachDescendantMatcher,
- DescendantT>(DescendantMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::ForEachDescendantMatcher>
+forEachDescendant = {};
/// \brief Matches if the node or any descendant matches.
///
@@ -1702,7 +1680,8 @@
template <typename T>
internal::PolymorphicMatcherWithParam2<
internal::EachOfMatcher, internal::Matcher<T>,
- internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, T> >
+ internal::ArgumentAdaptingMatcherFunc<
+ internal::ForEachDescendantMatcher>::Adaptor<T> >
findAll(const internal::Matcher<T> &Matcher) {
return eachOf(Matcher, forEachDescendant(Matcher));
}
@@ -1717,15 +1696,9 @@
/// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }".
///
/// Usable as: Any Matcher
-template <typename ParentT>
-internal::ArgumentAdaptingMatcher<internal::HasParentMatcher, ParentT,
- internal::TypeList<Decl, Stmt>,
- internal::TypeList<Decl, Stmt> >
-hasParent(const internal::Matcher<ParentT> &ParentMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::HasParentMatcher, ParentT, internal::TypeList<Decl, Stmt>,
- internal::TypeList<Decl, Stmt> >(ParentMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<
+ internal::HasParentMatcher, internal::TypeList<Decl, Stmt>,
+ internal::TypeList<Decl, Stmt> > hasParent = {};
/// \brief Matches AST nodes that have an ancestor that matches the provided
/// matcher.
@@ -1738,15 +1711,9 @@
/// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43.
///
/// Usable as: Any Matcher
-template <typename AncestorT>
-internal::ArgumentAdaptingMatcher<internal::HasAncestorMatcher, AncestorT,
- internal::TypeList<Decl, Stmt>,
- internal::TypeList<Decl, Stmt> >
-hasAncestor(const internal::Matcher<AncestorT> &AncestorMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::HasAncestorMatcher, AncestorT, internal::TypeList<Decl, Stmt>,
- internal::TypeList<Decl, Stmt> >(AncestorMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<
+ internal::HasAncestorMatcher, internal::TypeList<Decl, Stmt>,
+ internal::TypeList<Decl, Stmt> > hasAncestor = {};
/// \brief Matches if the provided matcher does not match.
///
Index: include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchersInternal.h
+++ include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -803,22 +803,33 @@
/// If a matcher does not need knowledge about the inner type, prefer to use
/// PolymorphicMatcherWithParam1.
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
- typename T, typename FromTypes = AdaptativeDefaultFromTypes,
+ typename FromTypes = AdaptativeDefaultFromTypes,
typename ToTypes = AdaptativeDefaultToTypes>
-class ArgumentAdaptingMatcher {
-public:
- explicit ArgumentAdaptingMatcher(const Matcher<T> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
+struct ArgumentAdaptingMatcherFunc {
+ template <typename T> class Adaptor {
+ public:
+ explicit Adaptor(const Matcher<T> &InnerMatcher)
+ : InnerMatcher(InnerMatcher) {}
+
+ typedef ToTypes ReturnTypes;
+
+ template <typename To> operator Matcher<To>() const {
+ return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
+ }
- typedef ToTypes ReturnTypes;
+ private:
+ const Matcher<T> InnerMatcher;
+ };
- template <typename To>
- operator Matcher<To>() const {
- return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
+ template <typename T>
+ static Adaptor<T> create(const Matcher<T> &InnerMatcher) {
+ return Adaptor<T>(InnerMatcher);
}
-private:
- const Matcher<T> InnerMatcher;
+ template <typename T>
+ Adaptor<T> operator()(const Matcher<T> &InnerMatcher) const {
+ return create(InnerMatcher);
+ }
};
/// \brief A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be
Index: lib/ASTMatchers/Dynamic/Marshallers.h
===================================================================
--- lib/ASTMatchers/Dynamic/Marshallers.h
+++ lib/ASTMatchers/Dynamic/Marshallers.h
@@ -280,6 +280,74 @@
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,33 @@
&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);
+}
+
+
+///----- Inline implementations -----///
+
+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
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -48,48 +48,6 @@
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 @@
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 @@
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);
@@ -253,14 +147,18 @@
REGISTER_MATCHER(expr);
REGISTER_MATCHER(fieldDecl);
REGISTER_MATCHER(floatLiteral);
+ REGISTER_MATCHER(forEach);
+ REGISTER_MATCHER(forEachDescendant);
REGISTER_MATCHER(forField);
REGISTER_MATCHER(forRangeStmt);
REGISTER_MATCHER(forStmt);
REGISTER_MATCHER(functionDecl);
REGISTER_MATCHER(functionTemplateDecl);
REGISTER_MATCHER(functionType);
REGISTER_MATCHER(functionalCastExpr);
REGISTER_MATCHER(gotoStmt);
+ REGISTER_MATCHER(has);
+ REGISTER_MATCHER(hasAncestor);
REGISTER_MATCHER(hasAnyArgument);
REGISTER_MATCHER(hasAnyConstructorInitializer);
REGISTER_MATCHER(hasAnyParameter);
@@ -276,6 +174,7 @@
REGISTER_MATCHER(hasConditionVariableStatement);
REGISTER_MATCHER(hasDeclContext);
REGISTER_MATCHER(hasDeducedType);
+ REGISTER_MATCHER(hasDescendant);
REGISTER_MATCHER(hasDestinationType);
REGISTER_MATCHER(hasEitherOperand);
REGISTER_MATCHER(hasElementType);
@@ -293,6 +192,7 @@
REGISTER_MATCHER(hasOperatorName);
REGISTER_MATCHER(hasOverloadedOperatorName);
REGISTER_MATCHER(hasParameter);
+ REGISTER_MATCHER(hasParent);
REGISTER_MATCHER(hasQualifier);
REGISTER_MATCHER(hasRHS);
REGISTER_MATCHER(hasSingleDecl);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits