]> granicus.if.org Git - clang/commitdiff
[Sema] Avoid crashing during this-> insertion recovery
authorReid Kleckner <rnk@google.com>
Wed, 30 Sep 2015 17:30:48 +0000 (17:30 +0000)
committerReid Kleckner <rnk@google.com>
Wed, 30 Sep 2015 17:30:48 +0000 (17:30 +0000)
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

lib/Sema/SemaExpr.cpp
test/SemaTemplate/recovery-crash.cpp

index 8e4624304e0eb6e84456dd18c36f3d376ec13381..be0da09f26520d91173dd9ed0876e58397d254f8 100644 (file)
@@ -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<T>::' 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<CXXMethodDecl>(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<CXXMethodDecl>(MemberFTD->getTemplatedDecl());
+            else
+              DepMethod = CurMethod;
+          } else {
             DepMethod = cast<CXXMethodDecl>(
                 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 =
index 78f6db40d5c85fc23d5e902e1fe605c4f4451f20..02f80495bb9411d257ad76a084e32d92aebd987b 100644 (file)
@@ -35,3 +35,25 @@ namespace PR16225 {
     g<S>(0);  // expected-note {{in instantiation of function template specialization}}
   }
 }
+
+namespace test1 {
+  template <typename> class ArraySlice {};
+  class Foo;
+  class NonTemplateClass {
+    void MemberFunction(ArraySlice<Foo>, int);
+    template <class T> void MemberFuncTemplate(ArraySlice<T>, int);
+  };
+  void NonTemplateClass::MemberFunction(ArraySlice<Foo> resource_data,
+                                        int now) {
+    // expected-note@+1 {{in instantiation of function template specialization 'test1::NonTemplateClass::MemberFuncTemplate<test1::Foo>'}}
+    MemberFuncTemplate(resource_data, now);
+  }
+  template <class T>
+  void NonTemplateClass::MemberFuncTemplate(ArraySlice<T> 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() {}
+}