Add support for eachOf/allOf/anyOf variadic matchers in the dynamic layer.
Summary:
Add support for eachOf/allOf/anyOf variadic matchers in the dynamic layer.
These function require some late binding behavior for the type conversions, thus changes in VariadicValue's MatcherList.
Second try. This time with a fix for C++11 builds.
Reviewers: klimek
CC: cfe-commits, revane
Differential Revision: http://llvm-reviews.chandlerc.com/D1536
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189500 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h
index 94b95b1..902fdc3 100644
--- a/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -348,6 +348,36 @@
std::vector<MatcherCreateCallback *> Overloads;
};
+/// \brief Variadic operator marshaller function.
+class VariadicOperatorMatcherCreateCallback : public MatcherCreateCallback {
+public:
+ typedef ast_matchers::internal::VariadicOperatorFunction VarFunc;
+ VariadicOperatorMatcherCreateCallback(VarFunc Func, StringRef MatcherName)
+ : Func(Func), MatcherName(MatcherName) {}
+
+ virtual VariantMatcher run(const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const {
+ std::vector<VariantMatcher> InnerArgs;
+ for (size_t i = 0, e = Args.size(); i != e; ++i) {
+ const ParserValue &Arg = Args[i];
+ const VariantValue &Value = Arg.Value;
+ if (!Value.isMatcher()) {
+ Error->addError(Arg.Range, Error->ET_RegistryWrongArgType)
+ << (i + 1) << "Matcher<>" << Value.getTypeAsString();
+ return VariantMatcher();
+ }
+ InnerArgs.push_back(Value.getMatcher());
+ }
+ return VariantMatcher::VariadicOperatorMatcher(Func, InnerArgs);
+ }
+
+private:
+ const VarFunc Func;
+ const StringRef MatcherName;
+};
+
+
/// Helper functions to select the appropriate marshaller functions.
/// They detect the number of arguments, arguments types and return type.
@@ -410,6 +440,13 @@
collect(typename FromTypeList::tail());
}
+/// \brief Variadic operator overload.
+MatcherCreateCallback *makeMatcherAutoMarshall(
+ ast_matchers::internal::VariadicOperatorMatcherFunc Func,
+ StringRef MatcherName) {
+ return new VariadicOperatorMatcherCreateCallback(Func.Func, MatcherName);
+}
+
} // namespace internal
} // namespace dynamic
} // namespace ast_matchers
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 55763b0..3f8e7d4 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -77,9 +77,6 @@
//
// Polymorphic + argument overload:
// unless
- // eachOf
- // anyOf
- // allOf
// findAll
//
// Other:
@@ -99,6 +96,8 @@
REGISTER_MATCHER(accessSpecDecl);
REGISTER_MATCHER(alignOfExpr);
+ REGISTER_MATCHER(allOf);
+ REGISTER_MATCHER(anyOf);
REGISTER_MATCHER(anything);
REGISTER_MATCHER(argumentCountIs);
REGISTER_MATCHER(arraySubscriptExpr);
@@ -141,6 +140,7 @@
REGISTER_MATCHER(destructorDecl);
REGISTER_MATCHER(doStmt);
REGISTER_MATCHER(dynamicCastExpr);
+ REGISTER_MATCHER(eachOf);
REGISTER_MATCHER(elaboratedType);
REGISTER_MATCHER(enumConstantDecl);
REGISTER_MATCHER(enumDecl);
diff --git a/lib/ASTMatchers/Dynamic/VariantValue.cpp b/lib/ASTMatchers/Dynamic/VariantValue.cpp
index 87aca7d..c350d78 100644
--- a/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ b/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -38,13 +38,9 @@
.str();
}
- virtual bool hasTypedMatcher(const MatcherOps &Ops) const {
- return Ops.canConstructFrom(*Matcher);
- }
-
- virtual const DynTypedMatcher *getTypedMatcher(const MatcherOps &Ops) const {
- assert(hasTypedMatcher(Ops));
- return Matcher.get();
+ virtual void makeTypedMatcher(MatcherOps &Ops) const {
+ if (Ops.canConstructFrom(*Matcher))
+ Ops.constructFrom(*Matcher);
}
private:
@@ -80,23 +76,49 @@
return (Twine("Matcher<") + Inner + ">").str();
}
- virtual bool hasTypedMatcher(const MatcherOps &Ops) const {
- return getTypedMatcher(Ops) != NULL;
- }
-
- virtual const DynTypedMatcher *getTypedMatcher(const MatcherOps &Ops) const {
- const DynTypedMatcher* Found = NULL;
+ virtual void makeTypedMatcher(MatcherOps &Ops) const {
+ const DynTypedMatcher *Found = NULL;
for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
if (Ops.canConstructFrom(*Matchers[i])) {
- if (Found) return NULL;
+ if (Found)
+ return;
Found = Matchers[i];
}
}
- return Found;
+ if (Found)
+ Ops.constructFrom(*Found);
+ }
+
+ std::vector<const DynTypedMatcher *> Matchers;
+};
+
+class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
+public:
+ VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
+ ArrayRef<VariantMatcher> Args)
+ : Func(Func), Args(Args) {}
+
+ virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
+ return false;
+ }
+
+ virtual std::string getTypeAsString() const {
+ std::string Inner;
+ for (size_t i = 0, e = Args.size(); i != e; ++i) {
+ if (i != 0)
+ Inner += "&";
+ Inner += Args[i].getTypeAsString();
+ }
+ return Inner;
+ }
+
+ virtual void makeTypedMatcher(MatcherOps &Ops) const {
+ Ops.constructVariadicOperator(Func, Args);
}
private:
- std::vector<const DynTypedMatcher *> Matchers;
+ const ast_matchers::internal::VariadicOperatorFunction Func;
+ const std::vector<VariantMatcher> Args;
};
VariantMatcher::VariantMatcher() {}
@@ -110,6 +132,12 @@
return VariantMatcher(new PolymorphicPayload(Matchers));
}
+VariantMatcher VariantMatcher::VariadicOperatorMatcher(
+ ast_matchers::internal::VariadicOperatorFunction Func,
+ ArrayRef<VariantMatcher> Args) {
+ return VariantMatcher(new VariadicOpPayload(Func, Args));
+}
+
bool VariantMatcher::getSingleMatcher(const DynTypedMatcher *&Out) const {
if (Value) return Value->getSingleMatcher(Out);
return false;