[PATCH] D61280: Variable auto-init: don't initialize aggregate padding of all aggregates

JF Bastien via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 29 14:13:52 PDT 2019


jfb created this revision.
jfb added reviewers: glider, pcc, kcc.
Herald added subscribers: cfe-commits, dexonsmith, jkorous.
Herald added a project: clang.

C guarantees that brace-init with fewer initializers than members in the
aggregate will initialize the rest of the aggregate as-if it were static
initialization. In turn static initialization guarantees that padding is
initialized to zero bits.

rdar://problem/50188861


Repository:
  rC Clang

https://reviews.llvm.org/D61280

Files:
  lib/CodeGen/CGDecl.cpp
  test/CodeGen/padding-init.c


Index: test/CodeGen/padding-init.c
===================================================================
--- /dev/null
+++ test/CodeGen/padding-init.c
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s
+
+// C guarantees that brace-init with fewer initializers than members in the
+// aggregate will initialize the rest of the aggregate as-if it were static
+// initialization. In turn static initialization guarantees that padding is
+// initialized to zero bits.
+
+// CHECK: @__const.partial_init.s = private unnamed_addr constant { i8, [7 x i8], i64 } { i8 42, [7 x i8] zeroinitializer, i64 0 }, align 8
+
+// Technically, we could initialize this padding to non-zero because all of the
+// struct's members have initializers.
+
+// CHECK: @__const.init_all.s = private unnamed_addr constant { i8, [7 x i8], i64 } { i8 42, [7 x i8] zeroinitializer, i64 -2401053089374216531 }, align 8
+
+struct S {
+  char c;
+  long long l;
+};
+
+void use(struct S*);
+
+// CHECK-LABEL: @empty_braces(
+// CHECK:       %s = alloca
+// CHECK-NEXT:  %[[B:[0-9+]]] = bitcast %struct.S* %s to i8*
+// CHECK-NEXT:  call void @llvm.memset{{.*}}(i8* align 8 %[[B]], i8 0,
+// CHECK-NEXT:  call void @use(%struct.S* %s)
+void empty_braces() {
+  struct S s = {};
+  return use(&s);
+}
+
+// CHECK-LABEL: @partial_init(
+// CHECK:       %s = alloca
+// CHECK-NEXT:  %[[B:[0-9+]]] = bitcast %struct.S* %s to i8*
+// CHECK-NEXT:  call void @llvm.memcpy{{.*}}(i8* align 8 %[[B]], {{.*}}@__const.partial_init.s
+// CHECK-NEXT:  call void @use(%struct.S* %s)
+void partial_init() {
+  struct S s = { .c = 42 };
+  return use(&s);
+}
+
+// CHECK-LABEL: @init_all(
+// CHECK:       %s = alloca
+// CHECK-NEXT:  %[[B:[0-9+]]] = bitcast %struct.S* %s to i8*
+// CHECK-NEXT:  call void @llvm.memcpy{{.*}}(i8* align 8 %[[B]], {{.*}}@__const.init_all.s
+// CHECK-NEXT:  call void @use(%struct.S* %s)
+void init_all() {
+  struct S s = { .c = 42, .l = 0xdeadbeefc0fedead };
+  return use(&s);
+}
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -1787,13 +1787,20 @@
       D.isUsableInConstantExpressions(getContext())) {
     assert(!capturedByInit && "constant init contains a capturing block?");
     constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D);
-    if (constant && trivialAutoVarInit !=
-                        LangOptions::TrivialAutoVarInitKind::Uninitialized) {
+    if (constant && !constant->isZeroValue() &&
+        (trivialAutoVarInit !=
+         LangOptions::TrivialAutoVarInitKind::Uninitialized)) {
       IsPattern isPattern =
           (trivialAutoVarInit == LangOptions::TrivialAutoVarInitKind::Pattern)
               ? IsPattern::Yes
               : IsPattern::No;
-      constant = constWithPadding(CGM, isPattern,
+      // C guarantees that brace-init with fewer initializers than members in
+      // the aggregate will initialize the rest of the aggregate as-if it were
+      // static initialization. In turn static initialization guarantees that
+      // padding is initialized to zero bits. We could instead pattern-init if D
+      // has any ImplicitValueInitExpr, but that seems to be unintuitive
+      // behavior.
+      constant = constWithPadding(CGM, IsPattern::No,
                                   replaceUndef(CGM, isPattern, constant));
     }
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D61280.197188.patch
Type: text/x-patch
Size: 3590 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190429/ff286449/attachment-0001.bin>


More information about the cfe-commits mailing list