Fix a crash on invalid with template handling

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.

llvm-svn: 265467
This commit is contained in:
Richard Trieu 2016-04-05 21:13:54 +00:00
parent 1de3c7e790
commit 265c344ef8
4 changed files with 20 additions and 8 deletions

View 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">;

View File

@ -7277,14 +7277,20 @@ Sema::ActOnExplicitInstantiation(Scope *S,
assert(Kind != TTK_Enum &&
"Invalid enum tag in class template explicit instantiation!");
ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(TD);
if (!ClassTemplate) {
unsigned ErrorKind = 0;
if (isa<TypeAliasTemplateDecl>(TD)) {
Diag(KWLoc, diag::err_tag_reference_non_tag) << Kind;
Diag(TD->getTemplatedDecl()->getLocation(),
diag::note_previous_use);
return true;
ErrorKind = 4;
} else if (isa<TemplateTemplateParmDecl>(TD)) {
ErrorKind = 5;
}
ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(TD);
Diag(TemplateNameLoc, diag::err_tag_reference_non_tag) << ErrorKind;
Diag(TD->getLocation(), diag::note_previous_use);
return true;
}
if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
Kind, /*isDefinition*/false, KWLoc,

View 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}}
}

View 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}}
};