zahiraam updated this revision to Diff 484665.
zahiraam marked an inline comment as done.
Herald added a subscriber: aheejin.

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

https://reviews.llvm.org/D137107

Files:
  clang/include/clang/Basic/DiagnosticCommonKinds.td
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/test/CodeGenCXX/PR19955.cpp
  clang/test/CodeGenCXX/aix-static-init.cpp
  clang/test/CodeGenCXX/call-conv-thru-alias.cpp
  clang/test/CodeGenCXX/const-init-cxx11.cpp
  clang/test/CodeGenCXX/ctor-dtor-alias.cpp
  clang/test/CodeGenCXX/cxx11-thread-local.cpp
  clang/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp
  clang/test/CodeGenCXX/cxx2a-thread-local-constinit.cpp
  clang/test/CodeGenCXX/dllimport.cpp
  clang/test/CodeGenCXX/dso-handle-custom.cpp
  clang/test/CodeGenCXX/funcattrs-global-ctor-dtor.cpp
  clang/test/CodeGenCXX/no_destroy.cpp
  clang/test/CodeGenCXX/non-const-init-cxx2a.cpp
  clang/test/CodeGenCXX/runtime-dllstorage.cpp
  clang/test/CodeGenCXX/static-destructor.cpp
  clang/test/CodeGenOpenCLCXX/atexit.clcpp
  clang/test/SemaCXX/PR19955.cpp
  clang/test/SemaCXX/constant-expression-cxx11.cpp
  clang/test/SemaCXX/dllimport-constexpr.cpp

Index: clang/test/SemaCXX/dllimport-constexpr.cpp
===================================================================
--- clang/test/SemaCXX/dllimport-constexpr.cpp
+++ clang/test/SemaCXX/dllimport-constexpr.cpp
@@ -40,7 +40,6 @@
 // constexpr initialization doesn't work for dllimport things.
 // expected-error@+1{{must be initialized by a constant expression}}
 constexpr void (*constexpr_import_func)() = &imported_func;
-// expected-error@+1{{must be initialized by a constant expression}}
 constexpr int *constexpr_import_int = &imported_int;
 // expected-error@+1{{must be initialized by a constant expression}}
 constexpr void (Foo::*constexpr_memptr)() = &Foo::imported_method;
@@ -60,3 +59,11 @@
   // expected-note@+1 {{requested here}}
   StaticConstexpr<imported_func>::g_fp();
 }
+
+extern int __declspec(dllimport) val;
+constexpr int& val_ref = val;
+
+void assigndllimporttoconst () {
+  extern int _declspec(dllimport) val;
+  constexpr int& val_ref = val;
+}
Index: clang/test/SemaCXX/constant-expression-cxx11.cpp
===================================================================
--- clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1595,7 +1595,7 @@
   void f(int k) { // expected-note {{here}}
     int arr[k]; // expected-warning {{C99}} expected-note {{function parameter 'k'}}
     constexpr int n = 1 +
-        sizeof(arr) // expected-error {{constant expression}}
+        sizeof(arr) // expected-error{{constexpr variable 'n' must be initialized by a constant expression}}
         * 3;
   }
 }
Index: clang/test/SemaCXX/PR19955.cpp
===================================================================
--- clang/test/SemaCXX/PR19955.cpp
+++ clang/test/SemaCXX/PR19955.cpp
@@ -2,7 +2,7 @@
 // RUN: %clang_cc1 -triple i686-mingw32 -verify -std=c++11 %s
 
 extern int __attribute__((dllimport)) var;
-constexpr int *varp = &var; // expected-error {{must be initialized by a constant expression}}
+constexpr int *varp = &var;
 
 extern __attribute__((dllimport)) void fun();
 constexpr void (*funp)(void) = &fun; // expected-error {{must be initialized by a constant expression}}
Index: clang/test/CodeGenOpenCLCXX/atexit.clcpp
===================================================================
--- clang/test/CodeGenOpenCLCXX/atexit.clcpp
+++ clang/test/CodeGenOpenCLCXX/atexit.clcpp
@@ -5,7 +5,7 @@
 };
 S s;
 
-//CHECK-LABEL: define internal spir_func void @__cxx_global_var_init()
+//CHECK-LABEL: define internal spir_func void @__dtor()
 //CHECK: call spir_func i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.S addrspace(4)*)* @_ZNU3AS41SD1Ev to void (i8*)*), i8* null, i8 addrspace(1)* @__dso_handle)
 
 //CHECK: declare spir_func i32 @__cxa_atexit(void (i8*)*, i8*, i8 addrspace(1)*)
Index: clang/test/CodeGenCXX/static-destructor.cpp
===================================================================
--- clang/test/CodeGenCXX/static-destructor.cpp
+++ clang/test/CodeGenCXX/static-destructor.cpp
@@ -16,17 +16,17 @@
 Foo global;
 
 // X86 destructors have void return, and are registered directly with __cxa_atexit.
-// X86: define internal void @__cxx_global_var_init()
+// X86-LABEL: define internal void @__dtor()
 // X86:   call i32 @__cxa_atexit(ptr @_ZN3FooD1Ev, ptr @global, ptr @__dso_handle)
 
 // ARM destructors return this, but can be registered directly with __cxa_atexit
 // because the calling conventions tolerate the mismatch.
