Hi!

The following patch implements the C++29
P3822R2 - Conditional noexcept specifiers in compound requirements
paper.  For mangling I've used what the clang++ fork mentioned in the
paper uses, so no N for no noexcept (as before) or noexcept (false),
N for noexcept (as before) or noexcept (true) and
C <expression> for noexcept (<expression>).  I've also checked all these
new testcases against that clang++ fork on godbolt (again, link in the
paper), everything is accepted or rejected the same in both compilers,
just there is apparently a difference in the mangling but preexisting and
unrelated to this exact patch (the no N vs. N vs. C <expression> is actually
the same).

So far lightly tested, ok for trunk if it passes full bootstrap/regtest?

2026-08-20  Jakub Jelinek  <[email protected]>

        PR c++/125822
gcc/c-family/
        * c-cppbuiltin.cc (c_cpp_builtins): Define __cpp_concepts to 202606L
        rather than 202002L for C++29.
gcc/cp/
        * cp-tree.def: Implement C++29 P3822R2 - Conditional noexcept
        specifiers in compound requirements.
        (COMPOUND_REQ): Use 3 operands rather than 2, adjust comment.
        * cp-tree.h (COMPOUND_REQ_NOEXCEPT_P): Remove.
        (finish_compound_requirement): Change last argument from bool to
        tree.
        * parser.cc (cp_parser_compound_requirement): Parse C++29 conditional
        noexcept in compound requirement.  Pass a tree to
        finish_compound_requirement rather than bool.
        * constraint.cc (tsubst_compound_requirement): Read noexcept from
        TREE_OPERAND (req, 2) rather than COMPOUND_REQ_NOEXCEPT_P (req),
        instantiate, convert, evaluate and pass to finish_compound_requirement.
        (finish_compound_requirement): Change last argument from bool to
        tree, store it as third operand of COMPOUND_REQ rather than in
        COMPOUND_REQ_NOEXCEPT_P flag and call check_for_bare_parameter_packs
        on it.
        * cxx-pretty-print.cc (pp_cxx_compound_requirement): Print noexcept
        with argument if TREE_OPERAND (t, 2) is neither true nor false
        constant and check it for printing "noexcept" instead oof
        COMPOUND_REQ_NOEXCEPT_P flag.
        * mangle.cc (write_requirement): Don't use COMPOUND_REQ_NOEXCEPT_P
        flag, instead mangle without N or with N if third operand is false
        or true constant and as C <expression> otherwise.
gcc/testsuite/
        * g++.dg/cpp29/complex-req-noexcept1.C: New test.
        * g++.dg/cpp29/complex-req-noexcept2.C: New test.
        * g++.dg/cpp29/complex-req-noexcept3.C: New test.
        * g++.dg/cpp29/complex-req-noexcept4.C: New test.
        * g++.dg/cpp29/complex-req-noexcept5.C: New test.
        * g++.dg/cpp29/feat-cxx29.C: Expect __cpp_concepts 202606L rather
        than 202002L for C++29.

--- gcc/c-family/c-cppbuiltin.cc.jj     2026-08-06 11:48:09.026003282 +0200
+++ gcc/c-family/c-cppbuiltin.cc        2026-08-20 17:03:31.614072266 +0200
@@ -1133,7 +1133,12 @@ c_cpp_builtins (cpp_reader *pfile)
          cpp_define (pfile, "__cpp_designated_initializers=202606L");
        }
       if (flag_concepts && cxx_dialect > cxx14)
-       cpp_define (pfile, "__cpp_concepts=202002L");
+       {
+         if (cxx_dialect > cxx26)
+           cpp_define (pfile, "__cpp_concepts=202606L");
+         else
+           cpp_define (pfile, "__cpp_concepts=202002L");
+       }
       else if (cxx_dialect >= cxx20)
        cpp_warn (pfile, "__cpp_concepts");
       if (flag_contracts)
