summaryrefslogtreecommitdiffstats
path: root/clang/include
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include')
-rw-r--r--clang/include/clang/ASTMatchers/ASTMatchers.h108
-rw-r--r--clang/include/clang/ASTMatchers/ASTMatchersInternal.h72
-rw-r--r--clang/include/clang/ASTMatchers/ASTMatchersMacros.h67
-rw-r--r--clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h3
-rw-r--r--clang/include/clang/ASTMatchers/Dynamic/Parser.h13
-rw-r--r--clang/include/clang/ASTMatchers/Dynamic/Registry.h28
-rw-r--r--clang/include/clang/ASTMatchers/Dynamic/VariantValue.h91
7 files changed, 256 insertions, 126 deletions
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 366707b0a44..d6c19b7dfa2 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -1451,10 +1451,13 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
///
/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl>
inline internal::PolymorphicMatcherWithParam1<
- internal::HasOverloadedOperatorNameMatcher, StringRef>
+ internal::HasOverloadedOperatorNameMatcher, StringRef,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>
hasOverloadedOperatorName(const StringRef Name) {
return internal::PolymorphicMatcherWithParam1<
- internal::HasOverloadedOperatorNameMatcher, StringRef>(Name);
+ internal::HasOverloadedOperatorNameMatcher, StringRef,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>(
+ Name);
}
/// \brief Matches C++ classes that are directly or indirectly derived from
@@ -1784,11 +1787,9 @@ inline internal::Matcher<CallExpr> callee(
/// class X {};
/// void y(X &x) { x; X z; }
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<Expr, NodeType>::value ||
- llvm::is_base_of<ValueDecl, NodeType>::value),
- instantiated_with_wrong_types);
+AST_POLYMORPHIC_MATCHER_P(hasType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl),
+ internal::Matcher<QualType>, InnerMatcher) {
return InnerMatcher.matches(Node.getType(), Finder, Builder);
}
@@ -1810,8 +1811,8 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>,
///
/// Usable as: Matcher<Expr>, Matcher<ValueDecl>
inline internal::PolymorphicMatcherWithParam1<
- internal::matcher_hasType0Matcher,
- internal::Matcher<QualType> >
+ internal::matcher_hasType0Matcher, internal::Matcher<QualType>,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl)>
hasType(const internal::Matcher<Decl> &InnerMatcher) {
return hasType(qualType(hasDeclaration(InnerMatcher)));
}
@@ -2013,11 +2014,9 @@ AST_MATCHER_P(
/// void f(int x, int y);
/// f(0, 0);
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
- llvm::is_base_of<CXXConstructExpr,
- NodeType>::value),
- instantiated_with_wrong_types);
+AST_POLYMORPHIC_MATCHER_P(argumentCountIs, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+ CallExpr, CXXConstructExpr),
+ unsigned, N) {
return Node.getNumArgs() == N;
}
@@ -2030,11 +2029,9 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) {
/// void x(int) { int y; x(y); }
/// \endcode
AST_POLYMORPHIC_MATCHER_P2(
- hasArgument, unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
- llvm::is_base_of<CXXConstructExpr,
- NodeType>::value),
- instantiated_with_wrong_types);
+ hasArgument,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(CallExpr, CXXConstructExpr),
+ unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
return (N < Node.getNumArgs() &&
InnerMatcher.matches(
*Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
@@ -2180,12 +2177,9 @@ AST_MATCHER(CXXConstructorDecl, isImplicit) {
/// the argument before applying the inner matcher. We'll want to remove
/// this to allow for greater control by the user once \c ignoreImplicit()
/// has been implemented.
-AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher<Expr>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
- llvm::is_base_of<CXXConstructExpr,
- NodeType>::value),
- instantiated_with_wrong_types);
+AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+ CallExpr, CXXConstructExpr),
+ internal::Matcher<Expr>, InnerMatcher) {
for (unsigned I = 0; I < Node.getNumArgs(); ++I) {
BoundNodesTreeBuilder Result(*Builder);
if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), Finder,
@@ -2280,15 +2274,10 @@ AST_MATCHER(FunctionDecl, isExternC) {
/// \code
/// if (true) {}
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher<Expr>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<IfStmt, NodeType>::value) ||
- (llvm::is_base_of<ForStmt, NodeType>::value) ||
- (llvm::is_base_of<WhileStmt, NodeType>::value) ||
- (llvm::is_base_of<DoStmt, NodeType>::value) ||
- (llvm::is_base_of<ConditionalOperator, NodeType>::value),
- has_condition_requires_if_statement_conditional_operator_or_loop);
+AST_POLYMORPHIC_MATCHER_P(
+ hasCondition, AST_POLYMORPHIC_SUPPORTED_TYPES_5(
+ IfStmt, ForStmt, WhileStmt, DoStmt, ConditionalOperator),
+ internal::Matcher<Expr>, InnerMatcher) {
const Expr *const Condition = Node.getCond();
return (Condition != NULL &&
InnerMatcher.matches(*Condition, Finder, Builder));
@@ -2325,18 +2314,15 @@ struct NotEqualsBoundNodePredicate {
/// forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d"))))))
/// will trigger a match for each combination of variable declaration
/// and reference to that variable declaration within a compound statement.
-AST_POLYMORPHIC_MATCHER_P(equalsBoundNode, std::string, ID) {
+AST_POLYMORPHIC_MATCHER_P(equalsBoundNode, AST_POLYMORPHIC_SUPPORTED_TYPES_4(
+ Stmt, Decl, Type, QualType),
+ std::string, ID) {
// FIXME: Figure out whether it makes sense to allow this
// on any other node types.
// For *Loc it probably does not make sense, as those seem
// unique. For NestedNameSepcifier it might make sense, as
// those also have pointer identity, but I'm not sure whether
// they're ever reused.
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<Stmt, NodeType>::value ||
- llvm::is_base_of<Decl, NodeType>::value ||
- llvm::is_base_of<Type, NodeType>::value ||
- llvm::is_base_of<QualType, NodeType>::value),
- equals_bound_node_requires_non_unique_node_class);
internal::NotEqualsBoundNodePredicate Predicate;
Predicate.ID = ID;
Predicate.Node = ast_type_traits::DynTypedNode::create(Node);
@@ -2403,13 +2389,9 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
/// matches 'for (;;) {}'
/// with compoundStmt()
/// matching '{}'
-AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<DoStmt, NodeType>::value) ||
- (llvm::is_base_of<ForStmt, NodeType>::value) ||
- (llvm::is_base_of<WhileStmt, NodeType>::value),
- has_body_requires_for_while_or_do_statement);
+AST_POLYMORPHIC_MATCHER_P(
+ hasBody, AST_POLYMORPHIC_SUPPORTED_TYPES_3(DoStmt, ForStmt, WhileStmt),
+ internal::Matcher<Stmt>, InnerMatcher) {
const Stmt *const Statement = Node.getBody();
return (Statement != NULL &&
InnerMatcher.matches(*Statement, Finder, Builder));
@@ -2470,11 +2452,9 @@ equals(const ValueT &Value) {
/// \code
/// !(a || b)
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<BinaryOperator, NodeType>::value) ||
- (llvm::is_base_of<UnaryOperator, NodeType>::value),
- has_condition_requires_if_statement_or_conditional_operator);
+AST_POLYMORPHIC_MATCHER_P(hasOperatorName, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+ BinaryOperator, UnaryOperator),
+ std::string, Name) {
return Name == Node.getOpcodeStr(Node.getOpcode());
}
@@ -2596,12 +2576,8 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression,
/// \endcode
///
/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>
-AST_POLYMORPHIC_MATCHER(isDefinition) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<TagDecl, NodeType>::value) ||
- (llvm::is_base_of<VarDecl, NodeType>::value) ||
- (llvm::is_base_of<FunctionDecl, NodeType>::value),
- is_definition_requires_isThisDeclarationADefinition_method);
+AST_POLYMORPHIC_MATCHER(isDefinition, AST_POLYMORPHIC_SUPPORTED_TYPES_3(
+ TagDecl, VarDecl, FunctionDecl)) {
return Node.isThisDeclarationADefinition();
}
@@ -2834,11 +2810,9 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
/// does not match, as X<A> is an explicit template specialization.
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
-AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) ||
- (llvm::is_base_of<VarDecl, NodeType>::value) ||
- (llvm::is_base_of<CXXRecordDecl, NodeType>::value),
- requires_getTemplateSpecializationKind_method);
+AST_POLYMORPHIC_MATCHER(
+ isTemplateInstantiation,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) {
return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation ||
Node.getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition);
@@ -2856,11 +2830,9 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) {
/// matches the specialization A<int>().
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
-AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) ||
- (llvm::is_base_of<VarDecl, NodeType>::value) ||
- (llvm::is_base_of<CXXRecordDecl, NodeType>::value),
- requires_getTemplateSpecializationKind_method);
+AST_POLYMORPHIC_MATCHER(
+ isExplicitTemplateSpecialization,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) {
return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization);
}
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 9e6d4bf3482..f29ea0e1dcc 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -761,6 +761,58 @@ private:
const Matcher<T> InnerMatcher;
};
+/// \brief A simple type-list implementation.
+///
+/// It is implemented as a flat struct with a maximum number of arguments to
+/// simplify compiler error messages.
+/// However, it is used as a "linked list" of types.
+///
+/// Note: If you need to extend for more types, add them as template arguments
+/// and to the "typedef TypeList<...> tail" below. Nothing else is needed.
+template <typename T1 = void, typename T2 = void, typename T3 = void,
+ typename T4 = void, typename T5 = void, typename T6 = void,
+ typename T7 = void, typename T8 = void>
+struct TypeList {
+ /// \brief The first type on the list.
+ typedef T1 head;
+
+ /// \brief A sub list with the tail. ie everything but the head.
+ ///
+ /// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the
+ /// end of the list.
+ typedef TypeList<T2, T3, T4, T5, T6, T7, T8> tail;
+
+ /// \brief Helper meta-function to determine if some type \c T is present or
+ /// a parent type in the list.
+ template <typename T> struct ContainsSuperOf {
+ static const bool value = llvm::is_base_of<head, T>::value ||
+ tail::template ContainsSuperOf<T>::value;
+ };
+};
+
+/// \brief Specialization of ContainsSuperOf for the empty list.
+template <> template <typename T> struct TypeList<>::ContainsSuperOf {
+ static const bool value = false;
+};
+
+/// \brief The empty type list.
+typedef TypeList<> EmptyTypeList;
+
+/// \brief A "type list" that contains all types.
+///
+/// Useful for matchers like \c anything and \c unless.
+typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
+ QualType, Type, TypeLoc, CXXCtorInitializer> AllNodeBaseTypes;
+
+/// \brief Helper meta-function to extract the argument out of a function of
+/// type void(Arg).
+///
+/// See AST_POLYMORPHIC_SUPPORTED_TYPES_* for details.
+template <class T> struct ExtractFunctionArgMeta;
+template <class T> struct ExtractFunctionArgMeta<void(T)> {
+ typedef T type;
+};
+
/// \brief A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be
/// created from N parameters p1, ..., pN (of type P1, ..., PN) and
/// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN)
@@ -773,24 +825,33 @@ private:
/// - PolymorphicMatcherWithParam1<ValueEqualsMatcher, int>(42)
/// creates an object that can be used as a Matcher<T> for any type T
/// where a ValueEqualsMatcher<T, int>(42) can be constructed.
-template <template <typename T> class MatcherT>
+template <template <typename T> class MatcherT,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
class PolymorphicMatcherWithParam0 {
public:
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
template <typename T>
operator Matcher<T>() const {
+ TOOLING_COMPILE_ASSERT(ReturnTypes::template ContainsSuperOf<T>::value,
+ right_polymorphic_conversion);
return Matcher<T>(new MatcherT<T>());
}
};
template <template <typename T, typename P1> class MatcherT,
- typename P1>
+ typename P1,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
class PolymorphicMatcherWithParam1 {
public:
explicit PolymorphicMatcherWithParam1(const P1 &Param1)
: Param1(Param1) {}
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
template <typename T>
operator Matcher<T>() const {
+ TOOLING_COMPILE_ASSERT(ReturnTypes::template ContainsSuperOf<T>::value,
+ right_polymorphic_conversion);
return Matcher<T>(new MatcherT<T, P1>(Param1));
}
@@ -799,14 +860,19 @@ private:
};
template <template <typename T, typename P1, typename P2> class MatcherT,
- typename P1, typename P2>
+ typename P1, typename P2,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
class PolymorphicMatcherWithParam2 {
public:
PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2)
: Param1(Param1), Param2(Param2) {}
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
template <typename T>
operator Matcher<T>() const {
+ TOOLING_COMPILE_ASSERT(ReturnTypes::template ContainsSuperOf<T>::value,
+ right_polymorphic_conversion);
return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2));
}
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
index f5ca26bca73..91e254eb571 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -155,16 +155,34 @@
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
+/// \brief Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER*
+/// macros.
+///
+/// You can't pass something like \c TypeList<Foo, Bar> to a macro, because it
+/// will look at that as two arguments. However, you can pass
+/// \c void(TypeList<Foo, Bar>), which works thanks to the parenthesis.
+/// The \c PolymorphicMatcherWithParam* classes will unpack the function type to
+/// extract the TypeList object.
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_2(t1, t2) \
+ void(internal::TypeList<t1, t2>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_3(t1, t2, t3) \
+ void(internal::TypeList<t1, t2, t3>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_4(t1, t2, t3, t4) \
+ void(internal::TypeList<t1, t2, t3, t4>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_5(t1, t2, t3, t4, t5) \
+ void(internal::TypeList<t1, t2, t3, t4, t5>)
+
/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
/// defines a single-parameter function named DefineMatcher() that is
/// polymorphic in the return type.
///
/// The variables are the same as for AST_MATCHER, but NodeType will be deduced
/// from the calling context.
-#define AST_POLYMORPHIC_MATCHER(DefineMatcher) \
- AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, 0)
+#define AST_POLYMORPHIC_MATCHER(DefineMatcher, ReturnTypesF) \
+ AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, ReturnTypesF, 0)
-#define AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, OverloadId) \
+#define AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, ReturnTypesF, \
+ OverloadId) \
namespace internal { \
template <typename NodeType> \
class matcher_##DefineMatcher##OverloadId##Matcher \
@@ -175,9 +193,11 @@
}; \
} \
inline internal::PolymorphicMatcherWithParam0< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher> DefineMatcher() {\
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF> \
+ DefineMatcher() { \
return internal::PolymorphicMatcherWithParam0< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher>(); \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, \
+ ReturnTypesF>(); \
} \
template <typename NodeType> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
@@ -193,11 +213,13 @@
/// of the matcher Matcher<NodeType> returned by the function matcher().
///
/// FIXME: Pull out common code with above macro?
-#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) \
- AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, 0)
+#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ReturnTypesF, ParamType, \
+ Param) \
+ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType, \
+ Param, 0)
-#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, \
- OverloadId) \
+#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, \
+ ParamType, Param, OverloadId) \
namespace internal { \
template <typename NodeType, typename ParamT> \
class matcher_##DefineMatcher##OverloadId##Matcher \
@@ -214,11 +236,11 @@
}; \
} \
inline internal::PolymorphicMatcherWithParam1< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType> \
- DefineMatcher(const ParamType &Param) { \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF> DefineMatcher(const ParamType & Param) { \
return internal::PolymorphicMatcherWithParam1< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType>( \
- Param); \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF>(Param); \
} \
template <typename NodeType, typename ParamT> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
@@ -233,13 +255,14 @@
/// The variables are the same as for AST_MATCHER_P2, with the
/// addition of NodeType, which specifies the node type of the matcher
/// Matcher<NodeType> returned by the function DefineMatcher().
-#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ParamType1, Param1, \
- ParamType2, Param2) \
- AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \
- ParamType2, Param2, 0)
+#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ReturnTypesF, ParamType1, \
+ Param1, ParamType2, Param2) \
+ AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType1, \
+ Param1, ParamType2, Param2, 0)
-#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \
- ParamType2, Param2, OverloadId) \
+#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, \
+ ParamType1, Param1, ParamType2, \
+ Param2, OverloadId) \
namespace internal { \
template <typename NodeType, typename ParamT1, typename ParamT2> \
class matcher_##DefineMatcher##OverloadId##Matcher \
@@ -258,11 +281,11 @@
} \
inline internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
- ParamType2> \
- DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \
+ ParamType2, ReturnTypesF> DefineMatcher(const ParamType1 & Param1, \
+ const ParamType2 & Param2) { \
return internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
- ParamType2>(Param1, Param2); \
+ ParamType2, ReturnTypesF>(Param1, Param2); \
} \
template <typename NodeType, typename ParamT1, typename ParamT2> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
diff --git a/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h
index 21e08ff2da8..973d54cead3 100644
--- a/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h
+++ b/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h
@@ -70,7 +70,8 @@ class Diagnostics {
ET_ParserInvalidToken = 108,
ET_ParserMalformedBindExpr = 109,
ET_ParserTrailingCode = 110,
- ET_ParserUnsignedError = 111
+ ET_ParserUnsignedError = 111,
+ ET_ParserOverloadedType = 112
};
/// \brief Helper stream class.
diff --git a/clang/include/clang/ASTMatchers/Dynamic/Parser.h b/clang/include/clang/ASTMatchers/Dynamic/Parser.h
index 51dbc8a5a43..b3fd7d607fb 100644
--- a/clang/include/clang/ASTMatchers/Dynamic/Parser.h
+++ b/clang/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -74,13 +74,14 @@ public:
///
/// \param Args The argument list for the matcher.
///
- /// \return The matcher object constructed by the processor, or NULL
- /// if an error occurred. In that case, \c Error will contain a
+ /// \return The matcher objects constructed by the processor, or an empty
+ /// list if an error occurred. In that case, \c Error will contain a
/// description of the error.
- /// The caller takes ownership of the DynTypedMatcher object returned.
- virtual DynTypedMatcher *actOnMatcherExpression(
- StringRef MatcherName, const SourceRange &NameRange, StringRef BindID,
- ArrayRef<ParserValue> Args, Diagnostics *Error) = 0;
+ virtual MatcherList actOnMatcherExpression(StringRef MatcherName,
+ const SourceRange &NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) = 0;
};
/// \brief Parse a matcher expression, creating matchers from the registry.
diff --git a/clang/include/clang/ASTMatchers/Dynamic/Registry.h b/clang/include/clang/ASTMatchers/Dynamic/Registry.h
index dede8df776f..a75f29641ab 100644
--- a/clang/include/clang/ASTMatchers/Dynamic/Registry.h
+++ b/clang/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -43,26 +43,26 @@ public:
/// values must be valid for the matcher requested. Otherwise, the function
/// will return an error.
///
- /// \return The matcher if no error was found. NULL if the matcher is not
- // found, or if the number of arguments or argument types do not
- /// match the signature. In that case \c Error will contain the description
- /// of the error.
- static DynTypedMatcher *constructMatcher(StringRef MatcherName,
- const SourceRange &NameRange,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error);
+ /// \return The matcher objects constructed if no error was found.
+ /// An empty list if the matcher is not found, or if the number of
+ /// arguments or argument types do not match the signature.
+ /// In that case \c Error will contain the description of the error.
+ static MatcherList constructMatcher(StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
/// \brief Construct a matcher from the registry and bind it.
///
/// Similar the \c constructMatcher() above, but it then tries to bind the
/// matcher to the specified \c BindID.
/// If the matcher is not bindable, it sets an error in \c Error and returns
- /// \c NULL.
- static DynTypedMatcher *constructBoundMatcher(StringRef MatcherName,
- const SourceRange &NameRange,
- StringRef BindID,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error);
+ /// an empty list.
+ static MatcherList constructBoundMatcher(StringRef MatcherName,
+ const SourceRange &NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
private:
Registry() LLVM_DELETED_FUNCTION;
diff --git a/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h b/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h
index c2e60e1ce9e..44f497248ae 100644
--- a/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h
+++ b/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -17,6 +17,8 @@
#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
+#include <vector>
+
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "llvm/ADT/Twine.h"
@@ -28,6 +30,73 @@ namespace dynamic {
using ast_matchers::internal::DynTypedMatcher;
+/// \brief A list of \c DynTypedMatcher objects.
+///
+/// The purpose of this list is to wrap multiple different matchers and
+/// provide the right one when calling \c hasTypedMatcher/getTypedMatcher.
+class MatcherList {
+public:
+ /// \brief An empty list.
+ MatcherList();
+ /// \brief Clones the matcher objects.
+ MatcherList(const MatcherList &Other);
+ /// \brief Clones the provided matcher.
+ MatcherList(const DynTypedMatcher &Matcher);
+ ~MatcherList();
+
+ MatcherList &operator=(const MatcherList &Other);
+
+ /// \brief Add a matcher to this list. The matcher is cloned.
+ void add(const DynTypedMatcher &Matcher);
+
+ /// \brief Empties the list.
+ void reset();
+
+ /// \brief Whether the list is empty.
+ bool empty() const { return List.empty(); }
+
+ ArrayRef<const DynTypedMatcher *> matchers() const { return List; }
+
+ /// \brief Determines if any of the contained matchers can be converted
+ /// to \c Matcher<T>.
+ ///
+ /// Returns true if one, and only one, of the contained matchers can be
+ /// converted to \c Matcher<T>. If there are more than one that can, the
+ /// result would be ambigous and false is returned.
+ template <class T>
+ bool hasTypedMatcher() const {
+ size_t Matches = 0;
+ for (size_t I = 0, E = List.size(); I != E; ++I) {
+ Matches += ast_matchers::internal::Matcher<T>::canConstructFrom(*List[I]);
+ }
+ return Matches == 1;
+ }
+
+ /// \brief Wrap the correct matcher as a \c Matcher<T>.
+ ///
+ /// Selects the appropriate matcher from the list and returns it as a
+ /// \c Matcher<T>.
+ /// Asserts that \c hasTypedMatcher<T>() is true.
+ template <class T>
+ ast_matchers::internal::Matcher<T> getTypedMatcher() const {
+ assert(hasTypedMatcher<T>());
+ for (size_t I = 0, E = List.size(); I != E; ++I) {
+ if (ast_matchers::internal::Matcher<T>::canConstructFrom(*List[I]))
+ return ast_matchers::internal::Matcher<T>::constructFrom(*List[I]);
+ }
+ llvm_unreachable("!hasTypedMatcher<T>()");
+ }
+
+ /// \brief String representation of the type of the value.
+ ///
+ /// If there are more than one matcher on the list, the string will show all
+ /// the types.
+ std::string getTypeAsString() const;
+
+private:
+ std::vector<const DynTypedMatcher *> List;
+};
+
/// \brief Variant value class.
///
/// Basically, a tagged union with value type semantics.
@@ -39,7 +108,7 @@ using ast_matchers::internal::DynTypedMatcher;
/// Supported types:
/// - \c unsigned
/// - \c std::string
-/// - \c DynTypedMatcher, and any \c Matcher<T>
+/// - \c MatcherList (\c DynTypedMatcher / \c Matcher<T>)
class VariantValue {
public:
VariantValue() : Type(VT_Nothing) {}
@@ -52,6 +121,7 @@ public:
VariantValue(unsigned Unsigned);
VariantValue(const std::string &String);
VariantValue(const DynTypedMatcher &Matcher);
+ VariantValue(const MatcherList &Matchers);
/// \brief Unsigned value functions.
bool isUnsigned() const;
@@ -64,22 +134,19 @@ public:
void setString(const std::string &String);
/// \brief Matcher value functions.
- bool isMatcher() const;
- const DynTypedMatcher &getMatcher() const;
- void setMatcher(const DynTypedMatcher &Matcher);
- /// \brief Set the value to be \c Matcher by taking ownership of the object.
- void takeMatcher(DynTypedMatcher *Matcher);
+ bool isMatchers() const;
+ const MatcherList &getMatchers() const;
+ void setMatchers(const MatcherList &Matchers);
- /// \brief Specialized Matcher<T> functions.
+ /// \brief Shortcut functions.
template <class T>
bool hasTypedMatcher() const {
- return isMatcher() &&
- ast_matchers::internal::Matcher<T>::canConstructFrom(getMatcher());
+ return isMatchers() && getMatchers().hasTypedMatcher<T>();
}
template <class T>
ast_matchers::internal::Matcher<T> getTypedMatcher() const {
- return ast_matchers::internal::Matcher<T>::constructFrom(getMatcher());
+ return getMatchers().getTypedMatcher<T>();
}
/// \brief String representation of the type of the value.
@@ -93,14 +160,14 @@ private:
VT_Nothing,
VT_Unsigned,
VT_String,
- VT_Matcher
+ VT_Matchers
};
/// \brief All supported value types.
union AllValues {
unsigned Unsigned;
std::string *String;
- DynTypedMatcher *Matcher;
+ MatcherList *Matchers;
};
ValueType Type;
OpenPOWER on IntegriCloud