jfb created this revision.
jfb added a reviewer: chandlerc.
Herald added subscribers: llvm-commits, lldb-commits, cfe-commits, dexonsmith, 
jkorous, hiraditya, javed.absar.
Herald added projects: clang, LLDB, LLVM.
jfb added a comment.

This is the main event: https://reviews.llvm.org/D65249#change-IWk6CtRl45h6
The rest is side-show.


Two things in this patch:

- Use std::aligned_storage instead of AlignedCharArray. Note: template 
parameters are swapped.
- Use variadic templates in the implementation of AlignedCharArrayUnion.

The other files are changed accordingly:

- Use std::aligned_storage.
- The buffer is no longer implicitly a character array, requiring casting in 
some cases.

This should be fine since our current minimum MSVC version is now Visual Studio
2017 version 15.0.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65249

Files:
  clang/include/clang/AST/APValue.h
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/AST/Expr.h
  clang/include/clang/Sema/Overload.h
  clang/lib/AST/APValue.cpp
  clang/lib/CodeGen/CGCleanup.cpp
  clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
  clang/lib/Frontend/PrecompiledPreamble.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/TypeLocBuilder.cpp
  clang/lib/Sema/TypeLocBuilder.h
  lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
  lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
  llvm/include/llvm/ADT/DenseMap.h
  llvm/include/llvm/ADT/IntervalMap.h
  llvm/include/llvm/CodeGen/DIE.h
  llvm/include/llvm/Support/AlignOf.h
  llvm/include/llvm/Support/Endian.h
  llvm/include/llvm/Support/Error.h
  llvm/include/llvm/Support/ErrorOr.h
  llvm/include/llvm/Support/JSON.h
  llvm/include/llvm/Support/TrailingObjects.h
  llvm/lib/Support/JSON.cpp
  llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
  llvm/unittests/Support/AlignOfTest.cpp

Index: llvm/unittests/Support/AlignOfTest.cpp
===================================================================
--- llvm/unittests/Support/AlignOfTest.cpp
+++ llvm/unittests/Support/AlignOfTest.cpp
@@ -233,16 +233,5 @@
 #ifndef _MSC_VER
   EXPECT_EQ(sizeof(V8), sizeof(AlignedCharArrayUnion<V8>));
 #endif
-
-  EXPECT_EQ(1u, (alignof(AlignedCharArray<1, 1>)));
-  EXPECT_EQ(2u, (alignof(AlignedCharArray<2, 1>)));
-  EXPECT_EQ(4u, (alignof(AlignedCharArray<4, 1>)));
-  EXPECT_EQ(8u, (alignof(AlignedCharArray<8, 1>)));
-  EXPECT_EQ(16u, (alignof(AlignedCharArray<16, 1>)));
-
-  EXPECT_EQ(1u, sizeof(AlignedCharArray<1, 1>));
-  EXPECT_EQ(7u, sizeof(AlignedCharArray<1, 7>));
-  EXPECT_EQ(2u, sizeof(AlignedCharArray<2, 2>));
-  EXPECT_EQ(16u, sizeof(AlignedCharArray<2, 16>));
 }
 } // end anonymous namespace
Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -81,11 +81,13 @@
   private:
     bool insaneIntVal(int V) { return V > 4 || V < -4; }
 
-    APFloat *getFpValPtr()
-      { return reinterpret_cast<APFloat *>(&FpValBuf.buffer[0]); }
+    APFloat *getFpValPtr() {
+      return reinterpret_cast<APFloat *>(&FpValBuf.buffer);
+    }
 
-    const APFloat *getFpValPtr() const
-      { return reinterpret_cast<const APFloat *>(&FpValBuf.buffer[0]); }
+    const APFloat *getFpValPtr() const {
+      return reinterpret_cast<const APFloat *>(&FpValBuf.buffer);
+    }
 
     const APFloat &getFpVal() const {
       assert(IsFp && BufHasFpVal && "Incorret state");
Index: llvm/lib/Support/JSON.cpp
===================================================================
--- llvm/lib/Support/JSON.cpp
+++ llvm/lib/Support/JSON.cpp
@@ -106,7 +106,7 @@
   case T_Boolean:
   case T_Double:
   case T_Integer:
-    memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer));
+    memcpy(&Union.buffer, &M.Union.buffer, sizeof(Union.buffer));
     break;
   case T_StringRef:
     create<StringRef>(M.as<StringRef>());
@@ -130,7 +130,7 @@
   case T_Boolean:
   case T_Double:
   case T_Integer:
-    memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer));
+    memcpy(&Union.buffer, &M.Union.buffer, sizeof(Union.buffer));
     break;
   case T_StringRef:
     create<StringRef>(M.as<StringRef>());
Index: llvm/include/llvm/Support/TrailingObjects.h
===================================================================
--- llvm/include/llvm/Support/TrailingObjects.h
+++ llvm/include/llvm/Support/TrailingObjects.h
@@ -369,7 +369,7 @@
   template <typename... Tys> struct FixedSizeStorage {
     template <size_t... Counts> struct with_counts {
       enum { Size = totalSizeToAlloc<Tys...>(Counts...) };
-      typedef llvm::AlignedCharArray<alignof(BaseTy), Size> type;
+      using type = typename std::aligned_storage<Size, alignof(BaseTy)>::type;
     };
   };
 
Index: llvm/include/llvm/Support/JSON.h
===================================================================
--- llvm/include/llvm/Support/JSON.h
+++ llvm/include/llvm/Support/JSON.h
@@ -451,12 +451,12 @@
   friend class Object;
 
   template <typename T, typename... U> void create(U &&... V) {
-    new (reinterpret_cast<T *>(Union.buffer)) T(std::forward<U>(V)...);
+    new (reinterpret_cast<T *>(&Union.buffer)) T(std::forward<U>(V)...);
   }
   template <typename T> T &as() const {
     // Using this two-step static_cast via void * instead of reinterpret_cast
     // silences a -Wstrict-aliasing false positive from GCC6 and earlier.
-    void *Storage = static_cast<void *>(Union.buffer);
+    void *Storage = static_cast<void *>(&Union.buffer);
     return *static_cast<T *>(Storage);
   }
 
