njames93 created this revision.
njames93 added a reviewer: aaron.ballman.
Herald added a subscriber: martong.
Herald added a reviewer: shafik.
Herald added a project: All.
njames93 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Adds a fix to the diagnostic of replacing the `= default` to `= delete`


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134549

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ASTImporter.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Serialization/ASTReaderDecl.cpp
  clang/lib/Serialization/ASTWriterDecl.cpp
  clang/test/CXX/class.derived/class.abstract/p16.cpp
  clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
  clang/test/CXX/class/class.compare/class.compare.default/p2.cpp
  clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
  clang/test/CXX/class/class.compare/class.eq/p2.cpp
  clang/test/CXX/class/class.compare/class.rel/p2.cpp
  clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
  clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
  clang/test/CXX/drs/dr6xx.cpp
  clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
  clang/test/SemaCXX/dr1301.cpp
  clang/test/SemaCXX/explicitly-defaulted.cpp
  clang/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp
  clang/test/SemaObjCXX/arc-0x.mm

Index: clang/test/SemaObjCXX/arc-0x.mm
===================================================================
--- clang/test/SemaObjCXX/arc-0x.mm
+++ clang/test/SemaObjCXX/arc-0x.mm
@@ -121,12 +121,12 @@
 
   union U1 {
     __weak id f0; // expected-note 12 {{'U1' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
-    U1() = default; // expected-warning {{explicitly defaulted default constructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}}
-    ~U1() = default; // expected-warning {{explicitly defaulted destructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}}
-    U1(const U1 &) = default; // expected-warning {{explicitly defaulted copy constructor is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}}
-    U1(U1 &&) = default; // expected-warning {{explicitly defaulted move constructor is implicitly deleted}}
-    U1 & operator=(const U1 &) = default; // expected-warning {{explicitly defaulted copy assignment operator is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}}
-    U1 & operator=(U1 &&) = default; // expected-warning {{explicitly defaulted move assignment operator is implicitly deleted}}
+    U1() = default; // expected-warning {{explicitly defaulted default constructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}} expected-note{{replace 'default'}}
+    ~U1() = default; // expected-warning {{explicitly defaulted destructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}} expected-note{{replace 'default'}}
+    U1(const U1 &) = default; // expected-warning {{explicitly defaulted copy constructor is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}} expected-note{{replace 'default'}}
+    U1(U1 &&) = default; // expected-warning {{explicitly defaulted move constructor is implicitly deleted}} expected-note{{replace 'default'}}
+    U1 & operator=(const U1 &) = default; // expected-warning {{explicitly defaulted copy assignment operator is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}} expected-note{{replace 'default'}}
+    U1 & operator=(U1 &&) = default; // expected-warning {{explicitly defaulted move assignment operator is implicitly deleted}} expected-note{{replace 'default'}}
   };
 
   id getStrong();
Index: clang/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp
===================================================================
--- clang/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp
+++ clang/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp
@@ -7,7 +7,7 @@
 } s; // expected-error {{attempt to use a deleted function}}
 
 struct T { // expected-note 2{{virtual destructor requires an unambiguous, accessible 'operator delete'}}
-  virtual ~T() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}} expected-warning {{implicitly deleted}}
+  virtual ~T() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}} expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
   void operator delete(void*, int);
   void operator delete(void*, double);
 } t; // expected-error {{attempt to use a deleted function}}
