On 8/14/26 4:49 PM, Wang Jinghao wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu.
-- >8 --
`rebuild_postconditions' uses `tsubst_expr' to replace the
placeholder result variable with one of the known return type.
Passing an empty template argument vector causes direct references
to template parameters in the condition to ICE in tsubst.
Use generic arguments for template declarations so that template
parameters map to themselves while the result variable is rebuilt.
It seems simpler to just return early if processing_template_decl and
not do this substitution at all, as attached. That leads to an excess
errors failure on dcl.contract.func.p7-t1.C, but this seems to actually
be an improvement: the error about using a non-const parm in a
postcondition refers to the location of the use.
* g++.dg/contracts/cpp26/pr125011.C: New test.
So template-post2.C.
Jason
From 2b5dc0abb6f1d6a482ce7f9cf509478322ceffcf Mon Sep 17 00:00:00 2001
From: Jason Merrill <[email protected]>
Date: Mon, 17 Aug 2026 10:25:31 -0400
Subject: [PATCH] c++: don't rebuild a template postcondition
To: [email protected]
gcc/cp/ChangeLog:
* contracts.cc (rebuild_postconditions): Skip if
processing_template_decl.
gcc/testsuite/ChangeLog:
* g++.dg/contracts/cpp26/dcl.contract.func.p7-t1.C: Expect
additional error.
---
gcc/cp/contracts.cc | 8 ++------
.../g++.dg/contracts/cpp26/dcl.contract.func.p7-t1.C | 4 ++--
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc
index d860c552bf2..a0f1ad07ff5 100644
--- a/gcc/cp/contracts.cc
+++ b/gcc/cp/contracts.cc
@@ -1976,7 +1976,7 @@ check_postcondition_result (tree fndecl, tree type, location_t loc)
void
rebuild_postconditions (tree fndecl)
{
- if (!fndecl || fndecl == error_mark_node)
+ if (!fndecl || fndecl == error_mark_node || processing_template_decl)
return;
tree type = TREE_TYPE (TREE_TYPE (fndecl));
@@ -2031,11 +2031,7 @@ rebuild_postconditions (tree fndecl)
bool old_pc = processing_postcondition;
processing_postcondition = true;
- /* Use generic arguments when rebuilding a template declaration. */
- tree args = (processing_template_decl && current_template_parms
- ? template_parms_to_args (current_template_parms)
- : make_tree_vec (0));
- condition = tsubst_expr (condition, args,
+ condition = tsubst_expr (condition, make_tree_vec (0),
tf_warning_or_error, fndecl);
/* Update the contract condition and result. */
diff --git a/gcc/testsuite/g++.dg/contracts/cpp26/dcl.contract.func.p7-t1.C b/gcc/testsuite/g++.dg/contracts/cpp26/dcl.contract.func.p7-t1.C
index 91d3f4a306e..82640d3b0fb 100644
--- a/gcc/testsuite/g++.dg/contracts/cpp26/dcl.contract.func.p7-t1.C
+++ b/gcc/testsuite/g++.dg/contracts/cpp26/dcl.contract.func.p7-t1.C
@@ -99,11 +99,11 @@ void PostCondT<int>::f<NTClass>(NTClass, NTClass&, NTClass*, NTClass const*, NTC
template <typename T>
int f2(const T i[10])
-post(r : r == i[0]){ return 1;};
+post(r : r == i[0]){ return 1;}; // { dg-error "used in a postcondition must be const" } on use
template
int f2<int>(const int i[10]);
-// { dg-error "used in a postcondition must be const" "" { target *-*-* } 101 }
+// { dg-error "used in a postcondition must be const" "" { target *-*-* } 101 } on decl
// P3520
template <typename T>
--
2.55.0