public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH] Handle correctly ARRAY_REFs from STRING_CST for wchar_t/char{16,32}_t (PR c++/48570)
@ 2011-04-12 17:06 Jakub Jelinek
  2011-04-12 23:14 ` Jason Merrill
  0 siblings, 1 reply; 4+ messages in thread
From: Jakub Jelinek @ 2011-04-12 17:06 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

Hi!

As the testcase below shows, cxx_eval_array_reference only works
properly if ary is CONSTRUCTOR or narrow STRING_CST, if it is
wchar_t/char16_t/char32_t string literal, it still reads a single
byte from the string as if it was a char string.

The following patch fixes that, bootstrapped/regtested on x86_64-linux
and i686-linux, ok for trunk/4.6?

2011-04-12  Jakub Jelinek  <jakub@redhat.com>

	PR c++/48570
	* semantics.c (cxx_eval_array_reference): Handle reading from
	wchar_t, char16_t and char32_t STRING_CST.

	* g++.dg/cpp0x/constexpr-wstring.C: New test.

--- gcc/cp/semantics.c.jj	2011-04-12 09:37:43.000000000 +0200
+++ gcc/cp/semantics.c	2011-04-12 15:46:43.000000000 +0200
@@ -6293,7 +6293,9 @@ cxx_eval_array_reference (const constexp
     return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
   len = (TREE_CODE (ary) == CONSTRUCTOR
 	 ? CONSTRUCTOR_NELTS (ary)
-	 : (unsigned)TREE_STRING_LENGTH (ary));
+	 : (unsigned)TREE_STRING_LENGTH (ary)
+	   * (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (ary)))
+	      / TYPE_PRECISION (char_type_node)));
   if (compare_tree_int (index, len) >= 0)
     {
       if (!allow_non_constant)
@@ -6304,9 +6306,19 @@ cxx_eval_array_reference (const constexp
   i = tree_low_cst (index, 0);
   if (TREE_CODE (ary) == CONSTRUCTOR)
     return VEC_index (constructor_elt, CONSTRUCTOR_ELTS (ary), i)->value;
-  else
+  else if (TYPE_PRECISION (TREE_TYPE (t)) == TYPE_PRECISION (char_type_node))
     return build_int_cst (cv_unqualified (TREE_TYPE (TREE_TYPE (ary))),
 			  TREE_STRING_POINTER (ary)[i]);
+  else
+    {
+      tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (ary)));
+      unsigned elem_len = (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (ary)))
+			   / TYPE_PRECISION (char_type_node));
+      return native_interpret_expr (type,
+				    (const unsigned char *)
+				    TREE_STRING_POINTER (ary) + i * elem_len,
+				    elem_len);
+    }
   /* Don't VERIFY_CONSTANT here.  */
 }
 
--- gcc/testsuite/g++.dg/cpp0x/constexpr-wstring.C.jj	2011-04-12 15:49:44.000000000 +0200
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-wstring.C	2011-04-12 15:48:55.000000000 +0200
@@ -0,0 +1,34 @@
+// PR c++/48570
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+extern "C" void abort ();
+constexpr wchar_t foo (int i) { return L"0123"[i]; }
+constexpr char16_t bar (int i) { return u"0123"[i]; }
+constexpr char32_t baz (int i) { return U"0123"[i]; }
+const wchar_t foo0 = foo (0);
+const wchar_t foo1 = foo (1);
+const wchar_t foo2 = foo (2);
+const wchar_t foo3 = foo (3);
+const wchar_t foo4 = foo (4);
+const char16_t bar0 = bar (0);
+const char16_t bar1 = bar (1);
+const char16_t bar2 = bar (2);
+const char16_t bar3 = bar (3);
+const char16_t bar4 = bar (4);
+const char32_t baz0 = baz (0);
+const char32_t baz1 = baz (1);
+const char32_t baz2 = baz (2);
+const char32_t baz3 = baz (3);
+const char32_t baz4 = baz (4);
+
+int
+main ()
+{
+  if (foo0 != L'0' || foo1 != L'1' || foo2 != L'2' || foo3 != L'3' || foo4 != L'\0')
+    abort ();
+  if (bar0 != u'0' || bar1 != u'1' || bar2 != u'2' || bar3 != u'3' || bar4 != u'\0')
+    abort ();
+  if (baz0 != U'0' || baz1 != U'1' || baz2 != U'2' || baz3 != U'3' || baz4 != U'\0')
+    abort ();
+}

	Jakub

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [C++ PATCH] Handle correctly ARRAY_REFs from STRING_CST for wchar_t/char{16,32}_t (PR c++/48570)
  2011-04-12 17:06 [C++ PATCH] Handle correctly ARRAY_REFs from STRING_CST for wchar_t/char{16,32}_t (PR c++/48570) Jakub Jelinek
@ 2011-04-12 23:14 ` Jason Merrill
  2011-04-13  8:49   ` Jakub Jelinek
  0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2011-04-12 23:14 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On 04/12/2011 01:06 PM, Jakub Jelinek wrote:
> +	 : (unsigned)TREE_STRING_LENGTH (ary)
> +	   * (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (ary)))
> +	      / TYPE_PRECISION (char_type_node)));

Don't you mean / instead of * here?  Let's also calculate the size of 
the element once rather than here and again later.

Jason

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [C++ PATCH] Handle correctly ARRAY_REFs from STRING_CST for wchar_t/char{16,32}_t (PR c++/48570)
  2011-04-12 23:14 ` Jason Merrill
