]> granicus.if.org Git - clang/commitdiff
Fix a crash on invalid, http://llvm.org/pr11599
authorNico Weber <nicolasweber@gmx.de>
Tue, 20 Dec 2011 20:32:49 +0000 (20:32 +0000)
committerNico Weber <nicolasweber@gmx.de>
Tue, 20 Dec 2011 20:32:49 +0000 (20:32 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146988 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateInstantiate.cpp
test/CXX/temp/temp.spec/temp.explicit/p3.cpp

index e86912a5218ad73b0481adc8bb7593c061897740..7c3165206c72b2cd1a17835197e30eb9e1376af8 100644 (file)
@@ -1709,6 +1709,13 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
         << Context.getTypeDeclType(Instantiation);
       Diag(Pattern->getLocation(), diag::note_template_decl_here);
     }
+
+    // In general, Instantiation isn't marked invalid to get more than one
+    // error for multiple undefined instantiations. But the code that does
+    // explicit declaration -> explicit definition conversion can't handle
+    // invalid declarations, so mark as invalid in that case.
+    if (TSK == TSK_ExplicitInstantiationDeclaration)
+       Instantiation->setInvalidDecl();
     return true;
   }
   Pattern = PatternDef;
@@ -1719,7 +1726,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
     MSInfo->setTemplateSpecializationKind(TSK);
     MSInfo->setPointOfInstantiation(PointOfInstantiation);
   } else if (ClassTemplateSpecializationDecl *Spec 
-               = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
+        = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
     Spec->setTemplateSpecializationKind(TSK);
     Spec->setPointOfInstantiation(PointOfInstantiation);
   }
@@ -1888,7 +1895,8 @@ Sema::InstantiateClassTemplateSpecialization(
       
       // If this is an explicit instantiation definition, mark the
       // vtable as used.
-      if (TSK == TSK_ExplicitInstantiationDefinition)
+      if (TSK == TSK_ExplicitInstantiationDefinition &&
+          !ClassTemplateSpec->isInvalidDecl())
         MarkVTableUsed(PointOfInstantiation, ClassTemplateSpec, true);
 
       return false;
index ff1438285e35d2bf04f9e941fbb62f457a59a362..38ae7688a0b5ad9a30ec007906e4add72b5eab6b 100644 (file)
@@ -72,3 +72,10 @@ namespace PR7979 {
   template <typename T> int S<T>::i;
   template <typename T> void S<T>::S2::h() {}
 }
+
+namespace PR11599 {
+  template <typename STRING_TYPE> class BasicStringPiece;  // expected-note {{template is declared here}}
+
+  extern template class BasicStringPiece<int>;  // expected-error{{explicit instantiation of undefined template 'PR11599::BasicStringPiece<int>}}
+  template class BasicStringPiece<int>;
+}