[ptr-traits] Implement the base pointer traits using the actual
authorChandler Carruth <chandlerc@gmail.com>
Wed, 30 Dec 2015 04:00:24 +0000 (04:00 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Wed, 30 Dec 2015 04:00:24 +0000 (04:00 +0000)
alignment of the pointee type!

This is the culmination of the ptr-traits work. Now the compiler will
catch me if I try to use a pointer to an empty struct as a key in
a dense map or inside a PointerIntPair or PointerUnion! This is much,
much better than sometimes corrupting data (and other times working
fine) due to insufficient alignment.

It also means that we will be much more diligent about rejecting other
uses of these constructs that aren't safe.

It also means that we can now be more aggressive with the constructs
when we actually have guaranteed higher alignment without specializing
stuff. I'll be going through and cleaning up all the current overrides
of these traits which are no longer necessary.

Many thanks to Richard, David, and others who helped me get all of this
together.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256620 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/PointerLikeTypeTraits.h

index 95d735869f2045f230a37f3b1eb3e26bdfe6497a..c12d237b2796a015633305d789240850c95ebf51 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
 #define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
 
 #ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
 #define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
 
+#include "llvm/Support/AlignOf.h"
 #include "llvm/Support/DataTypes.h"
 
 namespace llvm {
 #include "llvm/Support/DataTypes.h"
 
 namespace llvm {
@@ -27,15 +28,32 @@ template <typename T> class PointerLikeTypeTraits {
   // getNumLowBitsAvailable
 };
 
   // getNumLowBitsAvailable
 };
 
+namespace detail {
+/// A tiny meta function to compute the log2 of a compile time constant.
+template <size_t N>
+struct ConstantLog2
+    : std::integral_constant<size_t, ConstantLog2<N / 2>::value + 1> {};
+template <> struct ConstantLog2<1> : std::integral_constant<size_t, 0> {};
+}
+
 // Provide PointerLikeTypeTraits for non-cvr pointers.
 // Provide PointerLikeTypeTraits for non-cvr pointers.
-template <typename T> class PointerLikeTypeTraits<T *> {
-public:
+template <typename T> struct PointerLikeTypeTraits<T *> {
   static inline void *getAsVoidPointer(T *P) { return P; }
   static inline T *getFromVoidPointer(void *P) { return static_cast<T *>(P); }
 
   static inline void *getAsVoidPointer(T *P) { return P; }
   static inline T *getFromVoidPointer(void *P) { return static_cast<T *>(P); }
 
-  /// Note, we assume here that malloc returns objects at least 4-byte aligned.
-  /// However, this may be wrong, or pointers may be from something other than
-  /// malloc.  In this case, you should specialize this template to reduce this.
+  enum {
+    NumLowBitsAvailable = detail::ConstantLog2<AlignOf<T>::Alignment>::value
+  };
+};
+
+template <> struct PointerLikeTypeTraits<void *> {
+  static inline void *getAsVoidPointer(void *P) { return P; }
+  static inline void *getFromVoidPointer(void *P) { return P; }
+
+  /// Note, we assume here that void* is related to raw malloc'ed memory and
+  /// that malloc returns objects at least 4-byte aligned. However, this may be
+  /// wrong, or pointers may be from something other than malloc. In this case,
+  /// you should specify a real typed pointer or avoid this template.
   ///
   /// All clients should use assertions to do a run-time check to ensure that
   /// this is actually true.
   ///
   /// All clients should use assertions to do a run-time check to ensure that
   /// this is actually true.