From: Chandler Carruth Date: Sat, 13 Feb 2010 10:17:50 +0000 (+0000) Subject: Skip implicit instantiation of templated variables where a more recent X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=291b441a095b289c30d9f311fe37a2cf5ed6fd45;p=clang Skip implicit instantiation of templated variables where a more recent redeclaration provides an explicit instantiation or is invalid. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96097 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index caeea58470..a55193aa74 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2323,6 +2323,24 @@ void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) { VarDecl *Var = cast(Inst.first); assert(Var->isStaticDataMember() && "Not a static data member?"); + // Don't try to instantiate declarations if the most recent redeclaration + // is invalid. + if (Var->getMostRecentDeclaration()->isInvalidDecl()) + continue; + + // Check if the most recent declaration has changed the specialization kind + // and removed the need for implicit instantiation. + switch (Var->getMostRecentDeclaration()->getTemplateSpecializationKind()) { + case TSK_Undeclared: + assert(false && "Cannot instantitiate an undeclared specialization."); + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: + continue; // No longer need implicit instantiation. + case TSK_ImplicitInstantiation: + break; + } + PrettyStackTraceActionsDecl CrashInfo(DeclPtrTy::make(Var), Var->getLocation(), *this, Context.getSourceManager(), diff --git a/test/SemaTemplate/explicit-instantiation.cpp b/test/SemaTemplate/explicit-instantiation.cpp index 227856f1a8..de51f0992b 100644 --- a/test/SemaTemplate/explicit-instantiation.cpp +++ b/test/SemaTemplate/explicit-instantiation.cpp @@ -76,3 +76,10 @@ template void print_type(double*); // PR5069 template void foo0 (int (&)[I + 1]) { } template void foo0<2> (int (&)[3]); + +namespace explicit_instantiation_after_implicit_instantiation { + template struct X0 { static int x; }; + template int X0::x; + void test1() { (void)&X0<1>::x; } + template struct X0<1>; +}