From: James Y Knight Date: Wed, 30 Dec 2015 03:58:33 +0000 (+0000) Subject: Fix alignment issue in CodeGenFunction::PopCleanupBlock. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9559085cc9d1fce0685cdf325b46ae2d0c8dbb3e;p=clang Fix alignment issue in CodeGenFunction::PopCleanupBlock. It was copying an EHCleanupStack::Cleanup object into a SmallVector, with a comment saying that SmallVector's alignment is always large enough. Unfortunately, that isn't actually true after r162331 in 2012. Expand the code (somewhat distastefully) to get a stack allocation with a correct alignment. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@256619 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp index 245d6a7e4b..ba7dcf7de6 100644 --- a/lib/CodeGen/CGCleanup.cpp +++ b/lib/CodeGen/CGCleanup.cpp @@ -676,13 +676,25 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { return; } - // Copy the cleanup emission data out. Note that SmallVector - // guarantees maximal alignment for its buffer regardless of its - // type parameter. + // Copy the cleanup emission data out. This uses either a stack + // array or malloc'd memory, depending on the size, which is + // behavior that SmallVector would provide, if we could use it + // here. Unfortunately, if you ask for a SmallVector, the + // alignment isn't sufficient. auto *CleanupSource = reinterpret_cast(Scope.getCleanupBuffer()); - SmallVector CleanupBuffer( - CleanupSource, CleanupSource + Scope.getCleanupSize()); - auto *Fn = reinterpret_cast(CleanupBuffer.data()); + llvm::AlignedCharArray CleanupBufferStack; + std::unique_ptr CleanupBufferHeap; + size_t CleanupSize = Scope.getCleanupSize(); + EHScopeStack::Cleanup *Fn; + + if (CleanupSize <= sizeof(CleanupBufferStack)) { + memcpy(CleanupBufferStack.buffer, CleanupSource, CleanupSize); + Fn = reinterpret_cast(CleanupBufferStack.buffer); + } else { + CleanupBufferHeap.reset(new char[CleanupSize]); + memcpy(CleanupBufferHeap.get(), CleanupSource, CleanupSize); + Fn = reinterpret_cast(CleanupBufferHeap.get()); + } EHScopeStack::Cleanup::Flags cleanupFlags; if (Scope.isNormalCleanup())