Hi! On the following testcase we ICE, because the underlying artificial decls have NULL DECL_NAME (intentional), thus mangling is not able to figure out what to do. This patch attempts to follow the http://sourcerytools.com/pipermail/cxx-abi-dev/2016-August/002951.html proposal (and for error recovery just uses <decomp> in order not to ICE).
Not really sure about ABI tags though. I guess one can specify abi tag on the whole decomposition, perhaps __attribute__((abi_tag ("foobar"))) auto [ a, b ] = A (); And/or there could be ABI tags on the type of the artifical decl. What about ABI tags on the types that the decomposition resolved to (say if std::tuple* is involved)? Shall all ABI tags go at the end of the whole decomp decl, or shall the individual source names have their ABI tags attached after them? What about the std::tuple* case where the standalone vars exist too, shall e.g. abi_tag attributes be copied from the decomp var to those? Any other attributes to copy over (e.g. unused comes to mind). In any case, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk (and the rest would be resolved incrementally)? 2016-11-15 Jakub Jelinek <ja...@redhat.com> * decl.c (cp_finish_decomp): For DECL_NAMESPACE_SCOPE_P decl, set DECL_ASSEMBLER_NAME. * parser.c (cp_parser_decomposition_declaration): Likewise if returning error_mark_node. * mangle.c (mangle_decomp): New function. * cp-tree.h (mangle_decomp): New declaration. * g++.dg/cpp1z/decomp12.C: New test. --- gcc/cp/decl.c.jj 2016-11-15 09:57:00.000000000 +0100 +++ gcc/cp/decl.c 2016-11-15 12:16:41.230596777 +0100 @@ -7301,7 +7301,6 @@ get_tuple_decomp_init (tree decl, unsign void cp_finish_decomp (tree decl, tree first, unsigned int count) { - location_t loc = DECL_SOURCE_LOCATION (decl); if (error_operand_p (decl)) { error_out: @@ -7315,9 +7314,12 @@ cp_finish_decomp (tree decl, tree first, } first = DECL_CHAIN (first); } + if (DECL_P (decl) && DECL_NAMESPACE_SCOPE_P (decl)) + SET_DECL_ASSEMBLER_NAME (decl, get_identifier ("<decomp>")); return; } + location_t loc = DECL_SOURCE_LOCATION (decl); if (type_dependent_expression_p (decl) /* This happens for range for when not in templates. Still add the DECL_VALUE_EXPRs for later processing. */ @@ -7530,6 +7532,8 @@ cp_finish_decomp (tree decl, tree first, i++; } } + if (DECL_NAMESPACE_SCOPE_P (decl)) + SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v)); } /* Returns a declaration for a VAR_DECL as if: --- gcc/cp/parser.c.jj 2016-11-15 10:37:56.000000000 +0100 +++ gcc/cp/parser.c 2016-11-15 12:16:26.361784744 +0100 @@ -12944,6 +12944,7 @@ cp_parser_decomposition_declaration (cp_ tree decl = start_decl (declarator, decl_specifiers, SD_INITIALIZED, NULL_TREE, decl_specifiers->attributes, &pushed_scope); + tree orig_decl = decl; unsigned int i; cp_expr e; @@ -13020,6 +13021,12 @@ cp_parser_decomposition_declaration (cp_ if (pushed_scope) pop_scope (pushed_scope); + if (decl == error_mark_node && DECL_P (orig_decl)) + { + if (DECL_NAMESPACE_SCOPE_P (orig_decl)) + SET_DECL_ASSEMBLER_NAME (orig_decl, get_identifier ("<decomp>")); + } + return decl; } --- gcc/cp/mangle.c.jj 2016-11-11 14:01:06.000000000 +0100 +++ gcc/cp/mangle.c 2016-11-15 11:48:58.345751857 +0100 @@ -3995,6 +3995,53 @@ mangle_vtt_for_type (const tree type) return mangle_special_for_type (type, "TT"); } +/* Returns an identifier for the mangled name of the decomposition + artificial variable DECL. DECLS is the vector of the VAR_DECLs + for the identifier-list. */ + +tree +mangle_decomp (const tree decl, vec<tree> &decls) +{ + gcc_assert (!type_dependent_expression_p (decl)); + + location_t saved_loc = input_location; + input_location = DECL_SOURCE_LOCATION (decl); + + start_mangling (decl); + write_string ("_Z"); + + tree context = decl_mangling_context (decl); + gcc_assert (context != NULL_TREE); + + bool nested = false; + if (DECL_NAMESPACE_STD_P (context)) + write_string ("St"); + else if (context != global_namespace) + { + nested = true; + write_char ('N'); + write_prefix (decl_mangling_context (decl)); + } + + write_string ("DC"); + unsigned int i; + tree d; + FOR_EACH_VEC_ELT (decls, i, d) + write_unqualified_name (d); + write_char ('E'); + + if (nested) + write_char ('E'); + + tree id = finish_mangling_get_identifier (); + if (DEBUG_MANGLE) + fprintf (stderr, "mangle_decomp = '%s'\n\n", + IDENTIFIER_POINTER (id)); + + input_location = saved_loc; + return id; +} + /* Return an identifier for a construction vtable group. TYPE is the most derived class in the hierarchy; BINFO is the base subobject for which this construction vtable group will be used. --- gcc/cp/cp-tree.h.jj 2016-11-15 09:57:00.000000000 +0100 +++ gcc/cp/cp-tree.h 2016-11-15 11:49:40.446215562 +0100 @@ -6868,6 +6868,7 @@ extern bool decl_tls_wrapper_p (tree); extern tree mangle_ref_init_variable (tree); extern char * get_mangled_vtable_map_var_name (tree); extern bool mangle_return_type_p (tree); +extern tree mangle_decomp (tree, vec<tree> &); /* in dump.c */ extern bool cp_dump_tree (void *, tree); --- gcc/testsuite/g++.dg/cpp1z/decomp12.C.jj 2016-11-15 12:42:02.319445610 +0100 +++ gcc/testsuite/g++.dg/cpp1z/decomp12.C 2016-11-15 12:43:09.147608099 +0100 @@ -0,0 +1,52 @@ +// { dg-do compile { target c++11 } } +// { dg-options "" } + +struct A { int i; long j; int k : 2; char l; } a; +int c[2]; +struct B { template<int I> int &get () { return c[I]; } } b; +namespace std { + template<typename T> struct tuple_size; + template<int, typename> struct tuple_element; +} +template<> struct std::tuple_size<B> { static constexpr int value = 2; }; +template<int I> struct std::tuple_element<I,B> { typedef int type; }; + +auto [ aa, bb, cc, dd ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } +// { dg-final { scan-assembler "_ZDC2aa2bb2cc2ddE" } } +const auto & [ e, f, g, h ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } +// { dg-final { scan-assembler "_ZDC1e1f1g1hE" } } +auto [ ee, ff ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } +// { dg-final { scan-assembler "_ZDC2ee2ffE" } } +auto & [ gg, hh ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } +// { dg-final { scan-assembler "_ZDC2gg2hhE" } } +namespace N +{ + namespace M + { + auto [ i, j, k, l ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + // { dg-final { scan-assembler "_ZN1N1MDC1i1j1k1lEE" } } + auto & [ m, n, o, ppp ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + // { dg-final { scan-assembler "_ZN1N1MDC1m1n1o3pppEE" } } + auto [ ii, jj ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + // { dg-final { scan-assembler "_ZN1N1MDC2ii2jjEE" } } + // { dg-final { scan-assembler "_ZN1N1M2iiE" } } + // { dg-final { scan-assembler "_ZN1N1M2jjE" } } + auto & [ mm, nn ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + // { dg-final { scan-assembler "_ZN1N1MDC2mm2nnEE" } } + // { dg-final { scan-assembler "_ZN1N1M2mmE" } } + // { dg-final { scan-assembler "_ZN1N1M2nnE" } } + } +} +namespace std +{ + auto [ i2, j2, k2, l2 ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + // { dg-final { scan-assembler "_ZStDC2i22j22k22l2E" } } + auto [ vv, ww ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + // { dg-final { scan-assembler "_ZStDC2vv2wwE" } } + // { dg-final { scan-assembler "_ZSt2vv" } } + // { dg-final { scan-assembler "_ZSt2ww" } } +} +namespace +{ + auto [ v, w, x, y ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } +} Jakub