Enhancements for the DynTypedMatcher system.
- Added conversion routines and checks in Matcher<T> that take a DynTypedMatcher.
- Added type information on the error messages for the marshallers.
- Allows future work on Polymorphic/overloaded matchers. We should be
able to disambiguate at runtime and choose the appropriate overload.
llvm-svn: 184429
diff --git a/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
index 79c9389..6b1d660 100644
--- a/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
@@ -36,7 +36,7 @@
case Diagnostics::ET_RegistryWrongArgCount:
return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
case Diagnostics::ET_RegistryWrongArgType:
- return "Incorrect type on function $0 for arg $1.";
+ return "Incorrect type for arg $0. (Expected = $1) != (Actual = $2)";
case Diagnostics::ET_RegistryNotBindable:
return "Matcher does not support binding.";
diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/clang/lib/ASTMatchers/Dynamic/Marshallers.h
index 4ba33b8..aceddc9 100644
--- a/clang/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -42,6 +42,7 @@
};
template <> struct ArgTypeTraits<std::string> {
+ static StringRef asString() { return "String"; }
static bool is(const VariantValue &Value) { return Value.isString(); }
static const std::string &get(const VariantValue &Value) {
return Value.getString();
@@ -49,13 +50,21 @@
};
template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
- static bool is(const VariantValue &Value) { return Value.isMatcher(); }
+ static std::string asString() {
+ return (Twine("Matcher<") +
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>().asStringRef() +
+ ">").str();
+ }
+ static bool is(const VariantValue &Value) {
+ return Value.hasTypedMatcher<T>();
+ }
static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) {
return Value.getTypedMatcher<T>();
}
};
template <> struct ArgTypeTraits<unsigned> {
+ static std::string asString() { return "Unsigned"; }
static bool is(const VariantValue &Value) { return Value.isUnsigned(); }
static unsigned get(const VariantValue &Value) {
return Value.getUnsigned();
@@ -147,7 +156,8 @@
#define CHECK_ARG_TYPE(index, type) \
if (!ArgTypeTraits<type>::is(Args[index].Value)) { \
Error->pushErrorFrame(Args[index].Range, Error->ET_RegistryWrongArgType) \
- << MatcherName << (index + 1); \
+ << (index + 1) << ArgTypeTraits<type>::asString() \
+ << Args[index].Value.getTypeAsString(); \
return NULL; \
}
@@ -201,14 +211,16 @@
bool HasError = false;
for (size_t i = 0, e = Args.size(); i != e; ++i) {
- if (!Args[i].Value.isTypedMatcher<DerivedType>()) {
- Error->pushErrorFrame(Args[i].Range, Error->ET_RegistryWrongArgType)
- << MatcherName << (i + 1);
+ typedef ArgTypeTraits<DerivedMatcherType> DerivedTraits;
+ const ParserValue &Arg = Args[i];
+ const VariantValue &Value = Arg.Value;
+ if (!DerivedTraits::is(Value)) {
+ Error->pushErrorFrame(Arg.Range, Error->ET_RegistryWrongArgType)
+ << (i + 1) << DerivedTraits::asString() << Value.getTypeAsString();
HasError = true;
break;
}
- InnerArgs[i] =
- new DerivedMatcherType(Args[i].Value.getTypedMatcher<DerivedType>());
+ InnerArgs[i] = new DerivedMatcherType(DerivedTraits::get(Value));
}
DynTypedMatcher *Out = NULL;
diff --git a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
index 6fcbe7f..912858f 100644
--- a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -14,6 +14,8 @@
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+
namespace clang {
namespace ast_matchers {
namespace dynamic {
@@ -123,6 +125,18 @@
Value.Matcher = NewValue;
}
+std::string VariantValue::getTypeAsString() const {
+ switch (Type) {
+ case VT_String: return "String";
+ case VT_Matcher:
+ return (Twine("Matcher<") + getMatcher().getSupportedKind().asStringRef() +
+ ">").str();
+ case VT_Unsigned: return "Unsigned";
+ case VT_Nothing: return "Nothing";
+ }
+ llvm_unreachable("Invalid Type");
+}
+
} // end namespace dynamic
} // end namespace ast_matchers
} // end namespace clang