Index: llvm/include/llvm/Support/ErrorOr.h
===================================================================
--- llvm/include/llvm/Support/ErrorOr.h
+++ llvm/include/llvm/Support/ErrorOr.h
@@ -241,17 +241,17 @@
 
   storage_type *getStorage() {
     assert(!HasError && "Cannot get value when an error exists!");
-    return reinterpret_cast<storage_type*>(TStorage.buffer);
+    return reinterpret_cast<storage_type *>(&TStorage.buffer);
   }
 
   const storage_type *getStorage() const {
     assert(!HasError && "Cannot get value when an error exists!");
-    return reinterpret_cast<const storage_type*>(TStorage.buffer);
+    return reinterpret_cast<const storage_type *>(&TStorage.buffer);
   }
 
   std::error_code *getErrorStorage() {
     assert(HasError && "Cannot get error when a value exists!");
-    return reinterpret_cast<std::error_code *>(ErrorStorage.buffer);
+    return reinterpret_cast<std::error_code *>(&ErrorStorage.buffer);
   }
 
   const std::error_code *getErrorStorage() const {
Index: llvm/include/llvm/Support/Error.h
===================================================================
--- llvm/include/llvm/Support/Error.h
+++ llvm/include/llvm/Support/Error.h
@@ -624,22 +624,22 @@
 
   storage_type *getStorage() {
     assert(!HasError && "Cannot get value when an error exists!");
-    return reinterpret_cast<storage_type *>(TStorage.buffer);
+    return reinterpret_cast<storage_type *>(&TStorage.buffer);
   }
 
   const storage_type *getStorage() const {
     assert(!HasError && "Cannot get value when an error exists!");
-    return reinterpret_cast<const storage_type *>(TStorage.buffer);
+    return reinterpret_cast<const storage_type *>(&TStorage.buffer);
   }
 
   error_type *getErrorStorage() {
     assert(HasError && "Cannot get error when a value exists!");
-    return reinterpret_cast<error_type *>(ErrorStorage.buffer);
+    return reinterpret_cast<error_type *>(&ErrorStorage.buffer);
   }
 
   const error_type *getErrorStorage() const {
     assert(HasError && "Cannot get error when a value exists!");
-    return reinterpret_cast<const error_type *>(ErrorStorage.buffer);
+    return reinterpret_cast<const error_type *>(&ErrorStorage.buffer);
   }
 
   // Used by ExpectedAsOutParameter to reset the checked flag.
Index: llvm/include/llvm/Support/Endian.h
===================================================================
--- llvm/include/llvm/Support/Endian.h
+++ llvm/include/llvm/Support/Endian.h
@@ -216,13 +216,11 @@
   explicit packed_endian_specific_integral(value_type val) { *this = val; }
 
   operator value_type() const {
-    return endian::read<value_type, endian, alignment>(
-      (const void*)Value.buffer);
+    return endian::read<value_type, endian, alignment>((const void *)&Value);
   }
 
   void operator=(value_type newValue) {
-    endian::write<value_type, endian, alignment>(
-      (void*)Value.buffer, newValue);
+    endian::write<value_type, endian, alignment>((void *)&Value, newValue);
   }
 
   packed_endian_specific_integral &operator+=(value_type newValue) {
@@ -246,8 +244,9 @@
   }
 
 private:
-  AlignedCharArray<PickAlignment<value_type, alignment>::value,
-                   sizeof(value_type)> Value;
+  typename std::aligned_storage<
+      sizeof(value_type), PickAlignment<value_type, alignment>::value>::type
+      Value;
 
 public:
   struct ref {
Index: llvm/include/llvm/Support/AlignOf.h
===================================================================
--- llvm/include/llvm/Support/AlignOf.h
+++ llvm/include/llvm/Support/AlignOf.h
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file defines the AlignedCharArray and AlignedCharArrayUnion classes.
+// This file defines the AlignedCharArrayUnion classes.
 //
 //===----------------------------------------------------------------------===//
 
@@ -15,130 +15,42 @@
 
 #include "llvm/Support/Compiler.h"
 #include <cstddef>
+#include <type_traits>
 
 namespace llvm {
 
-/// \struct AlignedCharArray
-/// Helper for building an aligned character array type.
-///
-/// This template is used to explicitly build up a collection of aligned
-/// character array types. We have to build these up using a macro and explicit
-/// specialization to cope with MSVC (at least till 2015) 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 {
-  alignas(Alignment) char buffer[Size];
-};
-
-#else // _MSC_VER
-
-/// 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];
-  };
-};
+namespace detail {
+template <typename T, typename... Ts> class AlignerImpl {
+  T t;
+  AlignerImpl<Ts...> rest;
 
-template<std::size_t Size>
-struct AlignedCharArray<8, Size> {
-  union {
-    double aligned;
-    char buffer[Size];
-  };
+  AlignerImpl() = delete;
 };
 
-
-// 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,
-          typename T5 = char, typename T6 = char, typename T7 = char,
-          typename T8 = char, typename T9 = char, typename T10 = char>
-class AlignerImpl {
-  T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10;
+template <typename T> class AlignerImpl<T> {
+  T t;
 
   AlignerImpl() = delete;
 };
 
-template <typename T1,
-          typename T2 = char, typename T3 = char, typename T4 = char,
-          typename T5 = char, typename T6 = char, typename T7 = char,
-          typename T8 = char, typename T9 = char, typename T10 = char>
-union SizerImpl {
-  char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)],
-       arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)],
-       arr9[sizeof(T9)], arr10[sizeof(T10)];
+template <typename T, typename... Ts> union SizerImpl {
+  char arr[sizeof(T)];
+  SizerImpl<Ts...> rest;
 };
+
+template <typename T> union SizerImpl<T> { char arr[sizeof(T)]; };
 } // end namespace detail
 
-/// This union template exposes a suitably aligned and sized character
-/// array member which can hold elements of any of up to ten types.
+/// A suitably aligned and sized character array member which can hold elements
+/// of any type.
 ///
