diff options
Diffstat (limited to 'gcc/calls.c')
-rw-r--r-- | gcc/calls.c | 122 |
1 files changed, 68 insertions, 54 deletions
diff --git a/gcc/calls.c b/gcc/calls.c index b183be63dd4..31663f4f67b 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1196,65 +1196,79 @@ static GTY(()) tree alloc_object_size_limit; static tree alloc_max_size (void) { - if (!alloc_object_size_limit) - { - alloc_object_size_limit = TYPE_MAX_VALUE (ssizetype); + 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 = TYPE_MAX_VALUE (ssizetype); - 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) - { - wide_int w = wi::uhwi (limit, HOST_BITS_PER_WIDE_INT + 64); - w *= unit; - if (wi::ltu_p (w, alloc_object_size_limit)) - alloc_object_size_limit = wide_int_to_tree (ssizetype, 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; } |