diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index 698fd9da5ced1..005f2610ef9dd 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -120,7 +120,7 @@ namespace clang { /// A C++ access specifier (public, private, protected), plus the /// special value "none" which means different things in different contexts. - enum AccessSpecifier { + enum AccessSpecifier : uint8_t { AS_public, AS_protected, AS_private, diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h index b850223c953da..9d8fd893540a3 100644 --- a/llvm/include/llvm/ADT/DenseMapInfo.h +++ b/llvm/include/llvm/ADT/DenseMapInfo.h @@ -51,10 +51,10 @@ inline unsigned combineHashValue(unsigned a, unsigned b) { /// just be `void`. template struct DenseMapInfo { - //static inline T getEmptyKey(); - //static inline T getTombstoneKey(); - //static unsigned getHashValue(const T &Val); - //static bool isEqual(const T &LHS, const T &RHS); + // static constexpr T getEmptyKey(); + // static constexpr T getTombstoneKey(); + // static unsigned getHashValue(const T &Val); + // static bool isEqual(const T &LHS, const T &RHS); }; // Provide DenseMapInfo for all pointers. Come up with sentinel pointer values @@ -70,13 +70,13 @@ struct DenseMapInfo { // "Log2MaxAlign bits of alignment"); static constexpr uintptr_t Log2MaxAlign = 12; - static inline T* getEmptyKey() { + static constexpr T *getEmptyKey() { uintptr_t Val = static_cast(-1); Val <<= Log2MaxAlign; return reinterpret_cast(Val); } - static inline T* getTombstoneKey() { + static constexpr T *getTombstoneKey() { uintptr_t Val = static_cast(-2); Val <<= Log2MaxAlign; return reinterpret_cast(Val); @@ -92,8 +92,8 @@ struct DenseMapInfo { // Provide DenseMapInfo for chars. template<> struct DenseMapInfo { - static inline char getEmptyKey() { return ~0; } - static inline char getTombstoneKey() { return ~0 - 1; } + static constexpr char getEmptyKey() { return ~0; } + static constexpr char getTombstoneKey() { return ~0 - 1; } static unsigned getHashValue(const char& Val) { return Val * 37U; } static bool isEqual(const char &LHS, const char &RHS) { @@ -103,8 +103,8 @@ template<> struct DenseMapInfo { // Provide DenseMapInfo for unsigned chars. template <> struct DenseMapInfo { - static inline unsigned char getEmptyKey() { return ~0; } - static inline unsigned char getTombstoneKey() { return ~0 - 1; } + static constexpr unsigned char getEmptyKey() { return ~0; } + static constexpr unsigned char getTombstoneKey() { return ~0 - 1; } static unsigned getHashValue(const unsigned char &Val) { return Val * 37U; } static bool isEqual(const unsigned char &LHS, const unsigned char &RHS) { @@ -114,8 +114,8 @@ template <> struct DenseMapInfo { // Provide DenseMapInfo for unsigned shorts. template <> struct DenseMapInfo { - static inline unsigned short getEmptyKey() { return 0xFFFF; } - static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; } + static constexpr unsigned short getEmptyKey() { return 0xFFFF; } + static constexpr unsigned short getTombstoneKey() { return 0xFFFF - 1; } static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; } static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) { @@ -125,8 +125,8 @@ template <> struct DenseMapInfo { // Provide DenseMapInfo for unsigned ints. template<> struct DenseMapInfo { - static inline unsigned getEmptyKey() { return ~0U; } - static inline unsigned getTombstoneKey() { return ~0U - 1; } + static constexpr unsigned getEmptyKey() { return ~0U; } + static constexpr unsigned getTombstoneKey() { return ~0U - 1; } static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } static bool isEqual(const unsigned& LHS, const unsigned& RHS) { @@ -136,8 +136,8 @@ template<> struct DenseMapInfo { // Provide DenseMapInfo for unsigned longs. template<> struct DenseMapInfo { - static inline unsigned long getEmptyKey() { return ~0UL; } - static inline unsigned long getTombstoneKey() { return ~0UL - 1L; } + static constexpr unsigned long getEmptyKey() { return ~0UL; } + static constexpr unsigned long getTombstoneKey() { return ~0UL - 1L; } static unsigned getHashValue(const unsigned long& Val) { if constexpr (sizeof(Val) == 4) @@ -153,8 +153,8 @@ template<> struct DenseMapInfo { // Provide DenseMapInfo for unsigned long longs. template<> struct DenseMapInfo { - static inline unsigned long long getEmptyKey() { return ~0ULL; } - static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; } + static constexpr unsigned long long getEmptyKey() { return ~0ULL; } + static constexpr unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; } static unsigned getHashValue(const unsigned long long& Val) { return densemap::detail::mix(Val); @@ -168,16 +168,16 @@ template<> struct DenseMapInfo { // Provide DenseMapInfo for shorts. template <> struct DenseMapInfo { - static inline short getEmptyKey() { return 0x7FFF; } - static inline short getTombstoneKey() { return -0x7FFF - 1; } + static constexpr short getEmptyKey() { return 0x7FFF; } + static constexpr short getTombstoneKey() { return -0x7FFF - 1; } static unsigned getHashValue(const short &Val) { return Val * 37U; } static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; } }; // Provide DenseMapInfo for ints. template<> struct DenseMapInfo { - static inline int getEmptyKey() { return 0x7fffffff; } - static inline int getTombstoneKey() { return -0x7fffffff - 1; } + static constexpr int getEmptyKey() { return 0x7fffffff; } + static constexpr int getTombstoneKey() { return -0x7fffffff - 1; } static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); } static bool isEqual(const int& LHS, const int& RHS) { @@ -187,11 +187,11 @@ template<> struct DenseMapInfo { // Provide DenseMapInfo for longs. template<> struct DenseMapInfo { - static inline long getEmptyKey() { + static constexpr long getEmptyKey() { return (1UL << (sizeof(long) * 8 - 1)) - 1UL; } - static inline long getTombstoneKey() { return getEmptyKey() - 1L; } + static constexpr long getTombstoneKey() { return getEmptyKey() - 1L; } static unsigned getHashValue(const long& Val) { return (unsigned)(Val * 37UL); @@ -204,8 +204,10 @@ template<> struct DenseMapInfo { // Provide DenseMapInfo for long longs. template<> struct DenseMapInfo { - static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } - static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } + static constexpr long long getEmptyKey() { return 0x7fffffffffffffffLL; } + static constexpr long long getTombstoneKey() { + return -0x7fffffffffffffffLL - 1; + } static unsigned getHashValue(const long long& Val) { return (unsigned)(Val * 37ULL); @@ -224,12 +226,12 @@ struct DenseMapInfo> { using FirstInfo = DenseMapInfo; using SecondInfo = DenseMapInfo; - static inline Pair getEmptyKey() { + static constexpr Pair getEmptyKey() { return std::make_pair(FirstInfo::getEmptyKey(), SecondInfo::getEmptyKey()); } - static inline Pair getTombstoneKey() { + static constexpr Pair getTombstoneKey() { return std::make_pair(FirstInfo::getTombstoneKey(), SecondInfo::getTombstoneKey()); } @@ -257,11 +259,11 @@ struct DenseMapInfo> { template struct DenseMapInfo> { using Tuple = std::tuple; - static inline Tuple getEmptyKey() { + static constexpr Tuple getEmptyKey() { return Tuple(DenseMapInfo::getEmptyKey()...); } - static inline Tuple getTombstoneKey() { + static constexpr Tuple getTombstoneKey() { return Tuple(DenseMapInfo::getTombstoneKey()...); } @@ -309,10 +311,22 @@ struct DenseMapInfo>> { using UnderlyingType = std::underlying_type_t; using Info = DenseMapInfo; - static Enum getEmptyKey() { return static_cast(Info::getEmptyKey()); } + // If an enum does not have a "fixed" underlying type, it may be UB to cast + // some values of the underlying type to the enum. We use an "extra" constexpr + // local to ensure that such UB would trigger "static assertion expression is + // not an integral constant expression", rather than runtime UB. + // + // If you hit this error, you can fix by switching to `enum class`, or adding + // an explicit underlying type (e.g. `enum X : int`) to the enum's definition. + + static constexpr Enum getEmptyKey() { + constexpr Enum V = static_cast(Info::getEmptyKey()); + return V; + } - static Enum getTombstoneKey() { - return static_cast(Info::getTombstoneKey()); + static constexpr Enum getTombstoneKey() { + constexpr Enum V = static_cast(Info::getTombstoneKey()); + return V; } static unsigned getHashValue(const Enum &Val) { @@ -326,9 +340,11 @@ template struct DenseMapInfo> { using Optional = std::optional; using Info = DenseMapInfo; - static inline Optional getEmptyKey() { return {Info::getEmptyKey()}; } + static constexpr Optional getEmptyKey() { return {Info::getEmptyKey()}; } - static inline Optional getTombstoneKey() { return {Info::getTombstoneKey()}; } + static constexpr Optional getTombstoneKey() { + return {Info::getTombstoneKey()}; + } static unsigned getHashValue(const Optional &OptionalVal) { return detail::combineHashValue(