diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index 4fe9a3f87f53061c5c6ee1015cb56bd8720386d4..dc3c34f28d94bc92e42a8c6b7ed661966eccc29a 100644 --- a/include/clang/AST/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -145,6 +145,8 @@ private: template <class T> struct KindToKindId { static const NodeKindId Id = NKI_None; }; + template <class T> + struct KindToKindId<const T> : KindToKindId<T> {}; /// \brief Per kind info. struct KindInfo { @@ -221,6 +223,14 @@ public: return BaseConverter<T>::get(NodeKind, Storage.buffer); } + /// \brief Retrieve the stored node as type \c T. + /// + /// Similar to \c get(), but asserts that the type is what we are expecting. + template <typename T> + const T &getUnchecked() const { + return BaseConverter<T>::getUnchecked(NodeKind, Storage.buffer); + } + ASTNodeKind getNodeKind() const { return NodeKind; } /// \brief Returns a pointer that identifies the stored AST node. @@ -251,14 +261,15 @@ public: return getMemoizationData() < Other.getMemoizationData(); } bool operator==(const DynTypedNode &Other) const { - if (!NodeKind.isBaseOf(Other.NodeKind) && - !Other.NodeKind.isBaseOf(NodeKind)) + // DynTypedNode::create() stores the exact kind of the node in NodeKind. + // If they contain the same node, their NodeKind must be the same. + if (!NodeKind.isSame(Other.NodeKind)) return false; // FIXME: Implement for other types. - if (ASTNodeKind::getFromNodeKind<QualType>().isBaseOf(NodeKind)) { - return *get<QualType>() == *Other.get<QualType>(); - } + if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) + return getUnchecked<QualType>() == Other.getUnchecked<QualType>(); + assert(getMemoizationData() && Other.getMemoizationData()); return getMemoizationData() == Other.getMemoizationData(); } @@ -274,10 +285,14 @@ private: /// \brief Converter that uses dyn_cast<T> from a stored BaseT*. template <typename T, typename BaseT> struct DynCastPtrConverter { static const T *get(ASTNodeKind NodeKind, const char Storage[]) { - if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind)) - return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); + if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)) + return cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)); + return *cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); + } static DynTypedNode create(const BaseT &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNode(Node); @@ -294,6 +309,10 @@ private: return *reinterpret_cast<T *const *>(Storage); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); + return **reinterpret_cast<T *const *>(Storage); + } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); @@ -310,6 +329,10 @@ private: return reinterpret_cast<const T *>(Storage); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); + return *reinterpret_cast<const T *>(Storage); + } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index 3aecf4b0e440fe3b43903119dfd52df8aed4a9bb..95e740e65b114c46be04a109d69b678bd17d9893 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -218,10 +218,7 @@ public: bool dynMatches(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const override { - if (const T *Node = DynNode.get<T>()) { - return matches(*Node, Finder, Builder); - } - return false; + return matches(DynNode.getUnchecked<T>(), Finder, Builder); } };