summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGDecl.cpp
diff options
context:
space:
mode:
authorJF Bastien <jfbastien@apple.com>2019-02-08 01:29:17 +0000
committerJF Bastien <jfbastien@apple.com>2019-02-08 01:29:17 +0000
commitb347e752580961136913f7e076befd8e83d02cb7 (patch)
treec85b1c97d26b009c9c320960df2ebdaec76589f2 /clang/lib/CodeGen/CGDecl.cpp
parent0719b3527f5bc550d3677161ca49a0e6d462c9e1 (diff)
downloadbcm5719-llvm-b347e752580961136913f7e076befd8e83d02cb7.tar.gz
bcm5719-llvm-b347e752580961136913f7e076befd8e83d02cb7.zip
Variable auto-init: fix __block initialization
Summary: Automatic initialization [1] of __block variables was trampling over the block's headers after they'd been initialized, which caused self-init usage to crash, such as here: typedef struct XYZ { void (^block)(); } *xyz_t; __attribute__((noinline)) xyz_t create(void (^block)()) { xyz_t myself = malloc(sizeof(struct XYZ)); myself->block = block; return myself; } int main() { __block xyz_t captured = create(^(){ (void)captured; }); } This type of code shouldn't be broken by variable auto-init, even if it's sketchy. [1] With -ftrivial-auto-var-init=pattern <rdar://problem/47798396> Reviewers: rjmccall, pcc, kcc Subscribers: jkorous, dexonsmith, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D57797 llvm-svn: 353495
Diffstat (limited to 'clang/lib/CodeGen/CGDecl.cpp')
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp10
1 files changed, 7 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index f91fb010a79..734aa7e2c33 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1633,11 +1633,15 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
? LangOptions::TrivialAutoVarInitKind::Uninitialized
: getContext().getLangOpts().getTrivialAutoVarInit()));
- auto initializeWhatIsTechnicallyUninitialized = [&]() {
+ auto initializeWhatIsTechnicallyUninitialized = [&](Address Loc) {
if (trivialAutoVarInit ==
LangOptions::TrivialAutoVarInitKind::Uninitialized)
return;
+ // Only initialize a __block's storage: we always initialize the header.
+ if (emission.IsEscapingByRef)
+ Loc = emitBlockByrefAddress(Loc, &D, /*follow=*/false);
+
CharUnits Size = getContext().getTypeSizeInChars(type);
if (!Size.isZero()) {
switch (trivialAutoVarInit) {
@@ -1714,7 +1718,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
};
if (isTrivialInitializer(Init)) {
- initializeWhatIsTechnicallyUninitialized();
+ initializeWhatIsTechnicallyUninitialized(Loc);
return;
}
@@ -1728,7 +1732,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
}
if (!constant) {
- initializeWhatIsTechnicallyUninitialized();
+ initializeWhatIsTechnicallyUninitialized(Loc);
LValue lv = MakeAddrLValue(Loc, type);
lv.setNonGC(true);
return EmitExprAsInit(Init, &D, lv, capturedByInit);
OpenPOWER on IntegriCloud