diff options
| author | JF Bastien <jfbastien@apple.com> | 2019-02-08 01:29:17 +0000 |
|---|---|---|
| committer | JF Bastien <jfbastien@apple.com> | 2019-02-08 01:29:17 +0000 |
| commit | b347e752580961136913f7e076befd8e83d02cb7 (patch) | |
| tree | c85b1c97d26b009c9c320960df2ebdaec76589f2 /clang/lib/CodeGen/CGDecl.cpp | |
| parent | 0719b3527f5bc550d3677161ca49a0e6d462c9e1 (diff) | |
| download | bcm5719-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.cpp | 10 |
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); |

