]> granicus.if.org Git - clang/commitdiff
Fix a crash on invalid with template handling
authorRichard Trieu <rtrieu@google.com>
Tue, 5 Apr 2016 21:13:54 +0000 (21:13 +0000)
committerRichard Trieu <rtrieu@google.com>
Tue, 5 Apr 2016 21:13:54 +0000 (21:13 +0000)
This is a fix for https://llvm.org/bugs/show_bug.cgi?id=25561 which was a
crash on invalid.  Change the handling of invalid decls to have a catch-all
case to prevent unexpecting decls from triggering an assertion.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaTemplate.cpp
test/SemaCXX/using-decl-templates.cpp
test/SemaTemplate/template-id-expr.cpp

index 39212e31b19a5f34a5648e732873b64d7d1dcf67..35adb6e8d434242a23dfed119912aaf29c6f86e3 100644 (file)
@@ -4322,7 +4322,7 @@ def err_redefinition_different_typedef : Error<
   "%select{typedef|type alias|type alias template}0 "
   "redefinition with different types%diff{ ($ vs $)|}1,2">;
 def err_tag_reference_non_tag : Error<
-  "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template|a type alias template}0">;
+  "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template|a type alias template|a template template argument}0">;
 def err_tag_reference_conflict : Error<
   "implicit declaration introduced by elaborated type conflicts with "
   "%select{a declaration|a typedef|a type alias|a template}0 of the same name">;
index 18b739df7f5f9e853252497518e87f5bb518e278..fdb7d762d2945e646492806c8f84d662d2073e65 100644 (file)
@@ -7277,15 +7277,21 @@ Sema::ActOnExplicitInstantiation(Scope *S,
   assert(Kind != TTK_Enum &&
          "Invalid enum tag in class template explicit instantiation!");
 
-  if (isa<TypeAliasTemplateDecl>(TD)) {
-      Diag(KWLoc, diag::err_tag_reference_non_tag) << Kind;
-      Diag(TD->getTemplatedDecl()->getLocation(),
-           diag::note_previous_use);
+  ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(TD);
+
+  if (!ClassTemplate) {
+    unsigned ErrorKind = 0;
+    if (isa<TypeAliasTemplateDecl>(TD)) {
+      ErrorKind = 4;
+    } else if (isa<TemplateTemplateParmDecl>(TD)) {
+      ErrorKind = 5;
+    }
+
+    Diag(TemplateNameLoc, diag::err_tag_reference_non_tag) << ErrorKind;
+    Diag(TD->getLocation(), diag::note_previous_use);
     return true;
   }
 
-  ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(TD);
-
   if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
                                     Kind, /*isDefinition*/false, KWLoc,
                                     ClassTemplate->getIdentifier())) {
index 8314688bcbc7e688a5e040c880e64193e8dd9731..d766bb3ac6bf5702d8a609738e22560168475cca 100644 (file)
@@ -90,5 +90,5 @@ namespace aliastemplateinst {
   template<typename T> struct A { };
   template<typename T> using APtr = A<T*>; // expected-note{{previous use is here}}
 
-  template struct APtr<int>; // expected-error{{elaborated type refers to a non-tag type}}
+  template struct APtr<int>; // expected-error{{elaborated type refers to a type alias template}}
 }
index 4416f92723adc8d3a28a49cdecc662a0fad7ae09..499d289ee6754e58c239dbf640ed9109c5d5be76 100644 (file)
@@ -96,3 +96,9 @@ void f5() {
 }
 
 template void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}}
+
+class C {};
+template <template <typename> class D>  // expected-note{{previous use is here}}
+class E {
+  template class D<C>;  // expected-error {{elaborated type refers to a template template argument}}
+};