This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG56e72a40c198: Update `DynTypedNode` to support the conversion of `TypeLoc`s. (authored by jcking1034, committed by ymandel).
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,41 @@ EXPECT_FALSE(Node < Node); } +TEST(DynTypedNode, TypeLoc) { + std::string code = R"cc(void example() { int abc; })cc"; + auto AST = clang::tooling::buildASTFromCode(code); + auto matches = + match(traverse(TK_AsIs, + varDecl(hasName("abc"), hasTypeLoc(typeLoc().bind("tl")))), + AST->getASTContext()); + EXPECT_EQ(matches.size(), 1u); + + const auto &tl = *matches[0].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 matches = + match(traverse(TK_AsIs, varDecl(hasName("abc"), + hasTypeLoc(typeLoc().bind("ptl")))), + AST->getASTContext()); + EXPECT_EQ(matches.size(), 1u); + + const auto &tl = *matches[0].getNodeAs<TypeLoc>("ptl"); + DynTypedNode TypeLocNode = DynTypedNode::create(tl); + EXPECT_TRUE(TypeLocNode == TypeLocNode); + EXPECT_FALSE(TypeLocNode < TypeLocNode); + + const auto &ptl = *matches[0].getNodeAs<PointerTypeLoc>("ptl"); + EXPECT_EQ(&tl, &ptl); + DynTypedNode PointerTypeLocNode = DynTypedNode::create(ptl); + EXPECT_TRUE(PointerTypeLocNode == PointerTypeLocNode); + EXPECT_FALSE(PointerTypeLocNode < PointerTypeLocNode); +} + } // 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 cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits