From f3cec65d01595c0d74b5a33a6867dca786397e8f Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 31 Oct 2016 18:18:29 +0000 Subject: [PATCH] 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 --- clang/lib/Sema/SemaDeclCXX.cpp | 7 ++++++- clang/test/CXX/class.derived/class.abstract/p16.cpp | 18 +++++++++++++----- clang/test/CXX/special/class.dtor/p5-0x.cpp | 2 +- clang/test/CXX/special/class.dtor/p9.cpp | 2 +- 4 files changed, 21 insertions(+), 8 deletions(-) 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 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { // See if we're deleting a function which is already known to override a // non-deleted virtual function. - if (const CXXMethodDecl *MD = dyn_cast(Fn)) { + if (CXXMethodDecl *MD = dyn_cast(Fn)) { bool IssuedDiagnostic = false; for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), E = MD->end_overridden_methods(); @@ -13863,6 +13863,11 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { 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 @@ private: 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 @@ class D1 { 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 @@ namespace test2 { } #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() { -- 2.7.4