forked from OSchip/llvm-project
Don't allow dllimport variables in constant initializers
This is a follow-up to David's r211677. For the following code, we would end up referring to 'foo' in the initializer for 'arr', and then fail to link, because 'foo' is dllimport and needs to be accessed through the __imp_?foo. __declspec(dllimport) extern const char foo[]; const char* f() { static const char* const arr[] = { foo }; return arr[0]; } Differential Revision: http://reviews.llvm.org/D4299 llvm-svn: 211736
This commit is contained in:
parent
c010ddb73d
commit
82dd877e8a
|
@ -1275,13 +1275,8 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
|
||||||
if (Var->getTLSKind())
|
if (Var->getTLSKind())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check if this is a dllimport variable. Fail evaluation if we care
|
// A dllimport variable never acts like a constant.
|
||||||
// about side effects; a dllimport variable rarely acts like a constant
|
if (Var->hasAttr<DLLImportAttr>())
|
||||||
// except in places like template arguments. It never acts like a
|
|
||||||
// constant in C.
|
|
||||||
if ((!Info.getLangOpts().CPlusPlus ||
|
|
||||||
!Info.keepEvaluatingAfterSideEffect()) &&
|
|
||||||
Var->hasAttr<DLLImportAttr>())
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (const auto *FD = dyn_cast<const FunctionDecl>(VD)) {
|
if (const auto *FD = dyn_cast<const FunctionDecl>(VD)) {
|
||||||
|
@ -1295,9 +1290,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
|
||||||
// The C language has no notion of ODR; furthermore, it has no notion of
|
// The C language has no notion of ODR; furthermore, it has no notion of
|
||||||
// dynamic initialization. This means that we are permitted to
|
// dynamic initialization. This means that we are permitted to
|
||||||
// perform initialization with the address of the thunk.
|
// perform initialization with the address of the thunk.
|
||||||
if (Info.getLangOpts().CPlusPlus &&
|
if (Info.getLangOpts().CPlusPlus && FD->hasAttr<DLLImportAttr>())
|
||||||
!Info.keepEvaluatingAfterSideEffect() &&
|
|
||||||
FD->hasAttr<DLLImportAttr>())
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4193,7 +4193,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
|
||||||
if (Arg->isValueDependent() || Arg->isTypeDependent())
|
if (Arg->isValueDependent() || Arg->isTypeDependent())
|
||||||
return NPV_NotNullPointer;
|
return NPV_NotNullPointer;
|
||||||
|
|
||||||
if (!S.getLangOpts().CPlusPlus11)
|
if (!S.getLangOpts().CPlusPlus11 || S.getLangOpts().MSVCCompat)
|
||||||
return NPV_NotNullPointer;
|
return NPV_NotNullPointer;
|
||||||
|
|
||||||
// Determine whether we have a constant expression.
|
// Determine whether we have a constant expression.
|
||||||
|
|
|
@ -94,6 +94,14 @@ inline int __declspec(dllimport) inlineStaticLocalsFunc() {
|
||||||
};
|
};
|
||||||
USE(inlineStaticLocalsFunc);
|
USE(inlineStaticLocalsFunc);
|
||||||
|
|
||||||
|
// The address of a dllimport global cannot be used in constant initialization.
|
||||||
|
// M32-DAG: @"\01?arr@?0??initializationFunc@@YAPAHXZ@4QBQAHB" = internal global [1 x i32*] zeroinitializer
|
||||||
|
// GNU-DAG: @_ZZ18initializationFuncvE3arr = internal global [1 x i32*] zeroinitializer
|
||||||
|
int *initializationFunc() {
|
||||||
|
static int *const arr[] = {&ExternGlobalDecl};
|
||||||
|
return arr[0];
|
||||||
|
}
|
||||||
|
USE(initializationFunc);
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -118,7 +118,7 @@ typedef COM_CLASS_TEMPLATE_REF<struct_with_uuid, __uuidof(struct_with_uuid)> COM
|
||||||
|
|
||||||
COM_CLASS_TEMPLATE_REF<int, __uuidof(struct_with_uuid)> good_template_arg;
|
COM_CLASS_TEMPLATE_REF<int, __uuidof(struct_with_uuid)> good_template_arg;
|
||||||
|
|
||||||
COM_CLASS_TEMPLATE<int, __uuidof(struct_with_uuid)> bad_template_arg; // expected-error {{non-type template argument of type 'const _GUID' is not a constant expression}}
|
COM_CLASS_TEMPLATE<int, __uuidof(struct_with_uuid)> bad_template_arg; // expected-error {{non-type template argument of type 'const _GUID' cannot be converted to a value of type 'const GUID *' (aka 'const _GUID *')}}
|
||||||
|
|
||||||
namespace PR16911 {
|
namespace PR16911 {
|
||||||
struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid;
|
struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %clang_cc1 -triple i686-win32 -verify -std=c++11 %s
|
// RUN: %clang_cc1 -triple i686-win32 -fms-compatibility -verify -std=c++11 %s
|
||||||
|
|
||||||
extern int __attribute__((dllimport)) var;
|
extern int __attribute__((dllimport)) var;
|
||||||
constexpr int *varp = &var; // expected-error {{must be initialized by a constant expression}}
|
constexpr int *varp = &var; // expected-error {{must be initialized by a constant expression}}
|
||||||
|
|
Loading…
Reference in New Issue