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;
+}

Reply via email to