-/// These types may be arrays, structs, or any other types. The goal is to
-/// expose a char array buffer member which can be used as suitable storage for
-/// a placement new of any of these types. Support for more than ten types can
-/// be added at the cost of more boilerplate.
-template <typename T1,
-          typename T2 = char, typename T3 = char, typename T4 = char,
-          typename T5 = char, typename T6 = char, typename T7 = char,
-          typename T8 = char, typename T9 = char, typename T10 = char>
-struct AlignedCharArrayUnion : llvm::AlignedCharArray<
-    alignof(llvm::detail::AlignerImpl<T1, T2, T3, T4, T5,
-                                      T6, T7, T8, T9, T10>),
-    sizeof(::llvm::detail::SizerImpl<T1, T2, T3, T4, T5,
-                                     T6, T7, T8, T9, T10>)> {
+/// These types may be arrays, structs, or any other types. This exposes a
+/// `buffer` member which can be used as suitable storage for a placement new of
+/// any of these types.
+template <typename T, typename... Ts> struct AlignedCharArrayUnion {
+  typename std::aligned_storage<
+      sizeof(llvm::detail::SizerImpl<T, Ts...>),
+      alignof(::llvm::detail::AlignerImpl<T, Ts...>)>::type buffer;
 };
 } // end namespace llvm
 
Index: llvm/include/llvm/CodeGen/DIE.h
===================================================================
--- llvm/include/llvm/CodeGen/DIE.h
+++ llvm/include/llvm/CodeGen/DIE.h
@@ -382,12 +382,12 @@
     static_assert(std::is_standard_layout<T>::value ||
                       std::is_pointer<T>::value,
                   "Expected standard layout or pointer");
-    new (reinterpret_cast<void *>(Val.buffer)) T(V);
+    new (reinterpret_cast<void *>(&Val.buffer)) T(V);
   }
 
-  template <class T> T *get() { return reinterpret_cast<T *>(Val.buffer); }
+  template <class T> T *get() { return reinterpret_cast<T *>(&Val.buffer); }
   template <class T> const T *get() const {
-    return reinterpret_cast<const T *>(Val.buffer);
+    return reinterpret_cast<const T *>(&Val.buffer);
   }
   template <class T> void destruct() { get<T>()->~T(); }
 
Index: llvm/include/llvm/ADT/IntervalMap.h
===================================================================
--- llvm/include/llvm/ADT/IntervalMap.h
+++ llvm/include/llvm/ADT/IntervalMap.h
@@ -981,7 +981,8 @@
   /// Represent data as a node type without breaking aliasing rules.
   template <typename T>
   T &dataAs() const {
-    return *bit_cast<T *>(const_cast<char *>(data.buffer));
+    return *bit_cast<T *>(
+        const_cast<char *>(reinterpret_cast<const char *>(&data.buffer)));
   }
 
   const RootLeaf &rootLeaf() const {
@@ -1040,7 +1041,7 @@
 
 public:
   explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) {
-    assert((uintptr_t(data.buffer) & (alignof(RootLeaf) - 1)) == 0 &&
+    assert((uintptr_t(&data.buffer) & (alignof(RootLeaf) - 1)) == 0 &&
            "Insufficient alignment");
     new(&rootLeaf()) RootLeaf();
   }
Index: llvm/include/llvm/ADT/DenseMap.h
===================================================================
--- llvm/include/llvm/ADT/DenseMap.h
+++ llvm/include/llvm/ADT/DenseMap.h
@@ -1037,7 +1037,7 @@
 
       // First move the inline buckets into a temporary storage.
       AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage;
-      BucketT *TmpBegin = reinterpret_cast<BucketT *>(TmpStorage.buffer);
+      BucketT *TmpBegin = reinterpret_cast<BucketT *>(&TmpStorage.buffer);
       BucketT *TmpEnd = TmpBegin;
 
       // Loop over the buckets, moving non-empty, non-tombstones into the
@@ -1124,7 +1124,7 @@
     // Note that this cast does not violate aliasing rules as we assert that
     // the memory's dynamic type is the small, inline bucket buffer, and the
     // 'storage.buffer' static type is 'char *'.
-    return reinterpret_cast<const BucketT *>(storage.buffer);
+    return reinterpret_cast<const BucketT *>(&storage.buffer);
   }
 
   BucketT *getInlineBuckets() {
@@ -1135,7 +1135,7 @@
   const LargeRep *getLargeRep() const {
     assert(!Small);
     // Note, same rule about aliasing as with getInlineBuckets.
-    return reinterpret_cast<const LargeRep *>(storage.buffer);
+    return reinterpret_cast<const LargeRep *>(&storage.buffer);
   }
 
   LargeRep *getLargeRep() {
Index: lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
+++ lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
@@ -73,7 +73,7 @@
   };
 
   struct VReg {
-    llvm::AlignedCharArray<16, 16> bytes;
+    std::aligned_storage<16, 16>::type bytes;
   };
 
   // mirrors <mach/arm/thread_status.h> arm_neon_state64_t
Index: lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -424,7 +424,7 @@
   case fpu_v29:
   case fpu_v30:
   case fpu_v31:
-    value.SetBytes(fpu.v[reg - fpu_v0].bytes.buffer, reg_info->byte_size,
+    value.SetBytes(&fpu.v[reg - fpu_v0].bytes.buffer, reg_info->byte_size,
                    endian::InlHostByteOrder());
     break;
 
@@ -616,7 +616,7 @@
   case fpu_v29:
   case fpu_v30:
   case fpu_v31:
-    ::memcpy(fpu.v[reg - fpu_v0].bytes.buffer, value.GetBytes(),
+    ::memcpy(&fpu.v[reg - fpu_v0].bytes.buffer, value.GetBytes(),
              value.GetByteSize());
     break;
 
Index: clang/lib/Sema/TypeLocBuilder.h
===================================================================
--- clang/lib/Sema/TypeLocBuilder.h
+++ clang/lib/Sema/TypeLocBuilder.h
@@ -39,19 +39,18 @@
 
   /// The inline buffer.
   enum { BufferMaxAlignment = alignof(void *) };
-  llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;
+  std::aligned_storage<InlineCapacity, BufferMaxAlignment>::type InlineBuffer;
   unsigned NumBytesAtAlign4, NumBytesAtAlign8;
 
  public:
-  TypeLocBuilder()
-    : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity),
-      Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0)
-  {
-  }
-
-  ~TypeLocBuilder() {
-    if (Buffer != InlineBuffer.buffer)
-      delete[] Buffer;
+   TypeLocBuilder()
+       : Buffer(reinterpret_cast<char *>(&InlineBuffer)),
+         Capacity(InlineCapacity), Index(InlineCapacity), NumBytesAtAlign4(0),
+         NumBytesAtAlign8(0) {}
+
+   ~TypeLocBuilder() {
+     if (Buffer != reinterpret_cast<char *>(&InlineBuffer))
+       delete[] Buffer;
   }
 
   /// Ensures that this buffer has at least as much capacity as described.
Index: clang/lib/Sema/TypeLocBuilder.cpp
===================================================================
--- clang/lib/Sema/TypeLocBuilder.cpp
+++ clang/lib/Sema/TypeLocBuilder.cpp
@@ -51,7 +51,7 @@
          &Buffer[Index],
          Capacity - Index);
 
-  if (Buffer != InlineBuffer.buffer)
+  if (Buffer != reinterpret_cast<char *>(&InlineBuffer))
     delete[] Buffer;
 
   Buffer = NewBuffer;
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -7052,10 +7052,10 @@
   // allocator).
   QualType CallResultType = ConversionType.getNonLValueExprType(Context);
 
-  llvm::AlignedCharArray<alignof(CallExpr), sizeof(CallExpr) + sizeof(Stmt *)>
-      Buffer;
+  std::aligned_storage<sizeof(CallExpr) + sizeof(Stmt *),
+                       alignof(CallExpr)>::type Buffer;
   CallExpr *TheTemporaryCall = CallExpr::CreateTemporary(
-      Buffer.buffer, &ConversionFn, CallResultType, VK, From->getBeginLoc());
+      &Buffer, &ConversionFn, CallResultType, VK, From->getBeginLoc());
 
   ImplicitConversionSequence ICS =
       TryCopyInitialization(*this, TheTemporaryCall, ToType,
Index: clang/lib/Frontend/PrecompiledPreamble.cpp
===================================================================
--- clang/lib/Frontend/PrecompiledPreamble.cpp
+++ clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -637,7 +637,7 @@
 
 PrecompiledPreamble::TempPCHFile &PrecompiledPreamble::PCHStorage::asFile() {
   assert(getKind() == Kind::TempFile);
-  return *reinterpret_cast<TempPCHFile *>(Storage.buffer);
+  return *reinterpret_cast<TempPCHFile *>(&Storage.buffer);
 }
 
 const PrecompiledPreamble::TempPCHFile &
@@ -648,7 +648,7 @@
 PrecompiledPreamble::InMemoryPreamble &
 PrecompiledPreamble::PCHStorage::asMemory() {
   assert(getKind() == Kind::InMemory);
-  return *reinterpret_cast<InMemoryPreamble *>(Storage.buffer);
+  return *reinterpret_cast<InMemoryPreamble *>(&Storage.buffer);
 }
 
 const PrecompiledPreamble::InMemoryPreamble &
Index: clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
===================================================================
--- clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
+++ clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
@@ -184,10 +184,9 @@
   // the inotify file descriptor should have the same alignment as
   // struct inotify_event.
 
-  auto ManagedBuffer =
-      llvm::make_unique<llvm::AlignedCharArray<alignof(struct inotify_event),
-                                               EventBufferLength>>();
-  char *const Buf = ManagedBuffer->buffer;
+  auto ManagedBuffer = llvm::make_unique<std::aligned_storage<
+      EventBufferLength, alignof(struct inotify_event)>::type>();
+  char *const Buf = ManagedBuffer.get();
 
   const int EpollFD = epoll_create1(EPOLL_CLOEXEC);
   if (EpollFD == -1) {
@@ -350,4 +349,4 @@
   return llvm::make_unique<DirectoryWatcherLinux>(
       Path, Receiver, WaitForInitialSync, InotifyFD, InotifyWD,
       std::move(*InotifyPollingStopper));
-}
\ No newline at end of file
+}
Index: clang/lib/CodeGen/CGCleanup.cpp
===================================================================
--- clang/lib/CodeGen/CGCleanup.cpp
+++ clang/lib/CodeGen/CGCleanup.cpp
@@ -740,14 +740,16 @@
   // here. Unfortunately, if you ask for a SmallVector<char>, the
   // alignment isn't sufficient.
   auto *CleanupSource = reinterpret_cast<char *>(Scope.getCleanupBuffer());
