hans updated this revision to Diff 505127.
hans added a comment.

Thanks for the review!

Added tests to cover other calls that change behavior due to this.

Please take another look.


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

https://reviews.llvm.org/D145369

Files:
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGenCXX/const-init-cxx11.cpp
  clang/test/CodeGenCXX/const-init-cxx2a.cpp
  clang/test/CodeGenCXX/init-invariant.cpp
  clang/test/CodeGenCXX/static-init.cpp

Index: clang/test/CodeGenCXX/static-init.cpp
===================================================================
--- clang/test/CodeGenCXX/static-init.cpp
+++ clang/test/CodeGenCXX/static-init.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -triple=x86_64-pc-linuxs -emit-llvm -std=c++98 -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK98 %s
 // RUN: %clang_cc1 %s -triple=x86_64-pc-linuxs -emit-llvm -std=c++11 -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK11 %s
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linuxs -emit-llvm -std=c++20 -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK20 %s
 
 // CHECK: @_ZZ1hvE1i = internal global i32 0, align 4
 // CHECK: @base_req ={{.*}} global [4 x i8] c"foo\00", align 1
@@ -7,6 +8,8 @@
 
 // CHECK: @_ZZN5test31BC1EvE1u = internal global { i8, [3 x i8] } { i8 97, [3 x i8] undef }, align 4
 
+// CHECK20: @_ZZN5test51fEvE1a = internal constant %"struct.test5::A" { i32 42 }
+
 // CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0, comdat, align 4
 // CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0, comdat, align 8{{$}}
 // CHECK: @_ZZN5test1L6getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 16
@@ -173,3 +176,18 @@
 // CHECK: define linkonce_odr noundef nonnull align 8 dereferenceable(8) ptr @_ZN5test414useStaticLocalEv()
 // CHECK: ret ptr{{.*}} @_ZZN5test414useStaticLocalEvE3obj
 }
+
+#if __cplusplus >= 202002L
+// A const object with constexpr destructor can be emitted as a constant.
+namespace test5 {
+  struct A {
+    constexpr A(int x) : x_(x) {}
+    constexpr ~A() {}
+    int x_;
+  };
+  const int *f() {
+    static const A a{42};
+    return &a.x_;
+  }
+}
+#endif
Index: clang/test/CodeGenCXX/init-invariant.cpp
===================================================================
--- clang/test/CodeGenCXX/init-invariant.cpp
+++ clang/test/CodeGenCXX/init-invariant.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm %s -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK-O0
-// RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm %s -O1 -disable-llvm-passes -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i686-linux-gnu -std=c++20 -emit-llvm %s -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK-O0
+// RUN: %clang_cc1 -triple i686-linux-gnu -std=c++20 -emit-llvm %s -O1 -disable-llvm-passes -o - | FileCheck %s
 
 // Check that we add an llvm.invariant.start.p0i8 to mark when a global becomes
 // read-only. If globalopt can fold the initializer, it will then mark the
@@ -16,6 +16,16 @@
 // CHECK: @a ={{.*}} global {{.*}} zeroinitializer
 extern const A a = A();
 
+struct A2 {
+  A2();
+  constexpr ~A2() {}
+  int n;
+};
+
+// CHECK: @a2 ={{.*}} global {{.*}} zeroinitializer
+extern const A2 a2 = A2();
+
+
 struct B {
   B();
   mutable int n;
@@ -44,6 +54,9 @@
 // CHECK: call void @_ZN1AC1Ev(ptr noundef {{[^,]*}} @a)
 // CHECK: call {{.*}}@llvm.invariant.start.p0(i64 4, ptr @a)
 
+// CHECK: call void @_ZN2A2C1Ev(ptr noundef {{[^,]*}} @a2)
+// CHECK: call {{.*}}@llvm.invariant.start.p0(i64 4, ptr @a2)
+
 // CHECK: call void @_ZN1BC1Ev(ptr noundef {{[^,]*}} @b)
 // CHECK-NOT: call {{.*}}@llvm.invariant.start.p0(i64 noundef 4, ptr @b)
 
Index: clang/test/CodeGenCXX/const-init-cxx2a.cpp
===================================================================
--- clang/test/CodeGenCXX/const-init-cxx2a.cpp
+++ clang/test/CodeGenCXX/const-init-cxx2a.cpp
@@ -11,10 +11,10 @@
   constexpr ~B() { n *= 5; }
   int n = 123;
 };
-// CHECK: @b ={{.*}} global {{.*}} i32 123
+// CHECK: @b ={{.*}} constant {{.*}} i32 123
 extern constexpr B b = B();
 
-// CHECK: @_ZL1c = internal global {{.*}} i32 123
+// CHECK: @_ZL1c = internal constant {{.*}} i32 123
 const B c;
 int use_c() { return c.n; }
 
Index: clang/test/CodeGenCXX/const-init-cxx11.cpp
===================================================================
--- clang/test/CodeGenCXX/const-init-cxx11.cpp
+++ clang/test/CodeGenCXX/const-init-cxx11.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -no-opaque-pointers -w -fmerge-all-constants -triple x86_64-elf-gnu -emit-llvm -o - %s -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 -no-opaque-pointers -w -fmerge-all-constants -triple x86_64-elf-gnu -emit-llvm -o - %s -std=c++20 | FileCheck -check-prefix=CHECK20 %s
 
 // FIXME: The padding in all these objects should be zero-initialized.
 namespace StructUnion {
@@ -424,6 +425,7 @@
 // CHECK: @_ZGRN39ClassTemplateWithHiddenStaticDataMember1SIvE1aE_ = linkonce_odr hidden constant i32 5, comdat
 // CHECK: @_ZN39ClassTemplateWithHiddenStaticDataMember3useE ={{.*}} constant i32* @_ZGRN39ClassTemplateWithHiddenStaticDataMember1SIvE1aE_
 // CHECK: @_ZGRZN20InlineStaticConstRef3funEvE1i_ = linkonce_odr constant i32 10, comdat
+// CHECK20: @_ZZN12LocalVarInit4dtorEvE1a = internal constant {{.*}} i32 103
 
 // Constant initialization tests go before this point,
 // dynamic initialization tests go after.
@@ -483,6 +485,14 @@
   // CHECK-NOT: ret i32 103
   // CHECK: }
   int mutable_() { constexpr Mutable a = { f(103) }; return a.k; }
+
+#if __cplusplus >= 202002L
+  // CHECK20: define {{.*}} @_ZN12LocalVarInit4dtorEv
+  // CHECK20-NOT: call
+  // CHECK20: ret i32 103
+  struct Dtor { constexpr Dtor(int n) : k(n) {} constexpr ~Dtor() {} int k; };
+  int dtor() { constexpr Dtor a = { f(103) }; return a.k; }
+#endif
 }
 
 namespace CrossFuncLabelDiff {
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -4340,7 +4340,8 @@
     if (const CXXRecordDecl *Record
           = Context.getBaseElementType(Ty)->getAsCXXRecordDecl())
       return ExcludeCtor && !Record->hasMutableFields() &&
-             Record->hasTrivialDestructor();
+             (Record->hasTrivialDestructor() ||
+              Record->hasConstexprDestructor());
   }
 
   return true;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to