diff options
52 files changed, 1237 insertions, 150 deletions
diff --git a/contrib/ChangeLog b/contrib/ChangeLog index a1db267..a4f8bb3 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,7 @@ +2025-07-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * prepare-commit-msg: Force default git prefixes. + 2025-07-07 Martin Jambor <mjambor@suse.cz> * filter-clang-warnings.py (skip_warning): Also ignore diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 407faa7..750fbeb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,86 @@ +2025-07-08 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp> + + * config/xtensa/xtensa.cc (xtensa_b4const_or_zero): + Remove. + (xtensa_b4const): Add a case where the value is 0, and rename + to xtensa_b4const_or_zero. + (xtensa_rtx_costs): Fix to also consider the result of + xtensa_b4constu(). + +2025-07-08 Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org> + + * config/s390/s390.md (stack_protect_get_tpsi): New insn. + (stack_protect_get_tpdi): New insn. + (stack_protect_set): Use new insn. + (stack_protect_test): Use new insn. + +2025-07-08 Robin Dapp <rdapp@ventanamicro.com> + + PR target/120461 + * config/riscv/riscv-v.cc (emit_vlmax_insn_lra): Do not emit + vsetivli for XTHeadVector. + +2025-07-08 Robin Dapp <rdapp@ventanamicro.com> + + PR target/113829 + * config/riscv/riscv-vector-builtins.cc (registered_function::overloaded_hash): + Skip non-type arguments. + +2025-07-08 Andreas Schwab <schwab@suse.de> + + PR target/120995 + * config/riscv/sync.md (zacas_atomic_cas_value_strong<mode>): + Allow op3 to be zero. + +2025-07-08 Richard Biener <rguenther@suse.de> + + * config/i386/x86-tune.def (X86_TUNE_AVX512_MASKED_EPILOGUES): + New tunable, default on for m_ZNVER4 and m_ZNVER5. + * config/i386/i386.cc (ix86_vector_costs::finish_cost): With + X86_TUNE_AVX512_MASKED_EPILOGUES and when the main loop + had a vectorization factor > 2 use a masked epilogue when + possible and when not obviously problematic. + +2025-07-08 Richard Biener <rguenther@suse.de> + + * tree-vectorizer.h (vector_costs::suggested_epilogue_mode): + Add masked output parameter and return m_masked_epilogue. + (vector_costs::m_masked_epilogue): New tristate flag. + (vector_costs::vector_costs): Initialize m_masked_epilogue. + * tree-vect-loop.cc (vect_analyze_loop_1): Pass in masked + flag to optionally initialize can_use_partial_vectors_p. + (vect_analyze_loop): For epilogues also get whether to use + a masked epilogue for this loop from the target and use + that for the first epilogue mode we try. + +2025-07-08 Richard Biener <rguenther@suse.de> + + PR tree-optimization/120358 + * tree-ssa-structalias.cc (get_constraint_for_1): Adjust + pruning of sub-variables according to the imprecise + known start offset. + +2025-07-08 Alexandre Oliva <oliva@adacore.com> + + * config/vxworks-dummy.h (TARGET_VXWORKS_VAROFF): New. + (TARGET_VXWORKS_GOTTPIC): New. + * config/vxworks.h (TARGET_VXWORKS_VAROFF): Override. + (TARGET_VXWORKS_GOTTPIC): Likewise. + * config/i386/i386.cc (output_set_got): Disable VxWorks6 GOT + sequence on VxWorks7. + (legitimize_pic_address): Accept relative addressing of + labels on VxWorks7. + (ix86_delegitimize_address_1): Likewise. + (ix86_output_addr_diff_elt): Likewise. + * config/i386/i386.md (tablejump): Likewise. + (set_got, set_got_labelled): Set no-red-zone flag on VxWorks7. + * config/i386/predicates.md (gotoff_operand): Test + TARGET_VXWORKS_VAROFF. + +2025-07-08 Alexandre Oliva <oliva@adacore.com> + + * config.gcc (vxworks-dummy.h): Add to aarch64-*-* as well. + 2025-07-07 Qing Zhao <qing.zhao@oracle.com> Revert: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7475f8c..fc3b547 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20250708 +20250709 diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index f6db36e..02bc149 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -308,6 +308,9 @@ UNSPECV_SPLIT_STACK_CALL UNSPECV_OSC_BREAK + + ; Stack Protector + UNSPECV_SP_GET_TP ]) ;; @@ -365,6 +368,9 @@ (VR23_REGNUM 45) (VR24_REGNUM 46) (VR31_REGNUM 53) + ; Access registers + (AR0_REGNUM 36) + (AR1_REGNUM 37) ]) ; Rounding modes for binary floating point numbers @@ -11924,15 +11930,43 @@ ; Stack Protector Patterns ; +; Insns stack_protect_get_tp{si,di} are similar to *get_tp_{31,64} but still +; distinct in the sense that they force recomputation of the thread pointer +; instead of potentially reloading it from stack. + +(define_insn_and_split "stack_protect_get_tpsi" + [(set (match_operand:SI 0 "register_operand" "=d") + (unspec_volatile:SI [(const_int 0)] UNSPECV_SP_GET_TP))] + "" + "#" + "&& reload_completed" + [(set (match_dup 0) (reg:SI AR0_REGNUM))]) + +(define_insn_and_split "stack_protect_get_tpdi" + [(set (match_operand:DI 0 "register_operand" "=d") + (unspec_volatile:DI [(const_int 0)] UNSPECV_SP_GET_TP))] + "" + "#" + "&& reload_completed" + [(set (match_dup 1) (reg:SI AR0_REGNUM)) + (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32))) + (set (strict_low_part (match_dup 1)) (reg:SI AR1_REGNUM))] + "operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]));") + (define_expand "stack_protect_set" [(set (match_operand 0 "memory_operand" "") (match_operand 1 "memory_operand" ""))] "" { #ifdef TARGET_THREAD_SSP_OFFSET + rtx tp = gen_reg_rtx (Pmode); + if (TARGET_64BIT) + emit_insn (gen_stack_protect_get_tpdi (tp)); + else + emit_insn (gen_stack_protect_get_tpsi (tp)); operands[1] - = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), - GEN_INT (TARGET_THREAD_SSP_OFFSET))); + = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, tp, + GEN_INT (TARGET_THREAD_SSP_OFFSET))); #endif if (TARGET_64BIT) emit_insn (gen_stack_protect_setdi (operands[0], operands[1])); @@ -11958,9 +11992,14 @@ { rtx cc_reg, test; #ifdef TARGET_THREAD_SSP_OFFSET + rtx tp = gen_reg_rtx (Pmode); + if (TARGET_64BIT) + emit_insn (gen_stack_protect_get_tpdi (tp)); + else + emit_insn (gen_stack_protect_get_tpsi (tp)); operands[1] - = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), - GEN_INT (TARGET_THREAD_SSP_OFFSET))); + = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, tp, + GEN_INT (TARGET_THREAD_SSP_OFFSET))); #endif if (TARGET_64BIT) emit_insn (gen_stack_protect_testdi (operands[0], operands[1])); diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 8c43a69..b75cec1 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -423,12 +423,13 @@ xtensa_uimm8x4 (HOST_WIDE_INT v) } -static bool -xtensa_b4const (HOST_WIDE_INT v) +bool +xtensa_b4const_or_zero (HOST_WIDE_INT v) { switch (v) { case -1: + case 0: case 1: case 2: case 3: @@ -451,15 +452,6 @@ xtensa_b4const (HOST_WIDE_INT v) bool -xtensa_b4const_or_zero (HOST_WIDE_INT v) -{ - if (v == 0) - return true; - return xtensa_b4const (v); -} - - -bool xtensa_b4constu (HOST_WIDE_INT v) { switch (v) @@ -4512,7 +4504,8 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code, } break; case COMPARE: - if ((INTVAL (x) == 0) || xtensa_b4const (INTVAL (x))) + if (xtensa_b4const_or_zero (INTVAL (x)) + || xtensa_b4constu (INTVAL (x))) { *total = 0; return true; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 38a2d68..9fe49db 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,37 @@ +2025-07-08 Marek Polacek <polacek@redhat.com> + Andrew Pinski <quic_apinski@quicinc.com> + + PR c++/83469 + PR c++/93809 + * cp-tree.h (UNION_TYPE_P): Define. + (TYPENAME_IS_UNION_P): Define. + * decl.cc (struct typename_info): Add union_p field. + (struct typename_hasher::equal): Compare union_p field. + (build_typename_type): Use ti.union_p for union_type. Set + TYPENAME_IS_UNION_P. + * error.cc (dump_type) <case TYPENAME_TYPE>: Handle + TYPENAME_IS_UNION_P. + * module.cc (trees_out::type_node): Likewise. + * parser.cc (cp_parser_check_class_key): Allow typename key for union + types and allow union keyword for typename types. + * pt.cc (tsubst) <case TYPENAME_TYPE>: Don't conflate unions with + class_type. For TYPENAME_IS_CLASS_P, check NON_UNION_CLASS_TYPE_P + rather than CLASS_TYPE_P. Add TYPENAME_IS_UNION_P handling. + +2025-07-08 Jakub Jelinek <jakub@redhat.com> + + PR c++/117784 + * decl.cc: Implement part of C++26 P2686R4 - constexpr structured + bindings. + (cp_finish_decl): Pedwarn for C++23 and older on constinit on + structured bindings except for static/thread_local where it uses + earlier error. + (grokdeclarator): Pedwarn on constexpr structured bindings for + C++23 and older instead of emitting error always, don't clear + constexpr_p in that case. + * parser.cc (cp_parser_decomposition_declaration): Copy over + DECL_DECLARED_CONSTEXPR_P and DECL_DECLARED_CONSTINIT_P flags. + 2025-07-07 Alfie Richards <alfie.richards@arm.com> PR c++/119498 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1b893e2..3b92d9a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -506,6 +506,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; LAMBDA_EXPR_STATIC_P (in LAMBDA_EXPR) TARGET_EXPR_ELIDING_P (in TARGET_EXPR) contract_semantic (in ASSERTION_, PRECONDITION_, POSTCONDITION_STMT) + TYPENAME_IS_UNION_P (in TYPENAME_TYPE) 4: IDENTIFIER_MARKED (IDENTIFIER_NODEs) TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, CALL_EXPR, or FIELD_DECL). @@ -2354,6 +2355,10 @@ enum languages { lang_c, lang_cplusplus }; #define NON_UNION_CLASS_TYPE_P(T) \ (TREE_CODE (T) == RECORD_TYPE && TYPE_LANG_FLAG_5 (T)) +/* Nonzero if T is a class type and is a union. */ +#define UNION_TYPE_P(T) \ + (TREE_CODE (T) == UNION_TYPE && TYPE_LANG_FLAG_5 (T)) + /* Keep these checks in ascending code order. */ #define RECORD_OR_UNION_CODE_P(T) \ ((T) == RECORD_TYPE || (T) == UNION_TYPE) @@ -4485,11 +4490,14 @@ get_vec_init_expr (tree t) #define TYPENAME_IS_ENUM_P(NODE) \ (TREE_LANG_FLAG_0 (TYPENAME_TYPE_CHECK (NODE))) -/* True if a TYPENAME_TYPE was declared as a "class", "struct", or - "union". */ +/* True if a TYPENAME_TYPE was declared as a "class" or "struct". */ #define TYPENAME_IS_CLASS_P(NODE) \ (TREE_LANG_FLAG_1 (TYPENAME_TYPE_CHECK (NODE))) +/* True if a TYPENAME_TYPE was declared as a "union". */ +#define TYPENAME_IS_UNION_P(NODE) \ + (TREE_LANG_FLAG_3 (TYPENAME_TYPE_CHECK (NODE))) + /* True if a TYPENAME_TYPE is in the process of being resolved. */ #define TYPENAME_IS_RESOLVING_P(NODE) \ (TREE_LANG_FLAG_2 (TYPENAME_TYPE_CHECK (NODE))) diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index be26bd3..0e6afbe 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -4370,6 +4370,7 @@ struct typename_info { tree template_id; bool enum_p; bool class_p; + bool union_p; }; struct typename_hasher : ggc_ptr_hash<tree_node> @@ -4408,7 +4409,8 @@ struct typename_hasher : ggc_ptr_hash<tree_node> && TYPE_CONTEXT (t1) == t2->scope && TYPENAME_TYPE_FULLNAME (t1) == t2->template_id && TYPENAME_IS_ENUM_P (t1) == t2->enum_p - && TYPENAME_IS_CLASS_P (t1) == t2->class_p); + && TYPENAME_IS_CLASS_P (t1) == t2->class_p + && TYPENAME_IS_UNION_P (t1) == t2->union_p); } }; @@ -4432,9 +4434,8 @@ build_typename_type (tree context, tree name, tree fullname, ti.name = name; ti.template_id = fullname; ti.enum_p = tag_type == enum_type; - ti.class_p = (tag_type == class_type - || tag_type == record_type - || tag_type == union_type); + ti.class_p = (tag_type == class_type || tag_type == record_type); + ti.union_p = tag_type == union_type; hashval_t hash = typename_hasher::hash (&ti); /* See if we already have this type. */ @@ -4450,6 +4451,7 @@ build_typename_type (tree context, tree name, tree fullname, TYPENAME_TYPE_FULLNAME (t) = ti.template_id; TYPENAME_IS_ENUM_P (t) = ti.enum_p; TYPENAME_IS_CLASS_P (t) = ti.class_p; + TYPENAME_IS_UNION_P (t) = ti.union_p; /* Build the corresponding TYPE_DECL. */ tree d = build_decl (input_location, TYPE_DECL, name, t); @@ -9174,6 +9176,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, if (decomp) { + if (DECL_DECLARED_CONSTINIT_P (decl) && cxx_dialect < cxx26) + pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wc__26_extensions, + "%<constinit%> can be applied to structured binding " + "only with %<-std=c++2c%> or %<-std=gnu++2c%>"); cp_maybe_mangle_decomp (decl, decomp); if (TREE_STATIC (decl) && !DECL_FUNCTION_SCOPE_P (decl)) { @@ -13621,9 +13627,10 @@ grokdeclarator (const cp_declarator *declarator, if (typedef_p) error_at (declspecs->locations[ds_typedef], "structured binding declaration cannot be %qs", "typedef"); - if (constexpr_p && !concept_p) - error_at (declspecs->locations[ds_constexpr], "structured " - "binding declaration cannot be %qs", "constexpr"); + if (constexpr_p && !concept_p && cxx_dialect < cxx26) + pedwarn (declspecs->locations[ds_constexpr], OPT_Wc__26_extensions, + "structured binding declaration can be %qs only with " + "%<-std=c++2c%> or %<-std=gnu++2c%>", "constexpr"); if (consteval_p) error_at (declspecs->locations[ds_consteval], "structured " "binding declaration cannot be %qs", "consteval"); @@ -13634,8 +13641,11 @@ grokdeclarator (const cp_declarator *declarator, declspecs->gnu_thread_keyword_p ? "__thread" : "thread_local"); if (concept_p) - error_at (declspecs->locations[ds_concept], - "structured binding declaration cannot be %qs", "concept"); + { + error_at (declspecs->locations[ds_concept], + "structured binding declaration cannot be %qs", "concept"); + constexpr_p = 0; + } /* [dcl.struct.bind] "A cv that includes volatile is deprecated." */ if (type_quals & TYPE_QUAL_VOLATILE) warning_at (declspecs->locations[ds_volatile], OPT_Wvolatile, @@ -13690,7 +13700,6 @@ grokdeclarator (const cp_declarator *declarator, "%<auto%> type %qT", type); inlinep = 0; typedef_p = 0; - constexpr_p = 0; consteval_p = 0; concept_p = 0; if (storage_class != sc_static) diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc index abeb028..eb2ff33 100644 --- a/gcc/cp/error.cc +++ b/gcc/cp/error.cc @@ -810,6 +810,7 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags) pp_cxx_ws_string (pp, TYPENAME_IS_ENUM_P (t) ? "enum" : TYPENAME_IS_CLASS_P (t) ? "class" + : TYPENAME_IS_UNION_P (t) ? "union" : "typename"); dump_typename (pp, t, flags); break; diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index c8e79f3..6b5a60a 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -9619,6 +9619,8 @@ trees_out::type_node (tree type) tag_type = enum_type; else if (TYPENAME_IS_CLASS_P (type)) tag_type = class_type; + else if (TYPENAME_IS_UNION_P (type)) + tag_type = union_type; u (int (tag_type)); } } diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 239e6f9..8148495 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -16870,7 +16870,11 @@ cp_parser_decomposition_declaration (cp_parser *parser, decl = error_mark_node; } else - prev = decl2; + { + prev = decl2; + DECL_DECLARED_CONSTEXPR_P (decl2) = DECL_DECLARED_CONSTEXPR_P (decl); + DECL_DECLARED_CONSTINIT_P (decl2) = DECL_DECLARED_CONSTINIT_P (decl); + } if (elt_pushed_scope) pop_scope (elt_pushed_scope); } @@ -35924,7 +35928,9 @@ cp_parser_check_class_key (cp_parser *parser, location_t key_loc, return; bool seen_as_union = TREE_CODE (type) == UNION_TYPE; - if (seen_as_union != (class_key == union_type)) + if (class_key != typename_type + && TREE_CODE (type) != TYPENAME_TYPE + && seen_as_union != (class_key == union_type)) { auto_diagnostic_group d; if (permerror (input_location, "%qs tag used in naming %q#T", diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 3362a6f..40ce987 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -17250,13 +17250,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) return error_mark_node; } - /* FIXME: TYPENAME_IS_CLASS_P conflates 'class' vs 'struct' vs 'union' - tags. TYPENAME_TYPE should probably remember the exact tag that - was written. */ + /* FIXME: TYPENAME_IS_CLASS_P conflates 'class' vs 'struct' tags. + TYPENAME_TYPE should probably remember the exact tag that + was written for -Wmismatched-tags. */ enum tag_types tag_type - = TYPENAME_IS_CLASS_P (t) ? class_type - : TYPENAME_IS_ENUM_P (t) ? enum_type - : typename_type; + = (TYPENAME_IS_CLASS_P (t) ? class_type + : TYPENAME_IS_UNION_P (t) ? union_type + : TYPENAME_IS_ENUM_P (t) ? enum_type + : typename_type); tsubst_flags_t tcomplain = complain | tf_keep_type_decl; tcomplain |= tst_ok_flag | qualifying_scope_flag; f = make_typename_type (ctx, f, tag_type, tcomplain); @@ -17278,10 +17279,18 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) else return error_mark_node; } - else if (TYPENAME_IS_CLASS_P (t) && !CLASS_TYPE_P (f)) + else if (TYPENAME_IS_CLASS_P (t) && !NON_UNION_CLASS_TYPE_P (f)) { if (complain & tf_error) - error ("%qT resolves to %qT, which is not a class type", + error ("%qT resolves to %qT, which is not a non-union " + "class type", t, f); + else + return error_mark_node; + } + else if (TYPENAME_IS_UNION_P (t) && !UNION_TYPE_P (f)) + { + if (complain & tf_error) + error ("%qT resolves to %qT, which is not a union type", t, f); else return error_mark_node; diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 49eef94..168c475 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2025-07-08 Andre Vehreschild <vehre@gcc.gnu.org> + + PR fortran/120637 + * class.cc (finalize_component): Return true, when a finalizable + component was detect and do not free it. + 2025-07-07 Mikael Morin <mikael@gcc.gnu.org> * trans-intrinsic.cc (conv_intrinsic_move_alloc): Add pre and diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index b6fdf72..99bf24c 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -f5c453aa726ebb509e7b8cb20df7734f0e411404 +c4d7bfb9895efc196b04f18f5da77fd99b39212a The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3923bb7..5b38013 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,124 @@ +2025-07-08 Marek Polacek <polacek@redhat.com> + Andrew Pinski <quic_apinski@quicinc.com> + + PR c++/83469 + PR c++/93809 + * g++.dg/template/error45.C: Adjust dg-error. + * g++.dg/warn/Wredundant-tags-3.C: Remove xfail. + * g++.dg/parse/union1.C: New test. + * g++.dg/parse/union2.C: New test. + * g++.dg/parse/union3.C: New test. + * g++.dg/parse/union4.C: New test. + * g++.dg/parse/union5.C: New test. + * g++.dg/parse/union6.C: New test. + +2025-07-08 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp> + + * gcc.target/xtensa/BGEUI-BLTUI-32k-64k.c: New. + +2025-07-08 Jakub Jelinek <jakub@redhat.com> + + PR c++/117784 + * g++.dg/cpp1z/decomp3.C (test): For constexpr structured binding + initialize from constexpr var instead of non-constexpr and expect + just a pedwarn for C++23 and older instead of error always. + * g++.dg/cpp26/decomp9.C (foo): Likewise. + * g++.dg/cpp26/decomp22.C: New test. + * g++.dg/cpp26/decomp23.C: New test. + * g++.dg/cpp26/decomp24.C: New test. + * g++.dg/cpp26/decomp25.C: New test. + +2025-07-08 Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org> + + * gcc.target/s390/stack-protector-guard-tls-1.c: New test. + +2025-07-08 Richard Biener <rguenther@suse.de> + + * gcc.dg/guality/guality.h (guality_main): Declare noipa. + (guality_check): Likewise. + +2025-07-08 Robin Dapp <rdapp@ventanamicro.com> + + PR target/120461 + * gcc.target/riscv/rvv/xtheadvector/pr120461.c: New test. + +2025-07-08 Robin Dapp <rdapp@ventanamicro.com> + + PR target/113829 + * gcc.target/riscv/rvv/base/pr113829.c: New test. + +2025-07-08 Andreas Schwab <schwab@suse.de> + + PR target/120995 + * gcc.target/riscv/amo/zabha-zacas-atomic-cas.c: New test. + +2025-07-08 Jason Merrill <jason@redhat.com> + + * g++.dg/cpp1y/lambda-generic-variadic.C: Change to 'compile'. + +2025-07-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * gcc.target/i386/memcpy-pr120683-1.c (dg-options): Add + -fasynchronous-unwind-tables -fdwarf2-cfi-asm. + * gcc.target/i386/memcpy-pr120683-2.c: Likewise. + * gcc.target/i386/memcpy-pr120683-3.c: Likewise. + * gcc.target/i386/memcpy-pr120683-4.c: Likewise. + * gcc.target/i386/memcpy-pr120683-5.c: Likewise. + * gcc.target/i386/memcpy-pr120683-6.c: Likewise. + * gcc.target/i386/memcpy-pr120683-7.c: Likewise. + * gcc.target/i386/memcpy-strategy-12.c: Likewise. + * gcc.target/i386/memset-pr120683-1.c: Likewise. + * gcc.target/i386/memset-pr120683-10.c: Likewise. + * gcc.target/i386/memset-pr120683-11.c: Likewise. + * gcc.target/i386/memset-pr120683-12.c: Likewise. + * gcc.target/i386/memset-pr120683-13.c: Likewise. + * gcc.target/i386/memset-pr120683-14.c: Likewise. + * gcc.target/i386/memset-pr120683-15.c: Likewise. + * gcc.target/i386/memset-pr120683-16.c: Likewise. + * gcc.target/i386/memset-pr120683-17.c: Likewise. + * gcc.target/i386/memset-pr120683-18.c: Likewise. + * gcc.target/i386/memset-pr120683-19.c: Likewise. + * gcc.target/i386/memset-pr120683-2.c: Likewise. + * gcc.target/i386/memset-pr120683-20.c: Likewise. + * gcc.target/i386/memset-pr120683-21.c: Likewise. + * gcc.target/i386/memset-pr120683-22.c: Likewise. + * gcc.target/i386/memset-pr120683-23.c: Likewise. + * gcc.target/i386/memset-pr120683-3.c: Likewise. + * gcc.target/i386/memset-pr120683-4.c: Likewise. + * gcc.target/i386/memset-pr120683-5.c: Likewise. + * gcc.target/i386/memset-pr120683-6.c: Likewise. + * gcc.target/i386/memset-pr120683-7.c: Likewise. + * gcc.target/i386/memset-pr120683-8.c: Likewise. + * gcc.target/i386/memset-pr120683-9.c: Likewise. + +2025-07-08 Juergen Christ <jchrist@linux.ibm.com> + + * gcc.target/s390/vector/pattern-avg-1.c: Split test. + * gcc.target/s390/vector/pattern-mulh-1.c: Split test. + * gcc.target/s390/vector/pattern-avg-2.c: New test. + * gcc.target/s390/vector/pattern-mulh-2.c: New test. + +2025-07-08 Richard Biener <rguenther@suse.de> + + * gcc.target/i386/vect-mask-epilogue-1.c: New testcase. + * gcc.target/i386/vect-mask-epilogue-2.c: Likewise. + * gcc.target/i386/vect-epilogues-3.c: Adjust. + +2025-07-08 Andre Vehreschild <vehre@gcc.gnu.org> + + PR fortran/120637 + * gfortran.dg/asan/finalize_1.f90: New test. + +2025-07-08 Jeff Law <jlaw@ventanamicro.com> + + * gcc.dg/torture/pr120654.c: Use __builtin variants of malloc and free. + +2025-07-08 Jeff Law <jlaw@ventanamicro.com> + + * gcc.target/riscv/amo/zalrsc-rvwmo-amo-add-int.c: Adjust expected + output. + * gcc.target/riscv/amo/zalrsc-ztso-amo-add-int.c: Likewise. + 2025-07-07 Qing Zhao <qing.zhao@oracle.com> Revert: diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp3.C b/gcc/testsuite/g++.dg/cpp1z/decomp3.C index a9b23b0..202edc3 100644 --- a/gcc/testsuite/g++.dg/cpp1z/decomp3.C +++ b/gcc/testsuite/g++.dg/cpp1z/decomp3.C @@ -19,7 +19,8 @@ test (A &b, B c) // { dg-error "expected primary-expression before 'decltype'" "" { target c++11_down } .-2 } auto & & && & [ m, n, o ] = b; // { dg-error "multiple ref-qualifiers" } // { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 } - constexpr auto [ p ] = c; // { dg-error "structured binding declaration cannot be 'constexpr'" } + constexpr B c2 = { 42 }; + constexpr auto [ p ] = c2; // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } } // { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 } friend auto [ q ] = c; // { dg-error "'friend' used outside of class" } // { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp26/decomp22.C b/gcc/testsuite/g++.dg/cpp26/decomp22.C new file mode 100644 index 0000000..576a93b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp22.C @@ -0,0 +1,66 @@ +// C++26 P2686R4 - constexpr structured bindings +// { dg-do compile { target c++11 } } +// { dg-options "" } + +namespace std { + template <typename T> struct tuple_size; + template <int, typename> struct tuple_element; +} + +struct A { + int i, j; + template <int I> constexpr const int &get () const { return I == 1 ? j : i; } +}; + +template <> struct std::tuple_size <const A> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, const A> { using type = const int; }; + +constexpr struct B { + int i, j; + long long k, l; +} a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; + +constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto [ e, f, g ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto [ l, m, n, o ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +constexpr auto & [ p, q, r ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto & [ s, t, u ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +constexpr auto & [ v, w, x, y ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto & [ aa, ab, ac, ad ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +static_assert (b.i == 1 && b.l == 4 && c.j == 6 && c.k == 7 && d.i == 9 && d.k == 11, ""); +static_assert (h == 5 && i == 6 && j == 7 && k == 8, ""); +static_assert (p.i == 1 && p.l == 4 && q.j == 6 && q.k == 7 && r.i == 9 && r.k == 11, ""); +static_assert (&p.i == &a[0].i && &p.l == &a[0].l && &q.j == &a[1].j, ""); +static_assert (&q.k == &a[1].k && &r.i == &a[2].i && &r.k == &a[2].k, ""); +static_assert (v == 5 && w == 6 && x == 7 && y == 8, ""); +static_assert (&v == &a[1].i && &w == &a[1].j && &x == &a[1].k && &y == &a[1].l, ""); + +constexpr A z = { 42, -42 }; +constexpr auto [ ae, af, ag ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit const auto [ ah, ai, aj ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +constexpr auto & [ ak, al, am ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto & [ an, ao, ap ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +static_assert (ae == 42 && af == -42 && ag == 42, ""); +static_assert (&af == &ae + 1 && &ag == &ae, ""); +static_assert (&ae != &z.i && &af != &z.j && &ag != &z.i, ""); +static_assert (ak == 42 && al == -42 && am == 42, ""); +static_assert (&ak == &z.i && &al == &z.j && &am == &z.i, ""); diff --git a/gcc/testsuite/g++.dg/cpp26/decomp23.C b/gcc/testsuite/g++.dg/cpp26/decomp23.C new file mode 100644 index 0000000..ad2f7e0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp23.C @@ -0,0 +1,77 @@ +// C++26 P2686R4 - constexpr structured bindings +// { dg-do compile { target c++11 } } +// { dg-options "" } + +namespace std { + template <typename T> struct tuple_size; + template <int, typename> struct tuple_element; +} + +struct A { + int i, j; + template <int I> constexpr const int &get () const { return I == 1 ? j : i; } +}; + +template <> struct std::tuple_size <const A> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, const A> { using type = const int; }; + +struct B { + int i, j; + long long k, l; +}; + +void +foo () +{ + static constexpr B a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; + static constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit auto [ e, f, g ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit auto [ l, m, n, o ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static constexpr auto & [ p, q, r ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit auto & [ s, t, u ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static constexpr auto & [ v, w, x, y ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit auto & [ aa, ab, ac, ad ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static_assert (b.i == 1 && b.l == 4 && c.j == 6 && c.k == 7 && d.i == 9 && d.k == 11, ""); + static_assert (h == 5 && i == 6 && j == 7 && k == 8, ""); + static_assert (p.i == 1 && p.l == 4 && q.j == 6 && q.k == 7 && r.i == 9 && r.k == 11, ""); + static_assert (&p.i == &a[0].i && &p.l == &a[0].l && &q.j == &a[1].j, ""); + static_assert (&q.k == &a[1].k && &r.i == &a[2].i && &r.k == &a[2].k, ""); + static_assert (v == 5 && w == 6 && x == 7 && y == 8, ""); + static_assert (&v == &a[1].i && &w == &a[1].j && &x == &a[1].k && &y == &a[1].l, ""); + + static constexpr A z = { 42, -42 }; + static constexpr auto [ ae, af, ag ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit const auto [ ah, ai, aj ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static constexpr auto & [ ak, al, am ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit auto & [ an, ao, ap ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static_assert (ae == 42 && af == -42 && ag == 42, ""); + static_assert (&af == &ae + 1 && &ag == &ae, ""); + static_assert (&ae != &z.i && &af != &z.j && &ag != &z.i, ""); + static_assert (ak == 42 && al == -42 && am == 42, ""); + static_assert (&ak == &z.i && &al == &z.j && &am == &z.i, ""); +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp24.C b/gcc/testsuite/g++.dg/cpp26/decomp24.C new file mode 100644 index 0000000..5da1321 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp24.C @@ -0,0 +1,20 @@ +// C++26 P2686R4 - constexpr structured bindings +// { dg-do compile { target c++11 } } +// { dg-options "" } + +struct B { + int i, j; + long long k, l; +}; + +void +foo () +{ + constexpr B a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; + constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + static_assert (b.i == 1 && b.l == 4 && c.j == 6 && c.k == 7 && d.i == 9 && d.k == 11, ""); + static_assert (h == 5 && i == 6 && j == 7 && k == 8, ""); +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp25.C b/gcc/testsuite/g++.dg/cpp26/decomp25.C new file mode 100644 index 0000000..55559f0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp25.C @@ -0,0 +1,119 @@ +// C++26 P2686R4 - constexpr structured bindings +// { dg-do compile { target c++11 } } +// { dg-options "" } + +namespace std { + template <typename T> struct tuple_size; + template <int, typename> struct tuple_element; +} + +struct A { + int i, j; + template <int I> int &get () { return I == 1 ? j : i; } +}; + +template <> struct std::tuple_size <A> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, A> { using type = int; }; +template <> struct std::tuple_size <const A> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, const A> { using type = int; }; + +struct B { + int i, j; + long long k, l; +} a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; // { dg-message "'a' was not declared 'constexpr'" "" } + +struct C { + int i, j; + template <int I> const int &get () const { return I == 1 ? j : i; } +}; + +template <> struct std::tuple_size <const C> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, const C> { using type = const int; }; + +constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "the value of 'a' is not usable in a constant expression" "" { target *-*-* } .-2 } +#if __cpp_constinit >= 201907 +constinit auto [ e, f, g ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "'constinit' variable '<structured bindings>' does not have a constant initializer" "" { target c++20 } .-1 } + // { dg-error "the value of 'a' is not usable in a constant expression" "" { target c++20 } .-2 } +#endif +constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "the value of 'a' is not usable in a constant expression" "" { target *-*-* } .-2 } +#if __cpp_constinit >= 201907 +constinit auto [ l, m, n, o ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "'constinit' variable '<structured bindings>' does not have a constant initializer" "" { target c++20 } .-1 } + // { dg-error "the value of 'a' is not usable in a constant expression" "" { target c++20 } .-2 } +#endif +constexpr auto & [ p, q, r ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto & [ s, t, u ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +constexpr auto & [ v, w, x, y ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto & [ aa, ab, ac, ad ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + +A z = { 42, -42 }; // { dg-message "'z' was not declared 'constexpr'" "" } +constexpr auto [ ae, af, ag ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "the value of 'z' is not usable in a constant expression" "" { target *-*-* } .-2 } + // { dg-error "passing 'const A' as 'this' argument discards qualifiers" "" { target *-*-* } .-3 } + // { dg-error "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target *-*-* } .-4 } +#if __cpp_constinit >= 201907 +constinit const auto [ ah, ai, aj ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "'constinit' variable '<structured bindings>' does not have a constant initializer" "" { target c++20 } .-1 } + // { dg-error "the value of 'z' is not usable in a constant expression" "" { target c++20 } .-2 } + // { dg-error "passing 'const A' as 'this' argument discards qualifiers" "" { target c++20 } .-3 } + // { dg-error "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target c++20 } .-4 } + // { dg-error "'constinit' variable 'ah' does not have a constant initializer" "" { target c++20 } .-5 } + // { dg-error "'constinit' variable 'ai' does not have a constant initializer" "" { target c++20 } .-6 } + // { dg-error "'constinit' variable 'aj' does not have a constant initializer" "" { target c++20 } .-7 } +#endif +constexpr auto & [ ak, al, am ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target *-*-* } .-2 } +#if __cpp_constinit >= 201907 +constinit auto & [ an, ao, ap ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "'constinit' variable 'an' does not have a constant initializer" "" { target c++20 } .-1 } + // { dg-error "'constinit' variable 'ao' does not have a constant initializer" "" { target c++20 } .-2 } + // { dg-error "'constinit' variable 'ap' does not have a constant initializer" "" { target c++20 } .-3 } + // { dg-message "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target c++20 } .-4 } +#endif + +constexpr C zz = { 42, -42 }; +constexpr auto [ aq, ar, as ] = zz; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target *-*-* } .-2 } +#if __cpp_constinit >= 201907 +constinit const auto [ at, au, av ] = zz; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target c++20 } .-1 } + // { dg-error "'constinit' variable 'at' does not have a constant initializer" "" { target c++20 } .-2 } + // { dg-error "'constinit' variable 'au' does not have a constant initializer" "" { target c++20 } .-3 } + // { dg-error "'constinit' variable 'av' does not have a constant initializer" "" { target c++20 } .-4 } +#endif +constexpr auto & [ aw, ax, ay ] = zz; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target *-*-* } .-2 } +#if __cpp_constinit >= 201907 +constinit auto & [ az, ba, bb ] = zz; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "'constinit' variable 'az' does not have a constant initializer" "" { target c++20 } .-1 } + // { dg-error "'constinit' variable 'ba' does not have a constant initializer" "" { target c++20 } .-2 } + // { dg-error "'constinit' variable 'bb' does not have a constant initializer" "" { target c++20 } .-3 } + // { dg-message "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target c++20 } .-4 } +#endif + +void +foo () +{ +#if __cpp_constinit >= 201907 + constexpr B a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; + constinit auto [ b, c, d ] = a; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } + constinit auto & [ e, f, g ] = a; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } + constinit auto [ h, i, j, k ] = a[1]; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } + constinit auto & [ l, m, n, o ] = a[2]; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } +#endif +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp9.C b/gcc/testsuite/g++.dg/cpp26/decomp9.C index 5629c4c..ee18b60 100644 --- a/gcc/testsuite/g++.dg/cpp26/decomp9.C +++ b/gcc/testsuite/g++.dg/cpp26/decomp9.C @@ -63,6 +63,7 @@ foo (const S &&s) if (static auto [i, j, k] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } ; // { dg-error "'static' invalid in condition" "" { target *-*-* } .-1 } // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } - if (constexpr auto [i, j, k] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } - ; // { dg-error "structured binding declaration cannot be 'constexpr'" "" { target *-*-* } .-1 } + constexpr T t2 = { 1, 2, 3 }; + if (constexpr auto [i, j, k] = t2) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } + ; // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } } diff --git a/gcc/testsuite/g++.dg/parse/union1.C b/gcc/testsuite/g++.dg/parse/union1.C new file mode 100644 index 0000000..d567ea3 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union1.C @@ -0,0 +1,19 @@ +// PR c++/83469 +// { dg-do compile } + +struct S { + union U { int m; }; +}; + +template <typename T> +void +f () +{ + union T::U u; +} + +int +main() +{ + f<S>(); +} diff --git a/gcc/testsuite/g++.dg/parse/union2.C b/gcc/testsuite/g++.dg/parse/union2.C new file mode 100644 index 0000000..cdb1392 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union2.C @@ -0,0 +1,19 @@ +// PR c++/83469 +// { dg-do compile } + +struct S { + union U { int m; }; +}; + +template <typename T> +void +f () +{ + struct T::U u; // { dg-error "not a non-union class type" } +} + +int +main() +{ + f<S>(); +} diff --git a/gcc/testsuite/g++.dg/parse/union3.C b/gcc/testsuite/g++.dg/parse/union3.C new file mode 100644 index 0000000..61552a4 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union3.C @@ -0,0 +1,19 @@ +// PR c++/83469 +// { dg-do compile } + +struct S { + struct C { int m; }; +}; + +template <typename T> +void +f () +{ + union T::C u; // { dg-error "not a union type" } +} + +int +main() +{ + f<S>(); +} diff --git a/gcc/testsuite/g++.dg/parse/union4.C b/gcc/testsuite/g++.dg/parse/union4.C new file mode 100644 index 0000000..709f6a4 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union4.C @@ -0,0 +1,12 @@ +// PR c++/93809 +// { dg-do compile } + +class C { }; +enum E { }; +struct S { }; +union U { }; + +typedef typename ::C C2; +typedef typename ::E E2; +typedef typename ::S S2; +typedef typename ::U U2; diff --git a/gcc/testsuite/g++.dg/parse/union5.C b/gcc/testsuite/g++.dg/parse/union5.C new file mode 100644 index 0000000..18238dd --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union5.C @@ -0,0 +1,5 @@ +// PR c++/93809 +// { dg-do compile { target c++11 } } + +union U {}; +auto var = new (typename ::U); diff --git a/gcc/testsuite/g++.dg/parse/union6.C b/gcc/testsuite/g++.dg/parse/union6.C new file mode 100644 index 0000000..61b9568 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union6.C @@ -0,0 +1,5 @@ +// PR c++/93809 +// { dg-do compile } + +typedef union{} U; +typename ::U foo () { return U(); } diff --git a/gcc/testsuite/g++.dg/template/error45.C b/gcc/testsuite/g++.dg/template/error45.C index 064554d..f4c6560 100644 --- a/gcc/testsuite/g++.dg/template/error45.C +++ b/gcc/testsuite/g++.dg/template/error45.C @@ -11,7 +11,7 @@ struct enable_if< true, T > template < typename T > struct enable_if< true, T >::type -f( T x ); // { dg-error "not a class type" } +f( T x ); // { dg-error "not a non-union class type" } void g( void ) diff --git a/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C b/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C index 0eeee34..dcccdca 100644 --- a/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C +++ b/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C @@ -28,7 +28,7 @@ struct N::S s3; // { dg-warning "-Wredundant-tags" } N::U u1; typename N::U u2; // { dg-bogus "-Wredundant-tags" } - // { dg-bogus "'class' tag used in naming 'union N::U" "pr93809" { xfail *-*-*} .-1 } + // { dg-bogus "'class' tag used in naming 'union N::U" "pr93809" { target *-*-*} .-1 } union N::U u3; // { dg-warning "-Wredundant-tags" } diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h b/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h index 3de89f4..7e2c93e 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h @@ -4,7 +4,9 @@ #include <stdint-gcc.h> #include <stdbool.h> -typedef __uint128_t uint128_t; +#if __riscv_xlen == 64 +typedef unsigned __int128 uint128_t; +#endif /******************************************************************************/ /* Saturation Add (unsigned and signed) */ diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u128.c index 395a4cb..79f6297 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u128.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u128.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u128.c index 3c8b728..e5a9462 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u128.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u128.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u64-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u64-from-u128.c index e5572de..cbe2a22 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u64-from-u128.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u64-from-u128.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u128.c index 2e9c39a..1f54c30 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u128.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u128.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/s390/stack-protector-guard-tls-1.c b/gcc/testsuite/gcc.target/s390/stack-protector-guard-tls-1.c new file mode 100644 index 0000000..1efd245 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/stack-protector-guard-tls-1.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-protector-all" } */ +/* { dg-final { scan-assembler-times {\tear\t%r[0-9]+,%a[01]} 8 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\tsllg\t%r[0-9]+,%r[0-9]+,32} 4 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\tear\t%r[0-9]+,%a[01]} 3 { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler-times {\tmvc\t160\(8,%r15\),40\(%r[0-9]+\)} 2 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\tmvc\t100\(4,%r15\),20\(%r[0-9]+\)} 2 { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler-times {\tclc\t160\(8,%r15\),40\(%r[0-9]+\)} 2 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\tclc\t100\(4,%r15\),20\(%r[0-9]+\)} 2 { target { ! lp64 } } } } */ + +/* Computing the address of the thread pointer on s390 involves multiple + instructions and therefore bears the risk that the address of the canary or + intermediate values of it are spilled and reloaded. Therefore, as a + precaution compute the address always twice, i.e., one time for the prologue + and one time for the epilogue. */ + +void test_0 (void) { } + +void test_1 (void) +{ + __asm__ __volatile ("" ::: + "r0", + "r1", + "r2", + "r3", + "r4", + "r5", + "r6", + "r7", + "r8", + "r9", + "r10", + "r11", +#ifndef __PIC__ + "r12", +#endif + "r13", + "r14"); +} diff --git a/gcc/testsuite/gcc.target/xtensa/BGEUI-BLTUI-32k-64k.c b/gcc/testsuite/gcc.target/xtensa/BGEUI-BLTUI-32k-64k.c new file mode 100644 index 0000000..05873b8 --- /dev/null +++ b/gcc/testsuite/gcc.target/xtensa/BGEUI-BLTUI-32k-64k.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern void foo(void); + +void BGEUI_test(unsigned int a) +{ + if (a < 32768U) + foo(); +} + +void BLTUI_test(unsigned int a) +{ + if (a >= 65536U) + foo(); +} + +/* { dg-final { scan-assembler-times "bgeui" 1 } } */ +/* { dg-final { scan-assembler-times "bltui" 1 } } */ diff --git a/libgo/go/syscall/socket.go b/libgo/go/syscall/socket.go index 54a4a99..35665d5 100644 --- a/libgo/go/syscall/socket.go +++ b/libgo/go/syscall/socket.go @@ -467,7 +467,7 @@ func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) var iov Iovec if len(p) > 0 { diff --git a/libgo/runtime/go-memclr.c b/libgo/runtime/go-memclr.c index 53b8117..84df98d 100644 --- a/libgo/runtime/go-memclr.c +++ b/libgo/runtime/go-memclr.c @@ -11,50 +11,39 @@ void memclrNoHeapPointers(void *, uintptr) __attribute__ ((no_split_stack)); void -memclrNoHeapPointers (void *p1, uintptr len) +memclrNoHeapPointers(void *p1, uintptr len) { - -#if !defined(__PPC64__) - __builtin_memset(p1, 0, len); -#else - int64 rem,drem,i; - uint64 offset; - volatile uint64 *vp; + const uintptr ptr_size = sizeof(p1); + uintptr rem,drem,i; + uintptr offset; + volatile uintptr *vp; if (len == 0) { return; } rem = len; - offset = (uint64)p1 % 8; - // This memset is OK since it can't contain - // an 8 byte aligned pointer. - if ((rem < 8) || (offset > 0 && offset+rem <= 16)) { + offset = (uintptr)p1 % ptr_size; + if (rem < ptr_size || offset > 0) { + // This memset is OK since it can't contain + // an pointer aligned pointer. __builtin_memset(p1, 0, rem); return; } - // Move initial bytes to get to 8 byte boundary - if (offset > 0) { - __builtin_memset(p1, 0, 8-offset); - p1 = (void*)((char*)p1+8-offset); - rem -= 8-offset; - } - // If at least 8 bytes left, clear - drem = rem>>3; + drem = rem / ptr_size; - vp = (volatile uint64*)(p1); + vp = (volatile uintptr*)(p1); // Without the use of volatile here, the compiler // might convert the loop into a memset. for (i=0; i<drem; i++) { *vp = 0; vp++; - rem -= 8; + rem -= ptr_size; } - p1 = (void*)((char*)p1 + 8*drem); - // Clear any remaining + // Clear any remaining bytes. if (rem > 0) { - __builtin_memset (p1, 0, rem); + p1 = (void*)((char*)p1 + ptr_size*drem); + __builtin_memset(p1, 0, rem); } -#endif } diff --git a/libgo/runtime/go-memmove.c b/libgo/runtime/go-memmove.c index 1ca3f48..1dbd2b3 100644 --- a/libgo/runtime/go-memmove.c +++ b/libgo/runtime/go-memmove.c @@ -12,78 +12,60 @@ void gomemmove(void *, void *, uintptr) // This implementation is necessary since // the __builtin_memmove might use __libc_memmove -// which doesn't require atomicity of 8 byte +// which doesn't require atomicity of pointer-sized // moves. void -gomemmove (void *dst, void *src, uintptr len) +gomemmove(void *dst, void *src, uintptr len) { -#if !defined(__PPC64__) - __builtin_memmove(dst, src, len); -#else - uint64 offset, tail; - int64 rem; - uint64 dwords; - uint64 i; - char *bdst,*bsrc; - - rem = len; + const uintptr ptr_size = sizeof(dst); + uintptr tail; + uintptr rem; + uintptr dwords; + uintptr i; + char *bdst, *bsrc; if (len == 0) { - return; + return; } - // If src and dst don't have the same 8 byte alignment then - // there is no issue with copying pointer atomicity. Use the - // builtin. - if (((uint64)dst % 8) != ((uint64)src % 8) || len < 8) { - __builtin_memmove(dst, src, len); - return; + // We expect pointer-containing values to be pointer-aligned. + // If these pointers are not aligned, they don't contain pointers. + if ((uintptr)dst % ptr_size != 0 || (uintptr)src % ptr_size != 0 || len < ptr_size) { + __builtin_memmove(dst, src, len); + return; } - // Length >= 8 && same ptr alignment - offset = (uint64)dst % 8; - - // If not 8 byte alignment, move the intial bytes. - if (offset > 0) { - __builtin_memmove(dst, src, 8-offset); - dst += (8-offset); - src += (8-offset); - rem -= (8-offset); - } + bdst = (char*)dst; + bsrc = (char*)src; - // Move the tail bytes to make the backward move - // easier. - tail = rem % 8; + // Move the tail bytes to make the backward move easier. + rem = len; + tail = rem % ptr_size; if (tail > 0) { - __builtin_memmove(dst+rem-tail, src+rem-tail, tail); - rem -= tail; - } - - if (rem == 0) { - return; + __builtin_memmove(bdst+rem-tail, bsrc+rem-tail, tail); + rem -= tail; } - // Must now be 8 byte alignment and rem is multiple of 8. - dwords = len>>3; + // Must now be pointer alignment and rem is multiple of ptr_size. + dwords = rem / ptr_size; - // Determine if a backwards move is needed - // Forward or backward, move all doublewords + // Determine if a backwards move is needed. + // Forward or backward, move all words. - if ((uint64)(dst - src) < (uint64)rem) { - bdst = dst+rem-8; - bsrc = src+rem-8; - for (i = 0; i<dwords; i++) { - *(uint64*)bdst = *(uint64*)bsrc; - bdst -= 8; - bsrc -= 8; - } + if ((uintptr)(bdst - bsrc) < rem) { + bdst += rem - ptr_size; + bsrc += rem - ptr_size; + for (i = 0; i<dwords; i++) { + *(uintptr*)bdst = *(uintptr*)bsrc; + bdst -= ptr_size; + bsrc -= ptr_size; + } } else { - for (i = 0; i<dwords; i++) { - *(uint64*)dst = *(uint64*)src; - dst += 8; - src += 8; - } + for (i = 0; i<dwords; i++) { + *(uintptr*)bdst = *(uintptr*)bsrc; + bdst += ptr_size; + bsrc += ptr_size; + } } -#endif } diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4298304..090c5ce 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,175 @@ +2025-07-08 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/118681 + * testsuite/20_util/unsynchronized_pool_resource/118681.cc: Fix + deallocate argument. + +2025-07-08 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/118681 + * src/c++17/memory_resource.cc (choose_block_size): New + function. + (synchronized_pool_resource::do_allocate): Use choose_block_size + to determine appropriate block size. + (synchronized_pool_resource::do_deallocate): Likewise + (unsynchronized_pool_resource::do_allocate): Likewise. + (unsynchronized_pool_resource::do_deallocate): Likewise + * testsuite/20_util/synchronized_pool_resource/118681.cc: New + test. + * testsuite/20_util/unsynchronized_pool_resource/118681.cc: New + test. + +2025-07-08 Jonathan Wakely <jwakely@redhat.com> + + * include/debug/forward_list (_Safe_forward_list<>::_M_swap): + Adapt to _M_this() signature change. + +2025-07-08 Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/119861 + * include/std/format (formatter<_Rg, _CharT>::set_separator) + (formatter<_Rg, _CharT>::set_brackets): Constrain with + (format_kind<_Rg> == range_format::sequence). + * testsuite/std/format/ranges/pr119861_neg.cc: New test. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + PR libstdc++/120914 + * include/std/span (span): Update CTAD to enable + integral constants [P3029R1]. + * include/std/mdspan (extents): ditto. + (mdspan): ditto. + * testsuite/23_containers/span/deduction.cc: Test deduction + guide. + * testsuite/23_containers/mdspan/extents/misc.cc: ditto. + * testsuite/23_containers/mdspan/mdspan.cc: ditto. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + * testsuite/23_containers/span/contiguous_range_neg.cc: Silence + warning about unused variable myspan. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + PR libstdc++/107761 + * include/bits/version.def (mdspan): Set to 202207 and remove + no_stdname. + * include/bits/version.h: Regenerate. + * testsuite/23_containers/mdspan/version.cc: Test presence + of feature test macro. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + PR libstdc++/107761 + * include/std/mdspan (mdspan): New class. + * src/c++23/std.cc.in (mdspan): Add. + * testsuite/23_containers/mdspan/class_mandate_neg.cc: New test. + * testsuite/23_containers/mdspan/mdspan.cc: New test. + * testsuite/23_containers/mdspan/layout_like.h: Add class + LayoutLike which models a user-defined layout. + * testsuite/23_containers/mdspan/out_of_bounds_neg.cc: New file. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + * include/std/mdspan (__mdspan::__size): New function. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + * testsuite/23_containers/mdspan/extents/custom_integer.cc: + Delete IntLike and include "int_like.h". + * testsuite/23_containers/mdspan/extents/int_like.h: Add + IntLike. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + * include/std/mdspan (extents): Check prerequisite of the ctor that + static_extent(i) == dynamic_extent || extent(i) == other.extent(i). + * testsuite/23_containers/mdspan/extents/class_mandates_neg.cc: + Test the implemented prerequisite. + * testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc: New file. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + * include/std/mdspan: Check prerequisites of + layout_*::operator() with _GLIBCXX_DEBUG_ASSERTs. + * testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc: + Add tests for prerequisites. + +2025-07-08 Tomasz Kamiński <tkaminsk@redhat.com> + + * include/std/queue (formatter<queue<_Tp, _Container>, _CharT>) + (formatter<priority_queue<_Tp, _Container, _Compare>, _CharT>): + Add _GLIBCXX_RESOLVE_LIB_DEFECTS comments. + +2025-07-08 François Dumont <frs.dumont@gmail.com> + + PR c++/116369 + * config/abi/pre/gnu-versioned-namespace.ver: Use new const qualified symbols. + * config/abi/pre/gnu.ver: Add new const qualified symbols. + * include/debug/safe_base.h + (_Safe_iterator_base::_M_sequence): Declare as pointer-to-const. + (_Safe_iterator_base::_M_attach, _M_attach_single): New, take pointer-to-const + _Safe_sequence_base. + (_Safe_sequence_base::_M_detach_all, _M_detach_singular, _M_revalidate_singular) + (_M_swap, _M_get_mutex): New, const qualified. + (_Safe_sequence_base::_M_attach, _M_attach_single, _M_detach, _M_detach_single): + const qualify. + * include/debug/safe_container.h (_Safe_container<>::_M_cont): Add const qualifier. + (_Safe_container<>::_M_swap_base): New. + (_Safe_container(_Safe_container&&, const _Alloc&, std::false_type)): + Adapt to use latter. + (_Safe_container<>::operator=(_Safe_container&&)): Likewise. + (_Safe_container<>::_M_swap): Likewise and take parameter as const reference. + * include/debug/safe_unordered_base.h + (_Safe_local_iterator_base::_M_safe_container): New. + (_Safe_local_iterator_base::_Safe_local_iterator_base): Take + _Safe_unordered_container_base as pointer-to-const. + (_Safe_unordered_container_base::_M_attach, _M_attach_single): New, take + container as _Safe_unordered_container_base pointer-to-const. + (_Safe_unordered_container_base::_M_local_iterators, _M_const_local_iterators): + Add mutable. + (_Safe_unordered_container_base::_M_detach_all, _M_swap): New, const qualify. + (_Safe_unordered_container_base::_M_attach_local, _M_attach_local_single) + (_M_detach_local, _M_detach_local_single): Add const qualifier. + * include/debug/safe_unordered_container.h (_Safe_unordered_container::_M_self()): New. + * include/debug/safe_unordered_container.tcc + (_Safe_unordered_container::_M_invalidate_if, _M_invalidated_local_if): Use latter. + * include/debug/safe_iterator.h (_Safe_iterator<>::_M_attach, _M_attach_single): + Take _Safe_sequence_base as pointer-to-const. + (_Safe_iterator<>::_M_get_sequence): Add const_cast and comment about it. + * include/debug/safe_local_iterator.h (_Safe_local_iterator<>): Replace usages + of _M_sequence member by _M_safe_container(). + (_Safe_local_iterator<>::_M_attach, _M_attach_single): Take + _Safe_unordered_container_base as pointer-to-const. + (_Safe_local_iterator<>::_M_get_sequence): Rename into... + (_Safe_local_iterator<>::_M_get_ucontainer): ...this. Add necessary const_cast and + comment to explain it. + (_Safe_local_iterator<>::_M_is_begin, _M_is_end): Adapt. + * include/debug/safe_local_iterator.tcc: Adapt. + * include/debug/safe_sequence.h + (_Safe_sequence<>::_M_invalidate_if, _M_transfer_from_if): Add const qualifier. + * include/debug/safe_sequence.tcc: Adapt. + * include/debug/deque (std::__debug::deque::erase): Adapt to use new const + qualified methods. + * include/debug/formatter.h: Adapt. + * include/debug/forward_list (_Safe_forward_list::_M_this): Add const + qualification and return pointer for consistency with 'this' keyword. + (_Safe_forward_list::_M_swap_aux): Rename into... + (_Safe_forward_list::_S_swap_aux): ...this and take sequence as const reference. + (forward_list<>::resize): Adapt to use const methods. + * include/debug/list (list<>::resize): Likewise. + * src/c++11/debug.cc: Adapt to const qualification. + * testsuite/util/testsuite_containers.h + (forward_members_unordered::forward_members_unordered): Add check on local_iterator + conversion to const_local_iterator. + (forward_members::forward_members): Add check on iterator conversion to + const_iterator. + * testsuite/23_containers/unordered_map/const_container.cc: New test case. + * testsuite/23_containers/unordered_multimap/const_container.cc: New test case. + * testsuite/23_containers/unordered_multiset/const_container.cc: New test case. + * testsuite/23_containers/unordered_set/const_container.cc: New test case. + * testsuite/23_containers/vector/debug/mutex_association.cc: Adapt. + 2025-07-07 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/120949 diff --git a/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt b/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt index ac11d5d..5d55287 100644 --- a/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt +++ b/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt @@ -2124,6 +2124,10 @@ FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policy FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEC2EOS5_@@GLIBCXX_3.4.28 FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEC2Ev@@GLIBCXX_3.4.27 FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEaSEOS5_@@GLIBCXX_3.4.26 +FUNC:_ZNSt12__sso_stringC1Ev@@GLIBCXX_3.4.34 +FUNC:_ZNSt12__sso_stringC2Ev@@GLIBCXX_3.4.34 +FUNC:_ZNSt12__sso_stringD1Ev@@GLIBCXX_3.4.34 +FUNC:_ZNSt12__sso_stringD2Ev@@GLIBCXX_3.4.34 FUNC:_ZNSt12bad_weak_ptrD0Ev@@GLIBCXX_3.4.15 FUNC:_ZNSt12bad_weak_ptrD1Ev@@GLIBCXX_3.4.15 FUNC:_ZNSt12bad_weak_ptrD2Ev@@GLIBCXX_3.4.15 @@ -3221,6 +3225,8 @@ FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_Alloc_hiderC1EPcRKS FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_Alloc_hiderC2EPcOS3_@@GLIBCXX_3.4.23 FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_Alloc_hiderC2EPcRKS3_@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructEjc@@GLIBCXX_3.4.21 +FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructILb0EEEvPKcj@@GLIBCXX_3.4.34 +FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructILb1EEEvPKcj@@GLIBCXX_3.4.34 FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPKcS4_EEEEvT_SB_St20forward_iterator_tag@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPcS4_EEEEvT_SA_St20forward_iterator_tag@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag@@GLIBCXX_3.4.21 @@ -3374,6 +3380,8 @@ FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_Alloc_hiderC1EPwRKS FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_Alloc_hiderC2EPwOS3_@@GLIBCXX_3.4.23 FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_Alloc_hiderC2EPwRKS3_@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructEjw@@GLIBCXX_3.4.21 +FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructILb0EEEvPKwj@@GLIBCXX_3.4.34 +FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructILb1EEEvPKwj@@GLIBCXX_3.4.34 FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPKwS4_EEEEvT_SB_St20forward_iterator_tag@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPwS4_EEEEvT_SA_St20forward_iterator_tag@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructIPKwEEvT_S8_St20forward_iterator_tag@@GLIBCXX_3.4.21 @@ -3941,6 +3949,8 @@ FUNC:_ZNSt8__detail15_List_node_base11_M_transferEPS0_S1_@@GLIBCXX_3.4.15 FUNC:_ZNSt8__detail15_List_node_base4swapERS0_S1_@@GLIBCXX_3.4.15 FUNC:_ZNSt8__detail15_List_node_base7_M_hookEPS0_@@GLIBCXX_3.4.15 FUNC:_ZNSt8__detail15_List_node_base9_M_unhookEv@@GLIBCXX_3.4.15 +FUNC:_ZNSt8__format25__locale_encoding_to_utf8ERKSt6localeSt17basic_string_viewIcSt11char_traitsIcEEPv@@GLIBCXX_3.4.34 +FUNC:_ZNSt8__format26__with_encoding_conversionERKSt6locale@@GLIBCXX_3.4.34 FUNC:_ZNSt8bad_castD0Ev@@GLIBCXX_3.4 FUNC:_ZNSt8bad_castD1Ev@@GLIBCXX_3.4 FUNC:_ZNSt8bad_castD2Ev@@GLIBCXX_3.4 @@ -4617,6 +4627,7 @@ OBJECT:0:GLIBCXX_3.4.30 OBJECT:0:GLIBCXX_3.4.31 OBJECT:0:GLIBCXX_3.4.32 OBJECT:0:GLIBCXX_3.4.33 +OBJECT:0:GLIBCXX_3.4.34 OBJECT:0:GLIBCXX_3.4.4 OBJECT:0:GLIBCXX_3.4.5 OBJECT:0:GLIBCXX_3.4.6 diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list index 4e1511d..9da7dda 100644 --- a/libstdc++-v3/include/debug/forward_list +++ b/libstdc++-v3/include/debug/forward_list @@ -144,13 +144,13 @@ namespace __gnu_debug //std::swap(_M_this()->_M_version, __other._M_version); _Safe_iterator_base* __this_its = _M_this()->_M_iterators; _S_swap_aux(__other, __other._M_iterators, - _M_this(), _M_this()->_M_iterators); + *_M_this(), _M_this()->_M_iterators); _Safe_iterator_base* __this_const_its = _M_this()->_M_const_iterators; _S_swap_aux(__other, __other._M_const_iterators, - _M_this(), _M_this()->_M_const_iterators); - _S_swap_aux(_M_this(), __this_its, + *_M_this(), _M_this()->_M_const_iterators); + _S_swap_aux(*_M_this(), __this_its, __other, __other._M_iterators); - _S_swap_aux(_M_this(), __this_const_its, + _S_swap_aux(*_M_this(), __this_const_its, __other, __other._M_const_iterators); } diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 5749aa1..d584b81 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -6030,13 +6030,13 @@ namespace __format constexpr void set_separator(basic_string_view<_CharT> __sep) noexcept - requires (!_S_range_format_is_string) + requires (format_kind<_Rg> == range_format::sequence) { _M_under.set_separator(__sep); } constexpr void set_brackets(basic_string_view<_CharT> __open, basic_string_view<_CharT> __close) noexcept - requires (!_S_range_format_is_string) + requires (format_kind<_Rg> == range_format::sequence) { _M_under.set_brackets(__open, __close); } // We deviate from standard, that declares this as template accepting diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index 5a42aea..5d16de5 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -406,10 +406,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _IndexType, size_t... _Counts> auto __build_dextents_type(integer_sequence<size_t, _Counts...>) -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>; - - template<typename _Tp> - consteval size_t - __dynamic_extent() { return dynamic_extent; } } template<typename _IndexType, size_t _Rank> @@ -419,7 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename... _Integrals> requires (is_convertible_v<_Integrals, size_t> && ...) explicit extents(_Integrals...) -> - extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>; + extents<size_t, __detail::__maybe_static_ext<_Integrals>...>; struct layout_left { @@ -1316,7 +1312,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && (sizeof...(_Integrals) > 0) explicit mdspan(_ElementType*, _Integrals...) -> mdspan<_ElementType, - extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>>; + extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>; template<typename _ElementType, typename _OIndexType, size_t _Nm> mdspan(_ElementType*, span<_OIndexType, _Nm>) diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span index 49ab910..5629a71 100644 --- a/libstdc++-v3/include/std/span +++ b/libstdc++-v3/include/std/span @@ -476,6 +476,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; // deduction guides + namespace __detail + { + template<typename _Tp> + concept __integral_constant_like = is_integral_v<decltype(_Tp::value)> + && !is_same_v<bool, remove_const_t<decltype(_Tp::value)>> + && convertible_to<_Tp, decltype(_Tp::value)> + && equality_comparable_with<_Tp, decltype(_Tp::value)> + && bool_constant<_Tp() == _Tp::value>::value + && bool_constant<static_cast<decltype(_Tp::value)>(_Tp()) == _Tp::value> + ::value; + + template<typename _Tp> + constexpr size_t __maybe_static_ext = dynamic_extent; + + template<__integral_constant_like _Tp> + constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value}; + } template<typename _Type, size_t _ArrayExtent> span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>; @@ -489,7 +506,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<contiguous_iterator _Iter, typename _End> span(_Iter, _End) - -> span<remove_reference_t<iter_reference_t<_Iter>>>; + -> span<remove_reference_t<iter_reference_t<_Iter>>, + __detail::__maybe_static_ext<_End>>; template<ranges::contiguous_range _Range> span(_Range &&) diff --git a/libstdc++-v3/src/c++17/memory_resource.cc b/libstdc++-v3/src/c++17/memory_resource.cc index fac4c78..fddfe2c 100644 --- a/libstdc++-v3/src/c++17/memory_resource.cc +++ b/libstdc++-v3/src/c++17/memory_resource.cc @@ -1242,12 +1242,30 @@ namespace pmr return pools; } + static inline size_t + choose_block_size(size_t bytes, size_t alignment) + { + if (bytes == 0) [[unlikely]] + return alignment; + + // Use bit_ceil in case alignment is invalid (i.e. not a power of two). + size_t mask = std::__bit_ceil(alignment) - 1; + // Round up to a multiple of alignment. + size_t block_size = (bytes + mask) & ~mask; + + if (block_size >= bytes) [[likely]] + return block_size; + + // Wrapped around to zero, bytes must have been impossibly large. + return numeric_limits<size_t>::max(); + } + // Override for memory_resource::do_allocate void* synchronized_pool_resource:: do_allocate(size_t bytes, size_t alignment) { - const auto block_size = std::max(bytes, alignment); + const auto block_size = choose_block_size(bytes, alignment); const pool_options opts = _M_impl._M_opts; if (block_size <= opts.largest_required_pool_block) { @@ -1294,7 +1312,7 @@ namespace pmr synchronized_pool_resource:: do_deallocate(void* p, size_t bytes, size_t alignment) { - size_t block_size = std::max(bytes, alignment); + size_t block_size = choose_block_size(bytes, alignment); if (block_size <= _M_impl._M_opts.largest_required_pool_block) { const ptrdiff_t index = pool_index(block_size, _M_impl._M_npools); @@ -1453,7 +1471,7 @@ namespace pmr void* unsynchronized_pool_resource::do_allocate(size_t bytes, size_t alignment) { - const auto block_size = std::max(bytes, alignment); + const auto block_size = choose_block_size(bytes, alignment); if (block_size <= _M_impl._M_opts.largest_required_pool_block) { // Recreate pools if release() has been called: @@ -1470,7 +1488,7 @@ namespace pmr unsynchronized_pool_resource:: do_deallocate(void* p, size_t bytes, size_t alignment) { - size_t block_size = std::max(bytes, alignment); + size_t block_size = choose_block_size(bytes, alignment); if (block_size <= _M_impl._M_opts.largest_required_pool_block) { if (auto pool = _M_find_pool(block_size)) diff --git a/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc new file mode 100644 index 0000000..6d7434f --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc @@ -0,0 +1,5 @@ +// { dg-do run { target c++17 } } +// Bug 118681 - unsynchronized_pool_resource may fail to respect alignment + +#define RESOURCE std::pmr::synchronized_pool_resource +#include "../unsynchronized_pool_resource/118681.cc" diff --git a/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc new file mode 100644 index 0000000..9935f79 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc @@ -0,0 +1,58 @@ +// { dg-do run { target c++17 } } +// Bug 118681 - unsynchronized_pool_resource may fail to respect alignment + +#include <memory_resource> +#include <cstdio> +#include <testsuite_hooks.h> + +#ifndef RESOURCE +# define RESOURCE std::pmr::unsynchronized_pool_resource +#endif + +bool any_misaligned = false; + +bool +is_aligned(void* p, [[maybe_unused]] std::size_t size, std::size_t alignment) +{ + const bool misaligned = reinterpret_cast<std::uintptr_t>(p) % alignment; +#ifdef DEBUG + std::printf("allocate(%2zu, %2zu): %p is aligned %scorrectly\n", + size, alignment, p, misaligned ? "in" : ""); + any_misaligned |= misaligned; + return true; +#endif + return ! misaligned; +} + +void +test_alignment(std::pmr::memory_resource& res, bool dealloc) +{ + for (std::size_t alignment : { 8, 16, 32, 64 }) + { + for (std::size_t size : { 9, 12, 24, 40, 48, 56, 72 }) + { + void* p1 = res.allocate(size, alignment); + void* p2 = res.allocate(size, alignment); + + VERIFY( is_aligned(p1, size, alignment) ); + VERIFY( is_aligned(p2, size, alignment) ); + + if (dealloc) + { + res.deallocate(p1, size, alignment); + res.deallocate(p2, size, alignment); + } + } + } +} + +int main() +{ + RESOURCE res; + test_alignment(res, true); + res.release(); + test_alignment(res, false); + res.release(); + + VERIFY( ! any_misaligned ); +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc index e71fdc5..bca8901 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc @@ -98,12 +98,32 @@ test_deduction(Extents... exts) } constexpr bool +test_integral_constant_deduction() +{ + auto verify = [](auto actual, auto expected) + { + static_assert(std::same_as<decltype(actual), decltype(expected)>); + VERIFY(actual == expected); + }; + + constexpr auto c1 = std::integral_constant<size_t, 1>{}; + constexpr auto c2 = std::integral_constant<int, 2>{}; + + verify(std::extents(1), std::extents<size_t, dyn>{1}); + verify(std::extents(c1), std::extents<size_t, 1>{}); + verify(std::extents(c2), std::extents<size_t, 2>{}); + verify(std::extents(c1, 2), std::extents<size_t, 1, dyn>{2}); + return true; +} + +constexpr bool test_deduction_all() { test_deduction<0>(); test_deduction<1>(1); test_deduction<2>(1.0, 2.0f); test_deduction<3>(int(1), short(2), size_t(3)); + test_integral_constant_deduction(); return true; } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc index 9252273..a650fb1 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc @@ -246,6 +246,28 @@ test_from_pointer_and_shape() } constexpr bool +test_from_pointer_and_integral_constant() +{ + std::array<double, 6> buffer{}; + double * ptr = buffer.data(); + + auto verify = [ptr](auto actual, auto exts) + { + auto expected = std::mdspan<double, decltype(exts)>(ptr, exts); + static_assert(std::same_as<decltype(actual), decltype(expected)>); + VERIFY(actual.extents() == expected.extents()); + }; + + auto c3 = std::integral_constant<int, 3>{}; + auto c6 = std::integral_constant<int, 6>{}; + + verify(std::mdspan(ptr, 6), std::extents(6)); + verify(std::mdspan(ptr, c6), std::extents(c6)); + verify(std::mdspan(ptr, 2, c3), std::extents(2, c3)); + return true; +} + +constexpr bool test_from_extents() { constexpr size_t n = 3*5*7; @@ -616,6 +638,9 @@ main() test_from_pointer_and_shape(); static_assert(test_from_pointer_and_shape()); + test_from_pointer_and_integral_constant(); + static_assert(test_from_pointer_and_integral_constant()); + test_from_extents(); static_assert(test_from_extents()); diff --git a/libstdc++-v3/testsuite/23_containers/span/deduction.cc b/libstdc++-v3/testsuite/23_containers/span/deduction.cc index dce6ced..c66db90 100644 --- a/libstdc++-v3/testsuite/23_containers/span/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/span/deduction.cc @@ -80,4 +80,7 @@ test01() std::span s12(const_cast<const std::span<int>&>(s5)); static_assert( is_dynamic_span<int>(s12) ); + + std::span s13(a.data(), std::integral_constant<size_t, 3>{}); + static_assert( is_static_span<long, 3>(s13)); } diff --git a/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc b/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc new file mode 100644 index 0000000..9a6ed16 --- /dev/null +++ b/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc @@ -0,0 +1,52 @@ +// { dg-do compile { target c++23 } } + +#include <format> +#include <vector> + +// only format_kind::sequence provides set_brackets and set_separator methods + +template<std::range_format fk, typename T> +struct MyCont : std::vector<T> +{ + using std::vector<T>::vector; +}; + +template<std::range_format fk, typename T> +constexpr std::range_format std::format_kind<MyCont<fk, T>> = fk; + +void test_sequence() +{ + std::formatter<MyCont<std::range_format::sequence, int>, char> fmtter; + fmtter.set_brackets("{", "}"); + fmtter.set_separator(","); +} + +void test_map() +{ + std::formatter<MyCont<std::range_format::map, std::pair<int, int>>, char> fmtter; + fmtter.set_brackets("{", "}"); // { dg-error "here" } + fmtter.set_separator(","); // { dg-error "here" } +} + +void test_set() +{ + std::formatter<MyCont<std::range_format::set, int>, char> fmtter; + fmtter.set_brackets("{", "}"); // { dg-error "here" } + fmtter.set_separator(","); // { dg-error "here" } +} + +void test_string() +{ + std::formatter<MyCont<std::range_format::string, char>, char> fmtter; + fmtter.set_brackets("{", "}"); // { dg-error "here" } + fmtter.set_separator(","); // { dg-error "here" } +} + +void test_debug_string() +{ + std::formatter<MyCont<std::range_format::debug_string, char>, char> fmtter; + fmtter.set_brackets("{", "}"); // { dg-error "here" } + fmtter.set_separator(","); // { dg-error "here" } +} + +// { dg-error "no matching function for call to 'std::formatter<" "" { target *-*-* } 0 } |