diff options
Diffstat (limited to 'include/clang/AST/ASTTypeTraits.h')
-rw-r--r-- | include/clang/AST/ASTTypeTraits.h | 111 |
1 files changed, 86 insertions, 25 deletions
diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index 0e06e26e6d80..dc3c34f28d94 100644 --- a/include/clang/AST/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_AST_TYPE_TRAITS_H -#define LLVM_CLANG_AST_AST_TYPE_TRAITS_H +#ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H +#define LLVM_CLANG_AST_ASTTYPETRAITS_H #include "clang/AST/ASTFwd.h" #include "clang/AST/Decl.h" @@ -23,6 +23,7 @@ #include "clang/AST/TemplateBase.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/AlignOf.h" namespace llvm { @@ -53,9 +54,19 @@ public: return ASTNodeKind(KindToKindId<T>::Id); } + /// \{ + /// \brief Construct an identifier for the dynamic type of the node + static ASTNodeKind getFromNode(const Decl &D); + static ASTNodeKind getFromNode(const Stmt &S); + static ASTNodeKind getFromNode(const Type &T); + /// \} + /// \brief Returns \c true if \c this and \c Other represent the same kind. bool isSame(ASTNodeKind Other) const; + /// \brief Returns \c true only for the default \c ASTNodeKind() + bool isNone() const { return KindId == NKI_None; } + /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other. /// \param Distance If non-null, used to return the distance between \c this /// and \c Other in the class hierarchy. @@ -69,6 +80,32 @@ public: return KindId < Other.KindId; } + /// \brief Return the most derived type between \p Kind1 and \p Kind2. + /// + /// Return ASTNodeKind() if they are not related. + static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2); + + /// \brief Return the most derived common ancestor between Kind1 and Kind2. + /// + /// Return ASTNodeKind() if they are not related. + static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1, + ASTNodeKind Kind2); + + /// \brief Hooks for using ASTNodeKind as a key in a DenseMap. + struct DenseMapInfo { + // ASTNodeKind() is a good empty key because it is represented as a 0. + static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); } + // NKI_NumberOfKinds is not a valid value, so it is good for a + // tombstone key. + static inline ASTNodeKind getTombstoneKey() { + return ASTNodeKind(NKI_NumberOfKinds); + } + static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; } + static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) { + return LHS.KindId == RHS.KindId; + } + }; + private: /// \brief Kind ids. /// @@ -108,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 { @@ -184,12 +223,22 @@ 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. /// /// Note that this is not supported by all AST nodes. For AST nodes /// that don't have a pointer-defined identity inside the AST, this /// method returns NULL. - const void *getMemoizationData() const; + const void *getMemoizationData() const { return MemoizationData; } /// \brief Prints the node to the given output stream. void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; @@ -212,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(); } @@ -235,13 +285,18 @@ 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::getFromNodeKind<T>(); + Result.NodeKind = ASTNodeKind::getFromNode(Node); + Result.MemoizationData = &Node; new (Result.Storage.buffer) const BaseT * (&Node); return Result; } @@ -254,9 +309,14 @@ 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>(); + Result.MemoizationData = &Node; new (Result.Storage.buffer) const T * (&Node); return Result; } @@ -269,15 +329,21 @@ 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>(); + Result.MemoizationData = nullptr; new (Result.Storage.buffer) T(Node); return Result; } }; ASTNodeKind NodeKind; + const void *MemoizationData; /// \brief Stores the data of the node. /// @@ -345,20 +411,15 @@ template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter { } }; -inline const void *DynTypedNode::getMemoizationData() const { - if (ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(NodeKind)) { - return BaseConverter<Decl>::get(NodeKind, Storage.buffer); - } else if (ASTNodeKind::getFromNodeKind<Stmt>().isBaseOf(NodeKind)) { - return BaseConverter<Stmt>::get(NodeKind, Storage.buffer); - } else if (ASTNodeKind::getFromNodeKind<Type>().isBaseOf(NodeKind)) { - return BaseConverter<Type>::get(NodeKind, Storage.buffer); - } else if (ASTNodeKind::getFromNodeKind<NestedNameSpecifier>().isBaseOf(NodeKind)) { - return BaseConverter<NestedNameSpecifier>::get(NodeKind, Storage.buffer); - } - return nullptr; -} - } // end namespace ast_type_traits } // end namespace clang -#endif // LLVM_CLANG_AST_AST_TYPE_TRAITS_H +namespace llvm { + +template <> +struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind> + : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {}; + +} // end namespace llvm + +#endif |