[cfe-commits] r166094 - in /cfe/trunk: include/clang/ASTMatchers/ASTMatchFinder.h include/clang/ASTMatchers/ASTMatchers.h include/clang/ASTMatchers/ASTMatchersInternal.h include/clang/ASTMatchers/ASTMatchersMacros.h include/clang/ASTMatchers/ASTT

NAKAMURA Takumi geek4civic at gmail.com
Wed Oct 17 04:49:46 PDT 2012


It seems it broke 32-bit hosts.

I saw the failure on cygming, msvc, and i686-linux.
Also clang-i386-darwin10-RA at smooshlab would be dubious.


2012/10/17 Daniel Jasper <djasper at google.com>:
> 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list