summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGCleanup.cpp
diff options
context:
space:
mode:
authorJames Y Knight <jyknight@google.com>2015-12-30 03:58:33 +0000
committerJames Y Knight <jyknight@google.com>2015-12-30 03:58:33 +0000
commit54a3b2680f5819aad6e7e619e705358874773893 (patch)
tree21e7498fb65e0bcabca555ef6309a6238ec318d9 /clang/lib/CodeGen/CGCleanup.cpp
parentc92a9645f293471b9f2e5a7e0db14acbfc43da88 (diff)
downloadbcm5719-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.cpp24
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())
OpenPOWER on IntegriCloud