Index: clang/test/SemaCXX/explicitly-defaulted.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/explicitly-defaulted.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+struct Deleted {
+  Deleted() = delete; // expected-note 3{{marked deleted here}}
+  Deleted(const Deleted &) = delete; // expected-note 2{{marked deleted here}}
+  Deleted(Deleted &&) = delete; // expected-note 2{{marked deleted here}}
+  Deleted &operator=(const Deleted &) = delete; // expected-note 2{{marked deleted here}}
+  Deleted &operator=(Deleted &&) = delete; // expected-note 2{{marked deleted here}}
+  ~Deleted() = delete; // expected-note 2{{marked deleted here}}
+};
+
+struct Derive : Deleted { // expected-note 6{{because base class}}
+  Derive() = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+  Derive(const Derive &) = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+  Derive(Derive &&) = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+  Derive &operator=(const Derive &) = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+  Derive &operator=(Derive &&) = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+  ~Derive() = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+};
+
+struct Member {
+  Deleted A; // expected-note 6{{because field 'A'}}
+  Member() = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+  Member(const Member &) = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+  Member(Member &&) = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+  Member &operator=(const Member &) = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+  Member &operator=(Member &&) = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+  ~Member() = default; // expected-warning{{explicitly defaulted}} expected-note{{replace 'default' with 'delete'}}
+};
+
+template<typename T>
+struct TDerive : T { // expected-note {{because base class}}
+  TDerive() = default; //expected-note {{explicitly defaulted}} // Don't expect a fix note to be emitted
+};
+
+using ShouldDelete = TDerive<Deleted>;
+
+ShouldDelete A; // expected-error{{call to implicitly-deleted}}
Index: clang/test/SemaCXX/dr1301.cpp
===================================================================
--- clang/test/SemaCXX/dr1301.cpp
+++ clang/test/SemaCXX/dr1301.cpp
@@ -17,7 +17,7 @@
 int c = C().b.n; // expected-error {{call to implicitly-deleted default}}
 
 struct D {
-  D() = default; // expected-note {{here}} expected-warning {{implicitly deleted}}
+  D() = default; // expected-note {{here}} expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
   B b; // expected-note 2{{'b' has a deleted default constructor}}
 };
 int d = D().b.n; // expected-error {{call to implicitly-deleted default}}
Index: clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
===================================================================
--- clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
+++ clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
@@ -113,7 +113,7 @@
 
 struct defaulted_delete {
   no_default nd; // expected-note 2{{because field 'nd' has a deleted default constructor}}
-  defaulted_delete() = default; // expected-note{{implicitly deleted here}} expected-warning {{implicitly deleted}}
+  defaulted_delete() = default; // expected-note{{implicitly deleted here}} expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
 };
 defaulted_delete dd; // expected-error {{call to implicitly-deleted default constructor}}
 
Index: clang/test/CXX/drs/dr6xx.cpp
===================================================================
--- clang/test/CXX/drs/dr6xx.cpp
+++ clang/test/CXX/drs/dr6xx.cpp
@@ -776,7 +776,7 @@
 #if __cplusplus >= 201103L
 namespace dr667 { // dr667: yes
   struct A {
-    A() = default; // expected-warning {{explicitly defaulted default constructor is implicitly deleted}}
+    A() = default; // expected-warning {{explicitly defaulted default constructor is implicitly deleted}} expected-note{{replace 'default'}}
     int &r; // expected-note {{because field 'r' of reference type 'int &' would not be initialized}}
   };
   static_assert(!__is_trivially_constructible(A), "");
Index: clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
+++ clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
@@ -42,7 +42,7 @@
   };
   struct B {
     A a; // expected-note {{return type 'A' of three-way comparison for member 'a' is not a standard comparison category type}}
-    auto operator<=>(const B&) const = default; // expected-warning {{implicitly deleted}}
+    auto operator<=>(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
   };
 }
 
@@ -53,7 +53,7 @@
   };
   struct B {
     A a; // expected-note {{no viable three-way comparison function for member 'a'}}
-    auto operator<=>(const B&) const = default; // expected-warning {{implicitly deleted}}
+    auto operator<=>(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
   };
 }
 
@@ -122,6 +122,7 @@
     friend auto operator<=>(const d&, const d&) = default; // #d
     // expected-error@#d {{return type of defaulted 'operator<=>' cannot be deduced because three-way comparison for base class 'c' has a deduced return type and is not yet defined}}
     // expected-warning@#d {{implicitly deleted}}
