@@ -51,10 +51,10 @@ 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();
56- // static unsigned getHashValue(const T &Val);
57- // static bool isEqual(const T &LHS, const T &RHS);
54+ // static constexpr T getEmptyKey();
55+ // static constexpr T getTombstoneKey();
56+ // static unsigned getHashValue(const T &Val);
57+ // static bool isEqual(const T &LHS, const T &RHS);
5858};
5959
6060// Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
@@ -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,10 @@ 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 () {
209+ return -0x7fffffffffffffffLL - 1 ;
210+ }
209211
210212 static unsigned getHashValue (const long long & Val) {
211213 return (unsigned )(Val * 37ULL );
@@ -224,12 +226,12 @@ struct DenseMapInfo<std::pair<T, U>> {
224226 using FirstInfo = DenseMapInfo<T>;
225227 using SecondInfo = DenseMapInfo<U>;
226228
227- static inline Pair getEmptyKey () {
229+ static constexpr Pair getEmptyKey () {
228230 return std::make_pair (FirstInfo::getEmptyKey (),
229231 SecondInfo::getEmptyKey ());
230232 }
231233
232- static inline Pair getTombstoneKey () {
234+ static constexpr Pair getTombstoneKey () {
233235 return std::make_pair (FirstInfo::getTombstoneKey (),
234236 SecondInfo::getTombstoneKey ());
235237 }
@@ -257,11 +259,11 @@ struct DenseMapInfo<std::pair<T, U>> {
257259template <typename ... Ts> struct DenseMapInfo <std::tuple<Ts...>> {
258260 using Tuple = std::tuple<Ts...>;
259261
260- static inline Tuple getEmptyKey () {
262+ static constexpr Tuple getEmptyKey () {
261263 return Tuple (DenseMapInfo<Ts>::getEmptyKey ()...);
262264 }
263265
264- static inline Tuple getTombstoneKey () {
266+ static constexpr Tuple getTombstoneKey () {
265267 return Tuple (DenseMapInfo<Ts>::getTombstoneKey ()...);
266268 }
267269
@@ -309,10 +311,22 @@ struct DenseMapInfo<Enum, std::enable_if_t<std::is_enum_v<Enum>>> {
309311 using UnderlyingType = std::underlying_type_t <Enum>;
310312 using Info = DenseMapInfo<UnderlyingType>;
311313
312- static Enum getEmptyKey () { return static_cast <Enum>(Info::getEmptyKey ()); }
314+ // If an enum does not have a "fixed" underlying type, it may be UB to cast
315+ // some values of the underlying type to the enum. We use an "extra" constexpr
316+ // local to ensure that such UB would trigger "static assertion expression is
317+ // not an integral constant expression", rather than runtime UB.
318+ //
319+ // If you hit this error, you can fix by switching to `enum class`, or adding
320+ // an explicit underlying type (e.g. `enum X : int`) to the enum's definition.
321+
322+ static constexpr Enum getEmptyKey () {
323+ constexpr Enum V = static_cast <Enum>(Info::getEmptyKey ());
324+ return V;
325+ }
313326
314- static Enum getTombstoneKey () {
315- return static_cast <Enum>(Info::getTombstoneKey ());
327+ static constexpr Enum getTombstoneKey () {
328+ constexpr Enum V = static_cast <Enum>(Info::getTombstoneKey ());
329+ return V;
316330 }
317331
318332 static unsigned getHashValue (const Enum &Val) {
@@ -326,9 +340,11 @@ template <typename T> struct DenseMapInfo<std::optional<T>> {
326340 using Optional = std::optional<T>;
327341 using Info = DenseMapInfo<T>;
328342
329- static inline Optional getEmptyKey () { return {Info::getEmptyKey ()}; }
343+ static constexpr Optional getEmptyKey () { return {Info::getEmptyKey ()}; }
330344
331- static inline Optional getTombstoneKey () { return {Info::getTombstoneKey ()}; }
345+ static constexpr Optional getTombstoneKey () {
346+ return {Info::getTombstoneKey ()};
347+ }
332348
333349 static unsigned getHashValue (const Optional &OptionalVal) {
334350 return detail::combineHashValue (
0 commit comments