[clang] 1376c73 - [clang] Add fix-it note to defaulted-function-deleted warning

Nathan James via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 4 11:38:31 PDT 2022


Author: Nathan James
Date: 2022-10-04T19:38:10+01:00
New Revision: 1376c73927dcb899db5d46f7b970692e2e95f9ac

URL: https://github.com/llvm/llvm-project/commit/1376c73927dcb899db5d46f7b970692e2e95f9ac
DIFF: https://github.com/llvm/llvm-project/commit/1376c73927dcb899db5d46f7b970692e2e95f9ac.diff

LOG: [clang] Add fix-it note to defaulted-function-deleted warning

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

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D134549

Added: 
    clang/test/SemaCXX/explicitly-defaulted.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    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/microsoft-dtor-lookup-cxx11.cpp
    clang/test/SemaObjCXX/arc-0x.mm

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 9ece988929f4f..93974e89eec14 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -229,6 +229,8 @@ Improvements to Clang's diagnostics
   doesn't generate strange cascading errors, particularly in cases where a
   subsuming constraint fails, which would result in a less-specific overload to
   be selected.
+- Add a fix-it hint for the ``-Wdefaulted-function-deleted`` warning to
+  explicitly delete the function.
 
 Non-comprehensive list of changes in this release
 -------------------------------------------------

diff  --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 3ff2e2633f4d5..6a6db7a0c34c5 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -1944,6 +1944,8 @@ class FunctionDecl : public DeclaratorDecl,
   /// EndRangeLoc.
   SourceLocation EndRangeLoc;
 
+  SourceLocation DefaultKWLoc;
+
   /// The template or declaration that this declaration
   /// describes or was instantiated from, respectively.
   ///
@@ -2250,6 +2252,17 @@ class FunctionDecl : public DeclaratorDecl,
     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 {

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f53b67dd5df13..fd6651ee5d25f 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9261,6 +9261,8 @@ def err_incorrect_defaulted_consteval : Error<
 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">;

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9883176cd764d..37fcfd2940d76 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7631,7 +7631,8 @@ class Sema final {
   void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD);
 
   bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
-                                             CXXSpecialMember CSM);
+                                             CXXSpecialMember CSM,
+                                             SourceLocation DefaultLoc);
   void CheckDelayedMemberExceptionSpecs();
 
   bool CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *MD,

diff  --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 988fa6349a03e..5c64cf08f8e1b 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3587,6 +3587,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
   auto TInfo = importChecked(Err, FromTSI);
   auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
   auto ToEndLoc = importChecked(Err, D->getEndLoc());
+  auto ToDefaultLoc = importChecked(Err, D->getDefaultLoc());
   auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
   auto TrailingRequiresClause =
       importChecked(Err, D->getTrailingRequiresClause());
@@ -3707,6 +3708,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
   ToFunction->setFriendConstraintRefersToEnclosingTemplate(
       D->FriendConstraintRefersToEnclosingTemplate());
   ToFunction->setRangeEnd(ToEndLoc);
+  ToFunction->setDefaultLoc(ToDefaultLoc);
 
   // Set the parameters.
   for (auto *Param : Parameters) {

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 6af546958c4f0..82171f64a1d7b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7410,13 +7410,15 @@ void Sema::CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *FD) {
 
   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 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
         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 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
       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;
   }
@@ -17530,6 +17538,7 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
 
   FD->setDefaulted();
   FD->setExplicitlyDefaulted();
+  FD->setDefaultLoc(DefaultLoc);
 
   // Defer checking functions that are defaulted in a dependent context.
   if (FD->isDependentContext())
