Author: Eric Li Date: 2022-10-13T13:00:48-04:00 New Revision: 576283c3a8ef5078b3ec12fa442c14f3a1b5fea2
URL: https://github.com/llvm/llvm-project/commit/576283c3a8ef5078b3ec12fa442c14f3a1b5fea2 DIFF: https://github.com/llvm/llvm-project/commit/576283c3a8ef5078b3ec12fa442c14f3a1b5fea2.diff LOG: [clang] Support `constexpr` for some `ASTNodeKind` member functions Add `constexpr` support for: * The `getFromNodeKind` factory function * `isSame` * `isNone` * `hasPointerIdentity` This enables these functions to be used in SFINAE context for AST node types. Differential Revision: https://reviews.llvm.org/D135816 Added: Modified: clang/include/clang/AST/ASTTypeTraits.h clang/unittests/AST/ASTTypeTraitsTest.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/ASTTypeTraits.h b/clang/include/clang/AST/ASTTypeTraits.h index cd6b5143bf79..8713221a7378 100644 --- a/clang/include/clang/AST/ASTTypeTraits.h +++ b/clang/include/clang/AST/ASTTypeTraits.h @@ -51,11 +51,10 @@ enum TraversalKind { class ASTNodeKind { public: /// Empty identifier. It matches nothing. - ASTNodeKind() : KindId(NKI_None) {} + constexpr ASTNodeKind() : KindId(NKI_None) {} /// Construct an identifier for T. - template <class T> - static ASTNodeKind getFromNodeKind() { + template <class T> static constexpr ASTNodeKind getFromNodeKind() { return ASTNodeKind(KindToKindId<T>::Id); } @@ -71,12 +70,12 @@ class ASTNodeKind { /// \} /// Returns \c true if \c this and \c Other represent the same kind. - bool isSame(ASTNodeKind Other) const { + constexpr bool isSame(ASTNodeKind Other) const { return KindId != NKI_None && KindId == Other.KindId; } /// Returns \c true only for the default \c ASTNodeKind() - bool isNone() const { return KindId == NKI_None; } + constexpr bool isNone() const { return KindId == NKI_None; } /// 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 @@ -87,7 +86,7 @@ class ASTNodeKind { StringRef asStringRef() const; /// Strict weak ordering for ASTNodeKind. - bool operator<(const ASTNodeKind &Other) const { + constexpr bool operator<(const ASTNodeKind &Other) const { return KindId < Other.KindId; } @@ -121,7 +120,7 @@ class ASTNodeKind { /// Check if the given ASTNodeKind identifies a type that offers pointer /// identity. This is useful for the fast path in DynTypedNode. - bool hasPointerIdentity() const { + constexpr bool hasPointerIdentity() const { return KindId > NKI_LastKindWithoutPointerIdentity; } @@ -165,7 +164,7 @@ class ASTNodeKind { }; /// Use getFromNodeKind<T>() to construct the kind. - ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} + constexpr ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} /// Returns \c true if \c Base is a base kind of (or same as) \c /// Derived. diff --git a/clang/unittests/AST/ASTTypeTraitsTest.cpp b/clang/unittests/AST/ASTTypeTraitsTest.cpp index 9fcb00630209..dcea32d1f1c0 100644 --- a/clang/unittests/AST/ASTTypeTraitsTest.cpp +++ b/clang/unittests/AST/ASTTypeTraitsTest.cpp @@ -117,6 +117,47 @@ TEST(ASTNodeKind, UnknownKind) { EXPECT_FALSE(DNT<Foo>().isSame(DNT<Foo>())); } +template <typename T> +constexpr bool HasPointerIdentity = + ASTNodeKind::getFromNodeKind<T>().hasPointerIdentity(); + +TEST(ASTNodeKind, ConstexprHasPointerIdentity) { + EXPECT_TRUE(HasPointerIdentity<Decl>); + EXPECT_TRUE(HasPointerIdentity<Stmt>); + EXPECT_FALSE(HasPointerIdentity<TypeLoc>); + EXPECT_FALSE(HasPointerIdentity<QualType>); + EXPECT_FALSE(HasPointerIdentity<Foo>); + + constexpr bool DefaultConstructedHasPointerIdentity = + ASTNodeKind().hasPointerIdentity(); + EXPECT_FALSE(DefaultConstructedHasPointerIdentity); +} + +template <typename T, typename U> +constexpr bool NodeKindIsSame = + ASTNodeKind::getFromNodeKind<T>().isSame(ASTNodeKind::getFromNodeKind<U>()); + +TEST(ASTNodeKind, ConstexprIsSame) { + EXPECT_TRUE((NodeKindIsSame<Decl, Decl>)); + EXPECT_FALSE((NodeKindIsSame<Decl, VarDecl>)); + EXPECT_FALSE((NodeKindIsSame<Foo, Foo>)); + + constexpr bool DefaultConstructedIsSameToDefaultConstructed = + ASTNodeKind().isSame(ASTNodeKind()); + EXPECT_FALSE(DefaultConstructedIsSameToDefaultConstructed); +} + +template <typename T> +constexpr bool NodeKindIsNone = ASTNodeKind::getFromNodeKind<T>().isNone(); + +TEST(ASTNodeKind, ConstexprIsNone) { + EXPECT_FALSE(NodeKindIsNone<Decl>); + EXPECT_TRUE(NodeKindIsNone<Foo>); + + constexpr bool DefaultConstructedIsNone = ASTNodeKind().isNone(); + EXPECT_TRUE(DefaultConstructedIsNone); +} + TEST(ASTNodeKind, Name) { EXPECT_EQ("<None>", ASTNodeKind().asStringRef()); #define VERIFY_NAME(Node) EXPECT_EQ(#Node, DNT<Node>().asStringRef()); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits