From dd03a2db436ea1c99993bada326ee0fe570cf6d8 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 2 Jan 2015 01:33:12 +0000 Subject: [PATCH] Instantiation of a CXXMethodDecl may fail when the parameter type cannot be instantiated. Do not crash in this case. Fixes PR22040! The FIXME in the test is caused by TemplateDeclInstantiator::VisitCXXRecordDecl returning a nullptr instead of creating an invalid decl. This is a common pattern across all of TemplateDeclInstantiator, so I'm not comfortable changing it. The reason it's not invalid in the class template is due to support for an MSVC extension, see r137573. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@225071 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateInstantiateDecl.cpp | 6 ++++-- test/SemaTemplate/instantiate-method.cpp | 13 +++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9ba9c14559..40e86175b2 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2360,8 +2360,10 @@ Decl * TemplateDeclInstantiator Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *Decl) { CXXMethodDecl *OldFD = Decl->getSpecialization(); - CXXMethodDecl *NewFD = cast(VisitCXXMethodDecl(OldFD, - nullptr, true)); + CXXMethodDecl *NewFD = + cast_or_null(VisitCXXMethodDecl(OldFD, nullptr, true)); + if (!NewFD) + return nullptr; LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName, Sema::ForRedeclaration); diff --git a/test/SemaTemplate/instantiate-method.cpp b/test/SemaTemplate/instantiate-method.cpp index 58cb897955..4cc40af7e1 100644 --- a/test/SemaTemplate/instantiate-method.cpp +++ b/test/SemaTemplate/instantiate-method.cpp @@ -182,3 +182,16 @@ namespace SameSignatureAfterInstantiation { }; S s; // expected-note {{instantiation}} } + +namespace PR22040 { + template struct Foobar { + template <> void bazqux(typename T::type) {} // expected-error {{cannot specialize a function 'bazqux' within class scope}} expected-error 2{{cannot be used prior to '::' because it has no members}} + }; + + void test() { + // FIXME: we should suppress the "no member" errors + Foobar::bazqux(); // expected-error{{no member named 'bazqux' in }} expected-note{{in instantiation of template class }} + Foobar::bazqux(); // expected-error{{no member named 'bazqux' in }} expected-note{{in instantiation of template class }} + Foobar::bazqux(3); // expected-error{{no member named 'bazqux' in }} + } +} -- 2.40.0