diff options
author | Martin Sebor <msebor@redhat.com> | 2018-05-31 17:04:43 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2018-05-31 11:04:43 -0600 |
commit | d258f4aa696e770d7a06f960c34531804e649900 (patch) | |
tree | 2b6dac6be9352a05bbc3fe624037fdf0438691b5 /gcc/calls.c | |
parent | 3217e694854fe50be13091f071283f47aad9b348 (diff) | |
download | gcc-d258f4aa696e770d7a06f960c34531804e649900.zip gcc-d258f4aa696e770d7a06f960c34531804e649900.tar.gz gcc-d258f4aa696e770d7a06f960c34531804e649900.tar.bz2 |
PR c/82063 - issues with arguments enabled by -Wall
gcc/c-family/ChangeLog:
PR c/82063
* c.opt (-Wno-alloc-size-larger-than): New option.
* doc/invoke.texi (-Walloc-size-larger-than): Update.
gcc/ChangeLog:
PR c/82063
* calls.c (alloc_max_size): Correct a logic error/typo.
Treat excessive arguments as infinite. Warn for invalid arguments.
gcc/testsuite/ChangeLog:
PR c/82063
* gcc.dg/Walloc-size-larger-than-1.c: New test.
* gcc.dg/Walloc-size-larger-than-10.c: New test.
* gcc.dg/Walloc-size-larger-than-11.c: New test.
* gcc.dg/Walloc-size-larger-than-12.c: New test.
* gcc.dg/Walloc-size-larger-than-13.c: New test.
* gcc.dg/Walloc-size-larger-than-14.c: New test.
* gcc.dg/Walloc-size-larger-than-15.c: New test.
* gcc.dg/Walloc-size-larger-than-16.c: New test.
* gcc.dg/Walloc-size-larger-than-17.c: New test.
* gcc.dg/Walloc-size-larger-than-2.c: New test.
* gcc.dg/Walloc-size-larger-than-3.c: New test.
* gcc.dg/Walloc-size-larger-than-4.c: New test.
* gcc.dg/Walloc-size-larger-than-5.c: New test.
* gcc.dg/Walloc-size-larger-than-6.c: New test.
* gcc.dg/Walloc-size-larger-than-7.c: New test.
* gcc.dg/Walloc-size-larger-than-8.c: New test.
* gcc.dg/Walloc-size-larger-than-9.c: New test.
* gcc.dg/Walloc-size-larger-than.c: New test.
From-SVN: r261030
Diffstat (limited to 'gcc/calls.c')
-rw-r--r-- | gcc/calls.c | 124 |
1 files changed, 70 insertions, 54 deletions
diff --git a/gcc/calls.c b/gcc/calls.c index 1f2cde6..6e1ea92 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1231,65 +1231,81 @@ static GTY(()) tree alloc_object_size_limit; static tree alloc_max_size (void) { - if (!alloc_object_size_limit) - { - alloc_object_size_limit = max_object_size (); + if (alloc_object_size_limit) + return alloc_object_size_limit; - if (warn_alloc_size_limit) - { - char *end = NULL; - errno = 0; - unsigned HOST_WIDE_INT unit = 1; - unsigned HOST_WIDE_INT limit - = strtoull (warn_alloc_size_limit, &end, 10); + alloc_object_size_limit = max_object_size (); - if (!errno) - { - if (end && *end) - { - /* Numeric option arguments are at most INT_MAX. Make it - possible to specify a larger value by accepting common - suffixes. */ - if (!strcmp (end, "kB")) - unit = 1000; - else if (!strcasecmp (end, "KiB") || strcmp (end, "KB")) - unit = 1024; - else if (!strcmp (end, "MB")) - unit = HOST_WIDE_INT_UC (1000) * 1000; - else if (!strcasecmp (end, "MiB")) - unit = HOST_WIDE_INT_UC (1024) * 1024; - else if (!strcasecmp (end, "GB")) - unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000; - else if (!strcasecmp (end, "GiB")) - unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024; - else if (!strcasecmp (end, "TB")) - unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000; - else if (!strcasecmp (end, "TiB")) - unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024; - else if (!strcasecmp (end, "PB")) - unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000; - else if (!strcasecmp (end, "PiB")) - unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024; - else if (!strcasecmp (end, "EB")) - unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000 - * 1000; - else if (!strcasecmp (end, "EiB")) - unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024 - * 1024; - else - unit = 0; - } + if (!warn_alloc_size_limit) + return alloc_object_size_limit; - if (unit) - { - widest_int w = wi::mul (limit, unit); - if (w < wi::to_widest (alloc_object_size_limit)) - alloc_object_size_limit - = wide_int_to_tree (ptrdiff_type_node, w); - } - } + const char *optname = "-Walloc-size-larger-than="; + + char *end = NULL; + errno = 0; + unsigned HOST_WIDE_INT unit = 1; + unsigned HOST_WIDE_INT limit + = strtoull (warn_alloc_size_limit, &end, 10); + + /* If the value is too large to be represented use the maximum + representable value that strtoull sets limit to (setting + errno to ERANGE). */ + + if (end && *end) + { + /* Numeric option arguments are at most INT_MAX. Make it + possible to specify a larger value by accepting common + suffixes. */ + if (!strcmp (end, "kB")) + unit = 1000; + else if (!strcasecmp (end, "KiB") || !strcmp (end, "KB")) + unit = 1024; + else if (!strcmp (end, "MB")) + unit = HOST_WIDE_INT_UC (1000) * 1000; + else if (!strcasecmp (end, "MiB")) + unit = HOST_WIDE_INT_UC (1024) * 1024; + else if (!strcasecmp (end, "GB")) + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000; + else if (!strcasecmp (end, "GiB")) + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024; + else if (!strcasecmp (end, "TB")) + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000; + else if (!strcasecmp (end, "TiB")) + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024; + else if (!strcasecmp (end, "PB")) + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000; + else if (!strcasecmp (end, "PiB")) + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024; + else if (!strcasecmp (end, "EB")) + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000 + * 1000; + else if (!strcasecmp (end, "EiB")) + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024 + * 1024; + else + { + /* This could mean an unknown suffix or a bad prefix, like + "+-1". */ + warning_at (UNKNOWN_LOCATION, 0, + "invalid argument %qs to %qs", + warn_alloc_size_limit, optname); + + /* Ignore the limit extracted by strtoull. */ + unit = 0; } } + + if (unit) + { + widest_int w = wi::mul (limit, unit); + if (w < wi::to_widest (alloc_object_size_limit)) + alloc_object_size_limit + = wide_int_to_tree (ptrdiff_type_node, w); + else + alloc_object_size_limit = build_all_ones_cst (size_type_node); + } + + return alloc_object_size_limit; } |