[llvm] r284738 - [Support] Put back the MSVC hack for AlignedCharArray.

Benjamin Kramer via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 20 08:53:05 PDT 2016


Author: d0k
Date: Thu Oct 20 10:53:04 2016
New Revision: 284738

URL: http://llvm.org/viewvc/llvm-project?rev=284738&view=rev
Log:
[Support] Put back the MSVC hack for AlignedCharArray.

MSVC 2015 still errors when passing an alignas'd object by value as an
argument.

Modified:
    llvm/trunk/include/llvm/Support/AlignOf.h

Modified: llvm/trunk/include/llvm/Support/AlignOf.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/AlignOf.h?rev=284738&r1=284737&r2=284738&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/AlignOf.h (original)
+++ llvm/trunk/include/llvm/Support/AlignOf.h Thu Oct 20 10:53:04 2016
@@ -23,12 +23,85 @@ namespace llvm {
 /// \brief Helper for building an aligned character array type.
 ///
 /// This template is used to explicitly build up a collection of aligned
-/// character array types.
+/// character array types. We have to build these up using a macro and explicit
+/// specialization to cope with old versions of MSVC where only an
+/// integer literal can be used to specify an alignment constraint. Once built
+/// up here, we can then begin to indirect between these using normal C++
+/// template parameters.
+
+// MSVC requires special handling here.
+#ifndef _MSC_VER
+
 template<std::size_t Alignment, std::size_t Size>
 struct AlignedCharArray {
   LLVM_ALIGNAS(Alignment) char buffer[Size];
 };
 
+#else // _MSC_VER
+
+/// \brief Create a type with an aligned char buffer.
+template<std::size_t Alignment, std::size_t Size>
+struct AlignedCharArray;
+
+// We provide special variations of this template for the most common
+// alignments because __declspec(align(...)) doesn't actually work when it is
+// a member of a by-value function argument in MSVC, even if the alignment
+// request is something reasonably like 8-byte or 16-byte. Note that we can't
+// even include the declspec with the union that forces the alignment because
+// MSVC warns on the existence of the declspec despite the union member forcing
+// proper alignment.
+
+template<std::size_t Size>
+struct AlignedCharArray<1, Size> {
+  union {
+    char aligned;
+    char buffer[Size];
+  };
+};
+
+template<std::size_t Size>
+struct AlignedCharArray<2, Size> {
+  union {
+    short aligned;
+    char buffer[Size];
+  };
+};
+
+template<std::size_t Size>
+struct AlignedCharArray<4, Size> {
+  union {
+    int aligned;
+    char buffer[Size];
+  };
+};
+
+template<std::size_t Size>
+struct AlignedCharArray<8, Size> {
+  union {
+    double aligned;
+    char buffer[Size];
+  };
+};
+
+
+// The rest of these are provided with a __declspec(align(...)) and we simply
+// can't pass them by-value as function arguments on MSVC.
+
+#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
+  template<std::size_t Size> \
+  struct AlignedCharArray<x, Size> { \
+    __declspec(align(x)) char buffer[Size]; \
+  };
+
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128)
+
+#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
+
+#endif // _MSC_VER
+
 namespace detail {
 template <typename T1,
           typename T2 = char, typename T3 = char, typename T4 = char,




More information about the llvm-commits mailing list