When diagnosing that a defaulted function is ill-formed because it would be
implicitly deleted and overrides a non-deleted function, explain why the
function is deleted. For PR30844.

llvm-svn: 285610
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 518a780..2c74367 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -13850,7 +13850,7 @@
 
   // See if we're deleting a function which is already known to override a
   // non-deleted virtual function.
-  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
     bool IssuedDiagnostic = false;
     for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
                                         E = MD->end_overridden_methods();
@@ -13863,6 +13863,11 @@
         Diag((*I)->getLocation(), diag::note_overridden_virtual_function);
       }
     }
+    // If this function was implicitly deleted because it was defaulted,
+    // explain why it was deleted.
+    if (IssuedDiagnostic && MD->isDefaulted())
+      ShouldDeleteSpecialMember(MD, getSpecialMember(MD), nullptr,
+                                /*Diagnose*/true);
   }
 
   // C++11 [basic.start.main]p3:
diff --git a/clang/test/CXX/class.derived/class.abstract/p16.cpp b/clang/test/CXX/class.derived/class.abstract/p16.cpp
index 2053218..29adbcc 100644
--- a/clang/test/CXX/class.derived/class.abstract/p16.cpp
+++ b/clang/test/CXX/class.derived/class.abstract/p16.cpp
@@ -31,12 +31,20 @@
   D &operator=(D&&) = default;
   virtual ~D(); // expected-note 2{{here}}
 };
-struct E : D {}; // expected-error {{deleted function '~E' cannot override a non-deleted function}} \
-                 // expected-error {{deleted function 'operator=' cannot override a non-deleted function}}
+struct E : D {};
+// expected-error@-1 {{deleted function '~E' cannot override a non-deleted function}}
+// expected-note@-2 {{destructor of 'E' is implicitly deleted because base class 'D' has an inaccessible destructor}}
+// expected-error@-3 {{deleted function 'operator=' cannot override a non-deleted function}}
+// expected-note@-4 {{copy assignment operator of 'E' is implicitly deleted because base class 'D' has an inaccessible copy assignment operator}}
 struct F : D {};
-struct G : D {}; // expected-error {{deleted function '~G' cannot override a non-deleted function}}
-                 // expected-error@-1 {{deleted function 'operator=' cannot override a non-deleted function}}
+struct G : D {};
+// expected-error@-1 {{deleted function '~G' cannot override a non-deleted function}}
+// expected-note@-2 {{move assignment operator of 'G' is implicitly deleted because base class 'D' has an inaccessible move assignment operator}}
+// expected-error@-3 {{deleted function 'operator=' cannot override a non-deleted function}}
+// expected-note@-4 {{destructor of 'G' is implicitly deleted because base class 'D' has an inaccessible destructor}}
 struct H : D {
-  H &operator=(H&&) = default; // expected-error {{deleted function 'operator=' cannot override a non-deleted function}}
+  H &operator=(H&&) = default;
+  // expected-error@-1 {{deleted function 'operator=' cannot override a non-deleted function}}
+  // expected-note@-3 {{move assignment operator of 'H' is implicitly deleted because base class 'D' has an inaccessible move assignment operator}}
   ~H();
 };
diff --git a/clang/test/CXX/special/class.dtor/p5-0x.cpp b/clang/test/CXX/special/class.dtor/p5-0x.cpp
index e32279e..595784f 100644
--- a/clang/test/CXX/special/class.dtor/p5-0x.cpp
+++ b/clang/test/CXX/special/class.dtor/p5-0x.cpp
@@ -90,7 +90,7 @@
 public:
   virtual ~D1() = default; // expected-note {{here}}
 } d1; // ok
-struct D2 : D1 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} \
+struct D2 : D1 { // expected-note 2{{virtual destructor requires an unambiguous, accessible 'operator delete'}} \
                  // expected-error {{deleted function '~D2' cannot override a non-deleted}}
   // implicitly-virtual destructor
 } d2; // expected-error {{deleted function}}
diff --git a/clang/test/CXX/special/class.dtor/p9.cpp b/clang/test/CXX/special/class.dtor/p9.cpp
index 4c6fbf4..e812491 100644
--- a/clang/test/CXX/special/class.dtor/p9.cpp
+++ b/clang/test/CXX/special/class.dtor/p9.cpp
@@ -88,7 +88,7 @@
   }
 #else
   struct CBase { virtual ~CBase(); }; // expected-note {{overridden virtual function is here}}
-  struct C : CBase { // expected-error {{deleted function '~C' cannot override a non-deleted function}} expected-note {{requires an unambiguous, accessible 'operator delete'}}
+  struct C : CBase { // expected-error {{deleted function '~C' cannot override a non-deleted function}} expected-note 2{{requires an unambiguous, accessible 'operator delete'}}
     static void operator delete(void*, const int &);
   };
   void test() {