diff mbox

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

Message ID 5260A01F.5010701@verizon.net
State New
Headers show

Commit Message

Ed Smith-Rowland Oct. 18, 2013, 2:42 a.m. UTC
Here is a patch to correct the char type and the type, number of nontype 
parameter pack for user defined strng literal operator templates.

Bootstrapped and tested on x86_64-linux.

OK?
gcc/cp:

2013-10-17  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-17  Edward Smith-Rowland  <3dw4rd@verizon.net>

        PR c++/58708
	*g++.dg/cpp1y/pr58708.C : New.

Comments

Paolo Carlini Oct. 18, 2013, 10:03 a.m. UTC | #1
On 10/18/2013 04:42 AM, Ed Smith-Rowland wrote:
> Here is a patch to correct the char type and the type, number of 
> nontype parameter pack for user defined strng literal operator templates.
Let's make sure Jason is in CC.

Thanks!
Paolo.
Paolo Carlini Oct. 25, 2013, 10:08 a.m. UTC | #2
Hi,

On 10/18/2013 04:42 AM, Ed Smith-Rowland wrote:
> --- testsuite/g++.dg/cpp1y/pr58708.C	(revision 0)
> +++ testsuite/g++.dg/cpp1y/pr58708.C	(working copy)
> @@ -0,0 +1,70 @@
> +// { dg-options -std=c++1y }
> +
> +#include <array>
> +#include <vector>
> +#include <type_traits>
> +#include <testsuite_hooks.h>
are you sure you want these includes in a C++ front-end testcase? Even 
<testsuite_hooks.h> instead of <cassert>? What about something more 
minimal, not including large headers like <vector>, for the C++ 
front-end + a library testcase (first blush, the above would be 
perfectly fine)

Thanks,
Paolo.
Ed Smith-Rowland Oct. 25, 2013, 11:38 a.m. UTC | #3
On 10/25/2013 06:08 AM, Paolo Carlini wrote:
> Hi,
>
> On 10/18/2013 04:42 AM, Ed Smith-Rowland wrote:
>> --- testsuite/g++.dg/cpp1y/pr58708.C (revision 0)
>> +++ testsuite/g++.dg/cpp1y/pr58708.C    (working copy)
>> @@ -0,0 +1,70 @@
>> +// { dg-options -std=c++1y }
>> +
>> +#include <array>
>> +#include <vector>
>> +#include <type_traits>
>> +#include <testsuite_hooks.h>
> are you sure you want these includes in a C++ front-end testcase? Even 
> <testsuite_hooks.h> instead of <cassert>? What about something more 
> minimal, not including large headers like <vector>, for the C++ 
> front-end + a library testcase (first blush, the above would be 
> perfectly fine)
>
> Thanks,
> Paolo.
>
You're right.  I'll send something slimmer later tonight.
The rest of the tests in the cpp1y directory use __builtin_abort.
So, you also want a library testcase?
Paolo Carlini Oct. 25, 2013, 11:54 a.m. UTC | #4
On 10/25/2013 01:38 PM, Ed Smith-Rowland wrote:
> So, you also want a library testcase?
Up to you: if you feel it would test something that the c++ front-end 
testcase doesn't, why not.

Paolo.
diff mbox

Patch

Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 203739)
+++ cp/parser.c	(working copy)
@@ -3792,22 +3792,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;
 
@@ -21425,6 +21442,9 @@ 
       /* C++11 noreturn attribute is equivalent to GNU's.  */
       if (is_attribute_p ("noreturn", attr_id))
 	TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu");
+      /* C++14 deprecated attribute is equivalent to GNU's.  */
+      else if (cxx_dialect >= cxx1y && is_attribute_p ("deprecated", attr_id))
+	TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu");
     }
 
   /* Now parse the optional argument clause of the attribute.  */
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,70 @@ 
+// { dg-options -std=c++1y }
+
+#include <array>
+#include <vector>
+#include <type_traits>
+#include <testsuite_hooks.h>
+
+struct Foo
+{
+  std::array<bool, 4> type;
+  std::array<bool, 4> const_type;
+  std::vector<int> chars;
+};
+
+template<typename CharT, CharT... str>
+Foo
+operator""_foo()
+{
+  CharT arr[]{str...};
+
+  Foo foo;
+
+  foo.type[0] = std::is_same<CharT, char>::value;
+  foo.type[1] = std::is_same<CharT, wchar_t>::value;
+  foo.type[2] = std::is_same<CharT, char16_t>::value;
+  foo.type[3] = std::is_same<CharT, char32_t>::value;
+  foo.const_type[0] = std::is_same<CharT, const char>::value;
+  foo.const_type[1] = std::is_same<CharT, const wchar_t>::value;
+  foo.const_type[2] = std::is_same<CharT, const char16_t>::value;
+  foo.const_type[3] = std::is_same<CharT, const char32_t>::value;
+
+  for(CharT c : arr)
+    foo.chars.push_back((int)c);
+
+  return foo;
+}
+
+int
+main()
+{
+  Foo foo;
+
+  foo = U"\x10000\x10001\x10002"_foo;
+  VERIFY (foo.type[3] == true);
+  VERIFY (foo.chars.size() == 3);
+  VERIFY (foo.chars[0] == 65536);
+  VERIFY (foo.chars[1] == 65537);
+  VERIFY (foo.chars[2] == 65538);
+
+  foo = "\x61\x62\x63"_foo;
+  VERIFY (foo.type[0] == true);
+  VERIFY (foo.chars.size() == 3);
+  VERIFY (foo.chars[0] == 97);
+  VERIFY (foo.chars[1] == 98);
+  VERIFY (foo.chars[2] == 99);
+
+  foo = L"\x01020304\x05060708"_foo;
+  VERIFY (foo.type[1] == true);
+  VERIFY (foo.chars.size() == 2);
+  VERIFY (foo.chars[0] == 16909060);
+  VERIFY (foo.chars[1] == 84281096);
+
+  foo = u"\x0102\x0304\x0506\x0708"_foo;
+  VERIFY (foo.type[2] == true);
+  VERIFY (foo.chars.size() == 4);
+  VERIFY (foo.chars[0] == 258);
+  VERIFY (foo.chars[1] == 772);
+  VERIFY (foo.chars[2] == 1286);
+  VERIFY (foo.chars[3] == 1800);
+}