@ 2011-04-13  8:49   ` Jakub Jelinek
  2011-04-13 14:14     ` Jason Merrill
  0 siblings, 1 reply; 4+ messages in thread
From: Jakub Jelinek @ 2011-04-13  8:49 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

On Tue, Apr 12, 2011 at 07:13:51PM -0400, Jason Merrill wrote:
> On 04/12/2011 01:06 PM, Jakub Jelinek wrote:
> >+	 : (unsigned)TREE_STRING_LENGTH (ary)
> >+	   * (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (ary)))
> >+	      / TYPE_PRECISION (char_type_node)));
> 
> Don't you mean / instead of * here?

You're right, thanks for catching it.  I've added a testcase
for the out of bounds case too.

> Let's also calculate the size
> of the element once rather than here and again later.

Like this?  Bootstrapped/regtested on x86_64-linux and i686-linux:

2011-04-13  Jakub Jelinek  <jakub@redhat.com>

	PR c++/48570
	* semantics.c (cxx_eval_array_reference): Handle reading from
	wchar_t, char16_t and char32_t STRING_CST.

	* g++.dg/cpp0x/constexpr-wstring1.C: New test.
	* g++.dg/cpp0x/constexpr-wstring2.C: New test.

--- gcc/cp/semantics.c.jj	2011-04-12 19:43:49.433483082 +0200
+++ gcc/cp/semantics.c	2011-04-13 08:25:07.904796653 +0200
@@ -6279,7 +6279,7 @@ cxx_eval_array_reference (const constexp
 					   non_constant_p);
   tree index, oldidx;
   HOST_WIDE_INT i;
-  unsigned len;
+  unsigned len, elem_nchars = 1;
   if (*non_constant_p)
     return t;
   oldidx = TREE_OPERAND (t, 1);