+    // expected-note@#d {{replace 'default'}}
   };
   auto c::operator<=>(const c&) const& { // #c
     return std::strong_ordering::equal;
@@ -158,17 +159,17 @@
 
 namespace PR48856 {
   struct A {
-    auto operator<=>(const A &) const = default; // expected-warning {{implicitly deleted}}
+    auto operator<=>(const A &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
     void (*x)();                                 // expected-note {{because there is no viable three-way comparison function for member 'x'}}
   };
 
   struct B {
-    auto operator<=>(const B &) const = default; // expected-warning {{implicitly deleted}}
+    auto operator<=>(const B &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
     void (B::*x)();                              // expected-note {{because there is no viable three-way comparison function for member 'x'}}
   };
 
   struct C {
-    auto operator<=>(const C &) const = default; // expected-warning {{implicitly deleted}}
+    auto operator<=>(const C &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
     int C::*x;                                   // expected-note {{because there is no viable three-way comparison function for member 'x'}}
   };
 }
@@ -198,7 +199,7 @@
     operator fp() const;
   };
   struct b3 {
-    auto operator<=>(b3 const &) const = default; // expected-warning {{implicitly deleted}}
+    auto operator<=>(b3 const &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
     a3 f;                                         // expected-note {{because there is no viable three-way comparison function}}
   };
 
Index: clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
+++ clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
@@ -150,7 +150,7 @@
   };
   struct B {
     A a; // expected-note {{would invoke a private 'operator<=>'}}
-    friend std::strong_ordering operator<=>(const B &, const B &) = default; // expected-warning {{deleted}}
+    friend std::strong_ordering operator<=>(const B &, const B &) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
   };
 
   class C {
@@ -160,7 +160,7 @@
   };
   struct D {
     C c; // expected-note {{would invoke a private 'operator=='}}
-    friend std::strong_ordering operator<=>(const D &, const D &) = default; // expected-warning {{deleted}}
+    friend std::strong_ordering operator<=>(const D &, const D &) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
   };
 }
 
Index: clang/test/CXX/class/class.compare/class.rel/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.rel/p2.cpp
+++ clang/test/CXX/class/class.compare/class.rel/p2.cpp
@@ -22,10 +22,10 @@
 
   struct B {
     bool operator<=>(B) const = delete; // expected-note 4{{deleted here}} expected-note-re 8{{candidate {{.*}} deleted}}
-    friend bool operator<(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}}
-    friend bool operator<=(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}}
-    friend bool operator>(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}}
-    friend bool operator>=(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}}
+    friend bool operator<(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}} expected-note{{replace 'default'}}
+    friend bool operator<=(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}} expected-note{{replace 'default'}}
+    friend bool operator>(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}} expected-note{{replace 'default'}}
+    friend bool operator>=(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}} expected-note{{replace 'default'}}
   };
   bool b1 = B() < B(); // expected-error {{deleted}}
   bool b2 = B() <= B(); // expected-error {{deleted}}
@@ -36,7 +36,7 @@
     friend bool operator<=>(const C&, const C&);
     friend bool operator<(const C&, const C&); // expected-note {{because this non-rewritten comparison function would be the best match}}
 
-    bool operator<(const C&) const = default; // expected-warning {{implicitly deleted}}
+    bool operator<(const C&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
     bool operator>(const C&) const = default; // OK
   };
 }
@@ -53,7 +53,7 @@
 
   struct B {
     bool operator==(B) const = delete; // expected-note {{deleted here}} expected-note-re 2{{candidate {{.*}} deleted}}
-    friend bool operator!=(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}}
+    friend bool operator!=(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}} expected-note{{replace 'default'}}
   };
   bool b = B() != B(); // expected-error {{deleted}}
 
@@ -61,15 +61,15 @@
     friend bool operator==(const C&, const C&);
     friend bool operator!=(const C&, const C&); // expected-note {{because this non-rewritten comparison function would be the best match}}
 
-    bool operator!=(const C&) const = default; // expected-warning {{implicitly deleted}}
+    bool operator!=(const C&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
   };
 
   // Ensure we don't go into an infinite loop diagnosing this: the first function
   // is deleted because it calls the second function, which is deleted because it
   // calls the first.
   struct Evil {
-    friend bool operator!=(const Evil&, const Evil&) = default; // expected-warning {{implicitly deleted}} expected-note {{would be the best match}}
-    bool operator!=(const Evil&) const = default; // expected-warning {{implicitly deleted}} expected-note {{would be the best match}}
+    friend bool operator!=(const Evil&, const Evil&) = default; // expected-warning {{implicitly deleted}} expected-note {{would be the best match}} expected-note{{replace 'default'}}
+    bool operator!=(const Evil&) const = default; // expected-warning {{implicitly deleted}} expected-note {{would be the best match}} expected-note{{replace 'default'}}
   };
 }
 
