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