https://gcc.gnu.org/g:f9d1e2285ac37051915437ba461ac4987588e7ab

commit r17-2567-gf9d1e2285ac37051915437ba461ac4987588e7ab
Author: Ville Voutilainen <[email protected]>
Date:   Sun Jul 5 18:07:07 2026 +0300

    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.

Diff:
---
 gcc/cp/contracts.cc                             |  1 +
 gcc/testsuite/g++.dg/contracts/cpp26/pr125904.C | 55 +++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc
index bc9f23ba4cfa..25da963d0b4e 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 000000000000..d0aa1b478b97
--- /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