@@ -51,8 +51,8 @@ inline unsigned combineHashValue(unsigned a, unsigned b) {
5151// / just be `void`.
5252template <typename T, typename Enable = void >
5353struct DenseMapInfo {
54- // static inline T getEmptyKey();
55- // static inline T getTombstoneKey();
54+ // static constexpr T getEmptyKey();
55+ // static constexpr T getTombstoneKey();
5656 // static unsigned getHashValue(const T &Val);
5757 // static bool isEqual(const T &LHS, const T &RHS);
5858};
@@ -70,13 +70,13 @@ struct DenseMapInfo<T*> {
7070 // "Log2MaxAlign bits of alignment");
7171 static constexpr uintptr_t Log2MaxAlign = 12 ;
7272
73- static inline T* getEmptyKey () {
73+ static constexpr T* getEmptyKey () {
7474 uintptr_t Val = static_cast <uintptr_t >(-1 );
7575 Val <<= Log2MaxAlign;
7676 return reinterpret_cast <T*>(Val);
7777 }
7878
79- static inline T* getTombstoneKey () {
79+ static constexpr T* getTombstoneKey () {
8080 uintptr_t Val = static_cast <uintptr_t >(-2 );
8181 Val <<= Log2MaxAlign;
8282 return reinterpret_cast <T*>(Val);
@@ -92,8 +92,8 @@ struct DenseMapInfo<T*> {
9292
9393// Provide DenseMapInfo for chars.
9494template <> struct DenseMapInfo <char > {
95- static inline char getEmptyKey () { return ~0 ; }
96- static inline char getTombstoneKey () { return ~0 - 1 ; }
95+ static constexpr char getEmptyKey () { return ~0 ; }
96+ static constexpr char getTombstoneKey () { return ~0 - 1 ; }
9797 static unsigned getHashValue (const char & Val) { return Val * 37U ; }
9898
9999 static bool isEqual (const char &LHS, const char &RHS) {
@@ -103,8 +103,8 @@ template<> struct DenseMapInfo<char> {
103103
104104// Provide DenseMapInfo for unsigned chars.
105105template <> struct DenseMapInfo <unsigned char > {
106- static inline unsigned char getEmptyKey () { return ~0 ; }
107- static inline unsigned char getTombstoneKey () { return ~0 - 1 ; }
106+ static constexpr unsigned char getEmptyKey () { return ~0 ; }
107+ static constexpr unsigned char getTombstoneKey () { return ~0 - 1 ; }
108108 static unsigned getHashValue (const unsigned char &Val) { return Val * 37U ; }
109109
110110 static bool isEqual (const unsigned char &LHS, const unsigned char &RHS) {
@@ -114,8 +114,8 @@ template <> struct DenseMapInfo<unsigned char> {
114114
115115// Provide DenseMapInfo for unsigned shorts.
116116template <> struct DenseMapInfo <unsigned short > {
117- static inline unsigned short getEmptyKey () { return 0xFFFF ; }
118- static inline unsigned short getTombstoneKey () { return 0xFFFF - 1 ; }
117+ static constexpr unsigned short getEmptyKey () { return 0xFFFF ; }
118+ static constexpr unsigned short getTombstoneKey () { return 0xFFFF - 1 ; }
119119 static unsigned getHashValue (const unsigned short &Val) { return Val * 37U ; }
120120
121121 static bool isEqual (const unsigned short &LHS, const unsigned short &RHS) {
@@ -125,8 +125,8 @@ template <> struct DenseMapInfo<unsigned short> {
125125
126126// Provide DenseMapInfo for unsigned ints.
127127template <> struct DenseMapInfo <unsigned > {
128- static inline unsigned getEmptyKey () { return ~0U ; }
129- static inline unsigned getTombstoneKey () { return ~0U - 1 ; }
128+ static constexpr unsigned getEmptyKey () { return ~0U ; }
129+ static constexpr unsigned getTombstoneKey () { return ~0U - 1 ; }
130130 static unsigned getHashValue (const unsigned & Val) { return Val * 37U ; }
131131
132132 static bool isEqual (const unsigned & LHS, const unsigned & RHS) {
@@ -136,8 +136,8 @@ template<> struct DenseMapInfo<unsigned> {
136136
137137// Provide DenseMapInfo for unsigned longs.
138138template <> struct DenseMapInfo <unsigned long > {
139- static inline unsigned long getEmptyKey () { return ~0UL ; }
140- static inline unsigned long getTombstoneKey () { return ~0UL - 1L ; }
139+ static constexpr unsigned long getEmptyKey () { return ~0UL ; }
140+ static constexpr unsigned long getTombstoneKey () { return ~0UL - 1L ; }
141141
142142 static unsigned getHashValue (const unsigned long & Val) {
143143 if constexpr (sizeof (Val) == 4 )
@@ -153,8 +153,8 @@ template<> struct DenseMapInfo<unsigned long> {
153153
154154// Provide DenseMapInfo for unsigned long longs.
155155template <> struct DenseMapInfo <unsigned long long > {
156- static inline unsigned long long getEmptyKey () { return ~0ULL ; }
157- static inline unsigned long long getTombstoneKey () { return ~0ULL - 1ULL ; }
156+ static constexpr unsigned long long getEmptyKey () { return ~0ULL ; }
157+ static constexpr unsigned long long getTombstoneKey () { return ~0ULL - 1ULL ; }
158158
159159 static unsigned getHashValue (const unsigned long long & Val) {
160160 return densemap::detail::mix (Val);
@@ -168,16 +168,16 @@ template<> struct DenseMapInfo<unsigned long long> {
168168
169169// Provide DenseMapInfo for shorts.
170170template <> struct DenseMapInfo <short > {
171- static inline short getEmptyKey () { return 0x7FFF ; }
172- static inline short getTombstoneKey () { return -0x7FFF - 1 ; }
171+ static constexpr short getEmptyKey () { return 0x7FFF ; }
172+ static constexpr short getTombstoneKey () { return -0x7FFF - 1 ; }
173173 static unsigned getHashValue (const short &Val) { return Val * 37U ; }
174174 static bool isEqual (const short &LHS, const short &RHS) { return LHS == RHS; }
175175};
176176
177177// Provide DenseMapInfo for ints.
178178template <> struct DenseMapInfo <int > {
179- static inline int getEmptyKey () { return 0x7fffffff ; }
180- static inline int getTombstoneKey () { return -0x7fffffff - 1 ; }
179+ static constexpr int getEmptyKey () { return 0x7fffffff ; }
180+ static constexpr int getTombstoneKey () { return -0x7fffffff - 1 ; }
181181 static unsigned getHashValue (const int & Val) { return (unsigned )(Val * 37U ); }
182182
183183 static bool isEqual (const int & LHS, const int & RHS) {
@@ -187,11 +187,11 @@ template<> struct DenseMapInfo<int> {
187187
188188// Provide DenseMapInfo for longs.
189189template <> struct DenseMapInfo <long > {
190- static inline long getEmptyKey () {
190+ static constexpr long getEmptyKey () {
191191 return (1UL << (sizeof (long ) * 8 - 1 )) - 1UL ;
192192 }
193193
194- static inline long getTombstoneKey () { return getEmptyKey () - 1L ; }
194+ static constexpr long getTombstoneKey () { return getEmptyKey () - 1L ; }
195195
196196 static unsigned getHashValue (const long & Val) {
197197 return (unsigned )(Val * 37UL );
@@ -204,8 +204,8 @@ template<> struct DenseMapInfo<long> {
204204
205205// Provide DenseMapInfo for long longs.
206206template <> struct DenseMapInfo <long long > {
207- static inline long long getEmptyKey () { return 0x7fffffffffffffffLL ; }
208- static inline long long getTombstoneKey () { return -0x7fffffffffffffffLL -1 ; }
207+ static constexpr long long getEmptyKey () { return 0x7fffffffffffffffLL ; }
208+ static constexpr long long getTombstoneKey () { return -0x7fffffffffffffffLL -1 ; }
209209
210210 static unsigned getHashValue (const long long & Val) {
211211 return (unsigned )(Val * 37ULL );
@@ -224,12 +224,12 @@ struct DenseMapInfo<std::pair<T, U>> {
224224 using FirstInfo = DenseMapInfo<T>;
225225 using SecondInfo = DenseMapInfo<U>;
226226
227- static inline Pair getEmptyKey () {
227+ static constexpr Pair getEmptyKey () {
228228 return std::make_pair (FirstInfo::getEmptyKey (),
229229 SecondInfo::getEmptyKey ());
230230 }
231231
232- static inline Pair getTombstoneKey () {
232+ static constexpr Pair getTombstoneKey () {
233233 return std::make_pair (FirstInfo::getTombstoneKey (),
234234 SecondInfo::getTombstoneKey ());
235235 }
@@ -257,11 +257,11 @@ struct DenseMapInfo<std::pair<T, U>> {
257257template <typename ... Ts> struct DenseMapInfo <std::tuple<Ts...>> {
258258 using Tuple = std::tuple<Ts...>;
259259
260- static inline Tuple getEmptyKey () {
260+ static constexpr Tuple getEmptyKey () {
261261 return Tuple (DenseMapInfo<Ts>::getEmptyKey ()...);
262262 }
263263
264- static inline Tuple getTombstoneKey () {
264+ static constexpr Tuple getTombstoneKey () {
265265 return Tuple (DenseMapInfo<Ts>::getTombstoneKey ()...);
266266 }
267267
@@ -309,10 +309,22 @@ struct DenseMapInfo<Enum, std::enable_if_t<std::is_enum_v<Enum>>> {
309309 using UnderlyingType = std::underlying_type_t <Enum>;
310310 using Info = DenseMapInfo<UnderlyingType>;
311311
312- static Enum getEmptyKey () { return static_cast <Enum>(Info::getEmptyKey ()); }
312+ // If an enum does not have a "fixed" underlying type, it may be UB to cast
313+ // some values of the underlying type to the enum. We use an "extra" constexpr
314+ // local to ensure that such UB would trigger "static assertion expression is
315+ // not an integral constant expression", rather than runtime UB.
316+ //
317+ // If you hit this error, you can fix by switching to `enum class`, or adding
318+ // an explicit underlying type (e.g. `enum X : int`) to the enum's definition.
313319
314- static Enum getTombstoneKey () {
315- return static_cast <Enum>(Info::getTombstoneKey ());
320+ static constexpr Enum getEmptyKey () {
321+ constexpr Enum V = static_cast <Enum>(Info::getEmptyKey ());
322+ return V;
323+ }
324+
325+ static constexpr Enum getTombstoneKey () {
326+ constexpr Enum V = static_cast <Enum>(Info::getTombstoneKey ());
327+ return V;
316328 }
317329
318330 static unsigned getHashValue (const Enum &Val) {
@@ -326,9 +338,9 @@ template <typename T> struct DenseMapInfo<std::optional<T>> {
326338 using Optional = std::optional<T>;
327339 using Info = DenseMapInfo<T>;
328340
329- static inline Optional getEmptyKey () { return {Info::getEmptyKey ()}; }
341+ static constexpr Optional getEmptyKey () { return {Info::getEmptyKey ()}; }
330342
331- static inline Optional getTombstoneKey () { return {Info::getTombstoneKey ()}; }
343+ static constexpr Optional getTombstoneKey () { return {Info::getTombstoneKey ()}; }
332344
333345 static unsigned getHashValue (const Optional &OptionalVal) {
334346 return detail::combineHashValue (
0 commit comments