Author: rnk
Date: Wed Sep 30 12:30:48 2015
New Revision: 248925

URL: http://llvm.org/viewvc/llvm-project?rev=248925&view=rev
Log:
[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.

Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/SemaTemplate/recovery-crash.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=248925&r1=248924&r2=248925&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Sep 30 12:30:48 2015
@@ -1824,7 +1824,6 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXS
         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, CXXS
               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, CXXS
           TemplateArgumentListInfo TList;
           if (ULE->hasExplicitTemplateArgs())
             ULE->copyTemplateArgumentsInto(TList);
-          
+
           CXXScopeSpec SS;
           SS.Adopt(ULE->getQualifierLoc());
           CXXDependentScopeMemberExpr *DepExpr =

Modified: cfe/trunk/test/SemaTemplate/recovery-crash.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/recovery-crash.cpp?rev=248925&r1=248924&r2=248925&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/recovery-crash.cpp (original)
+++ cfe/trunk/test/SemaTemplate/recovery-crash.cpp Wed Sep 30 12:30:48 2015
@@ -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() {}
+}


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to