@@ -6291,9 +6291,14 @@ cxx_eval_array_reference (const constexp
     return t;
   else if (addr)
     return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
-  len = (TREE_CODE (ary) == CONSTRUCTOR
-	 ? CONSTRUCTOR_NELTS (ary)
-	 : (unsigned)TREE_STRING_LENGTH (ary));
+  if (TREE_CODE (ary) == CONSTRUCTOR)
+    len = CONSTRUCTOR_NELTS (ary);
+  else
+    {
+      elem_nchars = (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (ary)))
+		     / TYPE_PRECISION (char_type_node));
+      len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
+    }
   if (compare_tree_int (index, len) >= 0)
     {
       if (!allow_non_constant)
@@ -6304,9 +6309,16 @@ cxx_eval_array_reference (const constexp
   i = tree_low_cst (index, 0);
   if (TREE_CODE (ary) == CONSTRUCTOR)
     return VEC_index (constructor_elt, CONSTRUCTOR_ELTS (ary), i)->value;
-  else
+  else if (elem_nchars == 1)
     return build_int_cst (cv_unqualified (TREE_TYPE (TREE_TYPE (ary))),
 			  TREE_STRING_POINTER (ary)[i]);
+  else
+    {
+      tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (ary)));
+      return native_interpret_expr (type, (const unsigned char *)
+					  TREE_STRING_POINTER (ary)
+					  + i * elem_nchars, elem_nchars);
+    }
   /* Don't VERIFY_CONSTANT here.  */
 }
 
--- gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C.jj	2011-04-13 08:21:23.079513403 +0200
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C	2011-04-13 08:21:23.079513403 +0200
@@ -0,0 +1,34 @@
+// PR c++/48570
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+extern "C" void abort ();
+constexpr wchar_t foo (int i) { return L"0123"[i]; }
+constexpr char16_t bar (int i) { return u"0123"[i]; }
+constexpr char32_t baz (int i) { return U"0123"[i]; }
+const wchar_t foo0 = foo (0);
+const wchar_t foo1 = foo (1);
+const wchar_t foo2 = foo (2);
+const wchar_t foo3 = foo (3);
+const wchar_t foo4 = foo (4);
+const char16_t bar0 = bar (0);
+const char16_t bar1 = bar (1);
+const char16_t bar2 = bar (2);
+const char16_t bar3 = bar (3);
+const char16_t bar4 = bar (4);
+const char32_t baz0 = baz (0);
+const char32_t baz1 = baz (1);
+const char32_t baz2 = baz (2);
+const char32_t baz3 = baz (3);
+const char32_t baz4 = baz (4);
+
+int
+main ()
+{
+  if (foo0 != L'0' || foo1 != L'1' || foo2 != L'2' || foo3 != L'3' || foo4 != L'\0')
+    abort ();
+  if (bar0 != u'0' || bar1 != u'1' || bar2 != u'2' || bar3 != u'3' || bar4 != u'\0')
+    abort ();
+  if (baz0 != U'0' || baz1 != U'1' || baz2 != U'2' || baz3 != U'3' || baz4 != U'\0')
+    abort ();
+}
--- gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C.jj	2011-04-13 08:26:01.158764728 +0200
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C	2011-04-13 08:29:31.321808236 +0200
@@ -0,0 +1,7 @@
+// PR c++/48570
+// { dg-do compile }
+// { dg-options -std=c++0x }
+
+constexpr wchar_t c1 = L"hi"[3];	// { dg-error "out of bound" }
+constexpr char16_t c2 = u"hi"[3];	// { dg-error "out of bound" }
+constexpr char32_t c3 = U"hi"[3];	// { dg-error "out of bound" }


	Jakub

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [C++ PATCH] Handle correctly ARRAY_REFs from STRING_CST for wchar_t/char{16,32}_t (PR c++/48570)
  2011-04-13  8:49   ` Jakub Jelinek
@ 2011-04-13 14:14     ` Jason Merrill
  0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2011-04-13 14:14 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

OK.

Jason

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-04-13 14:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-12 17:06 [C++ PATCH] Handle correctly ARRAY_REFs from STRING_CST for wchar_t/char{16,32}_t (PR c++/48570) Jakub Jelinek
2011-04-12 23:14 ` Jason Merrill
2011-04-13  8:49   ` Jakub Jelinek
2011-04-13 14:14     ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).