@@ -78,7 +78,7 @@
     int operator<=>(A) const; // expected-note {{private}}
   };
   struct B : A {
-    friend bool operator<(const B&, const B&) = default; // expected-warning {{implicitly deleted}}
+    friend bool operator<(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
     // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because it would invoke a private 'operator<=>' member of 'Access::A'}}
   };
 }
Index: clang/test/CXX/class/class.compare/class.eq/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.eq/p2.cpp
+++ clang/test/CXX/class/class.compare/class.eq/p2.cpp
@@ -17,19 +17,19 @@
 
 struct H1 {
   bool operator==(const H1 &) const = default;
-  bool operator<(const H1 &) const = default; // expected-warning {{implicitly deleted}}
+  bool operator<(const H1 &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
   // expected-note@-1 {{because there is no viable three-way comparison function for 'H1'}}
   void (*x)();
 };
 struct H2 {
   bool operator==(const H2 &) const = default;
-  bool operator<(const H2 &) const = default; // expected-warning {{implicitly deleted}}
+  bool operator<(const H2 &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
   // expected-note@-1 {{because there is no viable three-way comparison function for 'H2'}}
   void (H2::*x)();
 };
 struct H3 {
   bool operator==(const H3 &) const = default;
-  bool operator<(const H3 &) const = default; // expected-warning {{implicitly deleted}}
+  bool operator<(const H3 &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
   // expected-note@-1 {{because there is no viable three-way comparison function for 'H3'}}
   int H3::*x;
 };
@@ -72,8 +72,8 @@
     bool operator==(const A &) const; // expected-note 2{{implicitly declared private here}}
   };
   struct B : A { // expected-note 2{{because it would invoke a private 'operator==' to compare base class 'A'}}
-    bool operator==(const B &) const = default; // expected-warning {{deleted}}
-    friend bool operator==(const B &, const B &) = default; // expected-warning {{deleted}}
+    bool operator==(const B &) const = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
+    friend bool operator==(const B &, const B &) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
   };
 
   class C {
@@ -86,8 +86,8 @@
   };
   struct E {
     C c; // expected-note 2{{because it would invoke a protected 'operator==' member of 'Access::C' to compare member 'c'}}
-    bool operator==(const E &) const = default; // expected-warning {{deleted}}
-    friend bool operator==(const E &, const E &) = default; // expected-warning {{deleted}}
+    bool operator==(const E &) const = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
+    friend bool operator==(const E &, const E &) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
   };
 
   struct F : C {
@@ -103,8 +103,8 @@
     using C::operator==; // expected-note 2{{declared private here}}
   };
   struct I : H { // expected-note 2{{private 'operator==' to compare base class 'H'}}
-    bool operator==(const I&) const = default; // expected-warning {{deleted}}
-    friend bool operator==(const I&, const I&) = default; // expected-warning {{deleted}}
+    bool operator==(const I&) const = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
+    friend bool operator==(const I&, const I&) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
   };
 
   class J {
Index: clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
+++ clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -std=c++20 -verify %s
 
 struct A {
-  bool operator!=(const A&) const = default; // expected-warning {{explicitly defaulted equality comparison operator is implicitly deleted}}
+  bool operator!=(const A&) const = default; // expected-warning {{explicitly defaulted equality comparison operator is implicitly deleted}} expected-note{{replace 'default'}}
   // expected-note@-1 {{defaulted 'operator!=' is implicitly deleted because there is no viable 'operator==' for 'A'}}
 };
 
@@ -9,7 +9,7 @@
 bool operator!=(Q, Q); // expected-note {{defaulted 'operator!=' is implicitly deleted because this non-rewritten comparison function would be the best match for the comparison}}
 struct B {
   operator Q() const;
-  bool operator!=(const B&) const = default; // expected-warning {{explicitly defaulted equality comparison operator is implicitly deleted}}
+  bool operator!=(const B&) const = default; // expected-warning {{explicitly defaulted equality comparison operator is implicitly deleted}} expected-note{{replace 'default'}}
 };
 
 struct R {};
@@ -21,18 +21,18 @@
 
 struct C {
   operator int() const; // expected-note {{defaulted 'operator!=' is implicitly deleted because a builtin comparison function using this conversion would be the best match for the comparison}}
-  bool operator!=(const C&) const = default; // expected-warning {{explicitly defaulted equality comparison operator is implicitly deleted}}
+  bool operator!=(const C&) const = default; // expected-warning {{explicitly defaulted equality comparison operator is implicitly deleted}} expected-note{{replace 'default'}}
 };
 
 struct D {
-  bool operator<(const D&) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}}
+  bool operator<(const D&) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}} expected-note{{replace 'default'}}
   // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because there is no viable three-way comparison function for 'D'}}
 };
 
 bool operator<(Q, Q); // expected-note {{defaulted 'operator<' is implicitly deleted because this non-rewritten comparison function would be the best match for the comparison}}
 struct E {
   operator Q() const;
-  bool operator<(const E&) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}}
+  bool operator<(const E&) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}} expected-note{{replace 'default'}}
 };
 
 int operator<=>(R, R);
