Author: Nathan Sidwell Date: 2021-12-20T08:47:54-08:00 New Revision: 23b2045eef45884566722d06f3e09224a0f6dc6c
URL: https://github.com/llvm/llvm-project/commit/23b2045eef45884566722d06f3e09224a0f6dc6c DIFF: https://github.com/llvm/llvm-project/commit/23b2045eef45884566722d06f3e09224a0f6dc6c.diff LOG: [clang] p2085 out-of-class comparison operator defaulting Commit 5fbe21a7748f missed committing the correct checking of out-of-class comparision operator argument types. These are they, from the originally posted diff. Reviewed By: mizvekov Differential Revision: https://reviews.llvm.org/D115894 Added: Modified: clang/lib/Sema/SemaDeclCXX.cpp clang/test/CXX/class/class.compare/class.compare.default/p1.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 119cdf2a3d3c0..01f0079198c74 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8531,8 +8531,6 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, QualType PlainTy = Context.getRecordType(RD); QualType RefTy = Context.getLValueReferenceType(PlainTy.withConst()); - if (IsMethod) - PlainTy = QualType(); Diag(FD->getLocation(), diag::err_defaulted_comparison_param) << int(DCK) << ParmTy << RefTy << int(!IsMethod) << PlainTy << Param->getSourceRange(); @@ -17266,10 +17264,13 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { // that we've marked it as defaulted. FD->setWillHaveBody(false); - // If this is a comparison's defaulted definition within the record, do - // the checking when the record is complete. - if (DefKind.isComparison() && isa<CXXRecordDecl>(FD->getLexicalDeclContext())) - return; + if (DefKind.isComparison()) { + // If this comparison's defaulting occurs within the definition of its + // lexical class context, we have to do the checking when complete. + if (auto const *RD = dyn_cast<CXXRecordDecl>(FD->getLexicalDeclContext())) + if (!RD->isCompleteDefinition()) + return; + } // If this member fn was defaulted on its first declaration, we will have // already performed the checking in CheckCompletedCXXClass. Such a 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 136afd8996432..4bfd27461ed5e 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 @@ -115,6 +115,28 @@ namespace LookupContext { } } +namespace evil1 { +template <class T> struct Bad { + // expected-error@+1{{found 'const float &'}} + bool operator==(T const &) const = default; + Bad(int = 0); +}; + +template <class T> struct Weird { + // expected-error@+1{{'float' cannot be used prior to '::'}} + bool operator==(typename T::Weird_ const &) const = default; + Weird(int = 0); +}; + +struct evil { + using Weird_ = Weird<evil>; +}; +template struct Bad<float>; // expected-note{{evil1::Bad<float>' requested}} +template struct Weird<float>; // expected-note{{evil1::Weird<float>' requested}} +template struct Weird<evil>; + +} // namespace evil1 + namespace P1946 { struct A { friend bool operator==(A &, A &); // expected-note {{would lose const qualifier}} @@ -161,5 +183,40 @@ enum e {}; bool operator==(e, int) = default; // expected-error{{expected class or reference to a constant class}} bool operator==(e *, int *) = default; // expected-error{{must have at least one}} - } // namespace p2085 + +namespace p2085_2 { +template <class T> struct S6 { + // expected-error@+2{{found 'const int &'}} + // expected-error@+1{{found 'const float &'}} + bool operator==(T const &) const; +}; +template <class T> bool S6<T>::operator==(T const &) const = default; + +template struct S6<int>; // expected-note{{S6<int>::operator==' requested}} + +void f1() { + S6<float> a; + (void)(a == 0); // expected-note{{S6<float>::operator==' requested}} +} + +template <class T> struct S7 { + // expected-error@+2{{'float' cannot be used}} + // expected-error@+1{{'int' cannot be used}} + bool operator==(typename T::S7_ const &) const; + S7(int = 0); +}; +template <class T> bool S7<T>::operator==(typename T::S7_ const &) const = default; + +struct evil { + using S7_ = S7<evil>; +}; +template struct S7<float>; // expected-note{{S7<float>' requested}} + +void f2() { + S7<int> a; // expected-note{{S7<int>' requested}} + S7<evil> b; + (void)(a == 0); // expected-error{{invalid operands}} + (void)(b == 0); +} +} // namespace p2085_2 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits