/* Old macro, superseded by
__cpp_nontype_template_parameter_auto. */
cpp_define (pfile, "__cpp_template_auto=201606L");
- cpp_define (pfile, "__cpp_structured_bindings=201606L");
+ if (cxx_dialect <= cxx23)
+ cpp_define (pfile, "__cpp_structured_bindings=201606L");
cpp_define (pfile, "__cpp_variadic_using=201611L");
cpp_define (pfile, "__cpp_guaranteed_copy_elision=201606L");
cpp_define (pfile, "__cpp_nontype_template_parameter_auto=201606L");
cpp_define (pfile, "__cpp_constexpr=202306L");
cpp_define (pfile, "__cpp_static_assert=202306L");
cpp_define (pfile, "__cpp_placeholder_variables=202306L");
+ cpp_define (pfile, "__cpp_structured_bindings=202403L");
}
if (flag_concepts)
{
/* Parse the identifier-list. */
auto_vec<cp_expr, 10> v;
+ bool attr_diagnosed = false;
+ int first_attr = -1;
+ unsigned int cnt = 0;
if (!cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_SQUARE))
while (true)
{
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)
+ {
+ pedwarn (cp_lexer_peek_token (parser->lexer)->location,
+ OPT_Wc__26_extensions,
+ "structured bindings with attributed identifiers "
+ "only available with %<-std=c++2c%> or "
+ "%<-std=gnu++2c%>");
+ attr_diagnosed = true;
+ }
+ attr = cp_parser_std_attribute_spec_seq (parser);
+ if (attr == error_mark_node)
+ attr = NULL_TREE;
+ if (attr && first_attr == -1)
+ first_attr = v.length ();
+ }
v.safe_push (e);
+ ++cnt;
+ if (first_attr != -1)
+ v.safe_push (attr);
if (!cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
break;
cp_lexer_consume_token (parser->lexer);
declarator->id_loc = e.get_location ();
}
tree elt_pushed_scope;
+ tree attr = NULL_TREE;
+ if (first_attr != -1 && i >= (unsigned) first_attr)
+ attr = v[++i].get_value ();
tree decl2 = start_decl (declarator, &decl_specs, SD_DECOMPOSITION,
- NULL_TREE, NULL_TREE, &elt_pushed_scope);
+ NULL_TREE, attr, &elt_pushed_scope);
if (decl2 == error_mark_node)
decl = error_mark_node;
else if (decl != error_mark_node && DECL_CHAIN (decl2) != prev)
if (decl != error_mark_node)
{
- cp_decomp decomp = { prev, v.length () };
+ cp_decomp decomp = { prev, cnt };
cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE,
(is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT),
&decomp);
else if (decl != error_mark_node)
{
*maybe_range_for_decl = prev;
- cp_decomp decomp = { prev, v.length () };
+ cp_decomp decomp = { prev, cnt };
/* Ensure DECL_VALUE_EXPR is created for all the decls but
the underlying DECL. */
cp_finish_decomp (decl, &decomp);
--- /dev/null
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+struct A {
+ int i;
+ template <int I> int& get() { return i; }
+};
+
+template<> struct std::tuple_size<A> { static const int value = 3; };
+template<int I> struct std::tuple_element<I,A> { using type = int; };
+
+struct B {
+ int i, j;
+ long long k, l;
+} z[6];
+
+void
+foo (A &a, B &b)
+{
+ auto [ c [[]], d, e [[maybe_unused]] ] = a; // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ auto [ f, h [[maybe_unused]] [[]], i [[]], j ] = b; // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ for (auto [ k, l [[maybe_unused]], m, n [[]]] : z) // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } }
+ ; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ auto &[o[[]][[]][[]], p[[]], q[[]]] = a; // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } }
+ ; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+}
--- /dev/null
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+struct A {
+ int i;
+ template <int I> int& get() { return i; }
+};
+
+template<> struct std::tuple_size<A> { static const int value = 3; };
+template<int I> struct std::tuple_element<I,A> { using type = int; };
+
+struct B {
+ int i, j;
+ long long k, l;
+} z[6];
+
+void
+foo (A &a, B &b)
+{
+ auto [ c [[]], d, e [[gnu::deprecated]] ] = a; // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-message "declared here" "" { target *-*-* } .-2 }
+ ++c;
+ ++d;
+ ++e; // { dg-warning "'e' is deprecated" }
+ auto [ f, h [[gnu::deprecated]] [[]], i [[]], j ] = b;// { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-message "declared here" "" { target *-*-* } .-2 }
+ ++f;
+ ++h; // { dg-warning "'h' is deprecated" }
+ ++i;
+ ++j;
+ for (auto [ k, l [[gnu::deprecated]], m, n [[]]] : z) // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-message "declared here" "" { target *-*-* } .-2 }
+ ++k;
+ ++l; // { dg-warning "'l' is deprecated" }
+ ++m;
+ ++n;
+ }
+}
#ifndef __cpp_structured_bindings
# error "__cpp_structured_bindings"
-#elif __cpp_structured_bindings != 201606
-# error "__cpp_structured_bindings != 201606"
+#elif __cpp_structured_bindings != 202403
+# error "__cpp_structured_bindings != 202403"
#endif
#ifndef __cpp_template_template_args