This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [C++ debug PATCH] [PR88534] accept VAR_DECL in class literal template parms


On 3/27/19 4:44 AM, Jonathan Wakely wrote:
On 21/03/19 15:03 -0400, Jason Merrill wrote:
On 3/20/19 6:06 PM, Marek Polacek wrote:
On Wed, Mar 20, 2019 at 10:58:32PM +0100, Jakub Jelinek wrote:
On Wed, Mar 20, 2019 at 05:55:04PM -0400, Marek Polacek wrote:
On Wed, Mar 20, 2019 at 04:56:33PM -0300, Alexandre Oliva wrote:
On Mar 20, 2019, Marek Polacek <polacek@redhat.com> wrote:

This test fails with
pr88534.C:58:1: sorry, unimplemented: string literal in function template signature

Interesting...  gcc-8 rejected it with an error message rejecting the
template parameter, but my latest trunk build (dated Mar 13, r269641)
compiles it all right.  Was there a subsequent fix, maybe?  I didn't
realize it was supposed to be rejected.

Ah, that problem only started with r269814, namely this hunk:

Maybe this is done too early and should be postponed to genericization
(perhaps except for TREE_STATIC vars)?

Or skip when DECL is template_parm_object_p.

Or handle it in mangle.c.  I don't see any reason we shouldn't accept

struct A
{
 char c[4];
};

template <A a> struct B { };
B<A{"FOO"}> b;

Probably we should use the same mangling whether the initializer for c was spelled as a string literal or list of integers.

The thing we still don't want to allow is mangling the *address* of a string literal.

Will that help PR 47488 as well?

What I have (attached) accepts all three test cases from PR 47488
(comment #0, #1, #2, and #5) but with different mangling.

The difference in the mangling of the function in the test case
in comment #0 is

  Clang: _Z1gIiEDTcl1fcvT__ELA1_KcEEERKS0_
  GCC 9: _Z1gIiEDTcl1fcvT__ELKc0EEERKS0_

I'm not very familiar with the C++ ABI mangling but from what
I can tell, Clang treats the type as a literal array of 1 const
char element (LA1_Kc) without actually encoding its value, while
with my patch GCC encodes it as a constant literal initializer
consisting of 1 null char (LKc0).  In other words, Clang would
mangle these two the same for the same T:

  template < typename T >
  decltype (f (T(), "123")) g (const T&);

  template < typename T >
  decltype (f (T(), "abc")) g (const T&);

while GCC would mangle them differently.

Which is correct?  Clang's seems correct in this case but would
it also be correct to mangle Jason's B<A{"FOO"}> the same as
B<A{"BAR"}>?

Martin
PR c++/89833 - sorry, unimplemented: string literal in function template signature

gcc/cp/ChangeLog:

	PR c++/89833
	* mangle.c (write_expression): Convert braced initializer lists
	to STRING_CSTs.
	(write_template_arg_literal): Mangle strings the same as braced
	initializer lists.

Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(revision 269965)
+++ gcc/cp/mangle.c	(working copy)
@@ -3136,6 +3136,10 @@ write_expression (tree expr)
     }
   else if (code == CONSTRUCTOR)
     {
+      /* Convert braced initializer lists to STRING_CSTs so that
+	 A<"Foo"> and A<{'F', 'o', 'o', 0}> mangle the same.  */
+      expr = braced_lists_to_strings (TREE_TYPE (expr), expr);
+
       vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (expr);
       unsigned i; tree val;
 
@@ -3354,8 +3358,13 @@ static void
 write_template_arg_literal (const tree value)
 {
   write_char ('L');
-  write_type (TREE_TYPE (value));
 
+  tree valtype = TREE_TYPE (value);
+  if (TREE_CODE (value) == STRING_CST)
+    valtype = TREE_TYPE (valtype);
+
+  write_type (valtype);
+
   /* Write a null member pointer value as (type)0, regardless of its
      real representation.  */
   if (null_member_pointer_value_p (value))
@@ -3397,7 +3406,15 @@ write_template_arg_literal (const tree value)
 	break;
 
       case STRING_CST:
-	sorry ("string literal in function template signature");
+	/* Mangle strings the same as braced initializer lists.  */
+	for (const char *p = TREE_STRING_POINTER (value); ; ++p)
+	  {
+	    write_unsigned_number (*(const unsigned char*)p);
+	    if (!*p)
+	      break;
+	    write_string ("EL");
+	    write_type (valtype);
+	  }
 	break;
 
       default:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]