--- gcc/cp/cp-tree.def.jj       2026-07-13 18:35:54.646463696 +0200
+++ gcc/cp/cp-tree.def  2026-08-20 13:25:10.643586955 +0200
@@ -515,10 +515,9 @@ DEFTREECODE (SIMPLE_REQ, "simple_req", t
 DEFTREECODE (TYPE_REQ, "type_req", tcc_expression, 1)
 
 /* A requirement for an expression and its properties. The
-   first operand is the expression, and the 2nd is its type.
-   The accessor COMPOUND_REQ_NOEXCEPT determines whether
-   the noexcept keyword was present. */
-DEFTREECODE (COMPOUND_REQ, "compound_req", tcc_expression, 2)
+   first operand is the expression, the 2nd is its type,
+   the third one is noexcept expression.   */
+DEFTREECODE (COMPOUND_REQ, "compound_req", tcc_expression, 3)
 
 /* A requires clause within a requires expression. */
 DEFTREECODE (NESTED_REQ, "nested_req", tcc_expression, 1)
--- gcc/cp/cp-tree.h.jj 2026-08-04 12:48:37.000000000 +0200
+++ gcc/cp/cp-tree.h    2026-08-20 13:25:26.091389686 +0200
@@ -442,7 +442,6 @@ extern GTY(()) tree cp_global_trees[CPTI
       PACK_EXPANSION_LOCAL_P (in *_PACK_EXPANSION)
       TINFO_HAS_ACCESS_ERRORS (in TEMPLATE_INFO)
       SIZEOF_EXPR_TYPE_P (in SIZEOF_EXPR)
-      COMPOUND_REQ_NOEXCEPT_P (in COMPOUND_REQ)
       BLOCK_OUTER_CURLY_BRACE_P (in BLOCK)
       FOLD_EXPR_MODIFY_P (*_FOLD_EXPR)
       IF_STMT_CONSTEXPR_P (IF_STMT)
@@ -1749,10 +1748,6 @@ check_constraint_info (tree t)
 #define TEMPLATE_PARM_CONSTRAINTS(NODE) \
   TREE_TYPE (TREE_LIST_CHECK (NODE))
 
-/* Non-zero if the noexcept is present in a compound requirement.  */
-#define COMPOUND_REQ_NOEXCEPT_P(NODE) \
-  TREE_LANG_FLAG_0 (TREE_CHECK (NODE, COMPOUND_REQ))
-
 /* A TREE_LIST whose TREE_VALUE is the constraints on the 'auto' placeholder
    type NODE, used in an argument deduction constraint.  The TREE_PURPOSE
    holds the set of template parameters that were in-scope when this 'auto'
@@ -9364,7 +9359,7 @@ extern tree finish_shorthand_constraint
 extern tree finish_requires_expr                (location_t, tree, tree);
 extern tree finish_simple_requirement           (location_t, tree);
 extern tree finish_type_requirement             (location_t, tree);
-extern tree finish_compound_requirement         (location_t, tree, tree, bool);
+extern tree finish_compound_requirement         (location_t, tree, tree, tree);
 extern tree finish_nested_requirement           (location_t, tree);
 extern tree tsubst_requires_expr                (tree, tree, tsubst_flags_t, 
tree);
 extern tree evaluate_requires_expr             (tree);
--- gcc/cp/parser.cc.jj 2026-08-06 10:56:18.062585734 +0200
+++ gcc/cp/parser.cc    2026-08-20 13:32:06.104289435 +0200
@@ -35287,8 +35287,10 @@ cp_parser_type_requirement (cp_parser *p
 
 /* Parse a compound requirement
 
-     compound-requirement:
-         '{' expression '}' 'noexcept' [opt] trailing-return-type [opt] ';' */
+   compound-requirement:
+     '{' expression '}' 'noexcept' [opt] trailing-return-type [opt] ';'
+     '{' expression '}' noexcept-specifier [opt] trailing-return-type [opt]
+       ';' (C++29)  */
 
 static tree
 cp_parser_compound_requirement (cp_parser *parser)
@@ -35320,11 +35322,21 @@ cp_parser_compound_requirement (cp_parse
     }
 
   /* Parse the optional noexcept. */
-  bool noexcept_p = false;
+  tree noex = boolean_false_node;
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_NOEXCEPT))
     {
-      cp_lexer_consume_token (parser->lexer);
-      noexcept_p = true;
+      if (cxx_dialect < cxx29
+         && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))
+       pedwarn (cp_lexer_peek_nth_token (parser->lexer, 2)->location,
+                OPT_Wc__29_extensions,
+                "conditional %<noexcept%> in compound requirement only "
+                "available with %<-std=c++2d%> or %<-std=gnu++2d%>");
+
+      noex = cp_parser_noexcept_specification_opt (parser,
+                                                  CP_PARSER_FLAGS_NONE,
+                                                  /*require_constexpr=*/true,
+                                                  /*consumed_expr=*/NULL,
+                                                  /*return_cond=*/true);
     }
 
   /* Parse the optional trailing return type. */
