]> granicus.if.org Git - clang/commitdiff
Sema: Allow dllimport entities in template args for mingw
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 26 Jun 2014 07:48:46 +0000 (07:48 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 26 Jun 2014 07:48:46 +0000 (07:48 +0000)
Previously dllimport variables inside of template arguments relied on
not using the C++11 codepath when -fms-compatibility was set.

While this allowed us to achieve compatibility with MSVC, it did so at
the expense of MingW.

Instead, try to use the DeclRefExpr we dig out of the template argument.
If it has the dllimport attribute, accept it and skip the C++11
null-pointer check.

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

lib/Sema/SemaTemplate.cpp
test/SemaCXX/PR19955.cpp

index 32d51d5d412e5c7215e597ac8003fd80bdcec50a..5a188453b4fe5b3b6b01bfde8b9e86aa991f0a97 100644 (file)
@@ -4337,22 +4337,6 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
   Expr *Arg = ArgIn;
   QualType ArgType = Arg->getType();
 
-  // If our parameter has pointer type, check for a null template value.
-  if (ParamType->isPointerType() || ParamType->isNullPtrType()) {
-    switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) {
-    case NPV_NullPointer:
-      S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
-      Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
-      return false;
-
-    case NPV_Error:
-      return true;
-        
-    case NPV_NotNullPointer:
-      break;
-    }
-  }
-
   bool AddressTaken = false;
   SourceLocation AddrOpLoc;
   if (S.getLangOpts().MicrosoftExt) {
@@ -4440,6 +4424,32 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
       Arg = subst->getReplacement()->IgnoreImpCasts();
   }
 
+  DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg);
+  ValueDecl *Entity = DRE ? DRE->getDecl() : nullptr;
+
+  // If our parameter has pointer type, check for a null template value.
+  if (ParamType->isPointerType() || ParamType->isNullPtrType()) {
+    NullPointerValueKind NPV;
+    // dllimport'd entities aren't constant but are available inside of template
+    // arguments.
+    if (Entity && Entity->hasAttr<DLLImportAttr>())
+      NPV = NPV_NotNullPointer;
+    else
+      NPV = isNullPointerValueTemplateArgument(S, Param, ParamType, ArgIn);
+    switch (NPV) {
+    case NPV_NullPointer:
+      S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
+      Converted = TemplateArgument(ParamType, /*isNullPtr=*/true);
+      return false;
+
+    case NPV_Error:
+      return true;
+
+    case NPV_NotNullPointer:
+      break;
+    }
+  }
+
   // Stop checking the precise nature of the argument if it is value dependent,
   // it should be checked when instantiated.
   if (Arg->isValueDependent()) {
@@ -4456,7 +4466,6 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
     return false;
   }
 
-  DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg);
   if (!DRE) {
     S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
     << Arg->getSourceRange();
@@ -4464,8 +4473,6 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
     return true;
   }
 
-  ValueDecl *Entity = DRE->getDecl();
-
   // Cannot refer to non-static data members
   if (isa<FieldDecl>(Entity) || isa<IndirectFieldDecl>(Entity)) {
     S.Diag(Arg->getLocStart(), diag::err_template_arg_field)
index fb1d74631b2bc4463f3718d01523e202c92dcfb7..cbbe2fe9af164187af4d424c2d1f21e97abfa6b1 100644 (file)
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple i686-win32 -fms-compatibility -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple i686-win32 -verify -std=c++11 %s
+// 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}}