Author: hans Date: Tue Feb 12 00:35:38 2019 New Revision: 353807 URL: http://llvm.org/viewvc/llvm-project?rev=353807&view=rev Log: Merging r353495: ------------------------------------------------------------------------ r353495 | jfb | 2019-02-08 02:29:17 +0100 (Fri, 08 Feb 2019) | 32 lines
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 ------------------------------------------------------------------------ Modified: cfe/branches/release_80/ (props changed) cfe/branches/release_80/lib/CodeGen/CGDecl.cpp cfe/branches/release_80/test/CodeGenCXX/trivial-auto-var-init.cpp Propchange: cfe/branches/release_80/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Tue Feb 12 00:35:38 2019 @@ -1,4 +1,4 @@ /cfe/branches/type-system-rewrite:134693-134817 -/cfe/trunk:351334,351340,351344,351360,351457,351459,351531,351579-351580,352040,352079,352099,352102,352105,352156,352221-352222,352229,352307,352323,352463,352539,352610,352672,352822,353393 +/cfe/trunk:351334,351340,351344,351360,351457,351459,351531,351579-351580,352040,352079,352099,352102,352105,352156,352221-352222,352229,352307,352323,352463,352539,352610,352672,352822,353393,353495 /cfe/trunk/test:170344 /cfe/trunk/test/SemaTemplate:126920 Modified: cfe/branches/release_80/lib/CodeGen/CGDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_80/lib/CodeGen/CGDecl.cpp?rev=353807&r1=353806&r2=353807&view=diff ============================================================================== --- cfe/branches/release_80/lib/CodeGen/CGDecl.cpp (original) +++ cfe/branches/release_80/lib/CodeGen/CGDecl.cpp Tue Feb 12 00:35:38 2019 @@ -1631,11 +1631,15 @@ void CodeGenFunction::EmitAutoVarInit(co ? 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) { @@ -1713,7 +1717,7 @@ void CodeGenFunction::EmitAutoVarInit(co }; if (isTrivialInitializer(Init)) { - initializeWhatIsTechnicallyUninitialized(); + initializeWhatIsTechnicallyUninitialized(Loc); return; } @@ -1727,7 +1731,7 @@ void CodeGenFunction::EmitAutoVarInit(co } if (!constant) { - initializeWhatIsTechnicallyUninitialized(); + initializeWhatIsTechnicallyUninitialized(Loc); LValue lv = MakeAddrLValue(Loc, type); lv.setNonGC(true); return EmitExprAsInit(Init, &D, lv, capturedByInit); Modified: cfe/branches/release_80/test/CodeGenCXX/trivial-auto-var-init.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_80/test/CodeGenCXX/trivial-auto-var-init.cpp?rev=353807&r1=353806&r2=353807&view=diff ============================================================================== --- cfe/branches/release_80/test/CodeGenCXX/trivial-auto-var-init.cpp (original) +++ cfe/branches/release_80/test/CodeGenCXX/trivial-auto-var-init.cpp Tue Feb 12 00:35:38 2019 @@ -30,6 +30,32 @@ void test_block() { used(block); } +// Using the variable being initialized is typically UB in C, but for blocks we +// can be nice: they imply extra book-keeping and we can do the auto-init before +// any of said book-keeping. +// +// UNINIT-LABEL: test_block_self_init( +// ZERO-LABEL: test_block_self_init( +// ZERO: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8 +// ZERO: %captured1 = getelementptr inbounds %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, i32 0, i32 4 +// ZERO-NEXT: store %struct.XYZ* null, %struct.XYZ** %captured1, align 8 +// ZERO: %call = call %struct.XYZ* @create( +// PATTERN-LABEL: test_block_self_init( +// PATTERN: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8 +// PATTERN: %captured1 = getelementptr inbounds %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, i32 0, i32 4 +// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8 +// PATTERN: %call = call %struct.XYZ* @create( +void test_block_self_init() { + using Block = void (^)(); + typedef struct XYZ { + Block block; + } * xyz_t; + extern xyz_t create(Block block); + __block xyz_t captured = create(^() { + (void)captured; + }); +} + // This type of code is currently not handled by zero / pattern initialization. // The test will break when that is fixed. // UNINIT-LABEL: test_goto_unreachable_value( _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits