aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2016-12-21 22:58:23 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2016-12-21 22:58:23 +0100
commitbc2a38dff859fcd1ec0aedd8c7d0fb748f2dbede (patch)
treef329df2339ddea40f6053ce6ac5b7a32624c58b6 /gcc
parent31bfc9b9dd65ecddff3afa690906d94ef7b773da (diff)
downloadgcc-bc2a38dff859fcd1ec0aedd8c7d0fb748f2dbede.zip
gcc-bc2a38dff859fcd1ec0aedd8c7d0fb748f2dbede.tar.gz
gcc-bc2a38dff859fcd1ec0aedd8c7d0fb748f2dbede.tar.bz2
re PR c++/77830 (internal compiler error: in output_constructor_regular_field, at varasm.c:4968, when using constexpr (with testcase))
PR c++/77830 * constexpr.c (cxx_eval_array_reference): Perform out of bounds verification even if lval is true, just allow one past the last element in that case. (cxx_eval_store_expression): Detect stores to out of bound ARRAY_REF. * g++.dg/cpp1y/pr77830.C: New test. * g++.dg/cpp0x/pr65398.C: Adjust expected diagnostics. From-SVN: r243873
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/constexpr.c117
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr65398.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr77830.C34
5 files changed, 137 insertions, 41 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index db3582a..180a0fb 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2016-12-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/77830
+ * constexpr.c (cxx_eval_array_reference): Perform out of bounds
+ verification even if lval is true, just allow one past the last
+ element in that case.
+ (cxx_eval_store_expression): Detect stores to out of bound
+ ARRAY_REF.
+
2016-12-21 Jason Merrill <jason@redhat.com>
Implement P0522R0, matching of template template arguments.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index aedd004..ca259cb 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -2183,9 +2183,9 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
lval,
non_constant_p, overflow_p);
tree index, oldidx;
- HOST_WIDE_INT i;
- tree elem_type;
- unsigned len, elem_nchars = 1;
+ HOST_WIDE_INT i = 0;
+ tree elem_type = NULL_TREE;
+ unsigned len = 0, elem_nchars = 1;
if (*non_constant_p)
return t;
oldidx = TREE_OPERAND (t, 1);
@@ -2193,39 +2193,38 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
false,
non_constant_p, overflow_p);
VERIFY_CONSTANT (index);
- if (lval && ary == oldary && index == oldidx)
- return t;
- else if (lval)
- return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
- elem_type = TREE_TYPE (TREE_TYPE (ary));
- if (TREE_CODE (ary) == VIEW_CONVERT_EXPR
- && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (ary, 0)))
- && TREE_TYPE (t) == TREE_TYPE (TREE_TYPE (TREE_OPERAND (ary, 0))))
- ary = TREE_OPERAND (ary, 0);
- if (TREE_CODE (ary) == CONSTRUCTOR)
- len = CONSTRUCTOR_NELTS (ary);
- else if (TREE_CODE (ary) == STRING_CST)
+ if (!lval)
{
- elem_nchars = (TYPE_PRECISION (elem_type)
- / TYPE_PRECISION (char_type_node));
- len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
- }
- else if (TREE_CODE (ary) == VECTOR_CST)
- len = VECTOR_CST_NELTS (ary);
- else
- {
- /* We can't do anything with other tree codes, so use
- VERIFY_CONSTANT to complain and fail. */
- VERIFY_CONSTANT (ary);
- gcc_unreachable ();
- }
+ elem_type = TREE_TYPE (TREE_TYPE (ary));
+ if (TREE_CODE (ary) == VIEW_CONVERT_EXPR
+ && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (ary, 0)))
+ && TREE_TYPE (t) == TREE_TYPE (TREE_TYPE (TREE_OPERAND (ary, 0))))
+ ary = TREE_OPERAND (ary, 0);
+ if (TREE_CODE (ary) == CONSTRUCTOR)
+ len = CONSTRUCTOR_NELTS (ary);
+ else if (TREE_CODE (ary) == STRING_CST)
+ {
+ elem_nchars = (TYPE_PRECISION (elem_type)
+ / TYPE_PRECISION (char_type_node));
+ len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
+ }
+ else if (TREE_CODE (ary) == VECTOR_CST)
+ len = VECTOR_CST_NELTS (ary);
+ else
+ {
+ /* We can't do anything with other tree codes, so use
+ VERIFY_CONSTANT to complain and fail. */
+ VERIFY_CONSTANT (ary);
+ gcc_unreachable ();
+ }
- if (!tree_fits_shwi_p (index)
- || (i = tree_to_shwi (index)) < 0)
- {
- diag_array_subscript (ctx, ary, index);
- *non_constant_p = true;
- return t;
+ if (!tree_fits_shwi_p (index)
+ || (i = tree_to_shwi (index)) < 0)
+ {
+ diag_array_subscript (ctx, ary, index);
+ *non_constant_p = true;
+ return t;
+ }
}
tree nelts;
@@ -2240,13 +2239,20 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p,
overflow_p);
VERIFY_CONSTANT (nelts);
- if (!tree_int_cst_lt (index, nelts))
+ if (lval
+ ? !tree_int_cst_le (index, nelts)
+ : !tree_int_cst_lt (index, nelts))
{
diag_array_subscript (ctx, ary, index);
*non_constant_p = true;
return t;
}
+ if (lval && ary == oldary && index == oldidx)
+ return t;
+ else if (lval)
+ return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
+
bool found;
if (TREE_CODE (ary) == CONSTRUCTOR)
{
@@ -3281,6 +3287,47 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
if (*non_constant_p)
return t;
+ /* cxx_eval_array_reference for lval = true allows references one past
+ end of array, because it does not know if it is just taking address
+ (which is valid), or actual dereference. Here we know it is
+ a dereference, so diagnose it here. */
+ for (tree probe = target; probe; )
+ {
+ switch (TREE_CODE (probe))
+ {
+ case ARRAY_REF:
+ tree nelts, ary;
+ ary = TREE_OPERAND (probe, 0);
+ if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE)
+ nelts = array_type_nelts_top (TREE_TYPE (ary));
+ else if (VECTOR_TYPE_P (TREE_TYPE (ary)))
+ nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary)));
+ else
+ gcc_unreachable ();
+ nelts = cxx_eval_constant_expression (ctx, nelts, false,
+ non_constant_p, overflow_p);
+ VERIFY_CONSTANT (nelts);
+ gcc_assert (TREE_CODE (nelts) == INTEGER_CST
+ && TREE_CODE (TREE_OPERAND (probe, 1)) == INTEGER_CST);
+ if (wi::eq_p (TREE_OPERAND (probe, 1), nelts))
+ {
+ diag_array_subscript (ctx, ary, TREE_OPERAND (probe, 1));
+ *non_constant_p = true;
+ return t;
+ }
+ /* FALLTHRU */
+
+ case BIT_FIELD_REF:
+ case COMPONENT_REF:
+ probe = TREE_OPERAND (probe, 0);
+ continue;
+
+ default:
+ probe = NULL_TREE;
+ continue;
+ }
+ }
+
if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (target), type))
{
/* For initialization of an empty base, the original target will be
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e6ee770..2da0d44 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2016-12-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/77830
+ * g++.dg/cpp1y/pr77830.C: New test.
+ * g++.dg/cpp0x/pr65398.C: Adjust expected diagnostics.
+
2016-12-21 Bernd Schmidt <bschmidt@redhat.com>
PR target/71321
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr65398.C b/gcc/testsuite/g++.dg/cpp0x/pr65398.C
index 6bd34a4..bab875c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr65398.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr65398.C
@@ -20,9 +20,9 @@ constexpr char d5 = *(&s[4] - 4);
constexpr char d6 = *(&s[4] - 5); // { dg-error "array subscript" }
/* Don't accept invalid stuff. */
-constexpr char e1 = *(&s[5] - 1); // { dg-error "is not a constant expression" }
-constexpr char e2 = *(&s[5] - 2); // { dg-error "is not a constant expression" }
-constexpr char e3 = *(&s[5] - 3); // { dg-error "is not a constant expression" }
+constexpr char e1 = *(&s[5] - 1); // { dg-error "array subscript" }
+constexpr char e2 = *(&s[5] - 2); // { dg-error "array subscript" }
+constexpr char e3 = *(&s[5] - 3); // { dg-error "array subscript" }
SA (c1 == 'a');
SA (c2 == 'b');
@@ -53,9 +53,9 @@ constexpr char j5 = *(&l[4] - 4);
constexpr char j6 = *(&l[4] - 5); // { dg-error "array subscript" }
/* Don't accept invalid stuff. */
-constexpr char k1 = *(&l[5] - 1); // { dg-error "is not a constant expression" }
-constexpr char k2 = *(&l[5] - 2); // { dg-error "is not a constant expression" }
-constexpr char k3 = *(&l[5] - 3); // { dg-error "is not a constant expression" }
+constexpr char k1 = *(&l[5] - 1); // { dg-error "array subscript" }
+constexpr char k2 = *(&l[5] - 2); // { dg-error "array subscript" }
+constexpr char k3 = *(&l[5] - 3); // { dg-error "array subscript" }
SA (i1 == 'c');
SA (i2 == 'd');
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr77830.C b/gcc/testsuite/g++.dg/cpp1y/pr77830.C
new file mode 100644
index 0000000..9235b40
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr77830.C
@@ -0,0 +1,34 @@
+// PR c++/77830
+// { dg-do compile { target c++14 } }
+
+template <int N>
+struct P
+{
+ char arr[N][1];
+ constexpr void foo (const char *, int);
+};
+
+template <int N>
+constexpr void
+P<N>::foo (const char *, int i)
+{
+ for (auto j = 0; j < 2; ++j)
+ arr[i][j] = true;
+}
+
+template <typename... T>
+constexpr auto
+bar (T... a)
+{
+ const char *s[]{a...};
+ P<sizeof...(a)> p{};
+ for (auto i = 0; i < sizeof...(a); ++i)
+ p.foo (s[i], i);
+ return p;
+}
+
+int
+main ()
+{
+ constexpr auto a = bar ("", ""); // { dg-error "outside the bounds of array type" }
+}