diff options
36 files changed, 2514 insertions, 153 deletions
diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc index 4aea902..5476d10 100644 --- a/gcc/c-family/c-cppbuiltin.cc +++ b/gcc/c-family/c-cppbuiltin.cc @@ -1090,7 +1090,7 @@ c_cpp_builtins (cpp_reader *pfile) cpp_define (pfile, "__cpp_constexpr_exceptions=202411L"); cpp_define (pfile, "__cpp_static_assert=202306L"); cpp_define (pfile, "__cpp_placeholder_variables=202306L"); - cpp_define (pfile, "__cpp_structured_bindings=202403L"); + cpp_define (pfile, "__cpp_structured_bindings=202411L"); cpp_define (pfile, "__cpp_deleted_function=202403L"); cpp_define (pfile, "__cpp_variadic_friend=202403L"); cpp_define (pfile, "__cpp_pack_indexing=202311L"); diff --git a/gcc/cobol/cbldiag.h b/gcc/cobol/cbldiag.h index dd16190..2554deb 100644 --- a/gcc/cobol/cbldiag.h +++ b/gcc/cobol/cbldiag.h @@ -122,8 +122,8 @@ static void location_dump( const char func[], int line, const char tag[], const LOC& loc) { extern int yy_flex_debug; // cppcheck-suppress shadowVariable if( yy_flex_debug ) { - const char *detail = gcobol_getenv("update_location"); // cppcheck-suppress knownConditionTrueFalse - if( detail ) { + const char *detail = gcobol_getenv("update_location"); + if( detail ) { // cppcheck-suppress knownConditionTrueFalse fprintf(stderr, "%s:%d: %s location (%d,%d) to (%d,%d)\n", func, line, tag, loc.first_line, loc.first_column, loc.last_line, loc.last_column); diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y index fae96ed..59cc64d 100644 --- a/gcc/cobol/parse.y +++ b/gcc/cobol/parse.y @@ -10336,8 +10336,8 @@ intrinsic: function_udf if( p != NULL ) { auto loc = symbol_field_location(field_index(p->field)); error_msg(loc, "FUNCTION %qs has " - "inconsistent parameter type %td (%qs)", - keyword_str($1), p - args.data(), name_of(p->field) ); + "inconsistent parameter type %ld (%qs)", + keyword_str($1), (long)(p - args.data()), name_of(p->field) ); YYERROR; } $$ = is_numeric(args[0].field)? diff --git a/gcc/cobol/scan.l b/gcc/cobol/scan.l index ba4c044..5773f09 100644 --- a/gcc/cobol/scan.l +++ b/gcc/cobol/scan.l @@ -123,7 +123,7 @@ NUMEDCHAR [BPVZ90/,]+{COUNT}? NUMEDCHARS {NUMEDCHAR}([.]?{NUMEDCHAR})* NUMED ([+-]{NUMEDCHARS}+)|({NUMEDCHARS}+[+-]) CURRENCY [A-Zfhijklmoqtuwy\x80-\xFF]{-}[ABCDEGNPRSVXZ] -NUMEDCUR (([.]?[-$0B/Z*+,P9()V+–]|{CURRENCY}+|{COUNT})+([.][$0B/Z*+P9()V+\–])*)+ +NUMEDCUR (([.]?[$0B/Z*+,P9()V+-]|{CURRENCY}+|{COUNT})+([.][$0B/Z*+P9()V+-])*)+ NUMEDITED {NUMED}|{NUMEDCUR} EDITED {ALPHED}|{NUMED}|{NUMEDCUR} diff --git a/gcc/cobol/scan_ante.h b/gcc/cobol/scan_ante.h index 31093a6..c00826d 100644 --- a/gcc/cobol/scan_ante.h +++ b/gcc/cobol/scan_ante.h @@ -149,7 +149,7 @@ numstr_of( const char string[], radix_t radix = decimal_e ) { } auto nx = std::count_if(input, p, fisdigit); if( 36 < nx ) { - error_msg(yylloc, "significand of %s has more than 36 digits (%td)", input, nx); + error_msg(yylloc, "significand of %s has more than 36 digits (%ld)", input, (long)nx); return NO_CONDITION; } diff --git a/gcc/cobol/show_parse.h b/gcc/cobol/show_parse.h index bd0e16f..e1a8cb2 100644 --- a/gcc/cobol/show_parse.h +++ b/gcc/cobol/show_parse.h @@ -500,7 +500,7 @@ class ANALYZE int level; inline static int analyze_level=1; public: - ANALYZE(const char *func_) : func(func_) + ANALYZE(const char *func_) : func(func_) // cppcheck-suppress noExplicitConstructor { level = 0; if( getenv("Analyze") ) diff --git a/gcc/cobol/util.cc b/gcc/cobol/util.cc index aed9483..2a7bf2b 100644 --- a/gcc/cobol/util.cc +++ b/gcc/cobol/util.cc @@ -1049,8 +1049,8 @@ cbl_field_t::report_invalid_initial_value(const YYLTYPE& loc) const { return TOUPPER(ch) == 'E'; } ); if( !has_exponent && data.precision() < pend - p ) { - error_msg(loc, "%s cannot represent VALUE %qs exactly (max %c%td)", - name, data.initial, '.', pend - p); + error_msg(loc, "%s cannot represent VALUE %qs exactly (max %c%ld)", + name, data.initial, '.', (long)(pend - p)); } } } diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index d30c9c7..2dbaf4a 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -25435,20 +25435,41 @@ aarch64_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global) return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | type; } +/* Return true if function declaration FNDECL needs to be marked as + having a variant PCS. */ + +static bool +aarch64_is_variant_pcs (tree fndecl) +{ + /* Check for ABIs that preserve more registers than usual. */ + arm_pcs pcs = (arm_pcs) fndecl_abi (fndecl).id (); + if (pcs == ARM_PCS_SIMD || pcs == ARM_PCS_SVE) + return true; + + /* Check for ABIs that allow PSTATE.SM to be 1 on entry. */ + tree fntype = TREE_TYPE (fndecl); + if (aarch64_fntype_pstate_sm (fntype) != AARCH64_ISA_MODE_SM_OFF) + return true; + + /* Check for ABIs that require PSTATE.ZA to be 1 on entry, either because + of ZA or ZT0. */ + if (aarch64_fntype_pstate_za (fntype) != 0) + return true; + + return false; +} + /* Output .variant_pcs for aarch64_vector_pcs function symbols. */ static void aarch64_asm_output_variant_pcs (FILE *stream, const tree decl, const char* name) { - if (TREE_CODE (decl) == FUNCTION_DECL) + if (TREE_CODE (decl) == FUNCTION_DECL + && aarch64_is_variant_pcs (decl)) { - arm_pcs pcs = (arm_pcs) fndecl_abi (decl).id (); - if (pcs == ARM_PCS_SIMD || pcs == ARM_PCS_SVE) - { - fprintf (stream, "\t.variant_pcs\t"); - assemble_name (stream, name); - fprintf (stream, "\n"); - } + fprintf (stream, "\t.variant_pcs\t"); + assemble_name (stream, name); + fprintf (stream, "\n"); } } diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 9283d97..63cad2a 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -7904,28 +7904,6 @@ extract_call_expr (tree call) call = TREE_OPERAND (call, 0); if (TREE_CODE (call) == TARGET_EXPR) call = TARGET_EXPR_INITIAL (call); - if (cxx_dialect >= cxx20) - switch (TREE_CODE (call)) - { - /* C++20 rewritten comparison operators. */ - case TRUTH_NOT_EXPR: - call = TREE_OPERAND (call, 0); - break; - case LT_EXPR: - case LE_EXPR: - case GT_EXPR: - case GE_EXPR: - case SPACESHIP_EXPR: - { - tree op0 = TREE_OPERAND (call, 0); - if (integer_zerop (op0)) - call = TREE_OPERAND (call, 1); - else - call = op0; - } - break; - default:; - } if (TREE_CODE (call) != CALL_EXPR && TREE_CODE (call) != AGGR_INIT_EXPR diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index b8ac454..eabf7f8 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -11615,12 +11615,14 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, } return false; } + tree ve = DECL_VALUE_EXPR (t); /* Treat __PRETTY_FUNCTION__ inside a template function as potentially-constant. */ - else if (DECL_PRETTY_FUNCTION_P (t) - && DECL_VALUE_EXPR (t) == error_mark_node) + if (DECL_PRETTY_FUNCTION_P (t) && ve == error_mark_node) return true; - return RECUR (DECL_VALUE_EXPR (t), rval); + if (DECL_DECOMPOSITION_P (t) && TREE_CODE (ve) == TREE_VEC) + return RECUR (TREE_VEC_ELT (ve, 0), rval); + return RECUR (ve, rval); } if (want_rval && (now || !var_in_maybe_constexpr_fn (t)) diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 8122fca..ab5b0c9 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -9748,7 +9748,7 @@ get_tuple_size (tree type) /* Return std::tuple_element<I,TYPE>::type. */ static tree -get_tuple_element_type (tree type, unsigned i) +get_tuple_element_type (tree type, unsigned HOST_WIDE_INT i) { tree args = make_tree_vec (2); TREE_VEC_ELT (args, 0) = build_int_cst (integer_type_node, i); @@ -9764,7 +9764,7 @@ get_tuple_element_type (tree type, unsigned i) /* Return e.get<i>() or get<i>(e). */ static tree -get_tuple_decomp_init (tree decl, unsigned i) +get_tuple_decomp_init (tree decl, unsigned HOST_WIDE_INT i) { tree targs = make_tree_vec (1); TREE_VEC_ELT (targs, 0) = build_int_cst (integer_type_node, i); @@ -9870,6 +9870,19 @@ cp_maybe_mangle_decomp (tree decl, cp_decomp *decomp) } } +/* Append #i to DECL_NAME (decl). */ + +static void +set_sb_pack_name (tree decl, unsigned HOST_WIDE_INT i) +{ + tree name = DECL_NAME (decl); + size_t len = IDENTIFIER_LENGTH (name) + 22; + char *n = XALLOCAVEC (char, len); + snprintf (n, len, "%s#" HOST_WIDE_INT_PRINT_UNSIGNED, + IDENTIFIER_POINTER (name), i); + DECL_NAME (decl) = get_identifier (n); +} + /* Finish a decomposition declaration. DECL is the underlying declaration "e", FIRST is the head of a chain of decls for the individual identifiers chained through DECL_CHAIN in reverse order and COUNT is the number of @@ -9926,10 +9939,13 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) auto_vec<tree, 16> v; v.safe_grow (count, true); tree d = first; + int pack = -1; for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d)) { v[count - i - 1] = d; fit_decomposition_lang_decl (d, decl); + if (DECL_PACK_P (d)) + pack = count - i - 1; } tree type = TREE_TYPE (decl); @@ -9951,6 +9967,14 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) tree eltype = NULL_TREE; unsigned HOST_WIDE_INT eltscnt = 0; + /* Structured binding packs when initializer is non-dependent should + have their DECL_VALUE_EXPR set to a TREE_VEC. First two elements + of that TREE_VEC are the base and index, what is normally represented + as DECL_VALUE_EXPR ARRAY_REF <base, index> where index is the index + of the pack first element. The remaining elements of the TREE_VEC + are VAR_DECLs for the pack elements. */ + tree packv = NULL_TREE; + if (TREE_CODE (type) == ARRAY_TYPE) { tree nelts; @@ -9969,7 +9993,7 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) goto error_out; } eltscnt = tree_to_uhwi (nelts); - if (count != eltscnt) + if (pack != -1 ? count - 1 > eltscnt : count != eltscnt) { cnt_mismatch: auto_diagnostic_group d; @@ -9990,12 +10014,37 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) eltype = TREE_TYPE (type); for (unsigned int i = 0; i < count; i++) { + if ((unsigned) pack == i) + { + packv = make_tree_vec (eltscnt - count + 3); + for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j) + { + tree t; + TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]); + set_sb_pack_name (t, j); + maybe_push_decl (t); + TREE_TYPE (t) = eltype; + layout_decl (t, 0); + if (!processing_template_decl) + { + tree a = unshare_expr (dexp); + a = build4 (ARRAY_REF, eltype, a, size_int (j + pack), + NULL_TREE, NULL_TREE); + SET_DECL_VALUE_EXPR (t, a); + DECL_HAS_VALUE_EXPR_P (t) = 1; + } + } + continue; + } TREE_TYPE (v[i]) = eltype; layout_decl (v[i], 0); if (processing_template_decl) continue; tree t = unshare_expr (dexp); - t = build4 (ARRAY_REF, eltype, t, size_int (i), NULL_TREE, NULL_TREE); + unsigned HOST_WIDE_INT j = i; + if (pack != -1 && (unsigned) pack < i) + j = i + eltscnt - count; + t = build4 (ARRAY_REF, eltype, t, size_int (j), NULL_TREE, NULL_TREE); SET_DECL_VALUE_EXPR (v[i], t); DECL_HAS_VALUE_EXPR_P (v[i]) = 1; } @@ -10004,17 +10053,41 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) else if (TREE_CODE (type) == COMPLEX_TYPE) { eltscnt = 2; - if (count != eltscnt) + if (pack != -1 ? count - 1 > eltscnt : count != eltscnt) goto cnt_mismatch; eltype = cp_build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type)); for (unsigned int i = 0; i < count; i++) { + if ((unsigned) pack == i) + { + packv = make_tree_vec (eltscnt - count + 3); + for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j) + { + tree t; + TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]); + set_sb_pack_name (t, j); + maybe_push_decl (t); + TREE_TYPE (t) = eltype; + layout_decl (t, 0); + if (!processing_template_decl) + { + tree a = build1 (pack + j ? IMAGPART_EXPR : REALPART_EXPR, eltype, + unshare_expr (dexp)); + SET_DECL_VALUE_EXPR (t, a); + DECL_HAS_VALUE_EXPR_P (t) = 1; + } + } + continue; + } TREE_TYPE (v[i]) = eltype; layout_decl (v[i], 0); if (processing_template_decl) continue; tree t = unshare_expr (dexp); - t = build1 (i ? IMAGPART_EXPR : REALPART_EXPR, eltype, t); + unsigned HOST_WIDE_INT j = i; + if (pack != -1 && (unsigned) pack < i) + j = i + eltscnt - count; + t = build1 (j ? IMAGPART_EXPR : REALPART_EXPR, eltype, t); SET_DECL_VALUE_EXPR (v[i], t); DECL_HAS_VALUE_EXPR_P (v[i]) = 1; } @@ -10026,19 +10099,47 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) error_at (loc, "cannot decompose variable length vector %qT", type); goto error_out; } - if (count != eltscnt) + if (pack != -1 ? count - 1 > eltscnt : count != eltscnt) goto cnt_mismatch; eltype = cp_build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type)); for (unsigned int i = 0; i < count; i++) { + if ((unsigned) pack == i) + { + packv = make_tree_vec (eltscnt - count + 3); + for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j) + { + tree t; + TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]); + set_sb_pack_name (t, j); + maybe_push_decl (t); + TREE_TYPE (t) = eltype; + layout_decl (t, 0); + if (!processing_template_decl) + { + tree a = unshare_expr (dexp); + location_t loc = DECL_SOURCE_LOCATION (t); + tree s = size_int (j + pack); + convert_vector_to_array_for_subscript (loc, &a, s); + a = build4 (ARRAY_REF, eltype, a, s, + NULL_TREE, NULL_TREE); + SET_DECL_VALUE_EXPR (t, a); + DECL_HAS_VALUE_EXPR_P (t) = 1; + } + } + continue; + } TREE_TYPE (v[i]) = eltype; layout_decl (v[i], 0); if (processing_template_decl) continue; tree t = unshare_expr (dexp); + unsigned HOST_WIDE_INT j = i; + if (pack != -1 && (unsigned) pack < i) + j = i + eltscnt - count; convert_vector_to_array_for_subscript (DECL_SOURCE_LOCATION (v[i]), - &t, size_int (i)); - t = build4 (ARRAY_REF, eltype, t, size_int (i), NULL_TREE, NULL_TREE); + &t, size_int (j)); + t = build4 (ARRAY_REF, eltype, t, size_int (j), NULL_TREE, NULL_TREE); SET_DECL_VALUE_EXPR (v[i], t); DECL_HAS_VALUE_EXPR_P (v[i]) = 1; } @@ -10062,11 +10163,11 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) goto error_out; } eltscnt = tree_to_uhwi (tsize); - if (count != eltscnt) + if (pack != -1 ? count - 1 > eltscnt : count != eltscnt) goto cnt_mismatch; - if (test_p) + if (test_p && eltscnt) return true; - if (!processing_template_decl && DECL_DECOMP_BASE (decl)) + if (!processing_template_decl && DECL_DECOMP_BASE (decl) && eltscnt) { /* For structured bindings used in conditions we need to evaluate the conversion of decl (aka e in the standard) to bool or @@ -10096,16 +10197,70 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) location_t sloc = input_location; location_t dloc = DECL_SOURCE_LOCATION (v[i]); + if ((unsigned) pack == i) + { + packv = make_tree_vec (eltscnt - count + 3); + for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j) + { + tree t; + TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]); + set_sb_pack_name (t, j); + input_location = dloc; + tree init = get_tuple_decomp_init (decl, j + pack); + tree eltype = (init == error_mark_node ? error_mark_node + : get_tuple_element_type (type, j + pack)); + input_location = sloc; + + if (VOID_TYPE_P (eltype)) + { + error ("%<std::tuple_element<%wu, %T>::type%> is " + "%<void%>", j + pack, type); + eltype = error_mark_node; + } + if (init == error_mark_node || eltype == error_mark_node) + { + inform (dloc, "in initialization of structured binding " + "pack %qD", v[pack]); + goto error_out; + } + if (j == 0 + && !processing_template_decl + && TREE_STATIC (decl)) + { + sorry_at (dloc, "mangling of structured binding pack " + "elements not implemented yet"); + goto error_out; + } + maybe_push_decl (t); + /* Save the decltype away before reference collapse. */ + hash_map_safe_put<hm_ggc> (decomp_type_table, t, eltype); + eltype = cp_build_reference_type (eltype, !lvalue_p (init)); + TREE_TYPE (t) = eltype; + layout_decl (t, 0); + DECL_HAS_VALUE_EXPR_P (t) = 0; + if (!processing_template_decl) + { + copy_linkage (t, decl); + cp_finish_decl (t, init, /*constexpr*/false, + /*asm*/NULL_TREE, LOOKUP_NORMAL); + } + } + continue; + } + + unsigned HOST_WIDE_INT j = i; + if (pack != -1 && (unsigned) pack < i) + j = i + eltscnt - count; input_location = dloc; - tree init = get_tuple_decomp_init (decl, i); + tree init = get_tuple_decomp_init (decl, j); tree eltype = (init == error_mark_node ? error_mark_node - : get_tuple_element_type (type, i)); + : get_tuple_element_type (type, j)); input_location = sloc; if (VOID_TYPE_P (eltype)) { - error ("%<std::tuple_element<%u, %T>::type%> is %<void%>", - i, type); + error ("%<std::tuple_element<%wu, %T>::type%> is %<void%>", + j, type); eltype = error_mark_node; } if (init == error_mark_node || eltype == error_mark_node) @@ -10159,6 +10314,12 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) goto error_out; else if (btype == NULL_TREE) { + if (pack == 0 && count == 1) + { + eltscnt = 0; + packv = make_tree_vec (2); + goto done; + } error_at (loc, "cannot decompose class type %qT without non-static " "data members", type); goto error_out; @@ -10170,7 +10331,7 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) continue; else eltscnt++; - if (count != eltscnt) + if (pack != -1 ? count - 1 > eltscnt : count != eltscnt) goto cnt_mismatch; tree t = dexp; if (type != btype) @@ -10179,6 +10340,7 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) /*nonnull*/false, tf_warning_or_error); type = btype; } + unsigned HOST_WIDE_INT j = 0; unsigned int i = 0; for (tree field = TYPE_FIELDS (btype); field; field = TREE_CHAIN (field)) if (TREE_CODE (field) != FIELD_DECL @@ -10191,6 +10353,32 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) NULL_TREE); if (REFERENCE_REF_P (tt)) tt = TREE_OPERAND (tt, 0); + if (pack != -1 && j >= (unsigned) pack) + { + if (j == (unsigned) pack) + { + packv = make_tree_vec (eltscnt - count + 3); + i++; + } + if (j < (unsigned) pack + eltscnt - (count - 1)) + { + tree t; + TREE_VEC_ELT (packv, j + 3 - i) = t = copy_node (v[pack]); + set_sb_pack_name (t, j + 1 - i); + maybe_push_decl (t); + TREE_TYPE (t) = TREE_TYPE (tt); + layout_decl (t, 0); + if (!processing_template_decl) + { + SET_DECL_VALUE_EXPR (t, tt); + DECL_HAS_VALUE_EXPR_P (t) = 1; + } + else + DECL_HAS_VALUE_EXPR_P (t) = 0; + j++; + continue; + } + } TREE_TYPE (v[i]) = TREE_TYPE (tt); layout_decl (v[i], 0); if (!processing_template_decl) @@ -10199,7 +10387,26 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p) DECL_HAS_VALUE_EXPR_P (v[i]) = 1; } i++; + j++; } + if (pack != -1 && j == (unsigned) pack) + { + gcc_checking_assert (eltscnt == count - 1); + packv = make_tree_vec (2); + } + } + done: + if (packv) + { + gcc_checking_assert (pack != -1); + TREE_VEC_ELT (packv, 0) = decl; + TREE_VEC_ELT (packv, 1) = size_int (pack); + SET_DECL_VALUE_EXPR (v[pack], packv); + DECL_HAS_VALUE_EXPR_P (v[pack]) = 1; + DECL_IGNORED_P (v[pack]) = 1; + if (!processing_template_decl) + for (unsigned int i = 0; i < TREE_VEC_LENGTH (packv) - 2U; ++i) + pushdecl (TREE_VEC_ELT (packv, 2 + i)); } if (processing_template_decl) { diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index a8c54c7..743fd74 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -14672,13 +14672,23 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl, tree v = DECL_VALUE_EXPR (range_decl); /* For decomposition declaration get all of the corresponding declarations out of the way. */ - if (TREE_CODE (v) == ARRAY_REF - && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) + if ((TREE_CODE (v) == ARRAY_REF + && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) + || (TREE_CODE (v) == TREE_VEC + && DECL_DECOMPOSITION_P (TREE_VEC_ELT (v, 0)))) { tree d = range_decl; - range_decl = TREE_OPERAND (v, 0); decomp = &decomp_d; - decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; + if (TREE_CODE (v) == ARRAY_REF) + { + range_decl = TREE_OPERAND (v, 0); + decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; + } + else + { + range_decl = TREE_VEC_ELT (v, 0); + decomp->count = tree_to_uhwi (TREE_VEC_ELT (v, 1)) + 1; + } decomp->decl = d; bool seen_name_independent_decl = false; for (unsigned int i = 0; i < decomp->count; @@ -16843,7 +16853,7 @@ cp_parser_simple_declaration (cp_parser* parser, } /* Helper of cp_parser_simple_declaration, parse a decomposition declaration. - decl-specifier-seq ref-qualifier [opt] [ identifier-list ] + decl-specifier-seq ref-qualifier [opt] [ sb-identifier-list ] initializer ; */ static tree @@ -16856,21 +16866,45 @@ cp_parser_decomposition_declaration (cp_parser *parser, location_t loc = cp_lexer_peek_token (parser->lexer)->location; cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE); - /* Parse the identifier-list. */ + /* Parse the sb-identifier-list. */ auto_vec<cp_expr, 10> v; bool attr_diagnosed = false; int first_attr = -1; + int pack = -1; unsigned int cnt = 0; if (!cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_SQUARE)) while (true) { + if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) + { + location_t elloc = cp_lexer_peek_token (parser->lexer)->location; + if (!processing_template_decl) + error_at (elloc, "structured binding pack outside of template"); + else if (pack != -1) + error_at (elloc, + "multiple packs in structured binding declaration"); + else + { + if (keyword == RID_MAX + && cxx_dialect >= cxx17 + && cxx_dialect < cxx26) + pedwarn (elloc, OPT_Wc__26_extensions, + "structured binding packs only available with " + "%<-std=c++2c%> or %<-std=gnu++2c%>"); + pack = cnt; + } + cp_lexer_consume_token (parser->lexer); + } cp_expr e = cp_parser_identifier (parser); if (e.get_value () == error_mark_node) break; tree attr = NULL_TREE; if (cp_next_tokens_can_be_std_attribute_p (parser)) { - if (cxx_dialect >= cxx17 && cxx_dialect < cxx26 && !attr_diagnosed) + if (keyword == RID_MAX + && cxx_dialect >= cxx17 + && cxx_dialect < cxx26 + && !attr_diagnosed) { pedwarn (cp_lexer_peek_token (parser->lexer)->location, OPT_Wc__26_extensions, @@ -16931,7 +16965,7 @@ cp_parser_decomposition_declaration (cp_parser *parser, &pushed_scope); tree orig_decl = decl; - unsigned int i; + unsigned int i, j; cp_expr e; cp_decl_specifier_seq decl_specs; clear_decl_specs (&decl_specs); @@ -16939,6 +16973,7 @@ cp_parser_decomposition_declaration (cp_parser *parser, if (decl_specifiers->storage_class == sc_static) decl_specs.storage_class = sc_static; tree prev = decl; + j = 0; FOR_EACH_VEC_ELT (v, i, e) { if (i == 0) @@ -16969,9 +17004,22 @@ cp_parser_decomposition_declaration (cp_parser *parser, prev = decl2; DECL_DECLARED_CONSTEXPR_P (decl2) = DECL_DECLARED_CONSTEXPR_P (decl); DECL_DECLARED_CONSTINIT_P (decl2) = DECL_DECLARED_CONSTINIT_P (decl); + if (j == (unsigned) pack) + { + tree dtype = cxx_make_type (DECLTYPE_TYPE); + DECLTYPE_TYPE_EXPR (dtype) = decl2; + DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (dtype) = 1; + SET_TYPE_STRUCTURAL_EQUALITY (dtype); + tree type = cxx_make_type (TYPE_PACK_EXPANSION); + PACK_EXPANSION_PATTERN (type) = dtype; + SET_TYPE_STRUCTURAL_EQUALITY (type); + PACK_EXPANSION_PARAMETER_PACKS (type) = decl2; + TREE_TYPE (decl2) = type; + } } if (elt_pushed_scope) pop_scope (elt_pushed_scope); + ++j; } if (v.is_empty ()) @@ -46300,6 +46348,14 @@ cp_convert_omp_range_for (tree &this_pre_body, tree &sl, decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; decomp->decl = decl; } + else if (TREE_CODE (v) == TREE_VEC + && DECL_DECOMPOSITION_P (TREE_VEC_ELT (v, 0))) + { + d = TREE_VEC_ELT (v, 0); + decomp = &decomp_d; + decomp->count = tree_to_uhwi (TREE_VEC_ELT (v, 1)) + 1; + decomp->decl = decl; + } } do_range_for_auto_deduction (d, init, decomp); } @@ -46423,6 +46479,15 @@ cp_convert_omp_range_for (tree &this_pre_body, tree &sl, decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; decomp->decl = d; } + else if (TREE_CODE (v) == TREE_VEC + && DECL_DECOMPOSITION_P (TREE_VEC_ELT (v, 0))) + { + tree d = orig_decl; + orig_decl = TREE_VEC_ELT (v, 0); + decomp = &decomp_d; + decomp->count = tree_to_uhwi (TREE_VEC_ELT (v, 1)) + 1; + decomp->decl = d; + } } tree auto_node = type_uses_auto (TREE_TYPE (orig_decl)); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index acfeb81..b6b13ed 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -13981,9 +13981,30 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, else if (is_capture_proxy (parm_pack)) { arg_pack = retrieve_local_specialization (parm_pack); + if (DECL_DECOMPOSITION_P (arg_pack)) + { + orig_arg = arg_pack; + goto expand_sb_pack; + } if (DECL_PACK_P (arg_pack)) arg_pack = NULL_TREE; } + else if (DECL_DECOMPOSITION_P (parm_pack)) + { + orig_arg = retrieve_local_specialization (parm_pack); + expand_sb_pack: + gcc_assert (DECL_DECOMPOSITION_P (orig_arg)); + if (TREE_TYPE (orig_arg) == error_mark_node) + return error_mark_node; + gcc_assert (DECL_HAS_VALUE_EXPR_P (orig_arg)); + arg_pack = DECL_VALUE_EXPR (orig_arg); + tree vec = make_tree_vec (TREE_VEC_LENGTH (arg_pack) - 2); + if (TREE_VEC_LENGTH (vec)) + memcpy (TREE_VEC_BEGIN (vec), &TREE_VEC_ELT (arg_pack, 2), + TREE_VEC_LENGTH (vec) * sizeof (tree)); + arg_pack = make_node (NONTYPE_ARGUMENT_PACK); + ARGUMENT_PACK_ARGS (arg_pack) = vec; + } else { int idx; @@ -13996,7 +14017,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, arg_pack = NULL_TREE; } - orig_arg = arg_pack; + if (orig_arg == NULL_TREE) + orig_arg = arg_pack; if (arg_pack && TREE_CODE (arg_pack) == ARGUMENT_PACK_SELECT) arg_pack = ARGUMENT_PACK_SELECT_FROM_PACK (arg_pack); @@ -14011,8 +14033,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, if (arg_pack) { - int my_len = - TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)); + int my_len + = TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)); /* Don't bother trying to do a partial substitution with incomplete packs; we'll try again after deduction. */ @@ -14176,8 +14198,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, /* Update the corresponding argument. */ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) - TREE_VEC_ELT (TREE_VEC_ELT (args, level -1 ), idx) = - TREE_TYPE (pack); + TREE_VEC_ELT (TREE_VEC_ELT (args, level -1 ), idx) + = TREE_TYPE (pack); else TREE_VEC_ELT (args, idx) = TREE_TYPE (pack); } @@ -15921,7 +15943,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain, tsubst_flags_t tcomplain = complain; if (VAR_P (t)) tcomplain |= tf_tst_ok; - type = tsubst (type, args, tcomplain, in_decl); + if (DECL_DECOMPOSITION_P (t) && DECL_PACK_P (t)) + type = NULL_TREE; + else + type = tsubst (type, args, tcomplain, in_decl); /* Substituting the type might have recursively instantiated this same alias (c++/86171). */ if (use_spec_table && gen_tmpl && DECL_ALIAS_TEMPLATE_P (gen_tmpl) @@ -15938,6 +15963,17 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain, { DECL_INITIALIZED_P (r) = 0; DECL_TEMPLATE_INSTANTIATED (r) = 0; + if (DECL_DECOMPOSITION_P (t) && DECL_PACK_P (t)) + { + tree dtype = cxx_make_type (DECLTYPE_TYPE); + DECLTYPE_TYPE_EXPR (dtype) = r; + DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (dtype) = 1; + SET_TYPE_STRUCTURAL_EQUALITY (dtype); + type = cxx_make_type (TYPE_PACK_EXPANSION); + PACK_EXPANSION_PATTERN (type) = dtype; + SET_TYPE_STRUCTURAL_EQUALITY (type); + PACK_EXPANSION_PARAMETER_PACKS (type) = r; + } if (TREE_CODE (type) == FUNCTION_TYPE) { /* It may seem that this case cannot occur, since: @@ -18555,13 +18591,17 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree &orig_declv, if (decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (decl)) { tree v = DECL_VALUE_EXPR (decl); - if (TREE_CODE (v) == ARRAY_REF - && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) + if ((TREE_CODE (v) == ARRAY_REF + && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) + || (TREE_CODE (v) == TREE_VEC + && DECL_DECOMPOSITION_P (TREE_VEC_ELT (v, 0)))) { + v = (TREE_CODE (v) == ARRAY_REF + ? TREE_OPERAND (v, 0) : TREE_VEC_ELT (v, 0)); cp_decomp decomp_d = { NULL_TREE, 0 }; - tree d = tsubst_decl (TREE_OPERAND (v, 0), args, complain); + tree d = tsubst_decl (v, args, complain); maybe_push_decl (d); - d = tsubst_decomp_names (d, TREE_OPERAND (v, 0), args, complain, + d = tsubst_decomp_names (d, v, args, complain, in_decl, &decomp_d); decomp = true; if (d == error_mark_node) @@ -21220,7 +21260,28 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ++c_inhibit_evaluation_warnings; /* We only want to compute the number of arguments. */ if (PACK_EXPANSION_P (op)) - expanded = tsubst_pack_expansion (op, args, complain, in_decl); + { + expanded = NULL_TREE; + if (DECL_DECOMPOSITION_P (PACK_EXPANSION_PATTERN (op))) + { + tree d = PACK_EXPANSION_PATTERN (op); + if (DECL_HAS_VALUE_EXPR_P (d)) + { + d = DECL_VALUE_EXPR (d); + if (TREE_CODE (d) == TREE_VEC) + { + tree b = TREE_VEC_ELT (d, 0); + if (!type_dependent_expression_p_push (b)) + { + expanded = void_node; + len = TREE_VEC_LENGTH (d) - 2; + } + } + } + } + if (!expanded) + expanded = tsubst_pack_expansion (op, args, complain, in_decl); + } else expanded = tsubst_template_args (ARGUMENT_PACK_ARGS (op), args, complain, in_decl); @@ -29050,6 +29111,24 @@ value_dependent_expression_p (tree expression) case SIZEOF_EXPR: if (SIZEOF_EXPR_TYPE_P (expression)) return dependent_type_p (TREE_TYPE (TREE_OPERAND (expression, 0))); + if (tree p = TREE_OPERAND (expression, 0)) + if (PACK_EXPANSION_P (p) + && DECL_DECOMPOSITION_P (PACK_EXPANSION_PATTERN (p))) + { + tree d = PACK_EXPANSION_PATTERN (p); + if (DECL_HAS_VALUE_EXPR_P (d)) + { + d = DECL_VALUE_EXPR (d); + /* [temp.dep.constexpr]/4: + Expressions of the following form are value-dependent: + sizeof ... ( identifier ) + unless the identifier is a structured binding pack whose + initializer is not dependent. */ + if (TREE_CODE (d) == TREE_VEC + && !type_dependent_expression_p (TREE_VEC_ELT (d, 0))) + return false; + } + } /* FALLTHRU */ case ALIGNOF_EXPR: case TYPEID_EXPR: @@ -29563,6 +29642,22 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees, tree op = TREE_OPERAND (*tp, 0); if (code == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (*tp)) op = TREE_TYPE (op); + else if (code == SIZEOF_EXPR + && PACK_EXPANSION_P (op) + && DECL_DECOMPOSITION_P (PACK_EXPANSION_PATTERN (op))) + { + tree d = PACK_EXPANSION_PATTERN (op); + if (DECL_HAS_VALUE_EXPR_P (d)) + { + d = DECL_VALUE_EXPR (d); + if (TREE_CODE (d) == TREE_VEC + && !type_dependent_expression_p (TREE_VEC_ELT (d, 0))) + { + *walk_subtrees = 0; + return NULL_TREE; + } + } + } if (TYPE_P (op)) { if (dependent_type_p (op)) diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index c723a07..ee9c048 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -8460,14 +8460,10 @@ simplify_context::simplify_gen_subreg (machine_mode outermode, rtx op, if (GET_CODE (op) == SUBREG || GET_CODE (op) == CONCAT - || GET_MODE (op) == VOIDmode) - return NULL_RTX; - - if (MODE_COMPOSITE_P (outermode) - && (CONST_SCALAR_INT_P (op) - || CONST_DOUBLE_AS_FLOAT_P (op) - || CONST_FIXED_P (op) - || GET_CODE (op) == CONST_VECTOR)) + || CONST_SCALAR_INT_P (op) + || CONST_DOUBLE_AS_FLOAT_P (op) + || CONST_FIXED_P (op) + || GET_CODE (op) == CONST_VECTOR) return NULL_RTX; if (validate_subreg (outermode, innermode, op, byte)) diff --git a/gcc/testsuite/g++.dg/cpp26/decomp13.C b/gcc/testsuite/g++.dg/cpp26/decomp13.C new file mode 100644 index 0000000..d01590f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp13.C @@ -0,0 +1,52 @@ +// P1061R10 - Structured Bindings can introduce a Pack +// { dg-do compile { target c++11 } } +// { dg-options "" } + +namespace std { + template<typename T> struct tuple_size; + template<int, typename> struct tuple_element; +} + +struct S { int a, b, c, d; }; +struct T { + int a[5]; + template <int I> int &get () { return a[I]; } +}; + +template<> struct std::tuple_size<T> { static const int value = 5; }; +template<int I> struct std::tuple_element<I,T> { using type = int; }; + +template <int N> +void +foo () +{ + auto [a, ...b, c] = S (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + auto [...d] = S (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + auto [...e, f, ...g, h] = S (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-error "multiple packs in structured binding declaration" "" { target *-*-* } .-2 } + auto [i, j, k, l, ...m, n] = S (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-error "6 names provided for structured binding" "" { target *-*-* } .-2 } + // { dg-message "while 'S' decomposes into 4 elements" "" { target *-*-* } .-3 } + auto [o, ...p, q, r, s] = S (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + auto [t, u, v, w, x, ...y, z] = T (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-error "7 names provided for structured binding" "" { target *-*-* } .-2 } + // { dg-message "while 'T' decomposes into 5 elements" "" { target *-*-* } .-3 } + int aa[] = { 1, 2, 3 }; + const auto & [ab, ...ac, ad, ae, af] = aa; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-error "5 names provided for structured binding" "" { target *-*-* } .-2 } + // { dg-message "while 'const int \\\[3\\\]' decomposes into 3 elements" "" { target *-*-* } .-3 } +} + +void +bar () +{ + auto [a, ...b, c, d] = S (); // { dg-error "structured binding pack outside of template" } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp14.C b/gcc/testsuite/g++.dg/cpp26/decomp14.C new file mode 100644 index 0000000..f626ec9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp14.C @@ -0,0 +1,474 @@ +// P1061R10 - Structured Bindings can introduce a Pack +// { dg-do run { target c++11 } } +// { dg-options "" } + +struct S { + int a; long long b; short c; + explicit operator bool () const noexcept { return true; } +}; +namespace std { + template <typename T> struct tuple_size; + template <int, typename> struct tuple_element; +} +struct T { + short c; int a; long long b; + template <int I> + typename std::tuple_element<I, T>::type &get (); + template <int I> + typename std::tuple_element<I, const T>::type &get () const; + explicit operator bool () const noexcept { return false; } +}; +template <> +struct std::tuple_size<T> { static constexpr int value = 3; }; +template <> +struct std::tuple_element<0, T> { typedef int type; }; +template <> +struct std::tuple_element<1, T> { typedef long long type; }; +template <> +struct std::tuple_element<2, T> { typedef short type; }; +template <> +std::tuple_element<0, T>::type &T::get <0> () { return a; } +template <> +std::tuple_element<1, T>::type &T::get <1> () { return b; } +template <> +std::tuple_element<2, T>::type &T::get <2> () { return c; } +template <> +struct std::tuple_size<const T> { static constexpr int value = 3; }; +template <> +struct std::tuple_element<0, const T> { typedef const int type; }; +template <> +struct std::tuple_element<1, const T> { typedef const long long type; }; +template <> +struct std::tuple_element<2, const T> { typedef const short type; }; +template <> +std::tuple_element<0, const T>::type &T::get <0> () const { return a; } +template <> +std::tuple_element<1, const T>::type &T::get <1> () const { return b; } +template <> +std::tuple_element<2, const T>::type &T::get <2> () const { return c; } +template <typename T, typename U> +struct same_type { static const bool value = false; }; +template <typename T> +struct same_type<T, T> { static const bool value = true; }; + +int +sum () +{ + return 0; +} + +template <typename T, typename ...A> +T +sum (T x, A... y) +{ + return x + sum (y...); +} + +template <typename T> +T +square (T x) +{ + return x * x; +} + +template <typename T> +T & +ref (T &x) +{ + return x; +} + +using size_t = decltype (sizeof 0); + +template <int N> +size_t +foo () +{ + S s = S { 1, 2, 3 }; + auto [sa, sb, sc] = S { 1, 2, 3 }; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + static_assert (same_type <decltype (sa), int>::value, ""); + static_assert (same_type <decltype (sb), long long>::value, ""); + static_assert (same_type <decltype (sc), short>::value, ""); + auto [sd, ...se] = S { 1, 2, 3 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + constexpr size_t ses = sizeof... (se); + static_assert (sizeof... (se) == 2, ""); + static_assert (same_type <decltype (sd), int>::value, ""); + static_assert (same_type <decltype (se...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (se...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + const auto & [...sf [[]], sg] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (sf) == 2, ""); + static_assert (same_type <decltype (sf...[0]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sf...[1]), const long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sg), const short>::value, ""); + auto [sh, si, sj [[]], ...sk] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (sk) == 0, ""); + static_assert (same_type <decltype (sh), int>::value, ""); + static_assert (same_type <decltype (si), long long>::value, ""); + static_assert (same_type <decltype (sj), short>::value, ""); + auto && [sl, ...sm [[maybe_unused]], sn] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (sm) == 1, ""); + static_assert (same_type <decltype (sl), int>::value, ""); + static_assert (same_type <decltype (sm...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sn), short>::value, ""); + auto [...so] = S { 1, 2, 3 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (so) == 3, ""); + static_assert (same_type <decltype (so...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (so...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (so...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [...sp, sq, sr, ss [[maybe_unused]]] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (sp) == 0, ""); + static_assert (same_type <decltype (sq), int>::value, ""); + static_assert (same_type <decltype (sr), long long>::value, ""); + static_assert (same_type <decltype (ss), short>::value, ""); + auto [st, ...su, sv, sw] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (su) == 0, ""); + static_assert (same_type <decltype (st), int>::value, ""); + static_assert (same_type <decltype (sv), long long>::value, ""); + static_assert (same_type <decltype (sw), short>::value, ""); + if (sa != 1 || sb != 2 || sc != 3 + || sd != 1 || se...[0] != 2 || se...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sf...[0] != 1 || sf...[1] != 2 || sg != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sh != 1 || si != 2 || sj != 3 + || sl != 1 || sm...[0] != 2 || sn != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || so...[0] != 1 || so...[1] != 2 || so...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sq != 1 || sr != 2 || ss != 3 + || st != 1 || sv != 2 || sw != 3 + || sum (se...) != 5 + || sum <decltype (se)...> (se...) != 5 + || sum (square (square (se))...) != 97 + || sum (sf...) != 3 + || sum (sk...) != 0 + || sum (sm...) != 2 + || sum (so...) != 6 + || sum <decltype (so)...> (so...) != 6 + || sum (square (so)...) != 14 + || sum (sp...) != 0 + || sum (su...) != 0 + || (se + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (... + sf) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + sk) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (sm + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (so + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (sp + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + su) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + __builtin_abort (); + S s2[] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; + int i = 0; + for (auto [sx, ...sy [[]]] : s2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (sy) == 2, ""); + static_assert (same_type <decltype (sx), int>::value, ""); + static_assert (same_type <decltype (sy...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sy...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (sx != i * 3 + 1 || sum (sy...) != i * 6 + 5) + __builtin_abort (); + auto fn1 = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn1 (); + auto fn2 = [&sy..., &i] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn2 (); + auto fn3 = [&...sy2 = sy, &i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn3 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn4 = [&...sy3 = ref (sy), &i] () { if (sum (sy3...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn4 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn5 = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn5 (); + auto fn6 = [sy..., i] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn6 (); + auto fn7 = [...sy2 = sy, i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn7 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn8 = [...sy3 = square (sy), i] () { if (sum (sy3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn8 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn9 = [&] () { auto fn = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn9 (); + auto fn10 = [&sy..., &i] () { auto fn = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn10 (); + auto fn11 = [&] () { auto fn = [&...sy2 = sy, &i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn11 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + auto fn12 = [&sy..., &i] () { auto fn = [&...sy3 = ref (sy), &i] () { if (sum (sy3...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn12 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + auto fn13 = [=] () { auto fn = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn13 (); + auto fn14 = [sy..., i] () { auto fn = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn14 (); + auto fn15 = [=] () { auto fn = [...sy2 = sy, i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn15 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + auto fn16 = [&sy..., &i] () { auto fn = [...sy3 = square (sy), i] () { if (sum (sy3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn16 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + ++i; + } + i = 0; + for (auto [...sz] : s2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (sz) == 3, ""); + static_assert (same_type <decltype (sz...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sz...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sz...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (sum (sz...) != i * 9 + 6) + __builtin_abort (); + auto fn = [=] () { if (sum (sz...) != i * 9 + 6) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn (); + ++i; + } + if (auto [...sx, sy] = s) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } + { + static_assert (sizeof... (sx) == 2, ""); + static_assert (same_type <decltype (sx...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sx...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sy), short>::value, ""); + if (sum (sx...) != 3 || sy != 3) + __builtin_abort (); + } + else + __builtin_abort (); + T t = T { 3, 1, 2 }; + auto [ta, tb, tc] = T { 3, 1, 2 }; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + static_assert (same_type <decltype (ta), int>::value, ""); + static_assert (same_type <decltype (tb), long long>::value, ""); + static_assert (same_type <decltype (tc), short>::value, ""); + auto [td [[maybe_unused]], ...te] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (te) == 2, ""); + static_assert (same_type <decltype (td), int>::value, ""); + static_assert (same_type <decltype (te...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (te...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [...tf [[maybe_unused]], tg] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (tf) == 2, ""); + static_assert (same_type <decltype (tf...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tf...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tg), short>::value, ""); + const auto & [th, ti, tj, ...tk] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (tk) == 0, ""); + static_assert (same_type <decltype (th), const int>::value, ""); + static_assert (same_type <decltype (ti), const long long>::value, ""); + static_assert (same_type <decltype (tj), const short>::value, ""); + auto [tl [[]], ...tm [[]], tn [[]]] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (tm) == 1, ""); + static_assert (same_type <decltype (tl), int>::value, ""); + static_assert (same_type <decltype (tm...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tn), short>::value, ""); + auto && [...to] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (to) == 3, ""); + static_assert (same_type <decltype (to...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (to...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (to...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [...tp, tq [[]], tr, ts] = T { 3, 1, 2 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (tp) == 0, ""); + static_assert (same_type <decltype (tq), int>::value, ""); + static_assert (same_type <decltype (tr), long long>::value, ""); + static_assert (same_type <decltype (ts), short>::value, ""); + auto [tt, ...tu [[]], tv, tw] = T { 3, 1, 2 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (tu) == 0, ""); + static_assert (same_type <decltype (tt), int>::value, ""); + static_assert (same_type <decltype (tv), long long>::value, ""); + static_assert (same_type <decltype (tw), short>::value, ""); + if (ta != 1 || tb != 2 || tc != 3 + || td != 1 || te...[0] != 2 || te...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || tf...[0] != 1 || tf...[1] != 2 || tg != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || th != 1 || ti != 2 || tj != 3 + || tl != 1 || tm...[0] != 2 || tn != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || to...[0] != 1 || to...[1] != 2 || to...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } } + || tq != 1 || tr != 2 || ts != 3 + || tt != 1 || tv != 2 || tw != 3 + || sum (te...) != 5 + || sum <decltype (te)...> (te...) != 5 + || sum (square (square (te))...) != 97 + || sum (tf...) != 3 + || sum (tk...) != 0 + || sum (tm...) != 2 + || sum (to...) != 6 + || sum <decltype (to)...> (to...) != 6 + || sum (square (to)...) != 14 + || sum (tp...) != 0 + || sum (tu...) != 0 + || (te + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (... + tf) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + tk) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (tm + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (to + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (tp + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + tu) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + __builtin_abort (); + T t2[] = { { 3, 1, 2 }, { 6, 4, 5 }, { 9, 7, 8 } }; + i = 0; + for (auto [tx, ...ty] : t2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (ty) == 2, ""); + static_assert (same_type <decltype (tx), int>::value, ""); + static_assert (same_type <decltype (ty...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ty...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (tx != i * 3 + 1 || sum (ty...) != i * 6 + 5) + __builtin_abort (); + auto fn1 = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; + fn1 (); + auto fn2 = [&ty..., &i] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn2 (); + auto fn3 = [&...ty2 = ty, &i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn3 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn4 = [&...ty3 = ref (ty), &i] () { if (sum (ty3...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn4 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn5 = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; + fn5 (); + auto fn6 = [ty..., i] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn6 (); + auto fn7 = [...ty2 = ty, i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn7 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn8 = [...ty3 = square (ty), i] () { if (sum (ty3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn8 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn9 = [&] () { auto fn = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; + fn9 (); + auto fn10 = [&ty..., &i] () { auto fn = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn10 (); + auto fn11 = [&] () { auto fn = [&...ty2 = ty, &i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn11 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn12 = [&ty..., &i] () { auto fn = [&...ty3 = ref (ty), &i] () { if (sum (ty3...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn12 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + auto fn13 = [=] () { auto fn = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; + fn13 (); + auto fn14 = [ty..., i] () { auto fn = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn14 (); + auto fn15 = [=] () { auto fn = [...ty2 = ty, i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn15 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn16 = [&ty..., &i] () { auto fn = [...ty3 = square (ty), i] () { if (sum (ty3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn16 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + ++i; + } + i = 0; + for (auto [...tz] : t2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (tz) == 3, ""); + static_assert (same_type <decltype (tz...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tz...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tz...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (sum (tz...) != i * 9 + 6) + __builtin_abort (); + auto fn = [=] () { if (sum (tz...) != i * 9 + 6) __builtin_abort (); }; + fn (); + ++i; + } + if (auto [...tx [[maybe_unused]], ty] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } + __builtin_abort (); + else + { + static_assert (sizeof... (tx) == 2, ""); + static_assert (same_type <decltype (tx...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tx...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ty), short>::value, ""); + if (sum (tx...) != 3 || ty != 3) + __builtin_abort (); + } + int a[3] = { 1, 2, 3 }; + auto [aa, ab, ac] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + static_assert (same_type <decltype (aa), int>::value, ""); + static_assert (same_type <decltype (ab), int>::value, ""); + static_assert (same_type <decltype (ac), int>::value, ""); + auto [ad [[maybe_unused]], ...ae [[maybe_unused]]] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (ae) == 2, ""); + static_assert (same_type <decltype (ad), int>::value, ""); + static_assert (same_type <decltype (ae...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ae...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [...af, ag] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (af) == 2, ""); + static_assert (same_type <decltype (af...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (af...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ag), int>::value, ""); + auto [ah, ai [[]], aj, ...ak [[]]] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (ak) == 0, ""); + static_assert (same_type <decltype (ah), int>::value, ""); + static_assert (same_type <decltype (ai), int>::value, ""); + static_assert (same_type <decltype (aj), int>::value, ""); + auto [al, ...am [[]], an] = a;// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (am) == 1, ""); + static_assert (same_type <decltype (al), int>::value, ""); + static_assert (same_type <decltype (am...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (an), int>::value, ""); + const auto &[...ao] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (ao) == 3, ""); + static_assert (same_type <decltype (ao...[0]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ao...[1]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ao...[2]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto &&[...ap, aq, ar [[]], as] = a;// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (ap) == 0, ""); + static_assert (same_type <decltype (aq), int>::value, ""); + static_assert (same_type <decltype (ar), int>::value, ""); + static_assert (same_type <decltype (as), int>::value, ""); + auto [at, ...au, av, aw] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (au) == 0, ""); + static_assert (same_type <decltype (at), int>::value, ""); + static_assert (same_type <decltype (av), int>::value, ""); + static_assert (same_type <decltype (aw), int>::value, ""); + if (aa != 1 || ab != 2 || ac != 3 + || ad != 1 || ae...[0] != 2 || ae...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || af...[0] != 1 || af...[1] != 2 || ag != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || ah != 1 || ai != 2 || aj != 3 + || al != 1 || am...[0] != 2 || an != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || ao...[0] != 1 || ao...[1] != 2 || ao...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } } + || aq != 1 || ar != 2 || as != 3 + || at != 1 || av != 2 || aw != 3 + || sum (ae...) != 5 + || sum <decltype (ae)...> (ae...) != 5 + || sum (square (square (ae))...) != 97 + || sum (af...) != 3 + || sum (ak...) != 0 + || sum (am...) != 2 + || sum (ao...) != 6 + || sum <decltype (ao)...> (ao...) != 6 + || sum (square (ao)...) != 14 + || sum (ap...) != 0 + || sum (au...) != 0 + || (ae + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (... + af) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + ak) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (am + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (ao + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (ap + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + au) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + __builtin_abort (); + return ses; +} + +int +main () +{ + if (foo <0> () != 2) + __builtin_abort (); +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp15.C b/gcc/testsuite/g++.dg/cpp26/decomp15.C new file mode 100644 index 0000000..9bb55b3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp15.C @@ -0,0 +1,474 @@ +// P1061R10 - Structured Bindings can introduce a Pack +// { dg-do run { target c++11 } } +// { dg-options "" } + +struct S { + int a; long long b; short c; + explicit operator bool () const noexcept { return true; } +}; +namespace std { + template <typename T> struct tuple_size; + template <int, typename> struct tuple_element; +} +struct T { + short c; int a; long long b; + template <int I> + typename std::tuple_element<I, T>::type &get (); + template <int I> + typename std::tuple_element<I, const T>::type &get () const; + explicit operator bool () const noexcept { return false; } +}; +template <> +struct std::tuple_size<T> { static constexpr int value = 3; }; +template <> +struct std::tuple_element<0, T> { typedef int type; }; +template <> +struct std::tuple_element<1, T> { typedef long long type; }; +template <> +struct std::tuple_element<2, T> { typedef short type; }; +template <> +std::tuple_element<0, T>::type &T::get <0> () { return a; } +template <> +std::tuple_element<1, T>::type &T::get <1> () { return b; } +template <> +std::tuple_element<2, T>::type &T::get <2> () { return c; } +template <> +struct std::tuple_size<const T> { static constexpr int value = 3; }; +template <> +struct std::tuple_element<0, const T> { typedef const int type; }; +template <> +struct std::tuple_element<1, const T> { typedef const long long type; }; +template <> +struct std::tuple_element<2, const T> { typedef const short type; }; +template <> +std::tuple_element<0, const T>::type &T::get <0> () const { return a; } +template <> +std::tuple_element<1, const T>::type &T::get <1> () const { return b; } +template <> +std::tuple_element<2, const T>::type &T::get <2> () const { return c; } +template <typename T, typename U> +struct same_type { static const bool value = false; }; +template <typename T> +struct same_type<T, T> { static const bool value = true; }; + +int +sum () +{ + return 0; +} + +template <typename T, typename ...A> +T +sum (T x, A... y) +{ + return x + sum (y...); +} + +template <typename T> +T +square (T x) +{ + return x * x; +} + +template <typename T> +T & +ref (T &x) +{ + return x; +} + +using size_t = decltype (sizeof 0); + +template <typename S, typename T, typename U> +size_t +foo () +{ + S s = S { 1, 2, 3 }; + auto [sa, sb, sc] = S { 1, 2, 3 }; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + static_assert (same_type <decltype (sa), int>::value, ""); + static_assert (same_type <decltype (sb), long long>::value, ""); + static_assert (same_type <decltype (sc), short>::value, ""); + auto [sd, ...se] = S { 1, 2, 3 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (se) == 2, ""); + static_assert (same_type <decltype (sd), int>::value, ""); + static_assert (same_type <decltype (se...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (se...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + const auto & [...sf [[]], sg] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (sf) == 2, ""); + static_assert (same_type <decltype (sf...[0]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sf...[1]), const long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sg), const short>::value, ""); + auto [sh, si, sj [[]], ...sk] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (sk) == 0, ""); + static_assert (same_type <decltype (sh), int>::value, ""); + static_assert (same_type <decltype (si), long long>::value, ""); + static_assert (same_type <decltype (sj), short>::value, ""); + auto && [sl, ...sm [[maybe_unused]], sn] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (sm) == 1, ""); + static_assert (same_type <decltype (sl), int>::value, ""); + static_assert (same_type <decltype (sm...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sn), short>::value, ""); + auto [...so] = S { 1, 2, 3 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (so) == 3, ""); + static_assert (same_type <decltype (so...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (so...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (so...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [...sp, sq, sr, ss [[maybe_unused]]] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (sp) == 0, ""); + static_assert (same_type <decltype (sq), int>::value, ""); + static_assert (same_type <decltype (sr), long long>::value, ""); + static_assert (same_type <decltype (ss), short>::value, ""); + auto [st, ...su, sv, sw] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (su) == 0, ""); + static_assert (same_type <decltype (st), int>::value, ""); + static_assert (same_type <decltype (sv), long long>::value, ""); + static_assert (same_type <decltype (sw), short>::value, ""); + if (sa != 1 || sb != 2 || sc != 3 + || sd != 1 || se...[0] != 2 || se...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sf...[0] != 1 || sf...[1] != 2 || sg != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sh != 1 || si != 2 || sj != 3 + || sl != 1 || sm...[0] != 2 || sn != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || so...[0] != 1 || so...[1] != 2 || so...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sq != 1 || sr != 2 || ss != 3 + || st != 1 || sv != 2 || sw != 3 + || sum (se...) != 5 + || sum <decltype (se)...> (se...) != 5 + || sum (square (square (se))...) != 97 + || sum (sf...) != 3 + || sum (sk...) != 0 + || sum (sm...) != 2 + || sum (so...) != 6 + || sum <decltype (so)...> (so...) != 6 + || sum (square (so)...) != 14 + || sum (sp...) != 0 + || sum (su...) != 0 + || (se + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (... + sf) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + sk) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (sm + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (so + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (sp + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + su) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + __builtin_abort (); + S s2[] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; + int i = 0; + for (auto [sx, ...sy [[]]] : s2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (sy) == 2, ""); + static_assert (same_type <decltype (sx), int>::value, ""); + static_assert (same_type <decltype (sy...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sy...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (sx != i * 3 + 1 || sum (sy...) != i * 6 + 5) + __builtin_abort (); + auto fn1 = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn1 (); + auto fn2 = [&sy..., &i] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn2 (); + auto fn3 = [&...sy2 = sy, &i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn3 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn4 = [&...sy3 = ref (sy), &i] () { if (sum (sy3...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn4 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn5 = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn5 (); + auto fn6 = [sy..., i] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn6 (); + auto fn7 = [...sy2 = sy, i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn7 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn8 = [...sy3 = square (sy), i] () { if (sum (sy3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn8 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn9 = [&] () { auto fn = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn9 (); + auto fn10 = [&sy..., &i] () { auto fn = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn10 (); + auto fn11 = [&] () { auto fn = [&...sy2 = sy, &i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn11 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + auto fn12 = [&sy..., &i] () { auto fn = [&...sy3 = ref (sy), &i] () { if (sum (sy3...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn12 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + auto fn13 = [=] () { auto fn = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn13 (); + auto fn14 = [sy..., i] () { auto fn = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn14 (); + auto fn15 = [=] () { auto fn = [...sy2 = sy, i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn15 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + auto fn16 = [&sy..., &i] () { auto fn = [...sy3 = square (sy), i] () { if (sum (sy3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn16 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + ++i; + } + i = 0; + for (auto [...sz] : s2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (sz) == 3, ""); + static_assert (same_type <decltype (sz...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sz...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sz...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (sum (sz...) != i * 9 + 6) + __builtin_abort (); + auto fn = [=] () { if (sum (sz...) != i * 9 + 6) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn (); + ++i; + } + if (auto [...sx, sy] = s) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } + { + static_assert (sizeof... (sx) == 2, ""); + static_assert (same_type <decltype (sx...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sx...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (sy), short>::value, ""); + if (sum (sx...) != 3 || sy != 3) + __builtin_abort (); + } + else + __builtin_abort (); + T t = T { 3, 1, 2 }; + auto [ta, tb, tc] = T { 3, 1, 2 }; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + static_assert (same_type <decltype (ta), int>::value, ""); + static_assert (same_type <decltype (tb), long long>::value, ""); + static_assert (same_type <decltype (tc), short>::value, ""); + auto [td [[maybe_unused]], ...te] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (te) == 2, ""); + static_assert (same_type <decltype (td), int>::value, ""); + static_assert (same_type <decltype (te...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (te...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [...tf [[maybe_unused]], tg] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (tf) == 2, ""); + static_assert (same_type <decltype (tf...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tf...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tg), short>::value, ""); + const auto & [th, ti, tj, ...tk] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (tk) == 0, ""); + static_assert (same_type <decltype (th), const int>::value, ""); + static_assert (same_type <decltype (ti), const long long>::value, ""); + static_assert (same_type <decltype (tj), const short>::value, ""); + auto [tl [[]], ...tm [[]], tn [[]]] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (tm) == 1, ""); + static_assert (same_type <decltype (tl), int>::value, ""); + static_assert (same_type <decltype (tm...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tn), short>::value, ""); + auto && [...to] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (to) == 3, ""); + constexpr size_t tos = sizeof... (to); + static_assert (same_type <decltype (to...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (to...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (to...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [...tp, tq [[]], tr, ts] = T { 3, 1, 2 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (tp) == 0, ""); + static_assert (same_type <decltype (tq), int>::value, ""); + static_assert (same_type <decltype (tr), long long>::value, ""); + static_assert (same_type <decltype (ts), short>::value, ""); + auto [tt, ...tu [[]], tv, tw] = T { 3, 1, 2 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (tu) == 0, ""); + static_assert (same_type <decltype (tt), int>::value, ""); + static_assert (same_type <decltype (tv), long long>::value, ""); + static_assert (same_type <decltype (tw), short>::value, ""); + if (ta != 1 || tb != 2 || tc != 3 + || td != 1 || te...[0] != 2 || te...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || tf...[0] != 1 || tf...[1] != 2 || tg != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || th != 1 || ti != 2 || tj != 3 + || tl != 1 || tm...[0] != 2 || tn != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || to...[0] != 1 || to...[1] != 2 || to...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } } + || tq != 1 || tr != 2 || ts != 3 + || tt != 1 || tv != 2 || tw != 3 + || sum (te...) != 5 + || sum <decltype (te)...> (te...) != 5 + || sum (square (square (te))...) != 97 + || sum (tf...) != 3 + || sum (tk...) != 0 + || sum (tm...) != 2 + || sum (to...) != 6 + || sum <decltype (to)...> (to...) != 6 + || sum (square (to)...) != 14 + || sum (tp...) != 0 + || sum (tu...) != 0 + || (te + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (... + tf) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + tk) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (tm + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (to + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (tp + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + tu) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + __builtin_abort (); + T t2[] = { { 3, 1, 2 }, { 6, 4, 5 }, { 9, 7, 8 } }; + i = 0; + for (auto [tx, ...ty] : t2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (ty) == 2, ""); + static_assert (same_type <decltype (tx), int>::value, ""); + static_assert (same_type <decltype (ty...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ty...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (tx != i * 3 + 1 || sum (ty...) != i * 6 + 5) + __builtin_abort (); + auto fn1 = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; + fn1 (); + auto fn2 = [&ty..., &i] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn2 (); + auto fn3 = [&...ty2 = ty, &i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn3 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn4 = [&...ty3 = ref (ty), &i] () { if (sum (ty3...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn4 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn5 = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; + fn5 (); + auto fn6 = [ty..., i] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn6 (); + auto fn7 = [...ty2 = ty, i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn7 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn8 = [...ty3 = square (ty), i] () { if (sum (ty3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn8 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn9 = [&] () { auto fn = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; + fn9 (); + auto fn10 = [&ty..., &i] () { auto fn = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn10 (); + auto fn11 = [&] () { auto fn = [&...ty2 = ty, &i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn11 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn12 = [&ty..., &i] () { auto fn = [&...ty3 = ref (ty), &i] () { if (sum (ty3...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn12 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + auto fn13 = [=] () { auto fn = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; + fn13 (); + auto fn14 = [ty..., i] () { auto fn = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } } + fn14 (); + auto fn15 = [=] () { auto fn = [...ty2 = ty, i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn15 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + auto fn16 = [&ty..., &i] () { auto fn = [...ty3 = square (ty), i] () { if (sum (ty3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } } + fn16 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 } + // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 } + ++i; + } + i = 0; + for (auto [...tz] : t2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (tz) == 3, ""); + static_assert (same_type <decltype (tz...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tz...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tz...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (sum (tz...) != i * 9 + 6) + __builtin_abort (); + auto fn = [=] () { if (sum (tz...) != i * 9 + 6) __builtin_abort (); }; + fn (); + ++i; + } + if (auto [...tx [[maybe_unused]], ty] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } + __builtin_abort (); + else + { + static_assert (sizeof... (tx) == 2, ""); + static_assert (same_type <decltype (tx...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (tx...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ty), short>::value, ""); + if (sum (tx...) != 3 || ty != 3) + __builtin_abort (); + } + U a[3] = { 1, 2, 3 }; + auto [aa, ab, ac] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + static_assert (same_type <decltype (aa), int>::value, ""); + static_assert (same_type <decltype (ab), int>::value, ""); + static_assert (same_type <decltype (ac), int>::value, ""); + auto [ad [[maybe_unused]], ...ae [[maybe_unused]]] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (ae) == 2, ""); + static_assert (same_type <decltype (ad), int>::value, ""); + static_assert (same_type <decltype (ae...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ae...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [...af, ag] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (af) == 2, ""); + static_assert (same_type <decltype (af...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (af...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ag), int>::value, ""); + auto [ah, ai [[]], aj, ...ak [[]]] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (ak) == 0, ""); + static_assert (same_type <decltype (ah), int>::value, ""); + static_assert (same_type <decltype (ai), int>::value, ""); + static_assert (same_type <decltype (aj), int>::value, ""); + auto [al, ...am [[]], an] = a;// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (am) == 1, ""); + static_assert (same_type <decltype (al), int>::value, ""); + static_assert (same_type <decltype (am...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (an), int>::value, ""); + const auto &[...ao] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (ao) == 3, ""); + static_assert (same_type <decltype (ao...[0]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ao...[1]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ao...[2]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto &&[...ap, aq, ar [[]], as] = a;// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 } + static_assert (sizeof... (ap) == 0, ""); + static_assert (same_type <decltype (aq), int>::value, ""); + static_assert (same_type <decltype (ar), int>::value, ""); + static_assert (same_type <decltype (as), int>::value, ""); + auto [at, ...au, av, aw] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (au) == 0, ""); + static_assert (same_type <decltype (at), int>::value, ""); + static_assert (same_type <decltype (av), int>::value, ""); + static_assert (same_type <decltype (aw), int>::value, ""); + if (aa != 1 || ab != 2 || ac != 3 + || ad != 1 || ae...[0] != 2 || ae...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || af...[0] != 1 || af...[1] != 2 || ag != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || ah != 1 || ai != 2 || aj != 3 + || al != 1 || am...[0] != 2 || an != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || ao...[0] != 1 || ao...[1] != 2 || ao...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } } + || aq != 1 || ar != 2 || as != 3 + || at != 1 || av != 2 || aw != 3 + || sum (ae...) != 5 + || sum <decltype (ae)...> (ae...) != 5 + || sum (square (square (ae))...) != 97 + || sum (af...) != 3 + || sum (ak...) != 0 + || sum (am...) != 2 + || sum (ao...) != 6 + || sum <decltype (ao)...> (ao...) != 6 + || sum (square (ao)...) != 14 + || sum (ap...) != 0 + || sum (au...) != 0 + || (ae + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (... + af) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + ak) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (am + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (ao + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (ap + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + au) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + __builtin_abort (); + return tos; +} + +int +main () +{ + if (foo <S, T, int> () != 3) + __builtin_abort (); +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp16.C b/gcc/testsuite/g++.dg/cpp26/decomp16.C new file mode 100644 index 0000000..548f9af --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp16.C @@ -0,0 +1,240 @@ +// P1061R10 - Structured Bindings can introduce a Pack +// { dg-do run { target c++11 } } +// { dg-options "" } + +int +sum () +{ + return 0; +} + +template <typename T, typename ...A> +T +sum (T x, A... y) +{ + return x + sum (y...); +} + +template <typename T> +T +square (T x) +{ + return x * x; +} + +template <typename T, typename U> +struct same_type { static const bool value = false; }; + +template <typename T> +struct same_type<T, T> { static const bool value = true; }; + +typedef int V __attribute__((vector_size (16 * sizeof (int)))); + +template <int N> +void +foo () +{ + V v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + auto [...va] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (va) == 16, ""); + static_assert (same_type <decltype (va...[5]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (va...[13]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [vb, ...vc, vd, ve] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (vc) == 13, ""); + static_assert (same_type <decltype (vb), int>::value, ""); + static_assert (same_type <decltype (vc...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (vc...[12]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (vd), int>::value, ""); + static_assert (same_type <decltype (ve), int>::value, ""); + auto [vf, vg, vh, vi, ...vj] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (vj) == 12, ""); + static_assert (same_type <decltype (vf), int>::value, ""); + static_assert (same_type <decltype (vg), int>::value, ""); + static_assert (same_type <decltype (vh), int>::value, ""); + static_assert (same_type <decltype (vi), int>::value, ""); + static_assert (same_type <decltype (vj...[2]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (vj...[10]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (va...[13] != 14 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sum (va...) != 8 * 17 + || sum (square (va)...) != 1496 + || vb != 1 + || vc...[10] != 12 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sum (vc...) != 15 * 7 - 1 + || sum <decltype (vc)...> (vc...) != 15 * 7 - 1 + || vd != 15 || ve != 16 + || vf != 1 || vg != 2 || vh != 3 || vi != 4 + || sum (vj...) != 8 * 17 - 10 + || (va + ...) != 8 * 17 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (... + vc) != 15 * 7 - 1 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + vj) != 8 * 17 - 10) // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + __builtin_abort (); + V v2[3] = { v, v + 1, v + 2 }; + int i = 0; + for (auto [vk, ...vl, vm] : v2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (vl) == 14, ""); + static_assert (same_type <decltype (vk), int>::value, ""); + static_assert (same_type <decltype (vl...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (vl...[9]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (vm), int>::value, ""); + if (vk != i + 1 || sum (vl...) != i * 14 + 15 * 8 - 1 || vm != i + 16) + __builtin_abort (); + ++i; + } + _Complex double c = 1.0 + 2.0i; + auto [...ca] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (ca) == 2, ""); + static_assert (same_type <decltype (ca...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ca...[1]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [cb, ...cc, cd] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (cc) == 0, ""); + static_assert (same_type <decltype (cb), double>::value, ""); + static_assert (same_type <decltype (cd), double>::value, ""); + auto [ce, ...cf] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (cf) == 1, ""); + static_assert (same_type <decltype (ce), double>::value, ""); + static_assert (same_type <decltype (cf...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [...cg, ch] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (cg) == 1, ""); + static_assert (same_type <decltype (cg...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ch), double>::value, ""); + if (ca...[0] != 1.0 || ca...[1] != 2.0// { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sum (ca...) != 3.0 + || sum <decltype (ca)...> (ca...) != 3.0 + || sum (square (square (square (ca)))...) != 257.0 + || cb != 1.0 || cd != 2.0 + || ce != 1.0 || cf...[0] != 2.0 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sum (cf...) != 2.0 + || cg...[0] != 1.0 || ch != 2.0 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sum (cg...) != 1.0 + || (ca + ...) != 3.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0.0 + ... + cc) != 0.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (... + cf) != 2.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (cg + ... + 0.0) != 1.0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + __builtin_abort (); + _Complex float c2[3] = { 1.0f + 2.0fi, 2.0f + 3.0fi, 3.0f + 4.0fi }; + i = 0; + for (auto [...ci] : c2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (ci) == 2, ""); + static_assert (same_type <decltype (ci...[0]), float>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ci...[1]), float>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (sum (ci...) != i * 2 + 3.0f) + __builtin_abort (); + ++i; + } +} + +template <typename V, typename C, typename D> +void +bar () +{ + V v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + auto [...va] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (va) == 16, ""); + static_assert (same_type <decltype (va...[5]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (va...[13]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [vb, ...vc, vd, ve] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (vc) == 13, ""); + static_assert (same_type <decltype (vb), int>::value, ""); + static_assert (same_type <decltype (vc...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (vc...[12]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (vd), int>::value, ""); + static_assert (same_type <decltype (ve), int>::value, ""); + auto [vf, vg, vh, vi, ...vj] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (vj) == 12, ""); + static_assert (same_type <decltype (vf), int>::value, ""); + static_assert (same_type <decltype (vg), int>::value, ""); + static_assert (same_type <decltype (vh), int>::value, ""); + static_assert (same_type <decltype (vi), int>::value, ""); + static_assert (same_type <decltype (vj...[2]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (vj...[10]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (va...[13] != 14 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sum (va...) != 8 * 17 + || vb != 1 + || vc...[10] != 12 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sum (vc...) != 15 * 7 - 1 + || sum <decltype (vc)...> (vc...) != 15 * 7 - 1 + || vd != 15 || ve != 16 + || vf != 1 || vg != 2 || vh != 3 || vi != 4 + || sum (vj...) != 8 * 17 - 10 + || (va + ...) != 8 * 17 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (... + vc) != 15 * 7 - 1 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0 + ... + vj) != 8 * 17 - 10) // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + __builtin_abort (); + V v2[3] = { v, v + 1, v + 2 }; + int i = 0; + for (auto [vk, ...vl, vm] : v2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (vl) == 14, ""); + static_assert (same_type <decltype (vk), int>::value, ""); + static_assert (same_type <decltype (vl...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (vl...[9]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (vm), int>::value, ""); + if (vk != i + 1 || sum (vl...) != i * 14 + 15 * 8 - 1 || vm != i + 16) + __builtin_abort (); + ++i; + } + C c = 1.0 + 2.0i; + auto [...ca] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (ca) == 2, ""); + static_assert (same_type <decltype (ca...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ca...[1]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [cb, ...cc, cd] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (cc) == 0, ""); + static_assert (same_type <decltype (cb), double>::value, ""); + static_assert (same_type <decltype (cd), double>::value, ""); + auto [ce, ...cf] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (cf) == 1, ""); + static_assert (same_type <decltype (ce), double>::value, ""); + static_assert (same_type <decltype (cf...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + auto [...cg, ch] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (cg) == 1, ""); + static_assert (same_type <decltype (cg...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ch), double>::value, ""); + if (ca...[0] != 1.0 || ca...[1] != 2.0// { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sum (ca...) != 3.0 + || sum <decltype (ca)...> (ca...) != 3.0 + || cb != 1.0 || cd != 2.0 + || ce != 1.0 || cf...[0] != 2.0 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sum (cf...) != 2.0 + || cg...[0] != 1.0 || ch != 2.0 // { dg-warning "pack indexing only available with" "" { target c++23_down } } + || sum (cg...) != 1.0 + || (ca + ...) != 3.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (0.0 + ... + cc) != 0.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (... + cf) != 2.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + || (cg + ... + 0.0) != 1.0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } } + __builtin_abort (); + D c2[3] = { 1.0f + 2.0fi, 2.0f + 3.0fi, 3.0f + 4.0fi }; + i = 0; + for (auto [...ci] : c2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (ci) == 2, ""); + static_assert (same_type <decltype (ci...[0]), float>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + static_assert (same_type <decltype (ci...[1]), float>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } } + if (sum (ci...) != i * 2 + 3.0f) + __builtin_abort (); + ++i; + } +} + +int +main () +{ + foo <0> (); + bar <V, _Complex double, _Complex float> (); +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp17.C b/gcc/testsuite/g++.dg/cpp26/decomp17.C new file mode 100644 index 0000000..49ad0e2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp17.C @@ -0,0 +1,28 @@ +// P1061R10 - Structured Bindings can introduce a Pack +// { dg-do compile { target c++11 } } +// { dg-options "" } + +typedef int V __attribute__((vector_size (16 * sizeof (int)))); + +template <int N> +void +foo () +{ + V v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + auto [va, vb, vc, vd, ...ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq, vr] = v; + // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } .-1 } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-2 } + // { dg-error "18 names provided for structured binding" "" { target *-*-* } .-3 } + // { dg-message "while '__vector\\\(16\\\) int' decomposes into 16 elements" "" { target *-*-* } .-4 } + _Complex double c = 1.0 + 2.0i; + auto [...ca, cb, cc, cd] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-error "4 names provided for structured binding" "" { target *-*-* } .-2 } + // { dg-message "while '__complex__ double' decomposes into 2 elements" "" { target *-*-* } .-3 } +} + +int +main () +{ + foo <0> (); +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp18.C b/gcc/testsuite/g++.dg/cpp26/decomp18.C new file mode 100644 index 0000000..86b9bf4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp18.C @@ -0,0 +1,109 @@ +// P1061R10 - Structured Bindings can introduce a Pack +// { dg-do run { target c++11 } } +// { dg-options "" } + +struct S { int a, b, c; }; +namespace std { + template <typename T> struct tuple_size; + template <int, typename> struct tuple_element; +} +struct T { + int a[3]; + template <int I> + int &get () { return a[2 - I]; } +}; +template <> +struct std::tuple_size<T> { static constexpr int value = 3; }; +template <int N> +struct std::tuple_element<N, T> { typedef int type; }; + +template <int N> +inline int +foo () +{ + static int a[4] = { N, N + 1, N + 2, N + 3 }; + static auto [...aa] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } + aa...[1]++; // { dg-warning "pack indexing only available with" "" { target c++23_down } } + return (... + aa); // { dg-warning "fold-expressions only available with" "" { target c++14_down } } +} + +template <int N> +inline int +bar () +{ + static S s = { N, N + 1, N + 2 }; + static auto [...sa] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } + sa...[1]++; // { dg-warning "pack indexing only available with" "" { target c++23_down } } + return (sa + ...); // { dg-warning "fold-expressions only available with" "" { target c++14_down } } +} + +template <int N> +inline int +baz () +{ + static T t = { { N, N + 1, N + 2 } }; + static auto [ta, ...tb, tc, td] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } + tc++; + return ((ta + tc + td) + ... + tb); // { dg-warning "fold-expressions only available with" "" { target c++14_down } } +} + +template <int N> +inline int +qux () +{ + thread_local int a[4] = { N, N + 1, N + 2, N + 3 }; + thread_local auto [...aa] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } .-2 } + aa...[1]++; // { dg-warning "pack indexing only available with" "" { target c++23_down } } + return (... + aa); // { dg-warning "fold-expressions only available with" "" { target c++14_down } } +} + +template <int N> +inline int +freddy () +{ + thread_local S s = { N, N + 1, N + 2 }; + thread_local auto [...sa] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } .-2 } + sa...[1]++; // { dg-warning "pack indexing only available with" "" { target c++23_down } } + return (sa + ...); // { dg-warning "fold-expressions only available with" "" { target c++14_down } } +} + +template <int N> +inline int +corge () +{ + thread_local T t = { { N, N + 1, N + 2 } }; + thread_local auto [ta, ...tb, tc, td] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } .-2 } + tc++; + return ((ta + tc + td) + ... + tb); // { dg-warning "fold-expressions only available with" "" { target c++14_down } } +} + +int +main () +{ + if (foo <2> () != 15 || foo <2> () != 16 || foo <2> () != 17 + || foo <42> () != 175 || foo <42> () != 176 + || bar <5> () != 19 || bar <5> () != 20 || bar <5> () != 21 + || bar <18> () != 58 || bar <18> () != 59 + || baz <3> () != 13 || baz <3> () != 14 || baz <3> () != 15 + || baz <22> () != 70 || baz <22> () != 71) + __builtin_abort (); + if (qux <2> () != 15 || qux <2> () != 16 || qux <2> () != 17 + || qux <42> () != 175 || qux <42> () != 176 + || freddy <5> () != 19 || freddy <5> () != 20 || freddy <5> () != 21 + || freddy <18> () != 58 || freddy <18> () != 59 + || corge <3> () != 13 || corge <3> () != 14 || corge <3> () != 15 + || corge <22> () != 70 || corge <22> () != 71) + __builtin_abort (); +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp19.C b/gcc/testsuite/g++.dg/cpp26/decomp19.C new file mode 100644 index 0000000..b4d97a1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp19.C @@ -0,0 +1,46 @@ +// P1061R10 - Structured Bindings can introduce a Pack +// { dg-do compile { target c++11 } } +// { dg-options "" } + +namespace std { + template <typename T> struct tuple_size; + template <int, typename> struct tuple_element; +} +struct T { + int a[3]; + template <int I> + int &get () { return a[2 - I]; } +}; +template <> +struct std::tuple_size<T> { static constexpr int value = 3; }; +template <int N> +struct std::tuple_element<N, T> { typedef int type; }; + +template <int N> +inline void +foo () +{ + static T t = { { N, N + 1, N + 2 } }; + static auto [ta, ...tb, tc] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } + // { dg-message "mangling of structured binding pack elements not implemented yet" "" { target *-*-* } .-3 } +} + +template <int N> +inline void +bar () +{ + thread_local T t = { { N, N + 1, N + 2 } }; + thread_local auto [...ta] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + // { dg-warning "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } .-2 } + // { dg-message "mangling of structured binding pack elements not implemented yet" "" { target *-*-* } .-3 } +} + +int +main () +{ + foo <0> (); + bar <0> (); +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp20.C b/gcc/testsuite/g++.dg/cpp26/decomp20.C new file mode 100644 index 0000000..5091e13 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp20.C @@ -0,0 +1,53 @@ +// P1061R10 - Structured Bindings can introduce a Pack +// { dg-do compile { target c++11 } } +// { dg-options "" } + +struct S { + explicit operator bool () const noexcept { return true; } +}; +namespace std { + template <typename T> struct tuple_size; + template <int, typename> struct tuple_element; +} +int x; +struct T { + template <int I> + int &get () { return x; } + explicit operator bool () const noexcept { return false; } +}; +template <> +struct std::tuple_size<T> { static constexpr int value = 0; }; +template <int N> +struct std::tuple_element<N, T> { typedef int type; }; + +template <int N> +void +foo () +{ + int a[0] = {}; + auto [...aa] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (aa) == 0, ""); + S s = {}; + auto [...sa] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (sa) == 0, ""); + T t = {}; + auto [...ta] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (ta) == 0, ""); + if (auto [...sb] = s) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } + static_assert (sizeof... (sb) == 0, ""); + else + __builtin_abort (); + if (auto [...tb] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } + __builtin_abort (); + else + static_assert (sizeof... (tb) == 0, ""); +} + +int +main () +{ + foo <0> (); +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp21.C b/gcc/testsuite/g++.dg/cpp26/decomp21.C new file mode 100644 index 0000000..6baa8aa --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp21.C @@ -0,0 +1,103 @@ +// P1061R10 - Structured Bindings can introduce a Pack +// { dg-do run { target c++11 } } +// { dg-options "" } + +using size_t = decltype (sizeof 0); + +auto g () -> int (&)[4] +{ + static int a[4] = { 1, 2, 3, 4 }; + return a; +} + +template <size_t N> +void +h (int (&arr)[N]) +{ + auto [a, ...b, c] = arr; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (b) == 2, ""); + auto &[f, ...g, h] = arr; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (g) == 2, ""); + if (&f != &arr[0] || &h != &arr[3] + || &g...[0] != &arr[1] || &g...[1] != &arr[2]) // { dg-warning "pack indexing only available with" "" { target c++23_down } } + __builtin_abort (); + auto &[...e] = arr; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof ... (e) == 4, ""); + if (&e...[0] != &arr[0] || &e...[3] != &arr[3]) // { dg-warning "pack indexing only available with" "" { target c++23_down } } + __builtin_abort (); +} + +struct C { int x, y, z; }; + +template <class T> +void +now_i_know_my () +{ + auto [a, b, c] = C (); // { dg-warning "structured bindings only available with" "" { target c++14_down } } + auto [d, ...e] = C (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (e) == 2, ""); + auto [...f, g] = C (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (f) == 2, ""); + auto [h, i, j, ...k] = C (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (k) == 0, ""); +// auto [l, m, n, o, ...p] = C (); +} + +auto foo () -> int (&)[2] +{ + static int a[2] = { 1, 2 }; + return a; +} + +template <class T> +void +bar () +{ + auto [...a] = foo (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (a) == 2, ""); + auto [b, c, ...d] = foo (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + static_assert (sizeof... (d) == 0, ""); +} + +struct D { }; + +void +baz (...) +{ + __builtin_abort (); +} + +template <typename T> +void +qux () +{ + D arr[1] = {}; + auto [...e] = arr; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + baz (e...); +} + +int d; + +void +baz (D) +{ + d = 1; +} + +int +main () +{ + h (g ()); + now_i_know_my <int> (); + bar <int> (); + qux <int> (); +} diff --git a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C index cfc5f61..9284bc2 100644 --- a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C +++ b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C @@ -395,8 +395,8 @@ #ifndef __cpp_structured_bindings # error "__cpp_structured_bindings" -#elif __cpp_structured_bindings != 202403 -# error "__cpp_structured_bindings != 202403" +#elif __cpp_structured_bindings != 202411 +# error "__cpp_structured_bindings != 202411" #endif #ifndef __cpp_template_template_args diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c new file mode 100644 index 0000000..f80baf3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +struct vec_char_16 +{ + unsigned char raw[2]; +}; + +static inline struct vec_char_16 +Dup128VecFromValues(unsigned char t0, unsigned char t1) +{ + struct vec_char_16 result; + result.raw[0] = t0; + result.raw[1] = t1; + return result; +} + +int f(unsigned char t0, unsigned char t1) +{ + struct vec_char_16 a = Dup128VecFromValues(t0, t1); + struct vec_char_16 b; + __builtin_memcpy(&b, &a, sizeof(a)); + return b.raw[0] + b.raw[1]; +} + +/* Ideally we'd optimize this at FRE1 time but we only replace + the loads from b.raw[] with BIT_FIELD_REFs which get optimized + only later in the next FRE. */ +/* { dg-final { scan-tree-dump-not "MEM" "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sme/pr121414_1.c b/gcc/testsuite/gcc.target/aarch64/sme/pr121414_1.c new file mode 100644 index 0000000..ad8600f --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sme/pr121414_1.c @@ -0,0 +1,27 @@ +#pragma GCC target "+sme2" + +void f1() __arm_streaming_compatible {} +void f2() __arm_streaming {} +void f3() __arm_in("za") {} +void f4() __arm_out("za") {} +void f5() __arm_inout("za") {} +void f6() __arm_in("zt0") {} +void f7() __arm_out("zt0") {} +void f8() __arm_inout("zt0") {} + +__arm_locally_streaming void g1() {} +__arm_new("za") void g2() {} +__arm_new("zt0") void g3() {} + +/* { dg-final { scan-assembler {\t\.variant_pcs\tf1\n} } } */ +/* { dg-final { scan-assembler {\t\.variant_pcs\tf2\n} } } */ +/* { dg-final { scan-assembler {\t\.variant_pcs\tf3\n} } } */ +/* { dg-final { scan-assembler {\t\.variant_pcs\tf4\n} } } */ +/* { dg-final { scan-assembler {\t\.variant_pcs\tf5\n} } } */ +/* { dg-final { scan-assembler {\t\.variant_pcs\tf6\n} } } */ +/* { dg-final { scan-assembler {\t\.variant_pcs\tf7\n} } } */ +/* { dg-final { scan-assembler {\t\.variant_pcs\tf8\n} } } */ + +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tg1\n} } } */ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tg2\n} } } */ +/* { dg-final { scan-assembler-not {\t\.variant_pcs\tg3\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr120718.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr120718.c new file mode 100644 index 0000000..9ca0938 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr120718.c @@ -0,0 +1,12 @@ +/* { dg-options "-O2" } */ + +#include <arm_sve.h> +typedef int __attribute__((vector_size(8))) v2si; +typedef struct { int x; int y; } A; +void bar(A a); +void foo() +{ + A a; + *(v2si *)&a = (v2si){0, (int)svcntd_pat(SV_ALL)}; + bar(a); +} diff --git a/gcc/testsuite/gcc.target/i386/pr90579.c b/gcc/testsuite/gcc.target/i386/pr90579.c index ab48a44..bd2fd33 100644 --- a/gcc/testsuite/gcc.target/i386/pr90579.c +++ b/gcc/testsuite/gcc.target/i386/pr90579.c @@ -16,8 +16,5 @@ loop (int k, double x) return t; } -/* Verify we end up with scalar loads from r for the final sum. */ -/* { dg-final { scan-assembler "vaddsd\tr\\\+40" } } */ -/* { dg-final { scan-assembler "vaddsd\tr\\\+32" } } */ -/* { dg-final { scan-assembler "vaddsd\tr\\\+24" } } */ -/* { dg-final { scan-assembler "vaddsd\tr\\\+16" } } */ +/* Verify we end up with no loads from r. */ +/* { dg-final { scan-assembler-not "v\[ma\]\[^\t \]+\tr" } } */ diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index 00315d1..1c113f8 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -5633,6 +5633,28 @@ visit_nary_op (tree lhs, gassign *stmt) } } break; + case BIT_FIELD_REF: + if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == SSA_NAME) + { + tree op0 = TREE_OPERAND (rhs1, 0); + gassign *ass = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op0)); + if (ass + && !gimple_has_volatile_ops (ass) + && vn_get_stmt_kind (ass) == VN_REFERENCE) + { + tree last_vuse = gimple_vuse (ass); + tree op = build3 (BIT_FIELD_REF, TREE_TYPE (rhs1), + gimple_assign_rhs1 (ass), + TREE_OPERAND (rhs1, 1), TREE_OPERAND (rhs1, 2)); + tree result = vn_reference_lookup (op, gimple_vuse (ass), + default_vn_walk_kind, + NULL, true, &last_vuse); + if (result + && useless_type_conversion_p (type, TREE_TYPE (result))) + return set_ssa_val_to (lhs, result); + } + } + break; case TRUNC_DIV_EXPR: if (TYPE_UNSIGNED (type)) break; diff --git a/libgcobol/Makefile.am b/libgcobol/Makefile.am index 0a17d20..1e3d3432 100644 --- a/libgcobol/Makefile.am +++ b/libgcobol/Makefile.am @@ -42,6 +42,7 @@ libgcobol_la_SOURCES = \ intrinsic.cc \ io.cc \ libgcobol.cc \ + stringbin.cc \ valconv.cc WARN_CFLAGS = -W -Wall -Wwrite-strings diff --git a/libgcobol/Makefile.in b/libgcobol/Makefile.in index 5fdc42c..42dc823 100644 --- a/libgcobol/Makefile.in +++ b/libgcobol/Makefile.in @@ -178,7 +178,7 @@ libgcobol_la_LIBADD = @BUILD_LIBGCOBOL_TRUE@am_libgcobol_la_OBJECTS = charmaps.lo \ @BUILD_LIBGCOBOL_TRUE@ constants.lo gfileio.lo gmath.lo \ @BUILD_LIBGCOBOL_TRUE@ intrinsic.lo io.lo libgcobol.lo \ -@BUILD_LIBGCOBOL_TRUE@ valconv.lo +@BUILD_LIBGCOBOL_TRUE@ stringbin.lo valconv.lo libgcobol_la_OBJECTS = $(am_libgcobol_la_OBJECTS) @BUILD_LIBGCOBOL_TRUE@am_libgcobol_la_rpath = -rpath $(toolexeclibdir) AM_V_P = $(am__v_P_@AM_V@) @@ -404,6 +404,7 @@ gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER) @BUILD_LIBGCOBOL_TRUE@ intrinsic.cc \ @BUILD_LIBGCOBOL_TRUE@ io.cc \ @BUILD_LIBGCOBOL_TRUE@ libgcobol.cc \ +@BUILD_LIBGCOBOL_TRUE@ stringbin.cc \ @BUILD_LIBGCOBOL_TRUE@ valconv.cc @BUILD_LIBGCOBOL_TRUE@WARN_CFLAGS = -W -Wall -Wwrite-strings @@ -526,6 +527,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intrinsic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcobol.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stringbin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/valconv.Plo@am__quote@ .cc.o: diff --git a/libgcobol/libgcobol.cc b/libgcobol/libgcobol.cc index c3d78d4..a7b4b55 100644 --- a/libgcobol/libgcobol.cc +++ b/libgcobol/libgcobol.cc @@ -72,6 +72,8 @@ #include <sys/time.h> #include <execinfo.h> #include "exceptl.h" +#include "stringbin.h" + /* BSD extension. */ #if !defined(LOG_PERROR) @@ -798,7 +800,7 @@ __gg__power_of_ten(int n) fprintf(stderr, "Trying to raise 10 to %d as an int128, which we can't do.\n", n); - fprintf(stderr, "The problem is in %s.\n", __func__); + fprintf(stderr, "The problem is in %s %s:%d.\n", __func__, __FILE__, __LINE__); abort(); } if( n <= MAX_POWER ) @@ -875,56 +877,6 @@ __gg__scale_by_power_of_ten_2(__int128 value, int N) return value; } -extern "C" -bool -__gg__binary_to_string(char *result, int digits, __int128 value) - { - // The result is not terminated, because this routine is used - // to put information directly into cblc_field_t::data - // Our caller has to keep track of whether value was negative. - - // Note that this routine operates in the source code-set space; that is - // the result comes back with zero as an ASCII 0x30, not an EBCDIC 0xF0 - - if( value < 0 ) - { - value = -value; - } - result += digits-1 ; - while( digits-- ) - { - *result-- = value%10 + ascii_zero; - value /= 10; - } - // Should value be non-zero, it means we potentially have a size error - return value != 0; - } - -extern "C" -bool -__gg__binary_to_string_internal(char *result, int digits, __int128 value) - { - // The result is not terminated, because this routine is used - // to put information directly into cblc_field_t::data - // Our caller has to keep track of whether value was negative. - - // Note that this routine operates in the source code-set space; that is - // the result comes back with zero as an ASCII 0x30, not an EBCDIC 0xF0 - - if( value < 0 ) - { - value = -value; - } - result += digits-1 ; - while( digits-- ) - { - *result-- = (value%10) + internal_zero; - value /= 10; - } - // Should value be non-zero, it means we potentially have a size error - return value != 0; - } - static bool value_is_too_big(const cblc_field_t *var, __int128 value, @@ -1617,9 +1569,13 @@ int128_to_field(cblc_field_t *var, // Note that sending a signed value to an alphanumeric strips off // any plus or minus signs. + memset(location, 0, length); size_error = __gg__binary_to_string_internal( - PTRCAST(char, location), - length, value); + PTRCAST(char, location), + length > MAX_FIXED_POINT_DIGITS + ? MAX_FIXED_POINT_DIGITS + : length, + value); break; case FldNumericDisplay: @@ -1708,7 +1664,7 @@ int128_to_field(cblc_field_t *var, // At this point, value is scaled to the target's rdigits - size_error = __gg__binary_to_string(ach, var->digits, value); + size_error = __gg__binary_to_string_ascii(ach, var->digits, value); ach[var->digits] = NULLCH; // Convert that string according to the PICTURE clause @@ -1749,7 +1705,7 @@ int128_to_field(cblc_field_t *var, case FldAlphaEdited: { char ach[128]; - size_error = __gg__binary_to_string(ach, length, value); + size_error = __gg__binary_to_string_ascii(ach, length, value); ach[length] = NULLCH; // Convert that string according to the PICTURE clause @@ -6126,7 +6082,7 @@ __gg__move( cblc_field_t *fdest, // Convert it to the full complement of digits available // from the source...but no more - __gg__binary_to_string(ach, source_digits, value); + __gg__binary_to_string_ascii(ach, source_digits, value); // Binary to string returns ASCII characters: for(int i=0; i<source_digits; i++) diff --git a/libgcobol/stringbin.cc b/libgcobol/stringbin.cc new file mode 100644 index 0000000..d35ea82 --- /dev/null +++ b/libgcobol/stringbin.cc @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <algorithm> +#include <cctype> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <ctime> +#include <set> +#include <stack> +#include <string> +#include <unordered_map> +#include <vector> + +#include <dirent.h> +#include <dlfcn.h> +#include <err.h> +#include <fcntl.h> +#include <fenv.h> +#include <math.h> // required for fpclassify(3), not in cmath +#include <setjmp.h> +#include <signal.h> +#include <syslog.h> +#include <unistd.h> +#include <stdarg.h> +#if __has_include(<errno.h>) +# include <errno.h> // for program_invocation_short_name +#endif + +#include "config.h" +#include "libgcobol-fp.h" + +#include "ec.h" +#include "common-defs.h" +#include "io.h" +#include "gcobolio.h" +#include "libgcobol.h" +#include "gfileio.h" +#include "charmaps.h" +#include "valconv.h" +#include <sys/mman.h> +#include <sys/resource.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/time.h> +#include <execinfo.h> +#include "exceptl.h" +#include "stringbin.h" + +/* This routine evolved from a primitive binary-to-string routine that simply + peeled digits off the bottom of an __int128 by using + + value % 10 + '0'; + value /= 10; + + That turns out to be unnecessarily slow. + + The routine implemented here uses a divide-and-conquer approach to + minimimizing the number of operations, and when you get down to two + digits it does a divide-by-100 and uses the remainder in a table lookup + to get the digits. */ + +/* These static tables are born of a pathologic desire to avoid calculations. + Whether that paranoia is justified (perhaps "digit%10 + '0';" ) would + actually be faster) is currently untested. But I figured this would be + pretty darn fast. + + Use them when you know the index is between zero and one hundred. */ + +static const char digit_low[100] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + }; + +static const char digit_high[100] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + }; + +static char combined_string[128]; +static char zero_char; + +typedef struct + { + int start; + int run; + union + { + unsigned __int128 val128; + uint64_t val64; + uint32_t val32; + uint16_t val16; + uint8_t val8; + }; + } COMBINED; + +static +void +string_from_combined(const COMBINED &combined) + { + COMBINED left; + COMBINED right; + + uint16_t v16; + + switch(combined.run) + { + case 1: + // We know that val8 is a single digit + combined_string[combined.start] = combined.val8 + zero_char;; + break; + + case 2: + // We know that val8 has two digits + combined_string[combined.start] = digit_high[combined.val8] + zero_char; + combined_string[combined.start+1] = digit_low [combined.val8] + zero_char; + break; + + case 3: + // We know that val16 has three digits. + v16 = combined.val16; + combined_string[combined.start] = v16 / 100 + zero_char; + v16 %= 100; + combined_string[combined.start+1] = v16 / 10 + zero_char; + combined_string[combined.start+2] = v16 % 10 + zero_char; + break; + + case 4: + // We know that val16 has four digits: + v16 = combined.val16; + combined_string[combined.start] = v16 / 1000 + zero_char; + v16 %= 1000; + combined_string[combined.start+1] = v16 / 100 + zero_char; + v16 %= 100; + combined_string[combined.start+2] = v16 / 10 + zero_char; + combined_string[combined.start+3] = v16 % 10 + zero_char; + break; + + case 5: + case 6: + case 7: + case 8: + // We know that val32 can be treated as two 4-digit pieces + left.start = combined.start; + left.run = combined.run - 4; + left.val16 = combined.val32 / 10000; + + right.start = combined.start+left.run; + right.run = 4; + right.val16 = combined.val32 % 10000; + + string_from_combined(left); + string_from_combined(right); + break; + + case 9: + // We break val32 into a 1-digit piece, and an 8-digit piece: + left.start = combined.start; + left.run = combined.run - 8; + left.val32 = combined.val32 / 100000000; + + right.start = combined.start+left.run; + right.run = 8; + right.val32 = combined.val32 % 100000000; + + string_from_combined(left); + string_from_combined(right); + break; + + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + // We know we can treat val64 as two 9-digit pieces: + left.start = combined.start; + left.run = combined.run - 9; + left.val32 = combined.val64 / 1000000000; + + right.start = combined.start+left.run; + right.run = 9; + right.val32 = combined.val64 % 1000000000; + + string_from_combined(left); + string_from_combined(right); + break; + + case 19: + // We split off the bottom nine digits + left.start = combined.start; + left.run = combined.run - 9; + left.val64 = combined.val64 / 1000000000; + + right.start = combined.start+left.run; + right.run = 9; + right.val32 = combined.val64 % 1000000000; + + string_from_combined(left); + string_from_combined(right); + break; + + default: + // For twenty or more digits we peel eighteen digits at a time off the + // right side: + left.start = combined.start; + left.run = combined.run - 18; + left.val128 = combined.val128 / 1000000000000000000ULL; + + right.start = combined.start+left.run; + right.run = 18; + right.val64 = combined.val128 % 1000000000000000000ULL; + + string_from_combined(left); + string_from_combined(right); + break; + } + } + +bool +__gg__binary_to_string_ascii(char *result, int digits, __int128 value) + { + zero_char = ascii_zero; + + // Note that this routine does not terminate the generated string with a + // NUL. This routine is sometimes used to generate a NumericDisplay string + // of digits in place, with no terminator. + __int128 mask = __gg__power_of_ten(digits); + + COMBINED combined; + if( value < 0 ) + { + value = -value; + } + + // A non-zero retval means the number was too big to fit into the desired + // number of digits: + bool retval = !!(value / mask); + + // mask off the bottom digits to avoid garbage when value is too large + value %= mask; + + combined.start = 0; + combined.run = digits; + combined.val128 = value; + string_from_combined(combined); + memcpy(result, combined_string, digits); + return retval; + } + +bool +__gg__binary_to_string_internal(char *result, int digits, __int128 value) + { + zero_char = internal_zero; + + // Note that this routine does not terminate the generated string with a + // NUL. This routine is sometimes used to generate a NumericDisplay string + // of digits in place, with no terminator. + __int128 mask = __gg__power_of_ten(digits); + + COMBINED combined; + if( value < 0 ) + { + value = -value; + } + + // A non-zero retval means the number was too big to fit into the desired + // number of digits: + bool retval = !!(value / mask); + + // mask off the bottom digits to avoid garbage when value is too large + value %= mask; + + combined.start = 0; + combined.run = digits; + combined.val128 = value; + string_from_combined(combined); + memcpy(result, combined_string, digits); + return retval; + } + diff --git a/libgcobol/stringbin.h b/libgcobol/stringbin.h new file mode 100644 index 0000000..0276704 --- /dev/null +++ b/libgcobol/stringbin.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef STRINGBIN_H_ +#define STRINGBIN_H_ + +extern "C" +bool __gg__binary_to_string_ascii(char *result, + int digits, + __int128 value); +extern "C" +bool __gg__binary_to_string_internal( char *result, + int digits, + __int128 value); + +#endif diff --git a/libstdc++-v3/doc/html/manual/appendix_porting.html b/libstdc++-v3/doc/html/manual/appendix_porting.html index 887fa50..7b63613 100644 --- a/libstdc++-v3/doc/html/manual/appendix_porting.html +++ b/libstdc++-v3/doc/html/manual/appendix_porting.html @@ -26,7 +26,7 @@ Support for C++11 dialect. </a></span></dt><dt><span class="section"><a href="backwards.html#backwards.third.iterator_type"> <code class="code">Container::iterator_type</code> is not necessarily <code class="code">Container::value_type*</code> </a></span></dt></dl></dd></dl></dd></dl></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="appendix.porting.build_hacking"></a>Configure and Build Hacking</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="build_hacking.prereq"></a>Prerequisites</h3></div></div></div><p> - As noted <a class="link" href="http://gcc.gnu.org/install/prerequisites.html" target="_top">previously</a>, + As noted <a class="link" href="https://gcc.gnu.org/install/prerequisites.html" target="_top">previously</a>, certain other tools are necessary for hacking on files that control configure (<code class="code">configure.ac</code>, <code class="code">acinclude.m4</code>) and make diff --git a/libstdc++-v3/doc/xml/manual/build_hacking.xml b/libstdc++-v3/doc/xml/manual/build_hacking.xml index 20de49f..4c044d9 100644 --- a/libstdc++-v3/doc/xml/manual/build_hacking.xml +++ b/libstdc++-v3/doc/xml/manual/build_hacking.xml @@ -17,7 +17,7 @@ <section xml:id="build_hacking.prereq"><info><title>Prerequisites</title></info> <para> - As noted <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://gcc.gnu.org/install/prerequisites.html">previously</link>, + As noted <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://gcc.gnu.org/install/prerequisites.html">previously</link>, certain other tools are necessary for hacking on files that control configure (<code>configure.ac</code>, <code>acinclude.m4</code>) and make |