Patchwork PR C++/58708 - string literal operator templates broken

login
register
mail settings
Submitter Ed Smith-Rowland
Date Oct. 31, 2013, 12:34 p.m.
Message ID <52724E6F.7040408@verizon.net>
Download mbox | patch
Permalink /patch/287477/
State New
Headers show

Comments

Ed Smith-Rowland - Oct. 31, 2013, 12:34 p.m.
On 10/25/2013 10:40 AM, Jakub Jelinek wrote:
> On Fri, Oct 25, 2013 at 10:29:41AM -0400, Ed Smith-Rowland wrote:
>> 2013-10-25  Edward Smith-Rowland  <3dw4rd@verizon.net>
>>
>>          PR c++/58708
>> 	* parser.c (make_string_pack): Discover non-const type and size
>> 	of character and build parm pack with correct type and chars.
>>
>> gcc/testsuite:
>>
>> 2013-10-25  Edward Smith-Rowland  <3dw4rd@verizon.net>
>>
>>          PR c++/58708
>> 	*g++.dg/cpp1y/pr58708.C : New.
>> --- testsuite/g++.dg/cpp1y/pr58708.C	(revision 0)
>> +++ testsuite/g++.dg/cpp1y/pr58708.C	(working copy)
>> @@ -0,0 +1,91 @@
>> +// { dg-options -std=c++1y }
>> +// { dg-do run }
>> +
>> +template<typename _Tp, _Tp __v>
>> +  struct integral_constant
>> +  {
>> +    static constexpr _Tp                  value = __v;
>> +    typedef _Tp                           value_type;
>> +    typedef integral_constant<_Tp, __v>   type;
>> +    constexpr operator value_type() const { return value; }
>> +    constexpr value_type operator()() const { return value; }
>> +  };
>> +
>> +template<typename _Tp, _Tp __v>
>> +  constexpr _Tp integral_constant<_Tp, __v>::value;
>> +
>> +typedef integral_constant<bool, true>     true_type;
>> +
>> +typedef integral_constant<bool, false>    false_type;
>> +
>> +template<typename, typename>
>> +  struct is_same
>> +  : public false_type { };
>> +
>> +template<typename _Tp>
>> +  struct is_same<_Tp, _Tp>
>> +  : public true_type { };
> Why not just the minimal:
> template< class T, class U >
> struct is_same {
>    static constexpr bool value = false;
> };
>
> template< class T >
> struct is_same<T, T> {
>    static constexpr bool value = true;
> };
> other tests are using?
>
> 	Jakub
>
All,

Here is a new patch.  It's the same patch but a lighter testcase.

Built and tested on x86_64-linux.

OK?

Ed
gcc/cp:

2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>

        PR c++/58708
	* parser.c (make_string_pack): Discover non-const type and size
	of character and build parm pack with correct type and chars.

gcc/testsuite:

2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>

        PR c++/58708
	*g++.dg/cpp1y/pr58708.C : New.
Jakub Jelinek - Oct. 31, 2013, 12:39 p.m.
On Thu, Oct 31, 2013 at 08:34:55AM -0400, Ed Smith-Rowland wrote:
> 2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>
> 
>         PR c++/58708
> 	* parser.c (make_string_pack): Discover non-const type and size
> 	of character and build parm pack with correct type and chars.
> 
> gcc/testsuite:
> 
> 2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>
> 
>         PR c++/58708
> 	*g++.dg/cpp1y/pr58708.C : New.

The testcase LGTM, the ChangeLog entry doesn't have space after *
and has extra space before : (and both the PR and * g++.dg/ line
should be indented by a single tab and no other spaces).
For the C++ parser change I'm deferring it to Jason, if it has
been already approved, the patch is ok, if not, Jason needs to ack it.

	Jakub
Jason Merrill - Nov. 1, 2013, 8:33 p.m.
OK.

Jason

Patch

Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 203997)
+++ cp/parser.c	(working copy)
@@ -3793,22 +3793,39 @@ 
   tree charvec;
   tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
   const char *str = TREE_STRING_POINTER (value);
-  int i, len = TREE_STRING_LENGTH (value) - 1;
+  int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value))));
+  int len = TREE_STRING_LENGTH (value) / sz - 1;
   tree argvec = make_tree_vec (2);
 