-// ARM: define internal void @__cxx_global_var_init()
+// ARM-LABEL: define internal void @__dtor()
 // ARM:   call i32 @__cxa_atexit(ptr @_ZN3FooD1Ev, ptr @global, ptr @__dso_handle)
 
 // Wasm destructors return this, and use a wrapper function, which is registered
 // with __cxa_atexit.
-// WASM: define internal void @__cxx_global_var_init()
+// WASM-LABEL: define internal void @__dtor()
 // WASM: call i32 @__cxa_atexit(ptr @__cxx_global_array_dtor, ptr null, ptr @__dso_handle)
 
 // WASM: define internal void @__cxx_global_array_dtor(ptr noundef %0)
Index: clang/test/CodeGenCXX/runtime-dllstorage.cpp
===================================================================
--- clang/test/CodeGenCXX/runtime-dllstorage.cpp
+++ clang/test/CodeGenCXX/runtime-dllstorage.cpp
@@ -114,7 +114,6 @@
 // CHECK-MS-DAG: declare dso_local void @_Init_thread_header(ptr)
 // CHECK-MS-DAG: declare dso_local void @_Init_thread_footer(ptr)
 
-// CHECK-IA-DAG: @_ZTH1t = dso_local alias void (), ptr @__tls_init
 // CHECK-IA-DAG: declare dso_local i32 @__gxx_personality_v0(...)
 // CHECK-IA-DAG: define linkonce_odr hidden void @__clang_call_terminate(ptr noundef %0)
 
Index: clang/test/CodeGenCXX/non-const-init-cxx2a.cpp
===================================================================
--- clang/test/CodeGenCXX/non-const-init-cxx2a.cpp
+++ clang/test/CodeGenCXX/non-const-init-cxx2a.cpp
@@ -15,5 +15,5 @@
 // CHECK: @b ={{.*}} global {{.*}} i32 123
 B b = B();
 
-// CHECK: define {{.*}}cxx_global_var_init
+// CHECK-LABEL: define {{.*}}dtor
 // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN1BD1Ev, {{.*}} @b
Index: clang/test/CodeGenCXX/no_destroy.cpp
===================================================================
--- clang/test/CodeGenCXX/no_destroy.cpp
+++ clang/test/CodeGenCXX/no_destroy.cpp
@@ -1,6 +1,8 @@
 // RUN: %clang_cc1 %s -emit-llvm -triple x86_64-apple-macosx10.13.0 -o - | FileCheck %s --check-prefixes=CHECK,NO_EXCEPTIONS
 // RUN: %clang_cc1 -fexceptions %s -emit-llvm -triple x86_64-apple-macosx10.13.0 -o - | FileCheck %s --check-prefixes=CHECK,EXCEPTIONS
 
+// CHECK: @llvm.global_ctors = appending global [5 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__dtor, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__dtor.1, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__dtor.2, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__dtor.3, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_no_destroy.cpp, ptr null }]
+
 struct NonTrivial {
   ~NonTrivial();
 };
@@ -35,10 +37,10 @@
   [[clang::no_destroy]] thread_local NonTrivial2 nt22;
 }
 
-// CHECK-LABEL: define internal void @__cxx_global_var_init
+// CHECK-LABEL: define internal void @__dtor.2
 // CHECK: __cxa_atexit{{.*}}_ZN10NonTrivialD1Ev
 [[clang::always_destroy]] NonTrivial nt3;
-// CHECK-LABEL: define internal void @__cxx_global_var_init
+// CHECK-LABEL: define internal void @__dtor.3
 // CHECK: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev
 [[clang::always_destroy]] thread_local NonTrivial nt4;
 
Index: clang/test/CodeGenCXX/funcattrs-global-ctor-dtor.cpp
===================================================================
--- clang/test/CodeGenCXX/funcattrs-global-ctor-dtor.cpp
+++ clang/test/CodeGenCXX/funcattrs-global-ctor-dtor.cpp
@@ -7,6 +7,5 @@
 
 A g;
 
-// CHECK: define internal void @__cxx_global_var_init() [[ATTR0:#[0-9]+]]
-// CHECK: define internal void @_GLOBAL__sub_I_funcattrs_global_ctor_dtor.cpp() [[ATTR0]]
+// CHECK: define internal void @__dtor() [[ATTR0:#[0-9]+]]
 // CHECK: attributes [[ATTR0]] = {{{.*}} sspstrong {{.*}}}
Index: clang/test/CodeGenCXX/dso-handle-custom.cpp
===================================================================
--- clang/test/CodeGenCXX/dso-handle-custom.cpp
+++ clang/test/CodeGenCXX/dso-handle-custom.cpp
@@ -8,7 +8,7 @@
 
 // CHECK-DEFAULT: @__dso_handle = global ptr @__dso_handle, align 8
 // CHECK-HIDDEN: @__dso_handle = hidden global ptr @__dso_handle, align 8
