serge-sans-paille updated this revision to Diff 541475.
serge-sans-paille added a comment.

switch from cascading ternary operator to cascading if for readability.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D155580/new/

https://reviews.llvm.org/D155580

Files:
  clang/lib/CodeGen/CGDecl.cpp
  clang/test/CodeGenCXX/auto-var-init-empty-class.cpp
  clang/test/CodeGenCXX/auto-var-init.cpp

Index: clang/test/CodeGenCXX/auto-var-init.cpp
===================================================================
--- clang/test/CodeGenCXX/auto-var-init.cpp
+++ clang/test/CodeGenCXX/auto-var-init.cpp
@@ -43,9 +43,6 @@
 // PATTERN-NOT: undef
 // ZERO-NOT: undef
 
-// PATTERN-O0: @__const.test_empty_uninit.uninit = private unnamed_addr constant %struct.empty { i8 [[I8]] }, align 1
-// PATTERN-O1-NOT: @__const.test_empty_uninit.uninit
-struct empty {};
 // PATTERN-O0: @__const.test_small_uninit.uninit = private unnamed_addr constant %struct.small { i8 [[I8]] }, align 1
 // PATTERN-O0: @__const.test_small_custom.custom = private unnamed_addr constant %struct.small { i8 42 }, align 1
 // ZERO-O0: @__const.test_small_custom.custom = private unnamed_addr constant %struct.small { i8 42 }, align 1
@@ -586,24 +583,6 @@
 // CHECK-NOT:   !annotation
 // CHECK-NEXT:  call void @{{.*}}used{{.*}}%braces)
 
-TEST_UNINIT(empty, empty);
-// CHECK-LABEL: @test_empty_uninit()
-// CHECK:       %uninit = alloca %struct.empty, align
-// CHECK-NEXT:  call void @{{.*}}used{{.*}}%uninit)
-// PATTERN-LABEL: @test_empty_uninit()
-// PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_empty_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]]
-// PATTERN-O1: store i8 [[I8]], {{.*}} align 1, !annotation [[AUTO_INIT]]
-// ZERO-LABEL: @test_empty_uninit()
-// ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]]
-// ZERO-O1: store i8 0, {{.*}} align 1, !annotation [[AUTO_INIT]]
-
-TEST_BRACES(empty, empty);
-// CHECK-LABEL: @test_empty_braces()
-// CHECK:       %braces = alloca %struct.empty, align
-// CHECK-NEXT:  call void @llvm.memcpy
-// CHECK-NOT:   !annotation
-// CHECK-NEXT:  call void @{{.*}}used{{.*}}%braces)
-
 TEST_UNINIT(small, small);
 // CHECK-LABEL: @test_small_uninit()
 // CHECK:       %uninit = alloca %struct.small, align
Index: clang/test/CodeGenCXX/auto-var-init-empty-class.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/auto-var-init-empty-class.cpp
@@ -0,0 +1,18 @@
+// 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++ empty classes still take some memory, but there is no need to initialize
+// it has it cannot be accessed. This matches GCC behavior.
+
+struct S {
+};
+
+extern "C" void use(struct S*);
+
+// CHECK-LABEL: @empty_class(
+// CHECK:       %s = alloca
+// CHECK-NEXT:  call void @use(ptr noundef %s)
+extern "C" void empty_class(void) {
+  S s;
+  return use(&s);
+}
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -1855,6 +1855,13 @@
   }
 }
 
+static bool isEmptyClass(VarDecl const &D) {
+  const Type *Ty = D.getType().getTypePtr();
+  if (const auto *CxxRecordTy = Ty->getAsCXXRecordDecl())
+    return CxxRecordTy->isEmpty();
+  return false;
+}
+
 void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
   assert(emission.Variable && "emission was not valid!");
 
@@ -1902,13 +1909,18 @@
   const Address Loc =
       locIsByrefHeader ? emission.getObjectAddress(*this) : emission.Addr;
 
-  // Note: constexpr already initializes everything correctly.
-  LangOptions::TrivialAutoVarInitKind trivialAutoVarInit =
-      (D.isConstexpr()
-           ? LangOptions::TrivialAutoVarInitKind::Uninitialized
-           : (D.getAttr<UninitializedAttr>()
-                  ? LangOptions::TrivialAutoVarInitKind::Uninitialized
-                  : getContext().getLangOpts().getTrivialAutoVarInit()));
+  LangOptions::TrivialAutoVarInitKind trivialAutoVarInit;
+  if (D.isConstexpr())
+    // Constexpr already initializes everything correctly.
+    trivialAutoVarInit = LangOptions::TrivialAutoVarInitKind::Uninitialized;
+  else if (D.getAttr<UninitializedAttr>())
+    trivialAutoVarInit = LangOptions::TrivialAutoVarInitKind::Uninitialized;
+  else if (isEmptyClass(D))
+    // Empty classes still use a byte, but it's ok not to initialize it as
+    // it cannot be legitimately accessed.
+    trivialAutoVarInit = LangOptions::TrivialAutoVarInitKind::Uninitialized;
+  else
+    trivialAutoVarInit = getContext().getLangOpts().getTrivialAutoVarInit();
 
   auto initializeWhatIsTechnicallyUninitialized = [&](Address Loc) {
     if (trivialAutoVarInit ==
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to