-  llvm::AlignedCharArray<EHScopeStack::ScopeStackAlignment, 8 * sizeof(void *)> CleanupBufferStack;
+  std::aligned_storage<8 * sizeof(void *),
+                       EHScopeStack::ScopeStackAlignment>::type
+      CleanupBufferStack;
   std::unique_ptr<char[]> CleanupBufferHeap;
   size_t CleanupSize = Scope.getCleanupSize();
   EHScopeStack::Cleanup *Fn;
 
   if (CleanupSize <= sizeof(CleanupBufferStack)) {
-    memcpy(CleanupBufferStack.buffer, CleanupSource, CleanupSize);
-    Fn = reinterpret_cast<EHScopeStack::Cleanup *>(CleanupBufferStack.buffer);
+    memcpy(&CleanupBufferStack, CleanupSource, CleanupSize);
+    Fn = reinterpret_cast<EHScopeStack::Cleanup *>(&CleanupBufferStack);
   } else {
     CleanupBufferHeap.reset(new char[CleanupSize]);
     memcpy(CleanupBufferHeap.get(), CleanupSource, CleanupSize);
Index: clang/lib/AST/APValue.cpp
===================================================================
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -240,7 +240,7 @@
   }
   case Vector:
     MakeVector();
-    setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts,
+    setVector(((const Vec *)(const char *)&RHS.Data.buffer)->Elts,
               RHS.getVectorLength());
     break;
   case ComplexInt:
@@ -292,29 +292,29 @@
 
 void APValue::DestroyDataAndMakeUninit() {
   if (Kind == Int)
-    ((APSInt*)(char*)Data.buffer)->~APSInt();
+    ((APSInt *)(char *)&Data.buffer)->~APSInt();
   else if (Kind == Float)
-    ((APFloat*)(char*)Data.buffer)->~APFloat();
+    ((APFloat *)(char *)&Data.buffer)->~APFloat();
   else if (Kind == FixedPoint)
-    ((APFixedPoint *)(char *)Data.buffer)->~APFixedPoint();
+    ((APFixedPoint *)(char *)&Data.buffer)->~APFixedPoint();
   else if (Kind == Vector)
-    ((Vec*)(char*)Data.buffer)->~Vec();
+    ((Vec *)(char *)&Data.buffer)->~Vec();
   else if (Kind == ComplexInt)
-    ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt();
+    ((ComplexAPSInt *)(char *)&Data.buffer)->~ComplexAPSInt();
   else if (Kind == ComplexFloat)
-    ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat();
+    ((ComplexAPFloat *)(char *)&Data.buffer)->~ComplexAPFloat();
   else if (Kind == LValue)
-    ((LV*)(char*)Data.buffer)->~LV();
+    ((LV *)(char *)&Data.buffer)->~LV();
   else if (Kind == Array)
-    ((Arr*)(char*)Data.buffer)->~Arr();
+    ((Arr *)(char *)&Data.buffer)->~Arr();
   else if (Kind == Struct)
-    ((StructData*)(char*)Data.buffer)->~StructData();
+    ((StructData *)(char *)&Data.buffer)->~StructData();
   else if (Kind == Union)
-    ((UnionData*)(char*)Data.buffer)->~UnionData();
+    ((UnionData *)(char *)&Data.buffer)->~UnionData();
   else if (Kind == MemberPointer)
-    ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData();
+    ((MemberPointerData *)(char *)&Data.buffer)->~MemberPointerData();
   else if (Kind == AddrLabelDiff)
-    ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData();
+    ((AddrLabelDiffData *)(char *)&Data.buffer)->~AddrLabelDiffData();
   Kind = None;
 }
 
