From: Reid Kleckner Date: Wed, 30 Sep 2015 17:30:48 +0000 (+0000) Subject: [Sema] Avoid crashing during this-> insertion recovery X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=41f1777a09480c6cc3f388e0a2cc48cd1f56cf2f;p=clang [Sema] Avoid crashing during this-> insertion recovery We get into this bad state when someone defines a new member function for a class but forgets to add the declaration to the class body. Calling the new member function from a member function template of the class will crash during instantiation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@248925 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8e4624304e..be0da09f26 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1824,7 +1824,6 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, bool isInstance = CurMethod && CurMethod->isInstance() && DC == CurMethod->getParent() && !isDefaultArgument; - // Give a code modification hint to insert 'this->'. // TODO: fixit for inserting 'Base::' in the other cases. @@ -1838,15 +1837,23 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CallsUndergoingInstantiation.back()->getCallee()); CXXMethodDecl *DepMethod; - if (CurMethod->isDependentContext()) + if (CurMethod->isDependentContext()) { DepMethod = CurMethod; - else if (CurMethod->getTemplatedKind() == - FunctionDecl::TK_FunctionTemplateSpecialization) - DepMethod = cast(CurMethod->getPrimaryTemplate()-> - getInstantiatedFromMemberTemplate()->getTemplatedDecl()); - else + } else if (FunctionTemplateDecl *FTD = + CurMethod->getPrimaryTemplate()) { + // We have a member function template. It may be contained in a + // class template. If so, get the original pattern for the member + // function template. Otherwise, 'this' isn't dependent and we can + // use CurMethod as is. + if (FunctionTemplateDecl *MemberFTD = + FTD->getInstantiatedFromMemberTemplate()) + DepMethod = cast(MemberFTD->getTemplatedDecl()); + else + DepMethod = CurMethod; + } else { DepMethod = cast( CurMethod->getInstantiatedFromMemberFunction()); + } assert(DepMethod && "No template pattern found"); QualType DepThisType = DepMethod->getThisType(Context); @@ -1856,7 +1863,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, TemplateArgumentListInfo TList; if (ULE->hasExplicitTemplateArgs()) ULE->copyTemplateArgumentsInto(TList); - + CXXScopeSpec SS; SS.Adopt(ULE->getQualifierLoc()); CXXDependentScopeMemberExpr *DepExpr = diff --git a/test/SemaTemplate/recovery-crash.cpp b/test/SemaTemplate/recovery-crash.cpp index 78f6db40d5..02f80495bb 100644 --- a/test/SemaTemplate/recovery-crash.cpp +++ b/test/SemaTemplate/recovery-crash.cpp @@ -35,3 +35,25 @@ namespace PR16225 { g(0); // expected-note {{in instantiation of function template specialization}} } } + +namespace test1 { + template class ArraySlice {}; + class Foo; + class NonTemplateClass { + void MemberFunction(ArraySlice, int); + template void MemberFuncTemplate(ArraySlice, int); + }; + void NonTemplateClass::MemberFunction(ArraySlice resource_data, + int now) { + // expected-note@+1 {{in instantiation of function template specialization 'test1::NonTemplateClass::MemberFuncTemplate'}} + MemberFuncTemplate(resource_data, now); + } + template + void NonTemplateClass::MemberFuncTemplate(ArraySlice resource_data, int) { + // expected-error@+1 {{use of undeclared identifier 'UndeclaredMethod'}} + UndeclaredMethod(resource_data); + } + // expected-error@+2 {{out-of-line definition of 'UndeclaredMethod' does not match any declaration}} + // expected-note@+1 {{must qualify identifier to find this declaration in dependent base class}} + void NonTemplateClass::UndeclaredMethod() {} +}