]> granicus.if.org Git - clang/commitdiff
Add a workaround for PR7947, a crash trying to recover from invalid C++ code.
authorNick Lewycky <nicholas@mxc.ca>
Fri, 20 Aug 2010 20:54:15 +0000 (20:54 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Fri, 20 Aug 2010 20:54:15 +0000 (20:54 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111675 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/SemaTemplate/recovery-crash.cpp [new file with mode: 0644]

index 15e0f7f1c772aa97d08aa88e6e2b2599d5d6ec2a..487b9e62f4819290472d7ae4741c2e25ba640e66 100644 (file)
@@ -892,25 +892,30 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
         // TODO: fixit for inserting 'Base<T>::' in the other cases.
         // Actually quite difficult!
         if (isInstance) {
-          Diag(R.getNameLoc(), diagnostic) << Name
-            << FixItHint::CreateInsertion(R.getNameLoc(), "this->");
-
           UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(
               CallsUndergoingInstantiation.back()->getCallee());
-          CXXMethodDecl *DepMethod = cast<CXXMethodDecl>(
+          CXXMethodDecl *DepMethod = cast_or_null<CXXMethodDecl>(
               CurMethod->getInstantiatedFromMemberFunction());
-          QualType DepThisType = DepMethod->getThisType(Context);
-          CXXThisExpr *DepThis = new (Context) CXXThisExpr(R.getNameLoc(),
-                                                           DepThisType, false);
-          TemplateArgumentListInfo TList;
-          if (ULE->hasExplicitTemplateArgs())
-            ULE->copyTemplateArgumentsInto(TList);
-          CXXDependentScopeMemberExpr *DepExpr =
-              CXXDependentScopeMemberExpr::Create(
-                  Context, DepThis, DepThisType, true, SourceLocation(),
-                  ULE->getQualifier(), ULE->getQualifierRange(), NULL,
-                  R.getLookupNameInfo(), &TList);
-          CallsUndergoingInstantiation.back()->setCallee(DepExpr);
+         if (DepMethod) {
+            Diag(R.getNameLoc(), diagnostic) << Name
+              << FixItHint::CreateInsertion(R.getNameLoc(), "this->");
+            QualType DepThisType = DepMethod->getThisType(Context);
+            CXXThisExpr *DepThis = new (Context) CXXThisExpr(
+                                       R.getNameLoc(), DepThisType, false);
+            TemplateArgumentListInfo TList;
+            if (ULE->hasExplicitTemplateArgs())
+              ULE->copyTemplateArgumentsInto(TList);
+            CXXDependentScopeMemberExpr *DepExpr =
+                CXXDependentScopeMemberExpr::Create(
+                    Context, DepThis, DepThisType, true, SourceLocation(),
+                    ULE->getQualifier(), ULE->getQualifierRange(), NULL,
+                    R.getLookupNameInfo(), &TList);
+            CallsUndergoingInstantiation.back()->setCallee(DepExpr);
+         } else {
+            // FIXME: we should be able to handle this case too. It is correct
+            // to add this-> here. This is a workaround for PR7947.
+            Diag(R.getNameLoc(), diagnostic) << Name;
+         }
         } else {
           Diag(R.getNameLoc(), diagnostic) << Name;
         }
diff --git a/test/SemaTemplate/recovery-crash.cpp b/test/SemaTemplate/recovery-crash.cpp
new file mode 100644 (file)
index 0000000..0ed3258
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// We don't expect a fix-it to be applied in this case. Clang used to crash
+// trying to recover while adding 'this->' before Work(x);
+
+template <typename> struct A {
+  static void Work(int);  // expected-note{{must qualify identifier}}
+};
+
+template <typename T> struct B : public A<T> {
+  template <typename T2> B(T2 x) {
+    Work(x);  // expected-error{{use of undeclared identifier}}
+  }
+};
+
+void Test() {
+  B<int> b(0);  // expected-note{{in instantiation of function template}}
+}
+