@@ -35376,7 +35388,7 @@ cp_parser_compound_requirement (cp_parse
   if (expr == error_mark_node || type == error_mark_node)
     return error_mark_node;
 
-  return finish_compound_requirement (loc, expr, type, noexcept_p);
+  return finish_compound_requirement (loc, expr, type, noex);
 }
 
 /* Parse a nested requirement. This is the same as a requires clause.
--- gcc/cp/constraint.cc.jj     2026-07-13 18:35:54.645463709 +0200
+++ gcc/cp/constraint.cc        2026-08-20 17:32:32.501294056 +0200
@@ -1507,6 +1507,7 @@ tsubst_compound_requirement (tree t, tre
 {
   tree t0 = TREE_OPERAND (t, 0);
   tree t1 = TREE_OPERAND (t, 1);
+  tree noex = TREE_OPERAND (t, 2);
   tree expr = tsubst_valid_expression_requirement (t0, args, info);
   if (expr == error_mark_node)
     return error_mark_node;
@@ -1516,8 +1517,17 @@ tsubst_compound_requirement (tree t, tre
   subst_info quiet (info.complain & ~tf_warning_or_error, info.in_decl);
 
   /* Check the noexcept condition.  */
-  bool noexcept_p = COMPOUND_REQ_NOEXCEPT_P (t);
-  if (noexcept_p && !processing_template_decl
+  noex = tsubst_expr (noex, args, info.complain, info.in_decl);
+  if (!instantiation_dependent_expression_p (noex))
+    {
+      noex = build_converted_constant_bool_expr (noex, info.complain);
+      noex = instantiate_non_dependent_expr (noex, info.complain);
+      noex = cxx_constant_value (noex, info.complain);
+    }
+  if (noex == error_mark_node)
+    return error_mark_node;
+  if (!processing_template_decl
+      && integer_nonzerop (noex)
       && !expr_noexcept_p (expr, quiet.complain))
     {
       if (info.diagnose_unsatisfaction_p ())
@@ -1573,8 +1583,7 @@ tsubst_compound_requirement (tree t, tre
     }
 
   if (processing_template_decl)
-    return finish_compound_requirement (EXPR_LOCATION (t),
-                                       expr, type, noexcept_p);
+    return finish_compound_requirement (EXPR_LOCATION (t), expr, type, noex);
   return boolean_true_node;
 }
 
@@ -2984,14 +2993,17 @@ finish_type_requirement (location_t loc,
    its properties.  If TYPE is non-null, then it specifies either
    an implicit conversion or argument deduction constraint,
    depending on whether any placeholders occur in the type name.
-   NOEXCEPT_P is true iff the noexcept keyword was specified.  */
+   NOEX is boolean_true_node iff the noexcept keyword was specified
+   or expression if noexcept (expr) was specified.  */
 
 tree
-finish_compound_requirement (location_t loc, tree expr, tree type, bool 
noexcept_p)
+finish_compound_requirement (location_t loc, tree expr, tree type,
+                            tree noex)
 {
-  tree req = build_nt (COMPOUND_REQ, expr, type);
+  if (check_for_bare_parameter_packs (noex))
+    noex = error_mark_node;
+  tree req = build_nt (COMPOUND_REQ, expr, type, noex);
   SET_EXPR_LOCATION (req, loc);
-  COMPOUND_REQ_NOEXCEPT_P (req) = noexcept_p;
   return req;
 }
 
--- gcc/cp/cxx-pretty-print.cc.jj       2026-07-13 18:35:54.647463684 +0200
+++ gcc/cp/cxx-pretty-print.cc  2026-08-20 13:53:34.718015103 +0200
@@ -2860,8 +2860,14 @@ pp_cxx_compound_requirement (cxx_pretty_
   pp->expression (TREE_OPERAND (t, 0));
   pp_cxx_right_brace (pp);
 
-  if (COMPOUND_REQ_NOEXCEPT_P (t))
+  if (TREE_OPERAND (t, 2) == boolean_true_node)
     pp_cxx_ws_string (pp, "noexcept");
+  else if (TREE_OPERAND (t, 2) != boolean_false_node)
+    {
+      pp_cxx_ws_string (pp, "noexcept(");
+      pp->expression (TREE_OPERAND (t, 2));
+      pp_cxx_right_paren (pp);
+    }
 
   if (tree type = TREE_OPERAND (t, 1))
     {
--- gcc/cp/mangle.cc.jj 2026-08-19 09:02:35.350546050 +0200
+++ gcc/cp/mangle.cc    2026-08-20 16:41:21.225644857 +0200
@@ -3214,15 +3214,23 @@ write_requirement (tree req)
   switch (tree_code code = TREE_CODE (req))
     {
       /* # simple-requirement or compound-requirement
-        <requirement> ::= X <expression> [ N ] [ R <type-constraint> ] */
+        <requirement> ::= X <expression> [ N ] [ R <type-constraint> ]
+                          X <expression> C <expression>
+                            [ R <type-constraint> ]  */
     case SIMPLE_REQ:
     case COMPOUND_REQ:
       write_char ('X');
       write_expression (op);
       if (code == SIMPLE_REQ)
        break;
-      if (COMPOUND_REQ_NOEXCEPT_P (req))
+      if (operand_equal_p (TREE_OPERAND (req, 2), boolean_true_node))
        write_char ('N');
+      else if (TREE_OPERAND (req, 2) != error_mark_node
+              && !operand_equal_p (TREE_OPERAND (req, 2), boolean_false_node))
+       {
+         write_char ('C');
+         write_expression (TREE_OPERAND (req, 2));
+       }
       if (tree constr = TREE_OPERAND (req, 1))
        {
          write_char ('R');
--- gcc/testsuite/g++.dg/cpp29/complex-req-noexcept1.C.jj       2026-08-20 
15:33:37.653755051 +0200
+++ gcc/testsuite/g++.dg/cpp29/complex-req-noexcept1.C  2026-08-20 
17:17:49.968363935 +0200
@@ -0,0 +1,73 @@
+// C++29 P3822R2 - Conditional noexcept specifiers in compound requirements
+// { dg-do compile { target c++20 } }
+// { dg-options "" }
+
+int foo ();
+int bar () noexcept;
+struct A { int foo (); };
+struct B { int foo () noexcept; };
+struct C { int foo (); char c[42]; };
+struct D { int foo () noexcept; char c[42]; };
+struct E { long foo (); };
+struct F { long foo () noexcept; };
+struct G { long foo (); char c[42]; };
+struct H { long foo () noexcept; char c[42]; };
+template <bool B>
+struct J { constexpr operator bool () { return B; }; };
+template <typename T, typename U>
+constexpr bool s = false;
+template <typename T>
+constexpr bool s <T, T> = true;
+template <typename T, typename U>
+concept S = s <T, U>;
+
+static_assert (!requires { { foo () } noexcept; });
+static_assert (!requires { { foo () } noexcept (true); });     // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+static_assert (requires { { foo () } noexcept (false); });     // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+static_assert (!requires { { foo () } noexcept (42 == 42); }); // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+static_assert (requires { { foo () } noexcept (42 != 42); });  // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+static_assert (!requires { { foo () } noexcept (J <true> {}); });// { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+static_assert (requires { { foo () } noexcept (J <false> {}); });// { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+static_assert (requires { { bar () } noexcept; });
+static_assert (requires { { bar () } noexcept (true); });      // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+static_assert (requires { { bar () } noexcept (false); });     // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+static_assert (requires { { bar () } noexcept (42 == 42); });  // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+static_assert (requires { { bar () } noexcept (42 != 42); });  // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+static_assert (requires { { bar () } noexcept (J <true> {}); });// { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+static_assert (requires { { bar () } noexcept (J <false> {}); });// { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+
+template <typename T, bool B>
+concept V = requires (T t) { { t.foo () } noexcept (B); };     // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+
+static_assert (V <A, false>);
+static_assert (!V <A, true>);
+static_assert (V <B, false>);
+static_assert (V <B, true>);
+
+template <typename T>
+concept W = requires (T t) {
+  { t.foo () } noexcept (sizeof (T) > sizeof (A)) -> S <int>;  // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+};
+
+static_assert (W <A>);
+static_assert (W <B>);
+static_assert (!W <C>);
+static_assert (W <D>);
+static_assert (!W <E>);
+static_assert (!W <F>);
+static_assert (!W <G>);
+static_assert (!W <H>);
+
+template <typename T>
+struct I { static constexpr bool i = sizeof (T) > sizeof (A); };
+template <typename T>
+concept Z = requires (T t) { { t.foo () } noexcept (I <T>::i); }; // { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+
+static_assert (Z <A>);
+static_assert (Z <B>);
+static_assert (!Z <C>);
+static_assert (Z <D>);
+static_assert (Z <E>);
+static_assert (Z <F>);
+static_assert (!Z <G>);
+static_assert (Z <H>);
--- gcc/testsuite/g++.dg/cpp29/complex-req-noexcept2.C.jj       2026-08-20 
16:26:29.493864020 +0200
+++ gcc/testsuite/g++.dg/cpp29/complex-req-noexcept2.C  2026-08-20 
16:45:52.376233696 +0200
@@ -0,0 +1,39 @@
+// C++29 P3822R2 - Conditional noexcept specifiers in compound requirements
+// { dg-do compile { target c++20 } }
+// { dg-options "" }
+
+template <typename T, int N>
+concept A = sizeof (T) < N;
+template <typename T>
+concept B = A <T, 1000>;
+template <typename T>
+struct C { using type = T; };
+
+template <typename T>
+void foo (int n)
+requires requires {
+  T ();
+  n;
+  n == T ();
+  { T () + 1 } -> B;
+  { T () - 1 } noexcept;
+  { T () * 1 } noexcept -> A <1234>;
+  { T () + 2 } noexcept (true);                                // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+  { T () - 2 } noexcept (true) -> A <1234>;            // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+  { T () * 2 } noexcept (false);                       // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+  { T () + 3 } noexcept (false) -> A <1234>;           // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+  { T () - 3 } noexcept (sizeof (T) > 100);            // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+  { T () * 3 } noexcept (sizeof (T) > 100) -> A <1234>;        // { dg-warning 
"conditional 'noexcept' in compound requirement only available with" "" { 
target c++26_down } }
+  typename T;
+  typename C <T>;
+  typename C <T>::type;
+  typename C <decltype (n)>;
+  requires A <T, 256>;
+}
+{
+}
+
+template
+void foo <int> (int);
+
+// { dg-final { scan-assembler 
"_Z3fooIiEviQrqXcvT__EXfL0p_XeqfL0p_cvS0__EXplcvS0__ELi1ER1BXmicvS0__ELi1ENXmlcvS0__ELi1ENR1AILi1234EEXplcvS0__ELi2ENXmicvS0__ELi2ENR1AILi1234EEXmlcvS0__ELi2EXplcvS0__ELi3ER1AILi1234EEXmicvS0__ELi3ECgtstS0_Li100EXmlcvS0__ELi3ECgtstS0_Li100ER1AILi1234EETS0_T1CIS0_ETNS2_4typeETS1_IiEQ1AIS0_Li256EEE"
 } }
--- gcc/testsuite/g++.dg/cpp29/complex-req-noexcept3.C.jj       2026-08-20 
16:55:21.258146332 +0200
+++ gcc/testsuite/g++.dg/cpp29/complex-req-noexcept3.C  2026-08-20 
17:00:35.320255521 +0200
@@ -0,0 +1,46 @@
+// C++29 P3822R2 - Conditional noexcept specifiers in compound requirements
+// { dg-do compile { target c++29 } }
+
+#include <concepts>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+template <typename R, typename... Args>
+struct vtbl { virtual auto call (Args &&...) -> R = 0; virtual ~vtbl () 
noexcept {}; };
+
+template <typename T, typename R, typename... Args>
+struct impl : vtbl <R, Args...> {
+  impl (auto &&y) : x { std::forward <decltype (y)> (y) } {}
+  auto call (Args &&...xs) -> R override { return x (static_cast <Args &&> 
(xs)...); }
+  T x;
+};
+
+template <typename F>
+struct any_f;
+
+template <typename X, bool noexc, typename R, typename...Args>
+concept invocable_r = requires (X x, Args...xs) {
+  { x (static_cast <Args> (xs)...) } noexcept (noexc) -> std::convertible_to 
<R>;
+};
+
+template <typename X, typename T>
+concept not_same = !std::same_as <std::decay_t <X>, T>;
+
+template <typename R, typename... Args, bool noexc>
+struct any_f <R (Args...) noexcept (noexc)> {
+  template <not_same <any_f> T>
+  any_f (T &&x)
+    requires invocable_r <T &, noexc, R, Args...>
+    : f (new impl <std::decay_t <T>, R, Args...> (std::forward <T> (x))) {}
+  auto operator () (std::convertible_to <Args> auto &&...xs) noexcept (noexc) 
-> R {
+    return f->call (std::forward <decltype (xs)> (xs)...);
+  }
+  std::unique_ptr <vtbl <R, Args...>> f;
+};
+
+int
+main ()
+{
+  any_f <int (long, long) noexcept> x ([] (long, long) noexcept -> int { 
return 2; });
+}
--- gcc/testsuite/g++.dg/cpp29/complex-req-noexcept4.C.jj       2026-08-20 
17:05:04.962912426 +0200
+++ gcc/testsuite/g++.dg/cpp29/complex-req-noexcept4.C  2026-08-20 
17:34:41.880668366 +0200
@@ -0,0 +1,29 @@
+// C++29 P3822R2 - Conditional noexcept specifiers in compound requirements
+// { dg-do compile { target c++20 } }
+// { dg-options "" }
+
+int foo ();
+int bar () noexcept;
+template <bool N>
+struct A {};
+template <bool N>
+struct B { constexpr operator bool () { return N; }; };
+struct C { int foo (); };
+struct D { int foo () noexcept (true); };
+
+static_assert (requires { { foo () } noexcept (B <false> {}); });      // { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+static_assert (!requires { { foo () } noexcept (B <true> {}); });      // { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+static_assert (requires { { bar () } noexcept (B <false> {}); });      // { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+static_assert (requires { { bar () } noexcept (B <true> {}); });       // { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+
+template <typename T, typename U>
+concept V = requires (T t) { { t.foo () } noexcept (U {}); };          // { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+
+static_assert (!V <C, A <false>>);
+static_assert (!V <C, A <true>>);
+static_assert (!V <D, A <false>>);
+static_assert (!V <D, A <true>>);
+static_assert (V <C, B <false>>);
+static_assert (!V <C, B <true>>);
+static_assert (V <D, B <false>>);
+static_assert (V <D, B <true>>);
--- gcc/testsuite/g++.dg/cpp29/complex-req-noexcept5.C.jj       2026-08-20 
17:34:18.478962415 +0200
+++ gcc/testsuite/g++.dg/cpp29/complex-req-noexcept5.C  2026-08-20 
17:38:13.250012440 +0200
@@ -0,0 +1,27 @@
+// C++29 P3822R2 - Conditional noexcept specifiers in compound requirements
+// { dg-do compile { target c++20 } }
+// { dg-options "" }
+
+int foo ();
+int bar () noexcept;
+template <bool N>
+struct A {};
+template <bool N>
+struct B { constexpr operator bool () { return N; }; };
+struct C { int foo (); };
+struct D { int foo () noexcept (true); };
+
+bool a = requires { { foo () } noexcept (A <false> {}); };             // { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+// { dg-error "could not convert 'A<false>\\\(\\\)' from 'A<false>' to 'bool'" 
"" { target *-*-* } .-1 }
+bool b = requires { { foo () } noexcept (A <true> {}); };              // { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+// { dg-error "could not convert 'A<true>\\\(\\\)' from 'A<true>' to 'bool'" 
"" { target *-*-* } .-1 }
+
+template <typename T, typename U>
+concept V = requires (T t) { { t.foo () } noexcept (U {}); };          // { 
dg-warning "conditional 'noexcept' in compound requirement only available with" 
"" { target c++26_down } }
+// { dg-error "could not convert 'A<false>\\\(\\\)' from 'A<false>' to 'bool'" 
"" { target *-*-* } .-1 }
+// { dg-error "could not convert 'A<true>\\\(\\\)' from 'A<true>' to 'bool'" 
"" { target *-*-* } .-2 }
+
+static_assert (V <C, A <false>>);                                      // { 
dg-error "static assertion failed" }
+static_assert (V <C, A <true>>);                                       // { 
dg-error "static assertion failed" }
+static_assert (V <D, A <false>>);                                      // { 
dg-error "static assertion failed" }
+static_assert (V <D, A <true>>);                                       // { 
dg-error "static assertion failed" }
--- gcc/testsuite/g++.dg/cpp29/feat-cxx29.C.jj  2026-08-06 11:49:25.894550497 
+0200
+++ gcc/testsuite/g++.dg/cpp29/feat-cxx29.C     2026-08-20 17:01:07.882852265 
+0200
@@ -487,8 +487,8 @@
 
 #ifndef __cpp_concepts
 #  error "__cpp_concepts"
-#elif __cpp_concepts != 202002
-#  error "__cpp_concepts != 202002"
+#elif __cpp_concepts != 202606
+#  error "__cpp_concepts != 202606"
 #endif
 
 #ifndef __cpp_using_enum

        Jakub

Reply via email to