Author: Richard Smith Date: 2019-12-05T18:44:15-08:00 New Revision: 759909506c2b557b9bc5cd3883970dea48e0b86b
URL: https://github.com/llvm/llvm-project/commit/759909506c2b557b9bc5cd3883970dea48e0b86b DIFF: https://github.com/llvm/llvm-project/commit/759909506c2b557b9bc5cd3883970dea48e0b86b.diff LOG: Fix crash if a user-defined conversion is applied in the middle of a rewrite of an operator in terms of operator<=>. Added: Modified: clang/include/clang/AST/Expr.h clang/lib/AST/Expr.cpp clang/lib/AST/ExprCXX.cpp clang/test/SemaCXX/compare-cxx2a.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 867615ded162..afb710efe792 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -792,6 +792,16 @@ class Expr : public ValueStmt { return const_cast<Expr *>(this)->IgnoreImplicit(); } + /// Skip past any implicit AST nodes which might surround this expression + /// until reaching a fixed point. Same as IgnoreImplicit, except that it + /// also skips over implicit calls to constructors and conversion functions. + /// + /// FIXME: Should IgnoreImplicit do this? + Expr *IgnoreImplicitAsWritten() LLVM_READONLY; + const Expr *IgnoreImplicitAsWritten() const { + return const_cast<Expr *>(this)->IgnoreImplicitAsWritten(); + } + /// Skip past any parentheses which might surround this expression until /// reaching a fixed point. Skips: /// * ParenExpr diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 3bc2ea60aa14..c4c8fcf25495 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2893,6 +2893,13 @@ static Expr *IgnoreImplicitSingleStep(Expr *E) { return E; } +static Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) { + if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) + return ICE->getSubExprAsWritten(); + + return IgnoreImplicitSingleStep(E); +} + static Expr *IgnoreParensSingleStep(Expr *E) { if (auto *PE = dyn_cast<ParenExpr>(E)) return PE->getSubExpr(); @@ -2972,6 +2979,10 @@ Expr *Expr::IgnoreImplicit() { return IgnoreExprNodes(this, IgnoreImplicitSingleStep); } +Expr *Expr::IgnoreImplicitAsWritten() { + return IgnoreExprNodes(this, IgnoreImplicitAsWrittenSingleStep); +} + Expr *Expr::IgnoreParens() { return IgnoreExprNodes(this, IgnoreParensSingleStep); } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index bef181ed4cf7..deb76820afe5 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -107,7 +107,7 @@ CXXRewrittenBinaryOperator::getDecomposedForm() const { return Result; // Otherwise, we expect a <=> to now be on the LHS. - E = Result.LHS->IgnoreImplicit(); + E = Result.LHS->IgnoreImplicitAsWritten(); if (auto *BO = dyn_cast<BinaryOperator>(E)) { assert(BO->getOpcode() == BO_Cmp); Result.LHS = BO->getLHS(); diff --git a/clang/test/SemaCXX/compare-cxx2a.cpp b/clang/test/SemaCXX/compare-cxx2a.cpp index 28854a77fb24..1aca2dd86c58 100644 --- a/clang/test/SemaCXX/compare-cxx2a.cpp +++ b/clang/test/SemaCXX/compare-cxx2a.cpp @@ -361,6 +361,11 @@ void test_user_conv() { } } +struct X { + constexpr const Conv<int, -1> operator<=>(X) { return {}; } +}; +static_assert(X() < X()); + } // namespace TestUserDefinedConvSeq void test_array_conv() { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits