Skip to content

Commit 7599095

Browse files
committed
Fix crash if a user-defined conversion is applied in the middle of a
rewrite of an operator in terms of operator<=>.
1 parent 757bc55 commit 7599095

File tree

4 files changed

+27
-1
lines changed

4 files changed

+27
-1
lines changed

clang/include/clang/AST/Expr.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,16 @@ class Expr : public ValueStmt {
792792
return const_cast<Expr *>(this)->IgnoreImplicit();
793793
}
794794

795+
/// Skip past any implicit AST nodes which might surround this expression
796+
/// until reaching a fixed point. Same as IgnoreImplicit, except that it
797+
/// also skips over implicit calls to constructors and conversion functions.
798+
///
799+
/// FIXME: Should IgnoreImplicit do this?
800+
Expr *IgnoreImplicitAsWritten() LLVM_READONLY;
801+
const Expr *IgnoreImplicitAsWritten() const {
802+
return const_cast<Expr *>(this)->IgnoreImplicitAsWritten();
803+
}
804+
795805
/// Skip past any parentheses which might surround this expression until
796806
/// reaching a fixed point. Skips:
797807
/// * ParenExpr

clang/lib/AST/Expr.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2893,6 +2893,13 @@ static Expr *IgnoreImplicitSingleStep(Expr *E) {
28932893
return E;
28942894
}
28952895

2896+
static Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) {
2897+
if (auto *ICE = dyn_cast<ImplicitCastExpr>(E))
2898+
return ICE->getSubExprAsWritten();
2899+
2900+
return IgnoreImplicitSingleStep(E);
2901+
}
2902+
28962903
static Expr *IgnoreParensSingleStep(Expr *E) {
28972904
if (auto *PE = dyn_cast<ParenExpr>(E))
28982905
return PE->getSubExpr();
@@ -2972,6 +2979,10 @@ Expr *Expr::IgnoreImplicit() {
29722979
return IgnoreExprNodes(this, IgnoreImplicitSingleStep);
29732980
}
29742981

2982+
Expr *Expr::IgnoreImplicitAsWritten() {
2983+
return IgnoreExprNodes(this, IgnoreImplicitAsWrittenSingleStep);
2984+
}
2985+
29752986
Expr *Expr::IgnoreParens() {
29762987
return IgnoreExprNodes(this, IgnoreParensSingleStep);
29772988
}

clang/lib/AST/ExprCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ CXXRewrittenBinaryOperator::getDecomposedForm() const {
107107
return Result;
108108

109109
// Otherwise, we expect a <=> to now be on the LHS.
110-
E = Result.LHS->IgnoreImplicit();
110+
E = Result.LHS->IgnoreImplicitAsWritten();
111111
if (auto *BO = dyn_cast<BinaryOperator>(E)) {
112112
assert(BO->getOpcode() == BO_Cmp);
113113
Result.LHS = BO->getLHS();

clang/test/SemaCXX/compare-cxx2a.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,11 @@ void test_user_conv() {
361361
}
362362
}
363363

364+
struct X {
365+
constexpr const Conv<int, -1> operator<=>(X) { return {}; }
366+
};
367+
static_assert(X() < X());
368+
364369
} // namespace TestUserDefinedConvSeq
365370

366371
void test_array_conv() {

0 commit comments

Comments
 (0)