aboutsummaryrefslogtreecommitdiff
path: root/include/clang/AST/ASTTypeTraits.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/ASTTypeTraits.h')
-rw-r--r--include/clang/AST/ASTTypeTraits.h111
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