aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorJens Massberg <massberg@google.com>2023-04-21 16:41:43 +0200
committerJens Massberg <massberg@google.com>2023-06-07 12:56:35 +0200
commit593a2740f7a499e35f19e64d180d0b8246b52ba3 (patch)
treed2d2124b4cbd35f7b0c2922e3d3cf877e027bff7 /clang/lib
parent4e312abdfd4fb9d60afe6590588092ba0bfb23c9 (diff)
downloadllvm-593a2740f7a499e35f19e64d180d0b8246b52ba3.zip
llvm-593a2740f7a499e35f19e64d180d0b8246b52ba3.tar.gz
llvm-593a2740f7a499e35f19e64d180d0b8246b52ba3.tar.bz2
[clang] Show error if defaulted comparions operator function is volatile or has ref-qualifier &&.
This patch implemed the change proposed in [P2002R1] to 11.11.1 [class.compare.default] paragraph 1. A defaulted compariosn operator function must be non-volatile and must either have no ref-qualifier or the ref-qualifier &. Differential Revision: https://reviews.llvm.org/D148924
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp26
1 files changed, 24 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 3169b38..9b3bcc2 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -8582,8 +8582,8 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
// C++2a [class.compare.default]p1:
// A defaulted comparison operator function for some class C shall be a
// non-template function declared in the member-specification of C that is
- // -- a non-static const member of C having one parameter of type
- // const C&, or
+ // -- a non-static const non-volatile member of C having one parameter of
+ // type const C& and either no ref-qualifier or the ref-qualifier &, or
// -- a friend of C having two parameters of type const C& or two
// parameters of type C.
@@ -8593,6 +8593,17 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
auto *MD = cast<CXXMethodDecl>(FD);
assert(!MD->isStatic() && "comparison function cannot be a static member");
+ if (MD->getRefQualifier() == RQ_RValue) {
+ Diag(MD->getLocation(), diag::err_ref_qualifier_comparison_operator);
+
+ // Remove the ref qualifier to recover.
+ const auto *FPT = MD->getType()->castAs<FunctionProtoType>();
+ FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+ EPI.RefQualifier = RQ_None;
+ MD->setType(Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), EPI));
+ }
+
// If we're out-of-class, this is the class we're comparing.
if (!RD)
RD = MD->getParent();
@@ -8615,6 +8626,17 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
MD->setType(Context.getFunctionType(FPT->getReturnType(),
FPT->getParamTypes(), EPI));
}
+
+ if (MD->isVolatile()) {
+ Diag(MD->getLocation(), diag::err_volatile_comparison_operator);
+
+ // Remove the 'volatile' from the type to recover.
+ const auto *FPT = MD->getType()->castAs<FunctionProtoType>();
+ FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+ EPI.TypeQuals.removeVolatile();
+ MD->setType(Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), EPI));
+ }
}
if (FD->getNumParams() != (IsMethod ? 1 : 2)) {