[clang] 7599095 - Fix crash if a user-defined conversion is applied in the middle of a

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 5 18:46:53 PST 2019


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() {


        


More information about the cfe-commits mailing list