@@ -1010,6 +1010,9 @@ Driver Undocumented
; 18: Corrects errors in mangling of lambdas with additional context.
; Default in G++ 13.
;
+; 19: Emits ABI tags if needed in structured binding mangled names.
+; Default in G++ 14.
+;
; Additional positive integers will be assigned as new versions of
; the ABI become the default version of the ABI.
fabi-version=
@@ -3016,6 +3016,9 @@ in C++14 and up.
Version 18, which first appeard in G++ 13, fixes manglings of lambdas
that have additional context.
+Version 19, which first appeard in G++ 14, fixes manglings of structured
+bindings to include ABI tags.
+
See also @option{-Wabi}.
@opindex fabi-compat-version
@@ -974,7 +974,7 @@ c_common_post_options (const char **pfil
/* Change flag_abi_version to be the actual current ABI level, for the
benefit of c_cpp_builtins, and to make comparison simpler. */
- const int latest_abi_version = 18;
+ const int latest_abi_version = 19;
/* Generate compatibility aliases for ABI v13 (8.2) by default. */
const int abi_compat_default = 13;
@@ -6858,7 +6858,7 @@ extern void pop_switch (void);
extern void note_break_stmt (void);
extern bool note_iteration_stmt_body_start (void);
extern void note_iteration_stmt_body_end (bool);
-extern void determine_local_discriminator (tree);
+extern void determine_local_discriminator (tree, tree = NULL_TREE);
extern bool member_like_constrained_friend_p (tree);
extern bool fns_correspond (tree, tree);
extern int decls_match (tree, tree, bool = true);
@@ -6891,9 +6891,9 @@ extern tree start_decl (const cp_decl
extern void start_decl_1 (tree, bool);
extern bool check_array_initializer (tree, tree, tree);
extern void omp_declare_variant_finalize (tree, tree);
-extern void cp_finish_decl (tree, tree, bool, tree, int);
+struct cp_decomp { tree decl; unsigned int count; };
+extern void cp_finish_decl (tree, tree, bool, tree, int, cp_decomp * = nullptr);
extern tree lookup_decomp_type (tree);
-extern void cp_maybe_mangle_decomp (tree, tree, unsigned int);
extern void cp_finish_decomp (tree, tree, unsigned int);
extern int cp_complete_array_type (tree *, tree, bool);
extern int cp_complete_array_type_or_error (tree *, tree, bool, tsubst_flags_t);
@@ -911,15 +911,16 @@ static GTY((deletable)) vec<tree, va_gc>
generally very few of these in any particular function. */
void
-determine_local_discriminator (tree decl)
+determine_local_discriminator (tree decl, tree name)
{
auto_cond_timevar tv (TV_NAME_LOOKUP);
retrofit_lang_decl (decl);
tree ctx = DECL_CONTEXT (decl);
- tree name = (TREE_CODE (decl) == TYPE_DECL
- && TYPE_UNNAMED_P (TREE_TYPE (decl))
- ? NULL_TREE : DECL_NAME (decl));
size_t nelts = vec_safe_length (local_entities);
+ if (name == NULL_TREE)
+ name = (TREE_CODE (decl) == TYPE_DECL
+ && TYPE_UNNAMED_P (TREE_TYPE (decl))
+ ? NULL_TREE : DECL_NAME (decl));
for (size_t i = 0; i < nelts; i += 2)
{
tree *pair = &(*local_entities)[i];
@@ -6417,8 +6418,9 @@ layout_var_decl (tree decl)
void
maybe_commonize_var (tree decl)
{
- /* Don't mess with __FUNCTION__ and similar. */
- if (DECL_ARTIFICIAL (decl))
+ /* Don't mess with __FUNCTION__ and similar. But do handle structured
+ bindings. */
+ if (DECL_ARTIFICIAL (decl) && !DECL_DECOMPOSITION_P (decl))
return;
/* Static data in a function with comdat linkage also has comdat
@@ -8212,6 +8214,8 @@ omp_declare_variant_finalize (tree decl,
}
}
+static void cp_maybe_mangle_decomp (tree, tree, unsigned int);
+
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
@@ -8221,11 +8225,14 @@ omp_declare_variant_finalize (tree decl,
true, then INIT is an integral constant expression.
FLAGS is LOOKUP_ONLYCONVERTING if the = init syntax was used, else 0
- if the (init) syntax was used. */
+ if the (init) syntax was used.
+
+ DECOMP is first identifier's DECL and identifier count in a structured
+ bindings, nullptr if not a structured binding. */
void
cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
- tree asmspec_tree, int flags)
+ tree asmspec_tree, int flags, cp_decomp *decomp)
{
vec<tree, va_gc> *cleanups = NULL;
const char *asmspec = NULL;
@@ -8600,6 +8607,9 @@ cp_finish_decl (tree decl, tree init, bo
return;
}
+ if (decomp)
+ cp_maybe_mangle_decomp (decl, decomp->decl, decomp->count);
+
/* If this is a local variable that will need a mangled name,
register it now. We must do this before processing the
initializer for the variable, since the initialization might
@@ -9070,7 +9080,7 @@ lookup_decomp_type (tree v)
/* Mangle a decomposition declaration if needed. Arguments like
in cp_finish_decomp. */
-void
+static void
cp_maybe_mangle_decomp (tree decl, tree first, unsigned int count)
{
if (!processing_template_decl
@@ -9082,6 +9092,25 @@ cp_maybe_mangle_decomp (tree decl, tree
tree d = first;
for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d))
v[count - i - 1] = d;
+ if (DECL_FUNCTION_SCOPE_P (decl))
+ {
+ size_t sz = 3;
+ for (unsigned int i = 0; i < count; ++i)
+ sz += IDENTIFIER_LENGTH (DECL_NAME (v[i])) + 1;
+ char *name = XALLOCAVEC (char, sz);
+ name[0] = 'D';
+ name[1] = 'C';
+ char *p = name + 2;
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ size_t len = IDENTIFIER_LENGTH (DECL_NAME (v[i]));
+ *p++ = ' ';
+ memcpy (p, IDENTIFIER_POINTER (DECL_NAME (v[i])), len);
+ p += len;
+ }
+ *p = '\0';
+ determine_local_discriminator (decl, get_identifier (name));
+ }
SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v));
maybe_apply_pragma_weak (decl);
}
@@ -1347,51 +1347,6 @@ write_template_prefix (const tree node)
add_substitution (substitution);
}
-/* As the list of identifiers for the structured binding declaration
- DECL is likely gone, try to recover the DC <source-name>+ E portion
- from its mangled name. Return pointer to the DC and set len to
- the length up to and including the terminating E. On failure
- return NULL. */
-
-static const char *
-find_decomp_unqualified_name (tree decl, size_t *len)
-{
- const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
- bool nested = false;
- if (!startswith (p, "_Z"))
- return NULL;
- p += 2;
- if (startswith (p, "St"))
- p += 2;
- else if (*p == 'N')
- {
- nested = true;
- ++p;
- while (ISDIGIT (p[0]))
- {
- char *e;
- long num = strtol (p, &e, 10);
- if (num >= 1 && num < end - e)
- p = e + num;
- else
- break;
- }
- }
- if (!startswith (p, "DC"))
- return NULL;
- if (nested)
- {
- if (end[-1] != 'E')
- return NULL;
- --end;
- }
- if (end[-1] != 'E')
- return NULL;
- *len = end - p;
- return p;
-}
-
/* "For the purposes of mangling, the name of an anonymous union is considered
to be the name of the first named data member found by a pre-order,
depth-first, declaration-order walk of the data members of the anonymous
@@ -1465,17 +1420,7 @@ write_unqualified_name (tree decl)
{
found = true;
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
- const char *decomp_str = NULL;
- size_t decomp_len = 0;
- if (VAR_P (decl)
- && DECL_DECOMPOSITION_P (decl)
- && DECL_NAME (decl) == NULL_TREE
- && DECL_NAMESPACE_SCOPE_P (decl))
- decomp_str = find_decomp_unqualified_name (decl, &decomp_len);
- if (decomp_str)
- write_chars (decomp_str, decomp_len);
- else
- write_source_name (DECL_ASSEMBLER_NAME (decl));
+ write_source_name (DECL_ASSEMBLER_NAME (decl));
}
else if (DECL_DECLARES_FUNCTION_P (decl))
{
@@ -4373,6 +4318,7 @@ mangle_decomp (const tree decl, vec<tree
location_t saved_loc = input_location;
input_location = DECL_SOURCE_LOCATION (decl);
+ check_abi_tags (decl);
start_mangling (decl);
write_string ("_Z");
@@ -4380,13 +4326,21 @@ mangle_decomp (const tree decl, vec<tree
gcc_assert (context != NULL_TREE);
bool nested = false;
+ bool local = false;
if (DECL_NAMESPACE_STD_P (context))
write_string ("St");
+ else if (TREE_CODE (context) == FUNCTION_DECL)
+ {
+ local = true;
+ write_char ('Z');
+ write_encoding (context);
+ write_char ('E');
+ }
else if (context != global_namespace)
{
nested = true;
write_char ('N');
- write_prefix (decl_mangling_context (decl));
+ write_prefix (context);
}
write_string ("DC");
@@ -4396,8 +4350,21 @@ mangle_decomp (const tree decl, vec<tree
write_unqualified_name (d);
write_char ('E');
+ if (tree tags = get_abi_tags (decl))
+ {
+ /* We didn't emit ABI tags for structured bindings before ABI 19. */
+ if (!G.need_abi_warning
+ && abi_warn_or_compat_version_crosses (19))
+ G.need_abi_warning = 1;
+
+ if (abi_version_at_least (19))
+ write_abi_tags (tags);
+ }
+
if (nested)
write_char ('E');
+ else if (local && DECL_DISCRIMINATOR_P (decl))
+ write_discriminator (discriminator_for_local_entity (decl));
tree id = finish_mangling_get_identifier ();
if (DEBUG_MANGLE)
@@ -4405,6 +4372,37 @@ mangle_decomp (const tree decl, vec<tree
IDENTIFIER_POINTER (id));
input_location = saved_loc;
+
+ if (warn_abi && G.need_abi_warning)
+ {
+ const char fabi_version[] = "-fabi-version";
+ tree id2 = id;
+ int save_ver = flag_abi_version;
+
+ if (flag_abi_version != warn_abi_version)
+ {
+ flag_abi_version = warn_abi_version;
+ id2 = mangle_decomp (decl, decls);
+ flag_abi_version = save_ver;
+ }
+
+ if (id2 == id)
+ /* OK. */;
+ else if (warn_abi_version != 0
+ && abi_version_at_least (warn_abi_version))
+ warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi,
+ "the mangled name of %qD changed between "
+ "%<%s=%d%> (%qD) and %<%s=%d%> (%qD)",
+ G.entity, fabi_version, warn_abi_version, id2,
+ fabi_version, save_ver, id);
+ else
+ warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi,
+ "the mangled name of %qD changes between "
+ "%<%s=%d%> (%qD) and %<%s=%d%> (%qD)",
+ G.entity, fabi_version, save_ver, id,
+ fabi_version, warn_abi_version, id2);
+ }
+
return id;
}
@@ -4574,6 +4572,13 @@ write_guarded_var_name (const tree varia
/* The name of a guard variable for a reference temporary should refer
to the reference, not the temporary. */
write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
+ else if (DECL_DECOMPOSITION_P (variable)
+ && DECL_NAME (variable) == NULL_TREE
+ && startswith (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (variable)),
+ "_Z"))
+ /* The name of a guard variable for a structured binding needs special
+ casing. */
+ write_string (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (variable)) + 2);
else
write_name (variable, /*ignore_local_scope=*/0);
}
@@ -4640,7 +4645,7 @@ mangle_ref_init_variable (const tree var
start_mangling (variable);
write_string ("_ZGR");
check_abi_tags (variable);
- write_name (variable, /*ignore_local_scope=*/0);
+ write_guarded_var_name (variable);
/* Avoid name clashes with aggregate initialization of multiple
references at once. */
write_compact_number (current_ref_temp_count++);
@@ -14182,15 +14182,20 @@ cp_convert_range_for (tree statement, tr
tf_warning_or_error);
finish_for_expr (expression, statement);
+ cp_decomp decomp_data, *decomp = nullptr;
if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl))
- cp_maybe_mangle_decomp (range_decl, decomp_first_name, decomp_cnt);
+ {
+ decomp_data.decl = decomp_first_name;
+ decomp_data.count = decomp_cnt;
+ decomp = &decomp_data;
+ }
/* The declaration is initialized with *__begin inside the loop body. */
tree deref_begin = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR,
NULL_TREE, tf_warning_or_error);
cp_finish_decl (range_decl, deref_begin,
/*is_constant_init*/false, NULL_TREE,
- LOOKUP_ONLYCONVERTING);
+ LOOKUP_ONLYCONVERTING, decomp);
if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl))
cp_finish_decomp (range_decl, decomp_first_name, decomp_cnt);
@@ -15890,9 +15895,10 @@ cp_parser_decomposition_declaration (cp_
if (decl != error_mark_node)
{
- cp_maybe_mangle_decomp (decl, prev, v.length ());
+ cp_decomp decomp = { prev, v.length () };
cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE,
- (is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT));
+ (is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT),
+ &decomp);
cp_finish_decomp (decl, prev, v.length ());
}
}
@@ -43697,27 +43703,26 @@ cp_finish_omp_range_for (tree orig, tree
gcc_assert (TREE_CODE (orig) == TREE_LIST
&& TREE_CODE (TREE_CHAIN (orig)) == TREE_VEC);
tree decl = TREE_VEC_ELT (TREE_CHAIN (orig), 2);
- tree decomp_first_name = NULL_TREE;
- unsigned int decomp_cnt = 0;
+ cp_decomp decomp_data, *decomp = nullptr;
if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
{
- decomp_first_name = TREE_VEC_ELT (TREE_CHAIN (orig), 3);
- decomp_cnt = TREE_VEC_LENGTH (TREE_CHAIN (orig)) - 3;
+ decomp_data.decl = TREE_VEC_ELT (TREE_CHAIN (orig), 3);
+ decomp_data.count = TREE_VEC_LENGTH (TREE_CHAIN (orig)) - 3;
if (TREE_PUBLIC (TREE_CHAIN (orig)))
{
/* Undo temporary clearing of DECL_HAS_VALUE_EXPR_P done
by cp_convert_omp_range_for above. */
TREE_PUBLIC (TREE_CHAIN (orig)) = 0;
- tree d = decomp_first_name;
- for (unsigned i = 0; i < decomp_cnt; i++)
+ tree d = decomp_data.decl;
+ for (unsigned i = 0; i < decomp_data.count; i++)
{
if (TREE_TYPE (d) != error_mark_node)
DECL_HAS_VALUE_EXPR_P (d) = 1;
d = DECL_CHAIN (d);
}
}
- cp_maybe_mangle_decomp (decl, decomp_first_name, decomp_cnt);
+ decomp = &decomp_data;
}
/* The declaration is initialized with *__begin inside the loop body. */
@@ -43725,9 +43730,9 @@ cp_finish_omp_range_for (tree orig, tree
build_x_indirect_ref (input_location, begin, RO_UNARY_STAR,
NULL_TREE, tf_warning_or_error),
/*is_constant_init*/false, NULL_TREE,
- LOOKUP_ONLYCONVERTING);
+ LOOKUP_ONLYCONVERTING, decomp);
if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
- cp_finish_decomp (decl, decomp_first_name, decomp_cnt);
+ cp_finish_decomp (decl, decomp->decl, decomp->count);
}
/* Return true if next tokens contain a standard attribute that contains
@@ -19043,8 +19043,8 @@ tsubst_expr (tree t, tree args, tsubst_f
else
{
bool const_init = false;
- unsigned int cnt = 0;
- tree first = NULL_TREE, ndecl = error_mark_node;
+ cp_decomp decomp_data, *decomp = nullptr;
+ tree ndecl = error_mark_node;
tree asmspec_tree = NULL_TREE;
maybe_push_decl (decl);
@@ -19056,9 +19056,13 @@ tsubst_expr (tree t, tree args, tsubst_f
if (VAR_P (decl)
&& DECL_DECOMPOSITION_P (decl)
&& TREE_TYPE (pattern_decl) != error_mark_node)
- ndecl = tsubst_decomp_names (decl, pattern_decl, args,
- complain, in_decl, &first,
- &cnt);
+ {
+ ndecl = tsubst_decomp_names (decl, pattern_decl, args,
+ complain, in_decl,
+ &decomp_data.decl,
+ &decomp_data.count);
+ decomp = &decomp_data;
+ }
init = tsubst_init (init, decl, args, complain, in_decl);
@@ -19066,9 +19070,6 @@ tsubst_expr (tree t, tree args, tsubst_f
const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P
(pattern_decl));
- if (ndecl != error_mark_node)
- cp_maybe_mangle_decomp (ndecl, first, cnt);
-
/* In a non-template function, VLA type declarations are
handled in grokdeclarator; for templates, handle them
now. */
@@ -19085,10 +19086,11 @@ tsubst_expr (tree t, tree args, tsubst_f
TREE_TYPE (asmspec_tree) = char_array_type_node;
}
- cp_finish_decl (decl, init, const_init, asmspec_tree, 0);
+ cp_finish_decl (decl, init, const_init, asmspec_tree, 0,
+ decomp);
if (ndecl != error_mark_node)
- cp_finish_decomp (ndecl, first, cnt);
+ cp_finish_decomp (ndecl, decomp->decl, decomp->count);
}
}
}
@@ -0,0 +1,74 @@
+// PR c++/111069
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+extern int a[2];
+struct Y { int b, c, d; };
+
+inline int
+freddy ()
+{
+ static auto [i, j] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ static auto [k, l] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ int ret = ++i + ++k;
+ {
+ static auto [i, j] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ static auto [k, l] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ ret += ++i + ++k;
+ }
+ {
+ static auto [i, j] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ static auto [k, l] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ ret += ++i + ++k;
+ }
+ return ret;
+}
+
+namespace N
+{
+ namespace M
+ {
+ template <int N>
+ inline int
+ corge ()
+ {
+ static auto [i, j] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ static auto && [u, v, w] = Y{}; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ int ret = ++i + ++u;
+ {
+ static auto && [u, v, w] = Y{}; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ ret += ++v;
+ }
+ return ret;
+ }
+ }
+}
+
+int (*p) () = &freddy;
+int (*q) () = N::M::corge<3>;
+
+// { dg-final { scan-assembler "_ZZ6freddyvEDC1i1jE" } }
+// { dg-final { scan-assembler "_ZZ6freddyvEDC1i1jE_0" } }
+// { dg-final { scan-assembler "_ZZ6freddyvEDC1i1jE_1" } }
+// { dg-final { scan-assembler "_ZZ6freddyvEDC1k1lE" } }
+// { dg-final { scan-assembler "_ZZ6freddyvEDC1k1lE_0" } }
+// { dg-final { scan-assembler "_ZZ6freddyvEDC1k1lE_1" } }
+// { dg-final { scan-assembler "_ZZN1N1M5corgeILi3EEEivEDC1i1jE" } }
+// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1i1jE" } }
+// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1i1jE_0" } }
+// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1i1jE_1" } }
+// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1k1lE" } }
+// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1k1lE_0" } }
+// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1k1lE_1" } }
+// { dg-final { scan-assembler "_ZGVZN1N1M5corgeILi3EEEivEDC1i1jE" } }
+// { dg-final { scan-assembler "_ZGRZN1N1M5corgeILi3EEEivEDC1u1v1wE_" } }
+// { dg-final { scan-assembler "_ZGRZN1N1M5corgeILi3EEEivEDC1u1v1wE_0_" } }
@@ -0,0 +1,82 @@
+// PR c++/111069
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct [[gnu::abi_tag ("foobar")]] S { int i; };
+extern S a[2];
+struct [[gnu::abi_tag ("qux")]] T { int i; S j; int k; };
+extern T b[2];
+
+namespace N {
+ auto [i, j] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto [k, l] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+}
+
+inline int
+foo ()
+{
+ static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ static auto [o, p] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ int ret = ++N::i.i + ++N::k.i;
+ {
+ static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+
+ ret += ++n.i;
+ }
+ {
+ static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+
+ ret += ++n.i;
+ }
+ ret += ++m.i + ++o.i;
+ return ret;
+}
+
+template <typename T>
+inline int
+bar ()
+{
+ static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ static auto [o, p] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ int ret = 0;
+ {
+ static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ ret += ++n.i;
+ }
+ {
+ static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 }
+ ret += ++n.i;
+ }
+ ret += ++m.i + ++o.i;
+ return ret;
+}
+
+int (*p) () = &foo;
+int (*q) () = &bar<T>;
+
+// { dg-final { scan-assembler "_ZZ3foovEDC1m1nEB6foobar" } }
+// { dg-final { scan-assembler "_ZZ3foovEDC1m1nEB6foobar_0" } }
+// { dg-final { scan-assembler "_ZZ3foovEDC1m1nEB6foobar_1" } }
+// { dg-final { scan-assembler "_ZZ3foovEDC1o1pEB3qux" } }
+// { dg-final { scan-assembler "_ZZ3barI1TB3quxEivEDC1m1nEB6foobar" } }
+// { dg-final { scan-assembler "_ZZ3barI1TB3quxEivEDC1m1nEB6foobar_0" } }
+// { dg-final { scan-assembler "_ZZ3barI1TB3quxEivEDC1m1nEB6foobar_1" } }
+// { dg-final { scan-assembler "_ZZ3barI1TB3quxEivEDC1o1pEB3qux" } }
+// { dg-final { scan-assembler "_ZN1NDC1i1jEB6foobarE" } }
+// { dg-final { scan-assembler "_ZN1NDC1k1lEB3quxE" } }
+// { dg-final { scan-assembler "_ZGVZ3foovEDC1m1nEB6foobar" } }
+// { dg-final { scan-assembler "_ZGVZ3foovEDC1m1nEB6foobar_0" } }
+// { dg-final { scan-assembler "_ZGVZ3foovEDC1m1nEB6foobar_1" } }
+// { dg-final { scan-assembler "_ZGVZ3foovEDC1o1pEB3qux" } }
+// { dg-final { scan-assembler "_ZGVZ3barI1TB3quxEivEDC1m1nEB6foobar" } }
+// { dg-final { scan-assembler "_ZGVZ3barI1TB3quxEivEDC1m1nEB6foobar_0" } }
+// { dg-final { scan-assembler "_ZGVZ3barI1TB3quxEivEDC1m1nEB6foobar_1" } }
+// { dg-final { scan-assembler "_ZGVZ3barI1TB3quxEivEDC1o1pEB3qux" } }
@@ -1,6 +1,6 @@
// This testcase will need to be kept in sync with c_common_post_options.
// { dg-options "-fabi-version=0" }
-#if __GXX_ABI_VERSION != 1018
+#if __GXX_ABI_VERSION != 1019
#error "Incorrect value of __GXX_ABI_VERSION"
#endif