diff options
74 files changed, 1749 insertions, 215 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/auto-profile.cc b/gcc/auto-profile.cc index a970eb8..e27bcc7 100644 --- a/gcc/auto-profile.cc +++ b/gcc/auto-profile.cc @@ -622,9 +622,11 @@ get_original_name (const char *name, bool alloc = true) } /* Suffixes of clones that compiler generates after auto-profile. */ const char *suffixes[] = {"isra", "constprop", "lto_priv", "part", "cold"}; - for (unsigned i = 0; i < sizeof (suffixes); ++i) + for (unsigned i = 0; i < sizeof (suffixes) / sizeof (const char *); ++i) { - if (strncmp (next_dot + 1, suffixes[i], strlen (suffixes[i])) == 0) + int len = strlen (suffixes[i]); + if (len == last_dot - next_dot - 1 + && strncmp (next_dot + 1, suffixes[i], strlen (suffixes[i])) == 0) { *next_dot = 0; return get_original_name (ret, false); @@ -3304,10 +3306,22 @@ cmp (const void *a, const void *b) return 0; } +/* To scalle a connected component of graph we collect desired scales of + basic blocks on the boundary and then compute a robust average. */ + +struct scale +{ + /* Scale descired. */ + sreal scale; + /* Weight for averaging computed from execution count of the edge + scale originates from. */ + uint64_t weight; +}; + /* Add scale ORIG/ANNOTATED to SCALES. */ static void -add_scale (vec <sreal> *scales, profile_count annotated, profile_count orig) +add_scale (vec <scale> *scales, profile_count annotated, profile_count orig) { if (dump_file) { @@ -3316,15 +3330,15 @@ add_scale (vec <sreal> *scales, profile_count annotated, profile_count orig) annotated.dump (dump_file); fprintf (dump_file, "\n"); } - if (orig.nonzero_p ()) + if (orig.force_nonzero () == orig) { sreal scale = annotated.guessed_local () .to_sreal_scale (orig); if (dump_file) - fprintf (dump_file, " adding scale %.16f\n", - scale.to_double ()); - scales->safe_push (scale); + fprintf (dump_file, " adding scale %.16f, weight %" PRId64 "\n", + scale.to_double (), annotated.value () + 1); + scales->safe_push ({scale, annotated.value () + 1}); } } @@ -3370,7 +3384,7 @@ afdo_adjust_guessed_profile (bb_set *annotated_bb) /* Basic blocks of connected component currently processed. */ auto_vec <basic_block, 20> bbs (n_basic_blocks_for_fn (cfun)); /* Scale factors found. */ - auto_vec <sreal, 20> scales; + auto_vec <scale, 20> scales; auto_vec <basic_block, 20> stack (n_basic_blocks_for_fn (cfun)); basic_block seed_bb; @@ -3382,9 +3396,15 @@ afdo_adjust_guessed_profile (bb_set *annotated_bb) >=2 is an id of the component BB belongs to. */ auto_vec <unsigned int, 20> component; component.safe_grow (last_basic_block_for_fn (cfun)); + profile_count max_count_in_fn = profile_count::zero (); FOR_ALL_BB_FN (seed_bb, cfun) - component[seed_bb->index] - = is_bb_annotated (seed_bb, *annotated_bb) ? 1 : 0; + if (is_bb_annotated (seed_bb, *annotated_bb)) + { + component[seed_bb->index] = 1; + max_count_in_fn = max_count_in_fn.max (seed_bb->count); + } + else + component[seed_bb->index] = 0; FOR_ALL_BB_FN (seed_bb, cfun) if (!component[seed_bb->index]) { @@ -3507,12 +3527,15 @@ afdo_adjust_guessed_profile (bb_set *annotated_bb) profile_count annotated_count = e->dest->count; profile_count out_count = profile_count::zero (); bool ok = true; + for (edge e2: e->dest->preds) if (AFDO_EINFO (e2)->is_annotated ()) annotated_count -= AFDO_EINFO (e2)->get_count (); - else if (component[e->src->index] == component_id) - out_count += e->count (); - else if (e->probability.nonzero_p ()) + else if (component[e2->src->index] == component_id) + out_count += e2->count (); + else if (is_bb_annotated (e2->src, *annotated_bb)) + annotated_count -= e2->count (); + else if (e2->probability.nonzero_p ()) { ok = false; break; @@ -3559,7 +3582,43 @@ afdo_adjust_guessed_profile (bb_set *annotated_bb) } gcc_checking_assert (scales.length ()); scales.qsort (cmp); - scale_bbs (bbs, scales[scales.length () / 2]); + + uint64_t overall_weight = 0; + for (scale &e : scales) + overall_weight += e.weight; + + uint64_t cummulated = 0, weight_sum = 0; + sreal scale_sum = 0; + for (scale &e : scales) + { + uint64_t prev = cummulated; + cummulated += e.weight; + if (cummulated >= overall_weight / 4 + && prev <= 3 * overall_weight / 4) + { + scale_sum += e.scale * e.weight; + weight_sum += e.weight; + if (dump_file) + fprintf (dump_file, " accounting scale %.16f, weight %" PRId64 "\n", + e.scale.to_double (), e.weight); + } + else if (dump_file) + fprintf (dump_file, " ignoring scale %.16f, weight %" PRId64 "\n", + e.scale.to_double (), e.weight); + } + sreal scale = scale_sum / (sreal)weight_sum; + + /* Avoid scaled regions to have very large counts. + Otherwise they may dominate ipa-profile's histogram computing cutoff + of hot basic blocks. */ + if (max_count * scale > max_count_in_fn.guessed_local ()) + { + fprintf (dump_file, "Scaling by %.16f produces max count ", scale.to_double ()); + (max_count * scale).dump (dump_file); + fprintf (dump_file, " that exceeds max count in fn; capping\n"); + scale = max_count_in_fn.guessed_local ().to_sreal_scale (max_count); + } + scale_bbs (bbs, scale); } } diff --git a/gcc/config.gcc b/gcc/config.gcc index 5953ace..8ed1113 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -1847,11 +1847,11 @@ moxie-*-moxiebox*) ;; h8300-*-elf*) tmake_file="h8300/t-h8300" - tm_file="h8300/h8300.h elfos.h newlib-stdint.h h8300/elf.h" + tm_file="elfos.h h8300/h8300.h newlib-stdint.h h8300/elf.h" ;; h8300-*-linux*) tmake_file="${tmake_file} h8300/t-h8300 h8300/t-linux" - tm_file="h8300/h8300.h elfos.h gnu-user.h linux.h glibc-stdint.h h8300/linux.h" + tm_file="elfos.h h8300/h8300.h gnu-user.h linux.h glibc-stdint.h h8300/linux.h" ;; hppa*64*-*-linux*) target_cpu_default="MASK_PA_11|MASK_PA_20" diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h index cba50de..105385f 100644 --- a/gcc/config/arm/arm_neon.h +++ b/gcc/config/arm/arm_neon.h @@ -20938,11 +20938,6 @@ vbfdotq_lane_f32 (float32x4_t __r, bfloat16x8_t __a, bfloat16x4_t __b, return __builtin_neon_vbfdot_lanev4bfv4sf (__r, __a, __b, __index); } -#pragma GCC pop_options - -#pragma GCC push_options -#pragma GCC target ("arch=armv8.2-a+bf16") - typedef struct bfloat16x4x2_t { bfloat16x4_t val[2]; diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h index 6b2dd65..8018b63 100644 --- a/gcc/config/h8300/h8300.h +++ b/gcc/config/h8300/h8300.h @@ -610,6 +610,12 @@ struct cum_arg #define DATA_SECTION_ASM_OP "\t.section .data" #define BSS_SECTION_ASM_OP "\t.section .bss" +/* Override default definitions from elfos.h. */ +#undef INIT_SECTION_ASM_OP +#define INIT_SECTION_ASM_OP "\t.section\t.init,\"ax\"" +#undef FINI_SECTION_ASM_OP +#define FINI_SECTION_ASM_OP "\t.section\t.fini,\"ax\"" + #undef DO_GLOBAL_CTORS_BODY #define DO_GLOBAL_CTORS_BODY \ { \ @@ -647,19 +653,11 @@ struct cum_arg /* Globalizing directive for a label. */ #define GLOBAL_ASM_OP "\t.global " +/* Override default definition from elfos.h. */ +#undef ASM_DECLARE_FUNCTION_NAME #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ ASM_OUTPUT_FUNCTION_LABEL (FILE, NAME, DECL) -/* This is how to store into the string LABEL - the symbol_ref name of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - This is suitable for output with `assemble_name'. - - N.B.: The h8300.md branch_true and branch_false patterns also know - how to generate internal labels. */ -#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ - sprintf (LABEL, "*.%s%lu", PREFIX, (unsigned long)(NUM)) - /* This is how to output an insn to push a register on the stack. It need not be very fast code. */ @@ -690,9 +688,6 @@ struct cum_arg if ((LOG) != 0) \ fprintf (FILE, "\t.align %d\n", (LOG)) -#define ASM_OUTPUT_SKIP(FILE, SIZE) \ - fprintf (FILE, "\t.space %d\n", (int)(SIZE)) - /* This says how to output an assembler line to define a global common symbol. */ diff --git a/gcc/config/riscv/riscv-avlprop.cc b/gcc/config/riscv/riscv-avlprop.cc index bb4aceb..3031c29 100644 --- a/gcc/config/riscv/riscv-avlprop.cc +++ b/gcc/config/riscv/riscv-avlprop.cc @@ -508,7 +508,7 @@ pass_avlprop::execute (function *fn) simplify_replace_vlmax_avl (rinsn, prop.second); } - if (rvv_vector_bits == RVV_VECTOR_BITS_ZVL) + if (rvv_vector_bits == RVV_VECTOR_BITS_ZVL && !TARGET_XTHEADVECTOR) { /* Simplify VLMAX AVL into immediate AVL. E.g. Simplify this following case: 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 99b9854..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); 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 32c6a42..8148495 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -35928,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/ext-dce.cc b/gcc/ext-dce.cc index e7635fb..67ec92a 100644 --- a/gcc/ext-dce.cc +++ b/gcc/ext-dce.cc @@ -757,7 +757,7 @@ ext_dce_process_uses (rtx_insn *insn, rtx obj, and process the inner object. */ if (paradoxical_subreg_p (y)) y = XEXP (y, 0); - else if (SUBREG_P (y) && SUBREG_BYTE (y).is_constant ()) + else if (SUBREG_P (y) && subreg_lsb (y).is_constant (&bit)) { /* If !TRULY_NOOP_TRUNCATION_MODES_P, the mode change performed by Y would normally need to be a @@ -774,8 +774,6 @@ ext_dce_process_uses (rtx_insn *insn, rtx obj, GET_MODE (SUBREG_REG (y)))))) break; - bit = subreg_lsb (y).to_constant (); - /* If this is a wide object (more bits than we can fit in a HOST_WIDE_INT), then just break from the SET context. That will cause the iterator to walk down 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/match.pd b/gcc/match.pd index ec2f560..67b33ee 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3716,6 +3716,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if ((TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@2) == INTEGER_CST) || ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) + || (VECTOR_TYPE_P (TREE_TYPE (@1)) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, code2)) || POINTER_TYPE_P (TREE_TYPE (@1))) && bitwise_equal_p (@1, @2))) (with @@ -3754,27 +3756,39 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (code1 == EQ_EXPR && val) @3) (if (code1 == EQ_EXPR && !val) { constant_boolean_node (false, type); }) (if (code1 == NE_EXPR && !val && allbits) @4) - (if (code1 == NE_EXPR + (if ((code1 == NE_EXPR && code2 == GE_EXPR && cmp == 0 && allbits) + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, GT_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (gt @c0 (convert @1))) - (if (code1 == NE_EXPR + (if ((code1 == NE_EXPR && code2 == LE_EXPR && cmp == 0 && allbits) + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, LT_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (lt @c0 (convert @1))) /* (a != (b+1)) & (a > b) -> a > (b+1) */ - (if (code1 == NE_EXPR + (if ((code1 == NE_EXPR && code2 == GT_EXPR && one_after && allbits) + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, GT_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (gt @c0 (convert @1))) /* (a != (b-1)) & (a < b) -> a < (b-1) */ - (if (code1 == NE_EXPR + (if ((code1 == NE_EXPR && code2 == LT_EXPR && one_before && allbits) + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, LT_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (lt @c0 (convert @1))) ) ) @@ -3793,6 +3807,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if ((TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@2) == INTEGER_CST) || ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) + || (VECTOR_TYPE_P (TREE_TYPE (@1)) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, code2)) || POINTER_TYPE_P (TREE_TYPE (@1))) && operand_equal_p (@1, @2))) (with @@ -3843,6 +3859,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if ((TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@2) == INTEGER_CST) || ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) + || (VECTOR_TYPE_P (TREE_TYPE (@1))) || POINTER_TYPE_P (TREE_TYPE (@1))) && bitwise_equal_p (@1, @2))) (with @@ -3884,24 +3901,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (code1 == EQ_EXPR && code2 == GT_EXPR && cmp == 0 - && allbits) + && allbits + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, GE_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (ge @c0 @2)) (if (code1 == EQ_EXPR && code2 == LT_EXPR && cmp == 0 - && allbits) + && allbits + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, LE_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (le @c0 @2)) /* (a == (b-1)) | (a >= b) -> a >= (b-1) */ (if (code1 == EQ_EXPR && code2 == GE_EXPR && one_before - && allbits) + && allbits + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, GE_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (ge @c0 (convert @1))) /* (a == (b+1)) | (a <= b) -> a <= (b-1) */ (if (code1 == EQ_EXPR && code2 == LE_EXPR && one_after - && allbits) + && allbits + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, LE_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (le @c0 (convert @1))) ) ) @@ -3966,7 +3995,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) rcmp (ne le gt ne lt ge) (simplify (op:c (cmp1:c @0 @1) (cmp2 @0 @1)) - (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0))) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + || POINTER_TYPE_P (TREE_TYPE (@0)) + || (VECTOR_TYPE_P (TREE_TYPE (@1)) + && expand_vec_cmp_expr_p (TREE_TYPE (@0), type, rcmp))) (rcmp @0 @1))))) /* Optimize (a CMP b) == (a CMP b) */ @@ -3975,7 +4007,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) rcmp (eq gt le eq ge lt) (simplify (eq:c (cmp1:c @0 @1) (cmp2 @0 @1)) - (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0))) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + || POINTER_TYPE_P (TREE_TYPE (@0)) + || (VECTOR_TYPE_P (TREE_TYPE (@0)) + && expand_vec_cmp_expr_p (TREE_TYPE (@0), type, rcmp))) (rcmp @0 @1)))) /* (type)([0,1]@a != 0) -> (type)a @@ -5981,6 +6016,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && !expand_vec_cond_expr_p (TREE_TYPE (@1), TREE_TYPE (@0))))) (vec_cond @0 (op! @1 @3) (op! @2 @4)))) +/* (@0 ? @2 : @3) lop (@1 ? @2 : @3) --> (@0 lop @1) ? @2 : @3. */ +(for lop (bit_and bit_ior bit_xor) + (simplify + (lop + (vec_cond @0 integer_minus_onep@2 integer_zerop@3) + (vec_cond @1 @2 @3)) + (if (target_supports_op_p (TREE_TYPE (@0), lop, optab_vector)) + (vec_cond (lop @0 @1) @2 @3)))) + /* (c ? a : b) op d --> c ? (a op d) : (b op d) */ (simplify (op (vec_cond:s @0 @1 @2) @3) @@ -11635,4 +11679,4 @@ and, && VECTOR_TYPE_P (type) && direct_internal_fn_supported_p (IFN_AVG_CEIL, type, OPTIMIZE_FOR_BOTH)) (IFN_AVG_CEIL @0 @2))) -#endif +#endif
\ No newline at end of file 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/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.dg/builtin-dynamic-object-size-pr120780.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-pr120780.c index 0d6593e..12e6c29 100644 --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-pr120780.c +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-pr120780.c @@ -207,7 +207,7 @@ test5 (size_t sz) } int -main (size_t sz) +main (void) { test1 (sizeof (struct container)); test1 (sizeof (struct container) - sizeof (int)); diff --git a/gcc/testsuite/gcc.dg/vect/pr101145.c b/gcc/testsuite/gcc.dg/vect/pr101145.c index cd11c03..c055ae6 100644 --- a/gcc/testsuite/gcc.dg/vect/pr101145.c +++ b/gcc/testsuite/gcc.dg/vect/pr101145.c @@ -2,7 +2,7 @@ /* { dg-additional-options "-O3" } */ #include <limits.h> -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { while (n < ++l) @@ -10,7 +10,7 @@ foo (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo_1 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned) { while (UINT_MAX - 64 < ++l) @@ -18,7 +18,7 @@ foo_1 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo_2 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { l = UINT_MAX - 32; @@ -27,7 +27,7 @@ foo_2 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo_3 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { while (n <= ++l) @@ -35,7 +35,7 @@ foo_3 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo_4 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { // infininate while (0 <= ++l) @@ -43,7 +43,7 @@ foo_4 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo_5 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { //no loop @@ -53,7 +53,7 @@ foo_5 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) bar (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { while (--l < n) @@ -61,7 +61,7 @@ bar (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) bar_1 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned) { while (--l < 64) @@ -69,7 +69,7 @@ bar_1 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) bar_2 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { l = 32; diff --git a/gcc/testsuite/gcc.dg/vect/pr120922.c b/gcc/testsuite/gcc.dg/vect/pr120922.c new file mode 100644 index 0000000..1a7247a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr120922.c @@ -0,0 +1,18 @@ +/* { dg-require-effective-target vect_int } */ +/* { dg-additional-options "-fsigned-char -fno-strict-aliasing -fwrapv" } */ +/* { dg-additional-options "-march=rv64gcv_zvl1024b -mrvv-vector-bits=zvl -mrvv-max-lmul=m8 -O3" { target { riscv_v } } } */ + +char g; +unsigned char h; +int i[9][6]; +int main() { + int k[5]; + if (g) + goto l; + for (; h <= 5; h++) + i[0][h] = *k; +l: + return 0; +} + +/* { dg-final { scan-tree-dump "loop vectorized" "vect" { target riscv_v } } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr118348_1.c b/gcc/testsuite/gcc.target/aarch64/pr118348_1.c index 75f6dad..2715dcb 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr118348_1.c +++ b/gcc/testsuite/gcc.target/aarch64/pr118348_1.c @@ -1,4 +1,4 @@ -/* { dg-do run { target aarch64_sve128_hw } } */ +/* { dg-do run { target { aarch64_sve128_hw && fstack_protector } } } */ /* { dg-options "-O2 -fopenmp-simd -fno-trapping-math -msve-vector-bits=128 --param aarch64-autovec-preference=sve-only -fstack-protector-strong" } */ #pragma GCC target "+sve" diff --git a/gcc/testsuite/gcc.target/aarch64/pr118348_2.c b/gcc/testsuite/gcc.target/aarch64/pr118348_2.c index 2e20004..4ce8d20 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr118348_2.c +++ b/gcc/testsuite/gcc.target/aarch64/pr118348_2.c @@ -1,4 +1,4 @@ -/* { dg-do run { target aarch64_sve256_hw } } */ +/* { dg-do run { target { aarch64_sve256_hw && fstack_protector } } } */ /* { dg-options "-O2 -fopenmp-simd -fno-trapping-math -msve-vector-bits=256 --param aarch64-autovec-preference=sve-only -fstack-protector-strong" } */ #include "pr118348_1.c" diff --git a/gcc/testsuite/gcc.target/aarch64/vector-compare-5.c b/gcc/testsuite/gcc.target/aarch64/vector-compare-5.c new file mode 100644 index 0000000..a1a601d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/vector-compare-5.c @@ -0,0 +1,67 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-fdump-tree-original-all" } */ + +typedef int v4i __attribute__((vector_size(4*sizeof(int)))); + +/* Ensure we can simplify `VEC_COND_EXPR(a OP1 b) OP2 VEC_COND_EXPR(a OP3 b)` + * into `VEC_COND_EXPR(a OP4 b)` + */ + +void use (v4i const *z); + +void +g (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x > *y | *x == *y; // expect >= + *t = *x > *y | *x <= *y; // expect true +} + +void +h (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x <= *y & *x >= *y; // expect x == y + *t = *x <= *y & *x != *y; // expect x<y +} + +void +i (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x == *y | *x != *y; // expect true + *t = *x == *y & *x != *y; // expect false +} + +void +k (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x < *y | *x == *y; // x <= y + *t = *x < *y & *x > *y; // expect false +} + +void +m (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x <= *y ^ *x >= *y; /* expect x != y */ + *t = *x <= *y ^ *x != *y; /* expect x <= y */ +} + +void +n (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x == *y ^ *x != *y; /* expect true */ + *t = *x == *y ^ *x == *y; /* expect false */ +} + + +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*>=\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*==\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*<\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*<=\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*!=\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*>=\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*;" "original" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120642.c b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120642.c new file mode 100644 index 0000000..1a72580 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120642.c @@ -0,0 +1,4 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mcpu=xt-c920 -mrvv-vector-bits=zvl" } */ +int __attribute__((__vector_size__(4 * sizeof(int)))) v; +void foo() { v /= 3; } 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/vector/pattern-avg-1.c b/gcc/testsuite/gcc.target/s390/vector/pattern-avg-1.c index 30c6ed4..285ebc9 100644 --- a/gcc/testsuite/gcc.target/s390/vector/pattern-avg-1.c +++ b/gcc/testsuite/gcc.target/s390/vector/pattern-avg-1.c @@ -22,4 +22,5 @@ TEST(char,short,16) TEST(short,int,8) TEST(int,long,4) -/* { dg-final { scan-tree-dump-times "\.AVG_CEIL" 6 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\.AVG_CEIL" 6 "optimized" { target lp64 } } } */ +/* { dg-final { scan-tree-dump-times "\.AVG_CEIL" 4 "optimized" { target { ! lp64 } } } } */ diff --git a/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-1.c b/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-1.c index f71ef06..f0b37d6 100644 --- a/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-1.c +++ b/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-1.c @@ -23,6 +23,5 @@ TEST(char,short,16,8) TEST(short,int,8,16) -TEST(int,long,4,32) -/* { dg-final { scan-tree-dump-times "\.MULH" 6 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\.MULH" 4 "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-2.c b/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-2.c index 6ac6855..2ff66b7 100644 --- a/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-2.c +++ b/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-2.c @@ -21,6 +21,7 @@ (((unsigned T2)l[i] * (unsigned T2)r[i]) >> S); \ } +TEST(int,long,4,32) TEST(long,__int128,2,64) -/* { dg-final { scan-tree-dump-times "\.MULH" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\.MULH" 4 "optimized" } } */ 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/gcc/tree-inline.cc b/gcc/tree-inline.cc index 7e0ac69..e8fe035 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -2888,11 +2888,9 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, profile_count count) profile_count::adjust_for_ipa_scaling (&num, &den); ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = - ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count.apply_scale (count, - ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count); + ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count.apply_scale (num, den); EXIT_BLOCK_PTR_FOR_FN (cfun)->count = - EXIT_BLOCK_PTR_FOR_FN (src_cfun)->count.apply_scale (count, - ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count); + EXIT_BLOCK_PTR_FOR_FN (src_cfun)->count.apply_scale (num, den); if (src_cfun->eh) init_eh_for_function (); diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc index 4696943..2d01a4b 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -2859,7 +2859,19 @@ vect_gen_vector_loop_niters (loop_vec_info loop_vinfo, tree niters, we have to represent the vector niter TYPE_MAX_VALUE + 1 / vf. */ if (stmts != NULL && const_vf > 0) { - if (niters_no_overflow) + if (niters_no_overflow + && LOOP_VINFO_USING_PARTIAL_VECTORS_P (loop_vinfo)) + { + int_range<1> vr (type, + wi::one (TYPE_PRECISION (type)), + wi::div_ceil (wi::max_value + (TYPE_PRECISION (type), + TYPE_SIGN (type)), + const_vf, + TYPE_SIGN (type))); + set_range_info (niters_vector, vr); + } + else if (niters_no_overflow) { int_range<1> vr (type, wi::one (TYPE_PRECISION (type)), diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index d5044d5..42e0015 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -7822,7 +7822,7 @@ vectorizable_reduction (loop_vec_info loop_vinfo, inside the loop body. The last operand is the reduction variable, which is defined by the loop-header-phi. */ - tree vectype_out = STMT_VINFO_VECTYPE (stmt_info); + tree vectype_out = SLP_TREE_VECTYPE (slp_for_stmt_info); STMT_VINFO_REDUC_VECTYPE (reduc_info) = vectype_out; STMT_VINFO_REDUC_VECTYPE_IN (reduc_info) = vectype_in; diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 5767a35..da20127 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -13368,6 +13368,14 @@ vect_analyze_stmt (vec_info *vinfo, gcc_unreachable (); } + if (PURE_SLP_STMT (stmt_info) && !node) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, + "handled only by SLP analysis\n"); + return opt_result::success (); + } + tree saved_vectype = STMT_VINFO_VECTYPE (stmt_info); if (node) STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (node); @@ -13381,14 +13389,6 @@ vect_analyze_stmt (vec_info *vinfo, *need_to_vectorize = true; } - if (PURE_SLP_STMT (stmt_info) && !node) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "handled only by SLP analysis\n"); - return opt_result::success (); - } - /* When we arrive here with a non-SLP statement and we are supposed to use SLP for everything fail vectorization. */ if (!node) 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/bits/max_size_type.h b/libstdc++-v3/include/bits/max_size_type.h index 73a6d14..30c5b12 100644 --- a/libstdc++-v3/include/bits/max_size_type.h +++ b/libstdc++-v3/include/bits/max_size_type.h @@ -38,6 +38,7 @@ #include <ext/numeric_traits.h> #include <bit> // __bit_width #include <numbers> +#include <limits> // __glibcxx_integral_traps // This header implements unsigned and signed integer-class types (as per // [iterator.concept.winc]) that are one bit wider than the widest supported @@ -775,10 +776,27 @@ namespace ranges static constexpr bool is_signed = false; static constexpr bool is_integer = true; static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr int radix = 2; static constexpr int digits = __gnu_cxx::__int_traits<_Sp::__rep>::__digits + 1; static constexpr int digits10 = static_cast<int>(digits * numbers::ln2 / numbers::ln10); + static constexpr int max_digits10 = 0; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool is_iec559 = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr bool has_denorm_loss = false; + static constexpr bool tinyness_before = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr float_round_style round_style = round_toward_zero; static constexpr _Sp min() noexcept @@ -791,6 +809,30 @@ namespace ranges static constexpr _Sp lowest() noexcept { return min(); } + + static constexpr _Sp + denorm_min() noexcept + { return 0; } + + static constexpr _Sp + epsilon() noexcept + { return 0; } + + static constexpr _Sp + round_error() noexcept + { return 0; } + + static constexpr _Sp + infinity() noexcept + { return 0; } + + static constexpr _Sp + quiet_NaN() noexcept + { return 0; } + + static constexpr _Sp + signaling_NaN() noexcept + { return 0; } }; template<> @@ -802,9 +844,26 @@ namespace ranges static constexpr bool is_signed = true; static constexpr bool is_integer = true; static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr int radix = 2; static constexpr int digits = numeric_limits<_Sp>::digits - 1; static constexpr int digits10 = static_cast<int>(digits * numbers::ln2 / numbers::ln10); + static constexpr int max_digits10 = 0; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool is_iec559 = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr bool has_denorm_loss = false; + static constexpr bool tinyness_before = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr float_round_style round_style = round_toward_zero; static constexpr _Dp min() noexcept @@ -817,6 +876,30 @@ namespace ranges static constexpr _Dp lowest() noexcept { return min(); } + + static constexpr _Dp + denorm_min() noexcept + { return 0; } + + static constexpr _Dp + epsilon() noexcept + { return 0; } + + static constexpr _Dp + round_error() noexcept + { return 0; } + + static constexpr _Dp + infinity() noexcept + { return 0; } + + static constexpr _Dp + quiet_NaN() noexcept + { return 0; } + + static constexpr _Dp + signaling_NaN() noexcept + { return 0; } }; template<> diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h index a196a0f..f2b4601 100644 --- a/libstdc++-v3/include/bits/shared_ptr.h +++ b/libstdc++-v3/include/bits/shared_ptr.h @@ -909,6 +909,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>> { }; +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + + /** + * @brief Provides ownership-based hashing. + * @headerfile memory + * @since C++26 + */ + struct owner_hash + { + template<typename _Tp> + size_t + operator()(const shared_ptr<_Tp>& __s) const noexcept + { return __s.owner_hash(); } + + template<typename _Tp> + size_t + operator()(const weak_ptr<_Tp>& __s) const noexcept + { return __s.owner_hash(); } + + using is_transparent = void; + }; + + /** + * @brief Provides ownership-based mixed equality comparisons of + * shared and weak pointers. + * @headerfile memory + * @since C++26 + */ + struct owner_equal + { + template<typename _Tp1, typename _Tp2> + bool + operator()(const shared_ptr<_Tp1>& __lhs, + const shared_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + template<typename _Tp1, typename _Tp2> + bool + operator()(const shared_ptr<_Tp1>& __lhs, + const weak_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + template<typename _Tp1, typename _Tp2> + bool + operator()(const weak_ptr<_Tp1>& __lhs, + const shared_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + template<typename _Tp1, typename _Tp2> + bool + operator()(const weak_ptr<_Tp1>& __lhs, + const weak_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + using is_transparent = void; + }; +#endif + /** * @brief Base class allowing use of the member function `shared_from_this`. * @headerfile memory diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index b4be1b4..fb868e7 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -1122,6 +1122,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_less(const __weak_count<_Lp>& __rhs) const noexcept { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t + _M_owner_hash() const noexcept + { return std::hash<_Sp_counted_base<_Lp>*>()(this->_M_pi); } +#endif + // Friend function injected into enclosing namespace and found by ADL friend inline bool operator==(const __shared_count& __a, const __shared_count& __b) noexcept @@ -1225,6 +1231,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_less(const __shared_count<_Lp>& __rhs) const noexcept { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t + _M_owner_hash() const noexcept + { return std::hash<_Sp_counted_base<_Lp>*>()(this->_M_pi); } +#endif + // Friend function injected into enclosing namespace and found by ADL friend inline bool operator==(const __weak_count& __a, const __weak_count& __b) noexcept @@ -1715,6 +1727,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_refcount._M_less(__rhs._M_refcount); } /// @} +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t owner_hash() const noexcept { return _M_refcount._M_owner_hash(); } + + template<typename _Tp1> + bool + owner_equal(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } + + template<typename _Tp1> + bool + owner_equal(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } +#endif + protected: // This constructor is non-standard, it is used by allocate_shared. template<typename _Alloc, typename... _Args> @@ -2098,6 +2124,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept { return _M_refcount._M_less(__rhs._M_refcount); } +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t owner_hash() const noexcept { return _M_refcount._M_owner_hash(); } + + template<typename _Tp1> + bool + owner_equal(const __shared_ptr<_Tp1, _Lp> & __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } + + template<typename _Tp1> + bool + owner_equal(const __weak_ptr<_Tp1, _Lp> & __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } +#endif + void reset() noexcept { __weak_ptr().swap(*this); } diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index f1015ab..31385b5 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -2007,6 +2007,15 @@ ftms = { }; ftms = { + name = smart_ptr_owner_equality; + values = { + v = 202306; + cxxmin = 26; + hosted = yes; + }; +}; + +ftms = { name = sstream_from_string_view; values = { v = 202306; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 80f6586..aa53f29 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -2249,6 +2249,16 @@ #endif /* !defined(__cpp_lib_polymorphic) && defined(__glibcxx_want_polymorphic) */ #undef __glibcxx_want_polymorphic +#if !defined(__cpp_lib_smart_ptr_owner_equality) +# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED +# define __glibcxx_smart_ptr_owner_equality 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_smart_ptr_owner_equality) +# define __cpp_lib_smart_ptr_owner_equality 202306L +# endif +# endif +#endif /* !defined(__cpp_lib_smart_ptr_owner_equality) && defined(__glibcxx_want_smart_ptr_owner_equality) */ +#undef __glibcxx_want_smart_ptr_owner_equality + #if !defined(__cpp_lib_sstream_from_string_view) # if (__cplusplus > 202302L) && _GLIBCXX_HOSTED # define __glibcxx_sstream_from_string_view 202306L 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/memory b/libstdc++-v3/include/std/memory index 1da03b3..763a57e 100644 --- a/libstdc++-v3/include/std/memory +++ b/libstdc++-v3/include/std/memory @@ -121,6 +121,7 @@ #define __glibcxx_want_smart_ptr_for_overwrite #define __glibcxx_want_to_address #define __glibcxx_want_transparent_operators +#define __glibcxx_want_smart_ptr_owner_equality #include <bits/version.h> #if __cplusplus >= 201103L && __cplusplus <= 202002L && _GLIBCXX_HOSTED diff --git a/libstdc++-v3/src/c++17/memory_resource.cc b/libstdc++-v3/src/c++17/memory_resource.cc index fac4c78..c61569f 100644 --- a/libstdc++-v3/src/c++17/memory_resource.cc +++ b/libstdc++-v3/src/c++17/memory_resource.cc @@ -182,8 +182,8 @@ namespace pmr // versions will not use this symbol. monotonic_buffer_resource::~monotonic_buffer_resource() { release(); } - namespace { - +namespace +{ // aligned_size<N> stores the size and alignment of a memory allocation. // The size must be a multiple of N, leaving the low log2(N) bits free // to store the base-2 logarithm of the alignment. @@ -221,7 +221,7 @@ namespace pmr return (n + alignment - 1) & ~(alignment - 1); } - } // namespace +} // namespace // Memory allocated by the upstream resource is managed in a linked list // of _Chunk objects. A _Chunk object recording the size and alignment of @@ -307,8 +307,8 @@ namespace pmr // Helper types for synchronized_pool_resource & unsynchronized_pool_resource - namespace { - +namespace +{ // Simple bitset with runtime size. // Tracks which blocks in a pool chunk are used/unused. struct bitset @@ -636,7 +636,7 @@ namespace pmr static_assert(sizeof(big_block) == (2 * sizeof(void*))); - } // namespace +} // namespace // A pool that serves blocks of a particular size. // Each pool manages a number of chunks. @@ -868,7 +868,16 @@ namespace pmr using big_block::big_block; }; - namespace { +namespace +{ + // N.B. it is important that we don't skip any power of two sizes if there + // is a non-power of two size between them, e.g. must not have pool sizes + // of 24 and 40 without having a pool size of 32. Otherwise an allocation + // of 32 bytes with alignment 16 would choose the 40-byte pool which is not + // correctly aligned for 16-byte alignment. It would be OK (but suboptimal) + // to have no pool of size 32 if we have pool sizes of 16 and 64 and no + // non-power of two sizes between those, because the example of (32, 16) + // would choose the 64-byte pool, which would be correctly aligned. constexpr size_t pool_sizes[] = { 8, 16, 24, @@ -983,7 +992,7 @@ namespace pmr using exclusive_lock = lock_guard<shared_mutex>; #endif - } // namespace +} // namespace __pool_resource:: __pool_resource(const pool_options& opts, memory_resource* upstream) @@ -1075,12 +1084,33 @@ namespace pmr return p; } + // Determine the appropriate allocation size, rounding up to a multiple + // of the alignment if needed. + 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(); + } + + #ifdef _GLIBCXX_HAS_GTHREADS // synchronized_pool_resource members. /* Notes on implementation and thread safety: * - * Each synchronized_pool_resource manages an linked list of N+1 _TPools + * Each synchronized_pool_resource manages a linked list of N+1 _TPools * objects, where N is the number of threads using the pool resource. * Each _TPools object has its own set of pools, with their own chunks. * The first element of the list, _M_tpools[0], can be used by any thread. @@ -1247,7 +1277,7 @@ namespace pmr 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 +1324,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 +1483,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 +1500,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/owner_equal/cmp.cc b/libstdc++-v3/testsuite/20_util/owner_equal/cmp.cc new file mode 100644 index 0000000..311ddf2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/owner_equal/cmp.cc @@ -0,0 +1,105 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.6 Struct owner_equal [util.smartptr.owner.equal] + +#include <memory> +#include <algorithm> +#include <testsuite_hooks.h> + +struct A { }; + +struct B { A a[2]; }; + +int +test01() +{ + // test empty shared_ptr owners compare equivalent + std::owner_equal eq; + std::shared_ptr<A> p1; + std::shared_ptr<A> p2; + VERIFY( eq(p1, p2) && eq(p2, p1) ); + std::weak_ptr<A> p3; + VERIFY( eq(p1, p3) && eq(p3, p1) ); + VERIFY( eq(p1, p3) && eq(p3, p1) ); + return 0; +} + + +// Construction from pointer +int +test02() +{ + std::owner_equal eq; + + std::shared_ptr<A> empty; + + std::shared_ptr<A> a1(new A); + VERIFY( !eq(empty, a1) && !eq(a1, empty) ); + + std::shared_ptr<A> a2(new A); + VERIFY( !eq(a1, a2) && !eq(a2, a1) ); + + std::weak_ptr<A> w1(a1); + VERIFY( eq(a1, w1) && eq(w1, a1) ); + + std::weak_ptr<A> w2(a2); + VERIFY( !eq(w1, w2) && !eq(w2, w1) ); + + a1.reset(); + VERIFY( eq(empty, a1) && eq(a1, empty) ); + VERIFY( !eq(a1, w1) && !eq(w1, a1) ); + + a2.reset(); + VERIFY( eq(a2, a1) && eq(a1, a2) ); + + return 0; +} + +// aliasing +int +test03() +{ + std::owner_equal eq; + + std::shared_ptr<B> b(new B); + std::shared_ptr<A> a0(b, &b->a[0]); + std::shared_ptr<A> a1(b, &b->a[1]); + // values are different but owners are equivalent: + VERIFY( a0 < a1 && eq(a0, a1) && eq(b, a0) && eq(b, a1) ); + + std::weak_ptr<A> w0(a0); + std::weak_ptr<A> w1(a1); + VERIFY( eq(w0, w1) && eq(w1, w0) ); + VERIFY( eq(a0, w1) && eq(w1, a0) ); + VERIFY( eq(w0, a1) && eq(a1, w0) ); + + return 0; +} + +// as binary predicate +int +test04() +{ + std::owner_equal eq; + + std::shared_ptr<B> b(new B); + std::shared_ptr<A> a0(b, &b->a[0]); + std::shared_ptr<A> a1(b, &b->a[1]); + std::shared_ptr<A> c(new A); + std::weak_ptr<A> a[3]{a0, a1, c}; + std::weak_ptr<A>* p = std::unique(a, a+3, eq); + VERIFY( p == &a[2] ); + + return 0; +} + +int +main() +{ + test01(); + test02(); + test03(); + test04(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/owner_equal/noexcept.cc b/libstdc++-v3/testsuite/20_util/owner_equal/noexcept.cc new file mode 100644 index 0000000..fb479f6 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/owner_equal/noexcept.cc @@ -0,0 +1,30 @@ +// { dg-do compile { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.6 Struct owner_equal [util.smartptr.owner.equal] + +#include <memory> + +#ifndef __cpp_lib_smart_ptr_owner_equality +# error "Feature-test macro for smart ptr owner equality missing in <memory>" +#elif __cpp_lib_smart_ptr_owner_equality != 202306L +# error "Feature-test macro for smart ptr owner equality has wrong value in <memory>" +#endif + +const std::owner_equal eq; +const std::shared_ptr<int> si; +const std::weak_ptr<int> wi; +static_assert( noexcept(!eq(si, si)) ); +static_assert( noexcept(!eq(si, wi)) ); +static_assert( noexcept(!eq(wi, si)) ); +static_assert( noexcept(!eq(wi, wi)) ); +static_assert( noexcept(!eq(si, wi)) ); +static_assert( noexcept(!eq(wi, si)) ); +const std::shared_ptr<long> sl; +const std::weak_ptr<char> wc; +static_assert( noexcept(!eq(si, si)) ); +static_assert( noexcept(!eq(si, sl)) ); +static_assert( noexcept(!eq(sl, si)) ); +static_assert( noexcept(!eq(si, wc)) ); +static_assert( noexcept(!eq(wc, si)) ); +static_assert( noexcept(!eq(wc, wi)) ); diff --git a/libstdc++-v3/testsuite/20_util/owner_equal/version.cc b/libstdc++-v3/testsuite/20_util/owner_equal/version.cc new file mode 100644 index 0000000..db29154 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/owner_equal/version.cc @@ -0,0 +1,13 @@ +// { dg-do compile { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 17.3.2 Header <version> synopsis [version.syn] + +#include <version> + +#ifndef __cpp_lib_smart_ptr_owner_equality +# error "Feature-test macro for smart ptr owner equality missing in <version>" +#elif __cpp_lib_smart_ptr_owner_equality != 202306L +# error "Feature-test macro for smart ptr owner equality has wrong value in <version>" +#endif + diff --git a/libstdc++-v3/testsuite/20_util/owner_hash/cmp.cc b/libstdc++-v3/testsuite/20_util/owner_hash/cmp.cc new file mode 100644 index 0000000..c03a926 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/owner_hash/cmp.cc @@ -0,0 +1,87 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.5 Struct owner_hash [util.smartptr.owner.hash] + +#include <memory> +#include <algorithm> +#include <testsuite_hooks.h> + +struct A { }; + +struct B { A a[2]; }; + +int +test01() +{ + // test empty shared_ptr hashes compare equivalent + std::owner_hash oh; + std::shared_ptr<A> p1; + std::shared_ptr<A> p2; + VERIFY( oh(p1) == oh(p2) ); + std::weak_ptr<A> p3; + VERIFY( oh(p1) == oh(p3) ); + VERIFY( oh(p1) == oh(p3) ); + return 0; +} + + +// Construction from pointer +int +test02() +{ + std::owner_hash oh; + + std::shared_ptr<A> empty; + + std::shared_ptr<A> a1(new A); + VERIFY( oh(empty) != oh(a1) ); + + std::shared_ptr<A> a2(new A); + VERIFY( oh(a1) != oh(a2) ); + + std::weak_ptr<A> w1(a1); + VERIFY( oh(a1) == oh(w1) ); + + std::weak_ptr<A> w2(a2); + VERIFY( oh(w1) != oh(w2) ); + + a1.reset(); + VERIFY( oh(empty) == oh(a1) ); + VERIFY( oh(a1) != oh(w1) ); + + a2.reset(); + VERIFY( oh(a2) == oh(a1) ); + + return 0; +} + +// aliasing +int +test03() +{ + std::owner_hash oh; + + std::shared_ptr<B> b(new B); + std::shared_ptr<A> a0(b, &b->a[0]); + std::shared_ptr<A> a1(b, &b->a[1]); + // values are different but owners are ohuivalent: + VERIFY( a0 < a1 && oh(a0) == oh(a1) && oh(b) == oh(a0) && oh(b) == oh(a1) ); + + std::weak_ptr<A> w0(a0); + std::weak_ptr<A> w1(a1); + VERIFY( oh(w0) == oh(w1) ); + VERIFY( oh(a0) == oh(w1) ); + VERIFY( oh(w0) == oh(a1) ); + + return 0; +} + +int +main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/owner_hash/noexcept.cc b/libstdc++-v3/testsuite/20_util/owner_hash/noexcept.cc new file mode 100644 index 0000000..12b2f2f --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/owner_hash/noexcept.cc @@ -0,0 +1,16 @@ +// { dg-do compile { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.5 Struct owner_hash [util.smartptr.owner.hash] + +#include <memory> + +const std::owner_hash oh; +const std::shared_ptr<int> si; +const std::weak_ptr<int> wi; +static_assert( noexcept(!oh(si)) ); +static_assert( noexcept(!oh(wi)) ); +const std::shared_ptr<long> sl; +const std::weak_ptr<char> wc; +static_assert( noexcept(!oh(sl)) ); +static_assert( noexcept(!oh(wc)) ); diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_equal.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_equal.cc new file mode 100644 index 0000000..7ec8691 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_equal.cc @@ -0,0 +1,74 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.2.6 shared_ptr observers [util.smartptr.shared.obs] + +#include <memory> +#include <testsuite_hooks.h> + +struct A +{ + int i; + virtual ~A() { } +}; + +struct B : A +{ +}; + +void +test01() +{ + // test empty shared_ptr owners compare equivalent + std::shared_ptr<A> p1; + std::shared_ptr<B> p2; + VERIFY( p1.owner_equal(p2) && p2.owner_equal(p1) ); +} + + +// Construction from pointer +void +test02() +{ + std::shared_ptr<A> a0; + + std::shared_ptr<A> a1(new A); + VERIFY( !a1.owner_equal(a0) && !a0.owner_equal(a1) ); + + std::shared_ptr<B> b1(new B); + VERIFY( !a1.owner_equal(b1) && !b1.owner_equal(a1) ); + + std::shared_ptr<A> a2(a1); + VERIFY( a1.owner_equal(a2) && a2.owner_equal(a1) ); + a2 = b1; + VERIFY( b1.owner_equal(a2) && a2.owner_equal(b1) ); + + std::weak_ptr<A> w1(a1); + VERIFY( a1.owner_equal(w1) && w1.owner_equal(a1) ); + std::weak_ptr<A> w2(a2); + VERIFY( b1.owner_equal(w2) && w2.owner_equal(b1) ); + + static_assert( noexcept(a1.owner_equal(a0)) ); + static_assert( noexcept(a1.owner_equal(b1)) ); + static_assert( noexcept(b1.owner_equal(a1)) ); + static_assert( noexcept(a1.owner_equal(w1)) ); + static_assert( noexcept(b1.owner_equal(w1)) ); +} + +// Aliasing +void +test03() +{ + std::shared_ptr<A> p1(new A()); + std::shared_ptr<int> p2(p1, &p1->i); + VERIFY( p1.owner_equal(p2) && p2.owner_equal(p1) ); +} + +int +main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_hash.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_hash.cc new file mode 100644 index 0000000..8e6c02c --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_hash.cc @@ -0,0 +1,71 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.2.6 shared_ptr observers [util.smartptr.shared.obs] + +#include <memory> +#include <testsuite_hooks.h> + +struct A +{ + int i; + virtual ~A() { } +}; + +struct B : A +{ +}; + +void +test01() +{ + // test empty shared_ptr hashes compare equivalent + std::shared_ptr<A> p1; + std::shared_ptr<B> p2; + VERIFY( p1.owner_hash() == p2.owner_hash() ); +} + + +// Construction from pointer +void +test02() +{ + std::shared_ptr<A> a0; + + std::shared_ptr<A> a1(new A); + VERIFY( a1.owner_hash() != a0.owner_hash() ); + + std::shared_ptr<B> b1(new B); + VERIFY( a1.owner_hash() != b1.owner_hash() ); + + std::shared_ptr<A> a2(a1); + VERIFY( a1.owner_hash() == a2.owner_hash() ); + a2 = b1; + VERIFY( b1.owner_hash() == a2.owner_hash() ); + + std::weak_ptr<A> w1(a1); + VERIFY( a1.owner_hash() == w1.owner_hash() ); + std::weak_ptr<A> w2(a2); + VERIFY( b1.owner_hash() == w2.owner_hash() ); + + static_assert( noexcept(a1.owner_hash()) ); + static_assert( noexcept(b1.owner_hash()) ); +} + +// Aliasing +void +test03() +{ + std::shared_ptr<A> p1(new A()); + std::shared_ptr<int> p2(p1, &p1->i); + VERIFY( p1.owner_hash() == p2.owner_hash() ); +} + +int +main() +{ + test01(); + test02(); + test03(); + return 0; +} 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..facbf00 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc @@ -0,0 +1,6 @@ +// { dg-do run { target c++17 } } +// { dg-require-gthreads "" } +// 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/20_util/weak_ptr/observers/owner_equal.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_equal.cc new file mode 100644 index 0000000..0217a6e --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_equal.cc @@ -0,0 +1,52 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.3.6 weak_ptr observers [util.smartptr.weak.obs] + +#include <memory> +#include <testsuite_hooks.h> + +struct A { }; +struct B { }; + +void +test01() +{ + // test empty weak_ptr owners compare equivalent + std::weak_ptr<A> p1; + std::weak_ptr<B> p2; + VERIFY( p1.owner_equal(p2) && p2.owner_equal(p1) ); + + std::shared_ptr<B> p3; + VERIFY( p1.owner_equal(p3) && p3.owner_equal(p1) ); + + static_assert( noexcept(p1.owner_equal(p1)) ); + static_assert( noexcept(p1.owner_equal(p2)) ); + static_assert( noexcept(p1.owner_equal(p3)) ); + static_assert( noexcept(p2.owner_equal(p1)) ); +} + + +void +test02() +{ + std::shared_ptr<A> a0; + std::weak_ptr<A> w0(a0); + + std::shared_ptr<A> a1(new A); + std::weak_ptr<A> w1(a1); + VERIFY( a1.owner_equal(w1) && w1.owner_equal(a1) ); + VERIFY( !w1.owner_equal(w0) && !w0.owner_equal(w1) ); + VERIFY( !w1.owner_equal(a0) && !a0.owner_equal(w1) ); + + std::shared_ptr<B> b1(new B); + VERIFY( !w1.owner_equal(b1) && !b1.owner_equal(w1) ); +} + +int +main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_hash.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_hash.cc new file mode 100644 index 0000000..148a93b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_hash.cc @@ -0,0 +1,50 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.3.6 weak_ptr observers [util.smartptr.weak.obs] + +#include <memory> +#include <testsuite_hooks.h> + +struct A { }; +struct B { }; + +void +test01() +{ + // test empty weak_ptr hashes compare equivalent + std::weak_ptr<A> p1; + std::weak_ptr<B> p2; + VERIFY( p1.owner_hash() == p2.owner_hash() ); + + std::shared_ptr<B> p3; + VERIFY( p1.owner_hash() == p3.owner_hash() ); + + static_assert( noexcept(p1.owner_hash()) ); + static_assert( noexcept(p2.owner_hash()) ); +} + + +void +test02() +{ + std::shared_ptr<A> a0; + std::weak_ptr<A> w0(a0); + + std::shared_ptr<A> a1(new A); + std::weak_ptr<A> w1(a1); + VERIFY( a1.owner_hash() == w1.owner_hash() ); + VERIFY( w1.owner_hash() != w0.owner_hash() ); + VERIFY( w1.owner_hash() != a0.owner_hash() ); + + std::shared_ptr<B> b1(new B); + VERIFY( w1.owner_hash() != b1.owner_hash() ); +} + +int +main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc b/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc index 4739d9e..fbd783b 100644 --- a/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc +++ b/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc @@ -352,6 +352,9 @@ static_assert(numeric_limits<max_size_t>::is_specialized); static_assert(!numeric_limits<max_size_t>::is_signed); static_assert(numeric_limits<max_size_t>::is_integer); static_assert(numeric_limits<max_size_t>::is_exact); +static_assert(numeric_limits<max_size_t>::is_bounded); +static_assert(numeric_limits<max_size_t>::is_modulo); +static_assert(numeric_limits<max_size_t>::radix == 2); // We can't unconditionally use numeric_limits here because __int128 is an // integral type only in GNU mode. #if __SIZEOF_INT128__ @@ -379,6 +382,9 @@ static_assert(numeric_limits<max_diff_t>::is_specialized); static_assert(numeric_limits<max_diff_t>::is_signed); static_assert(numeric_limits<max_diff_t>::is_integer); static_assert(numeric_limits<max_diff_t>::is_exact); +static_assert(numeric_limits<max_diff_t>::is_bounded); +static_assert(!numeric_limits<max_diff_t>::is_modulo); +static_assert(numeric_limits<max_diff_t>::radix == 2); static_assert(numeric_limits<max_diff_t>::digits == numeric_limits<max_size_t>::digits - 1); static_assert(numeric_limits<max_diff_t>::digits10 @@ -400,6 +406,31 @@ static_assert(max_diff_t(max_size_t(1) << (numeric_limits<max_size_t>::digits-1)) == numeric_limits<max_diff_t>::min()); +template <typename integer_class> +constexpr bool verify_numeric_limits_values_not_meaningful_for = true + && (numeric_limits<integer_class>::max_digits10 == 0) + && (numeric_limits<integer_class>::min_exponent == 0) + && (numeric_limits<integer_class>::min_exponent10 == 0) + && (numeric_limits<integer_class>::max_exponent == 0) + && (numeric_limits<integer_class>::max_exponent10 == 0) + && !numeric_limits<integer_class>::is_iec559 + && !numeric_limits<integer_class>::has_infinity + && !numeric_limits<integer_class>::has_quiet_NaN + && !numeric_limits<integer_class>::has_signaling_NaN + && !numeric_limits<integer_class>::has_denorm_loss + && !numeric_limits<integer_class>::tinyness_before + && (numeric_limits<integer_class>::has_denorm == std::denorm_absent) + && (numeric_limits<integer_class>::round_style == std::round_toward_zero) + && (numeric_limits<integer_class>::denorm_min() == 0) + && (numeric_limits<integer_class>::epsilon() == 0) + && (numeric_limits<integer_class>::round_error() == 0) + && (numeric_limits<integer_class>::infinity() == 0) + && (numeric_limits<integer_class>::quiet_NaN() == 0) + && (numeric_limits<integer_class>::signaling_NaN() == 0); + +static_assert(verify_numeric_limits_values_not_meaningful_for<max_size_t>); +static_assert(verify_numeric_limits_values_not_meaningful_for<max_diff_t>); + // Verify that the types are structural types and can therefore be used // as NTTP types. template<max_size_t V> struct Su { static_assert(V*V == V+132); }; |