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:
Hans Wennborg 2014-06-25 22:19:48 +00:00
parent c010ddb73d
commit 82dd877e8a
5 changed files with 14 additions and 13 deletions

View File

@ -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;
} }
} }

View File

@ -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.

View File

@ -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);
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -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;

View File

@ -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}}