-// CHECK: define internal void @__cxx_global_var_init()
+// CHECK-LABEL: define internal void @__dtor()
 // CHECK:   call i32 @__cxa_atexit({{.*}}, {{.*}}, ptr @__dso_handle)
 
 #ifdef HIDDEN
Index: clang/test/CodeGenCXX/dllimport.cpp
===================================================================
--- clang/test/CodeGenCXX/dllimport.cpp
+++ clang/test/CodeGenCXX/dllimport.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -no-enable-noundef-analysis -triple i686-windows-msvc   -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -DMSABI -w | FileCheck --check-prefix=MSC --check-prefix=M32 %s
-// RUN: %clang_cc1 -no-enable-noundef-analysis -triple x86_64-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -DMSABI -w | FileCheck --check-prefix=MSC --check-prefix=M64 %s
+// RUN: %clang_cc1 -no-enable-noundef-analysis -triple i686-windows-msvc   -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -DMSABI -w | FileCheck --check-prefix=MSC --check-prefix=M32 --check-prefix=GL32 %s
+// RUN: %clang_cc1 -no-enable-noundef-analysis -triple x86_64-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -DMSABI -w | FileCheck --check-prefix=MSC --check-prefix=M64 --check-prefix=GL64 %s
 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple i686-windows-gnu    -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s         -w | FileCheck --check-prefix=GNU --check-prefix=G32 %s
 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple x86_64-windows-gnu  -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s         -w | FileCheck --check-prefix=GNU %s
 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple i686-windows-msvc   -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=18.00 -emit-llvm -std=c++1y -O1 -disable-llvm-passes -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M18 %s
