zahiraam updated this revision to Diff 484006.
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/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/dllimport.cpp
clang/test/CodeGenCXX/funcattrs-global-ctor-dtor.cpp
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/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,6 @@
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 @ctor() [[ATTR0:#[0-9]+]]
+// CHECK: define internal void @dtor() [[ATTR0]]
// CHECK: attributes [[ATTR0]] = {{{.*}} sspstrong {{.*}}}
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 65535, ptr @_GLOBAL__sub_I_dllimport.cpp, 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/ctor-dtor-alias.cpp
===================================================================
--- clang/test/CodeGenCXX/ctor-dtor-alias.cpp
+++ clang/test/CodeGenCXX/ctor-dtor-alias.cpp
@@ -73,14 +73,14 @@
// 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: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev
- // CHECK1: define linkonce_odr void @_ZN5test41AD2Ev({{.*}} comdat align
+ // CHECK1: define internal void @ctor()
+ // CHECK1: call void @_ZN5test41BC2Ev(%"struct.test4::B"* noundef nonnull align 4 dereferenceable(4) bitcast ({ i8** }* @_ZN5test41XE to %"struct.test4::B"*))
+ // CHECK1: define linkonce_odr void @_ZN5test41BC2Ev
// 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: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev
+ // NOOPT: define internal void @ctor()
+ // NOOPT: call void @_ZN5test41BC2Ev
// NOOPT: define linkonce_odr void @_ZN5test41BD2Ev({{.*}} comdat align
struct A {
virtual ~A() {}
@@ -94,9 +94,9 @@
namespace test5 {
// similar to test4, but with an internal B.
- // CHECK2: define internal void @__cxx_global_var_init.3()
- // CHECK2: call i32 @__cxa_atexit{{.*}}_ZN5test51AD2Ev
- // CHECK2: define linkonce_odr void @_ZN5test51AD2Ev({{.*}} comdat align
+ // CHECK2: define internal void @ctor.2()
+ // CHECK2: call void @_ZN5test512_GLOBAL__N_11BC2Ev(%"struct.test5::(anonymous namespace)::B"* noundef nonnull align 4 dereferenceable(4) bitcast ({ i8** }* @_ZN5test51XE to %"struct.test5::(anonymous namespace)::B"*))
+ // CHECK2: define internal void @dtor.3()
struct A {
virtual ~A() {}
};
@@ -120,8 +120,9 @@
};
}
B X;
- // CHECK3: define internal void @__cxx_global_var_init.4()
- // CHECK3: call i32 @__cxa_atexit({{.*}}@_ZN5test61AD2Ev
+ // CHECK3: define internal void @ctor.4()
+ // CHECK3: call void @_ZN5test612_GLOBAL__N_11BC2Ev(%"struct.test6::(anonymous namespace)::B"* noundef nonnull align 4 dereferenceable(4) bitcast ({ i8** }* @_ZN5test61XE to %"struct.test6::(anonymous namespace)::B"*))
+ // CHECK3: define internal void @dtor.5()
}
namespace test7 {
@@ -142,7 +143,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: define internal void @__cxx_global_var_init.6()
// 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,20 +430,30 @@
// 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-NOT: NonLiteralConstexpr
-// CHECK: call {{.*}}cxa_atexit{{.*}} @_ZN19NonLiteralConstexpr14NonTrivialDtorD1Ev {{.*}} @_ZN19NonLiteralConstexpr3ntdE
+// CHECK: define internal void @ctor()
+// CHECK: call void @_ZN19NonLiteralConstexpr14NonTrivialDtorC1Ev(%"struct.NonLiteralConstexpr::NonTrivialDtor"* noundef nonnull align 8 dereferenceable(16) @_ZN19NonLiteralConstexpr3ntdE)
// CHECK-NEXT: ret void
+// CHECK: define internal void @dtor()
+// CHECK: entry:
+// CHECK: %0 = call i32 @__cxa_atexit(void (i8*)* bitcast (void (%"struct.NonLiteralConstexpr::NonTrivialDtor"*)* @_ZN19NonLiteralConstexpr14NonTrivialDtorD1Ev to void (i8*)*), i8* bitcast (%"struct.NonLiteralConstexpr::NonTrivialDtor"* @_ZN19NonLiteralConstexpr3ntdE to i8*), i8* @__dso_handle)
+// CHECK: ret void
+
+// CHECK: define internal void @ctor.1()
+// CHECK: entry:
+// CHECK: call void @_ZN19NonLiteralConstexpr4BothC1Ev(%"struct.NonLiteralConstexpr::Both"* noundef nonnull align 4 dereferenceable(4) @_ZN19NonLiteralConstexpr1bE)
+// CHECK: ret void
+
+// CHECK: define internal void @dtor.2()
+// CHECK: entry:
+// CHECK: %0 = call i32 @__cxa_atexit(void (i8*)* bitcast (void (%"struct.NonLiteralConstexpr::Both"*)* @_ZN19NonLiteralConstexpr4BothD1Ev to void (i8*)*), i8* bitcast (%"struct.NonLiteralConstexpr::Both"* @_ZN19NonLiteralConstexpr1bE to i8*), i8* @__dso_handle) #3
+// CHECK: ret void
+
// We don't need to emit any dynamic initialization for NonLiteralConstexpr::vm.
// CHECK-NOT: NonLiteralConstexpr2vm
// 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-NOT: NonLiteralConstexpr
-// CHECK: call {{.*}}cxa_atexit{{.*}} @_ZN19NonLiteralConstexpr4BothD1Ev {{.*}} @_ZN19NonLiteralConstexpr1bE
-// CHECK-NEXT: ret void
// CHECK: define {{.*}}NonLiteralConstexpr10StaticVars
// CHECK-NOT: }
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,7 +13,7 @@
// 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: define internal void @ctor()
// CHECK: call i32 @atexit(void ()* @"??__F?inst@Derived@@2U1@A@@YAXXZ"
//
// CHECK: define internal void @"??__F?inst@Derived@@2U1@A@@YAXXZ"
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 [3 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 201, ptr @ctor, ptr null }, { 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,9 +108,9 @@
// CHECK: ret void
// CHECK: }
-// CHECK: define internal void @__cxx_global_var_init.3() [[ATTR:#[0-9]+]] {
+// CHECK: define internal void @ctor() [[ATTR:#[0-9]+]] {
// CHECK: entry:
-// CHECK: %0 = call i32 @atexit(ptr @__dtor__ZN5test31tE)
+// CHECK: call void @_ZN5test35Test3C1Ev(ptr noundef nonnull align 1 dereferenceable(1) @_ZN5test31tE)
// CHECK: ret void
// CHECK: }
@@ -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/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,11 @@
GO.setComdat(TheModule.getOrInsertComdat(GO.getName()));
}
+bool isStaticInit(const VarDecl *D, const LangOptions Opts) {
+ return Opts.CPlusPlus && D->hasConstantInitialization() &&
+ D->getType()->isRecordType();
+}
+
/// Pass IsTentative as true if you want to create a tentative definition.
void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
bool IsTentative) {
@@ -4839,6 +4844,13 @@
// also don't need to register a destructor.
if (getLangOpts().CPlusPlus && !NeedsGlobalDtor)
DelayedCXXInitPosition.erase(D);
+ if (isStaticInit(D, getLangOpts()) && NeedsGlobalDtor)
+ if (const CXXConstructExpr *E =
+ dyn_cast_or_null<CXXConstructExpr>(D->getInit())) {
+ const CXXConstructorDecl *CD = E->getConstructor();
+ if (!CD->isTrivial() && !D->getTLSKind())
+ NeedsGlobalCtor = true;
+ }
#ifndef NDEBUG
CharUnits VarSize = getContext().getTypeSizeInChars(ASTTy) +
@@ -4992,9 +5004,15 @@
maybeSetTrivialComdat(*D, *GV);
// Emit the initializer function if necessary.
- if (NeedsGlobalCtor || NeedsGlobalDtor)
- EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
+ if (isStaticInit(D, getLangOpts()) && NeedsGlobalCtor && NeedsGlobalDtor) {
+ EmitCXXCtorInit(D, GV, true, 201, llvm::StringLiteral("ctor"), false);
+ EmitCXXCtorInit(D, GV, false, 65535, llvm::StringLiteral("dtor"), true);
+ 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,11 @@
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>())
+ 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,12 @@
// 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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits