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

Reply via email to