-  tree string_char_type_node = TREE_TYPE (TREE_TYPE (value));
+  tree str_char_type_node = TREE_TYPE (TREE_TYPE (value));
+  str_char_type_node = TYPE_MAIN_VARIANT (str_char_type_node);
 
   /* First template parm is character type.  */
-  TREE_VEC_ELT (argvec, 0) = string_char_type_node;
+  TREE_VEC_ELT (argvec, 0) = str_char_type_node;
 
   /* Fill in CHARVEC with all of the parameters.  */
   charvec = make_tree_vec (len);
-  for (i = 0; i < len; ++i)
-    TREE_VEC_ELT (charvec, i) = build_int_cst (string_char_type_node, str[i]);
+  if (sz == 1)
+    {
+      for (int i = 0; i < len; ++i)
+	TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, str[i]);
+    }
+  else if (sz == 2)
+    {
+      const uint16_t *num = (const uint16_t *)str;
+      for (int i = 0; i < len; ++i)
+	TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, num[i]);
+    }
+  else if (sz == 4)
+    {
+      const uint32_t *num = (const uint32_t *)str;
+      for (int i = 0; i < len; ++i)
+	TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, num[i]);
+    }
 
   /* Build the argument packs.  */
   SET_ARGUMENT_PACK_ARGS (argpack, charvec);
-  TREE_TYPE (argpack) = string_char_type_node;
+  TREE_TYPE (argpack) = str_char_type_node;
 
   TREE_VEC_ELT (argvec, 1) = argpack;
 
Index: testsuite/g++.dg/cpp1y/pr58708.C
===================================================================
--- testsuite/g++.dg/cpp1y/pr58708.C	(revision 0)
+++ testsuite/g++.dg/cpp1y/pr58708.C	(working copy)
@@ -0,0 +1,60 @@ 
+// { dg-options -std=c++1y }
+// { dg-do run }
+
+template<typename, typename>
+  struct is_same
+  {
+    static constexpr bool value = false;
+  };
+
+template<typename _Tp>
+  struct is_same<_Tp, _Tp>
+  {
+    static constexpr bool value = true;
+  };
+
+template<typename CharT, CharT... Str>
+  struct Foo
+  {
+    using char_type = CharT;
+    char_type chars[sizeof...(Str)]{Str...};
+  };
+
+template<typename CharT, CharT... Str>
+  Foo<CharT, Str...>
+  operator""_foo()
+  {
+    return Foo<CharT, Str...>();
+  }
+
+int
+main()
+{
+  auto fooU = U"\x10000\x10001\x10002"_foo;
+  if (is_same<decltype(fooU)::char_type, char32_t>::value != true) __builtin_abort();
+  if (sizeof(fooU.chars)/sizeof(char32_t) != 3) __builtin_abort();
+  if (fooU.chars[0] != 65536) __builtin_abort();
+  if (fooU.chars[1] != 65537) __builtin_abort();
+  if (fooU.chars[2] != 65538) __builtin_abort();
+
+  auto foo = "\x61\x62\x63"_foo;
+  if (is_same<decltype(foo)::char_type, char>::value != true) __builtin_abort();
+  if (sizeof(foo.chars)/sizeof(char) != 3) __builtin_abort();
+  if (foo.chars[0] != 97) __builtin_abort();
+  if (foo.chars[1] != 98) __builtin_abort();
+  if (foo.chars[2] != 99) __builtin_abort();
+
+  auto wfoo = L"\x01020304\x05060708"_foo;
+  if (is_same<decltype(wfoo)::char_type, wchar_t>::value != true) __builtin_abort();
+  if (sizeof(wfoo.chars)/sizeof(wchar_t) != 2) __builtin_abort();
+  if (wfoo.chars[0] != 16909060) __builtin_abort();
+  if (wfoo.chars[1] != 84281096) __builtin_abort();
+
+  auto foou = u"\x0102\x0304\x0506\x0708"_foo;
+  if (is_same<decltype(foou)::char_type, char16_t>::value != true) __builtin_abort();
+  if (sizeof(foou.chars)/sizeof(char16_t) != 4) __builtin_abort();
+  if (foou.chars[0] != 258) __builtin_abort();
+  if (foou.chars[1] != 772) __builtin_abort();
+  if (foou.chars[2] != 1286) __builtin_abort();
+  if (foou.chars[3] != 1800) __builtin_abort();
+}