r186340 - Add support for type traversal matchers.
Samuel Benzaquen
sbenza at google.com
Mon Jul 15 12:25:07 PDT 2013
Author: sbenza
Date: Mon Jul 15 14:25:06 2013
New Revision: 186340
URL: http://llvm.org/viewvc/llvm-project?rev=186340&view=rev
Log:
Add support for type traversal matchers.
Summary:
Fixup the type traversal macros/matchers to specify the supported types.
Make the marshallers a little more generic to support any variadic function.
Update the doc script.
Reviewers: klimek
CC: cfe-commits, revane
Differential Revision: http://llvm-reviews.chandlerc.com/D1023
Modified:
cfe/trunk/docs/LibASTMatchersReference.html
cfe/trunk/docs/tools/dump_ast_matchers.py
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h
cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h
cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp
cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
Modified: cfe/trunk/docs/LibASTMatchersReference.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=186340&r1=186339&r2=186340&view=diff
==============================================================================
--- cfe/trunk/docs/LibASTMatchersReference.html (original)
+++ cfe/trunk/docs/LibASTMatchersReference.html Mon Jul 15 14:25:06 2013
@@ -2367,8 +2367,8 @@ arraySubscriptExpression(hasIndex(intege
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayTypeLoc.html">ArrayTypeLoc</a>></td><td class="name" onclick="toggle('hasElementTypeLoc1')"><a name="hasElementTypeLoc1Anchor">hasElementTypeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
-<tr><td colspan="4" class="doc" id="hasElementTypeLoc1"><pre>Matches arrays and C99 complex types that have a specific element
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayTypeLoc.html">ArrayTypeLoc</a>></td><td class="name" onclick="toggle('hasElementTypeLoc0')"><a name="hasElementTypeLoc0Anchor">hasElementTypeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
+<tr><td colspan="4" class="doc" id="hasElementTypeLoc0"><pre>Matches arrays and C99 complex types that have a specific element
type.
Given
@@ -2382,8 +2382,8 @@ Usable as: Matcher<<a href="http://cla
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>></td><td class="name" onclick="toggle('hasElementType1')"><a name="hasElementType1Anchor">hasElementType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
-<tr><td colspan="4" class="doc" id="hasElementType1"><pre>Matches arrays and C99 complex types that have a specific element
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>></td><td class="name" onclick="toggle('hasElementType0')"><a name="hasElementType0Anchor">hasElementType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
+<tr><td colspan="4" class="doc" id="hasElementType0"><pre>Matches arrays and C99 complex types that have a specific element
type.
Given
@@ -2461,8 +2461,8 @@ Example matches b (matcher = binaryOpera
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerTypeLoc.html">BlockPointerTypeLoc</a>></td><td class="name" onclick="toggle('pointeeLoc3')"><a name="pointeeLoc3Anchor">pointeeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
-<tr><td colspan="4" class="doc" id="pointeeLoc3"><pre>Narrows PointerType (and similar) matchers to those where the
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerTypeLoc.html">BlockPointerTypeLoc</a>></td><td class="name" onclick="toggle('pointeeLoc0')"><a name="pointeeLoc0Anchor">pointeeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
+<tr><td colspan="4" class="doc" id="pointeeLoc0"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
Given
@@ -2477,8 +2477,8 @@ Usable as: Matcher<<a href="http://cla
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>></td><td class="name" onclick="toggle('pointee3')"><a name="pointee3Anchor">pointee</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
-<tr><td colspan="4" class="doc" id="pointee3"><pre>Narrows PointerType (and similar) matchers to those where the
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>></td><td class="name" onclick="toggle('pointee0')"><a name="pointee0Anchor">pointee</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
+<tr><td colspan="4" class="doc" id="pointee0"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
Given
@@ -2771,8 +2771,8 @@ classTemplateSpecializationDecl(hasTempl
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ComplexTypeLoc.html">ComplexTypeLoc</a>></td><td class="name" onclick="toggle('hasElementTypeLoc0')"><a name="hasElementTypeLoc0Anchor">hasElementTypeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
-<tr><td colspan="4" class="doc" id="hasElementTypeLoc0"><pre>Matches arrays and C99 complex types that have a specific element
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ComplexTypeLoc.html">ComplexTypeLoc</a>></td><td class="name" onclick="toggle('hasElementTypeLoc1')"><a name="hasElementTypeLoc1Anchor">hasElementTypeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
+<tr><td colspan="4" class="doc" id="hasElementTypeLoc1"><pre>Matches arrays and C99 complex types that have a specific element
type.
Given
@@ -2786,8 +2786,8 @@ Usable as: Matcher<<a href="http://cla
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>></td><td class="name" onclick="toggle('hasElementType0')"><a name="hasElementType0Anchor">hasElementType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
-<tr><td colspan="4" class="doc" id="hasElementType0"><pre>Matches arrays and C99 complex types that have a specific element
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>></td><td class="name" onclick="toggle('hasElementType1')"><a name="hasElementType1Anchor">hasElementType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
+<tr><td colspan="4" class="doc" id="hasElementType1"><pre>Matches arrays and C99 complex types that have a specific element
type.
Given
@@ -3227,8 +3227,8 @@ memberExpr(member(hasName("first")))
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerTypeLoc.html">MemberPointerTypeLoc</a>></td><td class="name" onclick="toggle('pointeeLoc2')"><a name="pointeeLoc2Anchor">pointeeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
-<tr><td colspan="4" class="doc" id="pointeeLoc2"><pre>Narrows PointerType (and similar) matchers to those where the
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerTypeLoc.html">MemberPointerTypeLoc</a>></td><td class="name" onclick="toggle('pointeeLoc1')"><a name="pointeeLoc1Anchor">pointeeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
+<tr><td colspan="4" class="doc" id="pointeeLoc1"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
Given
@@ -3243,8 +3243,8 @@ Usable as: Matcher<<a href="http://cla
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>></td><td class="name" onclick="toggle('pointee2')"><a name="pointee2Anchor">pointee</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
-<tr><td colspan="4" class="doc" id="pointee2"><pre>Narrows PointerType (and similar) matchers to those where the
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>></td><td class="name" onclick="toggle('pointee1')"><a name="pointee1Anchor">pointee</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
+<tr><td colspan="4" class="doc" id="pointee1"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
Given
@@ -3338,8 +3338,8 @@ Usable as: Matcher<<a href="http://cla
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerTypeLoc.html">PointerTypeLoc</a>></td><td class="name" onclick="toggle('pointeeLoc1')"><a name="pointeeLoc1Anchor">pointeeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
-<tr><td colspan="4" class="doc" id="pointeeLoc1"><pre>Narrows PointerType (and similar) matchers to those where the
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerTypeLoc.html">PointerTypeLoc</a>></td><td class="name" onclick="toggle('pointeeLoc2')"><a name="pointeeLoc2Anchor">pointeeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
+<tr><td colspan="4" class="doc" id="pointeeLoc2"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
Given
@@ -3354,8 +3354,8 @@ Usable as: Matcher<<a href="http://cla
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>></td><td class="name" onclick="toggle('pointee1')"><a name="pointee1Anchor">pointee</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
-<tr><td colspan="4" class="doc" id="pointee1"><pre>Narrows PointerType (and similar) matchers to those where the
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>></td><td class="name" onclick="toggle('pointee2')"><a name="pointee2Anchor">pointee</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
+<tr><td colspan="4" class="doc" id="pointee2"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
Given
@@ -3414,8 +3414,8 @@ Usable as: Matcher<<a href="http://cla
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceTypeLoc.html">ReferenceTypeLoc</a>></td><td class="name" onclick="toggle('pointeeLoc0')"><a name="pointeeLoc0Anchor">pointeeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
-<tr><td colspan="4" class="doc" id="pointeeLoc0"><pre>Narrows PointerType (and similar) matchers to those where the
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceTypeLoc.html">ReferenceTypeLoc</a>></td><td class="name" onclick="toggle('pointeeLoc3')"><a name="pointeeLoc3Anchor">pointeeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr>
+<tr><td colspan="4" class="doc" id="pointeeLoc3"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
Given
@@ -3430,8 +3430,8 @@ Usable as: Matcher<<a href="http://cla
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>></td><td class="name" onclick="toggle('pointee0')"><a name="pointee0Anchor">pointee</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
-<tr><td colspan="4" class="doc" id="pointee0"><pre>Narrows PointerType (and similar) matchers to those where the
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>></td><td class="name" onclick="toggle('pointee3')"><a name="pointee3Anchor">pointee</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
+<tr><td colspan="4" class="doc" id="pointee3"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
Given
Modified: cfe/trunk/docs/tools/dump_ast_matchers.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/tools/dump_ast_matchers.py?rev=186340&r1=186339&r2=186340&view=diff
==============================================================================
--- cfe/trunk/docs/tools/dump_ast_matchers.py (original)
+++ cfe/trunk/docs/tools/dump_ast_matchers.py Mon Jul 15 14:25:06 2013
@@ -160,14 +160,17 @@ def act_on_decl(declaration, comment, al
m = re.match(""".*AST_TYPE(LOC)?_TRAVERSE_MATCHER\(
\s*([^\s,]+\s*),
- \s*(?:[^\s,]+\s*)
+ \s*(?:[^\s,]+\s*),
+ \s*AST_POLYMORPHIC_SUPPORTED_TYPES_([^(]*)\(([^)]*)\)
\)\s*;\s*$""", declaration, flags=re.X)
if m:
- loc = m.group(1)
- name = m.group(2)
- result_types = extract_result_types(comment)
- if not result_types:
- raise Exception('Did not find allowed result types for: %s' % name)
+ loc, name, n_results, results = m.groups()[0:4]
+ result_types = [r.strip() for r in results.split(',')]
+
+ comment_result_types = extract_result_types(comment)
+ if (comment_result_types and
+ sorted(result_types) != sorted(comment_result_types)):
+ raise Exception('Inconsistent documentation for: %s' % name)
for result_type in result_types:
add_matcher(result_type, name, 'Matcher<Type>', comment)
if loc:
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=186340&r1=186339&r2=186340&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Mon Jul 15 14:25:06 2013
@@ -2905,7 +2905,9 @@ AST_TYPE_MATCHER(ComplexType, complexTyp
/// matches "int b[7]"
///
/// Usable as: Matcher<ArrayType>, Matcher<ComplexType>
-AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement);
+AST_TYPELOC_TRAVERSE_MATCHER(
+ hasElementType, getElement,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(ArrayType, ComplexType));
/// \brief Matches C arrays with a specified constant size.
///
@@ -3012,7 +3014,8 @@ AST_TYPE_MATCHER(AtomicType, atomicType)
/// matches "_Atomic(int) i"
///
/// Usable as: Matcher<AtomicType>
-AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue);
+AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_1(AtomicType));
/// \brief Matches types nodes representing C++11 auto types.
///
@@ -3040,7 +3043,8 @@ AST_TYPE_MATCHER(AutoType, autoType);
/// matches "auto a"
///
/// Usable as: Matcher<AutoType>
-AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType);
+AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_1(AutoType));
/// \brief Matches \c FunctionType nodes.
///
@@ -3077,7 +3081,8 @@ AST_TYPE_MATCHER(ParenType, parenType);
/// \c ptr_to_func but not \c ptr_to_array.
///
/// Usable as: Matcher<ParenType>
-AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType);
+AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_1(ParenType));
/// \brief Matches block pointer types, i.e. types syntactically represented as
/// "void (^)(int)".
@@ -3171,7 +3176,10 @@ AST_TYPE_MATCHER(RValueReferenceType, rV
///
/// Usable as: Matcher<BlockPointerType>, Matcher<MemberPointerType>,
/// Matcher<PointerType>, Matcher<ReferenceType>
-AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee);
+AST_TYPELOC_TRAVERSE_MATCHER(
+ pointee, getPointee,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_4(BlockPointerType, MemberPointerType,
+ PointerType, ReferenceType));
/// \brief Matches typedef types.
///
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=186340&r1=186339&r2=186340&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Mon Jul 15 14:25:06 2013
@@ -1434,9 +1434,53 @@ private:
TypeLoc (T::*TraverseFunction)() const;
};
-template <typename T, typename InnerT>
-T makeTypeAllOfComposite(ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
- return T(makeAllOfComposite<InnerT>(InnerMatchers));
+/// \brief Converts a \c Matcher<InnerT> to a \c Matcher<OuterT>, where
+/// \c OuterT is any type that is supported by \c Getter.
+///
+/// \code Getter<OuterT>::value() \endcode returns a
+/// \code InnerTBase (OuterT::*)() \endcode, which is used to adapt a \c OuterT
+/// object into a \c InnerT
+template <typename InnerTBase,
+ template <typename OuterT> class Getter,
+ template <typename OuterT> class MatcherImpl,
+ typename ReturnTypesF>
+class TypeTraversePolymorphicMatcher {
+private:
+ typedef TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
+ ReturnTypesF> Self;
+ static Self create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers);
+
+public:
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
+ explicit TypeTraversePolymorphicMatcher(
+ ArrayRef<const Matcher<InnerTBase> *> InnerMatchers)
+ : InnerMatcher(makeAllOfComposite(InnerMatchers)) {}
+
+ template <typename OuterT> operator Matcher<OuterT>() const {
+ return Matcher<OuterT>(
+ new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value()));
+ }
+
+ struct Func : public llvm::VariadicFunction<Self, Matcher<InnerTBase>,
+ &Self::create> {
+ Func() {}
+ };
+
+private:
+ const Matcher<InnerTBase> InnerMatcher;
+};
+
+// Define the create() method out of line to silence a GCC warning about
+// the struct "Func" having greater visibility than its base, which comes from
+// using the flag -fvisibility-inlines-hidden.
+template <typename InnerTBase, template <typename OuterT> class Getter,
+ template <typename OuterT> class MatcherImpl, typename ReturnTypesF>
+TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF>
+TypeTraversePolymorphicMatcher<
+ InnerTBase, Getter, MatcherImpl,
+ ReturnTypesF>::create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers) {
+ return Self(InnerMatchers);
}
} // end namespace internal
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h?rev=186340&r1=186339&r2=186340&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h Mon Jul 15 14:25:06 2013
@@ -163,6 +163,7 @@
/// \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_1(t1) void(internal::TypeList<t1>)
#define AST_POLYMORPHIC_SUPPORTED_TYPES_2(t1, t2) \
void(internal::TypeList<t1, t2>)
#define AST_POLYMORPHIC_SUPPORTED_TYPES_3(t1, t2, t3) \
@@ -307,62 +308,27 @@
/// For a specific \c SpecificType, the traversal is done using
/// \c SpecificType::FunctionName. The existance of such a function determines
/// whether a corresponding matcher can be used on \c SpecificType.
-#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) \
- class Polymorphic##MatcherName##TypeMatcher { \
- public: \
- Polymorphic##MatcherName##TypeMatcher( \
- const internal::Matcher<QualType> &InnerMatcher) \
- : InnerMatcher(InnerMatcher) { \
- } \
- template <typename T> operator internal:: Matcher< T>() { \
- return internal::Matcher<T>(new internal::TypeTraverseMatcher<T>( \
- InnerMatcher, &T::FunctionName)); \
- } \
- private: \
- const internal::Matcher<QualType> InnerMatcher; \
- } \
- ; \
- class Variadic##MatcherName##TypeTraverseMatcher \
- : public llvm::VariadicFunction< \
- Polymorphic##MatcherName##TypeMatcher, internal::Matcher<QualType>, \
- internal::makeTypeAllOfComposite< \
- Polymorphic##MatcherName##TypeMatcher, QualType> > { \
- public: \
- Variadic##MatcherName##TypeTraverseMatcher() { \
- } \
+#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
+ namespace internal { \
+ template <typename T> struct TypeMatcher##MatcherName##Getter { \
+ static QualType (T::*value())() const { return &T::FunctionName; } \
+ }; \
} \
- ; \
- const Variadic##MatcherName##TypeTraverseMatcher MatcherName
+ const internal::TypeTraversePolymorphicMatcher< \
+ QualType, internal::TypeMatcher##MatcherName##Getter, \
+ internal::TypeTraverseMatcher, ReturnTypesF>::Func MatcherName
/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works
/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs.
-#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) \
- class Polymorphic##MatcherName##TypeLocMatcher { \
- public: \
- Polymorphic##MatcherName##TypeLocMatcher( \
- const internal::Matcher<TypeLoc> &InnerMatcher) \
- : InnerMatcher(InnerMatcher) { \
- } \
- template <typename T> operator internal:: Matcher< T>() { \
- return internal::Matcher<T>( \
- new internal::TypeLocTraverseMatcher<T>(InnerMatcher, \
- &T::FunctionName##Loc)); \
- } \
- private: \
- const internal::Matcher<TypeLoc> InnerMatcher; \
- } \
- ; \
- class Variadic##MatcherName##TypeLocTraverseMatcher \
- : public llvm::VariadicFunction< \
- Polymorphic##MatcherName##TypeLocMatcher, internal::Matcher<TypeLoc>,\
- internal::makeTypeAllOfComposite< \
- Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \
- public: \
- Variadic##MatcherName##TypeLocTraverseMatcher() { \
- } \
+#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
+ namespace internal { \
+ template <typename T> struct TypeLocMatcher##MatcherName##Getter { \
+ static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \
+ }; \
} \
- ; \
- const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \
- AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type)
+ const internal::TypeTraversePolymorphicMatcher< \
+ TypeLoc, internal::TypeLocMatcher##MatcherName##Getter, \
+ internal::TypeLocTraverseMatcher, ReturnTypesF>::Func MatcherName##Loc; \
+ AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h?rev=186340&r1=186339&r2=186340&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h Mon Jul 15 14:25:06 2013
@@ -240,32 +240,32 @@ static MatcherList matcherMarshall2(Retu
#undef CHECK_ARG_TYPE
/// \brief Variadic marshaller function.
-template <typename BaseType, typename DerivedType>
-MatcherList VariadicMatcherCreateCallback(StringRef MatcherName,
+template <typename ResultT, typename ArgT,
+ ResultT (*Func)(ArrayRef<const ArgT *>)>
+MatcherList variadicMatcherCreateCallback(StringRef MatcherName,
const SourceRange &NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
- typedef ast_matchers::internal::Matcher<DerivedType> DerivedMatcherType;
- DerivedMatcherType **InnerArgs = new DerivedMatcherType *[Args.size()]();
+ ArgT **InnerArgs = new ArgT *[Args.size()]();
bool HasError = false;
for (size_t i = 0, e = Args.size(); i != e; ++i) {
- typedef ArgTypeTraits<DerivedMatcherType> DerivedTraits;
+ typedef ArgTypeTraits<ArgT> ArgTraits;
const ParserValue &Arg = Args[i];
const VariantValue &Value = Arg.Value;
- if (!DerivedTraits::is(Value)) {
+ if (!ArgTraits::is(Value)) {
Error->pushErrorFrame(Arg.Range, Error->ET_RegistryWrongArgType)
- << (i + 1) << DerivedTraits::asString() << Value.getTypeAsString();
+ << (i + 1) << ArgTraits::asString() << Value.getTypeAsString();
HasError = true;
break;
}
- InnerArgs[i] = new DerivedMatcherType(DerivedTraits::get(Value));
+ InnerArgs[i] = new ArgT(ArgTraits::get(Value));
}
MatcherList Out;
if (!HasError) {
- Out = ast_matchers::internal::makeDynCastAllOfComposite<BaseType>(
- ArrayRef<const DerivedMatcherType *>(InnerArgs, Args.size()));
+ Out = outvalueToMatcherList(
+ Func(ArrayRef<const ArgT *>(InnerArgs, Args.size())));
}
for (size_t i = 0, e = Args.size(); i != e; ++i) {
@@ -303,22 +303,14 @@ MatcherCreateCallback *makeMatcherAutoMa
ReturnType (*)(ArgType1, ArgType2)>(matcherMarshall2, Func, MatcherName);
}
-/// \brief Variadic overloads.
-template <typename MatcherType>
-MatcherCreateCallback *makeMatcherAutoMarshall(
- ast_matchers::internal::VariadicAllOfMatcher<MatcherType> Func,
- StringRef MatcherName) {
- return new FreeFuncMatcherCreateCallback(
- &VariadicMatcherCreateCallback<MatcherType, MatcherType>, MatcherName);
-}
-
-template <typename BaseType, typename MatcherType>
+/// \brief Variadic overload.
+template <typename ResultT, typename ArgT,
+ ResultT (*Func)(ArrayRef<const ArgT *>)>
MatcherCreateCallback *
-makeMatcherAutoMarshall(ast_matchers::internal::VariadicDynCastAllOfMatcher<
- BaseType, MatcherType> Func,
+makeMatcherAutoMarshall(llvm::VariadicFunction<ResultT, ArgT, Func> VarFunc,
StringRef MatcherName) {
return new FreeFuncMatcherCreateCallback(
- &VariadicMatcherCreateCallback<BaseType, MatcherType>, MatcherName);
+ &variadicMatcherCreateCallback<ResultT, ArgT, Func>, MatcherName);
}
} // namespace internal
Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=186340&r1=186339&r2=186340&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Mon Jul 15 14:25:06 2013
@@ -69,13 +69,6 @@ RegistryMaps::RegistryMaps() {
// withInitializer
// isWritten
//
- // Type traversal:
- // hasElementType
- // hasValueType
- // hasDeducedType
- // innerType
- // pointee
- //
// Function overloaded by args:
// hasType
// callee
@@ -175,8 +168,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasCondition);
REGISTER_MATCHER(hasConditionVariableStatement);
REGISTER_MATCHER(hasDeclContext);
+ REGISTER_MATCHER(hasDeducedType);
REGISTER_MATCHER(hasDestinationType);
REGISTER_MATCHER(hasEitherOperand);
+ REGISTER_MATCHER(hasElementType);
REGISTER_MATCHER(hasFalseExpression);
REGISTER_MATCHER(hasImplicitDestinationType);
REGISTER_MATCHER(hasIncrement);
@@ -200,6 +195,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasTargetDecl);
REGISTER_MATCHER(hasTrueExpression);
REGISTER_MATCHER(hasUnaryOperand);
+ REGISTER_MATCHER(hasValueType);
REGISTER_MATCHER(ifStmt);
REGISTER_MATCHER(ignoringImpCasts);
REGISTER_MATCHER(ignoringParenCasts);
@@ -207,6 +203,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(implicitCastExpr);
REGISTER_MATCHER(incompleteArrayType);
REGISTER_MATCHER(initListExpr);
+ REGISTER_MATCHER(innerType);
REGISTER_MATCHER(integerLiteral);
REGISTER_MATCHER(isArrow);
REGISTER_MATCHER(isConstQualified);
@@ -245,6 +242,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(operatorCallExpr);
REGISTER_MATCHER(parameterCountIs);
REGISTER_MATCHER(parenType);
+ REGISTER_MATCHER(pointee);
REGISTER_MATCHER(pointerType);
REGISTER_MATCHER(qualType);
REGISTER_MATCHER(rValueReferenceType);
Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp?rev=186340&r1=186339&r2=186340&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp Mon Jul 15 14:25:06 2013
@@ -179,10 +179,12 @@ TEST(ParserTest, ParseMatcher) {
using ast_matchers::internal::Matcher;
TEST(ParserTest, FullParserTest) {
+ Diagnostics Error;
OwningPtr<DynTypedMatcher> VarDecl(Parser::parseMatcherExpression(
"varDecl(hasInitializer(binaryOperator(hasLHS(integerLiteral()),"
" hasOperatorName(\"+\"))))",
- NULL));
+ &Error));
+ EXPECT_EQ("", Error.ToStringFull());
Matcher<Decl> M = Matcher<Decl>::constructFrom(*VarDecl);
EXPECT_TRUE(matches("int x = 1 + false;", M));
EXPECT_FALSE(matches("int x = true + 1;", M));
@@ -190,13 +192,13 @@ TEST(ParserTest, FullParserTest) {
EXPECT_FALSE(matches("int x = true - 1;", M));
OwningPtr<DynTypedMatcher> HasParameter(Parser::parseMatcherExpression(
- "functionDecl(hasParameter(1, hasName(\"x\")))", NULL));
+ "functionDecl(hasParameter(1, hasName(\"x\")))", &Error));
+ EXPECT_EQ("", Error.ToStringFull());
M = Matcher<Decl>::constructFrom(*HasParameter);
EXPECT_TRUE(matches("void f(int a, int x);", M));
EXPECT_FALSE(matches("void f(int x, int a);", M));
- Diagnostics Error;
EXPECT_TRUE(Parser::parseMatcherExpression(
"hasInitializer(\n binaryOperator(hasLHS(\"A\")))", &Error) == NULL);
EXPECT_EQ("1:1: Error parsing argument 1 for matcher hasInitializer.\n"
Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp?rev=186340&r1=186339&r2=186340&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp Mon Jul 15 14:25:06 2013
@@ -36,32 +36,43 @@ public:
return Out;
}
- template <class T>
- Matcher<T> constructMatcher(StringRef MatcherName, Diagnostics *Error) {
- return Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error)
- .getTypedMatcher<T>();
+ MatcherList constructMatcher(StringRef MatcherName,
+ Diagnostics *Error = NULL) {
+ Diagnostics DummyError;
+ if (!Error) Error = &DummyError;
+ const MatcherList Out =
+ Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error);
+ EXPECT_EQ("", DummyError.ToStringFull());
+ return Out;
}
- template <class T>
- Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
- Diagnostics *Error) {
- return Registry::constructMatcher(MatcherName, SourceRange(), Args(Arg1),
- Error).getTypedMatcher<T>();
+ MatcherList constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
+ Diagnostics *Error = NULL) {
+ Diagnostics DummyError;
+ if (!Error) Error = &DummyError;
+ const MatcherList Out = Registry::constructMatcher(
+ MatcherName, SourceRange(), Args(Arg1), Error);
+ EXPECT_EQ("", DummyError.ToStringFull());
+ return Out;
}
- template <class T>
- Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
- const VariantValue &Arg2, Diagnostics *Error) {
- return Registry::constructMatcher(MatcherName, SourceRange(),
- Args(Arg1, Arg2), Error)
- .getTypedMatcher<T>();
+ MatcherList constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
+ const VariantValue &Arg2,
+ Diagnostics *Error = NULL) {
+ Diagnostics DummyError;
+ if (!Error) Error = &DummyError;
+ const MatcherList Out = Registry::constructMatcher(
+ MatcherName, SourceRange(), Args(Arg1, Arg2), Error);
+ EXPECT_EQ("", DummyError.ToStringFull());
+ return Out;
}
};
TEST_F(RegistryTest, CanConstructNoArgs) {
- Matcher<Stmt> IsArrowValue = constructMatcher<Stmt>(
- "memberExpr", constructMatcher<MemberExpr>("isArrow", NULL), NULL);
- Matcher<Stmt> BoolValue = constructMatcher<Stmt>("boolLiteral", NULL);
+ Matcher<Stmt> IsArrowValue = constructMatcher(
+ "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
+ Matcher<Stmt> BoolValue =
+ constructMatcher("boolLiteral").getTypedMatcher<Stmt>();
const std::string ClassSnippet = "struct Foo { int x; };\n"
"Foo *foo = new Foo;\n"
@@ -75,25 +86,25 @@ TEST_F(RegistryTest, CanConstructNoArgs)
}
TEST_F(RegistryTest, ConstructWithSimpleArgs) {
- Matcher<Decl> Value = constructMatcher<Decl>(
- "namedDecl",
- constructMatcher<NamedDecl>("hasName", std::string("X"), NULL), NULL);
+ Matcher<Decl> Value = constructMatcher(
+ "namedDecl", constructMatcher("hasName", std::string("X")))
+ .getTypedMatcher<Decl>();
EXPECT_TRUE(matches("class X {};", Value));
EXPECT_FALSE(matches("int x;", Value));
- Value =
- functionDecl(constructMatcher<FunctionDecl>("parameterCountIs", 2, NULL));
+ Value = functionDecl(constructMatcher("parameterCountIs", 2)
+ .getTypedMatcher<FunctionDecl>());
EXPECT_TRUE(matches("void foo(int,int);", Value));
EXPECT_FALSE(matches("void foo(int);", Value));
}
TEST_F(RegistryTest, ConstructWithMatcherArgs) {
- Matcher<Decl> HasInitializerSimple = constructMatcher<Decl>(
- "varDecl", constructMatcher<VarDecl>("hasInitializer", stmt(), NULL),
- NULL);
- Matcher<Decl> HasInitializerComplex = constructMatcher<Decl>(
- "varDecl", constructMatcher<VarDecl>("hasInitializer", callExpr(), NULL),
- NULL);
+ Matcher<Decl> HasInitializerSimple =
+ constructMatcher("varDecl", constructMatcher("hasInitializer", stmt()))
+ .getTypedMatcher<Decl>();
+ Matcher<Decl> HasInitializerComplex = constructMatcher(
+ "varDecl", constructMatcher("hasInitializer", callExpr()))
+ .getTypedMatcher<Decl>();
std::string code = "int i;";
EXPECT_FALSE(matches(code, HasInitializerSimple));
@@ -107,20 +118,20 @@ TEST_F(RegistryTest, ConstructWithMatche
EXPECT_TRUE(matches(code, HasInitializerSimple));
EXPECT_TRUE(matches(code, HasInitializerComplex));
- Matcher<Decl> HasParameter = functionDecl(
- constructMatcher<FunctionDecl>("hasParameter", 1, hasName("x"), NULL));
+ Matcher<Decl> HasParameter = functionDecl(constructMatcher(
+ "hasParameter", 1, hasName("x")).getTypedMatcher<FunctionDecl>());
EXPECT_TRUE(matches("void f(int a, int x);", HasParameter));
EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
}
TEST_F(RegistryTest, PolymorphicMatchers) {
- const MatcherList IsDefinition =
- Registry::constructMatcher("isDefinition", SourceRange(), Args(), NULL);
- Matcher<Decl> Var = constructMatcher<Decl>("varDecl", IsDefinition, NULL);
+ const MatcherList IsDefinition = constructMatcher("isDefinition");
+ Matcher<Decl> Var =
+ constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
Matcher<Decl> Class =
- constructMatcher<Decl>("recordDecl", IsDefinition, NULL);
+ constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();
Matcher<Decl> Func =
- constructMatcher<Decl>("functionDecl", IsDefinition, NULL);
+ constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>();
EXPECT_TRUE(matches("int a;", Var));
EXPECT_FALSE(matches("extern int a;", Var));
EXPECT_TRUE(matches("class A {};", Class));
@@ -128,9 +139,9 @@ TEST_F(RegistryTest, PolymorphicMatchers
EXPECT_TRUE(matches("void f(){};", Func));
EXPECT_FALSE(matches("void f();", Func));
- Matcher<Decl> Anything = constructMatcher<Decl>("anything", NULL);
+ Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
Matcher<Decl> RecordDecl =
- constructMatcher<Decl>("recordDecl", Anything, NULL);
+ constructMatcher("recordDecl", Anything).getTypedMatcher<Decl>();
EXPECT_TRUE(matches("int a;", Anything));
EXPECT_TRUE(matches("class A {};", Anything));
@@ -146,30 +157,42 @@ TEST_F(RegistryTest, PolymorphicMatchers
#endif
}
+TEST_F(RegistryTest, TypeTraversal) {
+ Matcher<Type> M = constructMatcher(
+ "pointerType",
+ constructMatcher("pointee", constructMatcher("isConstQualified"),
+ constructMatcher("isInteger"))).getTypedMatcher<Type>();
+ EXPECT_FALSE(matches("int *a;", M));
+ EXPECT_TRUE(matches("int const *b;", M));
+
+ M = constructMatcher(
+ "arrayType",
+ constructMatcher("hasElementType", constructMatcher("builtinType")))
+ .getTypedMatcher<Type>();
+ EXPECT_FALSE(matches("struct A{}; A a[7];;", M));
+ EXPECT_TRUE(matches("int b[7];", M));
+}
+
TEST_F(RegistryTest, Errors) {
// Incorrect argument count.
OwningPtr<Diagnostics> Error(new Diagnostics());
- EXPECT_TRUE(Registry::constructMatcher("hasInitializer", SourceRange(),
- Args(), Error.get()).empty());
+ EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).empty());
EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
Error->ToString());
Error.reset(new Diagnostics());
- EXPECT_TRUE(Registry::constructMatcher(
- "isArrow", SourceRange(), Args(std::string()), Error.get()).empty());
+ EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).empty());
EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
Error->ToString());
// Bad argument type
Error.reset(new Diagnostics());
- EXPECT_TRUE(Registry::constructMatcher(
- "ofClass", SourceRange(), Args(std::string()), Error.get()).empty());
+ EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).empty());
EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
"(Actual = String)",
Error->ToString());
Error.reset(new Diagnostics());
- EXPECT_TRUE(Registry::constructMatcher(
- "recordDecl", SourceRange(), Args(recordDecl(), parameterCountIs(3)),
- Error.get()).empty());
+ EXPECT_TRUE(constructMatcher("recordDecl", recordDecl(), parameterCountIs(3),
+ Error.get()).empty());
EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
"(Actual = Matcher<FunctionDecl>)",
Error->ToString());
More information about the cfe-commits
mailing list