@@ -43,5 +43,5 @@
 
 struct F {
   operator int() const; // expected-note {{defaulted 'operator<' is implicitly deleted because a builtin comparison function using this conversion would be the best match for the comparison}}
-  bool operator<(const F&) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}}
+  bool operator<(const F&) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}} expected-note{{replace 'default'}}
 };
Index: clang/test/CXX/class/class.compare/class.compare.default/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.compare.default/p2.cpp
+++ clang/test/CXX/class/class.compare/class.compare.default/p2.cpp
@@ -4,8 +4,8 @@
   int x;
   int &y; // expected-note 9{{because class 'A1' has a reference member}}
 
-  bool operator==(const A1&) const = default; // expected-warning {{implicitly deleted}} expected-note 2{{deleted here}}
-  bool operator<=>(const A1&) const = default; // expected-warning {{implicitly deleted}} expected-note 5{{deleted here}}
+  bool operator==(const A1&) const = default; // expected-warning {{implicitly deleted}} expected-note 2{{deleted here}} expected-note{{replace 'default'}}
+  bool operator<=>(const A1&) const = default; // expected-warning {{implicitly deleted}} expected-note 5{{deleted here}} expected-note{{replace 'default'}}
 };
 struct A2 {
   int x;
@@ -42,8 +42,8 @@
 struct A3 {
   int &x; // expected-note {{because class 'A3' has a reference member}}
 
-  bool operator==(const A3 &) const = default; // expected-warning {{implicitly deleted}}
-  bool operator<(const A3 &) const = default;  // expected-warning {{implicitly deleted}}
+  bool operator==(const A3 &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
+  bool operator<(const A3 &) const = default;  // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
   // expected-note@-1 {{because there is no viable three-way comparison function for 'A3'}}
 };
 
@@ -53,8 +53,8 @@
     int &y; // expected-note 2{{because class 'B1' has a reference member}}
   };
 
-  bool operator==(const B1&) const = default; // expected-warning {{implicitly deleted}}
-  bool operator<=>(const B1&) const = default; // expected-warning {{implicitly deleted}}
+  bool operator==(const B1&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
+  bool operator<=>(const B1&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
 };
 
 struct B2 {
@@ -76,8 +76,8 @@
 union C1 {
   int a;
 
-  bool operator==(const C1&) const = default; // expected-warning {{implicitly deleted}} expected-note {{because 'C1' is a union }}
-  bool operator<=>(const C1&) const = default; // expected-warning {{implicitly deleted}} expected-note {{because 'C1' is a union }}
+  bool operator==(const C1&) const = default; // expected-warning {{implicitly deleted}} expected-note {{because 'C1' is a union }} expected-note{{replace 'default'}}
+  bool operator<=>(const C1&) const = default; // expected-warning {{implicitly deleted}} expected-note {{because 'C1' is a union }} expected-note{{replace 'default'}}
 };
 
 union C2 {
@@ -98,8 +98,8 @@
     int a;
   };
 
-  bool operator==(const D1&) const = default; // expected-warning {{implicitly deleted}} expected-note {{because 'D1' is a union-like class}}
-  bool operator<=>(const D1&) const = default; // expected-warning {{implicitly deleted}} expected-note {{because 'D1' is a union-like class}}
+  bool operator==(const D1&) const = default; // expected-warning {{implicitly deleted}} expected-note {{because 'D1' is a union-like class}} expected-note{{replace 'default'}}
+  bool operator<=>(const D1&) const = default; // expected-warning {{implicitly deleted}} expected-note {{because 'D1' is a union-like class}} expected-note{{replace 'default'}}
 };
 struct D2 {
   union {
Index: clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
+++ clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
@@ -11,7 +11,7 @@
   friend bool operator!=(const B&, const B&) = default; // expected-error {{invalid parameter type for defaulted equality comparison}}
   friend bool operator<(const A&, const A&);
   friend bool operator<(const B&, const B&) = default; // expected-error {{invalid parameter type for defaulted relational comparison}}
-  friend bool operator>(A, A) = default; // expected-warning {{implicitly deleted}}
+  friend bool operator>(A, A) = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
 
   bool operator<(const A&) const;
   bool operator<=(const A&) const = default;
@@ -87,11 +87,11 @@
       bool operator>=(const B&, const B&); // expected-note 2{{best match}}
 
       struct B {
-        bool operator!=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
-        bool operator<(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
-        bool operator<=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
-        bool operator>(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
-        bool operator>=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
+        bool operator!=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}}
+        bool operator<(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}}
+        bool operator<=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}}
+        bool operator>(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}}
+        bool operator>=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}}
       };
       return B();
     }
