[llvm-branch-commits] [cfe-branch] r353807 - Merging r353495:

Hans Wennborg via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Feb 12 00:35:38 PST 2019


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(




More information about the llvm-branch-commits mailing list