@@ -348,9 +348,9 @@
            "same size.");
     return getComplexIntReal().needsCleanup();
   case LValue:
-    return reinterpret_cast<const LV *>(Data.buffer)->hasPathPtr();
+    return reinterpret_cast<const LV *>(&Data.buffer)->hasPathPtr();
   case MemberPointer:
-    return reinterpret_cast<const MemberPointerData *>(Data.buffer)
+    return reinterpret_cast<const MemberPointerData *>(&Data.buffer)
         ->hasPathPtr();
   }
   llvm_unreachable("Unknown APValue kind!");
@@ -359,9 +359,9 @@
 void APValue::swap(APValue &RHS) {
   std::swap(Kind, RHS.Kind);
   char TmpData[DataSize];
-  memcpy(TmpData, Data.buffer, DataSize);
-  memcpy(Data.buffer, RHS.Data.buffer, DataSize);
-  memcpy(RHS.Data.buffer, TmpData, DataSize);
+  memcpy(TmpData, &Data.buffer, DataSize);
+  memcpy(&Data.buffer, &RHS.Data.buffer, DataSize);
+  memcpy(&RHS.Data.buffer, TmpData, DataSize);
 }
 
 LLVM_DUMP_METHOD void APValue::dump() const {
@@ -706,49 +706,49 @@
 
 const APValue::LValueBase APValue::getLValueBase() const {
   assert(isLValue() && "Invalid accessor");
-  return ((const LV*)(const void*)Data.buffer)->Base;
+  return ((const LV *)(const void *)&Data.buffer)->Base;
 }
 
 bool APValue::isLValueOnePastTheEnd() const {
   assert(isLValue() && "Invalid accessor");
-  return ((const LV*)(const void*)Data.buffer)->IsOnePastTheEnd;
+  return ((const LV *)(const void *)&Data.buffer)->IsOnePastTheEnd;
 }
 
 CharUnits &APValue::getLValueOffset() {
   assert(isLValue() && "Invalid accessor");
-  return ((LV*)(void*)Data.buffer)->Offset;
+  return ((LV *)(void *)&Data.buffer)->Offset;
 }
 
 bool APValue::hasLValuePath() const {
   assert(isLValue() && "Invalid accessor");
-  return ((const LV*)(const char*)Data.buffer)->hasPath();
+  return ((const LV *)(const char *)&Data.buffer)->hasPath();
 }
 
 ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
   assert(isLValue() && hasLValuePath() && "Invalid accessor");
-  const LV &LVal = *((const LV*)(const char*)Data.buffer);
+  const LV &LVal = *((const LV *)(const char *)&Data.buffer);
   return llvm::makeArrayRef(LVal.getPath(), LVal.PathLength);
 }
 
 unsigned APValue::getLValueCallIndex() const {
   assert(isLValue() && "Invalid accessor");
-  return ((const LV*)(const char*)Data.buffer)->Base.getCallIndex();
+  return ((const LV *)(const char *)&Data.buffer)->Base.getCallIndex();
 }
 
 unsigned APValue::getLValueVersion() const {
   assert(isLValue() && "Invalid accessor");
-  return ((const LV*)(const char*)Data.buffer)->Base.getVersion();
+  return ((const LV *)(const char *)&Data.buffer)->Base.getVersion();
 }
 
 bool APValue::isNullPointer() const {
   assert(isLValue() && "Invalid usage");
-  return ((const LV*)(const char*)Data.buffer)->IsNullPtr;
+  return ((const LV *)(const char *)&Data.buffer)->IsNullPtr;
 }
 
 void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
                         bool IsNullPtr) {
   assert(isLValue() && "Invalid accessor");
-  LV &LVal = *((LV*)(char*)Data.buffer);
+  LV &LVal = *((LV *)(char *)&Data.buffer);
   LVal.Base = B;
   LVal.IsOnePastTheEnd = false;
   LVal.Offset = O;
@@ -760,7 +760,7 @@
                         ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
                         bool IsNullPtr) {
   assert(isLValue() && "Invalid accessor");
-  LV &LVal = *((LV*)(char*)Data.buffer);
+  LV &LVal = *((LV *)(char *)&Data.buffer);
   LVal.Base = B;
   LVal.IsOnePastTheEnd = IsOnePastTheEnd;
   LVal.Offset = O;
@@ -772,41 +772,41 @@
 const ValueDecl *APValue::getMemberPointerDecl() const {
   assert(isMemberPointer() && "Invalid accessor");
   const MemberPointerData &MPD =
-      *((const MemberPointerData *)(const char *)Data.buffer);
+      *((const MemberPointerData *)(const char *)&Data.buffer);
   return MPD.MemberAndIsDerivedMember.getPointer();
 }
 
 bool APValue::isMemberPointerToDerivedMember() const {
   assert(isMemberPointer() && "Invalid accessor");
   const MemberPointerData &MPD =
-      *((const MemberPointerData *)(const char *)Data.buffer);
+      *((const MemberPointerData *)(const char *)&Data.buffer);
   return MPD.MemberAndIsDerivedMember.getInt();
 }
 
 ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const {
   assert(isMemberPointer() && "Invalid accessor");
   const MemberPointerData &MPD =
-      *((const MemberPointerData *)(const char *)Data.buffer);
+      *((const MemberPointerData *)(const char *)&Data.buffer);
   return llvm::makeArrayRef(MPD.getPath(), MPD.PathLength);
 }
 
 void APValue::MakeLValue() {
   assert(isAbsent() && "Bad state change");
   static_assert(sizeof(LV) <= DataSize, "LV too big");
-  new ((void*)(char*)Data.buffer) LV();
+  new ((void *)(char *)&Data.buffer) LV();
   Kind = LValue;
 }
 
 void APValue::MakeArray(unsigned InitElts, unsigned Size) {
   assert(isAbsent() && "Bad state change");
-  new ((void*)(char*)Data.buffer) Arr(InitElts, Size);
+  new ((void *)(char *)&Data.buffer) Arr(InitElts, Size);
   Kind = Array;
 }
 
 void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
                                 ArrayRef<const CXXRecordDecl*> Path) {
   assert(isAbsent() && "Bad state change");
-  MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData;
+  MemberPointerData *MPD = new ((void *)(char *)&Data.buffer) MemberPointerData;
   Kind = MemberPointer;
   MPD->MemberAndIsDerivedMember.setPointer(Member);
   MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
Index: clang/include/clang/Sema/Overload.h
===================================================================
--- clang/include/clang/Sema/Overload.h
+++ clang/include/clang/Sema/Overload.h
@@ -881,7 +881,7 @@
     constexpr static unsigned NumInlineBytes =
         24 * sizeof(ImplicitConversionSequence);
     unsigned NumInlineBytesUsed = 0;
-    llvm::AlignedCharArray<alignof(void *), NumInlineBytes> InlineSpace;
+    std::aligned_storage<NumInlineBytes, alignof(void *)>::type InlineSpace;
 
     // Address space of the object being constructed.
     LangAS DestAS = LangAS::Default;
@@ -904,7 +904,8 @@
       unsigned NBytes = sizeof(T) * N;
       if (NBytes > NumInlineBytes - NumInlineBytesUsed)
         return SlabAllocator.Allocate<T>(N);
-      char *FreeSpaceStart = InlineSpace.buffer + NumInlineBytesUsed;
+      char *FreeSpaceStart =
+          reinterpret_cast<char *>(&InlineSpace) + NumInlineBytesUsed;
       assert(uintptr_t(FreeSpaceStart) % alignof(void *) == 0 &&
              "Misaligned storage!");
 
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -2619,9 +2619,9 @@
   /// + sizeof(Stmt *) bytes of storage, aligned to alignof(CallExpr):
   ///
   /// \code{.cpp}
-  ///   llvm::AlignedCharArray<alignof(CallExpr),
-  ///                          sizeof(CallExpr) + sizeof(Stmt *)> Buffer;
-  ///   CallExpr *TheCall = CallExpr::CreateTemporary(Buffer.buffer, etc);
+  ///   std::aligned_storage<sizeof(CallExpr) + sizeof(Stmt *),
+  ///                        alignof(CallExpr)>::type Buffer;
+  ///   CallExpr *TheCall = CallExpr::CreateTemporary(Buffer, etc);
   /// \endcode
   static CallExpr *CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
                                    ExprValueKind VK, SourceLocation RParenLoc,
Index: clang/include/clang/AST/ASTTypeTraits.h
===================================================================
--- clang/include/clang/AST/ASTTypeTraits.h
+++ clang/include/clang/AST/ASTTypeTraits.h
@@ -249,7 +249,7 @@
   /// use the pointer outside the scope of the DynTypedNode.
   template <typename T>
   const T *get() const {
-    return BaseConverter<T>::get(NodeKind, Storage.buffer);
+    return BaseConverter<T>::get(NodeKind, (const char *)&Storage.buffer);
   }
 
   /// Retrieve the stored node as type \c T.
@@ -257,7 +257,8 @@
   /// Similar to \c get(), but asserts that the type is what we are expecting.
   template <typename T>
   const T &getUnchecked() const {
-    return BaseConverter<T>::getUnchecked(NodeKind, Storage.buffer);
+    return BaseConverter<T>::getUnchecked(NodeKind,
+                                          (const char *)&Storage.buffer);
   }
 
   ASTNodeKind getNodeKind() const { return NodeKind; }
@@ -269,7 +270,7 @@
   /// method returns NULL.
   const void *getMemoizationData() const {
     return NodeKind.hasPointerIdentity()
-               ? *reinterpret_cast<void *const *>(Storage.buffer)
+               ? *reinterpret_cast<void *const *>(&Storage.buffer)
                : nullptr;
   }
 
@@ -404,7 +405,7 @@
     static DynTypedNode create(const BaseT &Node) {
       DynTypedNode Result;
       Result.NodeKind = ASTNodeKind::getFromNode(Node);
-      new (Result.Storage.buffer) const void *(&Node);
+      new (&Result.Storage.buffer) const void *(&Node);
       return Result;
     }
   };
