Author: rsmith
Date: Wed Oct 18 15:45:01 2017
New Revision: 316136

URL: http://llvm.org/viewvc/llvm-project?rev=316136&view=rev
Log:
Don't suppress instantiation of definitions for variables subject to explicit
instantiation declarations if they are usable from constant expressions.

We are permitted to instantiate in these cases, and required to do so in order
to have an initializer available for use within constant evaluation.

Added:
    cfe/trunk/test/SemaTemplate/cxx17-inline-variables.cpp
Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/CodeGenCXX/dllimport-members.cpp
    cfe/trunk/test/SemaTemplate/extern-templates.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=316136&r1=316135&r2=316136&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Oct 18 15:45:01 2017
@@ -14823,9 +14823,10 @@ static void DoMarkVarDeclReferenced(Sema
   TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
 
   bool OdrUseContext = isOdrUseContext(SemaRef);
+  bool UsableInConstantExpr =
+      Var->isUsableInConstantExpressions(SemaRef.Context);
   bool NeedDefinition =
-      OdrUseContext || (isEvaluatableContext(SemaRef) &&
-                        Var->isUsableInConstantExpressions(SemaRef.Context));
+      OdrUseContext || (isEvaluatableContext(SemaRef) && UsableInConstantExpr);
 
   VarTemplateSpecializationDecl *VarSpec =
       dyn_cast<VarTemplateSpecializationDecl>(Var);
@@ -14844,14 +14845,19 @@ static void DoMarkVarDeclReferenced(Sema
   // instantiations of variable templates, except for those that could be used
   // in a constant expression.
   if (NeedDefinition && isTemplateInstantiation(TSK)) {
-    bool TryInstantiating = TSK == TSK_ImplicitInstantiation;
+    // Per C++17 [temp.explicit]p10, we may instantiate despite an explicit
+    // instantiation declaration if a variable is usable in a constant
+    // expression (among other cases).
+    bool TryInstantiating =
+        TSK == TSK_ImplicitInstantiation ||
+        (TSK == TSK_ExplicitInstantiationDeclaration && UsableInConstantExpr);
 
     if (TryInstantiating && !isa<VarTemplateSpecializationDecl>(Var)) {
       if (Var->getPointOfInstantiation().isInvalid()) {
         // This is a modification of an existing AST node. Notify listeners.
         if (ASTMutationListener *L = SemaRef.getASTMutationListener())
           L->StaticDataMemberInstantiated(Var);
-      } else if (!Var->isUsableInConstantExpressions(SemaRef.Context))
+      } else if (!UsableInConstantExpr)
         // Don't bother trying to instantiate it again, unless we might need
         // its initializer before we get to the end of the TU.
         TryInstantiating = false;
@@ -14870,7 +14876,7 @@ static void DoMarkVarDeclReferenced(Sema
 
       // Do not instantiate specializations that are still type-dependent.
       if (IsNonDependent) {
-        if (Var->isUsableInConstantExpressions(SemaRef.Context)) {
+        if (UsableInConstantExpr) {
           // Do not defer instantiations of variables which could be used in a
           // constant expression.
           SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=316136&r1=316135&r2=316136&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Oct 18 15:45:01 2017
@@ -4359,10 +4359,12 @@ void Sema::InstantiateVariableDefinition
     return;
 
   // C++11 [temp.explicit]p10:
-  //   Except for inline functions, [...] explicit instantiation declarations
+  //   Except for inline functions, const variables of literal types, variables
+  //   of reference types, [...] explicit instantiation declarations
   //   have the effect of suppressing the implicit instantiation of the entity
   //   to which they refer.
-  if (TSK == TSK_ExplicitInstantiationDeclaration)
+  if (TSK == TSK_ExplicitInstantiationDeclaration &&
+      !Var->isUsableInConstantExpressions(getASTContext()))
     return;
 
   // Make sure to pass the instantiated variable to the consumer at the end.

Modified: cfe/trunk/test/CodeGenCXX/dllimport-members.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllimport-members.cpp?rev=316136&r1=316135&r2=316136&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllimport-members.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllimport-members.cpp Wed Oct 18 15:45:01 2017
@@ -836,7 +836,7 @@ USEMV(MemVarTmpl, ImportedStaticVar<Impl
 
 // Import explicit instantiation declaration of an imported member variable
 // template.
-// MSC-DAG: 
@"\01??$ImportedStaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = external 
dllimport constant i32
+// MSC-DAG: 
@"\01??$ImportedStaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = 
available_externally dllimport constant i32 1
 // GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ExplicitDecl_ImportedEE      
 = external dllimport constant i32
 extern template const int MemVarTmpl::ImportedStaticVar<ExplicitDecl_Imported>;
 USEMV(MemVarTmpl, ImportedStaticVar<ExplicitDecl_Imported>)
@@ -861,7 +861,7 @@ USEMV(MemVarTmpl, ImportedStaticVar<Expl
 
 // Import explicit instantiation declaration of a non-imported member variable
 // template.
-// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = 
external dllimport constant i32
+// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = 
available_externally dllimport constant i32 1
 // GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ImportedEE        = 
external dllimport constant i32
 extern template __declspec(dllimport) const int 
MemVarTmpl::StaticVar<ExplicitDecl_Imported>;
 USEMV(MemVarTmpl, StaticVar<ExplicitDecl_Imported>)

Added: cfe/trunk/test/SemaTemplate/cxx17-inline-variables.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/cxx17-inline-variables.cpp?rev=316136&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/cxx17-inline-variables.cpp (added)
+++ cfe/trunk/test/SemaTemplate/cxx17-inline-variables.cpp Wed Oct 18 15:45:01 
2017
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++17 -verify %s
+// expected-no-diagnostics
+template<bool> struct DominatorTreeBase {
+  static constexpr bool IsPostDominator = true;
+};
+extern template class DominatorTreeBase<false>;
+constexpr bool k = DominatorTreeBase<false>::IsPostDominator;

Modified: cfe/trunk/test/SemaTemplate/extern-templates.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/extern-templates.cpp?rev=316136&r1=316135&r2=316136&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/extern-templates.cpp (original)
+++ cfe/trunk/test/SemaTemplate/extern-templates.cpp Wed Oct 18 15:45:01 2017
@@ -71,3 +71,10 @@ extern template void X1<const void*>::g(
 void g_X1_2(X1<const void *> x1, const void *ptr) {
   x1.g(ptr);
 }
+
+namespace static_const_member {
+  template <typename T> struct A { static const int n; };
+  template <typename T> const int A<T>::n = 3;
+  extern template struct A<int>;
+  int arr[A<int>::n];
+}


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to