From 6bae49b56508f96719be3016bd699157a5274eb9 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 15 Jan 2020 12:36:20 -0800 Subject: [PATCH] PointerLikeTypeTraits: Standardize NumLowBitsAvailable on static constexpr rather than anonymous enum This is (more?) usable by GDB pretty printers and seems nicer to write. There's one tricky caveat that in C++14 (LLVM's codebase today) the static constexpr member declaration is not a definition - so odr use of this constant requires an out of line definition, which won't be provided (that'd make all these trait classes more annoyidng/expensive to maintain). But the use of this constant in the library implementation is/should always be in a non-odr context - only two unit tests needed to be touched to cope with this/avoid odr using these constants. Based on/expanded from D72590 by Christian Sigg. --- include/llvm/ADT/IntervalMap.h | 2 +- include/llvm/ADT/PointerEmbeddedInt.h | 2 +- include/llvm/ADT/PointerIntPair.h | 3 +- include/llvm/IR/Use.h | 4 +-- include/llvm/Support/PointerLikeTypeTraits.h | 14 +++++---- lib/Analysis/GlobalsModRef.cpp | 2 +- unittests/ADT/PointerEmbeddedIntTest.cpp | 4 +-- unittests/ADT/PointerIntPairTest.cpp | 32 ++++++++++---------- 8 files changed, 33 insertions(+), 30 deletions(-) diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index a02876ee77f..e9e6c54563f 100644 --- a/include/llvm/ADT/IntervalMap.h +++ b/include/llvm/ADT/IntervalMap.h @@ -491,7 +491,7 @@ class NodeRef { struct CacheAlignedPointerTraits { static inline void *getAsVoidPointer(void *P) { return P; } static inline void *getFromVoidPointer(void *P) { return P; } - enum { NumLowBitsAvailable = Log2CacheLine }; + static constexpr int NumLowBitsAvailable = Log2CacheLine; }; PointerIntPair pip; diff --git a/include/llvm/ADT/PointerEmbeddedInt.h b/include/llvm/ADT/PointerEmbeddedInt.h index 3eb6edb0343..fbc48af79da 100644 --- a/include/llvm/ADT/PointerEmbeddedInt.h +++ b/include/llvm/ADT/PointerEmbeddedInt.h @@ -94,7 +94,7 @@ struct PointerLikeTypeTraits> { return T(reinterpret_cast(P), typename T::RawValueTag()); } - enum { NumLowBitsAvailable = T::Shift }; + static constexpr int NumLowBitsAvailable = T::Shift; }; // Teach DenseMap how to use PointerEmbeddedInt objects as keys if the Int type diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index fa6bf150446..bcd7941798f 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -235,7 +235,8 @@ struct PointerLikeTypeTraits< return PointerIntPair::getFromOpaqueValue(P); } - enum { NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits }; + static constexpr int NumLowBitsAvailable = + PtrTraits::NumLowBitsAvailable - IntBits; }; } // end namespace llvm diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index 034ca2c8ac2..6c5dd60f117 100644 --- a/include/llvm/IR/Use.h +++ b/include/llvm/IR/Use.h @@ -69,7 +69,7 @@ public: return (User *)P; } - enum { NumLowBitsAvailable = 1 }; + static constexpr int NumLowBitsAvailable = 1; }; // A type for the word following an array of hung-off Uses in memory, which is @@ -85,7 +85,7 @@ public: return (Use **)P; } - enum { NumLowBitsAvailable = 2 }; + static constexpr int NumLowBitsAvailable = 2; }; private: diff --git a/include/llvm/Support/PointerLikeTypeTraits.h b/include/llvm/Support/PointerLikeTypeTraits.h index 1e7e5b53ca6..71ec8180751 100644 --- a/include/llvm/Support/PointerLikeTypeTraits.h +++ b/include/llvm/Support/PointerLikeTypeTraits.h @@ -56,7 +56,8 @@ template struct PointerLikeTypeTraits { static inline void *getAsVoidPointer(T *P) { return P; } static inline T *getFromVoidPointer(void *P) { return static_cast(P); } - enum { NumLowBitsAvailable = detail::ConstantLog2::value }; + static constexpr int NumLowBitsAvailable = + detail::ConstantLog2::value; }; template <> struct PointerLikeTypeTraits { @@ -70,7 +71,7 @@ template <> struct PointerLikeTypeTraits { /// /// All clients should use assertions to do a run-time check to ensure that /// this is actually true. - enum { NumLowBitsAvailable = 2 }; + static constexpr int NumLowBitsAvailable = 2; }; // Provide PointerLikeTypeTraits for const things. @@ -83,7 +84,7 @@ template struct PointerLikeTypeTraits { static inline const T getFromVoidPointer(const void *P) { return NonConst::getFromVoidPointer(const_cast(P)); } - enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable }; + static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable; }; // Provide PointerLikeTypeTraits for const pointers. @@ -96,7 +97,7 @@ template struct PointerLikeTypeTraits { static inline const T *getFromVoidPointer(const void *P) { return NonConst::getFromVoidPointer(const_cast(P)); } - enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable }; + static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable; }; // Provide PointerLikeTypeTraits for uintptr_t. @@ -108,7 +109,7 @@ template <> struct PointerLikeTypeTraits { return reinterpret_cast(P); } // No bits are available! - enum { NumLowBitsAvailable = 0 }; + static constexpr int NumLowBitsAvailable = 0; }; /// Provide suitable custom traits struct for function pointers. @@ -121,7 +122,8 @@ template <> struct PointerLikeTypeTraits { /// potentially use alignment attributes on functions to satisfy that. template struct FunctionPointerLikeTypeTraits { - enum { NumLowBitsAvailable = detail::ConstantLog2::value }; + static constexpr int NumLowBitsAvailable = + detail::ConstantLog2::value; static inline void *getAsVoidPointer(FunctionPointerT P) { assert((reinterpret_cast(P) & ~((uintptr_t)-1 << NumLowBitsAvailable)) == 0 && diff --git a/lib/Analysis/GlobalsModRef.cpp b/lib/Analysis/GlobalsModRef.cpp index 4361e0dc9bb..11005c403c1 100644 --- a/lib/Analysis/GlobalsModRef.cpp +++ b/lib/Analysis/GlobalsModRef.cpp @@ -77,7 +77,7 @@ class GlobalsAAResult::FunctionInfo { static inline AlignedMap *getFromVoidPointer(void *P) { return (AlignedMap *)P; } - enum { NumLowBitsAvailable = 3 }; + static constexpr int NumLowBitsAvailable = 3; static_assert(alignof(AlignedMap) >= (1 << NumLowBitsAvailable), "AlignedMap insufficiently aligned to have enough low bits."); }; diff --git a/unittests/ADT/PointerEmbeddedIntTest.cpp b/unittests/ADT/PointerEmbeddedIntTest.cpp index d24c8b8c75f..12096e489bc 100644 --- a/unittests/ADT/PointerEmbeddedIntTest.cpp +++ b/unittests/ADT/PointerEmbeddedIntTest.cpp @@ -17,8 +17,8 @@ TEST(PointerEmbeddedIntTest, Basic) { EXPECT_EQ(42, I); EXPECT_EQ(43, I + 1); - EXPECT_EQ(sizeof(uintptr_t) * CHAR_BIT - CHAR_BIT, - PointerLikeTypeTraits::NumLowBitsAvailable); + EXPECT_EQ((int)sizeof(uintptr_t) * CHAR_BIT - CHAR_BIT, + (int)PointerLikeTypeTraits::NumLowBitsAvailable); EXPECT_FALSE(I == J); EXPECT_TRUE(I != J); diff --git a/unittests/ADT/PointerIntPairTest.cpp b/unittests/ADT/PointerIntPairTest.cpp index 6b3a4c055c9..b8ba3e32b28 100644 --- a/unittests/ADT/PointerIntPairTest.cpp +++ b/unittests/ADT/PointerIntPairTest.cpp @@ -72,22 +72,22 @@ TEST(PointerIntPairTest, DefaultInitialize) { EXPECT_EQ(0U, Pair.getInt()); } +// In real code this would be a word-sized integer limited to 31 bits. +struct Fixnum31 { + uintptr_t Value; +}; +struct FixnumPointerTraits { + static inline void *getAsVoidPointer(Fixnum31 Num) { + return reinterpret_cast(Num.Value << NumLowBitsAvailable); + } + static inline Fixnum31 getFromVoidPointer(void *P) { + // In real code this would assert that the value is in range. + return {reinterpret_cast(P) >> NumLowBitsAvailable}; + } + static constexpr int NumLowBitsAvailable = + std::numeric_limits::digits - 31; +}; TEST(PointerIntPairTest, ManyUnusedBits) { - // In real code this would be a word-sized integer limited to 31 bits. - struct Fixnum31 { - uintptr_t Value; - }; - class FixnumPointerTraits { - public: - static inline void *getAsVoidPointer(Fixnum31 Num) { - return reinterpret_cast(Num.Value << NumLowBitsAvailable); - } - static inline Fixnum31 getFromVoidPointer(void *P) { - // In real code this would assert that the value is in range. - return { reinterpret_cast(P) >> NumLowBitsAvailable }; - } - enum { NumLowBitsAvailable = std::numeric_limits::digits - 31 }; - }; PointerIntPair pair; EXPECT_EQ((uintptr_t)0, pair.getPointer().Value); @@ -98,7 +98,7 @@ TEST(PointerIntPairTest, ManyUnusedBits) { EXPECT_TRUE(pair.getInt()); EXPECT_EQ(FixnumPointerTraits::NumLowBitsAvailable - 1, - PointerLikeTypeTraits::NumLowBitsAvailable); + (int)PointerLikeTypeTraits::NumLowBitsAvailable); static_assert( is_trivially_copyable<