@@ -424,7 +425,7 @@
     static DynTypedNode create(const T &Node) {
       DynTypedNode Result;
       Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
-      new (Result.Storage.buffer) const void *(&Node);
+      new (&Result.Storage.buffer) const void *(&Node);
       return Result;
     }
   };
@@ -443,7 +444,7 @@
     static DynTypedNode create(const T &Node) {
       DynTypedNode Result;
       Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
-      new (Result.Storage.buffer) T(Node);
+      new (&Result.Storage.buffer) T(Node);
       return Result;
     }
   };
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -584,25 +584,25 @@
 
   public:
     DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
-      new (Storage.buffer) DynTypedNode(N);
+      new (&Storage.buffer) DynTypedNode(N);
     }
 
     DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
-      new (Storage.buffer) ArrayRef<DynTypedNode>(A);
+      new (&Storage.buffer) ArrayRef<DynTypedNode>(A);
     }
 
     const ast_type_traits::DynTypedNode *begin() const {
       if (!IsSingleNode)
-        return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
+        return reinterpret_cast<const ArrayRef<DynTypedNode> *>(&Storage.buffer)
             ->begin();
-      return reinterpret_cast<const DynTypedNode *>(Storage.buffer);
+      return reinterpret_cast<const DynTypedNode *>(&Storage.buffer);
     }
 
     const ast_type_traits::DynTypedNode *end() const {
       if (!IsSingleNode)
-        return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
+        return reinterpret_cast<const ArrayRef<DynTypedNode> *>(&Storage.buffer)
             ->end();
-      return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1;
+      return reinterpret_cast<const DynTypedNode *>(&Storage.buffer) + 1;
     }
 
     size_t size() const { return end() - begin(); }