@@ -144,7 +144,7 @@
   struct B {
     A a; // expected-note {{no viable three-way comparison}}
     friend bool operator==(B, B) = default; // ok
-    friend bool operator==(const B&, const B&) = default; // expected-warning {{deleted}}
+    friend bool operator==(const B&, const B&) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
   };
 }
 
Index: clang/test/CXX/class.derived/class.abstract/p16.cpp
===================================================================
--- clang/test/CXX/class.derived/class.abstract/p16.cpp
+++ clang/test/CXX/class.derived/class.abstract/p16.cpp
@@ -43,7 +43,7 @@
 // expected-error@-3 {{deleted function 'operator=' cannot override a non-deleted function}}
 // expected-note@-4 {{move assignment operator of 'G' is implicitly deleted because base class 'D' has an inaccessible move assignment operator}}
 struct H : D { // expected-note {{deleted because base class 'D' has an inaccessible move assignment}}
-  H &operator=(H&&) = default; // expected-warning {{implicitly deleted}}
+  H &operator=(H&&) = default; // expected-warning {{implicitly deleted}} expected-note{{replace '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();
Index: clang/lib/Serialization/ASTWriterDecl.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -565,6 +565,7 @@
   Record.push_back(D->isLateTemplateParsed());
   Record.push_back(D->getLinkageInternal());
   Record.AddSourceLocation(D->getEndLoc());
+  Record.AddSourceLocation(D->getDefaultLoc());
 
   Record.push_back(D->getODRHash());
 
@@ -2287,6 +2288,7 @@
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // LocEnd
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 3));   // Default/DeleteLoc
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind
   // This Array slurps the rest of the record. Fortunately we want to encode
Index: clang/lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderDecl.cpp
+++ clang/lib/Serialization/ASTReaderDecl.cpp
@@ -933,6 +933,7 @@
 
   FD->setCachedLinkage(static_cast<Linkage>(Record.readInt()));
   FD->EndRangeLoc = readSourceLocation();
+  FD->setDefaultLoc(readSourceLocation());
 
   FD->ODRHash = Record.readInt();
   FD->setHasODRHash(true);
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -7410,13 +7410,15 @@
 
   if (DefKind.isSpecialMember()
           ? CheckExplicitlyDefaultedSpecialMember(cast<CXXMethodDecl>(FD),
-                                                  DefKind.asSpecialMember())
+                                                  DefKind.asSpecialMember(),
+                                                  FD->getDefaultLoc())
           : CheckExplicitlyDefaultedComparison(S, FD, DefKind.asComparison()))
     FD->setInvalidDecl();
 }
 
 bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
