diff options
author | Martin Sebor <msebor@redhat.com> | 2019-02-11 17:35:17 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2019-02-11 10:35:17 -0700 |
commit | 28a8cef1e240989c199dfd8538c826c134098f85 (patch) | |
tree | a7b930a4f8e120d187bde8f6ea311c2ed60e6d55 /gcc/c-family | |
parent | 3c4860e346b8292ac398d971aff933586b11e3ea (diff) | |
download | gcc-28a8cef1e240989c199dfd8538c826c134098f85.zip gcc-28a8cef1e240989c199dfd8538c826c134098f85.tar.gz gcc-28a8cef1e240989c199dfd8538c826c134098f85.tar.bz2 |
PR c++/87996 - size of array is negative error when SIZE_MAX/2 < sizeof(array) <= SIZE_MAX
gcc/ChangeLog:
PR c++/87996
* builtins.c (max_object_size): Move from here...
* builtins.h (max_object_size): ...and here...
* tree.c (max_object_size): ...to here...
* tree.h (max_object_size): ...and here.
gcc/c-family/ChangeLog:
PR c++/87996
* c-common.c (invalid_array_size_error): New function.
(valid_array_size_p): Call it. Handle size as well as type.
* c-common.h (valid_constant_size_p): New function.
(enum cst_size_error): New type.
gcc/cp/ChangeLog:
PR c++/87996
* decl.c (compute_array_index_type_loc): Preserve signed sizes
for diagnostics. Call valid_array_size_p instead of error.
* init.c (build_new_1): Compute size for diagnostic. Call
invalid_array_size_error
(build_new): Call valid_array_size_p instead of error.
gcc/testsuite/ChangeLog:
PR c++/87996
* c-c++-common/array-5.c: New test.
* c-c++-common/pr68107.c: Adjust text of diagnostics.
* g++.dg/init/new38.C: Same.
* g++.dg/init/new43.C: Same.
* g++.dg/init/new44.C: Same.
* g++.dg/init/new46.C: Same.
* g++.dg/other/large-size-array.C: Same.
* g++.dg/other/new-size-type.C: Same.
* g++.dg/template/array30.C: Same.
* g++.dg/template/array32.C: New test.
* g++.dg/template/dependent-name3.C: Adjust.
* gcc.dg/large-size-array-3.c: Same.
* gcc.dg/large-size-array-5.c: Same.
* gcc.dg/large-size-array.c: Same.
* g++.old-deja/g++.brendan/array1.C: Same.
* g++.old-deja/g++.mike/p6149.C: Same.
From-SVN: r268774
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 85 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 4 |
3 files changed, 80 insertions, 17 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index dd1173f..7dae7bf 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,11 @@ +2019-02-11 Martin Sebor <msebor@redhat.com> + + PR c++/87996 + * c-common.c (invalid_array_size_error): New function. + (valid_array_size_p): Call it. Handle size as well as type. + * c-common.h (valid_constant_size_p): New function. + (enum cst_size_error): New type. + 2019-01-31 David Malcolm <dmalcolm@redhat.com> PR c/89122 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index d3b5879..ae23e59 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -8231,29 +8231,82 @@ reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */) return false; } +/* Issue an ERROR for an invalid SIZE of array NAME which is null + for unnamed arrays. */ + +void +invalid_array_size_error (location_t loc, cst_size_error error, + const_tree size, const_tree name) +{ + tree maxsize = max_object_size (); + switch (error) + { + case cst_size_negative: + if (name) + error_at (loc, "size %qE of array %qE is negative", + size, name); + else + error_at (loc, "size %qE of array is negative", + size); + break; + case cst_size_too_big: + if (name) + error_at (loc, "size %qE of array %qE exceeds maximum " + "object size %qE", size, name, maxsize); + else + error_at (loc, "size %qE of array exceeds maximum " + "object size %qE", size, maxsize); + break; + case cst_size_overflow: + if (name) + error_at (loc, "size of array %qE exceeds maximum " + "object size %qE", name, maxsize); + else + error_at (loc, "size of array exceeds maximum " + "object size %qE", maxsize); + break; + default: + gcc_unreachable (); + } +} + /* Check if array size calculations overflow or if the array covers more than half of the address space. Return true if the size of the array - is valid, false otherwise. TYPE is the type of the array and NAME is - the name of the array, or NULL_TREE for unnamed arrays. */ + is valid, false otherwise. T is either the type of the array or its + size, and NAME is the name of the array, or null for unnamed arrays. */ bool -valid_array_size_p (location_t loc, tree type, tree name, bool complain) +valid_array_size_p (location_t loc, const_tree t, tree name, bool complain) { - if (type != error_mark_node - && COMPLETE_TYPE_P (type) - && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST - && !valid_constant_size_p (TYPE_SIZE_UNIT (type))) + if (t == error_mark_node) + return true; + + const_tree size; + if (TYPE_P (t)) { - if (complain) - { - if (name) - error_at (loc, "size of array %qE is too large", name); - else - error_at (loc, "size of unnamed array is too large"); - } - return false; + if (!COMPLETE_TYPE_P (t)) + return true; + size = TYPE_SIZE_UNIT (t); } - return true; + else + size = t; + + if (TREE_CODE (size) != INTEGER_CST) + return true; + + cst_size_error error; + if (valid_constant_size_p (size, &error)) + return true; + + if (!complain) + return false; + + if (TREE_CODE (TREE_TYPE (size)) == ENUMERAL_TYPE) + /* Show the value of the enumerator rather than its name. */ + size = convert (ssizetype, const_cast<tree> (size)); + + invalid_array_size_error (loc, error, size, name); + return false; } /* Read SOURCE_DATE_EPOCH from environment to have a deterministic diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 69cb76c..394a0ea 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1270,7 +1270,9 @@ extern tree find_inv_trees (tree *, int *, void *); extern tree replace_inv_trees (tree *, int *, void *); extern bool reject_gcc_builtin (const_tree, location_t = UNKNOWN_LOCATION); -extern bool valid_array_size_p (location_t, tree, tree, bool = true); +extern bool valid_array_size_p (location_t, const_tree, tree, bool = true); +extern void invalid_array_size_error (location_t, cst_size_error, + const_tree, const_tree); /* In c-warn.c. */ extern void constant_expression_warning (tree); |