Index: clang/include/clang/AST/APValue.h
===================================================================
--- clang/include/clang/AST/APValue.h
+++ clang/include/clang/AST/APValue.h
@@ -335,7 +335,7 @@
 
   APSInt &getInt() {
     assert(isInt() && "Invalid accessor");
-    return *(APSInt*)(char*)Data.buffer;
+    return *(APSInt *)(char *)&Data.buffer;
   }
   const APSInt &getInt() const {
     return const_cast<APValue*>(this)->getInt();
@@ -349,7 +349,7 @@
 
   APFloat &getFloat() {
     assert(isFloat() && "Invalid accessor");
-    return *(APFloat*)(char*)Data.buffer;
+    return *(APFloat *)(char *)&Data.buffer;
   }
   const APFloat &getFloat() const {
     return const_cast<APValue*>(this)->getFloat();
@@ -357,7 +357,7 @@
 
   APFixedPoint &getFixedPoint() {
     assert(isFixedPoint() && "Invalid accessor");
-    return *(APFixedPoint *)(char *)Data.buffer;
+    return *(APFixedPoint *)(char *)&Data.buffer;
   }
   const APFixedPoint &getFixedPoint() const {
     return const_cast<APValue *>(this)->getFixedPoint();
@@ -365,7 +365,7 @@
 
   APSInt &getComplexIntReal() {
     assert(isComplexInt() && "Invalid accessor");
-    return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
+    return ((ComplexAPSInt *)(char *)&Data.buffer)->Real;
   }
   const APSInt &getComplexIntReal() const {
     return const_cast<APValue*>(this)->getComplexIntReal();
@@ -373,7 +373,7 @@
 
   APSInt &getComplexIntImag() {
     assert(isComplexInt() && "Invalid accessor");
-    return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
+    return ((ComplexAPSInt *)(char *)&Data.buffer)->Imag;
   }
   const APSInt &getComplexIntImag() const {
     return const_cast<APValue*>(this)->getComplexIntImag();
@@ -381,7 +381,7 @@
 
   APFloat &getComplexFloatReal() {
     assert(isComplexFloat() && "Invalid accessor");
-    return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
+    return ((ComplexAPFloat *)(char *)&Data.buffer)->Real;
   }
   const APFloat &getComplexFloatReal() const {
     return const_cast<APValue*>(this)->getComplexFloatReal();
@@ -389,7 +389,7 @@
 
   APFloat &getComplexFloatImag() {
     assert(isComplexFloat() && "Invalid accessor");
-    return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
+    return ((ComplexAPFloat *)(char *)&Data.buffer)->Imag;
   }
   const APFloat &getComplexFloatImag() const {
     return const_cast<APValue*>(this)->getComplexFloatImag();
@@ -410,20 +410,20 @@
   APValue &getVectorElt(unsigned I) {
     assert(isVector() && "Invalid accessor");
     assert(I < getVectorLength() && "Index out of range");
-    return ((Vec*)(char*)Data.buffer)->Elts[I];
+    return ((Vec *)(char *)&Data.buffer)->Elts[I];
   }
   const APValue &getVectorElt(unsigned I) const {
     return const_cast<APValue*>(this)->getVectorElt(I);
   }
   unsigned getVectorLength() const {
     assert(isVector() && "Invalid accessor");
-    return ((const Vec*)(const void *)Data.buffer)->NumElts;
+    return ((const Vec *)(const void *)&Data.buffer)->NumElts;
   }
 
   APValue &getArrayInitializedElt(unsigned I) {
     assert(isArray() && "Invalid accessor");
     assert(I < getArrayInitializedElts() && "Index out of range");
-    return ((Arr*)(char*)Data.buffer)->Elts[I];
+    return ((Arr *)(char *)&Data.buffer)->Elts[I];
   }
   const APValue &getArrayInitializedElt(unsigned I) const {
     return const_cast<APValue*>(this)->getArrayInitializedElt(I);
@@ -434,35 +434,35 @@
   APValue &getArrayFiller() {
     assert(isArray() && "Invalid accessor");
     assert(hasArrayFiller() && "No array filler");
-    return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
+    return ((Arr *)(char *)&Data.buffer)->Elts[getArrayInitializedElts()];
   }
   const APValue &getArrayFiller() const {
     return const_cast<APValue*>(this)->getArrayFiller();
   }
   unsigned getArrayInitializedElts() const {
     assert(isArray() && "Invalid accessor");
-    return ((const Arr*)(const void *)Data.buffer)->NumElts;
+    return ((const Arr *)(const void *)&Data.buffer)->NumElts;
   }
   unsigned getArraySize() const {
     assert(isArray() && "Invalid accessor");
-    return ((const Arr*)(const void *)Data.buffer)->ArrSize;
+    return ((const Arr *)(const void *)&Data.buffer)->ArrSize;
   }
 
   unsigned getStructNumBases() const {
     assert(isStruct() && "Invalid accessor");
-    return ((const StructData*)(const char*)Data.buffer)->NumBases;
+    return ((const StructData *)(const char *)&Data.buffer)->NumBases;
   }
   unsigned getStructNumFields() const {
     assert(isStruct() && "Invalid accessor");
-    return ((const StructData*)(const char*)Data.buffer)->NumFields;
+    return ((const StructData *)(const char *)&Data.buffer)->NumFields;
   }
   APValue &getStructBase(unsigned i) {
     assert(isStruct() && "Invalid accessor");
-    return ((StructData*)(char*)Data.buffer)->Elts[i];
+    return ((StructData *)(char *)&Data.buffer)->Elts[i];
   }
   APValue &getStructField(unsigned i) {
     assert(isStruct() && "Invalid accessor");
-    return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
+    return ((StructData *)(char *)&Data.buffer)->Elts[getStructNumBases() + i];
   }
   const APValue &getStructBase(unsigned i) const {
     return const_cast<APValue*>(this)->getStructBase(i);
@@ -473,11 +473,11 @@
 
   const FieldDecl *getUnionField() const {
     assert(isUnion() && "Invalid accessor");
-    return ((const UnionData*)(const char*)Data.buffer)->Field;
+    return ((const UnionData *)(const char *)&Data.buffer)->Field;
   }
   APValue &getUnionValue() {
     assert(isUnion() && "Invalid accessor");
-    return *((UnionData*)(char*)Data.buffer)->Value;
+    return *((UnionData *)(char *)&Data.buffer)->Value;
   }
   const APValue &getUnionValue() const {
     return const_cast<APValue*>(this)->getUnionValue();
@@ -489,45 +489,45 @@
 
   const AddrLabelExpr* getAddrLabelDiffLHS() const {
     assert(isAddrLabelDiff() && "Invalid accessor");
-    return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
+    return ((const AddrLabelDiffData *)(const char *)&Data.buffer)->LHSExpr;
   }
   const AddrLabelExpr* getAddrLabelDiffRHS() const {
     assert(isAddrLabelDiff() && "Invalid accessor");
-    return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
+    return ((const AddrLabelDiffData *)(const char *)&Data.buffer)->RHSExpr;
   }
 
   void setInt(APSInt I) {
     assert(isInt() && "Invalid accessor");
-    *(APSInt *)(char *)Data.buffer = std::move(I);
+    *(APSInt *)(char *)&Data.buffer = std::move(I);
   }
   void setFloat(APFloat F) {
     assert(isFloat() && "Invalid accessor");
-    *(APFloat *)(char *)Data.buffer = std::move(F);
+    *(APFloat *)(char *)&Data.buffer = std::move(F);
   }
   void setFixedPoint(APFixedPoint FX) {
     assert(isFixedPoint() && "Invalid accessor");
-    *(APFixedPoint *)(char *)Data.buffer = std::move(FX);
+    *(APFixedPoint *)(char *)&Data.buffer = std::move(FX);
   }
   void setVector(const APValue *E, unsigned N) {
     assert(isVector() && "Invalid accessor");
-    ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
-    ((Vec*)(char*)Data.buffer)->NumElts = N;
+    ((Vec *)(char *)&Data.buffer)->Elts = new APValue[N];
+    ((Vec *)(char *)&Data.buffer)->NumElts = N;
     for (unsigned i = 0; i != N; ++i)
-      ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
+      ((Vec *)(char *)&Data.buffer)->Elts[i] = E[i];
   }
   void setComplexInt(APSInt R, APSInt I) {
     assert(R.getBitWidth() == I.getBitWidth() &&
            "Invalid complex int (type mismatch).");
     assert(isComplexInt() && "Invalid accessor");
-    ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R);
-    ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I);
+    ((ComplexAPSInt *)(char *)&Data.buffer)->Real = std::move(R);
+    ((ComplexAPSInt *)(char *)&Data.buffer)->Imag = std::move(I);
   }
   void setComplexFloat(APFloat R, APFloat I) {
     assert(&R.getSemantics() == &I.getSemantics() &&
            "Invalid complex float (type mismatch).");
     assert(isComplexFloat() && "Invalid accessor");
-    ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R);
-    ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
+    ((ComplexAPFloat *)(char *)&Data.buffer)->Real = std::move(R);
+    ((ComplexAPFloat *)(char *)&Data.buffer)->Imag = std::move(I);
   }
   void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
                  bool IsNullPtr);
@@ -536,13 +536,13 @@
                  bool IsNullPtr);
   void setUnion(const FieldDecl *Field, const APValue &Value) {
     assert(isUnion() && "Invalid accessor");
-    ((UnionData*)(char*)Data.buffer)->Field = Field;
-    *((UnionData*)(char*)Data.buffer)->Value = Value;
+    ((UnionData *)(char *)&Data.buffer)->Field = Field;
+    *((UnionData *)(char *)&Data.buffer)->Value = Value;
   }
   void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
                         const AddrLabelExpr* RHSExpr) {
-    ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
-    ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
+    ((AddrLabelDiffData *)(char *)&Data.buffer)->LHSExpr = LHSExpr;
+    ((AddrLabelDiffData *)(char *)&Data.buffer)->RHSExpr = RHSExpr;
   }
 
   /// Assign by swapping from a copy of the RHS.
@@ -555,51 +555,51 @@
   void DestroyDataAndMakeUninit();
   void MakeInt() {
     assert(isAbsent() && "Bad state change");
-    new ((void*)Data.buffer) APSInt(1);
+    new ((void *)&Data.buffer) APSInt(1);
     Kind = Int;
   }
   void MakeFloat() {
     assert(isAbsent() && "Bad state change");
-    new ((void*)(char*)Data.buffer) APFloat(0.0);
+    new ((void *)(char *)&Data.buffer) APFloat(0.0);
     Kind = Float;
   }
   void MakeFixedPoint(APFixedPoint &&FX) {
     assert(isAbsent() && "Bad state change");
-    new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX));
+    new ((void *)(char *)&Data.buffer) APFixedPoint(std::move(FX));
     Kind = FixedPoint;
   }
   void MakeVector() {
     assert(isAbsent() && "Bad state change");
-    new ((void*)(char*)Data.buffer) Vec();
+    new ((void *)(char *)&Data.buffer) Vec();
     Kind = Vector;
   }
   void MakeComplexInt() {
     assert(isAbsent() && "Bad state change");
-    new ((void*)(char*)Data.buffer) ComplexAPSInt();
+    new ((void *)(char *)&Data.buffer) ComplexAPSInt();
     Kind = ComplexInt;
   }
   void MakeComplexFloat() {
     assert(isAbsent() && "Bad state change");
-    new ((void*)(char*)Data.buffer) ComplexAPFloat();
+    new ((void *)(char *)&Data.buffer) ComplexAPFloat();
     Kind = ComplexFloat;
   }
   void MakeLValue();
   void MakeArray(unsigned InitElts, unsigned Size);
   void MakeStruct(unsigned B, unsigned M) {
     assert(isAbsent() && "Bad state change");
-    new ((void*)(char*)Data.buffer) StructData(B, M);
+    new ((void *)(char *)&Data.buffer) StructData(B, M);
     Kind = Struct;
   }
   void MakeUnion() {
     assert(isAbsent() && "Bad state change");
-    new ((void*)(char*)Data.buffer) UnionData();
+    new ((void *)(char *)&Data.buffer) UnionData();
     Kind = Union;
   }
   void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
                          ArrayRef<const CXXRecordDecl*> Path);
   void MakeAddrLabelDiff() {
     assert(isAbsent() && "Bad state change");
-    new ((void*)(char*)Data.buffer) AddrLabelDiffData();
+    new ((void *)(char *)&Data.buffer) AddrLabelDiffData();
     Kind = AddrLabelDiff;
   }
 };
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to