[C++ PATCH] Handle correctly ARRAY_REFs from STRING_CST for wchar_t/char{16,32}_t (PR c++/48570)
Jakub Jelinek
jakub@redhat.com
Tue Apr 12 17:06:00 GMT 2011
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
More information about the Gcc-patches
mailing list