@@ -737,8 +737,6 @@
 
 namespace PR19933 {
 // Don't dynamically initialize dllimport vars.
-// MSC2-NOT: @llvm.global_ctors
-// GNU2-NOT: @llvm.global_ctors
 
   struct NonPOD { NonPOD(); };
   template <typename T> struct A { static NonPOD x; };
@@ -856,6 +854,12 @@
 USEMEMFUNC(PR23770BaseTemplate<int>, f);
 // M32-DAG: declare dllimport x86_thiscallcc void @"?f@?$PR23770BaseTemplate@H@@QAEXXZ"
 
+// MSC-DAG: @"?val@@3HA" = external dllimport global i32
+// GL32-DAG: @"?x@@3PAHA" = dso_local global ptr null
+// GL64-DAG: @"?x@@3PEAHEA" = dso_local global ptr null
+// MSC-DAG: @"?impx@@3HA" = external dllimport global i32
+// MSC-DAG: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 201, ptr @__ctor, ptr null }]
+
 namespace PR27810 {
   template <class T>
   struct basic_ostream {
@@ -1026,3 +1030,15 @@
 void baz() { U<int> u; u.foo(); } // No diagnostic.
 
 }
+
+void assigndllimporttoconst () {
+  // MSC-DAG: define dso_local void @"?assigndllimporttoconst@@YAXXZ"()
+  // MSC-DAG: %[[VAL_REF:.*]] = alloca ptr
+  // MSC-DAG-NEXT: store ptr @"?val@@3HA", ptr %[[VAL_REF]]
+  extern int _declspec(dllimport) val;
+  constexpr int& val_ref = val;
+}
+
+_declspec(dllimport) int impx;
+constexpr int *y = &impx;
+int *x = &impx;
Index: clang/test/CodeGenCXX/cxx2a-thread-local-constinit.cpp
===================================================================
--- clang/test/CodeGenCXX/cxx2a-thread-local-constinit.cpp
+++ clang/test/CodeGenCXX/cxx2a-thread-local-constinit.cpp
@@ -14,6 +14,8 @@
 // CHECK-DAG:  @e = external thread_local global %struct.Destructed, align 4
 // CHECK-DAG:  @e2 ={{.*}} thread_local global %struct.Destructed zeroinitializer, align 4
 // CHECK-DAG:  @f ={{.*}} thread_local global i32 4, align 4
+// CHECK-DAG: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__dtor, i8* null }]
+
 
 extern thread_local int a;
 extern thread_local constinit int b;
@@ -85,7 +87,7 @@
 // CHECK: }
 int get_e() { return e.n; }
 
-// CHECK: define {{.*}}[[E2_INIT:@__cxx_global_var_init[^(]*]](
+// CHECK-LABEL: define {{.*}} @__dtor(
 // LINUX: call {{.*}} @__cxa_thread_atexit({{.*}} @_ZN10DestructedD1Ev {{.*}} @e2
 // DARWIN: call {{.*}} @_tlv_atexit({{.*}} @_ZN10DestructedD1Ev {{.*}} @e2
 thread_local constinit Destructed e2;
@@ -94,7 +96,6 @@
 
 // CHECK-LABEL: define {{.*}}__tls_init
 // CHECK: call {{.*}} [[D_INIT]]
-// CHECK: call {{.*}} [[E2_INIT]]
 
 // Because the call wrapper may be called speculatively (and simply because
 // it's required by the ABI), it must always be emitted for an external linkage
Index: clang/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp
===================================================================
--- clang/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp
+++ clang/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp
@@ -28,14 +28,15 @@
   // CHECK: @_ZN8Constant2d2E ={{.*}} global { i32, i8, i8 } { i32 1, i8 2, i8 3 }, align 4
   // CHECK: @_ZN8Constant2d3E ={{.*}} global { i32, i8, i8 } { i32 1, i8 0, i8 0 }, align 4
 
-  // CHECK-LABEL: define {{.*}}global_var_init
+  // CHECK-LABEL: define internal void @__dtor()
   // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN8Constant1DD1Ev {{.*}} @_ZN8Constant2d1E
 
-  // CHECK-LABEL: define {{.*}}global_var_init
+  // CHECK-LABEL: define internal void @__dtor.1()
   // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN8Constant1DD1Ev {{.*}} @_ZN8Constant2d2E
 
-  // CHECK-LABEL: define {{.*}}global_var_init
+  // CHECK-LABEL: define internal void @__dtor.2()
   // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN8Constant1DD1Ev {{.*}} @_ZN8Constant2d3E
+
 }
 
 namespace Dynamic {
@@ -64,7 +65,7 @@
   D d1 = {};
   // CHECK-LABEL: define {{.*}}global_var_init
   // CHECK: call void @_ZN7Dynamic1AC2Ev({{.*}} @_ZN7Dynamic2d1E
-  // CHECK: store i32 5, {{.*}}i8* getelementptr inbounds {{.*}} @_ZN7Dynamic2d1E{{.*}}, i64 8
+  // CHECK-NEXT: store i32 5, {{.*}}i8* getelementptr inbounds {{.*}} @_ZN7Dynamic2d1E{{.*}}, i64 8
   // CHECK: invoke void @_ZN7Dynamic1CC2Eb({{.*}} @_ZN7Dynamic2d1E{{.*}}, i1 noundef zeroext true)
   // CHECK:   unwind label %[[UNWIND:.*]]
   // CHECK: invoke noundef i32 @_ZN7Dynamic1fEv()
Index: clang/test/CodeGenCXX/cxx11-thread-local.cpp
===================================================================
--- clang/test/CodeGenCXX/cxx11-thread-local.cpp
+++ clang/test/CodeGenCXX/cxx11-thread-local.cpp
@@ -88,16 +88,15 @@
 
 // CHECK-DAG: @__tls_guard = internal thread_local global i8 0
 
-// CHECK-DAG: @llvm.global_ctors = appending global {{.*}} @[[GLOBAL_INIT:[^ ]*]]
+// CHECK-DAG: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__dtor, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @__dtor.10, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_cxx11_thread_local.cpp, i8* null }]
 
 // LINUX_AIX-DAG: @_ZTH1a ={{.*}} alias void (), void ()* @__tls_init
 // DARWIN-DAG: @_ZTH1a = internal alias void (), void ()* @__tls_init
 // LINUX_AIX-DAG: @_ZTHN1U1mE ={{.*}} alias void (), void ()* @__tls_init
 // DARWIN-DAG: @_ZTHN1U1mE = internal alias void (), void ()* @__tls_init
-// CHECK-DAG: @_ZTHN1VIiE1mE = linkonce_odr alias void (), void ()* @[[V_M_INIT:[^, ]*]]
-// CHECK-DAG: @_ZTHN1XIiE1mE = linkonce_odr alias void (), void ()* @[[X_M_INIT:[^, ]*]]
-// CHECK-DAG: @_ZTHN1VIfE1mE = weak_odr alias void (), void ()* @[[VF_M_INIT:[^, ]*]]
-// CHECK-DAG: @_ZTHN1XIfE1mE = weak_odr alias void (), void ()* @[[XF_M_INIT:[^, ]*]]
+// CHECK-DAG: @_ZTHN1VIiE1mE = linkonce_odr alias void (), void ()* @__cxx_global_var_init.9
+// CHECK-DAG: @_ZTHN1VIfE1mE = weak_odr alias void (), void ()* @__cxx_global_var_init.6
+
 // FIXME: We really want a CHECK-DAG-NOT for these.
 // CHECK-NOT: @_ZTHN1WIiE1mE =
 // CHECK-NOT: @_ZTHN1WIfE1mE =
@@ -181,13 +180,11 @@
 
 // LINUX_AIX-LABEL: define weak_odr hidden {{.*}}* @_ZTWN1XIiE1mE()
 // DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc {{.*}}* @_ZTWN1XIiE1mE()
-// LINUX_AIX: call void @_ZTHN1XIiE1mE()
-// DARWIN: call cxx_fast_tlscc void @_ZTHN1XIiE1mE()
 // CHECK: [[XM_ADDR:%.+]] = call align 1 %struct.Dtor* @llvm.threadlocal.address.p0s_struct.Dtors(%struct.Dtor* align 1 @_ZN1XIiE1mE)
 // CHECK: ret {{.*}}* [[XM_ADDR]]
 
-// LINUX_AIX: define internal void @[[VF_M_INIT]]()
-// DARWIN: define internal cxx_fast_tlscc void @[[VF_M_INIT]]()
+// LINUX_AIX: define internal void @__cxx_global_var_init.6()
+// DARWIN: define internal cxx_fast_tlscc void @__cxx_global_var_init.6()
 // CHECK-NOT: comdat
 // CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIfE1mE to i8*)
 // CHECK: %[[VF_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0
@@ -199,8 +196,8 @@
 // CHECK: store i32 %{{.*}}, i32* [[VFM_ADDR]], align 4
 // CHECK: br label
 
-// LINUX_AIX: define internal void @[[XF_M_INIT]]()
-// DARWIN: define internal cxx_fast_tlscc void @[[XF_M_INIT]]()
+// LINUX_AIX: define internal void @__dtor()
+// DARWIN: define internal void @__dtor()
 // CHECK-NOT: comdat
 // CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIfE1mE to i8*)
 // CHECK: %[[XF_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0
@@ -322,8 +319,8 @@
 // LINUX_AIX-LABEL: define internal noundef i32* @_ZTWN12_GLOBAL__N_16anon_iE()
 // DARWIN-LABEL: define internal cxx_fast_tlscc noundef i32* @_ZTWN12_GLOBAL__N_16anon_iE()
 
-// LINUX_AIX: define internal void @[[V_M_INIT]]()
-// DARWIN: define internal cxx_fast_tlscc void @[[V_M_INIT]]()
+// LINUX_AIX: define internal void @__cxx_global_var_init.9()
+// DARWIN: define internal cxx_fast_tlscc void @__cxx_global_var_init.9()
 // CHECK-NOT: comdat
 // CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*)
 // CHECK: %[[V_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0
@@ -335,8 +332,8 @@
 // CHECK: store i32 %{{.*}}, i32* [[VEM_ADDR]], align 4
 // CHECK: br label
 
-// LINUX_AIX: define internal void @[[X_M_INIT]]()
-// DARWIN: define internal cxx_fast_tlscc void @[[X_M_INIT]]()
+// LINUX_AIX: define internal void @__dtor.10()
+// DARWIN: define internal void @__dtor.10()
 // CHECK-NOT: comdat
 // CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIiE1mE to i8*)
 // CHECK: %[[X_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0
@@ -360,14 +357,11 @@
 // init:
 // CHECK: store i8 1, i8* @__tls_guard
 // CHECK-OPT: call {}* @llvm.invariant.start.p0i8(i64 1, i8* @__tls_guard)
-// CHECK-NOT: call void @[[V_M_INIT]]()
-// CHECK: call void @[[A_INIT]]()
-// CHECK-NOT: call void @[[V_M_INIT]]()
-// CHECK: call void @[[D_INIT]]()
-// CHECK-NOT: call void @[[V_M_INIT]]()
-// CHECK: call void @[[U_M_INIT]]()
-// CHECK-NOT: call void @[[V_M_INIT]]()
-
+// CHECK-NOT: call void @__dtor.10()
+// CHECK: call void @__cxx_global_var_init()
+// CHECK: call void @__cxx_global_var_init.2()
+// CHECK: call void @__cxx_global_var_init.3()
+// CHECK: call void @__cxx_global_var_init.8()
 
 // LINUX_AIX: define weak_odr hidden noundef i32* @_ZTW1a()
 // DARWIN: define cxx_fast_tlscc noundef i32* @_ZTW1a()
Index: clang/test/CodeGenCXX/ctor-dtor-alias.cpp
===================================================================
--- clang/test/CodeGenCXX/ctor-dtor-alias.cpp
+++ clang/test/CodeGenCXX/ctor-dtor-alias.cpp
@@ -54,7 +54,7 @@
 // test that instead of an internal alias we just use the other destructor
 // directly.
 
-// CHECK1: define internal void @__cxx_global_var_init.1()
+// CHECK1-LABEL: define internal void @__dtor()
 // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11AD2Ev
 // CHECK1: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev(
 namespace {
@@ -73,13 +73,13 @@
   // guarantee that they will be present in every TU. Instead, we just call
   // A's destructor directly.
 
-  // CHECK1: define internal void @__cxx_global_var_init.2()
+  // CHECK1-LABEL: define internal void @__dtor.1()
   // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev
   // CHECK1: define linkonce_odr void @_ZN5test41AD2Ev({{.*}} comdat align
 
   // test that we don't do this optimization at -O0 so that the debugger can
   // see both destructors.
-  // NOOPT: define internal void @__cxx_global_var_init.2()
+  // NOOPT: define internal void @__dtor.1()
   // NOOPT: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev
   // NOOPT: define linkonce_odr void @_ZN5test41BD2Ev({{.*}} comdat align
   struct A {
@@ -94,7 +94,7 @@
 namespace test5 {
   // similar to test4, but with an internal B.
 
-  // CHECK2: define internal void @__cxx_global_var_init.3()
+  // CHECK2-LABEL: define internal void @__dtor.2()
   // CHECK2: call i32 @__cxa_atexit{{.*}}_ZN5test51AD2Ev
   // CHECK2: define linkonce_odr void @_ZN5test51AD2Ev({{.*}} comdat align
   struct A {
@@ -120,7 +120,7 @@
   };
   }
   B X;
-  // CHECK3: define internal void @__cxx_global_var_init.4()
+  // CHECK3-LABEL: define internal void @__dtor.3()
   // CHECK3: call i32 @__cxa_atexit({{.*}}@_ZN5test61AD2Ev
 }
 
@@ -142,7 +142,7 @@
 namespace test8 {
   // Test that we replace ~zed with ~bar which is an alias to ~foo.
   // CHECK4: @_ZN5test83barD2Ev ={{.*}} unnamed_addr alias {{.*}} @_ZN5test83fooD2Ev
-  // CHECK4: define internal void @__cxx_global_var_init.5()
+  // CHECK4-LABEL: define internal void @__dtor.4()
   // CHECK4: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev
   struct foo {
     ~foo();
Index: clang/test/CodeGenCXX/const-init-cxx11.cpp
===================================================================
--- clang/test/CodeGenCXX/const-init-cxx11.cpp
+++ clang/test/CodeGenCXX/const-init-cxx11.cpp
@@ -430,7 +430,7 @@
 
 // We must emit a constant initializer for NonLiteralConstexpr::ntd, but also
 // emit an initializer to register its destructor.
-// CHECK: define {{.*}}cxx_global_var_init{{.*}}
+// CHECK-LABEL: define {{.*}} @__dtor()
 // CHECK-NOT: NonLiteralConstexpr
 // CHECK: call {{.*}}cxa_atexit{{.*}} @_ZN19NonLiteralConstexpr14NonTrivialDtorD1Ev {{.*}} @_ZN19NonLiteralConstexpr3ntdE
 // CHECK-NEXT: ret void
@@ -440,7 +440,7 @@
 
 // We must emit a constant initializer for NonLiteralConstexpr::b, but also
 // emit an initializer to register its destructor.
-// CHECK: define {{.*}}cxx_global_var_init{{.*}}
+// CHECK-LABEL: define {{.*}} @__dtor.1()
 // CHECK-NOT: NonLiteralConstexpr
 // CHECK: call {{.*}}cxa_atexit{{.*}} @_ZN19NonLiteralConstexpr4BothD1Ev {{.*}} @_ZN19NonLiteralConstexpr1bE
 // CHECK-NEXT: ret void
Index: clang/test/CodeGenCXX/call-conv-thru-alias.cpp
===================================================================
--- clang/test/CodeGenCXX/call-conv-thru-alias.cpp
+++ clang/test/CodeGenCXX/call-conv-thru-alias.cpp
@@ -13,8 +13,10 @@
 // CHECK: @"??1Derived@@UAE@XZ" = dso_local unnamed_addr alias void (%struct.Derived*), bitcast (void (%struct.Base*)* @"??1Base@@UAE@XZ" to void (%struct.Derived*)*)
 
 // CHECK: define dso_local x86_thiscallcc void @"??1Base@@UAE@XZ"
-// CHECK: define internal void @"??__E?inst@Derived@@2U1@A@@YAXXZ"
-// CHECK: call i32 @atexit(void ()* @"??__F?inst@Derived@@2U1@A@@YAXXZ"
+// CHECK-LABEL: define internal void @__dtor()
+// CHECK-NEXT: entry
+// CHECK-NEXT:   call i32 @atexit(void ()* @"??__F?inst@Derived@@2U1@A@@YAXXZ")
+
 //
 // CHECK: define internal void @"??__F?inst@Derived@@2U1@A@@YAXXZ"
 // CHECK-NEXT: entry:
Index: clang/test/CodeGenCXX/aix-static-init.cpp
===================================================================
--- clang/test/CodeGenCXX/aix-static-init.cpp
+++ clang/test/CodeGenCXX/aix-static-init.cpp
@@ -39,7 +39,7 @@
 } // namespace test4
 
 // CHECK: @_ZGVZN5test41fEvE11staticLocal = internal global i64 0, align 8
-// CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I__, ptr null }]
+// CHECK: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__dtor, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I__, ptr null }]
 // CHECK: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__D_a, ptr null }]
 
 // CHECK: define internal void @__cxx_global_var_init() [[ATTR:#[0-9]+]] {
@@ -108,7 +108,7 @@
 // CHECK:   ret void
 // CHECK: }
 
-// CHECK: define internal void @__cxx_global_var_init.3() [[ATTR:#[0-9]+]] {
+// CHECK: define internal void @__dtor() [[ATTR:#[0-9]+]] {
 // CHECK: entry:
 // CHECK:   %0 = call i32 @atexit(ptr @__dtor__ZN5test31tE)
 // CHECK:   ret void
@@ -180,7 +180,6 @@
 // CHECK:   call void @__cxx_global_var_init()
 // CHECK:   call void @__cxx_global_var_init.1()
 // CHECK:   call void @__cxx_global_var_init.2()
-// CHECK:   call void @__cxx_global_var_init.3()
 // CHECK:   ret void
 // CHECK: }
 
Index: clang/test/CodeGenCXX/PR19955.cpp
===================================================================
--- clang/test/CodeGenCXX/PR19955.cpp
+++ clang/test/CodeGenCXX/PR19955.cpp
@@ -1,27 +1,34 @@
 // RUN: %clang_cc1 -triple i686-windows-msvc -fms-extensions -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck %s --check-prefix X64
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck %s --check-prefix=CHECK-X64
 
 extern int __declspec(dllimport) var;
 extern void __declspec(dllimport) fun();
 
 extern int *varp;
 int *varp = &var;
-// CHECK-DAG: @"?varp@@3PAHA" = dso_local global ptr null
-// X64-DAG: @"?varp@@3PEAHEA" = dso_local global ptr null
+// CHECK: @"?varp@@3PAHA" = dso_local global ptr null
+// CHECK-X64: @"?varp@@3PEAHEA" = dso_local global ptr null
+// CHECK: @"?var@@3HA" = external dllimport global i32
+// CHECK: @"?funp@@3P6AXXZA" = dso_local global ptr null
 
-extern void (*funp)();
-void (*funp)() = &fun;
-// CHECK-DAG: @"?funp@@3P6AXXZA" = dso_local global ptr null
-// X64-DAG: @"?funp@@3P6AXXZEA" = dso_local global ptr null
-
-// CHECK-LABEL: @"??__Evarp@@YAXXZ"
-// CHECK-DAG: store ptr @"?var@@3HA", ptr @"?varp@@3PAHA"
+// CHECK-X64: @"?funp@@3P6AXXZEA" = dso_local global ptr null
+// CHECK: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 201, ptr @__ctor, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_PR19955.cpp, ptr null }]
 
-// X64-LABEL: @"??__Evarp@@YAXXZ"
-// X64-DAG: store ptr @"?var@@3HA", ptr @"?varp@@3PEAHEA"
+// CHECK-LABEL: define internal void @__ctor()
+// CHECK: entry
+// CHECK:   store ptr @"?var@@3HA", ptr @"?varp@@3PAHA"
+// CHECK-X64: store ptr @"?var@@3HA", ptr @"?varp@@3PEAHEA"
+// CHECK:   ret void
 
-// CHECK-LABEL: @"??__Efunp@@YAXXZ"()
-// CHECK-DAG: store ptr @"?fun@@YAXXZ", ptr @"?funp@@3P6AXXZA"
+extern void (*funp)();
+void (*funp)() = &fun;
+// CHECK-LABEL: define internal void @"??__Efunp@@YAXXZ"
+// CHECK: entry
+// CHECK:   store ptr @"?fun@@YAXXZ", ptr @"?funp@@3P6AXXZA"
+// CHECK-X64: store ptr @"?fun@@YAXXZ", ptr @"?funp@@3P6AXXZEA"
+// CHECK:   ret void
 
-// X64-LABEL: @"??__Efunp@@YAXXZ"()
-// X64-DAG: store ptr @"?fun@@YAXXZ", ptr @"?funp@@3P6AXXZEA"
+// CHECK-LABEL: define internal void @_GLOBAL__sub_I_PR19955.cpp()
+// CHECK: entry:
+// CHECK:   call void @"??__Efunp@@YAXXZ"()
+// CHECK:   ret void
Index: clang/lib/CodeGen/CodeGenModule.h
===================================================================
--- clang/lib/CodeGen/CodeGenModule.h
+++ clang/lib/CodeGen/CodeGenModule.h
@@ -1623,6 +1623,9 @@
   void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
                                     llvm::GlobalVariable *Addr,
                                     bool PerformInit);
+  void EmitCXXCtorInit(const VarDecl *D, llvm::GlobalVariable *Addr,
+                       bool PerformInit, int Priority,
+                       llvm::StringLiteral FnName, bool PerformDtor);
 
   void EmitPointerToInitFunc(const VarDecl *VD, llvm::GlobalVariable *Addr,
                              llvm::Function *InitFunc, InitSegAttr *ISA);
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -4756,6 +4756,10 @@
   GO.setComdat(TheModule.getOrInsertComdat(GO.getName()));
 }
 
+bool isStaticInit(const VarDecl *D, const LangOptions Opts) {
+  return Opts.CPlusPlus && D->hasConstantInitialization();
+}
+
 /// Pass IsTentative as true if you want to create a tentative definition.
 void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
                                             bool IsTentative) {
@@ -4992,9 +4996,18 @@
   maybeSetTrivialComdat(*D, *GV);
 
   // Emit the initializer function if necessary.
-  if (NeedsGlobalCtor || NeedsGlobalDtor)
-    EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
 
+  if (isStaticInit(D, getLangOpts())) {
+    if (NeedsGlobalCtor)
+      EmitCXXCtorInit(D, GV, true, 201, llvm::StringLiteral("__ctor"), false);
+    if (NeedsGlobalDtor)
+      EmitCXXCtorInit(D, GV, false, 65535, llvm::StringLiteral("__dtor"), true);
+    if (NeedsGlobalCtor || NeedsGlobalDtor)
+      DelayedCXXInitPosition[D] = ~0U;
+  } else {
+    if (NeedsGlobalCtor || NeedsGlobalDtor)
+      EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
+  }
   SanitizerMD->reportGlobal(GV, *D, NeedsGlobalCtor);
 
   // Emit global variable debug information.
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -4441,7 +4441,7 @@
   /// EmitCXXGlobalVarDeclInit - Create the initializer for a C++
   /// variable with global storage.
   void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV,
-                                bool PerformInit);
+                                bool PerformInit, bool PerformDtor = true);
 
   llvm::Function *createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor,
                                    llvm::Constant *Addr);
