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