diff mbox

[C++] Add mangling for P0217R3 decompositions at namespace scope

Message ID 20161115141218.GF3541@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Nov. 15, 2016, 2:12 p.m. UTC
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  <jakub@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.


	Jakub

Comments

Jason Merrill Nov. 15, 2016, 4:59 p.m. UTC | #1
OK.

On Tue, Nov 15, 2016 at 9:12 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> 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  <jakub@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
diff mbox

Patch

--- 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 } }
+}