diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -226,6 +226,8 @@ 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 --- a/clang/include/clang/AST/Decl.h +++ b/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 { diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9259,6 +9259,8 @@ def warn_defaulted_method_deleted : Warning< "explicitly defaulted %sub{select_special_member_kind}0 is implicitly " "deleted">, InGroup; +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 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7631,7 +7631,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, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -3587,6 +3587,7 @@ 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 @@ 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 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7410,13 +7410,15 @@ if (DefKind.isSpecialMember() ? CheckExplicitlyDefaultedSpecialMember(cast(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; } @@ -17530,6 +17538,7 @@ FD->setDefaulted(); FD->setExplicitlyDefaulted(); + FD->setDefaultLoc(DefaultLoc); // Defer checking functions that are defaulted in a dependent context. if (FD->isDependentContext()) @@ -17569,7 +17578,8 @@ } else { auto *MD = cast(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 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -934,6 +934,7 @@ FD->setCachedLinkage(static_cast(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 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -566,6 +566,7 @@ 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 @@ 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 --- a/clang/test/CXX/class.derived/class.abstract/p16.cpp +++ b/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(); 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 --- 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 @@ 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'}} }; } 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 --- 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 @@ 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 { 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 --- 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@-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'}} }; diff --git a/clang/test/CXX/class/class.compare/class.eq/p2.cpp b/clang/test/CXX/class/class.compare/class.eq/p2.cpp --- 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 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 { diff --git a/clang/test/CXX/class/class.compare/class.rel/p2.cpp b/clang/test/CXX/class/class.compare/class.rel/p2.cpp --- 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 @@ 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'}} }; } diff --git a/clang/test/CXX/class/class.compare/class.spaceship/p1.cpp b/clang/test/CXX/class/class.compare/class.spaceship/p1.cpp --- 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 @@ }; 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'}} }; } diff --git a/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp b/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp --- 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 @@ }; 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}} }; diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp --- a/clang/test/CXX/drs/dr6xx.cpp +++ b/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), ""); diff --git a/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp --- a/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp +++ b/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}} diff --git a/clang/test/SemaCXX/dr1301.cpp b/clang/test/SemaCXX/dr1301.cpp --- a/clang/test/SemaCXX/dr1301.cpp +++ b/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}} diff --git a/clang/test/SemaCXX/explicitly-defaulted.cpp b/clang/test/SemaCXX/explicitly-defaulted.cpp new file mode 100644 --- /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 +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; + +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 --- a/clang/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp +++ b/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}} diff --git a/clang/test/SemaObjCXX/arc-0x.mm b/clang/test/SemaObjCXX/arc-0x.mm --- a/clang/test/SemaObjCXX/arc-0x.mm +++ b/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();