Skip to content

Commit cafc741

Browse files
committed
[c++20] Synthesis of defaulted comparison functions.
Array members are not yet handled. In addition, defaulted comparisons can't yet find comparison operators by unqualified lookup (only by member lookup and ADL). These issues will be fixed in follow-on changes.
1 parent 27f5d35 commit cafc741

File tree

16 files changed

+743
-59
lines changed

16 files changed

+743
-59
lines changed

clang/include/clang/AST/Decl.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,6 +2115,16 @@ class FunctionDecl : public DeclaratorDecl,
21152115
FunctionDeclBits.IsExplicitlyDefaulted = ED;
21162116
}
21172117

2118+
/// True if this method is user-declared and was not
2119+
/// deleted or defaulted on its first declaration.
2120+
bool isUserProvided() const {
2121+
auto *DeclAsWritten = this;
2122+
if (FunctionDecl *Pattern = getTemplateInstantiationPattern())
2123+
DeclAsWritten = Pattern;
2124+
return !(DeclAsWritten->isDeleted() ||
2125+
DeclAsWritten->getCanonicalDecl()->isDefaulted());
2126+
}
2127+
21182128
/// Whether falling off this function implicitly returns null/zero.
21192129
/// If a more specific implicit return value is required, front-ends
21202130
/// should synthesize the appropriate return statements.

clang/include/clang/AST/DeclCXX.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,16 +1995,6 @@ class CXXMethodDecl : public FunctionDecl {
19951995
return const_cast<CXXMethodDecl*>(this)->getMostRecentDecl();
19961996
}
19971997

1998-
/// True if this method is user-declared and was not
1999-
/// deleted or defaulted on its first declaration.
2000-
bool isUserProvided() const {
2001-
auto *DeclAsWritten = this;
2002-
if (auto *Pattern = getTemplateInstantiationPattern())
2003-
DeclAsWritten = cast<CXXMethodDecl>(Pattern);
2004-
return !(DeclAsWritten->isDeleted() ||
2005-
DeclAsWritten->getCanonicalDecl()->isDefaulted());
2006-
}
2007-
20081998
void addOverriddenMethod(const CXXMethodDecl *MD);
20091999

20102000
using method_iterator = const CXXMethodDecl *const *;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1732,7 +1732,10 @@ def note_ivar_decl : Note<"instance variable is declared here">;
17321732
def note_bitfield_decl : Note<"bit-field is declared here">;
17331733
def note_implicit_param_decl : Note<"%0 is an implicit parameter">;
17341734
def note_member_synthesized_at : Note<
1735-
"in implicit %sub{select_special_member_kind}0 for %1 "
1735+
"in %select{implicit|defaulted}0 %sub{select_special_member_kind}1 for %2 "
1736+
"first required here">;
1737+
def note_comparison_synthesized_at : Note<
1738+
"in defaulted %sub{select_defaulted_comparison_kind}0 for %1 "
17361739
"first required here">;
17371740
def err_missing_default_ctor : Error<
17381741
"%select{constructor for %1 must explicitly initialize the|"

clang/include/clang/Sema/Sema.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3319,7 +3319,12 @@ class Sema final {
33193319
const UnresolvedSetImpl &Fns,
33203320
Expr *LHS, Expr *RHS,
33213321
bool RequiresADL = true,
3322-
bool AllowRewrittenCandidates = true);
3322+
bool AllowRewrittenCandidates = true,
3323+
FunctionDecl *DefaultedFn = nullptr);
3324+
ExprResult BuildSynthesizedThreeWayComparison(SourceLocation OpLoc,
3325+
const UnresolvedSetImpl &Fns,
3326+
Expr *LHS, Expr *RHS,
3327+
FunctionDecl *DefaultedFn);
33233328

33243329
ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
33253330
SourceLocation RLoc,
@@ -6516,6 +6521,8 @@ class Sema final {
65166521

65176522
bool CheckExplicitlyDefaultedComparison(FunctionDecl *MD,
65186523
DefaultedComparisonKind DCK);
6524+
void DefineDefaultedComparison(SourceLocation Loc, FunctionDecl *FD,
6525+
DefaultedComparisonKind DCK);
65196526

65206527
//===--------------------------------------------------------------------===//
65216528
// C++ Derived Classes

clang/lib/AST/ExprConstant.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6830,6 +6830,36 @@ class ExprEvaluatorBase
68306830
return StmtVisitorTy::Visit(Source);
68316831
}
68326832

6833+
bool VisitPseudoObjectExpr(const PseudoObjectExpr *E) {
6834+
for (const Expr *SemE : E->semantics()) {
6835+
if (auto *OVE = dyn_cast<OpaqueValueExpr>(SemE)) {
6836+
// FIXME: We can't handle the case where an OpaqueValueExpr is also the
6837+
// result expression: there could be two different LValues that would
6838+
// refer to the same object in that case, and we can't model that.
6839+
if (SemE == E->getResultExpr())
6840+
return Error(E);
6841+
6842+
// Unique OVEs get evaluated if and when we encounter them when
6843+
// emitting the rest of the semantic form, rather than eagerly.
6844+
if (OVE->isUnique())
6845+
continue;
6846+
6847+
LValue LV;
6848+
if (!Evaluate(Info.CurrentCall->createTemporary(
6849+
OVE, getStorageType(Info.Ctx, OVE), false, LV),
6850+
Info, OVE->getSourceExpr()))
6851+
return false;
6852+
} else if (SemE == E->getResultExpr()) {
6853+
if (!StmtVisitorTy::Visit(SemE))
6854+
return false;
6855+
} else {
6856+
if (!EvaluateIgnoredValue(Info, SemE))
6857+
return false;
6858+
}
6859+
}
6860+
return true;
6861+
}
6862+
68336863
bool VisitCallExpr(const CallExpr *E) {
68346864
APValue Result;
68356865
if (!handleCallExpr(E, Result, nullptr))

0 commit comments

Comments
 (0)