Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -2228,12 +2228,6 @@ // 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()) - // FIXME: Diagnostic! - return false; - // In CUDA/HIP device compilation, only device side variables have // constant addresses. if (Info.getCtx().getLangOpts().CUDA && Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -4819,6 +4819,9 @@ } } else { Init = Initializer; + if (Initializer->isDLLImportDependent()) + NeedsGlobalCtor = true; + else // We don't need an initializer, so remove the entry for the delayed // initializer position (just in case this entry was delayed) if we // also don't need to register a destructor. Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -13888,6 +13888,13 @@ if (HasConstInit) { // FIXME: Consider replacing the initializer with a ConstantExpr. + if (var->isConstexpr() && !var->getType()->isStructureType() && + !var->getType()->isArrayType() && IsGlobal) { + const ValueDecl *MyInit = Init->getAsBuiltinConstantDeclRef(Context); + if (MyInit && MyInit->hasAttr() && IsGlobal) + Diag(var->getLocation(), diag::err_constexpr_var_requires_const_init) + << var << Init->getSourceRange(); + } } else if (var->isConstexpr()) { SourceLocation DiagLoc = var->getLocation(); // If the note doesn't add any useful information other than a source Index: clang/test/CodeGenCXX/PR19955.cpp =================================================================== --- clang/test/CodeGenCXX/PR19955.cpp +++ clang/test/CodeGenCXX/PR19955.cpp @@ -6,17 +6,14 @@ 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-DAG: @"?varp@@3PAHA" = dso_local global ptr @"?var@@3HA" +// X64-DAG: @"?varp@@3PEAHEA" = dso_local global ptr @"?var@@3HA" 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" - // X64-LABEL: @"??__Evarp@@YAXXZ" // X64-DAG: store ptr @"?var@@3HA", ptr @"?varp@@3PEAHEA" Index: clang/test/CodeGenCXX/dllimport.cpp =================================================================== --- clang/test/CodeGenCXX/dllimport.cpp +++ clang/test/CodeGenCXX/dllimport.cpp @@ -98,8 +98,8 @@ USE(inlineStaticLocalsFunc); // The address of a dllimport global cannot be used in constant initialization. -// M32-DAG: @"?arr@?1??initializationFunc@@YAPAHXZ@4QBQAHB" = internal global [1 x ptr] zeroinitializer -// GNU-DAG: @_ZZ18initializationFuncvE3arr = internal global [1 x ptr] zeroinitializer +// M32-DAG: @"?arr@?1??initializationFunc@@YAPAHXZ@4QBQAHB" = internal constant [1 x ptr] [ptr @"?ExternGlobalDecl@@3HA"] +// GNU-DAG: @_ZZ18initializationFuncvE3arr = internal constant [1 x ptr] [ptr @ExternGlobalDecl] int *initializationFunc() { static int *const arr[] = {&ExternGlobalDecl}; return arr[0]; @@ -738,7 +738,6 @@ namespace PR19933 { // Don't dynamically initialize dllimport vars. // MSC2-NOT: @llvm.global_ctors -// GNU2-NOT: @llvm.global_ctors struct NonPOD { NonPOD(); }; template struct A { static NonPOD x; }; @@ -769,6 +768,7 @@ USEVAR(D<42>::y); // MSC-DAG: @"?x@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32 // MSC-DAG: @"?y@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32 + // MSC-DAG: @"?val@@3HA" = external dllimport global i32 } namespace PR21355 { @@ -1026,3 +1026,11 @@ void baz() { U u; u.foo(); } // No diagnostic. } + +void assigndllimport () { + // MSC-DAG: define dso_local void @"?assigndllimport@@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; +} Index: clang/test/Sema/dllimport.c =================================================================== --- clang/test/Sema/dllimport.c +++ clang/test/Sema/dllimport.c @@ -38,7 +38,7 @@ int GlobalDeclAttr __attribute__((dllimport)); // Address of variables can't be used for initialization in C language modes. -int *VarForInit = &GlobalDecl; // expected-error{{initializer element is not a compile-time constant}} +int *VarForInit = &GlobalDecl; // Not allowed on definitions. __declspec(dllimport) extern int ExternGlobalInit = 1; // expected-error{{definition of dllimport data}} 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; } } @@ -2490,5 +2490,5 @@ GH50055::E2 GlobalInitNotCE1 = (GH50055::E2)-1; // ok, not a constant expression context GH50055::E2 GlobalInitNotCE2 = GH50055::testDefaultArgForParam(); // ok, not a constant expression context -constexpr GH50055::E2 GlobalInitCE = (GH50055::E2)-1; +constexpr GH50055::E2 GlobalInitCE = (GH50055::E2)-1; //expected-error{{integer value -1 is outside the valid range of values [0, 7] for this enumeration type}} // expected-error@-1 {{integer value -1 is outside the valid range of values [0, 7] for this enumeration type}} Index: clang/test/SemaCXX/dllimport-constexpr.cpp =================================================================== --- clang/test/SemaCXX/dllimport-constexpr.cpp +++ clang/test/SemaCXX/dllimport-constexpr.cpp @@ -60,3 +60,12 @@ // expected-note@+1 {{requested here}} StaticConstexpr::g_fp(); } + +extern int __declspec(dllimport) val; +// expected-error@+1{{constexpr variable 'val_ref' must be initialized by a constant expression}} +constexpr int& val_ref = val; + +void AssignDllImportToConst () { + extern int _declspec(dllimport) val; + constexpr int& val_ref = val; +}