From 9c76a19e8f83e9e9a154d1779115b5061687c97b Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 13 Apr 2011 17:38:50 +0200 Subject: [PATCH] re PR regression/48570 (wrong subscription with -std=c++0x) 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. From-SVN: r172377 --- gcc/cp/ChangeLog | 6 ++++ gcc/cp/semantics.c | 22 +++++++++--- gcc/testsuite/ChangeLog | 6 ++++ .../g++.dg/cpp0x/constexpr-wstring1.C | 34 +++++++++++++++++++ .../g++.dg/cpp0x/constexpr-wstring2.C | 7 ++++ 5 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3745e1a1b71..a0d7cc249b3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2011-04-13 Jakub Jelinek + + PR c++/48570 + * semantics.c (cxx_eval_array_reference): Handle reading from + wchar_t, char16_t and char32_t STRING_CST. + 2011-04-13 Dodji Seketeli PR c++/48574 diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 8752f3712c3..c763f813c5c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -6279,7 +6279,7 @@ cxx_eval_array_reference (const constexpr_call *call, tree t, 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 constexpr_call *call, tree t, 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 constexpr_call *call, tree t, 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. */ } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f066a80ad70..46ff86a1bfd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-04-13 Jakub Jelinek + + PR c++/48570 + * g++.dg/cpp0x/constexpr-wstring1.C: New test. + * g++.dg/cpp0x/constexpr-wstring2.C: New test. + 2011-04-13 Dodji Seketeli PR c++/48574 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C new file mode 100644 index 00000000000..059977bfff9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C new file mode 100644 index 00000000000..4fc8980ef96 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C @@ -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" } -- 2.30.2