yronglin updated this revision to Diff 536802.
yronglin added a comment.

Address comment.

- Change `EvaluateDependentExpr`.
- Add more test for do/while/for/return/ctor.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D153296/new/

https://reviews.llvm.org/D153296

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/SemaCXX/constexpr-function-recovery-crash.cpp

Index: clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
===================================================================
--- clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
+++ clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
@@ -78,6 +78,132 @@
 constexpr int test12() { return "wrong"; } // expected-error {{cannot initialize return object of type 'int'}}
 constexpr int force12 = test12();          // expected-error {{must be initialized by a constant}}
 
+constexpr int test13() {
+    switch (invalid_value) { // expected-error {{use of undeclared identifier}}
+    case 0:
+        return 7;
+    default:
+        break;
+    }
+    return 0;
+}
+
+static_assert(test13(), "should not crash"); // expected-error {{static assertion expression is not an integral constant expression}}
+
+constexpr int test14() {
+    int sum = 0;
+    for (int i = 0; i < invalid_value; ++i) // expected-error {{use of undeclared identifier}}
+        sum = sum + i;
+    return sum;
+}
+
+static_assert(test14(), "should not crash"); // expected-error {{static assertion failed due to requirement}}
+
+constexpr int test15() {
+    int sum = 0;
+    for (int i = 0; i < 10; i += invalid_value) // expected-error {{use of undeclared identifier}}
+        sum = sum + i;
+    return sum;
+}
+
+static_assert(test15(), "should not crash"); // expected-error {{static assertion expression is not an integral constant expression}}
+
+constexpr int test16() {
+    int sum = 0;
+    for (int i = invalid_value; i < 10; ++i) // expected-error {{use of undeclared identifier}}
+        sum = sum + i;
+    return sum;
+}
+
+static_assert(test16(), "should not crash"); // expected-error {{static assertion expression is not an integral constant expression}}
+
+constexpr int test17() {
+    int sum = 0, i = 0;
+    do
+      sum += i;
+    while (invalid_value); // expected-error {{use of undeclared identifier}}
+    return sum;
+}
+
+static_assert(test17(), "should not crash"); // expected-error {{static assertion failed due to requirement}}
+
+constexpr int test18() {
+  int sum = 0, i = 0;
+  while (invalid_value) // expected-error {{use of undeclared identifier}}
+    sum += i;
+  return sum;
+}
+
+static_assert(test18(), "should not crash"); // expected-error {{static assertion expression is not an integral constant expression}}
+
+constexpr int test19() {
+    struct Test19 {
+        int a[2] = {0, 1};
+        constexpr const int *begin() const {
+            return invalid_value;  // expected-error {{use of undeclared identifier}}
+        }
+        constexpr const int *end() const {
+            return a + 2;
+        }
+    };
+
+    int sum = 0;
+    Test19 t;
+    for (const auto v : t) {
+        sum += v;
+    }
+    return sum;
+}
+
+static_assert(test19(), "should not crash"); // expected-error {{static assertion expression is not an integral constant expression}}
+
+constexpr int test20() {
+    struct Test20 {
+        int a[2] = {0, 1};
+        constexpr const int *begin() const {
+            return a;
+        }
+        constexpr const int *end() const {
+            return invalid_value;  // expected-error {{use of undeclared identifier}}
+        }
+    };
+
+    int sum = 0;
+    Test20 t;
+    for (const auto v : t) {
+        sum += v;
+    }
+    return sum;
+}
+
+static_assert(test20(), "should not crash"); // expected-error {{static assertion expression is not an integral constant expression}}
+
+constexpr int test21() {
+  return invalid_value; // expected-error {{use of undeclared identifier}}
+}
+
+static_assert(test21(), "should not crash"); // expected-error {{static assertion expression is not an integral constant expression}}
+
+constexpr int test22() {
+  struct Test22 {
+    int value = invalid_value; // expected-error {{use of undeclared identifier}}
+  };
+  return Test22().value;
+}
+
+static_assert(test22(), "should not crash"); // expected-error {{static assertion expression is not an integral constant expression}}
+
+constexpr int test23() {
+  struct Test23 {
+    int value;
+    constexpr Test23(int v) : value(v) {}
+    constexpr Test23(int a, int b) : Test23(a * b * invalid_value) {} // expected-error {{use of undeclared identifier}}
+  };
+  return Test23(1, 2).value;
+}
+
+static_assert(test23(), "should not crash"); // expected-error {{static assertion expression is not an integral constant expression}}
+
 #define TEST_EVALUATE(Name, X)         \
   constexpr int testEvaluate##Name() { \
     X return 0;                        \
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -4913,11 +4913,20 @@
 
 static bool EvaluateDependentExpr(const Expr *E, EvalInfo &Info) {
   assert(E->isValueDependent());
-  if (Info.noteSideEffect())
-    return true;
+  // Note that we have a side effect that matters for constant evaluation.
+  bool SideEffects = Info.noteSideEffect();
+  // If the reason we're here is because of a recovery expression, we don't
+  // want to continue to evaluate further as we will never know what the actual
+  // value is.
+  if (isa<RecoveryExpr>(E))
+    return false;
+
+  // Otherwise, return whether we want to continue after noting the side
+  // effects, which should only happen if the expression has errors but isn't
+  // a recovery expression on its own.
   assert(E->containsErrors() && "valid value-dependent expression should never "
                                 "reach invalid code path.");
-  return false;
+  return SideEffects;
 }
 
 /// Evaluate a condition (either a variable declaration or an expression).
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -568,6 +568,9 @@
 - Clang now correctly evaluates ``__has_extension (cxx_defaulted_functions)``
   and ``__has_extension (cxx_default_function_template_args)`` to 1.
   (`#61758 <https://github.com/llvm/llvm-project/issues/61758>`_)
+- Stop evaluating a constant expression if the condition expression which in
+  switch statement contains errors.
+  (`#63453 <https://github.com/llvm/llvm-project/issues/63453>_`)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to