@@ -4496,7 +4496,7 @@
   void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
                                         const VarDecl *D,
                                         llvm::GlobalVariable *Addr,
-                                        bool PerformInit);
+                                        bool PerformInit, bool PerformDtor = true);
 
   void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest);
 
Index: clang/lib/CodeGen/CGExprConstant.cpp
===================================================================
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -1920,8 +1920,14 @@
     if (auto VD = dyn_cast<VarDecl>(D)) {
       // We can never refer to a variable with local storage.
       if (!VD->hasLocalStorage()) {
-        if (VD->isFileVarDecl() || VD->hasExternalStorage())
+        if (VD->isFileVarDecl() || VD->hasExternalStorage()) {
+          if (VD->hasAttr<DLLImportAttr>()) {
+            DiagnosticsEngine &Diags = CGM.getContext().getDiagnostics();
+            Diags.Report(diag::warn_for_global_ctor_for_dllimport) << D;
+            return nullptr;
+          }
           return CGM.GetAddrOfGlobalVar(VD);
+        }
 
         if (VD->isLocalVarDecl()) {
           return CGM.getOrCreateStaticVarDecl(
Index: clang/lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGDeclCXX.cpp
+++ clang/lib/CodeGen/CGDeclCXX.cpp
@@ -175,7 +175,8 @@
 
 void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
                                                llvm::GlobalVariable *GV,
-                                               bool PerformInit) {
+                                               bool PerformInit,
+                                               bool PerformDtor) {
 
   const Expr *Init = D.getInit();
   QualType T = D.getType();
@@ -218,7 +219,7 @@
       EmitDeclInit(*this, D, DeclAddr);
     if (CGM.isTypeConstant(D.getType(), true))
       EmitDeclInvariant(*this, D, DeclPtr);
-    else
+    else if (PerformDtor)
       EmitDeclDestroy(*this, D, DeclAddr);
     return;
   }
@@ -504,6 +505,23 @@
     PtrArray->setComdat(C);
 }
 
+void CodeGenModule::EmitCXXCtorInit(const VarDecl *D,
+                                    llvm::GlobalVariable *Addr,
+                                    bool PerformInit, int Priority,
+                                    llvm::StringLiteral FuncName,
+                                    bool PerformDtor) {
+  auto I = DelayedCXXInitPosition.find(D);
+  if (I != DelayedCXXInitPosition.end() && I->second == ~0U)
+    return;
+
+  llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+  llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
+      FTy, FuncName.str(), getTypes().arrangeNullaryFunction());
+  CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(
+      Fn, D, Addr, PerformInit, PerformDtor);
+  AddGlobalCtor(Fn, Priority);
+}
+
 void
 CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
                                             llvm::GlobalVariable *Addr,
@@ -966,10 +984,9 @@
 }
 
 /// Emit the code necessary to initialize the given global variable.
