}
};
+ /// Check if the given ASTNodeKind identifies a type that offers pointer
+ /// identity. This is useful for the fast path in DynTypedNode.
+ bool hasPointerIdentity() const {
+ return KindId > NKI_LastKindWithoutPointerIdentity;
+ }
+
private:
/// \brief Kind ids.
///
/// Includes all possible base and derived kinds.
enum NodeKindId {
NKI_None,
- NKI_CXXCtorInitializer,
NKI_TemplateArgument,
- NKI_NestedNameSpecifier,
NKI_NestedNameSpecifierLoc,
NKI_QualType,
NKI_TypeLoc,
+ NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
+ NKI_CXXCtorInitializer,
+ NKI_NestedNameSpecifier,
NKI_Decl,
#define DECL(DERIVED, BASE) NKI_##DERIVED##Decl,
#include "clang/AST/DeclNodes.inc"
/// 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 { return MemoizationData; }
+ const void *getMemoizationData() const {
+ return NodeKind.hasPointerIdentity()
+ ? *reinterpret_cast<void *const *>(Storage.buffer)
+ : nullptr;
+ }
/// \brief Prints the node to the given output stream.
void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
template <typename T, typename BaseT> struct DynCastPtrConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
- return cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
+ return &getUnchecked(NodeKind, 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));
+ return *cast<T>(static_cast<const BaseT *>(
+ *reinterpret_cast<const void *const *>(Storage)));
}
static DynTypedNode create(const BaseT &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNode(Node);
- Result.MemoizationData = &Node;
- new (Result.Storage.buffer) const BaseT * (&Node);
+ new (Result.Storage.buffer) const void *(&Node);
return Result;
}
};
template <typename T> struct PtrConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
- return *reinterpret_cast<T *const *>(Storage);
+ return &getUnchecked(NodeKind, Storage);
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
- return **reinterpret_cast<T *const *>(Storage);
+ return *static_cast<const T *>(
+ *reinterpret_cast<const void *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);
+ new (Result.Storage.buffer) const void *(&Node);
return Result;
}
};
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.
///
/// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and
/// \c TemplateArguments on the other hand do not have storage or unique
/// pointers and thus need to be stored by value.
- typedef llvm::AlignedCharArrayUnion<
- Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *>
- KindsByPointer;
- llvm::AlignedCharArrayUnion<KindsByPointer, TemplateArgument,
- NestedNameSpecifierLoc, QualType, TypeLoc>
- Storage;
+ llvm::AlignedCharArrayUnion<const void *, TemplateArgument,
+ NestedNameSpecifierLoc, QualType,
+ TypeLoc> Storage;
};
template <typename T>