I noticed that the following code passed.
1 | consteval void foo( auto x ) pre( false ) { return x; }
2 |
3 | static_assert (foo( 1 ) == 1, "");
4 |
5 | int main() {
6 | foo( 1 );
7 | }
However, the code has contract violations.
In constexpr_call, a result with contract violations should
not be cached.
gcc/cp/ChangeLog:
* constexpr.cc (cxx_eval_constant_expression): Do not cache
result with contract violation.
gcc/testsuite/ChangeLog:
* g++.dg/contracts/cpp26/basic.contract.eval.p8-3.C: New test.
/* Only cache a permitted result of a constant expression. */
if (cacheable && !reduced_constant_expression_p (result))
cacheable = false;
+
+ /* Only cache a result without contract violations. */
+ if (cacheable && ctx->global->contract_statement)
+ cacheable = false;
}
else
/* Couldn't get a function copy to evaluate. */
--- /dev/null
+// basic.contract.eval/p8
+// If a contract violation occurs in a context that is manifestly
+// constant-evaluated ([expr.const]), and the evaluation semantic is a
+// terminating semantic, the program is ill-formed.
+// { dg-do compile { target c++23 } }
+// { dg-additional-options "-fcontracts" }
+
+consteval auto foo( auto x ) pre( false ) { return x; }
+// { dg-error {contract predicate is false in constant expression} "" { target *-*-* } .-1 }
+
+static_assert(foo( 42 ) == 42, "");
+
+int main() {
+ foo( 42 ); // { dg-error {call to consteval function 'foo<int>\(42\)' is not a constant expression} }
+}