aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/prepare-commit-msg2
-rw-r--r--gcc/config/i386/i386.cc59
-rw-r--r--gcc/config/i386/x86-tune.def5
-rw-r--r--gcc/config/riscv/riscv-v.cc2
-rw-r--r--gcc/config/riscv/riscv-vector-builtins.cc6
-rw-r--r--gcc/config/riscv/sync.md2
-rw-r--r--gcc/config/s390/s390.md47
-rw-r--r--gcc/config/xtensa/xtensa.cc17
-rw-r--r--gcc/cp/cp-tree.h12
-rw-r--r--gcc/cp/decl.cc29
-rw-r--r--gcc/cp/error.cc1
-rw-r--r--gcc/cp/module.cc2
-rw-r--r--gcc/cp/parser.cc10
-rw-r--r--gcc/cp/pt.cc25
-rw-r--r--gcc/fortran/class.cc24
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp3.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp22.C66
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp23.C77
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp24.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp25.C119
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp9.C5
-rw-r--r--gcc/testsuite/g++.dg/parse/union1.C19
-rw-r--r--gcc/testsuite/g++.dg/parse/union2.C19
-rw-r--r--gcc/testsuite/g++.dg/parse/union3.C19
-rw-r--r--gcc/testsuite/g++.dg/parse/union4.C12
-rw-r--r--gcc/testsuite/g++.dg/parse/union5.C5
-rw-r--r--gcc/testsuite/g++.dg/parse/union6.C5
-rw-r--r--gcc/testsuite/g++.dg/template/error45.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C2
-rw-r--r--gcc/testsuite/gcc.dg/guality/guality.h5
-rw-r--r--gcc/testsuite/gcc.target/i386/memcpy-pr120683-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memcpy-pr120683-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memcpy-pr120683-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memcpy-pr120683-4.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memcpy-pr120683-5.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memcpy-pr120683-6.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memcpy-pr120683-7.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memcpy-strategy-12.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-10.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-11.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-12.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-13.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-14.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-15.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-16.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-17.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-18.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-19.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-20.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-21.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-22.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-23.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-4.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-5.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-6.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-7.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-8.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-pr120683-9.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-epilogues-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-mask-epilogue-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-mask-epilogue-2.c14
-rw-r--r--gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-atomic-cas.c11
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/pr113829.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120461.c6
-rw-r--r--gcc/testsuite/gcc.target/s390/stack-protector-guard-tls-1.c39
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/pattern-avg-1.c3
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/pattern-avg-2.c23
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/pattern-mulh-1.c3
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/pattern-mulh-2.c26
-rw-r--r--gcc/testsuite/gcc.target/xtensa/BGEUI-BLTUI-32k-64k.c19
-rw-r--r--gcc/testsuite/gfortran.dg/asan/finalize_1.f9067
-rw-r--r--gcc/tree-ssa-structalias.cc5
-rw-r--r--gcc/tree-vect-loop.cc35
-rw-r--r--gcc/tree-vectorizer.h13
-rw-r--r--libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver18
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver14
-rw-r--r--libstdc++-v3/include/bits/version.def3
-rw-r--r--libstdc++-v3/include/bits/version.h3
-rw-r--r--libstdc++-v3/include/debug/deque5
-rw-r--r--libstdc++-v3/include/debug/formatter.h10
-rw-r--r--libstdc++-v3/include/debug/forward_list71
-rw-r--r--libstdc++-v3/include/debug/list15
-rw-r--r--libstdc++-v3/include/debug/safe_base.h77
-rw-r--r--libstdc++-v3/include/debug/safe_container.h25
-rw-r--r--libstdc++-v3/include/debug/safe_iterator.h14
-rw-r--r--libstdc++-v3/include/debug/safe_local_iterator.h102
-rw-r--r--libstdc++-v3/include/debug/safe_local_iterator.tcc4
-rw-r--r--libstdc++-v3/include/debug/safe_sequence.h9
-rw-r--r--libstdc++-v3/include/debug/safe_sequence.tcc6
-rw-r--r--libstdc++-v3/include/debug/safe_unordered_base.h67
-rw-r--r--libstdc++-v3/include/debug/safe_unordered_container.h4
-rw-r--r--libstdc++-v3/include/debug/safe_unordered_container.tcc4
-rw-r--r--libstdc++-v3/include/std/format4
-rw-r--r--libstdc++-v3/include/std/mdspan321
-rw-r--r--libstdc++-v3/include/std/queue10
-rw-r--r--libstdc++-v3/include/std/span20
-rw-r--r--libstdc++-v3/src/c++11/debug.cc174
-rw-r--r--libstdc++-v3/src/c++17/memory_resource.cc26
-rw-r--r--libstdc++-v3/src/c++23/std.cc.in3
-rw-r--r--libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc5
-rw-r--r--libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc58
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/class_mandate_neg.cc41
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc27
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc35
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h30
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc20
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h83
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc30
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc668
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc24
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/version.cc9
-rw-r--r--libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/span/deduction.cc3
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/const_container.cc19
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/const_container.cc22
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/const_container.cc15
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/const_container.cc14
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc2
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc52
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_containers.h6
125 files changed, 2785 insertions, 362 deletions
diff --git a/contrib/prepare-commit-msg b/contrib/prepare-commit-msg
index 1b87877..75d1025 100755
--- a/contrib/prepare-commit-msg
+++ b/contrib/prepare-commit-msg
@@ -78,4 +78,4 @@ else
tee="cat"
fi
-git $cmd | $tee | git gcc-mklog -c "$COMMIT_MSG_FILE"
+git $cmd --default-prefix | $tee | git gcc-mklog -c "$COMMIT_MSG_FILE"
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index fd3f35d..ad7360e 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -26295,6 +26295,65 @@ ix86_vector_costs::finish_cost (const vector_costs *scalar_costs)
&& LOOP_VINFO_VECT_FACTOR (loop_vinfo).to_constant () >= 16)
m_suggested_epilogue_mode = V8QImode;
+ /* When X86_TUNE_AVX512_MASKED_EPILOGUES is enabled try to use
+ a masked epilogue if that doesn't seem detrimental. */
+ if (loop_vinfo
+ && !LOOP_VINFO_EPILOGUE_P (loop_vinfo)
+ && LOOP_VINFO_VECT_FACTOR (loop_vinfo).to_constant () > 2
+ && ix86_tune_features[X86_TUNE_AVX512_MASKED_EPILOGUES]
+ && !OPTION_SET_P (param_vect_partial_vector_usage))
+ {
+ bool avoid = false;
+ if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
+ && LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) >= 0)
+ {
+ unsigned int peel_niter
+ = LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo);
+ if (LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo))
+ peel_niter += 1;
+ /* When we know the number of scalar iterations of the epilogue,
+ avoid masking when a single vector epilog iteration handles
+ it in full. */
+ if (pow2p_hwi ((LOOP_VINFO_INT_NITERS (loop_vinfo) - peel_niter)
+ % LOOP_VINFO_VECT_FACTOR (loop_vinfo).to_constant ()))
+ avoid = true;
+ }
+ if (!avoid && loop_outer (loop_outer (LOOP_VINFO_LOOP (loop_vinfo))))
+ for (auto ddr : LOOP_VINFO_DDRS (loop_vinfo))
+ {
+ if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
+ ;
+ else if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
+ ;
+ else
+ {
+ int loop_depth
+ = index_in_loop_nest (LOOP_VINFO_LOOP (loop_vinfo)->num,
+ DDR_LOOP_NEST (ddr));
+ if (DDR_NUM_DIST_VECTS (ddr) == 1
+ && DDR_DIST_VECTS (ddr)[0][loop_depth] == 0)
+ {
+ /* Avoid the case when there's an outer loop that might
+ traverse a multi-dimensional array with the inner
+ loop just executing the masked epilogue with a
+ read-write where the next outer iteration might
+ read from the masked part of the previous write,
+ 'n' filling half a vector.
+ for (j = 0; j < m; ++j)
+ for (i = 0; i < n; ++i)
+ a[j][i] = c * a[j][i]; */
+ avoid = true;
+ break;
+ }
+ }
+ }
+ if (!avoid)
+ {
+ m_suggested_epilogue_mode = loop_vinfo->vector_mode;
+ m_masked_epilogue = 1;
+ }
+ }
+
vector_costs::finish_cost (scalar_costs);
}
diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def
index 91cdca7..4773e5d 100644
--- a/gcc/config/i386/x86-tune.def
+++ b/gcc/config/i386/x86-tune.def
@@ -639,6 +639,11 @@ DEF_TUNE (X86_TUNE_AVX512_STORE_BY_PIECES, "avx512_store_by_pieces",
DEF_TUNE (X86_TUNE_AVX512_TWO_EPILOGUES, "avx512_two_epilogues",
m_ZNVER4 | m_ZNVER5)
+/* X86_TUNE_AVX512_MAKED_EPILOGUES: Use two masked vector epilogues
+ when fit. */
+DEF_TUNE (X86_TUNE_AVX512_MASKED_EPILOGUES, "avx512_masked_epilogues",
+ m_ZNVER4 | m_ZNVER5)
+
/*****************************************************************************/
/*****************************************************************************/
/* Historical relics: tuning flags that helps a specific old CPU designs */
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index a5ab8dd..22d1949 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -408,7 +408,7 @@ emit_vlmax_insn_lra (unsigned icode, unsigned insn_flags, rtx *ops, rtx vl)
gcc_assert (!can_create_pseudo_p ());
machine_mode mode = GET_MODE (ops[0]);
- if (imm_avl_p (mode))
+ if (imm_avl_p (mode) && !TARGET_XTHEADVECTOR)
{
/* Even though VL is a real hardreg already allocated since
it is post-RA now, we still gain benefits that we emit
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
index f652a12..8810af0 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -4977,6 +4977,12 @@ registered_function::overloaded_hash () const
for (unsigned int i = 0; i < argument_types.length (); i++)
{
type = argument_types[i];
+
+ /* If we're passed something entirely unreasonable, just ignore here.
+ We'll warn later anyway. */
+ if (TREE_CODE_CLASS (TREE_CODE (type)) != tcc_type)
+ continue;
+
unsigned_p = POINTER_TYPE_P (type) ? TYPE_UNSIGNED (TREE_TYPE (type))
: TYPE_UNSIGNED (type);
mode_p = POINTER_TYPE_P (type) ? TYPE_MODE (TREE_TYPE (type))
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index a75ea68..50ec8b3 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -627,7 +627,7 @@
(match_operand:SHORT 1 "memory_operand" "+A")) ;; memory
(set (match_dup 1)
(unspec_volatile:SHORT [(match_operand:SHORT 2 "register_operand" "0") ;; expected_val
- (match_operand:SHORT 3 "register_operand" "rJ") ;; desired_val
+ (match_operand:SHORT 3 "reg_or_0_operand" "rJ") ;; desired_val
(match_operand:SI 4 "const_int_operand") ;; mod_s
(match_operand:SI 5 "const_int_operand")] ;; mod_f
UNSPEC_COMPARE_AND_SWAP))]
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index f6db36e..02bc149 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -308,6 +308,9 @@
UNSPECV_SPLIT_STACK_CALL
UNSPECV_OSC_BREAK
+
+ ; Stack Protector
+ UNSPECV_SP_GET_TP
])
;;
@@ -365,6 +368,9 @@
(VR23_REGNUM 45)
(VR24_REGNUM 46)
(VR31_REGNUM 53)
+ ; Access registers
+ (AR0_REGNUM 36)
+ (AR1_REGNUM 37)
])
; Rounding modes for binary floating point numbers
@@ -11924,15 +11930,43 @@
; Stack Protector Patterns
;
+; Insns stack_protect_get_tp{si,di} are similar to *get_tp_{31,64} but still
+; distinct in the sense that they force recomputation of the thread pointer
+; instead of potentially reloading it from stack.
+
+(define_insn_and_split "stack_protect_get_tpsi"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec_volatile:SI [(const_int 0)] UNSPECV_SP_GET_TP))]
+ ""
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (reg:SI AR0_REGNUM))])
+
+(define_insn_and_split "stack_protect_get_tpdi"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (unspec_volatile:DI [(const_int 0)] UNSPECV_SP_GET_TP))]
+ ""
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 1) (reg:SI AR0_REGNUM))
+ (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32)))
+ (set (strict_low_part (match_dup 1)) (reg:SI AR1_REGNUM))]
+ "operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]));")
+
(define_expand "stack_protect_set"
[(set (match_operand 0 "memory_operand" "")
(match_operand 1 "memory_operand" ""))]
""
{
#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tp = gen_reg_rtx (Pmode);
+ if (TARGET_64BIT)
+ emit_insn (gen_stack_protect_get_tpdi (tp));
+ else
+ emit_insn (gen_stack_protect_get_tpsi (tp));
operands[1]
- = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (),
- GEN_INT (TARGET_THREAD_SSP_OFFSET)));
+ = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, tp,
+ GEN_INT (TARGET_THREAD_SSP_OFFSET)));
#endif
if (TARGET_64BIT)
emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
@@ -11958,9 +11992,14 @@
{
rtx cc_reg, test;
#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tp = gen_reg_rtx (Pmode);
+ if (TARGET_64BIT)
+ emit_insn (gen_stack_protect_get_tpdi (tp));
+ else
+ emit_insn (gen_stack_protect_get_tpsi (tp));
operands[1]
- = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (),
- GEN_INT (TARGET_THREAD_SSP_OFFSET)));
+ = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, tp,
+ GEN_INT (TARGET_THREAD_SSP_OFFSET)));
#endif
if (TARGET_64BIT)
emit_insn (gen_stack_protect_testdi (operands[0], operands[1]));
diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index 8c43a69..b75cec1 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -423,12 +423,13 @@ xtensa_uimm8x4 (HOST_WIDE_INT v)
}
-static bool
-xtensa_b4const (HOST_WIDE_INT v)
+bool
+xtensa_b4const_or_zero (HOST_WIDE_INT v)
{
switch (v)
{
case -1:
+ case 0:
case 1:
case 2:
case 3:
@@ -451,15 +452,6 @@ xtensa_b4const (HOST_WIDE_INT v)
bool
-xtensa_b4const_or_zero (HOST_WIDE_INT v)
-{
- if (v == 0)
- return true;
- return xtensa_b4const (v);
-}
-
-
-bool
xtensa_b4constu (HOST_WIDE_INT v)
{
switch (v)
@@ -4512,7 +4504,8 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
}
break;
case COMPARE:
- if ((INTVAL (x) == 0) || xtensa_b4const (INTVAL (x)))
+ if (xtensa_b4const_or_zero (INTVAL (x))
+ || xtensa_b4constu (INTVAL (x)))
{
*total = 0;
return true;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1b893e2..3b92d9a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -506,6 +506,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
LAMBDA_EXPR_STATIC_P (in LAMBDA_EXPR)
TARGET_EXPR_ELIDING_P (in TARGET_EXPR)
contract_semantic (in ASSERTION_, PRECONDITION_, POSTCONDITION_STMT)
+ TYPENAME_IS_UNION_P (in TYPENAME_TYPE)
4: IDENTIFIER_MARKED (IDENTIFIER_NODEs)
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
CALL_EXPR, or FIELD_DECL).
@@ -2354,6 +2355,10 @@ enum languages { lang_c, lang_cplusplus };
#define NON_UNION_CLASS_TYPE_P(T) \
(TREE_CODE (T) == RECORD_TYPE && TYPE_LANG_FLAG_5 (T))
+/* Nonzero if T is a class type and is a union. */
+#define UNION_TYPE_P(T) \
+ (TREE_CODE (T) == UNION_TYPE && TYPE_LANG_FLAG_5 (T))
+
/* Keep these checks in ascending code order. */
#define RECORD_OR_UNION_CODE_P(T) \
((T) == RECORD_TYPE || (T) == UNION_TYPE)
@@ -4485,11 +4490,14 @@ get_vec_init_expr (tree t)
#define TYPENAME_IS_ENUM_P(NODE) \
(TREE_LANG_FLAG_0 (TYPENAME_TYPE_CHECK (NODE)))
-/* True if a TYPENAME_TYPE was declared as a "class", "struct", or
- "union". */
+/* True if a TYPENAME_TYPE was declared as a "class" or "struct". */
#define TYPENAME_IS_CLASS_P(NODE) \
(TREE_LANG_FLAG_1 (TYPENAME_TYPE_CHECK (NODE)))
+/* True if a TYPENAME_TYPE was declared as a "union". */
+#define TYPENAME_IS_UNION_P(NODE) \
+ (TREE_LANG_FLAG_3 (TYPENAME_TYPE_CHECK (NODE)))
+
/* True if a TYPENAME_TYPE is in the process of being resolved. */
#define TYPENAME_IS_RESOLVING_P(NODE) \
(TREE_LANG_FLAG_2 (TYPENAME_TYPE_CHECK (NODE)))
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index be26bd3..0e6afbe 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -4370,6 +4370,7 @@ struct typename_info {
tree template_id;
bool enum_p;
bool class_p;
+ bool union_p;
};
struct typename_hasher : ggc_ptr_hash<tree_node>
@@ -4408,7 +4409,8 @@ struct typename_hasher : ggc_ptr_hash<tree_node>
&& TYPE_CONTEXT (t1) == t2->scope
&& TYPENAME_TYPE_FULLNAME (t1) == t2->template_id
&& TYPENAME_IS_ENUM_P (t1) == t2->enum_p
- && TYPENAME_IS_CLASS_P (t1) == t2->class_p);
+ && TYPENAME_IS_CLASS_P (t1) == t2->class_p
+ && TYPENAME_IS_UNION_P (t1) == t2->union_p);
}
};
@@ -4432,9 +4434,8 @@ build_typename_type (tree context, tree name, tree fullname,
ti.name = name;
ti.template_id = fullname;
ti.enum_p = tag_type == enum_type;
- ti.class_p = (tag_type == class_type
- || tag_type == record_type
- || tag_type == union_type);
+ ti.class_p = (tag_type == class_type || tag_type == record_type);
+ ti.union_p = tag_type == union_type;
hashval_t hash = typename_hasher::hash (&ti);
/* See if we already have this type. */
@@ -4450,6 +4451,7 @@ build_typename_type (tree context, tree name, tree fullname,
TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
TYPENAME_IS_ENUM_P (t) = ti.enum_p;
TYPENAME_IS_CLASS_P (t) = ti.class_p;
+ TYPENAME_IS_UNION_P (t) = ti.union_p;
/* Build the corresponding TYPE_DECL. */
tree d = build_decl (input_location, TYPE_DECL, name, t);
@@ -9174,6 +9176,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
if (decomp)
{
+ if (DECL_DECLARED_CONSTINIT_P (decl) && cxx_dialect < cxx26)
+ pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wc__26_extensions,
+ "%<constinit%> can be applied to structured binding "
+ "only with %<-std=c++2c%> or %<-std=gnu++2c%>");
cp_maybe_mangle_decomp (decl, decomp);
if (TREE_STATIC (decl) && !DECL_FUNCTION_SCOPE_P (decl))
{
@@ -13621,9 +13627,10 @@ grokdeclarator (const cp_declarator *declarator,
if (typedef_p)
error_at (declspecs->locations[ds_typedef],
"structured binding declaration cannot be %qs", "typedef");
- if (constexpr_p && !concept_p)
- error_at (declspecs->locations[ds_constexpr], "structured "
- "binding declaration cannot be %qs", "constexpr");
+ if (constexpr_p && !concept_p && cxx_dialect < cxx26)
+ pedwarn (declspecs->locations[ds_constexpr], OPT_Wc__26_extensions,
+ "structured binding declaration can be %qs only with "
+ "%<-std=c++2c%> or %<-std=gnu++2c%>", "constexpr");
if (consteval_p)
error_at (declspecs->locations[ds_consteval], "structured "
"binding declaration cannot be %qs", "consteval");
@@ -13634,8 +13641,11 @@ grokdeclarator (const cp_declarator *declarator,
declspecs->gnu_thread_keyword_p
? "__thread" : "thread_local");
if (concept_p)
- error_at (declspecs->locations[ds_concept],
- "structured binding declaration cannot be %qs", "concept");
+ {
+ error_at (declspecs->locations[ds_concept],
+ "structured binding declaration cannot be %qs", "concept");
+ constexpr_p = 0;
+ }
/* [dcl.struct.bind] "A cv that includes volatile is deprecated." */
if (type_quals & TYPE_QUAL_VOLATILE)
warning_at (declspecs->locations[ds_volatile], OPT_Wvolatile,
@@ -13690,7 +13700,6 @@ grokdeclarator (const cp_declarator *declarator,
"%<auto%> type %qT", type);
inlinep = 0;
typedef_p = 0;
- constexpr_p = 0;
consteval_p = 0;
concept_p = 0;
if (storage_class != sc_static)
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index abeb028..eb2ff33 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -810,6 +810,7 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)
pp_cxx_ws_string (pp,
TYPENAME_IS_ENUM_P (t) ? "enum"
: TYPENAME_IS_CLASS_P (t) ? "class"
+ : TYPENAME_IS_UNION_P (t) ? "union"
: "typename");
dump_typename (pp, t, flags);
break;
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index c8e79f3..6b5a60a 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -9619,6 +9619,8 @@ trees_out::type_node (tree type)
tag_type = enum_type;
else if (TYPENAME_IS_CLASS_P (type))
tag_type = class_type;
+ else if (TYPENAME_IS_UNION_P (type))
+ tag_type = union_type;
u (int (tag_type));
}
}
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 239e6f9..8148495 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -16870,7 +16870,11 @@ cp_parser_decomposition_declaration (cp_parser *parser,
decl = error_mark_node;
}
else
- prev = decl2;
+ {
+ prev = decl2;
+ DECL_DECLARED_CONSTEXPR_P (decl2) = DECL_DECLARED_CONSTEXPR_P (decl);
+ DECL_DECLARED_CONSTINIT_P (decl2) = DECL_DECLARED_CONSTINIT_P (decl);
+ }
if (elt_pushed_scope)
pop_scope (elt_pushed_scope);
}
@@ -35924,7 +35928,9 @@ cp_parser_check_class_key (cp_parser *parser, location_t key_loc,
return;
bool seen_as_union = TREE_CODE (type) == UNION_TYPE;
- if (seen_as_union != (class_key == union_type))
+ if (class_key != typename_type
+ && TREE_CODE (type) != TYPENAME_TYPE
+ && seen_as_union != (class_key == union_type))
{
auto_diagnostic_group d;
if (permerror (input_location, "%qs tag used in naming %q#T",
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 3362a6f..40ce987 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -17250,13 +17250,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return error_mark_node;
}
- /* FIXME: TYPENAME_IS_CLASS_P conflates 'class' vs 'struct' vs 'union'
- tags. TYPENAME_TYPE should probably remember the exact tag that
- was written. */
+ /* FIXME: TYPENAME_IS_CLASS_P conflates 'class' vs 'struct' tags.
+ TYPENAME_TYPE should probably remember the exact tag that
+ was written for -Wmismatched-tags. */
enum tag_types tag_type
- = TYPENAME_IS_CLASS_P (t) ? class_type
- : TYPENAME_IS_ENUM_P (t) ? enum_type
- : typename_type;
+ = (TYPENAME_IS_CLASS_P (t) ? class_type
+ : TYPENAME_IS_UNION_P (t) ? union_type
+ : TYPENAME_IS_ENUM_P (t) ? enum_type
+ : typename_type);
tsubst_flags_t tcomplain = complain | tf_keep_type_decl;
tcomplain |= tst_ok_flag | qualifying_scope_flag;
f = make_typename_type (ctx, f, tag_type, tcomplain);
@@ -17278,10 +17279,18 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else
return error_mark_node;
}
- else if (TYPENAME_IS_CLASS_P (t) && !CLASS_TYPE_P (f))
+ else if (TYPENAME_IS_CLASS_P (t) && !NON_UNION_CLASS_TYPE_P (f))
{
if (complain & tf_error)
- error ("%qT resolves to %qT, which is not a class type",
+ error ("%qT resolves to %qT, which is not a non-union "
+ "class type", t, f);
+ else
+ return error_mark_node;
+ }
+ else if (TYPENAME_IS_UNION_P (t) && !UNION_TYPE_P (f))
+ {
+ if (complain & tf_error)
+ error ("%qT resolves to %qT, which is not a union type",
t, f);
else
return error_mark_node;
diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc
index df18601..a1c6faf 100644
--- a/gcc/fortran/class.cc
+++ b/gcc/fortran/class.cc
@@ -1034,7 +1034,7 @@ comp_is_finalizable (gfc_component *comp)
of calling the appropriate finalizers, coarray deregistering, and
deallocation of allocatable subcomponents. */
-static void
+static bool
finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
gfc_symbol *stat, gfc_symbol *fini_coarray, gfc_code **code,
gfc_namespace *sub_ns)
@@ -1044,14 +1044,14 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
gfc_was_finalized *f;
if (!comp_is_finalizable (comp))
- return;
+ return false;
/* If this expression with this component has been finalized
already in this namespace, there is nothing to do. */
for (f = sub_ns->was_finalized; f; f = f->next)
{
if (f->e == expr && f->c == comp)
- return;
+ return false;
}
e = gfc_copy_expr (expr);
@@ -1208,8 +1208,6 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
final_wrap->ext.actual->next->next = gfc_get_actual_arglist ();
final_wrap->ext.actual->next->next->expr = fini_coarray_expr;
-
-
if (*code)
{
(*code)->next = final_wrap;
@@ -1221,11 +1219,14 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
else
{
gfc_component *c;
+ bool ret = false;
for (c = comp->ts.u.derived->components; c; c = c->next)
- finalize_component (e, comp->ts.u.derived, c, stat, fini_coarray, code,
- sub_ns);
- gfc_free_expr (e);
+ ret |= finalize_component (e, comp->ts.u.derived, c, stat, fini_coarray,
+ code, sub_ns);
+ /* Only free the expression, if it has never been used. */
+ if (!ret)
+ gfc_free_expr (e);
}
/* Record that this was finalized already in this namespace. */
@@ -1234,6 +1235,7 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
sub_ns->was_finalized->e = expr;
sub_ns->was_finalized->c = comp;
sub_ns->was_finalized->next = f;
+ return true;
}
@@ -2314,6 +2316,7 @@ finish_assumed_rank:
{
gfc_symbol *stat;
gfc_code *block = NULL;
+ gfc_expr *ptr_expr;
if (!ptr)
{
@@ -2359,14 +2362,15 @@ finish_assumed_rank:
sub_ns);
block = block->next;
+ ptr_expr = gfc_lval_expr_from_sym (ptr);
for (comp = derived->components; comp; comp = comp->next)
{
if (comp == derived->components && derived->attr.extension
&& ancestor_wrapper && ancestor_wrapper->expr_type != EXPR_NULL)
continue;
- finalize_component (gfc_lval_expr_from_sym (ptr), derived, comp,
- stat, fini_coarray, &block, sub_ns);
+ finalize_component (ptr_expr, derived, comp, stat, fini_coarray,
+ &block, sub_ns);
if (!last_code->block->next)
last_code->block->next = block;
}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C
index 971f58f..6ef8652 100644
--- a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C
@@ -1,5 +1,5 @@
// Basic generic lambda test
-// { dg-do run { target c++14 } }
+// { dg-do compile { target c++14 } }
template <typename T, typename U> struct pair {};
template <typename... T> struct tuple {};
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp3.C b/gcc/testsuite/g++.dg/cpp1z/decomp3.C
index a9b23b0..202edc3 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp3.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp3.C
@@ -19,7 +19,8 @@ test (A &b, B c)
// { dg-error "expected primary-expression before 'decltype'" "" { target c++11_down } .-2 }
auto & & && & [ m, n, o ] = b; // { dg-error "multiple ref-qualifiers" }
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
- constexpr auto [ p ] = c; // { dg-error "structured binding declaration cannot be 'constexpr'" }
+ constexpr B c2 = { 42 };
+ constexpr auto [ p ] = c2; // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } }
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
friend auto [ q ] = c; // { dg-error "'friend' used outside of class" }
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp22.C b/gcc/testsuite/g++.dg/cpp26/decomp22.C
new file mode 100644
index 0000000..576a93b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp22.C
@@ -0,0 +1,66 @@
+// C++26 P2686R4 - constexpr structured bindings
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+ template <typename T> struct tuple_size;
+ template <int, typename> struct tuple_element;
+}
+
+struct A {
+ int i, j;
+ template <int I> constexpr const int &get () const { return I == 1 ? j : i; }
+};
+
+template <> struct std::tuple_size <const A> { static const int value = 3; };
+template <int I> struct std::tuple_element <I, const A> { using type = const int; };
+
+constexpr struct B {
+ int i, j;
+ long long k, l;
+} a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
+
+constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+#if __cpp_constinit >= 201907
+constinit auto [ e, f, g ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+#if __cpp_constinit >= 201907
+constinit auto [ l, m, n, o ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+constexpr auto & [ p, q, r ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+#if __cpp_constinit >= 201907
+constinit auto & [ s, t, u ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+constexpr auto & [ v, w, x, y ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+#if __cpp_constinit >= 201907
+constinit auto & [ aa, ab, ac, ad ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+static_assert (b.i == 1 && b.l == 4 && c.j == 6 && c.k == 7 && d.i == 9 && d.k == 11, "");
+static_assert (h == 5 && i == 6 && j == 7 && k == 8, "");
+static_assert (p.i == 1 && p.l == 4 && q.j == 6 && q.k == 7 && r.i == 9 && r.k == 11, "");
+static_assert (&p.i == &a[0].i && &p.l == &a[0].l && &q.j == &a[1].j, "");
+static_assert (&q.k == &a[1].k && &r.i == &a[2].i && &r.k == &a[2].k, "");
+static_assert (v == 5 && w == 6 && x == 7 && y == 8, "");
+static_assert (&v == &a[1].i && &w == &a[1].j && &x == &a[1].k && &y == &a[1].l, "");
+
+constexpr A z = { 42, -42 };
+constexpr auto [ ae, af, ag ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+#if __cpp_constinit >= 201907
+constinit const auto [ ah, ai, aj ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+constexpr auto & [ ak, al, am ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+#if __cpp_constinit >= 201907
+constinit auto & [ an, ao, ap ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+static_assert (ae == 42 && af == -42 && ag == 42, "");
+static_assert (&af == &ae + 1 && &ag == &ae, "");
+static_assert (&ae != &z.i && &af != &z.j && &ag != &z.i, "");
+static_assert (ak == 42 && al == -42 && am == 42, "");
+static_assert (&ak == &z.i && &al == &z.j && &am == &z.i, "");
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp23.C b/gcc/testsuite/g++.dg/cpp26/decomp23.C
new file mode 100644
index 0000000..ad2f7e0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp23.C
@@ -0,0 +1,77 @@
+// C++26 P2686R4 - constexpr structured bindings
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+ template <typename T> struct tuple_size;
+ template <int, typename> struct tuple_element;
+}
+
+struct A {
+ int i, j;
+ template <int I> constexpr const int &get () const { return I == 1 ? j : i; }
+};
+
+template <> struct std::tuple_size <const A> { static const int value = 3; };
+template <int I> struct std::tuple_element <I, const A> { using type = const int; };
+
+struct B {
+ int i, j;
+ long long k, l;
+};
+
+void
+foo ()
+{
+ static constexpr B a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
+ static constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
+#if __cpp_constinit >= 201907
+ static constinit auto [ e, f, g ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+ static constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
+#if __cpp_constinit >= 201907
+ static constinit auto [ l, m, n, o ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+ static constexpr auto & [ p, q, r ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
+#if __cpp_constinit >= 201907
+ static constinit auto & [ s, t, u ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+ static constexpr auto & [ v, w, x, y ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
+#if __cpp_constinit >= 201907
+ static constinit auto & [ aa, ab, ac, ad ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+ static_assert (b.i == 1 && b.l == 4 && c.j == 6 && c.k == 7 && d.i == 9 && d.k == 11, "");
+ static_assert (h == 5 && i == 6 && j == 7 && k == 8, "");
+ static_assert (p.i == 1 && p.l == 4 && q.j == 6 && q.k == 7 && r.i == 9 && r.k == 11, "");
+ static_assert (&p.i == &a[0].i && &p.l == &a[0].l && &q.j == &a[1].j, "");
+ static_assert (&q.k == &a[1].k && &r.i == &a[2].i && &r.k == &a[2].k, "");
+ static_assert (v == 5 && w == 6 && x == 7 && y == 8, "");
+ static_assert (&v == &a[1].i && &w == &a[1].j && &x == &a[1].k && &y == &a[1].l, "");
+
+ static constexpr A z = { 42, -42 };
+ static constexpr auto [ ae, af, ag ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
+#if __cpp_constinit >= 201907
+ static constinit const auto [ ah, ai, aj ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+ static constexpr auto & [ ak, al, am ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
+#if __cpp_constinit >= 201907
+ static constinit auto & [ an, ao, ap ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+ static_assert (ae == 42 && af == -42 && ag == 42, "");
+ static_assert (&af == &ae + 1 && &ag == &ae, "");
+ static_assert (&ae != &z.i && &af != &z.j && &ag != &z.i, "");
+ static_assert (ak == 42 && al == -42 && am == 42, "");
+ static_assert (&ak == &z.i && &al == &z.j && &am == &z.i, "");
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp24.C b/gcc/testsuite/g++.dg/cpp26/decomp24.C
new file mode 100644
index 0000000..5da1321
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp24.C
@@ -0,0 +1,20 @@
+// C++26 P2686R4 - constexpr structured bindings
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct B {
+ int i, j;
+ long long k, l;
+};
+
+void
+foo ()
+{
+ constexpr B a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
+ constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ static_assert (b.i == 1 && b.l == 4 && c.j == 6 && c.k == 7 && d.i == 9 && d.k == 11, "");
+ static_assert (h == 5 && i == 6 && j == 7 && k == 8, "");
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp25.C b/gcc/testsuite/g++.dg/cpp26/decomp25.C
new file mode 100644
index 0000000..55559f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp25.C
@@ -0,0 +1,119 @@
+// C++26 P2686R4 - constexpr structured bindings
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+ template <typename T> struct tuple_size;
+ template <int, typename> struct tuple_element;
+}
+
+struct A {
+ int i, j;
+ template <int I> int &get () { return I == 1 ? j : i; }
+};
+
+template <> struct std::tuple_size <A> { static const int value = 3; };
+template <int I> struct std::tuple_element <I, A> { using type = int; };
+template <> struct std::tuple_size <const A> { static const int value = 3; };
+template <int I> struct std::tuple_element <I, const A> { using type = int; };
+
+struct B {
+ int i, j;
+ long long k, l;
+} a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; // { dg-message "'a' was not declared 'constexpr'" "" }
+
+struct C {
+ int i, j;
+ template <int I> const int &get () const { return I == 1 ? j : i; }
+};
+
+template <> struct std::tuple_size <const C> { static const int value = 3; };
+template <int I> struct std::tuple_element <I, const C> { using type = const int; };
+
+constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-error "the value of 'a' is not usable in a constant expression" "" { target *-*-* } .-2 }
+#if __cpp_constinit >= 201907
+constinit auto [ e, f, g ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+ // { dg-error "'constinit' variable '<structured bindings>' does not have a constant initializer" "" { target c++20 } .-1 }
+ // { dg-error "the value of 'a' is not usable in a constant expression" "" { target c++20 } .-2 }
+#endif
+constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-error "the value of 'a' is not usable in a constant expression" "" { target *-*-* } .-2 }
+#if __cpp_constinit >= 201907
+constinit auto [ l, m, n, o ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+ // { dg-error "'constinit' variable '<structured bindings>' does not have a constant initializer" "" { target c++20 } .-1 }
+ // { dg-error "the value of 'a' is not usable in a constant expression" "" { target c++20 } .-2 }
+#endif
+constexpr auto & [ p, q, r ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+#if __cpp_constinit >= 201907
+constinit auto & [ s, t, u ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+constexpr auto & [ v, w, x, y ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+#if __cpp_constinit >= 201907
+constinit auto & [ aa, ab, ac, ad ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+#endif
+
+A z = { 42, -42 }; // { dg-message "'z' was not declared 'constexpr'" "" }
+constexpr auto [ ae, af, ag ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-error "the value of 'z' is not usable in a constant expression" "" { target *-*-* } .-2 }
+ // { dg-error "passing 'const A' as 'this' argument discards qualifiers" "" { target *-*-* } .-3 }
+ // { dg-error "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target *-*-* } .-4 }
+#if __cpp_constinit >= 201907
+constinit const auto [ ah, ai, aj ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+ // { dg-error "'constinit' variable '<structured bindings>' does not have a constant initializer" "" { target c++20 } .-1 }
+ // { dg-error "the value of 'z' is not usable in a constant expression" "" { target c++20 } .-2 }
+ // { dg-error "passing 'const A' as 'this' argument discards qualifiers" "" { target c++20 } .-3 }
+ // { dg-error "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target c++20 } .-4 }
+ // { dg-error "'constinit' variable 'ah' does not have a constant initializer" "" { target c++20 } .-5 }
+ // { dg-error "'constinit' variable 'ai' does not have a constant initializer" "" { target c++20 } .-6 }
+ // { dg-error "'constinit' variable 'aj' does not have a constant initializer" "" { target c++20 } .-7 }
+#endif
+constexpr auto & [ ak, al, am ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-error "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target *-*-* } .-2 }
+#if __cpp_constinit >= 201907
+constinit auto & [ an, ao, ap ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+ // { dg-error "'constinit' variable 'an' does not have a constant initializer" "" { target c++20 } .-1 }
+ // { dg-error "'constinit' variable 'ao' does not have a constant initializer" "" { target c++20 } .-2 }
+ // { dg-error "'constinit' variable 'ap' does not have a constant initializer" "" { target c++20 } .-3 }
+ // { dg-message "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target c++20 } .-4 }
+#endif
+
+constexpr C zz = { 42, -42 };
+constexpr auto [ aq, ar, as ] = zz; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-error "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target *-*-* } .-2 }
+#if __cpp_constinit >= 201907
+constinit const auto [ at, au, av ] = zz; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+ // { dg-error "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target c++20 } .-1 }
+ // { dg-error "'constinit' variable 'at' does not have a constant initializer" "" { target c++20 } .-2 }
+ // { dg-error "'constinit' variable 'au' does not have a constant initializer" "" { target c++20 } .-3 }
+ // { dg-error "'constinit' variable 'av' does not have a constant initializer" "" { target c++20 } .-4 }
+#endif
+constexpr auto & [ aw, ax, ay ] = zz; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
+ // { dg-error "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target *-*-* } .-2 }
+#if __cpp_constinit >= 201907
+constinit auto & [ az, ba, bb ] = zz; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } }
+ // { dg-error "'constinit' variable 'az' does not have a constant initializer" "" { target c++20 } .-1 }
+ // { dg-error "'constinit' variable 'ba' does not have a constant initializer" "" { target c++20 } .-2 }
+ // { dg-error "'constinit' variable 'bb' does not have a constant initializer" "" { target c++20 } .-3 }
+ // { dg-message "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target c++20 } .-4 }
+#endif
+
+void
+foo ()
+{
+#if __cpp_constinit >= 201907
+ constexpr B a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
+ constinit auto [ b, c, d ] = a; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } }
+ constinit auto & [ e, f, g ] = a; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } }
+ constinit auto [ h, i, j, k ] = a[1]; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } }
+ constinit auto & [ l, m, n, o ] = a[2]; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } }
+#endif
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp9.C b/gcc/testsuite/g++.dg/cpp26/decomp9.C
index 5629c4c..ee18b60 100644
--- a/gcc/testsuite/g++.dg/cpp26/decomp9.C
+++ b/gcc/testsuite/g++.dg/cpp26/decomp9.C
@@ -63,6 +63,7 @@ foo (const S &&s)
if (static auto [i, j, k] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
; // { dg-error "'static' invalid in condition" "" { target *-*-* } .-1 }
// { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
- if (constexpr auto [i, j, k] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
- ; // { dg-error "structured binding declaration cannot be 'constexpr'" "" { target *-*-* } .-1 }
+ constexpr T t2 = { 1, 2, 3 };
+ if (constexpr auto [i, j, k] = t2) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+ ; // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 }
}
diff --git a/gcc/testsuite/g++.dg/parse/union1.C b/gcc/testsuite/g++.dg/parse/union1.C
new file mode 100644
index 0000000..d567ea3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/union1.C
@@ -0,0 +1,19 @@
+// PR c++/83469
+// { dg-do compile }
+
+struct S {
+ union U { int m; };
+};
+
+template <typename T>
+void
+f ()
+{
+ union T::U u;
+}
+
+int
+main()
+{
+ f<S>();
+}
diff --git a/gcc/testsuite/g++.dg/parse/union2.C b/gcc/testsuite/g++.dg/parse/union2.C
new file mode 100644
index 0000000..cdb1392
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/union2.C
@@ -0,0 +1,19 @@
+// PR c++/83469
+// { dg-do compile }
+
+struct S {
+ union U { int m; };
+};
+
+template <typename T>
+void
+f ()
+{
+ struct T::U u; // { dg-error "not a non-union class type" }
+}
+
+int
+main()
+{
+ f<S>();
+}
diff --git a/gcc/testsuite/g++.dg/parse/union3.C b/gcc/testsuite/g++.dg/parse/union3.C
new file mode 100644
index 0000000..61552a4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/union3.C
@@ -0,0 +1,19 @@
+// PR c++/83469
+// { dg-do compile }
+
+struct S {
+ struct C { int m; };
+};
+
+template <typename T>
+void
+f ()
+{
+ union T::C u; // { dg-error "not a union type" }
+}
+
+int
+main()
+{
+ f<S>();
+}
diff --git a/gcc/testsuite/g++.dg/parse/union4.C b/gcc/testsuite/g++.dg/parse/union4.C
new file mode 100644
index 0000000..709f6a4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/union4.C
@@ -0,0 +1,12 @@
+// PR c++/93809
+// { dg-do compile }
+
+class C { };
+enum E { };
+struct S { };
+union U { };
+
+typedef typename ::C C2;
+typedef typename ::E E2;
+typedef typename ::S S2;
+typedef typename ::U U2;
diff --git a/gcc/testsuite/g++.dg/parse/union5.C b/gcc/testsuite/g++.dg/parse/union5.C
new file mode 100644
index 0000000..18238dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/union5.C
@@ -0,0 +1,5 @@
+// PR c++/93809
+// { dg-do compile { target c++11 } }
+
+union U {};
+auto var = new (typename ::U);
diff --git a/gcc/testsuite/g++.dg/parse/union6.C b/gcc/testsuite/g++.dg/parse/union6.C
new file mode 100644
index 0000000..61b9568
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/union6.C
@@ -0,0 +1,5 @@
+// PR c++/93809
+// { dg-do compile }
+
+typedef union{} U;
+typename ::U foo () { return U(); }
diff --git a/gcc/testsuite/g++.dg/template/error45.C b/gcc/testsuite/g++.dg/template/error45.C
index 064554d..f4c6560 100644
--- a/gcc/testsuite/g++.dg/template/error45.C
+++ b/gcc/testsuite/g++.dg/template/error45.C
@@ -11,7 +11,7 @@ struct enable_if< true, T >
template < typename T >
struct enable_if< true, T >::type
-f( T x ); // { dg-error "not a class type" }
+f( T x ); // { dg-error "not a non-union class type" }
void
g( void )
diff --git a/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C b/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C
index 0eeee34..dcccdca 100644
--- a/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C
+++ b/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C
@@ -28,7 +28,7 @@ struct N::S s3; // { dg-warning "-Wredundant-tags" }
N::U u1;
typename N::U u2; // { dg-bogus "-Wredundant-tags" }
- // { dg-bogus "'class' tag used in naming 'union N::U" "pr93809" { xfail *-*-*} .-1 }
+ // { dg-bogus "'class' tag used in naming 'union N::U" "pr93809" { target *-*-*} .-1 }
union N::U u3; // { dg-warning "-Wredundant-tags" }
diff --git a/gcc/testsuite/gcc.dg/guality/guality.h b/gcc/testsuite/gcc.dg/guality/guality.h
index d41327c..48b59d2e 100644
--- a/gcc/testsuite/gcc.dg/guality/guality.h
+++ b/gcc/testsuite/gcc.dg/guality/guality.h
@@ -204,9 +204,10 @@ int volatile guality_attached;
of this wrapping, guality_main may not have an empty argument
list. */
-extern int guality_main (int argc, char *argv[]);
+extern int __attribute__((noipa))
+guality_main (int argc, char *argv[]);
-static void __attribute__((noinline))
+static void __attribute__((noipa))
guality_check (const char *name, gualchk_t value, int unknown_ok);
/* Set things up, run guality_main, then print a summary and quit. */
diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-1.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-1.c
index 753238e..b1f6678 100644
--- a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-1.c
+++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-sse -mmemcpy-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mno-sse -mmemcpy-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-2.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-2.c
index 9b0fb06..0d0e348 100644
--- a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-2.c
+++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-3.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-3.c
index 600459b..e5aca32 100644
--- a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-3.c
+++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-4.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-4.c
index 14833ff..27f7bed 100644
--- a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-4.c
+++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v3 -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-5.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-5.c
index 15ffed9..34a7408 100644
--- a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-5.c
+++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-5.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v3 -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-6.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-6.c
index d57dcc1..aa5d90d 100644
--- a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-6.c
+++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-6.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v4 -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-7.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-7.c
index d9eb77d..63d8a15 100644
--- a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-7.c
+++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-7.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v4 -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memcpy-strategy-12.c b/gcc/testsuite/gcc.target/i386/memcpy-strategy-12.c
index 4716086..c60cef0 100644
--- a/gcc/testsuite/gcc.target/i386/memcpy-strategy-12.c
+++ b/gcc/testsuite/gcc.target/i386/memcpy-strategy-12.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mtune=generic -mno-sse" } */
+/* { dg-options "-O2 -mtune=generic -mno-sse -fasynchronous-unwind-tables -fdwarf2-cfi-asm" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-1.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-1.c
index 90e544d..06e3892 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-1.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-10.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-10.c
index 6d3d9e7..36a924d 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-10.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-10.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-sse -mmemset-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -mno-sse -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-11.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-11.c
index 30b0cad..4868e56 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-11.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-11.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-sse -mmemset-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -mno-sse -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-12.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-12.c
index 15987a6..9112897 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-12.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-12.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-sse -mmemset-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -mno-sse -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-13.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-13.c
index 3da6ca7..69ec6c6 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-13.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-13.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-14.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-14.c
index 7ec9b3f..209cd67 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-14.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-14.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-15.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-15.c
index e754405..d19188f 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-15.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-15.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v3 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
+/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-16.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-16.c
index c519bf3..539714c 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-16.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-16.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v4 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
+/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-17.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-17.c
index 744184c..f58cb28 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-17.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-17.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-18.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-18.c
index 32f8981..a127028 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-18.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-18.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-19.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-19.c
index 04f9171..8dd5ae6 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-19.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-19.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-2.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-2.c
index f7834c0..3b84b29 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-2.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v3 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-20.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-20.c
index edece12..b8b9cb7 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-20.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-20.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-21.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-21.c
index a88e109..3c7bb7c 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-21.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-21.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-22.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-22.c
index f2bd698..96a21c8 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-22.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-22.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
-/* { dg-options "-O2 -march=x86-64 -mmemset-strategy=rep_8byte:8192:align,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=rep_8byte:8192:align,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-23.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-23.c
index 784f8dc..f3f5d80 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-23.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-23.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -minline-all-stringops -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -minline-all-stringops -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-3.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-3.c
index 621baf7..faa47ca 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-3.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v4 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
+/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-4.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-4.c
index 712404b..dc3aa57b 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-4.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-5.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-5.c
index f597395..a324f8e 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-5.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-5.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v3 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
+/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-6.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-6.c
index 7ba1b742..64e7589 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-6.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-6.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v4 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
+/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-7.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-7.c
index 62f61c5..022f6f9 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-7.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-7.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
+/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-8.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-8.c
index d12ab15..5254e21 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-8.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-8.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v3 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
+/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-9.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-9.c
index 1a0abe6..1719de6 100644
--- a/gcc/testsuite/gcc.target/i386/memset-pr120683-9.c
+++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-9.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=x86-64-v4 -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
+/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-epilogues-3.c b/gcc/testsuite/gcc.target/i386/vect-epilogues-3.c
index 0ee610f..e88ab30 100644
--- a/gcc/testsuite/gcc.target/i386/vect-epilogues-3.c
+++ b/gcc/testsuite/gcc.target/i386/vect-epilogues-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -mavx512bw -mtune=znver4 -fdump-tree-vect-optimized" } */
+/* { dg-options "-O3 -mavx512bw -mtune=znver4 --param vect-partial-vector-usage=0 -fdump-tree-vect-optimized" } */
int test (signed char *data, int n)
{
diff --git a/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-1.c b/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-1.c
new file mode 100644
index 0000000..55519aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=znver5 -fdump-tree-vect-optimized" } */
+
+void bar (double *a, double *b, double c, int n, int m)
+{
+ for (int j = 0; j < m; ++j)
+ for (int i = 0; i < n; ++i)
+ a[j*n + i] = b[j*n + i] + c;
+}
+
+/* { dg-final { scan-tree-dump "epilogue loop vectorized using masked 64 byte vectors" "vect" } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-2.c b/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-2.c
new file mode 100644
index 0000000..3dc28b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=znver5 -fdump-tree-vect-optimized" } */
+
+void foo (double *a, double b, double c, int n, int m)
+{
+ for (int j = 0; j < m; ++j)
+ for (int i = 0; i < n; ++i)
+ a[j*n + i] = a[j*n + i] * b + c;
+}
+
+/* We do not want to use a masked epilogue for the inner loop as the next
+ outer iteration will possibly immediately read from elements masked of
+ the previous inner loop epilogue and that never forwards. */
+/* { dg-final { scan-tree-dump "epilogue loop vectorized using 32 byte vectors" "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-atomic-cas.c b/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-atomic-cas.c
new file mode 100644
index 0000000..d3d84fd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-atomic-cas.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* PR target/120995 ICE unrecognized subword atomic cas */
+/* { dg-options "-O" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_zabha } */
+
+_Bool b;
+void atomic_bool_cmpxchg()
+{
+ __sync_bool_compare_and_swap(&b, 1, 0);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr113829.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr113829.c
new file mode 100644
index 0000000..48c291a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr113829.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gcv -mabi=lp64d" } */
+
+#pragma riscv intrinsic "vector"
+void
+foo (void)
+{
+ __riscv_vfredosum_tu (X); /* { dg-error "undeclared" } */
+ /* { dg-error "too many arguments" "" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120461.c b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120461.c
new file mode 100644
index 0000000..6939157
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120461.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=xt-c920 -mrvv-vector-bits=zvl -fzero-call-used-regs=all" */
+
+void
+foo ()
+{}
diff --git a/gcc/testsuite/gcc.target/s390/stack-protector-guard-tls-1.c b/gcc/testsuite/gcc.target/s390/stack-protector-guard-tls-1.c
new file mode 100644
index 0000000..1efd245
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/stack-protector-guard-tls-1.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fstack-protector-all" } */
+/* { dg-final { scan-assembler-times {\tear\t%r[0-9]+,%a[01]} 8 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {\tsllg\t%r[0-9]+,%r[0-9]+,32} 4 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {\tear\t%r[0-9]+,%a[01]} 3 { target { ! lp64 } } } } */
+/* { dg-final { scan-assembler-times {\tmvc\t160\(8,%r15\),40\(%r[0-9]+\)} 2 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {\tmvc\t100\(4,%r15\),20\(%r[0-9]+\)} 2 { target { ! lp64 } } } } */
+/* { dg-final { scan-assembler-times {\tclc\t160\(8,%r15\),40\(%r[0-9]+\)} 2 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {\tclc\t100\(4,%r15\),20\(%r[0-9]+\)} 2 { target { ! lp64 } } } } */
+
+/* Computing the address of the thread pointer on s390 involves multiple
+ instructions and therefore bears the risk that the address of the canary or
+ intermediate values of it are spilled and reloaded. Therefore, as a
+ precaution compute the address always twice, i.e., one time for the prologue
+ and one time for the epilogue. */
+
+void test_0 (void) { }
+
+void test_1 (void)
+{
+ __asm__ __volatile ("" :::
+ "r0",
+ "r1",
+ "r2",
+ "r3",
+ "r4",
+ "r5",
+ "r6",
+ "r7",
+ "r8",
+ "r9",
+ "r10",
+ "r11",
+#ifndef __PIC__
+ "r12",
+#endif
+ "r13",
+ "r14");
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/pattern-avg-1.c b/gcc/testsuite/gcc.target/s390/vector/pattern-avg-1.c
index a15301a..30c6ed4 100644
--- a/gcc/testsuite/gcc.target/s390/vector/pattern-avg-1.c
+++ b/gcc/testsuite/gcc.target/s390/vector/pattern-avg-1.c
@@ -21,6 +21,5 @@
TEST(char,short,16)
TEST(short,int,8)
TEST(int,long,4)
-TEST(long,__int128,2)
-/* { dg-final { scan-tree-dump-times "\.AVG_CEIL" 8 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\.AVG_CEIL" 6 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/pattern-avg-2.c b/gcc/testsuite/gcc.target/s390/vector/pattern-avg-2.c
new file mode 100644
index 0000000..1cc614e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/pattern-avg-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O3 -mzarch -march=z16 -ftree-vectorize -fdump-tree-optimized" } */
+
+#define TEST(T1,T2,N) \
+ void \
+ avg##T1 (signed T1 *__restrict res, signed T1 *__restrict a, \
+ signed T1 *__restrict b) \
+ { \
+ for (int i = 0; i < N; ++i) \
+ res[i] = ((signed T2)a[i] + b[i] + 1) >> 1; \
+ } \
+ \
+ void \
+ uavg##T1 (unsigned T1 *__restrict res, unsigned T1 *__restrict a, \
+ unsigned T1 *__restrict b) \
+ { \
+ for (int i = 0; i < N; ++i) \
+ res[i] = ((unsigned T2)a[i] + b[i] + 1) >> 1; \
+ }
+
+TEST(long,__int128,2)
+
+/* { dg-final { scan-tree-dump-times "\.AVG_CEIL" 2 "optimized" } } */
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 cd8e4e7d..f71ef06 100644
--- a/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-1.c
+++ b/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-1.c
@@ -24,6 +24,5 @@
TEST(char,short,16,8)
TEST(short,int,8,16)
TEST(int,long,4,32)
-TEST(long,__int128,2,64)
-/* { dg-final { scan-tree-dump-times "\.MULH" 8 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\.MULH" 6 "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
new file mode 100644
index 0000000..6ac6855
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-2.c
@@ -0,0 +1,26 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O3 -mzarch -march=arch15 -ftree-vectorize -fdump-tree-optimized" } */
+
+#define TEST(T1,T2,N,S) \
+ void \
+ mulh##T1 (signed T1 *__restrict res, \
+ signed T1 *__restrict l, \
+ signed T1 *__restrict r) \
+ { \
+ for (int i = 0; i < N; ++i) \
+ res[i] = (signed T1) (((signed T2)l[i] * (signed T2)r[i]) >> S); \
+ } \
+ \
+ void \
+ umulh##T1 (unsigned T1 *__restrict res, \
+ unsigned T1 *__restrict l, \
+ unsigned T1 *__restrict r) \
+ { \
+ for (int i = 0; i < N; ++i) \
+ res[i] = (unsigned T1) \
+ (((unsigned T2)l[i] * (unsigned T2)r[i]) >> S); \
+ }
+
+TEST(long,__int128,2,64)
+
+/* { dg-final { scan-tree-dump-times "\.MULH" 2 "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/testsuite/gfortran.dg/asan/finalize_1.f90 b/gcc/testsuite/gfortran.dg/asan/finalize_1.f90
new file mode 100644
index 0000000..ab53a9e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/asan/finalize_1.f90
@@ -0,0 +1,67 @@
+!{ dg-do run }
+
+! PR fortran/120637
+
+! Contributed by Antony Lewis <antony@cosmologist.info>
+! The unused module is needed to trigger the issue of not freeing the
+! memory of second module.
+
+ module MiscUtils
+ implicit none
+
+ contains
+
+ logical function isFloat0(R)
+ class(*), intent(in) :: R
+
+ select type(R)
+ type is (real)
+ isFloat0 = .true.
+ end select
+ end function isFloat0
+
+ end module MiscUtils
+
+ module results3
+ implicit none
+ public
+
+ Type ClTransferData2
+ real, dimension(:,:,:), allocatable :: Delta_p_l_k
+ end type ClTransferData2
+
+ type TCLdata2
+ Type(ClTransferData2) :: CTransScal, CTransTens, CTransVec
+ end type TCLdata2
+
+ type :: CAMBdata2
+ Type(TClData2) :: CLdata2
+ end type
+
+ end module results3
+
+program driver
+ use results3
+ integer i
+ do i=1, 2
+ call test()
+ end do
+
+ contains
+
+ subroutine test
+ implicit none
+ class(CAMBdata2), pointer :: Data
+
+ allocate(CAMBdata2::Data)
+
+ allocate(Data%ClData2%CTransScal%Delta_p_l_k(3, 1000, 1000))
+ allocate(Data%ClData2%CTransVec%Delta_p_l_k(3, 1000, 1000))
+ deallocate(Data)
+
+ end subroutine test
+
+ end program driver
+
+!{ dg-final { cleanup-modules "miscutils results3" } }
+
diff --git a/gcc/tree-ssa-structalias.cc b/gcc/tree-ssa-structalias.cc
index deca44a..0215243 100644
--- a/gcc/tree-ssa-structalias.cc
+++ b/gcc/tree-ssa-structalias.cc
@@ -3690,7 +3690,10 @@ get_constraint_for_1 (tree t, vec<ce_s> *results, bool address_p,
size = -1;
for (; curr; curr = vi_next (curr))
{
- if (curr->offset - vi->offset < size)
+ /* The start of the access might happen anywhere
+ within vi, so conservatively assume it was
+ at its end. */
+ if (curr->offset - (vi->offset + vi->size - 1) < size)
{
cs.var = curr->id;
results->safe_push (cs);
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 2782d61..d5044d5 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-eh.h"
#include "case-cfn-macros.h"
#include "langhooks.h"
+#include "opts.h"
/* Loop Vectorization Pass.
@@ -3400,8 +3401,10 @@ vect_joust_loop_vinfos (loop_vec_info new_loop_vinfo,
}
/* Analyze LOOP with VECTOR_MODES[MODE_I] and as epilogue if ORIG_LOOP_VINFO is
- not NULL. Set AUTODETECTED_VECTOR_MODE if VOIDmode and advance
- MODE_I to the next mode useful to analyze.
+ not NULL. When MASKED_P is not -1 override the default
+ LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P with it.
+ Set AUTODETECTED_VECTOR_MODE if VOIDmode and advance MODE_I to the next
+ mode useful to analyze.
Return the loop_vinfo on success and wrapped null on failure. */
static opt_loop_vec_info
@@ -3409,6 +3412,7 @@ vect_analyze_loop_1 (class loop *loop, vec_info_shared *shared,
const vect_loop_form_info *loop_form_info,
loop_vec_info orig_loop_vinfo,
const vector_modes &vector_modes, unsigned &mode_i,
+ int masked_p,
machine_mode &autodetected_vector_mode,
bool &fatal)
{
@@ -3417,6 +3421,8 @@ vect_analyze_loop_1 (class loop *loop, vec_info_shared *shared,
machine_mode vector_mode = vector_modes[mode_i];
loop_vinfo->vector_mode = vector_mode;
+ if (masked_p != -1)
+ loop_vinfo->can_use_partial_vectors_p = masked_p;
unsigned int suggested_unroll_factor = 1;
unsigned slp_done_for_suggested_uf = 0;
@@ -3600,7 +3606,7 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call,
cached_vf_per_mode[last_mode_i] = -1;
opt_loop_vec_info loop_vinfo
= vect_analyze_loop_1 (loop, shared, &loop_form_info,
- NULL, vector_modes, mode_i,
+ NULL, vector_modes, mode_i, -1,
autodetected_vector_mode, fatal);
if (fatal)
break;
@@ -3685,18 +3691,21 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call,
array may contain length-agnostic and length-specific modes. Their
ordering is not guaranteed, so we could end up picking a mode for the main
loop that is after the epilogue's optimal mode. */
+ int masked_p = -1;
if (!unlimited_cost_model (loop)
- && first_loop_vinfo->vector_costs->suggested_epilogue_mode () != VOIDmode)
+ && (first_loop_vinfo->vector_costs->suggested_epilogue_mode (masked_p)
+ != VOIDmode))
{
vector_modes[0]
- = first_loop_vinfo->vector_costs->suggested_epilogue_mode ();
+ = first_loop_vinfo->vector_costs->suggested_epilogue_mode (masked_p);
cached_vf_per_mode[0] = 0;
}
else
vector_modes[0] = autodetected_vector_mode;
mode_i = 0;
- bool supports_partial_vectors = param_vect_partial_vector_usage != 0;
+ bool supports_partial_vectors = (param_vect_partial_vector_usage != 0
+ || masked_p == 1);
machine_mode mask_mode;
if (supports_partial_vectors
&& !partial_vectors_supported_p ()
@@ -3710,6 +3719,10 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call,
loop_vec_info orig_loop_vinfo = first_loop_vinfo;
do
{
+ /* Let the user override what the target suggests. */
+ if (OPTION_SET_P (param_vect_partial_vector_usage))
+ masked_p = -1;
+
while (1)
{
/* If the target does not support partial vectors we can shorten the
@@ -3750,7 +3763,7 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call,
opt_loop_vec_info loop_vinfo
= vect_analyze_loop_1 (loop, shared, &loop_form_info,
orig_loop_vinfo,
- vector_modes, mode_i,
+ vector_modes, mode_i, masked_p,
autodetected_vector_mode, fatal);
if (fatal)
break;
@@ -3781,6 +3794,9 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call,
break;
}
+ /* Revert back to the default from the suggested prefered
+ epilogue vectorization mode. */
+ masked_p = -1;
if (mode_i == vector_modes.length ())
break;
}
@@ -3791,13 +3807,14 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call,
/* When we selected a first vectorized epilogue, see if the target
suggests to have another one. */
+ masked_p = -1;
if (!unlimited_cost_model (loop)
&& !LOOP_VINFO_USING_PARTIAL_VECTORS_P (orig_loop_vinfo)
- && (orig_loop_vinfo->vector_costs->suggested_epilogue_mode ()
+ && (orig_loop_vinfo->vector_costs->suggested_epilogue_mode (masked_p)
!= VOIDmode))
{
vector_modes[0]
- = orig_loop_vinfo->vector_costs->suggested_epilogue_mode ();
+ = orig_loop_vinfo->vector_costs->suggested_epilogue_mode (masked_p);
cached_vf_per_mode[0] = 0;
mode_i = 0;
}
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 66a2964..ba06c5d 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -1714,7 +1714,7 @@ public:
unsigned int outside_cost () const;
unsigned int total_cost () const;
unsigned int suggested_unroll_factor () const;
- machine_mode suggested_epilogue_mode () const;
+ machine_mode suggested_epilogue_mode (int &masked) const;
protected:
unsigned int record_stmt_cost (stmt_vec_info, vect_cost_model_location,
@@ -1738,8 +1738,13 @@ protected:
unsigned int m_suggested_unroll_factor;
/* The suggested mode to be used for a vectorized epilogue or VOIDmode,
- determined at finish_cost. */
+ determined at finish_cost. m_masked_epilogue specifies whether the
+ epilogue should use masked vectorization, regardless of the
+ --param vect-partial-vector-usage default. If -1 then the
+ --param setting takes precedence. If the user explicitly specified
+ --param vect-partial-vector-usage then that takes precedence. */
machine_mode m_suggested_epilogue_mode;
+ int m_masked_epilogue;
/* True if finish_cost has been called. */
bool m_finished;
@@ -1755,6 +1760,7 @@ vector_costs::vector_costs (vec_info *vinfo, bool costing_for_scalar)
m_costs (),
m_suggested_unroll_factor(1),
m_suggested_epilogue_mode(VOIDmode),
+ m_masked_epilogue (-1),
m_finished (false)
{
}
@@ -1815,9 +1821,10 @@ vector_costs::suggested_unroll_factor () const
/* Return the suggested epilogue mode. */
inline machine_mode
-vector_costs::suggested_epilogue_mode () const
+vector_costs::suggested_epilogue_mode (int &masked_p) const
{
gcc_checking_assert (m_finished);
+ masked_p = m_masked_epilogue;
return m_suggested_epilogue_mode;
}
diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
index 2818ab3..1c423ff 100644
--- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
+++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
@@ -117,11 +117,11 @@ GLIBCXX_8.0 {
_ZN9__gnu_cxx3__818stdio_sync_filebufI[cw]NSt3__811char_traitsI[cw]EEE[5-9]*;
# debug mode
- _ZN11__gnu_debug19_Safe_sequence_base12_M_get_mutexEv;
- _ZN11__gnu_debug19_Safe_sequence_base13_M_detach_allEv;
- _ZN11__gnu_debug19_Safe_sequence_base18_M_detach_singularEv;
- _ZN11__gnu_debug19_Safe_sequence_base22_M_revalidate_singularEv;
- _ZN11__gnu_debug19_Safe_sequence_base7_M_swapERS0_;
+ _ZNK11__gnu_debug19_Safe_sequence_base12_M_get_mutexEv;
+ _ZNK11__gnu_debug19_Safe_sequence_base13_M_detach_allEv;
+ _ZNK11__gnu_debug19_Safe_sequence_base18_M_detach_singularEv;
+ _ZNK11__gnu_debug19_Safe_sequence_base22_M_revalidate_singularEv;
+ _ZNK11__gnu_debug19_Safe_sequence_base7_M_swapERKS0_;
_ZN11__gnu_debug19_Safe_iterator_base9_M_attach*;
_ZN11__gnu_debug19_Safe_iterator_base16_M_attach_single*;
@@ -136,11 +136,11 @@ GLIBCXX_8.0 {
# __gnu_debug::_Safe_unordered_container_base
# __gnu_debug::_Safe_local_iterator_base
- _ZN11__gnu_debug30_Safe_unordered_container_base7_M_swapERS0_;
- _ZN11__gnu_debug30_Safe_unordered_container_base13_M_detach_allEv;
- _ZN11__gnu_debug25_Safe_local_iterator_base9_M_attachEPNS_19_Safe_sequence_baseEb;
+ _ZNK11__gnu_debug30_Safe_unordered_container_base7_M_swapERKS0_;
+ _ZNK11__gnu_debug30_Safe_unordered_container_base13_M_detach_allEv;
+ _ZN11__gnu_debug25_Safe_local_iterator_base9_M_attachEPKNS_30_Safe_unordered_container_baseEb;
_ZN11__gnu_debug25_Safe_local_iterator_base9_M_detachEv;
- _ZN11__gnu_debug25_Safe_local_iterator_base16_M_attach_singleEPNS_19_Safe_sequence_baseEb;
+ _ZN11__gnu_debug25_Safe_local_iterator_base16_M_attach_singleEPKNS_30_Safe_unordered_container_baseEb;
# parallel mode
_ZN14__gnu_parallel9_Settings3getEv;
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 73b6f33..b5a89c3 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -2555,6 +2555,20 @@ GLIBCXX_3.4.35 {
_ZNSt8__detail17__wait_until_implEPKvRNS_16__wait_args_baseERKNSt6chrono8durationI[lx]St5ratioIL[lx]1EL[lx]1000000000EEEE;
_ZNSt8__detail11__wait_args22_M_load_proxy_wait_valEPKv;
+ # __gnu_debug::_Safe_iterator_base and _Safe_sequence_base const
+ _ZN11__gnu_debug19_Safe_iterator_base9_M_attachEPKNS_19_Safe_sequence_baseEb;
+ _ZN11__gnu_debug19_Safe_iterator_base16_M_attach_singleEPKNS_19_Safe_sequence_baseEb;
+ _ZNK11__gnu_debug19_Safe_sequence_base13_M_detach_allEv;
+ _ZNK11__gnu_debug19_Safe_sequence_base18_M_detach_singularEv;
+ _ZNK11__gnu_debug19_Safe_sequence_base12_M_get_mutexEv;
+ _ZNK11__gnu_debug19_Safe_sequence_base22_M_revalidate_singularEv;
+ _ZNK11__gnu_debug19_Safe_sequence_base7_M_swapERKS0_;
+
+ # __gnu_debug::_Safe_local_iterator_base and _Safe_unordered_container_base const
+ _ZN11__gnu_debug25_Safe_local_iterator_base9_M_attachEPKNS_30_Safe_unordered_container_baseEb;
+ _ZN11__gnu_debug25_Safe_local_iterator_base16_M_attach_singleEPKNS_30_Safe_unordered_container_baseEb;
+ _ZNK11__gnu_debug30_Safe_unordered_container_base13_M_detach_allEv;
+ _ZNK11__gnu_debug30_Safe_unordered_container_base7_M_swapERKS0_;
} GLIBCXX_3.4.34;
# Symbols in the support library (libsupc++) have their own tag.
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 64f8190..f1015ab 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1007,9 +1007,8 @@ ftms = {
ftms = {
name = mdspan;
- no_stdname = true; // FIXME: remove
values = {
- v = 1; // FIXME: 202207
+ v = 202207;
cxxmin = 23;
};
};
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 744246a..80f6586 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1126,8 +1126,9 @@
#if !defined(__cpp_lib_mdspan)
# if (__cplusplus >= 202100L)
-# define __glibcxx_mdspan 1L
+# define __glibcxx_mdspan 202207L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_mdspan)
+# define __cpp_lib_mdspan 202207L
# endif
# endif
#endif /* !defined(__cpp_lib_mdspan) && defined(__glibcxx_want_mdspan) */
diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque
index 59d60b2..ed69eb8 100644
--- a/libstdc++-v3/include/debug/deque
+++ b/libstdc++-v3/include/debug/deque
@@ -650,7 +650,8 @@ namespace __debug
else if (__first.base() == _Base::begin()
|| __last.base() == _Base::end())
{
- this->_M_detach_singular();
+ const deque* __this = this;
+ __this->_M_detach_singular();
for (_Base_const_iterator __position = __first.base();
__position != __last.base(); ++__position)
{
@@ -663,7 +664,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h
index d80e8a7..8aa84ad 100644
--- a/libstdc++-v3/include/debug/formatter.h
+++ b/libstdc++-v3/include/debug/formatter.h
@@ -96,7 +96,7 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence, typename _Category>
class _Safe_iterator;
- template<typename _Iterator, typename _Sequence>
+ template<typename _Iterator, typename _UContainer>
class _Safe_local_iterator;
template<typename _Sequence>
@@ -316,8 +316,8 @@ namespace __gnu_debug
}
}
- template<typename _Iterator, typename _Sequence>
- _Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it,
+ template<typename _Iterator, typename _UContainer>
+ _Parameter(_Safe_local_iterator<_Iterator, _UContainer> const& __it,
const char* __name, _Is_iterator)
: _M_kind(__iterator), _M_variant()
{
@@ -326,8 +326,8 @@ namespace __gnu_debug
_M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator);
_M_variant._M_iterator._M_constness =
__it._S_constant() ? __const_iterator : __mutable_iterator;
- _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
- _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
+ _M_variant._M_iterator._M_sequence = __it._M_get_ucontainer();
+ _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_UContainer);
if (__it._M_singular())
{
diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list
index 60a2542..9da7dda 100644
--- a/libstdc++-v3/include/debug/forward_list
+++ b/libstdc++-v3/include/debug/forward_list
@@ -58,44 +58,44 @@ namespace __gnu_debug
class _Safe_forward_list
: public _Safe_sequence<_SafeSequence>
{
- _SafeSequence&
- _M_this() noexcept
- { return *static_cast<_SafeSequence*>(this); }
+ const _SafeSequence*
+ _M_this() const noexcept
+ { return static_cast<const _SafeSequence*>(this); }
static void
- _M_swap_aux(_Safe_sequence_base& __lhs,
+ _S_swap_aux(const _Safe_forward_list& __lhs,
_Safe_iterator_base*& __lhs_iterators,
- _Safe_sequence_base& __rhs,
+ const _Safe_forward_list& __rhs,
_Safe_iterator_base*& __rhs_iterators);
- void _M_swap_single(_Safe_sequence_base&) noexcept;
+ void _M_swap_single(const _Safe_forward_list&) const noexcept;
protected:
void
- _M_invalidate_all()
+ _M_invalidate_all() const
{
- using _Base_const_iterator = __decltype(_M_this()._M_base().cend());
+ using _Base_const_iterator = __decltype(_M_this()->_M_base().cend());
this->_M_invalidate_if([this](_Base_const_iterator __it)
{
- return __it != _M_this()._M_base().cbefore_begin()
- && __it != _M_this()._M_base().cend(); });
+ return __it != _M_this()->_M_base().cbefore_begin()
+ && __it != _M_this()->_M_base().cend(); });
}
- void _M_swap(_Safe_sequence_base&) noexcept;
+ void
+ _M_swap(const _Safe_forward_list&) const noexcept;
};
template<typename _SafeSequence>
void
_Safe_forward_list<_SafeSequence>::
- _M_swap_aux(_Safe_sequence_base& __lhs,
+ _S_swap_aux(const _Safe_forward_list& __lhs,
_Safe_iterator_base*& __lhs_iterators,
- _Safe_sequence_base& __rhs,
+ const _Safe_forward_list& __rhs,
_Safe_iterator_base*& __rhs_iterators)
{
using const_iterator = typename _SafeSequence::const_iterator;
_Safe_iterator_base* __bbegin_its = 0;
_Safe_iterator_base* __last_bbegin = 0;
- _SafeSequence& __rseq = static_cast<_SafeSequence&>(__rhs);
for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
{
@@ -104,7 +104,7 @@ namespace __gnu_debug
const_iterator* __victim =
static_cast<const_iterator*>(__victim_base);
__iter = __iter->_M_next;
- if (__victim->base() == __rseq._M_base().cbefore_begin())
+ if (__victim->base() == __rhs._M_this()->_M_base().cbefore_begin())
{
__victim->_M_unlink();
if (__lhs_iterators == __victim_base)
@@ -136,21 +136,21 @@ namespace __gnu_debug
template<typename _SafeSequence>
void
_Safe_forward_list<_SafeSequence>::
- _M_swap_single(_Safe_sequence_base& __other) noexcept
+ _M_swap_single(const _Safe_forward_list& __other) const noexcept
{
- std::swap(_M_this()._M_iterators, __other._M_iterators);
- std::swap(_M_this()._M_const_iterators, __other._M_const_iterators);
+ std::swap(_M_this()->_M_iterators, __other._M_iterators);
+ std::swap(_M_this()->_M_const_iterators, __other._M_const_iterators);
// Useless, always 1 on forward_list
- //std::swap(_M_this()_M_version, __other._M_version);
- _Safe_iterator_base* __this_its = _M_this()._M_iterators;
- _M_swap_aux(__other, __other._M_iterators,
- _M_this(), _M_this()._M_iterators);
- _Safe_iterator_base* __this_const_its = _M_this()._M_const_iterators;
- _M_swap_aux(__other, __other._M_const_iterators,
- _M_this(), _M_this()._M_const_iterators);
- _M_swap_aux(_M_this(), __this_its,
+ //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);
+ _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,
__other, __other._M_iterators);
- _M_swap_aux(_M_this(), __this_const_its,
+ _S_swap_aux(*_M_this(), __this_const_its,
__other, __other._M_const_iterators);
}
@@ -159,13 +159,12 @@ namespace __gnu_debug
template<typename _SafeSequence>
void
_Safe_forward_list<_SafeSequence>::
- _M_swap(_Safe_sequence_base& __other) noexcept
+ _M_swap(const _Safe_forward_list& __other) const noexcept
{
// We need to lock both sequences to swap
using namespace __gnu_cxx;
- __mutex *__this_mutex = &_M_this()._M_get_mutex();
- __mutex *__other_mutex =
- &static_cast<_SafeSequence&>(__other)._M_get_mutex();
+ __mutex *__this_mutex = &_M_this()->_M_get_mutex();
+ __mutex *__other_mutex = &__other._M_get_mutex();
if (__this_mutex == __other_mutex)
{
__scoped_lock __lock(*__this_mutex);
@@ -565,7 +564,8 @@ namespace __debug
void
resize(size_type __sz)
{
- this->_M_detach_singular();
+ const forward_list* __this = this;
+ __this->_M_detach_singular();
// if __sz < size(), invalidate all iterators in [begin+__sz, end()
_Base_iterator __victim = _Base::begin();
@@ -585,7 +585,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
@@ -593,7 +593,8 @@ namespace __debug
void
resize(size_type __sz, const value_type& __val)
{
- this->_M_detach_singular();
+ const forward_list* __this = this;
+ __this->_M_detach_singular();
// if __sz < size(), invalidate all iterators in [begin+__sz, end())
_Base_iterator __victim = _Base::begin();
@@ -613,7 +614,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list
index a9d974c..c502c7c 100644
--- a/libstdc++-v3/include/debug/list
+++ b/libstdc++-v3/include/debug/list
@@ -321,7 +321,8 @@ namespace __debug
void
resize(size_type __sz)
{
- this->_M_detach_singular();
+ const list* __this = this;
+ __this->_M_detach_singular();
// if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
@@ -338,7 +339,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
@@ -346,7 +347,8 @@ namespace __debug
void
resize(size_type __sz, const _Tp& __c)
{
- this->_M_detach_singular();
+ const list* __this = this;
+ __this->_M_detach_singular();
// if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
@@ -363,7 +365,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
@@ -371,7 +373,8 @@ namespace __debug
void
resize(size_type __sz, _Tp __c = _Tp())
{
- this->_M_detach_singular();
+ const list* __this = this;
+ __this->_M_detach_singular();
// if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
@@ -388,7 +391,7 @@ namespace __debug
}
__catch(...)
{
- this->_M_revalidate_singular();
+ __this->_M_revalidate_singular();
__throw_exception_again;
}
}
diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h
index cf3f170..4462297 100644
--- a/libstdc++-v3/include/debug/safe_base.h
+++ b/libstdc++-v3/include/debug/safe_base.h
@@ -53,8 +53,10 @@ namespace __gnu_debug
public:
/** The sequence this iterator references; may be NULL to indicate
- a singular iterator. */
- _Safe_sequence_base* _M_sequence;
+ * a singular iterator. Stored as pointer-to-const because sequence
+ * could be declared as const.
+ */
+ const _Safe_sequence_base* _M_sequence;
/** The version number of this iterator. The sentinel value 0 is
* used to indicate an invalidated iterator (i.e., one that is
@@ -92,7 +94,7 @@ namespace __gnu_debug
: _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
{
if (!std::__is_constant_evaluated())
- this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant);
+ this->_M_attach(__seq, __constant);
}
/** Initializes the iterator to reference the same sequence that
@@ -115,7 +117,7 @@ namespace __gnu_debug
/** For use in _Safe_iterator. */
__gnu_cxx::__mutex&
- _M_get_mutex() throw ();
+ _M_get_mutex() _GLIBCXX_USE_NOEXCEPT;
/** Attaches this iterator to the given sequence, detaching it
* from whatever sequence it was attached to originally. If the
@@ -123,11 +125,12 @@ namespace __gnu_debug
* unattached.
*/
void
- _M_attach(_Safe_sequence_base* __seq, bool __constant);
+ _M_attach(const _Safe_sequence_base* __seq, bool __constant);
/** Likewise, but not thread-safe. */
void
- _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ();
+ _M_attach_single(const _Safe_sequence_base* __seq,
+ bool __constant) _GLIBCXX_USE_NOEXCEPT;
/** Detach the iterator for whatever sequence it is attached to,
* if any.
@@ -135,10 +138,23 @@ namespace __gnu_debug
void
_M_detach();
+#if !_GLIBCXX_INLINE_VERSION
+ private:
+ /***************************************************************/
+ /** Not-const method preserved for abi backward compatibility. */
+ void
+ _M_attach(_Safe_sequence_base* __seq, bool __constant);
+
+ void
+ _M_attach_single(_Safe_sequence_base* __seq,
+ bool __constant) _GLIBCXX_USE_NOEXCEPT;
+ /***************************************************************/
+#endif
+
public:
/** Likewise, but not thread-safe. */
void
- _M_detach_single() throw ();
+ _M_detach_single() _GLIBCXX_USE_NOEXCEPT;
/** Determines if we are attached to the given sequence. */
bool
@@ -147,13 +163,13 @@ namespace __gnu_debug
/** Is this iterator singular? */
_GLIBCXX_PURE bool
- _M_singular() const throw ();
+ _M_singular() const _GLIBCXX_USE_NOEXCEPT;
/** Can we compare this iterator to the given iterator @p __x?
Returns true if both iterators are nonsingular and reference
the same sequence. */
_GLIBCXX_PURE bool
- _M_can_compare(const _Safe_iterator_base& __x) const throw ();
+ _M_can_compare(const _Safe_iterator_base& __x) const _GLIBCXX_USE_NOEXCEPT;
/** Invalidate the iterator, making it singular. */
void
@@ -162,11 +178,11 @@ namespace __gnu_debug
/** Reset all member variables */
void
- _M_reset() throw ();
+ _M_reset() _GLIBCXX_USE_NOEXCEPT;
/** Unlink itself */
void
- _M_unlink() throw ()
+ _M_unlink() _GLIBCXX_USE_NOEXCEPT
{
if (_M_prior)
_M_prior->_M_next = _M_next;
@@ -246,14 +262,14 @@ namespace __gnu_debug
/** Detach all iterators, leaving them singular. */
void
- _M_detach_all();
+ _M_detach_all() const;
/** Detach all singular iterators.
* @post for all iterators i attached to this sequence,
* i->_M_version == _M_version.
*/
void
- _M_detach_singular();
+ _M_detach_singular() const;
/** Revalidates all attached singular iterators. This method may
* be used to validate iterators that were invalidated before
@@ -261,7 +277,7 @@ namespace __gnu_debug
* valid again).
*/
void
- _M_revalidate_singular();
+ _M_revalidate_singular() const;
/** Swap this sequence with the given sequence. This operation
* also swaps ownership of the iterators, so that when the
@@ -269,11 +285,11 @@ namespace __gnu_debug
* one container now reference the other container.
*/
void
- _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT;
+ _M_swap(const _Safe_sequence_base& __x) const _GLIBCXX_USE_NOEXCEPT;
/** For use in _Safe_sequence. */
__gnu_cxx::__mutex&
- _M_get_mutex() throw ();
+ _M_get_mutex() const _GLIBCXX_USE_NOEXCEPT;
/** Invalidates all iterators. */
void
@@ -281,21 +297,42 @@ namespace __gnu_debug
{ if (++_M_version == 0) _M_version = 1; }
private:
+#if !_GLIBCXX_INLINE_VERSION
+ /***************************************************************/
+ /** Not-const method preserved for abi backward compatibility. */
+ void
+ _M_detach_all();
+
+ void
+ _M_detach_singular();
+
+ void
+ _M_revalidate_singular();
+
+ void
+ _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT;
+
+ __gnu_cxx::__mutex&
+ _M_get_mutex() _GLIBCXX_USE_NOEXCEPT;
+ /***************************************************************/
+#endif
+
/** Attach an iterator to this sequence. */
void
- _M_attach(_Safe_iterator_base* __it, bool __constant);
+ _M_attach(_Safe_iterator_base* __it, bool __constant) const;
/** Likewise but not thread safe. */
void
- _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ();
+ _M_attach_single(_Safe_iterator_base* __it,
+ bool __constant) const _GLIBCXX_USE_NOEXCEPT;
/** Detach an iterator from this sequence */
void
- _M_detach(_Safe_iterator_base* __it);
+ _M_detach(_Safe_iterator_base* __it) const;
/** Likewise but not thread safe. */
void
- _M_detach_single(_Safe_iterator_base* __it) throw ();
+ _M_detach_single(_Safe_iterator_base* __it) const _GLIBCXX_USE_NOEXCEPT;
};
} // namespace __gnu_debug
diff --git a/libstdc++-v3/include/debug/safe_container.h b/libstdc++-v3/include/debug/safe_container.h
index cb1e69a..3341806 100644
--- a/libstdc++-v3/include/debug/safe_container.h
+++ b/libstdc++-v3/include/debug/safe_container.h
@@ -44,9 +44,9 @@ namespace __gnu_debug
typedef _SafeBase<_SafeContainer> _Base;
_GLIBCXX20_CONSTEXPR
- _SafeContainer&
- _M_cont() _GLIBCXX_NOEXCEPT
- { return *static_cast<_SafeContainer*>(this); }
+ const _SafeContainer&
+ _M_cont() const _GLIBCXX_NOEXCEPT
+ { return *static_cast<const _SafeContainer*>(this); }
protected:
#if __cplusplus >= 201103L
@@ -56,6 +56,11 @@ namespace __gnu_debug
private:
_GLIBCXX20_CONSTEXPR
+ void
+ _M_swap_base(const _Safe_container& __x) const noexcept
+ { _Base::_M_swap(__x); }
+
+ _GLIBCXX20_CONSTEXPR
_Safe_container(_Safe_container&& __x, const _Alloc&, std::true_type)
: _Safe_container(std::move(__x))
{ }
@@ -67,7 +72,7 @@ namespace __gnu_debug
if (!std::__is_constant_evaluated())
{
if (__x._M_cont().get_allocator() == __a)
- _Base::_M_swap(__x);
+ _M_swap_base(__x);
else
__x._M_invalidate_all();
}
@@ -115,12 +120,12 @@ namespace __gnu_debug
bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
|| _M_cont().get_allocator() == __x._M_cont().get_allocator();
if (__xfer_memory)
- _Base::_M_swap(__x);
+ _M_swap_base(__x);
else
this->_M_invalidate_all();
}
else
- _Base::_M_swap(__x);
+ _M_swap_base(__x);
__x._M_invalidate_all();
return *this;
@@ -128,7 +133,7 @@ namespace __gnu_debug
_GLIBCXX20_CONSTEXPR
void
- _M_swap(_Safe_container& __x) noexcept
+ _M_swap(const _Safe_container& __x) const noexcept
{
if (_IsCxx11AllocatorAware)
{
@@ -139,8 +144,12 @@ namespace __gnu_debug
__x._M_cont()._M_base());
}
- _Base::_M_swap(__x);
+ _M_swap_base(__x);
}
+#else
+ void
+ _M_swap(const _Safe_container& __x) const throw()
+ { _Base::_M_swap(__x); }
#endif
};
diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h
index 7c56338..e0b1b46 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -224,7 +224,7 @@ namespace __gnu_debug
_M_message(__msg_init_copy_singular)
._M_iterator(*this, "this")
._M_iterator(__x, "other"));
- _Safe_sequence_base* __seq = __x._M_sequence;
+ const _Safe_sequence_base* __seq = __x._M_sequence;
__x._M_detach();
std::swap(base(), __x.base());
_M_attach(__seq);
@@ -445,12 +445,12 @@ namespace __gnu_debug
/** Attach iterator to the given sequence. */
void
- _M_attach(_Safe_sequence_base* __seq)
+ _M_attach(const _Safe_sequence_base* __seq)
{ _Safe_base::_M_attach(__seq, _S_constant()); }
/** Likewise, but not thread-safe. */
void
- _M_attach_single(_Safe_sequence_base* __seq)
+ _M_attach_single(const _Safe_sequence_base* __seq)
{ _Safe_base::_M_attach_single(__seq, _S_constant()); }
/// Is the iterator dereferenceable?
@@ -500,7 +500,13 @@ namespace __gnu_debug
typename __gnu_cxx::__conditional_type<
_IsConstant::__value, const _Sequence*, _Sequence*>::__type
_M_get_sequence() const
- { return static_cast<_Sequence*>(_M_sequence); }
+ {
+ // Looks like not const-correct, but if _IsConstant the constness
+ // is restored when returning the sequence pointer and if not
+ // _IsConstant we are allowed to remove constness.
+ return static_cast<_Sequence*>
+ (const_cast<_Safe_sequence_base*>(_M_sequence));
+ }
// Get distance to __rhs.
typename _Distance_traits<_Iterator>::__type
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h
index c84f4f1..47b3a80 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.h
+++ b/libstdc++-v3/include/debug/safe_local_iterator.h
@@ -52,15 +52,15 @@ namespace __gnu_debug
/** \brief Safe iterator wrapper.
*
* The class template %_Safe_local_iterator is a wrapper around an
- * iterator that tracks the iterator's movement among sequences and
- * checks that operations performed on the "safe" iterator are
+ * iterator that tracks the iterator's movement among unordered containers
+ * and checks that operations performed on the "safe" iterator are
* legal. In additional to the basic iterator operations (which are
* validated, and then passed to the underlying iterator),
* %_Safe_local_iterator has member functions for iterator invalidation,
- * attaching/detaching the iterator from sequences, and querying
+ * attaching/detaching the iterator from unordered containers, and querying
* the iterator's state.
*/
- template<typename _Iterator, typename _Sequence>
+ template<typename _Iterator, typename _UContainer>
class _Safe_local_iterator
: private _Iterator
, public _Safe_local_iterator_base
@@ -68,28 +68,27 @@ namespace __gnu_debug
typedef _Iterator _Iter_base;
typedef _Safe_local_iterator_base _Safe_base;
- typedef typename _Sequence::size_type size_type;
+ typedef typename _UContainer::size_type size_type;
typedef std::iterator_traits<_Iterator> _Traits;
- typedef std::__are_same<
- typename _Sequence::_Base::const_local_iterator,
- _Iterator> _IsConstant;
+ using _IsConstant = std::__are_same<
+ typename _UContainer::_Base::const_local_iterator, _Iterator>;
- typedef typename __gnu_cxx::__conditional_type<_IsConstant::__value,
- typename _Sequence::_Base::local_iterator,
- typename _Sequence::_Base::const_local_iterator>::__type
- _OtherIterator;
+ using _OtherIterator = std::__conditional_t<
+ _IsConstant::__value,
+ typename _UContainer::_Base::local_iterator,
+ typename _UContainer::_Base::const_local_iterator>;
typedef _Safe_local_iterator _Self;
- typedef _Safe_local_iterator<_OtherIterator, _Sequence> _OtherSelf;
+ typedef _Safe_local_iterator<_OtherIterator, _UContainer> _OtherSelf;
struct _Unchecked { };
_Safe_local_iterator(const _Safe_local_iterator& __x,
_Unchecked) noexcept
: _Iter_base(__x.base())
- { _M_attach(__x._M_sequence); }
+ { _M_attach(__x._M_safe_container()); }
public:
typedef _Iterator iterator_type;
@@ -104,12 +103,13 @@ namespace __gnu_debug
/**
* @brief Safe iterator construction from an unsafe iterator and
- * its sequence.
+ * its unordered container.
*
- * @pre @p seq is not NULL
+ * @pre @p cont is not NULL
* @post this is not singular
*/
- _Safe_local_iterator(_Iterator __i, const _Safe_sequence_base* __cont)
+ _Safe_local_iterator(_Iterator __i,
+ const _Safe_unordered_container_base* __cont)
: _Iter_base(__i), _Safe_base(__cont, _S_constant())
{ }
@@ -126,7 +126,7 @@ namespace __gnu_debug
_M_message(__msg_init_copy_singular)
._M_iterator(*this, "this")
._M_iterator(__x, "other"));
- _M_attach(__x._M_sequence);
+ _M_attach(__x._M_safe_container());
}
/**
@@ -141,7 +141,7 @@ namespace __gnu_debug
_M_message(__msg_init_copy_singular)
._M_iterator(*this, "this")
._M_iterator(__x, "other"));
- auto __cont = __x._M_sequence;
+ auto __cont = __x._M_safe_container();
__x._M_detach();
std::swap(base(), __x.base());
_M_attach(__cont);
@@ -156,7 +156,7 @@ namespace __gnu_debug
const _Safe_local_iterator<_MutableIterator,
typename __gnu_cxx::__enable_if<_IsConstant::__value &&
std::__are_same<_MutableIterator, _OtherIterator>::__value,
- _Sequence>::__type>& __x) noexcept
+ _UContainer>::__type>& __x) noexcept
: _Iter_base(__x.base())
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -166,7 +166,7 @@ namespace __gnu_debug
_M_message(__msg_init_const_singular)
._M_iterator(*this, "this")
._M_iterator(__x, "other"));
- _M_attach(__x._M_sequence);
+ _M_attach(__x._M_safe_container());
}
/**
@@ -193,7 +193,7 @@ namespace __gnu_debug
{
_M_detach();
base() = __x.base();
- _M_attach(__x._M_sequence);
+ _M_attach(__x._M_safe_container());
}
return *this;
@@ -225,7 +225,7 @@ namespace __gnu_debug
{
_M_detach();
base() = __x.base();
- _M_attach(__x._M_sequence);
+ _M_attach(__x._M_safe_container());
}
__x._M_detach();
@@ -318,15 +318,15 @@ namespace __gnu_debug
*/
operator _Iterator() const { return *this; }
- /** Attach iterator to the given sequence. */
+ /** Attach iterator to the given unordered container. */
void
- _M_attach(_Safe_sequence_base* __seq)
- { _Safe_base::_M_attach(__seq, _S_constant()); }
+ _M_attach(const _Safe_unordered_container_base* __cont)
+ { _Safe_base::_M_attach(__cont, _S_constant()); }
/** Likewise, but not thread-safe. */
void
- _M_attach_single(_Safe_sequence_base* __seq)
- { _Safe_base::_M_attach_single(__seq, _S_constant()); }
+ _M_attach_single(const _Safe_unordered_container_base* __cont)
+ { _Safe_base::_M_attach_single(__cont, _S_constant()); }
/// Is the iterator dereferenceable?
bool
@@ -353,25 +353,31 @@ namespace __gnu_debug
typename _Distance_traits<_Iterator>::__type
_M_get_distance_to(const _Safe_local_iterator& __rhs) const;
- // The sequence this iterator references.
- typename __gnu_cxx::__conditional_type<
- _IsConstant::__value, const _Sequence*, _Sequence*>::__type
- _M_get_sequence() const
- { return static_cast<_Sequence*>(_M_sequence); }
+ // The unordered container this iterator references.
+ std::__conditional_t<
+ _IsConstant::__value, const _UContainer*, _UContainer*>
+ _M_get_ucontainer() const
+ {
+ // Looks like not const-correct, but if _IsConstant the constness
+ // is restored when returning the container pointer and if not
+ // _IsConstant we are allowed to remove constness.
+ return static_cast<_UContainer*>
+ (const_cast<_Safe_unordered_container_base*>(_M_safe_container()));
+ }
- /// Is this iterator equal to the sequence's begin(bucket) iterator?
+ /// Is this iterator equal to the container's begin(bucket) iterator?
bool _M_is_begin() const
- { return base() == _M_get_sequence()->_M_base().begin(bucket()); }
+ { return base() == _M_get_ucontainer()->_M_base().begin(bucket()); }
- /// Is this iterator equal to the sequence's end(bucket) iterator?
+ /// Is this iterator equal to the container's end(bucket) iterator?
bool _M_is_end() const
- { return base() == _M_get_sequence()->_M_base().end(bucket()); }
+ { return base() == _M_get_ucontainer()->_M_base().end(bucket()); }
/// Is this iterator part of the same bucket as the other one?
template<typename _Other>
bool
_M_in_same_bucket(const _Safe_local_iterator<_Other,
- _Sequence>& __other) const
+ _UContainer>& __other) const
{ return bucket() == __other.bucket(); }
friend inline bool
@@ -404,31 +410,31 @@ namespace __gnu_debug
};
/** Safe local iterators know how to check if they form a valid range. */
- template<typename _Iterator, typename _Sequence>
+ template<typename _Iterator, typename _UContainer>
inline bool
- __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
- const _Safe_local_iterator<_Iterator, _Sequence>& __last,
+ __valid_range(const _Safe_local_iterator<_Iterator, _UContainer>& __first,
+ const _Safe_local_iterator<_Iterator, _UContainer>& __last,
typename _Distance_traits<_Iterator>::__type& __dist_info)
{ return __first._M_valid_range(__last, __dist_info); }
- template<typename _Iterator, typename _Sequence>
+ template<typename _Iterator, typename _UContainer>
inline bool
- __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
- const _Safe_local_iterator<_Iterator, _Sequence>& __last)
+ __valid_range(const _Safe_local_iterator<_Iterator, _UContainer>& __first,
+ const _Safe_local_iterator<_Iterator, _UContainer>& __last)
{
typename _Distance_traits<_Iterator>::__type __dist_info;
return __first._M_valid_range(__last, __dist_info);
}
#if __cplusplus < 201103L
- template<typename _Iterator, typename _Sequence>
- struct _Unsafe_type<_Safe_local_iterator<_Iterator, _Sequence> >
+ template<typename _Iterator, typename _UContainer>
+ struct _Unsafe_type<_Safe_local_iterator<_Iterator, _UContainer> >
{ typedef _Iterator _Type; };
#endif
- template<typename _Iterator, typename _Sequence>
+ template<typename _Iterator, typename _UContainer>
inline _Iterator
- __unsafe(const _Safe_local_iterator<_Iterator, _Sequence>& __it)
+ __unsafe(const _Safe_local_iterator<_Iterator, _UContainer>& __it)
{ return __it.base(); }
} // namespace __gnu_debug
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.tcc b/libstdc++-v3/include/debug/safe_local_iterator.tcc
index 71e5320..10fec3f 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_local_iterator.tcc
@@ -44,7 +44,7 @@ namespace __gnu_debug
if (__rhs._M_is_end())
return
{
- _M_get_sequence()->bucket_size(bucket()),
+ _M_get_ucontainer()->bucket_size(bucket()),
__dp_exact
};
@@ -56,7 +56,7 @@ namespace __gnu_debug
if (__rhs._M_is_begin())
return
{
- -_M_get_sequence()->bucket_size(bucket()),
+ -_M_get_ucontainer()->bucket_size(bucket()),
__dp_exact
};
diff --git a/libstdc++-v3/include/debug/safe_sequence.h b/libstdc++-v3/include/debug/safe_sequence.h
index 6b35afa..e10474a 100644
--- a/libstdc++-v3/include/debug/safe_sequence.h
+++ b/libstdc++-v3/include/debug/safe_sequence.h
@@ -114,7 +114,7 @@ namespace __gnu_debug
in the safe ones. */
template<typename _Predicate>
void
- _M_invalidate_if(_Predicate __pred);
+ _M_invalidate_if(_Predicate __pred) const;
/** Transfers all iterators @c x that reference @c from sequence,
are not singular, and for which @c __pred(x) returns @c
@@ -122,7 +122,8 @@ namespace __gnu_debug
in the safe ones. */
template<typename _Predicate>
void
- _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred);
+ _M_transfer_from_if(const _Safe_sequence& __from,
+ _Predicate __pred) const;
};
/// Like _Safe_sequence but with a special _M_invalidate_all implementation
@@ -133,12 +134,12 @@ namespace __gnu_debug
{
protected:
void
- _M_invalidate_all()
+ _M_invalidate_all() const
{
typedef typename _Sequence::const_iterator _Const_iterator;
typedef typename _Const_iterator::iterator_type _Base_const_iterator;
typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
- const _Sequence& __seq = *static_cast<_Sequence*>(this);
+ const _Sequence& __seq = *static_cast<const _Sequence*>(this);
this->_M_invalidate_if(_Not_equal(__seq._M_base().end()));
}
};
diff --git a/libstdc++-v3/include/debug/safe_sequence.tcc b/libstdc++-v3/include/debug/safe_sequence.tcc
index 336bf2a..053361d 100644
--- a/libstdc++-v3/include/debug/safe_sequence.tcc
+++ b/libstdc++-v3/include/debug/safe_sequence.tcc
@@ -35,7 +35,7 @@ namespace __gnu_debug
template<typename _Predicate>
void
_Safe_sequence<_Sequence>::
- _M_invalidate_if(_Predicate __pred)
+ _M_invalidate_if(_Predicate __pred) const
{
typedef typename _Sequence::iterator iterator;
typedef typename _Sequence::const_iterator const_iterator;
@@ -66,7 +66,7 @@ namespace __gnu_debug
template<typename _Predicate>
void
_Safe_sequence<_Sequence>::
- _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred)
+ _M_transfer_from_if(const _Safe_sequence& __from, _Predicate __pred) const
{
if (this == std::__addressof(__from))
return;
@@ -104,7 +104,7 @@ namespace __gnu_debug
}
for (_Safe_iterator_base* __iter2 = __from._M_const_iterators;
- __iter2;)
+ __iter2;)
{
_Safe_iterator_base* __victim_base = __iter2;
const_iterator* __victim =
diff --git a/libstdc++-v3/include/debug/safe_unordered_base.h b/libstdc++-v3/include/debug/safe_unordered_base.h
index 1547f5b..55cf581 100644
--- a/libstdc++-v3/include/debug/safe_unordered_base.h
+++ b/libstdc++-v3/include/debug/safe_unordered_base.h
@@ -49,6 +49,10 @@ namespace __gnu_debug
*/
class _Safe_local_iterator_base : public _Safe_iterator_base
{
+ public:
+ const _Safe_unordered_container_base*
+ _M_safe_container() const noexcept;
+
protected:
/** Initializes the iterator and makes it singular. */
_Safe_local_iterator_base()
@@ -61,32 +65,32 @@ namespace __gnu_debug
* singular. Otherwise, the iterator will reference @p __seq and
* be nonsingular.
*/
- _Safe_local_iterator_base(const _Safe_sequence_base* __seq, bool __constant)
- { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); }
+ _Safe_local_iterator_base(const _Safe_unordered_container_base* __seq,
+ bool __constant)
+ { _M_attach(__seq, __constant); }
/** Initializes the iterator to reference the same container that
@p __x does. @p __constant is true if this is a constant
iterator, and false if it is mutable. */
_Safe_local_iterator_base(const _Safe_local_iterator_base& __x,
bool __constant)
- { this->_M_attach(__x._M_sequence, __constant); }
+ { this->_M_attach(__x._M_safe_container(), __constant); }
~_Safe_local_iterator_base() { this->_M_detach(); }
- _Safe_unordered_container_base*
- _M_get_container() const noexcept;
-
/** Attaches this iterator to the given container, detaching it
* from whatever container it was attached to originally. If the
* new container is the NULL pointer, the iterator is left
* unattached.
*/
void
- _M_attach(_Safe_sequence_base* __seq, bool __constant);
+ _M_attach(const _Safe_unordered_container_base* __cont,
+ bool __constant);
/** Likewise, but not thread-safe. */
void
- _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ();
+ _M_attach_single(const _Safe_unordered_container_base* __cont,
+ bool __constant) noexcept;
/** Detach the iterator for whatever container it is attached to,
* if any.
@@ -96,7 +100,19 @@ namespace __gnu_debug
/** Likewise, but not thread-safe. */
void
- _M_detach_single() throw ();
+ _M_detach_single() noexcept;
+
+#if !_GLIBCXX_INLINE_VERSION
+ private:
+ /***************************************************************/
+ /** Not-const method preserved for abi backward compatibility. */
+ void
+ _M_attach(_Safe_sequence_base* __seq, bool __constant);
+
+ void
+ _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept;
+ /***************************************************************/
+#endif
};
/**
@@ -124,10 +140,10 @@ namespace __gnu_debug
public:
/// The list of mutable local iterators that reference this container
- _Safe_iterator_base* _M_local_iterators;
+ mutable _Safe_iterator_base* _M_local_iterators;
/// The list of constant local iterators that reference this container
- _Safe_iterator_base* _M_const_local_iterators;
+ mutable _Safe_iterator_base* _M_const_local_iterators;
protected:
// Initialize with a version number of 1 and no iterators
@@ -153,7 +169,7 @@ namespace __gnu_debug
/** Detach all iterators, leaving them singular. */
void
- _M_detach_all();
+ _M_detach_all() const;
/** Swap this container with the given container. This operation
* also swaps ownership of the iterators, so that when the
@@ -161,25 +177,42 @@ namespace __gnu_debug
* one container now reference the other container.
*/
void
- _M_swap(_Safe_unordered_container_base& __x) noexcept;
+ _M_swap(const _Safe_unordered_container_base& __x) const noexcept;
private:
+#if !_GLIBCXX_INLINE_VERSION
+ /***************************************************************/
+ /** Not-const method preserved for abi backward compatibility. */
+ void
+ _M_detach_all();
+
+ void
+ _M_swap(_Safe_unordered_container_base& __x) noexcept;
+ /***************************************************************/
+#endif
+
/** Attach an iterator to this container. */
void
- _M_attach_local(_Safe_iterator_base* __it, bool __constant);
+ _M_attach_local(_Safe_iterator_base* __it, bool __constant) const;
/** Likewise but not thread safe. */
void
- _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ();
+ _M_attach_local_single(_Safe_iterator_base* __it,
+ bool __constant) const noexcept;
/** Detach an iterator from this container */
void
- _M_detach_local(_Safe_iterator_base* __it);
+ _M_detach_local(_Safe_iterator_base* __it) const;
/** Likewise but not thread safe. */
void
- _M_detach_local_single(_Safe_iterator_base* __it) throw ();
+ _M_detach_local_single(_Safe_iterator_base* __it) const noexcept;
};
+
+ inline const _Safe_unordered_container_base*
+ _Safe_local_iterator_base::
+ _M_safe_container() const noexcept
+ { return static_cast<const _Safe_unordered_container_base*>(_M_sequence); }
} // namespace __gnu_debug
#endif
diff --git a/libstdc++-v3/include/debug/safe_unordered_container.h b/libstdc++-v3/include/debug/safe_unordered_container.h
index 2ba27db..b67b7e0 100644
--- a/libstdc++-v3/include/debug/safe_unordered_container.h
+++ b/libstdc++-v3/include/debug/safe_unordered_container.h
@@ -62,6 +62,10 @@ namespace __gnu_debug
_M_cont() noexcept
{ return *static_cast<_Container*>(this); }
+ const _Safe_unordered_container*
+ _M_self() const
+ { return this; }
+
protected:
void
_M_invalidate_locals()
diff --git a/libstdc++-v3/include/debug/safe_unordered_container.tcc b/libstdc++-v3/include/debug/safe_unordered_container.tcc
index 6819389..0732e63 100644
--- a/libstdc++-v3/include/debug/safe_unordered_container.tcc
+++ b/libstdc++-v3/include/debug/safe_unordered_container.tcc
@@ -40,7 +40,7 @@ namespace __gnu_debug
typedef typename _Container::iterator iterator;
typedef typename _Container::const_iterator const_iterator;
- __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
+ __gnu_cxx::__scoped_lock sentry(_M_self()->_M_get_mutex());
for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
{
iterator* __victim = static_cast<iterator*>(__iter);
@@ -72,7 +72,7 @@ namespace __gnu_debug
typedef typename _Container::local_iterator local_iterator;
typedef typename _Container::const_local_iterator const_local_iterator;
- __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
+ __gnu_cxx::__scoped_lock sentry(_M_self()->_M_get_mutex());
for (_Safe_iterator_base* __iter = _M_local_iterators; __iter;)
{
local_iterator* __victim = static_cast<local_iterator*>(__iter);
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 5749aa1..d584b81 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -6030,13 +6030,13 @@ namespace __format
constexpr void
set_separator(basic_string_view<_CharT> __sep) noexcept
- requires (!_S_range_format_is_string)
+ requires (format_kind<_Rg> == range_format::sequence)
{ _M_under.set_separator(__sep); }
constexpr void
set_brackets(basic_string_view<_CharT> __open,
basic_string_view<_CharT> __close) noexcept
- requires (!_S_range_format_is_string)
+ requires (format_kind<_Rg> == range_format::sequence)
{ _M_under.set_brackets(__open, __close); }
// We deviate from standard, that declares this as template accepting
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index 4a06fb2..5d16de5 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -111,9 +111,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<size_t _OtherRank, typename _GetOtherExtent>
+ static constexpr bool
+ _S_is_compatible_extents(_GetOtherExtent __get_extent) noexcept
+ {
+ if constexpr (_OtherRank == _S_rank)
+ for (size_t __i = 0; __i < _S_rank; ++__i)
+ if (_Extents[__i] != dynamic_extent
+ && !cmp_equal(_Extents[__i], _S_int_cast(__get_extent(__i))))
+ return false;
+ return true;
+ }
+
+ template<size_t _OtherRank, typename _GetOtherExtent>
constexpr void
_M_init_dynamic_extents(_GetOtherExtent __get_extent) noexcept
{
+ __glibcxx_assert(_S_is_compatible_extents<_OtherRank>(__get_extent));
for (size_t __i = 0; __i < _S_rank_dynamic; ++__i)
{
size_t __di = __i;
@@ -385,13 +398,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__rev_prod(const _Extents& __exts, size_t __r) noexcept
{ return __exts_prod(__exts, __r + 1, __exts.rank()); }
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __size(const _Extents& __exts) noexcept
+ { return __fwd_prod(__exts, __exts.rank()); }
+
template<typename _IndexType, size_t... _Counts>
auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
-> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
-
- template<typename _Tp>
- consteval size_t
- __dynamic_extent() { return dynamic_extent; }
}
template<typename _IndexType, size_t _Rank>
@@ -401,7 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename... _Integrals>
requires (is_convertible_v<_Integrals, size_t> && ...)
explicit extents(_Integrals...) ->
- extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>;
+ extents<size_t, __detail::__maybe_static_ext<_Integrals>...>;
struct layout_left
{
@@ -441,6 +455,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_IndexType __mult = 1;
auto __update = [&, __pos = 0u](_IndexType __idx) mutable
{
+ _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, __exts.extent(__pos)));
__res += __idx * __mult;
__mult *= __exts.extent(__pos);
++__pos;
@@ -577,7 +592,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr index_type
required_span_size() const noexcept
- { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); }
+ { return __mdspan::__size(_M_extents); }
template<__mdspan::__valid_index_type<index_type>... _Indices>
requires (sizeof...(_Indices) == extents_type::rank())
@@ -651,6 +666,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto __update = [&, __pos = __exts.rank()](_IndexType) mutable
{
--__pos;
+ _GLIBCXX_DEBUG_ASSERT(cmp_less(__ind_arr[__pos],
+ __exts.extent(__pos)));
__res += __ind_arr[__pos] * __mult;
__mult *= __exts.extent(__pos);
};
@@ -714,7 +731,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr index_type
required_span_size() const noexcept
- { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); }
+ { return __mdspan::__size(_M_extents); }
template<__mdspan::__valid_index_type<index_type>... _Indices>
requires (sizeof...(_Indices) == extents_type::rank())
@@ -822,6 +839,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
auto __update = [&, __pos = 0u](_IndexType __idx) mutable
{
+ _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx,
+ __m.extents().extent(__pos)));
__res += __idx * __m.stride(__pos++);
};
(__update(__indices), ...);
@@ -968,8 +987,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if constexpr (!is_always_exhaustive())
{
- constexpr auto __rank = extents_type::rank();
- auto __size = __mdspan::__fwd_prod(_M_extents, __rank);
+ auto __size = __mdspan::__size(_M_extents);
if(__size > 0)
return __size == required_span_size();
}
@@ -1035,6 +1053,291 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __p + __i; }
};
+ namespace __mdspan
+ {
+ template<typename _Extents, typename _IndexType, size_t _Nm>
+ constexpr bool
+ __is_multi_index(const _Extents& __exts, span<_IndexType, _Nm> __indices)
+ {
+ static_assert(__exts.rank() == _Nm);
+ for (size_t __i = 0; __i < __exts.rank(); ++__i)
+ if (__indices[__i] >= __exts.extent(__i))
+ return false;
+ return true;
+ }
+ }
+
+ template<typename _ElementType, typename _Extents,
+ typename _LayoutPolicy = layout_right,
+ typename _AccessorPolicy = default_accessor<_ElementType>>
+ class mdspan
+ {
+ static_assert(!is_array_v<_ElementType>,
+ "ElementType must not be an array type");
+ static_assert(!is_abstract_v<_ElementType>,
+ "ElementType must not be an abstract class type");
+ static_assert(__mdspan::__is_extents<_Extents>,
+ "Extents must be a specialization of std::extents");
+ static_assert(is_same_v<_ElementType,
+ typename _AccessorPolicy::element_type>);
+
+ public:
+ using extents_type = _Extents;
+ using layout_type = _LayoutPolicy;
+ using accessor_type = _AccessorPolicy;
+ using mapping_type = typename layout_type::template mapping<extents_type>;
+ using element_type = _ElementType;
+ using value_type = remove_cv_t<element_type>;
+ using index_type = typename extents_type::index_type;
+ using size_type = typename extents_type::size_type;
+ using rank_type = typename extents_type::rank_type;
+ using data_handle_type = typename accessor_type::data_handle_type;
+ using reference = typename accessor_type::reference;
+
+ static constexpr rank_type
+ rank() noexcept { return extents_type::rank(); }
+
+ static constexpr rank_type
+ rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
+
+ static constexpr size_t
+ static_extent(rank_type __r) noexcept
+ { return extents_type::static_extent(__r); }
+
+ constexpr index_type
+ extent(rank_type __r) const noexcept { return extents().extent(__r); }
+
+ constexpr
+ mdspan()
+ requires (rank_dynamic() > 0)
+ && is_default_constructible_v<data_handle_type>
+ && is_default_constructible_v<mapping_type>
+ && is_default_constructible_v<accessor_type>
+ : _M_accessor(), _M_mapping(), _M_handle()
+ { }
+
+ constexpr
+ mdspan(const mdspan& __other) = default;
+
+ constexpr
+ mdspan(mdspan&& __other) = default;
+
+ template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
+ requires (sizeof...(_OIndexTypes) == rank()
+ || sizeof...(_OIndexTypes) == rank_dynamic())
+ && is_constructible_v<mapping_type, extents_type>
+ && is_default_constructible_v<accessor_type>
+ constexpr explicit
+ mdspan(data_handle_type __handle, _OIndexTypes... __exts)
+ : _M_accessor(),
+ _M_mapping(_Extents(static_cast<index_type>(std::move(__exts))...)),
+ _M_handle(std::move(__handle))
+ { }
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType,
+ size_t _Nm>
+ requires (_Nm == rank() || _Nm == rank_dynamic())
+ && is_constructible_v<mapping_type, extents_type>
+ && is_default_constructible_v<accessor_type>
+ constexpr explicit(_Nm != rank_dynamic())
+ mdspan(data_handle_type __handle, span<_OIndexType, _Nm> __exts)
+ : _M_accessor(), _M_mapping(extents_type(__exts)),
+ _M_handle(std::move(__handle))
+ { }
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType,
+ size_t _Nm>
+ requires (_Nm == rank() || _Nm == rank_dynamic())
+ && is_constructible_v<mapping_type, extents_type>
+ && is_default_constructible_v<accessor_type>
+ constexpr explicit(_Nm != rank_dynamic())
+ mdspan(data_handle_type __handle, const array<_OIndexType, _Nm>& __exts)
+ : _M_accessor(), _M_mapping(extents_type(__exts)),
+ _M_handle(std::move(__handle))
+ { }
+
+ constexpr
+ mdspan(data_handle_type __handle, const extents_type& __exts)
+ requires is_constructible_v<mapping_type, const extents_type&>
+ && is_default_constructible_v<accessor_type>
+ : _M_accessor(), _M_mapping(__exts), _M_handle(std::move(__handle))
+ { }
+
+ constexpr
+ mdspan(data_handle_type __handle, const mapping_type& __mapping)
+ requires is_default_constructible_v<accessor_type>
+ : _M_accessor(), _M_mapping(__mapping), _M_handle(std::move(__handle))
+ { }
+
+ constexpr
+ mdspan(data_handle_type __handle, const mapping_type& __mapping,
+ const accessor_type& __accessor)
+ : _M_accessor(__accessor), _M_mapping(__mapping),
+ _M_handle(std::move(__handle))
+ { }
+
+ template<typename _OElementType, typename _OExtents, typename _OLayout,
+ typename _OAccessor>
+ requires is_constructible_v<mapping_type,
+ const typename _OLayout::mapping<_OExtents>&>
+ && is_constructible_v<accessor_type, const _OAccessor&>
+ constexpr explicit(!is_convertible_v<
+ const typename _OLayout::mapping<_OExtents>&, mapping_type>
+ || !is_convertible_v<const _OAccessor&, accessor_type>)
+ mdspan(const mdspan<_OElementType, _OExtents, _OLayout, _OAccessor>&
+ __other)
+ : _M_accessor(__other.accessor()), _M_mapping(__other.mapping()),
+ _M_handle(__other.data_handle())
+ {
+ static_assert(is_constructible_v<data_handle_type,
+ const typename _OAccessor::data_handle_type&>);
+ static_assert(is_constructible_v<extents_type, _OExtents>);
+ }
+
+ constexpr mdspan&
+ operator=(const mdspan& __other) = default;
+
+ constexpr mdspan&
+ operator=(mdspan&& __other) = default;
+
+ template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
+ requires (sizeof...(_OIndexTypes) == rank())
+ constexpr reference
+ operator[](_OIndexTypes... __indices) const
+ {
+ auto __checked_call = [this](auto... __idxs) -> index_type
+ {
+ if constexpr (sizeof...(__idxs) > 0)
+ __glibcxx_assert(__mdspan::__is_multi_index(extents(),
+ span<const index_type, sizeof...(__idxs)>({__idxs...})));
+ return _M_mapping(__idxs...);
+ };
+
+ auto __index = __checked_call(
+ static_cast<index_type>(std::move(__indices))...);
+ return _M_accessor.access(_M_handle, __index);
+ }
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType>
+ constexpr reference
+ operator[](span<_OIndexType, rank()> __indices) const
+ {
+ auto __call = [&]<size_t... _Counts>(index_sequence<_Counts...>)
+ -> reference
+ { return (*this)[index_type(as_const(__indices[_Counts]))...]; };
+ return __call(make_index_sequence<rank()>());
+ }
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType>
+ constexpr reference
+ operator[](const array<_OIndexType, rank()>& __indices) const
+ { return (*this)[span<const _OIndexType, rank()>(__indices)]; }
+
+ constexpr size_type
+ size() const noexcept
+ {
+ __glibcxx_assert(cmp_less_equal(_M_mapping.required_span_size(),
+ numeric_limits<size_t>::max()));
+ return size_type(__mdspan::__size(extents()));
+ }
+
+ [[nodiscard]]
+ constexpr bool
+ empty() const noexcept
+ {
+ return __mdspan::__empty(extents());
+ }
+
+ friend constexpr void
+ swap(mdspan& __x, mdspan& __y) noexcept
+ {
+ using std::swap;
+ swap(__x._M_mapping, __y._M_mapping);
+ swap(__x._M_accessor, __y._M_accessor);
+ swap(__x._M_handle, __y._M_handle);
+ }
+
+ constexpr const extents_type&
+ extents() const noexcept { return _M_mapping.extents(); }
+
+ constexpr const data_handle_type&
+ data_handle() const noexcept { return _M_handle; }
+
+ constexpr const mapping_type&
+ mapping() const noexcept { return _M_mapping; }
+
+ constexpr const accessor_type&
+ accessor() const noexcept { return _M_accessor; }
+
+ static constexpr bool
+ is_always_unique() { return mapping_type::is_always_unique(); }
+
+ static constexpr bool
+ is_always_exhaustive() { return mapping_type::is_always_exhaustive(); }
+
+ static constexpr bool
+ is_always_strided() { return mapping_type::is_always_strided(); }
+
+ constexpr bool
+ is_unique() const { return _M_mapping.is_unique(); }
+
+ constexpr bool
+ is_exhaustive() const { return _M_mapping.is_exhaustive(); }
+
+ constexpr bool
+ is_strided() const { return _M_mapping. is_strided(); }
+
+ constexpr index_type
+ stride(rank_type __r) const { return _M_mapping.stride(__r); }
+
+ private:
+ [[no_unique_address]] accessor_type _M_accessor;
+ [[no_unique_address]] mapping_type _M_mapping;
+ [[no_unique_address]] data_handle_type _M_handle;
+ };
+
+ template<typename _CArray>
+ requires is_array_v<_CArray> && (rank_v<_CArray> == 1)
+ mdspan(_CArray&)
+ -> mdspan<remove_all_extents_t<_CArray>,
+ extents<size_t, extent_v<_CArray, 0>>>;
+
+ template<typename _Pointer>
+ requires is_pointer_v<remove_reference_t<_Pointer>>
+ mdspan(_Pointer&&)
+ -> mdspan<remove_pointer_t<remove_reference_t<_Pointer>>, extents<size_t>>;
+
+ template<typename _ElementType, typename... _Integrals>
+ requires (is_convertible_v<_Integrals, size_t> && ...)
+ && (sizeof...(_Integrals) > 0)
+ explicit mdspan(_ElementType*, _Integrals...)
+ -> mdspan<_ElementType,
+ extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>;
+
+ template<typename _ElementType, typename _OIndexType, size_t _Nm>
+ mdspan(_ElementType*, span<_OIndexType, _Nm>)
+ -> mdspan<_ElementType, dextents<size_t, _Nm>>;
+
+ template<typename _ElementType, typename _OIndexType, size_t _Nm>
+ mdspan(_ElementType*, const array<_OIndexType, _Nm>&)
+ -> mdspan<_ElementType, dextents<size_t, _Nm>>;
+
+ template<typename _ElementType, typename _IndexType, size_t... _ExtentsPack>
+ mdspan(_ElementType*, const extents<_IndexType, _ExtentsPack...>&)
+ -> mdspan<_ElementType, extents<_IndexType, _ExtentsPack...>>;
+
+ template<typename _ElementType, typename _MappingType>
+ mdspan(_ElementType*, const _MappingType&)
+ -> mdspan<_ElementType, typename _MappingType::extents_type,
+ typename _MappingType::layout_type>;
+
+ template<typename _MappingType, typename _AccessorType>
+ mdspan(const typename _AccessorType::data_handle_type&, const _MappingType&,
+ const _AccessorType&)
+ -> mdspan<typename _AccessorType::element_type,
+ typename _MappingType::extents_type,
+ typename _MappingType::layout_type, _AccessorType>;
+
_GLIBCXX_END_NAMESPACE_VERSION
}
#endif
diff --git a/libstdc++-v3/include/std/queue b/libstdc++-v3/include/std/queue
index 9052589..1b76088 100644
--- a/libstdc++-v3/include/std/queue
+++ b/libstdc++-v3/include/std/queue
@@ -105,7 +105,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return _M_f.format(__a.c, __fc); }
private:
- // Standard uses formatter<ref_view<_Container>, _CharT>.
+ // Standard uses formatter<ref_view<_Container>, _CharT>, but range_formatter
+ // provides same behavior.
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3881. Incorrect formatting of container adapters backed by std::string
range_formatter<_Tp, _CharT> _M_f;
};
@@ -136,7 +139,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return _M_f.format(__a.c, __fc); }
private:
- // Standard uses formatter<ref_view<_Container>, _CharT>.
+ // Standard uses formatter<ref_view<_Container>, _CharT>, but range_formatter
+ // provides same behavior.
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3881. Incorrect formatting of container adapters backed by std::string
range_formatter<_Tp, _CharT> _M_f;
};
diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
index 49ab910..5629a71 100644
--- a/libstdc++-v3/include/std/span
+++ b/libstdc++-v3/include/std/span
@@ -476,6 +476,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
// deduction guides
+ namespace __detail
+ {
+ template<typename _Tp>
+ concept __integral_constant_like = is_integral_v<decltype(_Tp::value)>
+ && !is_same_v<bool, remove_const_t<decltype(_Tp::value)>>
+ && convertible_to<_Tp, decltype(_Tp::value)>
+ && equality_comparable_with<_Tp, decltype(_Tp::value)>
+ && bool_constant<_Tp() == _Tp::value>::value
+ && bool_constant<static_cast<decltype(_Tp::value)>(_Tp()) == _Tp::value>
+ ::value;
+
+ template<typename _Tp>
+ constexpr size_t __maybe_static_ext = dynamic_extent;
+
+ template<__integral_constant_like _Tp>
+ constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value};
+ }
template<typename _Type, size_t _ArrayExtent>
span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>;
@@ -489,7 +506,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<contiguous_iterator _Iter, typename _End>
span(_Iter, _End)
- -> span<remove_reference_t<iter_reference_t<_Iter>>>;
+ -> span<remove_reference_t<iter_reference_t<_Iter>>,
+ __detail::__maybe_static_ext<_End>>;
template<ranges::contiguous_range _Range>
span(_Range &&)
diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc
index 3533b5e..c6f6ef7 100644
--- a/libstdc++-v3/src/c++11/debug.cc
+++ b/libstdc++-v3/src/c++11/debug.cc
@@ -54,7 +54,7 @@ namespace
* in order to limit contention without breaking current library binary
* compatibility. */
__gnu_cxx::__mutex&
- get_safe_base_mutex(void* address)
+ get_safe_base_mutex(const void* address)
{
// Use arbitrarily __gnu_debug::vector<int> as the container giving
// alignment of debug containers.
@@ -70,9 +70,9 @@ namespace
#pragma GCC diagnostic warning "-Wabi=6"
void
- swap_its(__gnu_debug::_Safe_sequence_base& __lhs,
+ swap_its(const __gnu_debug::_Safe_sequence_base& __lhs,
__gnu_debug::_Safe_iterator_base*& __lhs_its,
- __gnu_debug::_Safe_sequence_base& __rhs,
+ const __gnu_debug::_Safe_sequence_base& __rhs,
__gnu_debug::_Safe_iterator_base*& __rhs_its)
{
swap(__lhs_its, __rhs_its);
@@ -84,8 +84,8 @@ namespace
}
void
- swap_seq_single(__gnu_debug::_Safe_sequence_base& __lhs,
- __gnu_debug::_Safe_sequence_base& __rhs)
+ swap_seq_single(const __gnu_debug::_Safe_sequence_base& __lhs,
+ const __gnu_debug::_Safe_sequence_base& __rhs)
{
swap(__lhs._M_version, __rhs._M_version);
swap_its(__lhs, __lhs._M_iterators,
@@ -118,17 +118,17 @@ namespace
void
swap_seq(__gnu_cxx::__mutex& lhs_mutex,
- __gnu_debug::_Safe_sequence_base& lhs,
+ const __gnu_debug::_Safe_sequence_base& lhs,
__gnu_cxx::__mutex& rhs_mutex,
- __gnu_debug::_Safe_sequence_base& rhs)
+ const __gnu_debug::_Safe_sequence_base& rhs)
{
lock_and_run(lhs_mutex, rhs_mutex,
[&lhs, &rhs]() { swap_seq_single(lhs, rhs); });
}
void
- swap_ucont_single(__gnu_debug::_Safe_unordered_container_base& __lhs,
- __gnu_debug::_Safe_unordered_container_base& __rhs)
+ swap_ucont_single(const __gnu_debug::_Safe_unordered_container_base& __lhs,
+ const __gnu_debug::_Safe_unordered_container_base& __rhs)
{
swap_seq_single(__lhs, __rhs);
swap_its(__lhs, __lhs._M_local_iterators,
@@ -139,9 +139,9 @@ namespace
void
swap_ucont(__gnu_cxx::__mutex& lhs_mutex,
- __gnu_debug::_Safe_unordered_container_base& lhs,
+ const __gnu_debug::_Safe_unordered_container_base& lhs,
__gnu_cxx::__mutex& rhs_mutex,
- __gnu_debug::_Safe_unordered_container_base& rhs)
+ const __gnu_debug::_Safe_unordered_container_base& rhs)
{
lock_and_run(lhs_mutex, rhs_mutex,
[&lhs, &rhs]() { swap_ucont_single(lhs, rhs); });
@@ -158,8 +158,8 @@ namespace
}
}
- void*
- acquire_sequence_ptr_for_lock(__gnu_debug::_Safe_sequence_base*& seq)
+ const void*
+ acquire_sequence_ptr_for_lock(__gnu_debug::_Safe_sequence_base const*& seq)
{
#ifdef __GTHREADS
if (!__gnu_cxx::__is_single_threaded())
@@ -169,7 +169,7 @@ namespace
}
void
- reset_sequence_ptr(__gnu_debug::_Safe_sequence_base*& seq)
+ reset_sequence_ptr(__gnu_debug::_Safe_sequence_base const*& seq)
{
#ifdef __GTHREADS
if (!__gnu_cxx::__is_single_threaded())
@@ -327,7 +327,7 @@ namespace __gnu_debug
void
_Safe_sequence_base::
- _M_detach_all()
+ _M_detach_all() const
{
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
detach_all(_M_iterators);
@@ -339,7 +339,7 @@ namespace __gnu_debug
void
_Safe_sequence_base::
- _M_detach_singular()
+ _M_detach_singular() const
{
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
@@ -361,7 +361,7 @@ namespace __gnu_debug
void
_Safe_sequence_base::
- _M_revalidate_singular()
+ _M_revalidate_singular() const
{
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
for (_Safe_iterator_base* __iter = _M_iterators; __iter;
@@ -375,17 +375,59 @@ namespace __gnu_debug
void
_Safe_sequence_base::
- _M_swap(_Safe_sequence_base& __x) noexcept
+ _M_swap(const _Safe_sequence_base& __x) const noexcept
{ swap_seq(_M_get_mutex(), *this, __x._M_get_mutex(), __x); }
__gnu_cxx::__mutex&
_Safe_sequence_base::
- _M_get_mutex() noexcept
+ _M_get_mutex() const noexcept
{ return get_safe_base_mutex(this); }
+#if !_GLIBCXX_INLINE_VERSION
+ void
+ _Safe_sequence_base::
+ _M_detach_all()
+ {
+ const _Safe_sequence_base* __this = this;
+ __this->_M_detach_all();
+ }
+
+ void
+ _Safe_sequence_base::
+ _M_detach_singular()
+ {
+ const _Safe_sequence_base* __this = this;
+ __this->_M_detach_singular();
+ }
+
+ void
+ _Safe_sequence_base::
+ _M_revalidate_singular()
+ {
+ const _Safe_sequence_base* __this = this;
+ __this->_M_revalidate_singular();
+ }
+
void
_Safe_sequence_base::
- _M_attach(_Safe_iterator_base* __it, bool __constant)
+ _M_swap(_Safe_sequence_base& __x) noexcept
+ {
+ const _Safe_sequence_base* __this = this;
+ __this->_M_swap(__x);
+ }
+
+ __gnu_cxx::__mutex&
+ _Safe_sequence_base::
+ _M_get_mutex() noexcept
+ {
+ const _Safe_sequence_base* __this = this;
+ return __this->_M_get_mutex();
+ }
+#endif
+
+ void
+ _Safe_sequence_base::
+ _M_attach(_Safe_iterator_base* __it, bool __constant) const
{
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
_M_attach_single(__it, __constant);
@@ -393,7 +435,7 @@ namespace __gnu_debug
void
_Safe_sequence_base::
- _M_attach_single(_Safe_iterator_base* __it, bool __constant) noexcept
+ _M_attach_single(_Safe_iterator_base* __it, bool __constant) const noexcept
{
_Safe_iterator_base*& __its =
__constant ? _M_const_iterators : _M_iterators;
@@ -405,7 +447,7 @@ namespace __gnu_debug
void
_Safe_sequence_base::
- _M_detach(_Safe_iterator_base* __it)
+ _M_detach(_Safe_iterator_base* __it) const
{
// Remove __it from this sequence's list
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
@@ -414,7 +456,7 @@ namespace __gnu_debug
void
_Safe_sequence_base::
- _M_detach_single(_Safe_iterator_base* __it) noexcept
+ _M_detach_single(_Safe_iterator_base* __it) const noexcept
{
// Remove __it from this sequence's list
__it->_M_unlink();
@@ -426,7 +468,7 @@ namespace __gnu_debug
void
_Safe_iterator_base::
- _M_attach(_Safe_sequence_base* __seq, bool __constant)
+ _M_attach(const _Safe_sequence_base* __seq, bool __constant)
{
_M_detach();
@@ -443,7 +485,7 @@ namespace __gnu_debug
void
_Safe_iterator_base::
- _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept
+ _M_attach_single(const _Safe_sequence_base* __seq, bool __constant) noexcept
{
_M_detach_single();
@@ -514,14 +556,27 @@ namespace __gnu_debug
_M_get_mutex() noexcept
{ return _M_sequence->_M_get_mutex(); }
- _Safe_unordered_container_base*
- _Safe_local_iterator_base::
- _M_get_container() const noexcept
- { return static_cast<_Safe_unordered_container_base*>(_M_sequence); }
+#if !_GLIBCXX_INLINE_VERSION
+ void
+ _Safe_iterator_base::
+ _M_attach(_Safe_sequence_base* __seq, bool __constant)
+ {
+ const _Safe_sequence_base* __cseq = __seq;
+ _M_attach(__cseq, __constant);
+ }
+
+ void
+ _Safe_iterator_base::
+ _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept
+ {
+ const _Safe_sequence_base* __cseq = __seq;
+ _M_attach_single(__cseq, __constant);
+ }
+#endif
void
_Safe_local_iterator_base::
- _M_attach(_Safe_sequence_base* __cont, bool __constant)
+ _M_attach(const _Safe_unordered_container_base* __cont, bool __constant)
{
_M_detach();
@@ -530,7 +585,7 @@ namespace __gnu_debug
{
_M_sequence = __cont;
_M_version = _M_sequence->_M_version;
- _M_get_container()->_M_attach_local(this, __constant);
+ _M_safe_container()->_M_attach_local(this, __constant);
}
else
_M_version = 0;
@@ -538,7 +593,8 @@ namespace __gnu_debug
void
_Safe_local_iterator_base::
- _M_attach_single(_Safe_sequence_base* __cont, bool __constant) noexcept
+ _M_attach_single(const _Safe_unordered_container_base* __cont,
+ bool __constant) noexcept
{
_M_detach_single();
@@ -547,7 +603,7 @@ namespace __gnu_debug
{
_M_sequence = __cont;
_M_version = _M_sequence->_M_version;
- _M_get_container()->_M_attach_local_single(this, __constant);
+ _M_safe_container()->_M_attach_local_single(this, __constant);
}
else
_M_version = 0;
@@ -570,14 +626,34 @@ namespace __gnu_debug
{
if (_M_sequence)
{
- _M_get_container()->_M_detach_local_single(this);
+ _M_safe_container()->_M_detach_local_single(this);
_M_reset();
}
}
+#if !_GLIBCXX_INLINE_VERSION
+ void
+ _Safe_local_iterator_base::
+ _M_attach(_Safe_sequence_base* __seq, bool __constant)
+ {
+ const _Safe_unordered_container_base* __cont
+ = static_cast<_Safe_unordered_container_base*>(__seq);
+ _M_attach(__cont, __constant);
+ }
+
+ void
+ _Safe_local_iterator_base::
+ _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept
+ {
+ const _Safe_unordered_container_base* __cont
+ = static_cast<_Safe_unordered_container_base*>(__seq);
+ _M_attach_single(__cont, __constant);
+ }
+#endif
+
void
_Safe_unordered_container_base::
- _M_detach_all()
+ _M_detach_all() const
{
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
detach_all(_M_iterators);
@@ -595,12 +671,12 @@ namespace __gnu_debug
void
_Safe_unordered_container_base::
- _M_swap(_Safe_unordered_container_base& __x) noexcept
+ _M_swap(const _Safe_unordered_container_base& __x) const noexcept
{ swap_ucont(_M_get_mutex(), *this, __x._M_get_mutex(), __x); }
void
_Safe_unordered_container_base::
- _M_attach_local(_Safe_iterator_base* __it, bool __constant)
+ _M_attach_local(_Safe_iterator_base* __it, bool __constant) const
{
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
_M_attach_local_single(__it, __constant);
@@ -608,7 +684,7 @@ namespace __gnu_debug
void
_Safe_unordered_container_base::
- _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) noexcept
+ _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) const noexcept
{
_Safe_iterator_base*& __its =
__constant ? _M_const_local_iterators : _M_local_iterators;
@@ -620,7 +696,7 @@ namespace __gnu_debug
void
_Safe_unordered_container_base::
- _M_detach_local(_Safe_iterator_base* __it)
+ _M_detach_local(_Safe_iterator_base* __it) const
{
// Remove __it from this container's list
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
@@ -629,7 +705,7 @@ namespace __gnu_debug
void
_Safe_unordered_container_base::
- _M_detach_local_single(_Safe_iterator_base* __it) noexcept
+ _M_detach_local_single(_Safe_iterator_base* __it) const noexcept
{
// Remove __it from this container's list
__it->_M_unlink();
@@ -638,6 +714,24 @@ namespace __gnu_debug
if (_M_local_iterators == __it)
_M_local_iterators = __it->_M_next;
}
+
+#if !_GLIBCXX_INLINE_VERSION
+ void
+ _Safe_unordered_container_base::
+ _M_detach_all()
+ {
+ const _Safe_unordered_container_base* __this = this;
+ __this->_M_detach_all();
+ }
+
+ void
+ _Safe_unordered_container_base::
+ _M_swap(_Safe_unordered_container_base& __x) noexcept
+ {
+ const _Safe_unordered_container_base* __this = this;
+ __this->_M_swap(__x);
+ }
+#endif
}
namespace
diff --git a/libstdc++-v3/src/c++17/memory_resource.cc b/libstdc++-v3/src/c++17/memory_resource.cc
index fac4c78..fddfe2c 100644
--- a/libstdc++-v3/src/c++17/memory_resource.cc
+++ b/libstdc++-v3/src/c++17/memory_resource.cc
@@ -1242,12 +1242,30 @@ namespace pmr
return pools;
}
+ static inline size_t
+ choose_block_size(size_t bytes, size_t alignment)
+ {
+ if (bytes == 0) [[unlikely]]
+ return alignment;
+
+ // Use bit_ceil in case alignment is invalid (i.e. not a power of two).
+ size_t mask = std::__bit_ceil(alignment) - 1;
+ // Round up to a multiple of alignment.
+ size_t block_size = (bytes + mask) & ~mask;
+
+ if (block_size >= bytes) [[likely]]
+ return block_size;
+
+ // Wrapped around to zero, bytes must have been impossibly large.
+ return numeric_limits<size_t>::max();
+ }
+
// Override for memory_resource::do_allocate
void*
synchronized_pool_resource::
do_allocate(size_t bytes, size_t alignment)
{
- const auto block_size = std::max(bytes, alignment);
+ const auto block_size = choose_block_size(bytes, alignment);
const pool_options opts = _M_impl._M_opts;
if (block_size <= opts.largest_required_pool_block)
{
@@ -1294,7 +1312,7 @@ namespace pmr
synchronized_pool_resource::
do_deallocate(void* p, size_t bytes, size_t alignment)
{
- size_t block_size = std::max(bytes, alignment);
+ size_t block_size = choose_block_size(bytes, alignment);
if (block_size <= _M_impl._M_opts.largest_required_pool_block)
{
const ptrdiff_t index = pool_index(block_size, _M_impl._M_npools);
@@ -1453,7 +1471,7 @@ namespace pmr
void*
unsynchronized_pool_resource::do_allocate(size_t bytes, size_t alignment)
{
- const auto block_size = std::max(bytes, alignment);
+ const auto block_size = choose_block_size(bytes, alignment);
if (block_size <= _M_impl._M_opts.largest_required_pool_block)
{
// Recreate pools if release() has been called:
@@ -1470,7 +1488,7 @@ namespace pmr
unsynchronized_pool_resource::
do_deallocate(void* p, size_t bytes, size_t alignment)
{
- size_t block_size = std::max(bytes, alignment);
+ size_t block_size = choose_block_size(bytes, alignment);
if (block_size <= _M_impl._M_opts.largest_required_pool_block)
{
if (auto pool = _M_find_pool(block_size))
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index 86e6d88..dd05a83 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -1846,7 +1846,8 @@ export namespace std
using std::layout_right;
using std::layout_stride;
using std::default_accessor;
- // FIXME layout_left_padded, layout_right_padded, aligned_accessor and mdspan
+ using std::mdspan;
+ // FIXME layout_left_padded, layout_right_padded, aligned_accessor, mdsubspan
}
#endif
diff --git a/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc
new file mode 100644
index 0000000..6d7434f
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc
@@ -0,0 +1,5 @@
+// { dg-do run { target c++17 } }
+// Bug 118681 - unsynchronized_pool_resource may fail to respect alignment
+
+#define RESOURCE std::pmr::synchronized_pool_resource
+#include "../unsynchronized_pool_resource/118681.cc"
diff --git a/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc
new file mode 100644
index 0000000..87e1b1d
--- /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(p2, size, alignment);
+ res.deallocate(p2, size, alignment);
+ }
+ }
+ }
+}
+
+int main()
+{
+ RESOURCE res;
+ test_alignment(res, true);
+ res.release();
+ test_alignment(res, false);
+ res.release();
+
+ VERIFY( ! any_misaligned );
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/class_mandate_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/class_mandate_neg.cc
new file mode 100644
index 0000000..de19b6d
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/class_mandate_neg.cc
@@ -0,0 +1,41 @@
+// { dg-do compile { target c++23 } }
+#include<mdspan>
+
+#include <cstdint>
+#include "layout_like.h"
+
+struct ExtentsLike
+{
+ using index_type = int;
+ using size_type = unsigned int;
+ using rank_type = size_t;
+
+ static constexpr size_t rank() { return 1; }
+ static constexpr size_t rank_dynamic() { return 0; }
+};
+
+constexpr bool
+test_custom_extents_type()
+{
+ std::mdspan<double, ExtentsLike> md1; // { dg-error "required from here" }
+ return true;
+}
+static_assert(test_custom_extents_type());
+
+constexpr bool
+test_element_type_mismatch()
+{
+ using E = std::extents<int, 1>;
+ using L = std::layout_right;
+ using A = std::default_accessor<double>;
+
+ [[maybe_unused]] std::mdspan<float, E, L, A> md2; // { dg-error "required from here" }
+ return true;
+};
+static_assert(test_element_type_mismatch());
+
+// { dg-prune-output "Extents must be a specialization of std::extents" }
+// { dg-prune-output "no type named '_S_storage'" }
+// { dg-prune-output "non-constant condition" }
+// { dg-prune-output "static assertion failed" }
+// { dg-prune-output "__glibcxx_assert" }
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc
index f9c1c01..67d18fe 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc
@@ -7,6 +7,8 @@ std::extents<uint8_t, size_t(1) << 9> e1; // { dg-error "from here" }
std::extents<char, 1> e2; // { dg-error "from here" }
std::extents<bool, 1> e3; // { dg-error "from here" }
std::extents<double, 1> e4; // { dg-error "from here" }
+
// { dg-prune-output "dynamic or representable as IndexType" }
// { dg-prune-output "signed or unsigned integer" }
// { dg-prune-output "invalid use of incomplete type" }
+// { dg-prune-output "non-constant condition for static assertion" }
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
index 2907ad1..404755b 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
@@ -2,38 +2,13 @@
#include <mdspan>
#include <testsuite_hooks.h>
+#include "int_like.h"
// Test construction from a custom integer-like object, that has
// no copy/move ctor or copy/move assignment operator.
constexpr size_t dyn = std::dynamic_extent;
-class IntLike
-{
-public:
- explicit
- IntLike(int i)
- : _M_i(i)
- { }
-
- IntLike() = delete;
- IntLike(const IntLike&) = delete;
- IntLike(IntLike&&) = delete;
-
- const IntLike&
- operator=(const IntLike&) = delete;
-
- const IntLike&
- operator=(IntLike&&) = delete;
-
- constexpr
- operator int() const noexcept
- { return _M_i; }
-
-private:
- int _M_i;
-};
-
static_assert(std::is_convertible_v<IntLike, int>);
static_assert(std::is_nothrow_constructible_v<int, IntLike>);
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc
new file mode 100644
index 0000000..b35e531
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++23 } }
+#include<mdspan>
+
+#include <cstdint>
+
+constexpr size_t dyn = std::dynamic_extent;
+
+constexpr bool
+test_dyn2sta_extents_mismatch_00()
+{
+ auto e0 = std::extents<int, dyn>{1};
+ [[maybe_unused]] auto e1 = std::extents<int, 2>{e0}; // { dg-error "expansion of" }
+ return true;
+}
+static_assert(test_dyn2sta_extents_mismatch_00()); // { dg-error "expansion of" }
+
+constexpr bool
+test_dyn2sta_extents_mismatch_01()
+{
+ [[maybe_unused]] auto e = std::extents<int, 1, dyn>{2, 2}; // { dg-error "expansion of" }
+ return true;
+}
+static_assert(test_dyn2sta_extents_mismatch_01()); // { dg-error "expansion of" }
+
+constexpr bool
+test_dyn2sta_extents_mismatch_02()
+{
+ std::array<int, 2> exts{2, 2};
+ [[maybe_unused]] auto e = std::extents<int, 1, dyn>{exts}; // { dg-error "expansion of" }
+ return true;
+}
+static_assert(test_dyn2sta_extents_mismatch_02()); // { dg-error "expansion of" }
+
+// { dg-prune-output "non-constant condition for static assertion" }
+// { dg-prune-output "__glibcxx_assert" }
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h b/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h
new file mode 100644
index 0000000..f39f4cc
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h
@@ -0,0 +1,30 @@
+#ifndef TEST_MDSPAN_INT_LIKE_H
+#define TEST_MDSPAN_INT_LIKE_H
+
+class IntLike
+{
+public:
+ explicit
+ IntLike(int i)
+ : _M_i(i)
+ { }
+
+ IntLike() = delete;
+ IntLike(const IntLike&) = delete;
+ IntLike(IntLike&&) = delete;
+
+ const IntLike&
+ operator=(const IntLike&) = delete;
+
+ const IntLike&
+ operator=(IntLike&&) = delete;
+
+ constexpr
+ operator int() const noexcept
+ { return _M_i; }
+
+private:
+ int _M_i;
+};
+
+#endif // TEST_MDSPAN_INT_LIKE_H
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
index e71fdc5..bca8901 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
@@ -98,12 +98,32 @@ test_deduction(Extents... exts)
}
constexpr bool
+test_integral_constant_deduction()
+{
+ auto verify = [](auto actual, auto expected)
+ {
+ static_assert(std::same_as<decltype(actual), decltype(expected)>);
+ VERIFY(actual == expected);
+ };
+
+ constexpr auto c1 = std::integral_constant<size_t, 1>{};
+ constexpr auto c2 = std::integral_constant<int, 2>{};
+
+ verify(std::extents(1), std::extents<size_t, dyn>{1});
+ verify(std::extents(c1), std::extents<size_t, 1>{});
+ verify(std::extents(c2), std::extents<size_t, 2>{});
+ verify(std::extents(c1, 2), std::extents<size_t, 1, dyn>{2});
+ return true;
+}
+
+constexpr bool
test_deduction_all()
{
test_deduction<0>();
test_deduction<1>(1);
test_deduction<2>(1.0, 2.0f);
test_deduction<3>(int(1), short(2), size_t(3));
+ test_integral_constant_deduction();
return true;
}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h b/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h
new file mode 100644
index 0000000..6a0f8ca
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h
@@ -0,0 +1,83 @@
+#ifndef TEST_MDSPAN_LAYOUT_LIKE_H
+#define TEST_MDSPAN_LAYOUT_LIKE_H 1
+
+struct LayoutLike
+{
+ template<typename Extents>
+ class mapping
+ {
+ public:
+ using extents_type = Extents;
+ using index_type = typename extents_type::index_type;
+ using size_type = typename extents_type::size_type;
+ using rank_type = typename extents_type::rank_type;
+ using layout_type = LayoutLike;
+
+ constexpr
+ mapping() noexcept = default;
+
+ constexpr
+ mapping(Extents exts)
+ : m_exts(exts)
+ { }
+
+ constexpr const extents_type&
+ extents() const noexcept { return m_exts; }
+
+ constexpr index_type
+ required_span_size() const noexcept
+ {
+ for (size_t i = 0; i < extents_type::rank(); ++i)
+ if (m_exts.extent(i) == 0)
+ return 0;
+ return 1;
+ }
+
+ template<typename... Indices>
+ requires (sizeof...(Indices) == extents_type::rank())
+ constexpr index_type
+ operator()(Indices...) const noexcept
+ { return 0; }
+
+ static constexpr index_type
+ stride(rank_type) noexcept
+ { return 0; }
+
+ static constexpr bool
+ is_always_unique() noexcept
+ { return false; }
+
+ static constexpr bool
+ is_always_exhaustive() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_always_strided() noexcept
+ { return true; }
+
+ constexpr bool
+ is_unique() noexcept
+ {
+ if (required_span_size() == 0)
+ return true;
+
+ for (size_t i = 0; i < extents_type::rank(); ++i)
+ if (m_exts.extent(i) > 1)
+ return false;
+ return true;
+ }
+
+ static constexpr bool
+ is_exhaustive() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_strided() noexcept
+ { return true; }
+
+ private:
+ Extents m_exts;
+ };
+};
+
+#endif
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc
new file mode 100644
index 0000000..fb8ff01
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc
@@ -0,0 +1,30 @@
+// { dg-do compile { target c++23 } }
+// { dg-require-debug-mode "" }
+#include<mdspan>
+
+template<typename Layout>
+ constexpr bool
+ test_out_of_bounds_1d()
+ {
+ auto m = typename Layout::mapping<std::extents<int, 0>>{};
+ (void) m(0); // { dg-error "expansion of" }
+ return true;
+ }
+static_assert(test_out_of_bounds_1d<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_out_of_bounds_1d<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_out_of_bounds_1d<std::layout_stride>()); // { dg-error "expansion of" }
+
+template<typename Layout>
+ constexpr bool
+ test_out_of_bounds_3d()
+ {
+ auto m = typename Layout::mapping<std::extents<int, 3, 5, 7>>{};
+ (void) m(2, 5, 5); // { dg-error "expansion of" }
+ return true;
+ }
+static_assert(test_out_of_bounds_3d<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_out_of_bounds_3d<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_out_of_bounds_3d<std::layout_stride>()); // { dg-error "expansion of" }
+
+// { dg-prune-output "non-constant condition for static assertion" }
+// { dg-prune-output "__glibcxx_assert" }
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
new file mode 100644
index 0000000..a650fb1
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
@@ -0,0 +1,668 @@
+// { dg-do run { target c++23 } }
+#include <mdspan>
+
+#include <testsuite_hooks.h>
+#include "extents/int_like.h"
+#include "layout_like.h"
+
+constexpr auto dyn = std::dynamic_extent;
+
+template<typename MDSpan, typename T, typename E, typename L = std::layout_right,
+ typename A = std::default_accessor<T>>
+ constexpr void
+ assert_typedefs()
+ {
+ static_assert(std::same_as<typename MDSpan::extents_type, E>);
+ static_assert(std::same_as<typename MDSpan::layout_type, L>);
+ static_assert(std::same_as<typename MDSpan::accessor_type, A>);
+ static_assert(std::same_as<typename MDSpan::mapping_type,
+ typename L::mapping<E>>);
+ static_assert(std::same_as<typename MDSpan::element_type, T>);
+ static_assert(std::same_as<typename MDSpan::value_type,
+ std::remove_const_t<T>>);
+ static_assert(std::same_as<typename MDSpan::index_type,
+ typename E::index_type>);
+ static_assert(std::same_as<typename MDSpan::size_type,
+ typename E::size_type>);
+ static_assert(std::same_as<typename MDSpan::rank_type,
+ typename E::rank_type>);
+ static_assert(std::same_as<typename MDSpan::data_handle_type,
+ typename A::data_handle_type>);
+ static_assert(std::same_as<typename MDSpan::reference,
+ typename A::reference>);
+ }
+
+template<typename T, typename E, typename L, template<typename U> typename A>
+ constexpr void
+ test_typedefs()
+ { assert_typedefs<std::mdspan<T, E, L, A<T>>, T, E, L, A<T>>(); }
+
+constexpr void
+test_typedefs_all()
+{
+ using E = std::extents<int, 1, 2>;
+ using L = std::layout_left;
+
+ test_typedefs<double, E, L, std::default_accessor>();
+ test_typedefs<const double, E, L, std::default_accessor>();
+}
+
+template<typename MDSpan>
+ constexpr void
+ test_rank()
+ {
+ using Extents = typename MDSpan::extents_type;
+ static_assert(MDSpan::rank() == Extents::rank());
+ static_assert(MDSpan::rank_dynamic() == Extents::rank_dynamic());
+ }
+
+constexpr bool
+test_rank_all()
+{
+ test_rank<std::mdspan<double, std::extents<int>>>();
+ test_rank<std::mdspan<double, std::extents<int, 1>>>();
+ test_rank<std::mdspan<double, std::extents<int, dyn>>>();
+ return true;
+}
+
+template<typename Extents>
+ constexpr void
+ test_extent(Extents exts)
+ {
+ double data = 1.0;
+ auto md = std::mdspan(&data, exts);
+ using MDSpan = decltype(md);
+
+ for(size_t i = 0; i < MDSpan::rank(); ++i)
+ {
+ VERIFY(MDSpan::static_extent(i) == Extents::static_extent(i));
+ VERIFY(md.extent(i) == exts.extent(i));
+ }
+ }
+
+constexpr bool
+test_extent_all()
+{
+ // For rank == 0, check existence of the methods without calling them.
+ test_extent(std::extents<int>{});
+ test_extent(std::extents<int, 0>{});
+ test_extent(std::extents<int, dyn>{});
+ return true;
+}
+
+template<typename MDSpan>
+ constexpr void
+ test_class_properties()
+ {
+ static_assert(std::copyable<MDSpan>);
+ static_assert(std::is_nothrow_move_constructible_v<MDSpan>);
+ static_assert(std::is_nothrow_move_assignable_v<MDSpan>);
+ static_assert(std::is_nothrow_swappable_v<MDSpan>);
+ constexpr bool trivially_copyable =
+ std::is_trivially_copyable_v<typename MDSpan::accessor_type>
+ && std::is_trivially_copyable_v<typename MDSpan::mapping_type>
+ && std::is_trivially_copyable_v<typename MDSpan::data_handle_type>;
+ static_assert(std::is_trivially_copyable_v<MDSpan> == trivially_copyable);
+ }
+
+constexpr bool
+test_class_properties_all()
+{
+ test_class_properties<std::mdspan<double, std::extents<int>>>();
+ test_class_properties<std::mdspan<double, std::extents<int, 1>>>();
+ test_class_properties<std::mdspan<double, std::extents<int, dyn>>>();
+ return true;
+}
+
+constexpr bool
+test_default_ctor()
+{
+ static_assert(!std::is_default_constructible_v<std::mdspan<double,
+ std::extents<int>>>);
+ static_assert(!std::is_default_constructible_v<std::mdspan<double,
+ std::extents<int, 1>>>);
+ static_assert(std::is_default_constructible_v<std::mdspan<double,
+ std::extents<int, dyn>>>);
+
+ std::mdspan<double, std::extents<int, dyn>> md;
+ VERIFY(md.data_handle() == nullptr);
+ VERIFY(md.empty());
+ return true;
+}
+
+constexpr bool
+test_from_other()
+{
+ using Extents = std::extents<int, 3, 5, 7>;
+ auto exts = Extents{};
+
+ auto mapping = std::layout_right::mapping(exts);
+ constexpr size_t n = mapping.required_span_size();
+ std::array<double, n> storage{};
+
+ auto md1 = std::mdspan(storage.data(), exts);
+ auto md2 = std::mdspan<double, std::dextents<int, 3>>(md1);
+
+ VERIFY(md1.data_handle() == md2.data_handle());
+ VERIFY(md1.size() == md2.size());
+
+ static_assert(!std::is_convertible_v<
+ std::mdspan<double, std::extents<unsigned int, 2>>,
+ std::mdspan<double, std::extents<int, 2>>>);
+
+ static_assert(std::is_convertible_v<
+ std::mdspan<double, std::extents<int, 2>>,
+ std::mdspan<const double, std::extents<int, 2>>>);
+
+ static_assert(!std::is_constructible_v<
+ std::mdspan<double, std::extents<int, 2>>,
+ std::mdspan<const double, std::extents<int, 2>>>);
+
+ return true;
+}
+
+template<typename T, typename E, typename L = std::layout_right,
+ typename A = std::default_accessor<T>>
+ constexpr void
+ assert_deduced_typedefs(auto md)
+ { assert_typedefs<decltype(md), T, E, L, A>(); }
+
+constexpr bool
+test_from_carray()
+{
+ constexpr size_t n = 5;
+ double data[n] = {1.1, 2.2, 3.3, 4.4, 5.5};
+
+ auto md = std::mdspan(data);
+ assert_deduced_typedefs<double, std::extents<size_t, n>>(md);
+ VERIFY(md.rank() == 1);
+ VERIFY(md.rank_dynamic() == 0);
+ VERIFY(md[2] == data[2]);
+ return true;
+}
+
+constexpr bool
+test_from_pointer()
+{
+ double value = 12.3;
+ auto md = std::mdspan(&value);
+ assert_deduced_typedefs<double, std::extents<size_t>>(md);
+ VERIFY(md.rank() == 0);
+ VERIFY(md.rank_dynamic() == 0);
+ VERIFY(md[] == value);
+ return true;
+}
+
+constexpr bool
+test_from_pointer_and_shape()
+{
+ constexpr size_t n = 6;
+ std::array<double, n> data{1.1, 2.2, 3.3, 4.4, 5.5, 6.6};
+ std::array<int, 2> shape{2, 3};
+ std::span<const int, 2> shape_view(shape);
+
+ auto verify = [&data](auto md)
+ {
+ assert_deduced_typedefs<double, std::dextents<size_t, 2>>(md);
+ VERIFY(md.rank() == 2);
+ VERIFY(md.rank_dynamic() == 2);
+ VERIFY((md[0, 0]) == data[0]);
+ VERIFY((md[0, 1]) == data[1]);
+ VERIFY((md[1, 0]) == data[3]);
+ };
+
+ verify(std::mdspan(data.data(), shape[0], shape[1]));
+ verify(std::mdspan(data.data(), shape));
+ verify(std::mdspan(data.data(), shape_view));
+
+ std::mdspan<double, std::dextents<size_t, 2>> md1 = {data.data(), shape};
+ verify(md1);
+
+ std::mdspan<double, std::dextents<size_t, 2>> md2 = {data.data(), shape_view};
+ verify(md2);
+
+ static_assert(std::is_constructible_v<
+ std::mdspan<float, std::extents<int, 3, 5>>, float*>);
+ static_assert(!std::is_constructible_v<
+ std::mdspan<float, std::extents<int, 3, 5>>, float*, int>);
+ static_assert(std::is_constructible_v<
+ std::mdspan<float, std::extents<int, 3, 5>>, float*, int, int>);
+ static_assert(std::is_constructible_v<
+ std::mdspan<float, std::extents<int, 3, 5>>, float*, std::span<int, 0>>);
+ static_assert(std::is_constructible_v<
+ std::mdspan<float, std::extents<int, 3, 5>>, float*, std::span<int, 2>>);
+ static_assert(!std::is_convertible_v<
+ float*, std::mdspan<float, std::extents<int, 3, 5>>>);
+
+ static_assert(std::is_constructible_v<
+ std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, 2>>);
+ static_assert(!std::is_constructible_v<
+ std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, 1>>);
+ static_assert(!std::is_constructible_v<
+ std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, 3>>);
+ static_assert(!std::is_constructible_v<
+ std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, dyn>>);
+ return true;
+}
+
+constexpr bool
+test_from_pointer_and_integral_constant()
+{
+ std::array<double, 6> buffer{};
+ double * ptr = buffer.data();
+
+ auto verify = [ptr](auto actual, auto exts)
+ {
+ auto expected = std::mdspan<double, decltype(exts)>(ptr, exts);
+ static_assert(std::same_as<decltype(actual), decltype(expected)>);
+ VERIFY(actual.extents() == expected.extents());
+ };
+
+ auto c3 = std::integral_constant<int, 3>{};
+ auto c6 = std::integral_constant<int, 6>{};
+
+ verify(std::mdspan(ptr, 6), std::extents(6));
+ verify(std::mdspan(ptr, c6), std::extents(c6));
+ verify(std::mdspan(ptr, 2, c3), std::extents(2, c3));
+ return true;
+}
+
+constexpr bool
+test_from_extents()
+{
+ constexpr size_t n = 3*5*7;
+ std::array<double, n> storage{};
+ using Extents = std::extents<int, 3, 5, 7>;
+ auto exts = Extents{};
+ auto md = std::mdspan(storage.data(), exts);
+
+ assert_deduced_typedefs<double, Extents>(md);
+ VERIFY(md.data_handle() == storage.data());
+ VERIFY(md.extents() == exts);
+ return true;
+}
+
+constexpr bool
+test_from_mapping()
+{
+ constexpr size_t n = 3*5*7;
+ std::array<double, n> storage{};
+ using Extents = std::extents<int, 3, 5, 7>;
+
+ auto exts = Extents{};
+ auto m = std::layout_left::mapping(exts);
+ auto md = std::mdspan(storage.data(), m);
+
+ assert_deduced_typedefs<double, Extents, std::layout_left>(md);
+ VERIFY(md.data_handle() == storage.data());
+ VERIFY(md.mapping() == m);
+ return true;
+}
+
+constexpr bool
+test_from_accessor()
+{
+ constexpr size_t n = 3*5*7;
+ std::array<double, n> storage{};
+ using Extents = std::extents<int, 3, 5, 7>;
+
+ auto exts = Extents{};
+ auto m = std::layout_left::mapping(exts);
+ auto a = std::default_accessor<double>{};
+ auto md = std::mdspan(storage.data(), m, a);
+
+ assert_deduced_typedefs<double, Extents, std::layout_left>(md);
+ VERIFY(md.data_handle() == storage.data());
+ VERIFY(md.mapping() == m);
+ return true;
+}
+
+void
+test_from_int_like()
+{
+ constexpr size_t n = 3*5*7;
+ std::array<double, n> storage{};
+
+ auto verify = [&](auto md)
+ {
+ VERIFY(md.data_handle() == storage.data());
+ VERIFY(md.extent(0) == 3);
+ VERIFY(md.extent(1) == 5);
+ VERIFY(md.extent(2) == 7);
+
+ VERIFY((md[IntLike(0), 0, IntLike(0)]) == 0.0);
+ auto zero = std::array{IntLike(0), IntLike(0), IntLike(0)};
+ auto zero_view = std::span<IntLike, 3>{zero};
+ VERIFY((md[zero]) == 0.0);
+ VERIFY((md[zero_view]) == 0.0);
+ };
+
+ auto shape = std::array{IntLike(3), IntLike(5), IntLike(7)};
+ auto shape_view = std::span<IntLike, 3>{shape};
+ verify(std::mdspan(storage.data(), IntLike(3), 5, IntLike(7)));
+ verify(std::mdspan(storage.data(), shape));
+ verify(std::mdspan(storage.data(), shape_view));
+}
+
+template<typename T, bool NothrowConstructible = true,
+ bool NothrowAssignable = true>
+ class OpaqueAccessor
+ {
+ struct Handle
+ {
+ constexpr
+ Handle(T * other)
+ : ptr(other)
+ { }
+
+ constexpr
+ Handle(const Handle&) noexcept(NothrowConstructible) = default;
+
+ constexpr
+ Handle(Handle&&) noexcept(NothrowConstructible) = default;
+
+ constexpr Handle&
+ operator=(const Handle&) noexcept(NothrowAssignable) = default;
+
+ constexpr Handle&
+ operator=(Handle&&) noexcept(NothrowAssignable) = default;
+
+ T * ptr;
+ };
+
+ public:
+ using element_type = T;
+ using reference = T&;
+ using data_handle_type = Handle;
+ using offset_policy = OpaqueAccessor;
+
+ reference
+ access(data_handle_type p, size_t i) const
+ {
+ ++access_count;
+ return p.ptr[i];
+ }
+
+ typename offset_policy::data_handle_type
+ offset(data_handle_type p, size_t i) const
+ {
+ ++offset_count;
+ return typename offset_policy::data_handle_type{(void*)(p.ptr + i)};
+ }
+
+ mutable size_t access_count = 0;
+ mutable size_t offset_count = 0;
+ };
+
+void
+test_from_opaque_accessor()
+{
+ constexpr size_t n = 3*5*7;
+ std::array<double, n> storage{};
+ using Extents = std::extents<int, 3, 5, 7>;
+
+ auto exts = Extents{};
+ auto m = std::layout_left::mapping(exts);
+ auto a = OpaqueAccessor<double>{};
+ auto handle = OpaqueAccessor<double>::data_handle_type{storage.data()};
+ auto md = std::mdspan(handle, m, a);
+
+ using MDSpan = decltype(md);
+ static_assert(std::same_as<MDSpan::accessor_type, decltype(a)>);
+
+ VERIFY((md[0, 0, 0]) == 0.0);
+ VERIFY(md.accessor().access_count == 1);
+
+ VERIFY((md[2, 4, 6]) == 0.0);
+ VERIFY(md.accessor().access_count == 2);
+}
+
+template<typename T, typename Base>
+ class BaseClassAccessor
+ {
+ public:
+ using element_type = T;
+ using reference = Base&;
+ using data_handle_type = T*;
+ using offset_policy = BaseClassAccessor;
+
+ static_assert(std::common_reference_with<reference&&, element_type&>);
+
+ reference
+ access(data_handle_type p, size_t i) const
+ { return p[i]; }
+
+ typename offset_policy::data_handle_type
+ offset(data_handle_type p, size_t i) const
+ { return typename offset_policy::data_handle_type{p + i}; }
+ };
+
+struct Base
+{
+ double value = 1.0;
+};
+
+struct Derived : Base
+{
+ double value = 2.0;
+};
+
+void
+test_from_base_class_accessor()
+{
+ constexpr size_t n = 3*5*7;
+ std::array<Derived, n> storage{};
+ using Extents = std::extents<int, 3, 5, 7>;
+
+ auto exts = Extents{};
+ auto m = std::layout_left::mapping(exts);
+ auto a = BaseClassAccessor<Derived, Base>{};
+ auto md = std::mdspan(storage.data(), m, a);
+
+ using MDSpan = decltype(md);
+ static_assert(std::same_as<MDSpan::accessor_type, decltype(a)>);
+ static_assert(std::same_as<decltype(md[0, 0, 0]), Base&>);
+ VERIFY((md[0, 0, 0].value) == 1.0);
+ VERIFY((md[2, 4, 6].value) == 1.0);
+}
+
+constexpr bool
+test_from_mapping_like()
+{
+ double data = 1.1;
+ auto m = LayoutLike::mapping<std::extents<int, 1, 2, 3>>{};
+ auto md = std::mdspan(&data, m);
+ VERIFY((md[0, 0, 0]) == data);
+ VERIFY((md[0, 1, 2]) == data);
+ return true;
+}
+
+template<typename MDSpan>
+ constexpr void
+ test_empty(MDSpan md)
+ {
+ VERIFY(md.empty() == (md.size() == 0));
+ }
+
+constexpr bool
+test_empty_all()
+{
+ test_empty(std::mdspan<double, std::extents<int, dyn>>{});
+ return true;
+}
+
+constexpr bool
+test_access()
+{
+ using Extents = std::extents<int, 3, 5, 7>;
+ auto exts = Extents{};
+
+ auto mapping = std::layout_left::mapping(exts);
+ constexpr size_t n = mapping.required_span_size();
+ std::array<double, n> storage{};
+
+ auto md = std::mdspan(storage.data(), mapping);
+ static_assert(std::__mdspan::__mapping_alike<decltype(md)>);
+
+ for(int i = 0; i < exts.extent(0); ++i)
+ for(int j = 0; j < exts.extent(1); ++j)
+ for(int k = 0; k < exts.extent(2); ++k)
+ {
+ std::array<int, 3> ijk{i, j, k};
+ storage[mapping(i, j, k)] = 1.0;
+ VERIFY((md[i, j, k]) == 1.0);
+ VERIFY((md[ijk]) == 1.0);
+ VERIFY((md[std::span(ijk)]) == 1.0);
+ storage[mapping(i, j, k)] = 0.0;
+ }
+ return true;
+}
+
+constexpr bool
+test_swap()
+{
+ using Extents = std::dextents<int, 2>;
+ auto e1 = Extents{3, 5};
+ auto e2 = Extents{7, 11};
+
+ std::array<double, 3*5> s1{};
+ std::array<double, 7*11> s2{};
+
+ auto md1 = std::mdspan(s1.data(), e1);
+ auto md2 = std::mdspan(s2.data(), e2);
+
+ std::swap(md1, md2);
+
+ VERIFY(md1.data_handle() == s2.data());
+ VERIFY(md2.data_handle() == s1.data());
+
+ VERIFY(md1.size() == s2.size());
+ VERIFY(md2.size() == s1.size());
+ return true;
+}
+
+namespace adl
+{
+ template<typename T>
+ struct SwappableAccessor
+ {
+ using element_type = T;
+ using reference = T&;
+ using data_handle_type = T*;
+ using offset_policy = SwappableAccessor;
+
+ reference
+ access(data_handle_type p, size_t i) const
+ { return p[i]; }
+
+ typename offset_policy::data_handle_type
+ offset(data_handle_type p, size_t i) const
+ { return p + i; }
+
+ friend void
+ swap(SwappableAccessor&, SwappableAccessor&)
+ { ++swap_count; }
+
+ static inline size_t swap_count = 0;
+ };
+}
+
+void
+test_swap_adl()
+{
+ using Extents = std::extents<int, dyn>;
+ using Layout = std::layout_left;
+ using Accessor = adl::SwappableAccessor<double>;
+ Accessor::swap_count = 0;
+
+ std::mdspan<double, Extents, Layout, Accessor> m1, m2;
+ swap(m1, m2);
+ VERIFY(Accessor::swap_count == 1);
+}
+
+template<bool Constructible, bool Assignable>
+constexpr void
+test_nothrow_movable()
+{
+ using Layout = std::layout_left;
+ using Extents = std::dextents<int, 3>;
+ using Accessor = OpaqueAccessor<int, Constructible, Assignable>;
+ using Handle = Accessor::data_handle_type;
+ static_assert(std::is_nothrow_move_assignable_v<Accessor>);
+ static_assert(std::is_nothrow_move_constructible_v<Accessor>);
+ static_assert(std::is_nothrow_move_assignable_v<Handle> == Assignable);
+ static_assert(std::is_nothrow_move_constructible_v<Handle> == Constructible);
+
+ using MDSpan = std::mdspan<int, Extents, Layout, Accessor>;
+ static_assert(std::is_nothrow_move_assignable_v<MDSpan> == Assignable);
+ static_assert(std::is_nothrow_move_constructible_v<MDSpan> == Constructible);
+}
+
+constexpr void
+test_nothrow_movable_all()
+{
+ using MDSpan = std::mdspan<double, std::dextents<int, 3>>;
+ static_assert(std::is_nothrow_move_assignable_v<MDSpan>);
+ static_assert(std::is_nothrow_move_constructible_v<MDSpan>);
+
+ test_nothrow_movable<true, true>();
+ test_nothrow_movable<true, false>();
+ test_nothrow_movable<false, true>();
+ test_nothrow_movable<false, false>();
+}
+
+int
+main()
+{
+ test_typedefs_all();
+
+ test_rank_all();
+ test_extent_all();
+ static_assert(test_extent_all());
+
+ test_class_properties_all();
+ static_assert(test_class_properties_all());
+
+ test_empty_all();
+ static_assert(test_empty_all());
+
+ test_default_ctor();
+ static_assert(test_default_ctor());
+
+ test_from_other();
+ static_assert(test_from_other());
+
+ test_from_carray();
+ static_assert(test_from_carray());
+
+ test_from_pointer_and_shape();
+ static_assert(test_from_pointer_and_shape());
+
+ test_from_pointer_and_integral_constant();
+ static_assert(test_from_pointer_and_integral_constant());
+
+ test_from_extents();
+ static_assert(test_from_extents());
+
+ test_from_mapping();
+ static_assert(test_from_mapping());
+
+ test_from_accessor();
+ static_assert(test_from_accessor());
+
+ test_from_int_like();
+ test_from_opaque_accessor();
+ test_from_base_class_accessor();
+ test_from_mapping_like();
+ static_assert(test_from_mapping_like());
+
+ test_access();
+ static_assert(test_access());
+
+ test_swap();
+ static_assert(test_swap());
+ test_swap_adl();
+
+ test_nothrow_movable_all();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc
new file mode 100644
index 0000000..dceae56
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc
@@ -0,0 +1,24 @@
+// { dg-do compile { target c++23 } }
+#include<mdspan>
+
+#include "layout_like.h"
+
+template<typename Layout>
+constexpr bool
+test_invalid_multi_index()
+{
+
+ double data = 1.1;
+ auto m = typename Layout::mapping<std::extents<int, 1, 2, 3>>{};
+ auto md = std::mdspan(&data, m);
+
+ [[maybe_unused]] double x = md[0, 2, 2]; // { dg-error "expansion of" }
+ return true;
+};
+static_assert(test_invalid_multi_index<LayoutLike>()); // { dg-error "expansion of" }
+static_assert(test_invalid_multi_index<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_invalid_multi_index<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_invalid_multi_index<std::layout_stride>()); // { dg-error "expansion of" }
+
+// { dg-prune-output "non-constant condition" }
+// { dg-prune-output "__glibcxx_assert" }
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/version.cc b/libstdc++-v3/testsuite/23_containers/mdspan/version.cc
new file mode 100644
index 0000000..106ee40
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/version.cc
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++23 } }
+#include <mdspan>
+
+#ifndef __cpp_lib_mdspan
+#error "Feature test macro __cpp_lib_mdspan is missing for <mdspan>"
+#if __cpp_lib_mdspan < 202207
+#error "Feature test macro __cpp_lib_mdspan has the wrong value"
+#endif
+#endif
diff --git a/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc b/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc
index c9e9112..890fdf8 100644
--- a/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc
@@ -25,6 +25,7 @@ main()
{
std::deque<int> d{};
std::span<int, std::dynamic_extent> myspan(d); // { dg-error "no match" }
+ (void) myspan;
}
// { dg-prune-output "data" }
diff --git a/libstdc++-v3/testsuite/23_containers/span/deduction.cc b/libstdc++-v3/testsuite/23_containers/span/deduction.cc
index dce6ced..c66db90 100644
--- a/libstdc++-v3/testsuite/23_containers/span/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/span/deduction.cc
@@ -80,4 +80,7 @@ test01()
std::span s12(const_cast<const std::span<int>&>(s5));
static_assert( is_dynamic_span<int>(s12) );
+
+ std::span s13(a.data(), std::integral_constant<size_t, 3>{});
+ static_assert( is_static_span<long, 3>(s13));
}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/const_container.cc
new file mode 100644
index 0000000..e62f158
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/const_container.cc
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++11 } }
+
+#include <unordered_map>
+
+#include <testsuite_hooks.h>
+
+// PR c++/116369
+const std::unordered_map<int, int> um
+ {
+ { 0, 1 },
+ { 2, 3 },
+ { 4, 5 }
+ };
+
+int main()
+{
+ VERIFY( um.size() == 3 );
+ VERIFY( um.find(0) != um.end() );
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/const_container.cc
new file mode 100644
index 0000000..3da1e33
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/const_container.cc
@@ -0,0 +1,22 @@
+// { dg-do compile { target c++11 } }
+
+#include <unordered_map>
+
+#include <testsuite_hooks.h>
+
+// PR c++/116369
+const std::unordered_multimap<int, int> umm
+ {
+ { 0, 1 },
+ { 0, 1 },
+ { 2, 3 },
+ { 2, 3 },
+ { 4, 5 },
+ { 4, 5 }
+ };
+
+int main()
+{
+ VERIFY( umm.size() == 6 );
+ VERIFY( umm.find(0) != umm.end() );
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/const_container.cc
new file mode 100644
index 0000000..841d25a
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/const_container.cc
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+
+#include <unordered_set>
+
+#include <testsuite_hooks.h>
+
+// PR c++/116369
+const std::unordered_multiset<int> ums
+ { 0, 0, 1, 1, 2, 2 };
+
+int main()
+{
+ VERIFY( ums.size() == 6 );
+ VERIFY( ums.find(0) != ums.end() );
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/const_container.cc
new file mode 100644
index 0000000..ffdbbad
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/const_container.cc
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++11 } }
+
+#include <unordered_set>
+
+#include <testsuite_hooks.h>
+
+// PR c++/116369
+const std::unordered_set<int> us { 0, 1, 2 };
+
+int main()
+{
+ VERIFY( us.size() == 3 );
+ VERIFY( us.find(0) != us.end() );
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc
index ba2ede0..792ed45 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc
@@ -25,7 +25,7 @@ class container : public __gnu_debug::_Safe_sequence<container>
{
public:
__gnu_cxx::__mutex&
- get_mutex()
+ get_mutex() const
{ return this->_M_get_mutex(); }
};
diff --git a/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc b/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc
new file mode 100644
index 0000000..9a6ed16
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc
@@ -0,0 +1,52 @@
+// { dg-do compile { target c++23 } }
+
+#include <format>
+#include <vector>
+
+// only format_kind::sequence provides set_brackets and set_separator methods
+
+template<std::range_format fk, typename T>
+struct MyCont : std::vector<T>
+{
+ using std::vector<T>::vector;
+};
+
+template<std::range_format fk, typename T>
+constexpr std::range_format std::format_kind<MyCont<fk, T>> = fk;
+
+void test_sequence()
+{
+ std::formatter<MyCont<std::range_format::sequence, int>, char> fmtter;
+ fmtter.set_brackets("{", "}");
+ fmtter.set_separator(",");
+}
+
+void test_map()
+{
+ std::formatter<MyCont<std::range_format::map, std::pair<int, int>>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+void test_set()
+{
+ std::formatter<MyCont<std::range_format::set, int>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+void test_string()
+{
+ std::formatter<MyCont<std::range_format::string, char>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+void test_debug_string()
+{
+ std::formatter<MyCont<std::range_format::debug_string, char>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+// { dg-error "no matching function for call to 'std::formatter<" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/util/testsuite_containers.h b/libstdc++-v3/testsuite/util/testsuite_containers.h
index 37491a4..ab0107f 100644
--- a/libstdc++-v3/testsuite/util/testsuite_containers.h
+++ b/libstdc++-v3/testsuite/util/testsuite_containers.h
@@ -210,6 +210,9 @@ namespace __gnu_test
clit = container.cbegin(bn);
assert( ++clit == container.cend(bn) );
+ clit = container.begin(bn);
+ assert( ++clit == container.cend(bn) );
+
assert( container.begin(bn) != container.cend(bn) );
}
};
@@ -304,6 +307,9 @@ namespace __gnu_test
assert( container.cbegin() != container.cend() );
assert( container.cbegin() != container.end() );
assert( container.begin() != container.cend() );
+
+ auto cit = container.begin();
+ assert( cit == container.cbegin() );
}
};