Don't allow dllimport variables in constant initializers
authorHans Wennborg <hans@hanshq.net>
Wed, 25 Jun 2014 22:19:48 +0000 (22:19 +0000)
committerHans Wennborg <hans@hanshq.net>
Wed, 25 Jun 2014 22:19:48 +0000 (22:19 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@211736 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprConstant.cpp
lib/Sema/SemaTemplate.cpp
test/CodeGenCXX/dllimport.cpp
test/Parser/MicrosoftExtensions.cpp
test/SemaCXX/PR19955.cpp

index 5897f2c48569bcc3db616d080eadff02370ab30c..2803310c3256c1ad6cce4504a0ff04581ae12734 100644 (file)
@@ -1275,13 +1275,8 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
       if (Var->getTLSKind())
         return false;
 
-      // Check if this is a dllimport variable.  Fail evaluation if we care
-      // about side effects; a dllimport variable rarely acts like a constant
-      // except in places like template arguments.  It never acts like a
-      // constant in C.
-      if ((!Info.getLangOpts().CPlusPlus ||
-           !Info.keepEvaluatingAfterSideEffect()) &&
-          Var->hasAttr<DLLImportAttr>())
+      // A dllimport variable never acts like a constant.
+      if (Var->hasAttr<DLLImportAttr>())
         return false;
     }
     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
       // dynamic initialization.  This means that we are permitted to
       // perform initialization with the address of the thunk.
-      if (Info.getLangOpts().CPlusPlus &&
-          !Info.keepEvaluatingAfterSideEffect() &&
-          FD->hasAttr<DLLImportAttr>())
+      if (Info.getLangOpts().CPlusPlus && FD->hasAttr<DLLImportAttr>())
         return false;
     }
   }
index 84c58d12ea8e394fee824b94ae8597be6de9efa1..00d93f852808580dcae05828b964265027c94917 100644 (file)
@@ -4193,7 +4193,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
   if (Arg->isValueDependent() || Arg->isTypeDependent())
     return NPV_NotNullPointer;
   
-  if (!S.getLangOpts().CPlusPlus11)
+  if (!S.getLangOpts().CPlusPlus11 || S.getLangOpts().MSVCCompat)
     return NPV_NotNullPointer;
   
   // Determine whether we have a constant expression.
index 63b119277eca47328f294cd86766d87c36a199cc..d15eea24f2f59e495f2df96449a8ce55c432b817 100644 (file)
@@ -94,6 +94,14 @@ inline int __declspec(dllimport) 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);
 
 
 //===----------------------------------------------------------------------===//
index 7f3ef6d903c4e15ead4d7c337a11f0a15c7e6e33..076de7cd785c0048e473a79fdea7e70886820737 100644 (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<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 {
 struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid;
index 4596e5a459e4b5bf7b5630089e274241447f6dbd..fb1d74631b2bc4463f3718d01523e202c92dcfb7 100644 (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;
 constexpr int *varp = &var; // expected-error {{must be initialized by a constant expression}}