-void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
-                                                       const VarDecl *D,
-                                                 llvm::GlobalVariable *Addr,
-                                                       bool PerformInit) {
+void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(
+    llvm::Function *Fn, const VarDecl *D, llvm::GlobalVariable *Addr,
+    bool PerformInit, bool PerformDtor) {
   // Check if we need to emit debug info for variable initializer.
   if (D->hasAttr<NoDebugAttr>())
     DebugInfo = nullptr; // disable debug info indefinitely for this function
@@ -994,7 +1011,7 @@
        isTemplateInstantiation(D->getTemplateSpecializationKind()))) {
     EmitCXXGuardedInit(*D, Addr, PerformInit);
   } else {
-    EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit);
+    EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit, PerformDtor);
   }
 
   if (getLangOpts().HLSL)
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -2228,11 +2228,13 @@
         // FIXME: Diagnostic!
         return false;
 
-      // A dllimport variable never acts like a constant, unless we're
-      // evaluating a value for use only in name mangling.
-      if (!isForManglingOnly(Kind) && Var->hasAttr<DLLImportAttr>())
-        // FIXME: Diagnostic!
-        return false;
+      // In C mode, a dllimport variable never acts like a constant, unless
+      // we're evaluating a value for use only in name mangling.
+
+      if (!Info.getCtx().getLangOpts().CPlusPlus)
+        if (!isForManglingOnly(Kind) && Var->hasAttr<DLLImportAttr>())
+          // FIXME: Diagnostic!
+          return false;
 
       // In CUDA/HIP device compilation, only device side variables have
       // constant addresses.
Index: clang/include/clang/Basic/DiagnosticCommonKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -251,6 +251,10 @@
 def err_unimplemented_conversion_with_fixed_point_type : Error<
   "conversion between fixed point and %0 is not yet supported">;
 
+def warn_for_global_ctor_for_dllimport : Warning<
+  "global constructor is generated for dllimport global var %0">,
+  InGroup<GlobalConstructors>;
+
 // SEH
 def err_seh_expected_handler : Error<
   "expected '__except' or '__finally' block">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to