@@ -17569,7 +17578,8 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
   } else {
     auto *MD = cast<CXXMethodDecl>(FD);
 
-    if (CheckExplicitlyDefaultedSpecialMember(MD, DefKind.asSpecialMember()))
+    if (CheckExplicitlyDefaultedSpecialMember(MD, DefKind.asSpecialMember(),
+                                              DefaultLoc))
       MD->setInvalidDecl();
     else
       DefineDefaultedFunction(*this, MD, DefaultLoc);

diff  --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 5ada9f66f2028..b7abcfa8a0ecd 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -934,6 +934,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
 
   FD->setCachedLinkage(static_cast<Linkage>(Record.readInt()));
   FD->EndRangeLoc = readSourceLocation();
+  FD->setDefaultLoc(readSourceLocation());
 
   FD->ODRHash = Record.readInt();
   FD->setHasODRHash(true);

diff  --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 6d9d0ed8dc1d7..f9858a52ae176 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -566,6 +566,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
   Record.push_back(D->FriendConstraintRefersToEnclosingTemplate());
   Record.push_back(D->getLinkageInternal());
   Record.AddSourceLocation(D->getEndLoc());
+  Record.AddSourceLocation(D->getDefaultLoc());
 
   Record.push_back(D->getODRHash());
 
@@ -2289,6 +2290,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // FriendConstraintRefersToEnclosingTemplate
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // LocEnd
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // Default
   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

diff  --git a/clang/test/CXX/class.derived/class.abstract/p16.cpp b/clang/test/CXX/class.derived/class.abstract/p16.cpp
index e4bca4248b173..e02dc39dbbcd6 100644
--- a/clang/test/CXX/class.derived/class.abstract/p16.cpp
+++ b/clang/test/CXX/class.derived/class.abstract/p16.cpp
@@ -43,7 +43,7 @@ struct G : D {};
 // expected-error at -3 {{deleted function 'operator=' cannot override a non-deleted function}}
 // expected-note at -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 at -1 {{deleted function 'operator=' cannot override a non-deleted function}}
   // expected-note at -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/class/class.compare/class.compare.default/p1.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
index 42196665ba069..18b4e271c4bf7 100644
--- a/clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
+++ b/clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
@@ -11,7 +11,7 @@ struct A {
   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 @@ namespace LookupContext {
       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 @@ namespace P1946 {
   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'}}
   };
 }
 

diff  --git a/clang/test/CXX/class/class.compare/class.compare.default/p2.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p2.cpp
index a1653d85abbf0..dfa9b8fd99331 100644
--- a/clang/test/CXX/class/class.compare/class.compare.default/p2.cpp
+++ b/clang/test/CXX/class/class.compare/class.compare.default/p2.cpp
@@ -4,8 +4,8 @@ struct A1 {
   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 @@ void f(A2 a) {
 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 at -1 {{because there is no viable three-way comparison function for 'A3'}}
 };
 
@@ -53,8 +53,8 @@ struct B1 {
     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 @@ struct B2 {
 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 @@ struct D1 {
     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 {

diff  --git a/clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp b/clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
index 7226d565b6c3e..07d43f15aac14 100644
--- a/clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
+++ b/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 at -1 {{defaulted 'operator!=' is implicitly deleted because there is no viable 'operator==' for 'A'}}
 };
 
@@ -9,7 +9,7 @@ struct Q {};
 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 B2 {
 
 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 at -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 E2 {
 
 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'}}
 };

diff  --git a/clang/test/CXX/class/class.compare/class.eq/p2.cpp b/clang/test/CXX/class/class.compare/class.eq/p2.cpp
index b98cef80925ad..7cb07b784bc28 100644
--- a/clang/test/CXX/class/class.compare/class.eq/p2.cpp
+++ b/clang/test/CXX/class/class.compare/class.eq/p2.cpp
@@ -17,19 +17,19 @@ struct G { bool operator==(G) const = delete; }; // expected-note {{deleted here
 
 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 at -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 at -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 at -1 {{because there is no viable three-way comparison function for 'H3'}}
   int H3::*x;
 };
@@ -72,8 +72,8 @@ namespace Access {
     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 @@ namespace Access {
   };
   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 @@ namespace Access {
     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 {

diff  --git a/clang/test/CXX/class/class.compare/class.rel/p2.cpp b/clang/test/CXX/class/class.compare/class.rel/p2.cpp
index 21a68f9f4c67b..90115284d2bd0 100644
--- a/clang/test/CXX/class/class.compare/class.rel/p2.cpp
+++ b/clang/test/CXX/class/class.compare/class.rel/p2.cpp
@@ -22,10 +22,10 @@ namespace Rel {
 
   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 @@ namespace Rel {
     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 @@ namespace NotEqual {
 
   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 @@ namespace NotEqual {
     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 @@ namespace Access {
     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 at -1 {{defaulted 'operator<' is implicitly deleted because it would invoke a private 'operator<=>' member of 'Access::A'}}
   };
 }

diff  --git a/clang/test/CXX/class/class.compare/class.spaceship/p1.cpp b/clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
index e2ee3880818f4..c5e7226364660 100644
--- a/clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
+++ b/clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
@@ -150,7 +150,7 @@ namespace Access {
   };
   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 @@ namespace Access {
   };
   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'}}
   };
 }
 

diff  --git a/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp b/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
index b6e135e0f8654..5648cea862a1b 100644
--- a/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
+++ b/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
@@ -42,7 +42,7 @@ namespace DeducedNotCat {
   };
   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 @@ namespace DeducedVsSynthesized {
   };
   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 @@ namespace PR44723 {
     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 BadDeducedType {
 
 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 @@ namespace PR50591 {
     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}}
   };
 

diff  --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp
index 6e61b56555b20..527379590bd39 100644
--- a/clang/test/CXX/drs/dr6xx.cpp
+++ b/clang/test/CXX/drs/dr6xx.cpp
@@ -776,7 +776,7 @@ namespace dr666 { // dr666: yes
 #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), "");

diff  --git a/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
index f8a40f97c9791..e816110d6dc22 100644
--- a/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
+++ b/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
@@ -113,7 +113,7 @@ has_friend hf;
 
 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}}
 

diff  --git a/clang/test/SemaCXX/dr1301.cpp b/clang/test/SemaCXX/dr1301.cpp
index b7dc91d563300..73701e1fe7236 100644
--- a/clang/test/SemaCXX/dr1301.cpp
+++ b/clang/test/SemaCXX/dr1301.cpp
@@ -17,7 +17,7 @@ struct C {
 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}}

diff  --git a/clang/test/SemaCXX/explicitly-defaulted.cpp b/clang/test/SemaCXX/explicitly-defaulted.cpp
new file mode 100644
index 0000000000000..724f7bbbc30b6
--- /dev/null
+++ b/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}}

diff  --git a/clang/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp b/clang/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp
index 000492e0edf19..5c222d7a2f837 100644
--- a/clang/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp
+++ b/clang/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp
@@ -7,7 +7,7 @@ struct S {
 } 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}}

diff  --git a/clang/test/SemaObjCXX/arc-0x.mm b/clang/test/SemaObjCXX/arc-0x.mm
index 734f28a65eb6e..b7f27e4e19db9 100644
--- a/clang/test/SemaObjCXX/arc-0x.mm
+++ b/clang/test/SemaObjCXX/arc-0x.mm
@@ -121,12 +121,12 @@ void test() {
 
   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();


        


More information about the cfe-commits mailing list