It seems it broke 32-bit hosts. I saw the failure on cygming, msvc, and i686-linux. Also clang-i386-darwin10-RA@smooshlab would be dubious.
2012/10/17 Daniel Jasper <[email protected]>: > Author: djasper > Date: Wed Oct 17 03:52:59 2012 > New Revision: 166094 > > URL: http://llvm.org/viewvc/llvm-project?rev=166094&view=rev > Log: > First version of matchers for Types and TypeLocs. > > Review: http://llvm-reviews.chandlerc.com/D47 > > Modified: > cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h > cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h > cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h > cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h > cfe/trunk/include/clang/ASTMatchers/ASTTypeTraits.h > cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp > cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp > > Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h?rev=166094&r1=166093&r2=166094&view=diff > ============================================================================== > --- cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h (original) > +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h Wed Oct 17 03:52:59 > 2012 > @@ -116,6 +116,8 @@ > MatchCallback *Action); > void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch, > MatchCallback *Action); > + void addMatcher(const TypeLocMatcher &NodeMatch, > + MatchCallback *Action); > /// @} > > /// \brief Creates a clang ASTConsumer that finds all matches. > > Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=166094&r1=166093&r2=166094&view=diff > ============================================================================== > --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) > +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Wed Oct 17 03:52:59 2012 > @@ -108,8 +108,9 @@ > /// hierarchy. > /// @{ > typedef internal::Matcher<Decl> DeclarationMatcher; > -typedef internal::Matcher<QualType> TypeMatcher; > typedef internal::Matcher<Stmt> StatementMatcher; > +typedef internal::Matcher<QualType> TypeMatcher; > +typedef internal::Matcher<TypeLoc> TypeLocMatcher; > typedef internal::Matcher<NestedNameSpecifier> NestedNameSpecifierMatcher; > typedef internal::Matcher<NestedNameSpecifierLoc> > NestedNameSpecifierLocMatcher; > /// @} > @@ -2438,6 +2439,282 @@ > internal::IsExplicitTemplateSpecializationMatcher>(); > } > > +/// \brief Matches \c QualTypes in the clang AST. > +const internal::VariadicAllOfMatcher<QualType> qualType; > + > +/// \brief Matches \c Types in the clang AST. > +const internal::VariadicDynCastAllOfMatcher<Type, Type> type; > + > +/// \brief Matches \c TypeLocs in the clang AST. > +const internal::VariadicDynCastAllOfMatcher<TypeLoc, TypeLoc> typeLoc; > + > +/// \brief Matches \c TypeLocs for which the given inner > +/// QualType-matcher matches. > +inline internal::BindableMatcher<TypeLoc> loc( > + const internal::Matcher<QualType> &InnerMatcher) { > + return internal::BindableMatcher<TypeLoc>( > + new internal::TypeLocTypeMatcher(InnerMatcher)); > +} > + > +/// \brief Matches builtin Types. > +/// > +/// Given > +/// \code > +/// struct A {}; > +/// A a; > +/// int b; > +/// float c; > +/// bool d; > +/// \endcode > +/// builtinType() > +/// matches "int b", "float c" and "bool d" > +AST_TYPE_MATCHER(BuiltinType, builtinType); > + > +/// \brief Matches all kinds of arrays. > +/// > +/// Given > +/// \code > +/// int a[] = { 2, 3 }; > +/// int b[4]; > +/// void f() { int c[a[0]]; } > +/// \endcode > +/// arrayType() > +/// matches "int a[]", "int b[4]" and "int c[a[0]]"; > +AST_TYPE_MATCHER(ArrayType, arrayType); > + > +/// \brief Matches C99 complex types. > +/// > +/// Given > +/// \code > +/// _Complex float f; > +/// \endcode > +/// complexType() > +/// matches "_Complex float f" > +AST_TYPE_MATCHER(ComplexType, complexType); > + > +/// \brief Matches arrays and C99 complex types that have a specific element > +/// type. > +/// > +/// Given > +/// \code > +/// struct A {}; > +/// A a[7]; > +/// int b[7]; > +/// \endcode > +/// arrayType(hasElementType(builtinType())) > +/// matches "int b[7]" > +/// > +/// Usable as: Matcher<ArrayType>, Matcher<ComplexType> > +AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement); > + > +/// \brief Matches C arrays with a specified constant size. > +/// > +/// Given > +/// \code > +/// void() { > +/// int a[2]; > +/// int b[] = { 2, 3 }; > +/// int c[b[0]]; > +/// } > +/// \endcode > +/// constantArrayType() > +/// matches "int a[2]" > +AST_TYPE_MATCHER(ConstantArrayType, constantArrayType); > + > +/// \brief Matches \c ConstantArrayType nodes that have the specified size. > +/// > +/// Given > +/// \code > +/// int a[42]; > +/// int b[2 * 21]; > +/// int c[41], d[43]; > +/// \endcode > +/// constantArrayType(hasSize(42)) > +/// matches "int a[42]" and "int b[2 * 21]" > +AST_MATCHER_P(ConstantArrayType, hasSize, unsigned, N) { > + return Node.getSize() == N; > +} > + > +/// \brief Matches C++ arrays whose size is a value-dependent expression. > +/// > +/// Given > +/// \code > +/// template<typename T, int Size> > +/// class array { > +/// T data[Size]; > +/// }; > +/// \endcode > +/// dependentSizedArrayType > +/// matches "T data[Size]" > +AST_TYPE_MATCHER(DependentSizedArrayType, dependentSizedArrayType); > + > +/// \brief Matches C arrays with unspecified size. > +/// > +/// Given > +/// \code > +/// int a[] = { 2, 3 }; > +/// int b[42]; > +/// void f(int c[]) { int d[a[0]]; }; > +/// \endcode > +/// incompleteArrayType() > +/// matches "int a[]" and "int c[]" > +AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType); > + > +/// \brief Matches C arrays with a specified size that is not an > +/// integer-constant-expression. > +/// > +/// Given > +/// \code > +/// void f() { > +/// int a[] = { 2, 3 } > +/// int b[42]; > +/// int c[a[0]]; > +/// \endcode > +/// variableArrayType() > +/// matches "int c[a[0]]" > +AST_TYPE_MATCHER(VariableArrayType, variableArrayType); > + > +/// \brief Matches \c VariableArrayType nodes that have a specific size > +/// expression. > +/// > +/// Given > +/// \code > +/// void f(int b) { > +/// int a[b]; > +/// } > +/// \endcode > +/// variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to( > +/// varDecl(hasName("b"))))))) > +/// matches "int a[b]" > +AST_MATCHER_P(VariableArrayType, hasSizeExpr, > + internal::Matcher<Expr>, InnerMatcher) { > + return InnerMatcher.matches(*Node.getSizeExpr(), Finder, Builder); > +} > + > +/// \brief Matches atomic types. > +/// > +/// Given > +/// \code > +/// _Atomic(int) i; > +/// \endcode > +/// atomicType() > +/// matches "_Atomic(int) i" > +AST_TYPE_MATCHER(AtomicType, atomicType); > + > +/// \brief Matches atomic types with a specific value type. > +/// > +/// Given > +/// \code > +/// _Atomic(int) i; > +/// _Atomic(float) f; > +/// \endcode > +/// atomicType(hasValueType(isInteger())) > +/// matches "_Atomic(int) i" > +/// > +/// Usable as: Matcher<AtomicType> > +AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue); > + > +/// \brief Matches types nodes representing C++11 auto types. > +/// > +/// Given: > +/// \code > +/// auto n = 4; > +/// int v[] = { 2, 3 } > +/// for (auto i : v) { } > +/// \endcode > +/// autoType() > +/// matches "auto n" and "auto i" > +AST_TYPE_MATCHER(AutoType, autoType); > + > +/// \brief Matches \c AutoType nodes where the deduced type is a specific > type. > +/// > +/// Note: There is no \c TypeLoc for the deduced type and thus no > +/// \c getDeducedLoc() matcher. > +/// > +/// Given > +/// \code > +/// auto a = 1; > +/// auto b = 2.0; > +/// \endcode > +/// autoType(hasDeducedType(isInteger())) > +/// matches "auto a" > +/// > +/// Usable as: Matcher<AutoType> > +AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType); > + > +/// \brief Matches block pointer types, i.e. types syntactically represented > as > +/// "void (^)(int)". > +/// > +/// The \c pointee is always required to be a \c FunctionType. > +AST_TYPE_MATCHER(BlockPointerType, blockPointerType); > + > +/// \brief Matches member pointer types. > +/// Given > +/// \code > +/// struct A { int i; } > +/// A::* ptr = A::i; > +/// \endcode > +/// memberPointerType() > +/// matches "A::* ptr" > +AST_TYPE_MATCHER(MemberPointerType, memberPointerType); > + > +/// \brief Matches pointer types. > +/// > +/// Given > +/// \code > +/// int *a; > +/// int &b = *a; > +/// int c = 5; > +/// \endcode > +/// pointerType() > +/// matches "int *a" > +AST_TYPE_MATCHER(PointerType, pointerType); > + > +/// \brief Matches reference types. > +/// > +/// Given > +/// \code > +/// int *a; > +/// int &b = *a; > +/// int c = 5; > +/// \endcode > +/// pointerType() > +/// matches "int &b" > +AST_TYPE_MATCHER(ReferenceType, referenceType); > + > +/// \brief Narrows PointerType (and similar) matchers to those where the > +/// \c pointee matches a given matcher. > +/// > +/// Given > +/// \code > +/// int *a; > +/// int const *b; > +/// float const *f; > +/// \endcode > +/// pointerType(pointee(isConstQualified(), isInteger())) > +/// matches "int const *b" > +/// > +/// Usable as: Matcher<BlockPointerType>, Matcher<MemberPointerType>, > +/// Matcher<PointerType>, Matcher<ReferenceType> > +AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee); > + > +/// \brief Matches typedef types. > +/// > +/// Given > +/// \code > +/// typedef int X; > +/// \endcode > +/// typedefType() > +/// matches "typedef int X" > +AST_TYPE_MATCHER(TypedefType, typedefType); > + > +/// \brief Matches \c TypedefTypes referring to a specific > +/// \c TypedefNameDecl. > +AST_MATCHER_P(TypedefType, hasDecl, > + internal::Matcher<TypedefNameDecl>, InnerMatcher) { > + return InnerMatcher.matches(*Node.getDecl(), Finder, Builder); > +} > + > /// \brief Matches nested name specifiers. > /// > /// Given > @@ -2468,8 +2745,6 @@ > > /// \brief Matches nested name specifiers that specify a type matching the > /// given \c QualType matcher without qualifiers. > -/// FIXME: This is a temporary solution. Switch to using Type-matchers as > soon > -/// as we have those. > /// > /// Given > /// \code > @@ -2485,8 +2760,23 @@ > return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, > Builder); > } > > -/// \brief Matches on the prefix of a \c NestedNameSpecifier or > -/// \c NestedNameSpecifierLoc. > +/// \brief Matches nested name specifier locs that specify a type matching > the > +/// given \c TypeLoc. > +/// > +/// Given > +/// \code > +/// struct A { struct B { struct C {}; }; }; > +/// A::B::C c; > +/// \endcode > +/// nestedNameSpecifierLoc(specifiesTypeLoc(loc(type( > +/// hasDeclaration(recordDecl(hasName("A"))))))) > +/// matches "A::" > +AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, > + internal::Matcher<TypeLoc>, InnerMatcher) { > + return InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); > +} > + > +/// \brief Matches on the prefix of a \c NestedNameSpecifier. > /// > /// Given > /// \code > @@ -2494,9 +2784,27 @@ > /// A::B::C c; > /// \endcode > /// nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and > +/// matches "A::" > +inline internal::Matcher<NestedNameSpecifier> hasPrefix( > + const internal::Matcher<NestedNameSpecifier> &InnerMatcher) { > + return internal::makeMatcher( > + new internal::NestedNameSpecifierPrefixMatcher(InnerMatcher)); > +} > + > +/// \brief Matches on the prefix of a \c NestedNameSpecifierLoc. > +/// > +/// Given > +/// \code > +/// struct A { struct B { struct C {}; }; }; > +/// A::B::C c; > +/// \endcode > /// nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct > A"))))) > -/// both match "A::" > -LOC_TRAVERSE_MATCHER(hasPrefix, NestedNameSpecifier, getPrefix) > +/// matches "A::" > +inline internal::Matcher<NestedNameSpecifierLoc> hasPrefix( > + const internal::Matcher<NestedNameSpecifierLoc> &InnerMatcher) { > + return internal::makeMatcher( > + new internal::NestedNameSpecifierLocPrefixMatcher(InnerMatcher)); > +} > > /// \brief Matches nested name specifiers that specify a namespace matching > the > /// given namespace matcher. > > Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=166094&r1=166093&r2=166094&view=diff > ============================================================================== > --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original) > +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Wed Oct 17 > 03:52:59 2012 > @@ -268,6 +268,16 @@ > !llvm::is_same<From, T>::value >::type* = 0) > : Implementation(new ImplicitCastMatcher<From>(Other)) {} > > + /// \brief Implicitly converts \c Matcher<Type> to \c Matcher<QualType>. > + /// > + /// The resulting matcher is not strict, i.e. ignores qualifiers. > + template <typename TypeT> > + Matcher(const Matcher<TypeT> &Other, > + typename llvm::enable_if_c< > + llvm::is_same<T, QualType>::value && > + llvm::is_same<TypeT, Type>::value >::type* = 0) > + : Implementation(new TypeToQualType<TypeT>(Other)) {} > + > /// \brief Forwards the call to the underlying MatcherInterface<T> pointer. > bool matches(const T &Node, > ASTMatchFinder *Finder, > @@ -291,6 +301,29 @@ > return matches(*Node, Finder, Builder); > } > > + /// \brief Allows the conversion of a \c Matcher<Type> to a \c > + /// Matcher<QualType>. > + /// > + /// Depending on the constructor argument, the matcher is either strict, > i.e. > + /// does only matches in the absence of qualifiers, or not, i.e. simply > + /// ignores any qualifiers. > + template <typename TypeT> > + class TypeToQualType : public MatcherInterface<QualType> { > + public: > + TypeToQualType(const Matcher<TypeT> &InnerMatcher) > + : InnerMatcher(InnerMatcher) {} > + > + virtual bool matches(const QualType &Node, > + ASTMatchFinder *Finder, > + BoundNodesTreeBuilder *Builder) const { > + if (Node.isNull()) > + return false; > + return InnerMatcher.matches(*Node, Finder, Builder); > + } > + private: > + const Matcher<TypeT> InnerMatcher; > + }; > + > private: > /// \brief Allows conversion from Matcher<Base> to Matcher<T> if T > /// is derived from Base. > @@ -950,7 +983,6 @@ > } > }; > > - > class IsArrowMatcher : public SingleNodeMatcherInterface<MemberExpr> { > public: > virtual bool matchesNode(const MemberExpr &Node) const { > @@ -1011,7 +1043,7 @@ > class LocMatcher : public MatcherInterface<TLoc> { > public: > explicit LocMatcher(const Matcher<T> &InnerMatcher) > - : InnerMatcher(InnerMatcher) {} > + : InnerMatcher(InnerMatcher) {} > > virtual bool matches(const TLoc &Node, > ASTMatchFinder *Finder, > @@ -1025,61 +1057,128 @@ > const NestedNameSpecifier *extract(const NestedNameSpecifierLoc &Loc) > const { > return Loc.getNestedNameSpecifier(); > } > - // FIXME: Add overload for TypeLoc when implementing TypeLoc-matchers. > > const Matcher<T> InnerMatcher; > }; > > +/// \brief Matches \c NestedNameSpecifiers with a prefix matching another > +/// \c Matcher<NestedNameSpecifier>. > +class NestedNameSpecifierPrefixMatcher > + : public MatcherInterface<NestedNameSpecifier> { > +public: > + explicit NestedNameSpecifierPrefixMatcher( > + const Matcher<NestedNameSpecifier> &InnerMatcher) > + : InnerMatcher(InnerMatcher) {} > + > + virtual bool matches(const NestedNameSpecifier &Node, > + ASTMatchFinder *Finder, > + BoundNodesTreeBuilder *Builder) const { > + NestedNameSpecifier *NextNode = Node.getPrefix(); > + if (NextNode == NULL) > + return false; > + return InnerMatcher.matches(*NextNode, Finder, Builder); > + } > + > +private: > + const Matcher<NestedNameSpecifier> InnerMatcher; > +}; > + > +/// \brief Matches \c NestedNameSpecifierLocs with a prefix matching another > +/// \c Matcher<NestedNameSpecifierLoc>. > +class NestedNameSpecifierLocPrefixMatcher > + : public MatcherInterface<NestedNameSpecifierLoc> { > +public: > + explicit NestedNameSpecifierLocPrefixMatcher( > + const Matcher<NestedNameSpecifierLoc> &InnerMatcher) > + : InnerMatcher(InnerMatcher) {} > + > + virtual bool matches(const NestedNameSpecifierLoc &Node, > + ASTMatchFinder *Finder, > + BoundNodesTreeBuilder *Builder) const { > + NestedNameSpecifierLoc NextNode = Node.getPrefix(); > + if (!NextNode) > + return false; > + return InnerMatcher.matches(NextNode, Finder, Builder); > + } > + > +private: > + const Matcher<NestedNameSpecifierLoc> InnerMatcher; > +}; > + > +/// \brief Matches \c TypeLocs based on an inner matcher matching a certain > +/// \c QualType. > +/// > +/// Used to implement the \c loc() matcher. > +class TypeLocTypeMatcher : public MatcherInterface<TypeLoc> { > +public: > + explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher) > + : InnerMatcher(InnerMatcher) {} > + > + virtual bool matches(const TypeLoc &Node, > + ASTMatchFinder *Finder, > + BoundNodesTreeBuilder *Builder) const { > + if (!Node) > + return false; > + return InnerMatcher.matches(Node.getType(), Finder, Builder); > + } > + > +private: > + const Matcher<QualType> InnerMatcher; > +}; > + > /// \brief Matches nodes of type \c T for which the inner matcher matches on > a > /// another node of type \c T that can be reached using a given traverse > /// function. > template <typename T> > -class TraverseMatcher : public MatcherInterface<T> { > +class TypeTraverseMatcher : public MatcherInterface<T> { > public: > - explicit TraverseMatcher(const Matcher<T> &InnerMatcher, > - T *(T::*TraverseFunction)() const) > + explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher, > + QualType (T::*TraverseFunction)() const) > : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} > > virtual bool matches(const T &Node, > ASTMatchFinder *Finder, > BoundNodesTreeBuilder *Builder) const { > - T* NextNode = (Node.*TraverseFunction)(); > - if (NextNode == NULL) > + QualType NextNode = (Node.*TraverseFunction)(); > + if (NextNode.isNull()) > return false; > - return InnerMatcher.matches(*NextNode, Finder, Builder); > + return InnerMatcher.matches(NextNode, Finder, Builder); > } > > private: > - const Matcher<T> InnerMatcher; > - T *(T::*TraverseFunction)() const; > + const Matcher<QualType> InnerMatcher; > + QualType (T::*TraverseFunction)() const; > }; > > /// \brief Matches nodes of type \c T in a ..Loc hierarchy, for which the > inner > /// matcher matches on a another node of type \c T that can be reached using > a > /// given traverse function. > template <typename T> > -class LocTraverseMatcher : public MatcherInterface<T> { > +class TypeLocTraverseMatcher : public MatcherInterface<T> { > public: > - explicit LocTraverseMatcher(const Matcher<T> &InnerMatcher, > - T (T::*TraverseFunction)() const) > + explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher, > + TypeLoc (T::*TraverseFunction)() const) > : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} > > virtual bool matches(const T &Node, > ASTMatchFinder *Finder, > BoundNodesTreeBuilder *Builder) const { > - if (!Node) > - return false; > - T NextNode = (Node.*TraverseFunction)(); > + TypeLoc NextNode = (Node.*TraverseFunction)(); > if (!NextNode) > return false; > return InnerMatcher.matches(NextNode, Finder, Builder); > } > > private: > - const Matcher<T> InnerMatcher; > - T (T::*TraverseFunction)() const; > + const Matcher<TypeLoc> InnerMatcher; > + TypeLoc (T::*TraverseFunction)() const; > }; > > +template <typename T, typename InnerT> > +T makeTypeAllOfComposite(ArrayRef<const Matcher<InnerT> *> InnerMatchers) { > + return T(makeAllOfComposite<InnerT>(InnerMatchers)); > +} > + > } // end namespace internal > } // end namespace ast_matchers > } // end namespace clang > > Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h?rev=166094&r1=166093&r2=166094&view=diff > ============================================================================== > --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h (original) > +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h Wed Oct 17 > 03:52:59 2012 > @@ -221,23 +221,69 @@ > const NodeType &Node, ASTMatchFinder *Finder, > \ > BoundNodesTreeBuilder *Builder) const > > -/// \brief LOC_TRAVERSE_MATCHER(MatcherName, NodeType, FunctionName) > -/// defines the matcher \c MatcherName that can be used to traverse > -/// a Type or NestedNameSpecifier as well as the corresponding ..Loc. > +/// \brief Creates a variadic matcher for both a specific \c Type as well as > +/// the corresponding \c TypeLoc. > +#define AST_TYPE_MATCHER(NodeType, MatcherName) > \ > + const internal::VariadicDynCastAllOfMatcher<Type, NodeType> MatcherName; > \ > + const internal::VariadicDynCastAllOfMatcher<TypeLoc, > \ > + NodeType##Loc> MatcherName##Loc > + > +/// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines > +/// the matcher \c MatcherName that can be used to traverse from one \c Type > +/// to another. > /// > -/// The traversal is done using the given \c FunctionName. > -#define LOC_TRAVERSE_MATCHER( > \ > - MatcherName, NodeType, FunctionName) > \ > - inline internal::Matcher<NodeType> hasPrefix( > \ > - const internal::Matcher<NodeType> &InnerMatcher) { > \ > - return internal::makeMatcher(new internal::TraverseMatcher<NodeType>( > \ > - InnerMatcher, &NodeType::getPrefix)); > \ > +/// 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() {} > \ > +}; > \ > +const Variadic##MatcherName##TypeTraverseMatcher 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)); > \ > } > \ > - inline internal::Matcher<NodeType##Loc> hasPrefix( > \ > - const internal::Matcher<NodeType##Loc> &InnerMatcher) { > \ > - return internal::makeMatcher( > \ > - new internal::LocTraverseMatcher<NodeType##Loc>( > \ > - InnerMatcher, &NodeType##Loc::getPrefix)); > \ > - } > +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() {} > \ > +}; > \ > +const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; > \ > +AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type) > > #endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H > > Modified: cfe/trunk/include/clang/ASTMatchers/ASTTypeTraits.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTTypeTraits.h?rev=166094&r1=166093&r2=166094&view=diff > ============================================================================== > --- cfe/trunk/include/clang/ASTMatchers/ASTTypeTraits.h (original) > +++ cfe/trunk/include/clang/ASTMatchers/ASTTypeTraits.h Wed Oct 17 03:52:59 > 2012 > @@ -74,9 +74,11 @@ > enum NodeTypeTag { > NT_Decl, > NT_Stmt, > + NT_Type, > NT_NestedNameSpecifier, > NT_NestedNameSpecifierLoc, > - NT_QualType > + NT_QualType, > + NT_TypeLoc > } Tag; > > /// \brief Stores the data of the node. > @@ -85,8 +87,11 @@ > /// guaranteed to be unique pointers pointing to dedicated storage in the > /// AST. \c QualTypes on the other hand do not have storage or unique > /// pointers and thus need to be stored by value. > - llvm::AlignedCharArrayUnion<Decl*, Stmt*, NestedNameSpecifierLoc, > QualType> Storage; > + llvm::AlignedCharArrayUnion<Decl*, QualType, TypeLoc, > NestedNameSpecifierLoc> > + Storage; > }; > + > +// FIXME: Pull out abstraction for the following. > template<typename T> struct DynTypedNode::BaseConverter<T, > typename llvm::enable_if<llvm::is_base_of<Decl, T> >::type> { > static const T *get(NodeTypeTag Tag, const char Storage[]) { > @@ -115,6 +120,20 @@ > return Result; > } > }; > +template<typename T> struct DynTypedNode::BaseConverter<T, > + typename llvm::enable_if<llvm::is_base_of<Type, T> >::type> { > + static const T *get(NodeTypeTag Tag, const char Storage[]) { > + if (Tag == NT_Type) > + return dyn_cast<T>(*reinterpret_cast<Type*const*>(Storage)); > + return NULL; > + } > + static DynTypedNode create(const Type &Node) { > + DynTypedNode Result; > + Result.Tag = NT_Type; > + new (Result.Storage.buffer) const Type*(&Node); > + return Result; > + } > +}; > template<> struct DynTypedNode::BaseConverter<NestedNameSpecifier, void> { > static const NestedNameSpecifier *get(NodeTypeTag Tag, const char > Storage[]) { > if (Tag == NT_NestedNameSpecifier) > @@ -155,6 +174,19 @@ > return Result; > } > }; > +template<> struct DynTypedNode::BaseConverter<TypeLoc, void> { > + static const TypeLoc *get(NodeTypeTag Tag, const char Storage[]) { > + if (Tag == NT_TypeLoc) > + return reinterpret_cast<const TypeLoc*>(Storage); > + return NULL; > + } > + static DynTypedNode create(const TypeLoc &Node) { > + DynTypedNode Result; > + Result.Tag = NT_TypeLoc; > + new (Result.Storage.buffer) TypeLoc(Node); > + return Result; > + } > +}; > // The only operation we allow on unsupported types is \c get. > // This allows to conveniently use \c DynTypedNode when having an arbitrary > // AST node that is not supported, but prevents misuse - a user cannot create > > Modified: cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp?rev=166094&r1=166093&r2=166094&view=diff > ============================================================================== > --- cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp (original) > +++ cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp Wed Oct 17 03:52:59 2012 > @@ -553,10 +553,15 @@ > return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode); > } > > -bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLoc) { > - match(TypeLoc.getType()); > - return RecursiveASTVisitor<MatchASTVisitor>:: > - TraverseTypeLoc(TypeLoc); > +bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) { > + // The RecursiveASTVisitor only visits types if they're not within > TypeLocs. > + // We still want to find those types via matchers, so we match them here. > Note > + // that the TypeLocs are structurally a shadow-hierarchy to the expressed > + // type, so we visit all involved parts of a compound type when matching on > + // each TypeLoc. > + match(TypeLocNode); > + match(TypeLocNode.getType()); > + return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode); > } > > bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { > @@ -649,6 +654,12 @@ > new NestedNameSpecifierLocMatcher(NodeMatch), Action)); > } > > +void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch, > + MatchCallback *Action) { > + MatcherCallbackPairs.push_back(std::make_pair( > + new TypeLocMatcher(NodeMatch), Action)); > +} > + > ASTConsumer *MatchFinder::newASTConsumer() { > return new internal::MatchASTConsumer(&MatcherCallbackPairs, ParsingDone); > } > > Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=166094&r1=166093&r2=166094&view=diff > ============================================================================== > --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original) > +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Wed Oct 17 03:52:59 > 2012 > @@ -2884,6 +2884,185 @@ > hasAncestor(recordDecl(hasName("A"))))))))); > } > > +TEST(TypeMatching, MatchesTypes) { > + EXPECT_TRUE(matches("struct S {};", qualType().bind("loc"))); > +} > + > +TEST(TypeMatching, MatchesArrayTypes) { > + EXPECT_TRUE(matches("int a[] = {2,3};", arrayType())); > + EXPECT_TRUE(matches("int a[42];", arrayType())); > + EXPECT_TRUE(matches("void f(int b) { int a[b]; }", arrayType())); > + > + EXPECT_TRUE(notMatches("struct A {}; A a[7];", > + arrayType(hasElementType(builtinType())))); > + > + EXPECT_TRUE(matches( > + "int const a[] = { 2, 3 };", > + qualType(arrayType(hasElementType(builtinType()))))); > + EXPECT_TRUE(matches( > + "int const a[] = { 2, 3 };", > + qualType(isConstQualified(), > arrayType(hasElementType(builtinType()))))); > + EXPECT_TRUE(matches( > + "typedef const int T; T x[] = { 1, 2 };", > + qualType(isConstQualified(), arrayType()))); > + > + EXPECT_TRUE(notMatches( > + "int a[] = { 2, 3 };", > + qualType(isConstQualified(), > arrayType(hasElementType(builtinType()))))); > + EXPECT_TRUE(notMatches( > + "int a[] = { 2, 3 };", > + qualType(arrayType(hasElementType(isConstQualified(), > builtinType()))))); > + EXPECT_TRUE(notMatches( > + "int const a[] = { 2, 3 };", > + qualType(arrayType(hasElementType(builtinType())), > + unless(isConstQualified())))); > + > + EXPECT_TRUE(matches("int a[2];", > + constantArrayType(hasElementType(builtinType())))); > + EXPECT_TRUE(matches("const int a = 0;", qualType(isInteger()))); > +} > + > +TEST(TypeMatching, MatchesComplexTypes) { > + EXPECT_TRUE(matches("_Complex float f;", complexType())); > + EXPECT_TRUE(matches( > + "_Complex float f;", > + complexType(hasElementType(builtinType())))); > + EXPECT_TRUE(notMatches( > + "_Complex float f;", > + complexType(hasElementType(isInteger())))); > +} > + > +TEST(TypeMatching, MatchesConstantArrayTypes) { > + EXPECT_TRUE(matches("int a[2];", constantArrayType())); > + EXPECT_TRUE(notMatches( > + "void f() { int a[] = { 2, 3 }; int b[a[0]]; }", > + constantArrayType(hasElementType(builtinType())))); > + > + EXPECT_TRUE(matches("int a[42];", constantArrayType(hasSize(42)))); > + EXPECT_TRUE(matches("int b[2*21];", constantArrayType(hasSize(42)))); > + EXPECT_TRUE(notMatches("int c[41], d[43];", > constantArrayType(hasSize(42)))); > +} > + > +TEST(TypeMatching, MatchesDependentSizedArrayTypes) { > + EXPECT_TRUE(matches( > + "template <typename T, int Size> class array { T data[Size]; };", > + dependentSizedArrayType())); > + EXPECT_TRUE(notMatches( > + "int a[42]; int b[] = { 2, 3 }; void f() { int c[b[0]]; }", > + dependentSizedArrayType())); > +} > + > +TEST(TypeMatching, MatchesIncompleteArrayType) { > + EXPECT_TRUE(matches("int a[] = { 2, 3 };", incompleteArrayType())); > + EXPECT_TRUE(matches("void f(int a[]) {}", incompleteArrayType())); > + > + EXPECT_TRUE(notMatches("int a[42]; void f() { int b[a[0]]; }", > + incompleteArrayType())); > +} > + > +TEST(TypeMatching, MatchesVariableArrayType) { > + EXPECT_TRUE(matches("void f(int b) { int a[b]; }", variableArrayType())); > + EXPECT_TRUE(notMatches("int a[] = {2, 3}; int b[42];", > variableArrayType())); > + > + EXPECT_TRUE(matches( > + "void f(int b) { int a[b]; }", > + variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to( > + varDecl(hasName("b"))))))))); > +} > + > +TEST(TypeMatching, MatchesAtomicTypes) { > + EXPECT_TRUE(matches("_Atomic(int) i;", atomicType())); > + > + EXPECT_TRUE(matches("_Atomic(int) i;", > + atomicType(hasValueType(isInteger())))); > + EXPECT_TRUE(notMatches("_Atomic(float) f;", > + atomicType(hasValueType(isInteger())))); > +} > + > +TEST(TypeMatching, MatchesAutoTypes) { > + EXPECT_TRUE(matches("auto i = 2;", autoType())); > + EXPECT_TRUE(matches("int v[] = { 2, 3 }; void f() { for (int i : v) {} }", > + autoType())); > + > + EXPECT_TRUE(matches("auto a = 1;", > + autoType(hasDeducedType(isInteger())))); > + EXPECT_TRUE(notMatches("auto b = 2.0;", > + autoType(hasDeducedType(isInteger())))); > +} > + > +TEST(TypeMatching, PointerTypes) { > + EXPECT_TRUE(matchAndVerifyResultTrue( > + "int* a;", > + pointerTypeLoc(pointeeLoc(typeLoc().bind("loc"))), > + new VerifyIdIsBoundTo<TypeLoc>("loc", 1))); > + EXPECT_TRUE(matchAndVerifyResultTrue( > + "int* a;", > + pointerTypeLoc().bind("loc"), > + new VerifyIdIsBoundTo<TypeLoc>("loc", 1))); > + EXPECT_TRUE(matches( > + "int** a;", > + pointerTypeLoc(pointeeLoc(loc(qualType()))))); > + EXPECT_TRUE(matches( > + "int** a;", > + loc(pointerType(pointee(pointerType()))))); > + EXPECT_TRUE(matches( > + "int* b; int* * const a = &b;", > + loc(qualType(isConstQualified(), pointerType())))); > + > + std::string Fragment = "struct A { int i; }; int A::* ptr = &A::i;"; > + EXPECT_TRUE(notMatches(Fragment, blockPointerType())); > + EXPECT_TRUE(matches(Fragment, memberPointerType())); > + EXPECT_TRUE(notMatches(Fragment, pointerType())); > + EXPECT_TRUE(notMatches(Fragment, referenceType())); > + > + Fragment = "int *I;"; > + EXPECT_TRUE(notMatches(Fragment, blockPointerType())); > + EXPECT_TRUE(notMatches(Fragment, memberPointerType())); > + EXPECT_TRUE(matches(Fragment, pointerType())); > + EXPECT_TRUE(notMatches(Fragment, referenceType())); > + > + Fragment = "int a; int &b = a;"; > + EXPECT_TRUE(notMatches(Fragment, blockPointerType())); > + EXPECT_TRUE(notMatches(Fragment, memberPointerType())); > + EXPECT_TRUE(notMatches(Fragment, pointerType())); > + EXPECT_TRUE(matches(Fragment, referenceType())); > +} > + > +TEST(TypeMatching, PointeeTypes) { > + EXPECT_TRUE(matches("int b; int &a = b;", > + referenceType(pointee(builtinType())))); > + EXPECT_TRUE(matches("int *a;", pointerType(pointee(builtinType())))); > + > + EXPECT_TRUE(matches("int *a;", > + pointerTypeLoc(pointeeLoc(loc(builtinType()))))); > + > + EXPECT_TRUE(matches( > + "int const *A;", > + pointerType(pointee(isConstQualified(), builtinType())))); > + EXPECT_TRUE(notMatches( > + "int *A;", > + pointerType(pointee(isConstQualified(), builtinType())))); > +} > + > +TEST(TypeMatching, MatchesPointersToConstTypes) { > + EXPECT_TRUE(matches("int b; int * const a = &b;", > + loc(pointerType()))); > + EXPECT_TRUE(matches("int b; int * const a = &b;", > + pointerTypeLoc())); > + EXPECT_TRUE(matches( > + "int b; const int * a = &b;", > + pointerTypeLoc(pointeeLoc(builtinTypeLoc())))); > + EXPECT_TRUE(matches( > + "int b; const int * a = &b;", > + pointerType(pointee(builtinType())))); > +} > + > +TEST(TypeMatching, MatchesTypedefTypes) { > + EXPECT_TRUE(matches("typedef int X;", typedefType())); > + > + EXPECT_TRUE(matches("typedef int X;", typedefType(hasDecl(decl())))); > +} > + > TEST(NNS, MatchesNestedNameSpecifiers) { > EXPECT_TRUE(matches("namespace ns { struct A {}; } ns::A a;", > nestedNameSpecifier())); > @@ -2942,8 +3121,8 @@ > nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))))); > EXPECT_TRUE(matches( > "struct A { struct B { struct C {}; }; }; A::B::C c;", > - nestedNameSpecifierLoc(hasPrefix(loc( > - specifiesType(asString("struct A"))))))); > + nestedNameSpecifierLoc(hasPrefix( > + specifiesTypeLoc(loc(qualType(asString("struct A")))))))); > } > > } // end namespace ast_matchers > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
