On Fri, Aug 21, 2026 at 7:56 PM Waffl3x <[email protected]> wrote: > > Iains pointed out this patch to me after I submitted mine. Didn't mean > to duplicate work, sorry! Don't mind :P > > On Monday, August 17th, 2026 at 1:40 PM, Jason Merrill <[email protected]> > wrote: > > On 8/14/26 4:33 PM, Wang Jinghao wrote: > > > For precondition and postcondition without a result binding, whether > > > the return type is auto is irrelevant to the condition expression, so > > > type conversions should be completed immediately. > > > > > > PR c++/125537 > > > > > > gcc/cp/ChangeLog: > > > > > > * pt.cc (tsubst_contract): Keep template processing enabled > > > only for postconditions with an undeduced result binding. > > > > Hmm, I notice this is still a different condition from > > cp_parser_late_contract_condition and rebuild_postconditions, which only > > check whether there's a result binding, not whether it's auto. They > > ought to agree on the condition for treating the postcondition as a > > pseudo-template. > > By the time you're in rebuild_postconditions I believe the placeholder > return type is gone. It bails out early 'if the return type is > undeduced', I haven't looked at cp_parser_late_contract_condition > enough though so maybe there are issues on that side. > > > > gcc/testsuite/ChangeLog: > > > > > > * g++.dg/contracts/cpp26/pr125537.C: New test. > > > > Please name tests by what they are testing, not just by PR number. So > > this could be template-post1.C. > > > > Jason > > I guess I'll have to fix my patches as well then. I have a follow up patch that implements this part, perhaps it might be useful to you. This should also be one of the causes of the ICE in PR125574.
Jinghao > > Alex
From ae75a439d2379c00f66605069b364ead4db70b08 Mon Sep 17 00:00:00 2001 From: Wang Jinghao <[email protected]> Date: Mon, 24 Aug 2026 04:44:11 +0800 Subject: [PATCH] c++, contracts: Use the same condition for enabling pseudo-template mode in cp_parser_late_contract_condition gcc/cp/ChangeLog: * contracts.cc (rebuild_postconditions): Only rebuild undeduced result variable. * parser.cc (cp_parser_late_contract_condition): Enable pseudo-template mode only for result bindings whose return type has not yet been deduced. Do not immediately rebuild postconditions that have already completed late parsing. gcc/testsuite/ChangeLog: * g++.dg/contracts/cpp26/pr125537.C: Move to... * g++.dg/contracts/cpp26/template-post1.C: ...here. * g++.dg/contracts/cpp26/contracts-class1.C: New test. --- gcc/cp/contracts.cc | 7 ++++++- gcc/cp/parser.cc | 10 +++++----- .../g++.dg/contracts/cpp26/contracts-class1.C | 14 ++++++++++++++ .../cpp26/{pr125537.C => template-post1.C} | 0 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/contracts/cpp26/contracts-class1.C rename gcc/testsuite/g++.dg/contracts/cpp26/{pr125537.C => template-post1.C} (100%) diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc index d860c552bf2..ab655436eaa 100644 --- a/gcc/cp/contracts.cc +++ b/gcc/cp/contracts.cc @@ -1982,7 +1982,7 @@ rebuild_postconditions (tree fndecl) tree type = TREE_TYPE (TREE_TYPE (fndecl)); /* If the return type is undeduced, defer until later. */ - if (TREE_CODE (type) == TEMPLATE_TYPE_PARM) + if (TREE_CODE (type) == TEMPLATE_TYPE_PARM || type_uses_auto (type)) return; tree contract_spec = get_fn_contract_specifiers (fndecl); @@ -2017,6 +2017,11 @@ rebuild_postconditions (tree fndecl) continue; } + /* A concrete late-parsed result variable still needs validation, but + not rebuilding. Rebuild only one whose type was undeduced. */ + if (!type_uses_auto (TREE_TYPE (oldvar))) + continue; + /* "Instantiate" the result variable using the known type. */ tree newvar = copy_node (oldvar); TREE_TYPE (newvar) = type; diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 3b4de7c7d3a..6f2eae990eb 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -33821,21 +33821,21 @@ cp_parser_late_contract_condition (cp_parser *parser, tree fn, tree contract) processing_postcondition = POSTCONDITION_P (contract); /* Build a fake variable for the result identifier. */ tree result = NULL_TREE; + const bool undeduced_result_type_p + = r_ident && type_uses_auto (type); if (r_ident) { cp_expr result_id (r_ident, r_loc); result = make_postcondition_variable (result_id, type); - ++processing_template_decl; + if (undeduced_result_type_p) + ++processing_template_decl; } cp_expr parsed_condition = cp_parser_conditional_expression (parser); /* Commit to changes. */ update_late_contract (contract, result, parsed_condition); - if (r_ident) + if (undeduced_result_type_p) --processing_template_decl; - /* Rebuild the postcondition since we didn't do it in grokfndecl. */ - rebuild_postconditions (fn); - /* Leave our temporary scope for the postcondition result. */ processing_postcondition = old_pc; gcc_checking_assert (scope_chain && scope_chain->bindings diff --git a/gcc/testsuite/g++.dg/contracts/cpp26/contracts-class1.C b/gcc/testsuite/g++.dg/contracts/cpp26/contracts-class1.C new file mode 100644 index 00000000000..a878e212f1f --- /dev/null +++ b/gcc/testsuite/g++.dg/contracts/cpp26/contracts-class1.C @@ -0,0 +1,14 @@ +// Check whether deferred deduction works correctly when post conditions +// are used in member functions. +// { dg-do compile { target c++26 } } +// { dg-additional-options "-fcontracts" } + +bool check (bool b) { return b; } + +class S +{ + bool f () + post (r: check (r)) + post (r: r) + {} +}; diff --git a/gcc/testsuite/g++.dg/contracts/cpp26/pr125537.C b/gcc/testsuite/g++.dg/contracts/cpp26/template-post1.C similarity index 100% rename from gcc/testsuite/g++.dg/contracts/cpp26/pr125537.C rename to gcc/testsuite/g++.dg/contracts/cpp26/template-post1.C -- 2.52.0
