jcking1034 updated this revision to Diff 376573.
jcking1034 marked an inline comment as done.
jcking1034 added a comment.
Fix typing for `create` and add unit tests.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D110586/new/
https://reviews.llvm.org/D110586
Files:
clang/include/clang/AST/ASTTypeTraits.h
clang/lib/AST/ASTTypeTraits.cpp
clang/unittests/AST/ASTTypeTraitsTest.cpp
Index: clang/unittests/AST/ASTTypeTraitsTest.cpp
===================================================================
--- clang/unittests/AST/ASTTypeTraitsTest.cpp
+++ clang/unittests/AST/ASTTypeTraitsTest.cpp
@@ -199,5 +199,34 @@
EXPECT_FALSE(Node < Node);
}
+TEST(DynTypedNode, TypeLoc) {
+ std::string code = R"cc(void example() { int abc; })cc";
+ auto AST = clang::tooling::buildASTFromCode(code);
+ auto &context = AST->getASTContext();
+ auto matches = match(traverse(TK_AsIs, typeLoc().bind("tl")), context);
+ for (auto &nodes : matches) {
+ const auto &tl = *nodes.getNodeAs<TypeLoc>("tl");
+ DynTypedNode Node = DynTypedNode::create(tl);
+ EXPECT_TRUE(Node == Node);
+ EXPECT_FALSE(Node < Node);
+ }
+}
+
+TEST(DynTypedNode, PointerTypeLoc) {
+ std::string code = R"cc(void example() { int* abc; })cc";
+ auto AST = clang::tooling::buildASTFromCode(code);
+ auto &context = AST->getASTContext();
+ auto matches =
+ match(traverse(TK_AsIs, varDecl(hasName("abc"),
+ hasTypeLoc(typeLoc().bind("ptl")))),
+ context);
+ for (auto &nodes : matches) {
+ const auto ptl = nodes.getNodeAs<TypeLoc>("ptl")->castAs<PointerTypeLoc>();
+ DynTypedNode Node = DynTypedNode::create(ptl);
+ EXPECT_TRUE(Node == Node);
+ EXPECT_FALSE(Node < Node);
+ }
+}
+
} // namespace
} // namespace clang
Index: clang/lib/AST/ASTTypeTraits.cpp
===================================================================
--- clang/lib/AST/ASTTypeTraits.cpp
+++ clang/lib/AST/ASTTypeTraits.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OpenMPClause.h"
+#include "clang/AST/TypeLoc.h"
using namespace clang;
@@ -28,6 +29,8 @@
{NKI_None, "TemplateName"},
{NKI_None, "NestedNameSpecifierLoc"},
{NKI_None, "QualType"},
+#define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},
+#include "clang/AST/TypeLocNodes.def"
{NKI_None, "TypeLoc"},
{NKI_None, "CXXBaseSpecifier"},
{NKI_None, "CXXCtorInitializer"},
@@ -127,6 +130,17 @@
llvm_unreachable("invalid type kind");
}
+ ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc &T) {
+ switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case TypeLoc::CLASS: \
+ return ASTNodeKind(NKI_##CLASS##TypeLoc);
+#include "clang/AST/TypeLocNodes.def"
+ }
+ llvm_unreachable("invalid typeloc kind");
+ }
+
ASTNodeKind ASTNodeKind::getFromNode(const OMPClause &C) {
switch (C.getClauseKind()) {
#define GEN_CLANG_CLAUSE_CLASS
Index: clang/include/clang/AST/ASTTypeTraits.h
===================================================================
--- clang/include/clang/AST/ASTTypeTraits.h
+++ clang/include/clang/AST/ASTTypeTraits.h
@@ -63,6 +63,7 @@
static ASTNodeKind getFromNode(const Decl &D);
static ASTNodeKind getFromNode(const Stmt &S);
static ASTNodeKind getFromNode(const Type &T);
+ static ASTNodeKind getFromNode(const TypeLoc &T);
static ASTNodeKind getFromNode(const OMPClause &C);
static ASTNodeKind getFromNode(const Attr &A);
/// \}
@@ -133,6 +134,8 @@
NKI_TemplateName,
NKI_NestedNameSpecifierLoc,
NKI_QualType,
+#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
+#include "clang/AST/TypeLocNodes.def"
NKI_TypeLoc,
NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
NKI_CXXBaseSpecifier,
@@ -198,6 +201,8 @@
KIND_TO_KIND_ID(NestedNameSpecifier)
KIND_TO_KIND_ID(NestedNameSpecifierLoc)
KIND_TO_KIND_ID(QualType)
+#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
+#include "clang/AST/TypeLocNodes.def"
KIND_TO_KIND_ID(TypeLoc)
KIND_TO_KIND_ID(Decl)
KIND_TO_KIND_ID(Stmt)
@@ -304,7 +309,7 @@
return getUnchecked<QualType>().getAsOpaquePtr() <
Other.getUnchecked<QualType>().getAsOpaquePtr();
- if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) {
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(NodeKind)) {
auto TLA = getUnchecked<TypeLoc>();
auto TLB = Other.getUnchecked<TypeLoc>();
return std::make_pair(TLA.getType().getAsOpaquePtr(),
@@ -336,7 +341,7 @@
if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
return getUnchecked<QualType>() == Other.getUnchecked<QualType>();
- if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind))
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(NodeKind))
return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>();
if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind))
@@ -365,7 +370,7 @@
}
static unsigned getHashValue(const DynTypedNode &Val) {
// FIXME: Add hashing support for the remaining types.
- if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(Val.NodeKind)) {
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(Val.NodeKind)) {
auto TL = Val.getUnchecked<TypeLoc>();
return llvm::hash_combine(TL.getType().getAsOpaquePtr(),
TL.getOpaqueData());
@@ -455,6 +460,29 @@
}
};
+ /// Converter that stores nodes by value. It must be possible to dynamically
+ /// cast the stored node within a type hierarchy without breaking (especially
+ /// through slicing).
+ template <typename T, typename BaseT,
+ typename = std::enable_if_t<(sizeof(T) == sizeof(BaseT))>>
+ struct DynCastValueConverter {
+ static const T *get(ASTNodeKind NodeKind, const void *Storage) {
+ if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
+ return &getUnchecked(NodeKind, Storage);
+ return nullptr;
+ }
+ static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
+ assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
+ return *static_cast<const T *>(reinterpret_cast<const BaseT *>(Storage));
+ }
+ static DynTypedNode create(const T &Node) {
+ DynTypedNode Result;
+ Result.NodeKind = ASTNodeKind::getFromNode(Node);
+ new (&Result.Storage) T(Node);
+ return Result;
+ }
+ };
+
ASTNodeKind NodeKind;
/// Stores the data of the node.
@@ -525,9 +553,10 @@
struct DynTypedNode::BaseConverter<QualType,
void> : public ValueConverter<QualType> {};
-template <>
+template <typename T>
struct DynTypedNode::BaseConverter<
- TypeLoc, void> : public ValueConverter<TypeLoc> {};
+ T, std::enable_if_t<std::is_base_of<TypeLoc, T>::value>>
+ : public DynCastValueConverter<T, TypeLoc> {};
template <>
struct DynTypedNode::BaseConverter<CXXBaseSpecifier, void>
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits