[PATCH] c++, libstdc++, v5: Implement C++26 P3068R5 - constexpr exceptions [PR117785]

Jason Merrill jason@redhat.com
Tue Jul 15 12:30:33 GMT 2025


On 7/15/25 7:49 AM, Jonathan Wakely wrote:
> On Thu, 10 Jul 2025 at 09:06, Jakub Jelinek wrote:
>>
>> On Wed, Jul 09, 2025 at 06:45:41PM -0400, Jason Merrill wrote:
>>>> +     && reduced_constant_expression_p (val))
>>>
>>> And a value doesn't need to be constant to be printable, we should be able
>>> to print it unconditionally.
>>
>> Sure, the question is if printing non-constant value is better for users.
>> The change to do unconditionally the %qE results in
>> /usr/src/gcc/gcc/testsuite/g++.dg/cpp26/constexpr-eh12.C:71:49: error: uncaught exception '(E*)(& heap )'
>> while previously it was
>> /usr/src/gcc/gcc/testsuite/g++.dg/cpp26/constexpr-eh12.C:71:49: error: uncaught exception of type 'E*'
>> I've kept the conditional for now but if you really want that change, can remove it
>> in the 2 spots and tweak constexpr-eh12.C test's expectations.
>>
>>> Is there a reason not to add it to heap_vars here?
>>
>> In the earlier patch I had:
>>
>>>> +    case CXA_ALLOCATE_EXCEPTION:
>> ...
>>>> +     tree var = cxa_allocate_exception (loc, type, size_zero_node);
>>>> +     ctx->global->heap_vars.safe_push (var);
>>>> +     ctx->global->put_value (var, NULL_TREE);
>> vs.
>>>> +    case CXA_BAD_CAST:
>>>> +    case CXA_BAD_TYPEID:
>>>> +    case CXA_THROW_BAD_ARRAY_NEW_LENGTH:
>> ...
>>>> +     tree var = cxa_allocate_exception (loc, type, size_one_node);
>>>> +     tree ctor
>>>> +       = build_special_member_call (var, complete_ctor_identifier,
>>>> +                                    NULL, type, LOOKUP_NORMAL,
>>>> +                                    ctx->quiet ? tf_none
>>>> +                                    : tf_warning_or_error);
>>>> +     if (ctor == error_mark_node)
>>>> +       {
>>>> +         *non_constant_p = true;
>>>> +         return call;
>>>> +       }
>>>> +     ctx->global->heap_vars.safe_push (var);
>>
>> and so it wasn't added to heap_vars if build_special_member_call failed.
>> But thinking about it now, we really don't care about what is in heap_vars
>> if *non_constant_p, so I've made the change.
>>
>> The rest incorporated into the following version of the patch, passes
>> GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make check-g++ RUNTESTFLAGS="--target_board=unix/-fpie dg.exp='constexpr-eh* constexpr-asm-5.C static_assert1.C feat-cxx26.C constexpr-throw.C constexpr-84192.C constexpr-dynamic*.C consteval34.C constexpr-new27.C consteval-memfn1.C constexpr-typeid5.C constexpr-ellipsis*'"
>> so far.
>>
>> 2025-07-10  Jakub Jelinek  <jakub@redhat.com>
>>
>>          PR c++/117785
>> gcc/c-family/
>>          * c-cppbuiltin.cc (c_cpp_builtins): Predefine
>>          __cpp_constexpr_exceptions=202411L for C++26.
>> gcc/cp/
>>          * constexpr.cc: Implement C++26 P3068R5 - constexpr exceptions.
>>          (class constexpr_global_ctx): Add caught_exceptions and
>>          uncaught_exceptions members.
>>          (constexpr_global_ctx::constexpr_global_ctx): Initialize
>>          uncaught_exceptions.
>>          (returns, breaks, continues, switches): Move earlier.
>>          (throws): New function.
>>          (exception_what_str, diagnose_std_terminate,
>>          diagnose_uncaught_exception): New functions.
>>          (enum cxa_builtin): New type.
>>          (cxx_cxa_builtin_fn_p, cxx_eval_cxa_builtin_fn): New functions.
>>          (cxx_eval_builtin_function_call): Add jump_target argument.  Call
>>          cxx_eval_cxa_builtin_fn for __builtin_eh_ptr_adjust_ref.  Adjust
>>          cxx_eval_constant_expression calls, if it results in jmp_target,
>>          set *jump_target to it and return.
>>          (cxx_bind_parameters_in_call): Add jump_target argument.  Pass
>>          it through to cxx_eval_constant_expression.  If it sets *jump_target,
>>          break.
>>          (fold_operand): Adjust cxx_eval_constant_expression caller.
>>          (cxx_eval_assert): Likewise.  If it set jmp_target, return true.
>>          (cxx_eval_internal_function): Add jump_target argument.  Pass it
>>          through to cxx_eval_constant_expression.  Return early if
>>          *jump_target after recursing on args.
>>          (cxx_eval_dynamic_cast_fn): Likewise.  Don't set reference_p for
>>          C++26 with -fexceptions.
>>          (cxx_eval_thunk_call): Add jump_target argument.  Pass it through
>>          to cxx_eval_constant_expression.
>>          (cxx_set_object_constness): Likewise.  Don't set TREE_READONLY if
>>          throws (jump_target).
>>          (cxx_eval_call_expression): Add jump_target argument.  Pass it
>>          through to cxx_eval_internal_function, cxx_eval_builtin_function_call,
>>          cxx_eval_thunk_call, cxx_eval_dynamic_cast_fn and
>>          cxx_set_object_constness.  Pass it through also
>>          cxx_eval_constant_expression on arguments, cxx_bind_parameters_in_call
>>          and cxx_fold_indirect_ref and for those cases return early if
>>          *jump_target.  Call cxx_eval_cxa_builtin_fn for cxx_cxa_builtin_fn_p
>>          functions.  For cxx_eval_constant_expression on body, pass address of
>>          cleared jmp_target automatic variable, if it throws propagate to
>>          *jump_target and make it non-cacheable.  For C++26 don't diagnose
>>          calls to non-constexpr functions before cxx_bind_parameters_in_call
>>          could report some argument throwing an exception.
>>          (cxx_eval_unary_expression): Add jump_target argument.  Pass it
>>          through to cxx_eval_constant_expression and return early if
>>          *jump_target after the call.
>>          (cxx_fold_pointer_plus_expression): Likewise.
>>          (cxx_eval_binary_expression): Likewise and similarly for
>>          cxx_fold_pointer_plus_expression call.
>>          (cxx_eval_conditional_expression): Pass jump_target to
>>          cxx_eval_constant_expression on first operand and return early if
>>          *jump_target after the call.
>>          (cxx_eval_vector_conditional_expression): Add jump_target argument.
>>          Pass it through to cxx_eval_constant_expression for all 3 arguments
>>          and return early if *jump_target after any of those calls.
>>          (get_array_or_vector_nelts): Add jump_target argument.  Pass it
>>          through to cxx_eval_constant_expression.
>>          (eval_and_check_array_index): Add jump_target argument.  Pass it
>>          through to cxx_eval_constant_expression calls and return early after
>>          each of them if *jump_target.
>>          (cxx_eval_array_reference): Likewise.
>>          (cxx_eval_component_reference): Likewise.
>>          (cxx_eval_bit_field_ref): Likewise.
>>          (cxx_eval_bit_cast): Likewise.  Assert CHECKING_P call doesn't
>>          throw or return.
>>          (cxx_eval_logical_expression): Add jump_target argument.  Pass it
>>          through to cxx_eval_constant_expression calls and return early after
>>          each of them if *jump_target.
>>          (cxx_eval_bare_aggregate): Likewise.
>>          (cxx_eval_vec_init_1): Add jump_target argument.  Pass it through
>>          to cxx_eval_bare_aggregate and recursive call.  Pass it through
>>          to get_array_or_vector_nelts and cxx_eval_constant_expression
>>          and return early after it if *jump_target.
>>          (cxx_eval_vec_init): Add jump_target argument.  Pass it through
>>          to cxx_eval_constant_expression and cxx_eval_vec_init_1.
>>          (cxx_union_active_member): Add jump_target argument.  Pass it
>>          through to cxx_eval_constant_expression and return early after it
>>          if *jump_target.
>>          (cxx_fold_indirect_ref_1): Add jump_target argument.  Pass it
>>          through to cxx_union_active_member and recursive calls.
>>          (cxx_eval_indirect_ref): Add jump_target argument.  Pass it through
>>          to cxx_fold_indirect_ref_1 calls and to recursive call, in which
>>          case return early after it if *jump_target.
>>          (cxx_fold_indirect_ref): Add jump_target argument.  Pass it through
>>          to cxx_fold_indirect_ref and cxx_eval_constant_expression calls and
>>          return early after those if *jump_target.
>>          (cxx_eval_trinary_expression): Add jump_target argument.  Pass it
>>          through to cxx_eval_constant_expression calls and return early after
>>          those if *jump_target.
>>          (cxx_eval_store_expression): Add jump_target argument.  Pass it
>>          through to cxx_eval_constant_expression and eval_and_check_array_index
>>          calls and return early after those if *jump_target.
>>          (cxx_eval_increment_expression): Add jump_target argument.  Pass it
>>          through to cxx_eval_constant_expression calls and return early after
>>          those if *jump_target.
>>          (label_matches): Handle VAR_DECL case.
>>          (cxx_eval_statement_list): Remove local_target variable and
>>          !jump_target handling.  Handle throws (jump_target) like returns or
>>          breaks.
>>          (cxx_eval_loop_expr): Remove local_target variable and !jump_target
>>          handling.  Pass it through to cxx_eval_constant_expression.  Handle
>>          throws (jump_target) like returns.
>>          (cxx_eval_switch_expr): Pass jump_target through to
>>          cxx_eval_constant_expression on cond, return early after it if
>>          *jump_target.
>>          (build_new_constexpr_heap_type): Add jump_target argument.  Pass it
>>          through to cxx_eval_constant_expression calls, return early after
>>          those if *jump_target.
>>          (merge_jump_target): New function.
>>          (cxx_eval_constant_expression): Make jump_target argument no longer
>>          defaulted, don't test jump_target for NULL.  Pass jump_target
>>          through to recursive calls, cxx_eval_call_expression,
>>          cxx_eval_store_expression, cxx_eval_indirect_ref,
>>          cxx_eval_unary_expression, cxx_eval_binary_expression,
>>          cxx_eval_logical_expression, cxx_eval_array_reference,
>>          cxx_eval_component_reference, cxx_eval_bit_field_ref,
>>          cxx_eval_vector_conditional_expression, cxx_eval_bare_aggregate,
>>          cxx_eval_vec_init, cxx_eval_trinary_expression, cxx_fold_indirect_ref,
>>          build_new_constexpr_heap_type, cxx_eval_increment_expression,
>>          cxx_eval_bit_cast and return earlyu after some of those if
>>          *jump_target as needed.
>>          (cxx_eval_constant_expression) <case TARGET_EXPR>: For C++26 push
>>          also CLEANUP_EH_ONLY cleanups, with NULL_TREE marker after them.
>>          (cxx_eval_constant_expression) <case RETURN_EXPR>: Don't override
>>          *jump_target if throws (jump_target).
>>          (cxx_eval_constant_expression) <case TRY_CATCH_EXPR, case TRY_BLOCK,
>>          case MUST_NOT_THROW_EXPR, case TRY_FINALLY_EXPR, case CLEANUP_STMT>:
>>          Handle C++26 constant expressions.
>>          (cxx_eval_constant_expression) <case CLEANUP_POINT_EXPR>: For C++26
>>          with throws (jump_target) evaluate the CLEANUP_EH_ONLY cleanups as
>>          well, and if not throws (jump_target) skip those.  Set *jump_target
>>          if some of the cleanups threw.
>>          (cxx_eval_constant_expression) <case THROW_EXPR>: Recurse on operand
>>          for C++26.
>>          (cxx_eval_outermost_constant_expr): Diagnose uncaught exceptions both
>>          from main expression and cleanups, diagnose also
>>          break/continue/returns from the main expression.  Handle
>>          CLEANUP_EH_ONLY cleanup markers.  Don't diagnose mutable poison stuff
>>          if non_constant_p.  Use different diagnostics for non-deleted heap
>>          allocations if they were allocated by __cxa_allocate_exception.
>>          (callee_might_throw): New function.
>>          (struct check_for_return_continue_data): Add could_throw field.
>>          (check_for_return_continue): Handle AGGR_INIT_EXPR and CALL_EXPR and
>>          set d->could_throw if they could throw.
>>          (potential_constant_expression_1): For CALL_EXPR allow
>>          cxx_dynamic_cast_fn_p calls.  For C++26 set *jump_target to void_node
>>          for calls that could throw.  For C++26 if call to non-constexpr call
>>          is seen, try to evaluate arguments first and if they could throw,
>>          don't diagnose call to non-constexpr function nor return false.
>>          Adjust check_for_return_continue_data initializers and set
>>          *jump_target to void_node if data.could_throw_p.  For C++26 recurse on
>>          THROW_EXPR argument.  Add comment explaining TRY_BLOCK handling with
>>          C++26 exceptions.  Handle throws like returns in some cases.
>>          * cp-tree.h (MUST_NOT_THROW_NOEXCEPT_P, MUST_NOT_THROW_THROW_P,
>>          MUST_NOT_THROW_CATCH_P, DECL_EXCEPTION_REFCOUNT): Define.
>>          (DECL_LOCAL_DECL_P): Fix comment typo, VARIABLE_DECL -> VAR_DECL.
>>          (enum cp_built_in_function): Add CP_BUILT_IN_EH_PTR_ADJUST_REF,
>>          (handler_match_for_exception_type): Declare.
>>          * call.cc (handler_match_for_exception_type): New function.
>>          * except.cc (initialize_handler_parm): Set MUST_NOT_THROW_CATCH_P
>>          on newly created MUST_NOT_THROW_EXPR.
>>          (begin_eh_spec_block): Set MUST_NOT_THROW_NOEXCEPT_P.
>>          (wrap_cleanups_r): Set MUST_NOT_THROW_THROW_P.
>>          (build_throw): Add another TARGET_EXPR whose scope spans
>>          until after the __cxa_throw call and copy pointer value from ptr
>>          to it and use it in __cxa_throw argument.
>>          * tree.cc (builtin_valid_in_constant_expr_p): Handle
>>          CP_BUILT_IN_EH_PTR_ADJUST_REF.
>>          * decl.cc (cxx_init_decl_processing): Initialize
>>          __builtin_eh_ptr_adjust_ref FE builtin.
>>          * pt.cc (tsubst_stmt) <case MUST_NOT_THROW_EXPR>: Copy the
>>          MUST_NOT_THROW_NOEXCEPT_P, MUST_NOT_THROW_THROW_P and
>>          MUST_NOT_THROW_CATCH_P flags.
>>          * cp-gimplify.cc (cp_gimplify_expr) <case CALL_EXPR>: Error on
>>          non-folded CP_BUILT_IN_EH_PTR_ADJUST_REF calls.
>> gcc/testsuite/
>>          * g++.dg/cpp0x/constexpr-ellipsis2.C: Expect different diagnostics for
>>          C++26.
>>          * g++.dg/cpp0x/constexpr-throw.C: Likewise.
>>          * g++.dg/cpp1y/constexpr-84192.C: Expect different diagnostics.
>>          * g++.dg/cpp1y/constexpr-throw.C: Expect different diagnostics for
>>          C++26.
>>          * g++.dg/cpp1z/constexpr-asm-5.C: Likewise.
>>          * g++.dg/cpp26/constexpr-eh1.C: New test.
>>          * g++.dg/cpp26/constexpr-eh2.C: New test.
>>          * g++.dg/cpp26/constexpr-eh3.C: New test.
>>          * g++.dg/cpp26/constexpr-eh4.C: New test.
>>          * g++.dg/cpp26/constexpr-eh5.C: New test.
>>          * g++.dg/cpp26/constexpr-eh6.C: New test.
>>          * g++.dg/cpp26/constexpr-eh7.C: New test.
>>          * g++.dg/cpp26/constexpr-eh8.C: New test.
>>          * g++.dg/cpp26/constexpr-eh9.C: New test.
>>          * g++.dg/cpp26/constexpr-eh10.C: New test.
>>          * g++.dg/cpp26/constexpr-eh11.C: New test.
>>          * g++.dg/cpp26/constexpr-eh12.C: New test.
>>          * g++.dg/cpp26/constexpr-eh13.C: New test.
>>          * g++.dg/cpp26/constexpr-eh14.C: New test.
>>          * g++.dg/cpp26/constexpr-eh15.C: New test.
>>          * g++.dg/cpp26/feat-cxx26.C: Change formatting in __cpp_pack_indexing
>>          and __cpp_pp_embed test.  Add __cpp_constexpr_exceptions test.
>>          * g++.dg/cpp26/static_assert1.C: Expect different diagnostics for
>>          C++26.
>>          * g++.dg/cpp2a/consteval34.C: Likewise.
>>          * g++.dg/cpp2a/consteval-memfn1.C: Likewise.
>>          * g++.dg/cpp2a/constexpr-dynamic4.C: For C++26 add std::exception and
>>          std::bad_cast definitions and expect different diagnostics.
>>          * g++.dg/cpp2a/constexpr-dynamic6.C: Likewise.
>>          * g++.dg/cpp2a/constexpr-dynamic7.C: Likewise.
>>          * g++.dg/cpp2a/constexpr-dynamic8.C: Likewise.
>>          * g++.dg/cpp2a/constexpr-dynamic9.C: Likewise.
>>          * g++.dg/cpp2a/constexpr-dynamic11.C: Likewise.
>>          * g++.dg/cpp2a/constexpr-dynamic14.C: Likewise.
>>          * g++.dg/cpp2a/constexpr-dynamic18.C: Likewise.
>>          * g++.dg/cpp2a/constexpr-new27.C: New test.
>>          * g++.dg/cpp2a/constexpr-typeid5.C: New test.
>> libstdc++-v3/
>>          * include/bits/version.def (constexpr_exceptions): New.
>>          * include/bits/version.h: Regenerate.
>>          * libsupc++/exception (std::bad_exception::bad_exception): Add
>>          _GLIBCXX26_CONSTEXPR.
>>          (std::bad_exception::~bad_exception, std::bad_exception::what): For
>>          C++26 add constexpr and define inline.
>>          * libsupc++/exception.h (std::exception::exception,
>>          std::exception::operator=): Add _GLIBCXX26_CONSTEXPR.
>>          (std::exception::~exception, std::exception::what): For C++26 add
>>          constexpr and define inline.
>>          * libsupc++/exception_ptr.h (std::make_exception_ptr): Add
>>          _GLIBCXX26_CONSTEXPR.  For if consteval use just throw with
>>          current_exception() in catch.
>>          (std::exception_ptr::exception_ptr(void*)): For C++26 add constexpr
>>          and define inline.
>>          (std::exception_ptr::exception_ptr()): Add _GLIBCXX26_CONSTEXPR.
>>          (std::exception_ptr::exception_ptr(const exception_ptr&)): Likewise.
>>          Use __builtin_eh_ptr_adjust_ref if consteval and compiler has it
>>          instead of _M_addref.
>>          (std::exception_ptr::exception_ptr(nullptr_t)): Add
>>          _GLIBCXX26_CONSTEXPR.
>>          (std::exception_ptr::exception_ptr(exception_ptr&&)): Likewise.
>>          (std::exception_ptr::operator=): Likewise.
>>          (std::exception_ptr::~exception_ptr): Likewise.  Use
>>          __builtin_eh_ptr_adjust_ref if consteval and compiler has it
>>          instead of _M_release.
>>          (std::exception_ptr::swap): Add _GLIBCXX26_CONSTEXPR.
>>          (std::exception_ptr::operator bool): Likewise.
>>          (std::exception_ptr::operator==): Likewise.
>>          * libsupc++/nested_exception.h
>>          (std::nested_exception::nested_exception): Add _GLIBCXX26_CONSTEXPR.
>>          (std::nested_exception::operator=): Likewise.
>>          (std::nested_exception::~nested_exception): For C++26 add constexpr
>>          and define inline.
>>          (std::nested_exception::rethrow_if_nested): Add _GLIBCXX26_CONSTEXPR.
>>          (std::nested_exception::nested_ptr): Likewise.
>>          (std::_Nested_exception::_Nested_exception): Likewise.
>>          (std::throw_with_nested, std::rethrow_if_nested): Likewise.
>>          * libsupc++/new (std::bad_alloc::bad_alloc): Likewise.
>>          (std::bad_alloc::operator=): Likewise.
>>          (std::bad_alloc::~bad_alloc): For C++26 add constexpr and define
>>          inline.
>>          (std::bad_alloc::what): Likewise.
>>          (std::bad_array_new_length::bad_array_new_length): Add
>>          _GLIBCXX26_CONSTEXPR.
>>          (std::bad_array_new_length::~bad_array_new_length): For C++26 add
>>          constexpr and define inline.
>>          (std::bad_array_new_length::what): Likewise.
>>          * libsupc++/typeinfo (std::bad_cast::bad_cast): Add
>>          _GLIBCXX26_CONSTEXPR.
>>          (std::bad_cast::~bad_cast): For C++26 add constexpr and define inline.
>>          (std::bad_cast::what): Likewise.
>>          (std::bad_typeid::bad_typeid): Add _GLIBCXX26_CONSTEXPR.
>>          (std::bad_typeid::~bad_typeid): For C++26 add constexpr and define
>>          inline.
>>          (std::bad_typeid::what): Likewise.
>>
> 
> 
> I'm seeing some unexpected libstdc++ test failures since this commit
> (confirmed by bisection).
> 
> $ export GLIBCXX_TESTSUITE_STDS=26
> $ make check RUNTESTFLAGS="conformance.exp=25_algo*debug/constexpr*neg.cc
> --target_board=unix/-D_GLIBCXX_DEBUG"
> 
> FAIL: 25_algorithms/copy/debug/constexpr_neg.cc  -std=gnu++26  (test
> for errors, line )
> FAIL: 25_algorithms/copy/debug/constexpr_neg.cc  -std=gnu++26 (test
> for excess errors)
> FAIL: 25_algorithms/copy_backward/debug/constexpr_neg.cc  -std=gnu++26
> (test for excess errors)
> FAIL: 25_algorithms/equal/debug/constexpr_neg.cc  -std=gnu++26  (test
> for errors, line )
> FAIL: 25_algorithms/equal/debug/constexpr_neg.cc  -std=gnu++26 (test
> for excess errors)
> FAIL: 25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc
> -std=gnu++26 (test for excess errors)
> FAIL: 25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc
>   -std=gnu++26 (test for excess errors)
> FAIL: 25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc
> -std=gnu++26 (test for excess errors)
> FAIL: 25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc
> -std=gnu++26 (test for excess errors)
> FAIL: 25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc
>   -std=gnu++26 (test for excess errors)
> FAIL: 25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc
> -std=gnu++26 (test for excess errors)
> 
> 
> The difference is in the diagnostic we get from the expansion of this macro:
> 
> #define _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,_Func)    \
>    do {                                    \
>      if (__builtin_expect(!bool(_Cond), false))                \
>        __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func)        \
>      ._ErrMsg._M_error();                        \
>    } while (false)
> 
> 
> The dg-error lines in the tests expect a "non-constant condition"
> error and the location to match:
> // { dg-error "_Error_formatter::_M_error()" "" { target *-*-* } 0 }
> 
> but now the error points to the _Error_formatter::_S_at(...) function.
> 
> The diagnostic only changed for C++26, and I'm not sure why (the _S_at
> function isn't constexpr, so why wasn't it failing there before?)

In C++23, we could see that the outermost thing in the expression is a 
call to _M_error, and it's non-constexpr, so we give up at that point 
and never look at the call to _S_at.

In C++26, evaluating the arguments to a function (including the object 
argument) might throw before we get to calling the non-constexpr 
function, so we need to evaluate them before giving up.

> Is this change in diagnostics expected?
> I already have a patch to make the necessary changes to the tests, but
> I wanted to understand why it is required.
> 
> The fixes are all of this form:
> 
> -// { dg-error "_Error_formatter::_M_error()" "" { target *-*-* } 0 }
> +// { dg-error "_Error_formatter::(_M_error|_S_at)" "" { target *-*-* } 0 }
> 



More information about the Libstdc++ mailing list