-                                                 CXXSpecialMember CSM) {
+                                                 CXXSpecialMember CSM,
+                                                 SourceLocation DefaultLoc) {
   CXXRecordDecl *RD = MD->getParent();
 
   assert(MD->isExplicitlyDefaulted() && CSM != CXXInvalid &&
@@ -7608,8 +7610,11 @@
         Diag(MD->getLocation(), diag::warn_defaulted_method_deleted) << CSM;
         if (ShouldDeleteForTypeMismatch) {
           Diag(MD->getLocation(), diag::note_deleted_type_mismatch) << CSM;
-        } else {
-          ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true);
+        } else if (ShouldDeleteSpecialMember(MD, CSM, nullptr,
+                                             /*Diagnose*/ true) &&
+                   DefaultLoc.isValid()) {
+          Diag(DefaultLoc, diag::note_replace_equals_default_to_delete)
+              << FixItHint::CreateReplacement(DefaultLoc, "delete");
         }
       }
       if (ShouldDeleteForTypeMismatch && !HadError) {
@@ -8708,6 +8713,9 @@
       DefaultedComparisonAnalyzer(*this, RD, FD, DCK,
                                   DefaultedComparisonAnalyzer::ExplainDeleted)
           .visit();
+      if (FD->getDefaultLoc().isValid())
+        Diag(FD->getDefaultLoc(), diag::note_replace_equals_default_to_delete)
+            << FixItHint::CreateReplacement(FD->getDefaultLoc(), "delete");
     }
     return false;
   }
@@ -17502,6 +17510,7 @@
 
   FD->setDefaulted();
   FD->setExplicitlyDefaulted();
+  FD->setDefaultLoc(DefaultLoc);
 
   // Defer checking functions that are defaulted in a dependent context.
   if (FD->isDependentContext())
@@ -17541,7 +17550,8 @@
   } else {
     auto *MD = cast<CXXMethodDecl>(FD);
 
-    if (CheckExplicitlyDefaultedSpecialMember(MD, DefKind.asSpecialMember()))
+    if (CheckExplicitlyDefaultedSpecialMember(MD, DefKind.asSpecialMember(),
+                                              DefaultLoc))
       MD->setInvalidDecl();
     else
       DefineDefaultedFunction(*this, MD, DefaultLoc);
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -3702,6 +3702,7 @@
   ToFunction->setExplicitlyDefaulted(D->isExplicitlyDefaulted());
   ToFunction->setDeletedAsWritten(D->isDeletedAsWritten());
   ToFunction->setRangeEnd(ToEndLoc);
+  ToFunction->setDefaultLoc(D->getDefaultLoc());
 
   // Set the parameters.
   for (auto *Param : Parameters) {
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -7550,7 +7550,8 @@
   void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD);
 
   bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
-                                             CXXSpecialMember CSM);
+                                             CXXSpecialMember CSM,
+                                             SourceLocation DefaultLoc);
   void CheckDelayedMemberExceptionSpecs();
 
   bool CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *MD,
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9243,6 +9243,8 @@
 def warn_defaulted_method_deleted : Warning<
   "explicitly defaulted %sub{select_special_member_kind}0 is implicitly "
   "deleted">, InGroup<DefaultedFunctionDeleted>;
+def note_replace_equals_default_to_delete : Note<
+  "replace 'default' with 'delete'">;
 def err_out_of_line_default_deletes : Error<
   "defaulting this %sub{select_special_member_kind}0 "
   "would delete it after its first declaration">;
Index: clang/include/clang/AST/Decl.h
===================================================================
--- clang/include/clang/AST/Decl.h
+++ clang/include/clang/AST/Decl.h
@@ -1944,6 +1944,8 @@
   /// EndRangeLoc.
   SourceLocation EndRangeLoc;
 
+  SourceLocation DefaultKWLoc;
+
   /// The template or declaration that this declaration
   /// describes or was instantiated from, respectively.
   ///
@@ -2250,6 +2252,17 @@
     FunctionDeclBits.IsExplicitlyDefaulted = ED;
   }
 
+  SourceLocation getDefaultLoc() const {
+    return isExplicitlyDefaulted() ? DefaultKWLoc : SourceLocation();
+  }
+
+  void setDefaultLoc(SourceLocation NewLoc) {
+    assert(NewLoc.isInvalid() ||
+           isExplicitlyDefaulted() &&
+               "Can't set default loc is function isn't explicitly defaulted");
+    DefaultKWLoc = NewLoc;
+  }
+
   /// True if this method is user-declared and was not
   /// deleted or defaulted on its first declaration.
   bool isUserProvided() const {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to