diff options
| author | James Y Knight <jyknight@google.com> | 2015-12-30 03:58:33 +0000 |
|---|---|---|
| committer | James Y Knight <jyknight@google.com> | 2015-12-30 03:58:33 +0000 |
| commit | 54a3b2680f5819aad6e7e619e705358874773893 (patch) | |
| tree | 21e7498fb65e0bcabca555ef6309a6238ec318d9 /clang/lib/CodeGen/CGCleanup.cpp | |
| parent | c92a9645f293471b9f2e5a7e0db14acbfc43da88 (diff) | |
| download | bcm5719-llvm-54a3b2680f5819aad6e7e619e705358874773893.tar.gz bcm5719-llvm-54a3b2680f5819aad6e7e619e705358874773893.zip | |
Fix alignment issue in CodeGenFunction::PopCleanupBlock.
It was copying an EHCleanupStack::Cleanup object into a
SmallVector<char>, 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.
llvm-svn: 256619
Diffstat (limited to 'clang/lib/CodeGen/CGCleanup.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGCleanup.cpp | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index 245d6a7e4b0..ba7dcf7de6c 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/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<char>, the + // alignment isn't sufficient. auto *CleanupSource = reinterpret_cast<char *>(Scope.getCleanupBuffer()); - SmallVector<char, 8 * sizeof(void *)> CleanupBuffer( - CleanupSource, CleanupSource + Scope.getCleanupSize()); - auto *Fn = reinterpret_cast<EHScopeStack::Cleanup *>(CleanupBuffer.data()); + llvm::AlignedCharArray<EHScopeStack::ScopeStackAlignment, 8 * sizeof(void *)> 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); + } else { + CleanupBufferHeap.reset(new char[CleanupSize]); + memcpy(CleanupBufferHeap.get(), CleanupSource, CleanupSize); + Fn = reinterpret_cast<EHScopeStack::Cleanup *>(CleanupBufferHeap.get()); + } EHScopeStack::Cleanup::Flags cleanupFlags; if (Scope.isNormalCleanup()) |

