c++: Make contract assertions have side effects [PR125904]
gcc/cp/ChangeLog:
PR c++/125904
* contracts.cc (build_contract_check): Set TREE_SIDE_EFFECTS.
gcc/testsuite/ChangeLog:
PR c++/125904
* g++.dg/contracts/cpp26/pr125904.C: New test.
Tested on Linux/ppc64le (gcc112), ok for trunk and the 16 branch?
diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc
index bc9f23ba4cf..25da963d0b4 100644
--- a/gcc/cp/contracts.cc
+++ b/gcc/cp/contracts.cc
@@ -3048,6 +3048,7 @@ build_contract_check (tree contract)
finish_then_clause (do_check);
finish_if_stmt (do_check);
+ TREE_SIDE_EFFECTS (cc_bind) = true;
BIND_EXPR_BODY (cc_bind) = pop_stmt_list (BIND_EXPR_BODY (cc_bind));
return cc_bind;
}
diff --git a/gcc/testsuite/g++.dg/contracts/cpp26/pr125904.C b/gcc/testsuite/g++.dg/contracts/cpp26/pr125904.C
new file mode 100644
index 00000000000..d0aa1b478b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/contracts/cpp26/pr125904.C
@@ -0,0 +1,55 @@
+// { dg-do run { target c++26 } }
+// { dg-additional-options "-fcontracts -fcontract-evaluation-semantic=observe" }
+// { dg-skip-if "requires hosted libstdc++ for stdc++exp" { ! hostedlib } }
+
+#include <iostream>
+#include <contracts>
+
+#define VERIFY_ASSERT(statement, asserts) \
+ { \
+ bool violation = false;\
+ try{ \
+ statement; \
+ } catch(int &ex) { \
+ violation = true; \
+ } \
+ if ((asserts && !violation) || (!(asserts) && violation)) __builtin_abort(); \
+ } \
+
+static_assert (__cpp_contracts >= 202502L);
+
+void handle_contract_violation(const std::contracts::contract_violation &violation) {
+ std::cerr << "custom std::handle_contract_violation called:"
+ << " " << violation.location().line()
+ << " " << violation.location().file_name()
+ << std::endl;
+ throw -(int)violation.location().line();
+}
+
+void f1()
+{
+ for (int i = 0; i < 10; ++i)
+ contract_assert(false);
+}
+
+void f2()
+{
+ do {
+ contract_assert(false);
+ } while (false);
+}
+
+void f3()
+{
+ int i = 1;
+ while (i--)
+ contract_assert(false);
+}
+
+int main()
+{
+ VERIFY_ASSERT(f1(), true);
+ VERIFY_ASSERT(f2(), true);
+ VERIFY_ASSERT(f3(), true);
+ return 0;
+}