aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-09-29 17:10:54 -0600
committerMartin Sebor <msebor@redhat.com>2020-09-29 17:13:55 -0600
commit873f8c1e6df94a9dcbfbe69f06538e3e45ba151d (patch)
tree9c7680bda586670d728244c647851453b47c059b /gcc/calls.c
parent969baf03acd8124345617cea125b148568c7370a (diff)
downloadgcc-873f8c1e6df94a9dcbfbe69f06538e3e45ba151d.zip
gcc-873f8c1e6df94a9dcbfbe69f06538e3e45ba151d.tar.gz
gcc-873f8c1e6df94a9dcbfbe69f06538e3e45ba151d.tar.bz2
Correct and improve -Wnonnull for calls to functions with VLA arguments (PR middle-end/97188).
Resolves: PR middle-end/97188 - ICE passing a null VLA to a function expecting at least one element gcc/ChangeLog: PR middle-end/97188 * calls.c (maybe_warn_rdwr_sizes): Simplify warning messages. Correct handling of VLA argumments. gcc/testsuite/ChangeLog: PR middle-end/97188 * gcc.dg/Wstringop-overflow-23.c: Adjust text of expected warnings. * gcc.dg/Wnonnull-4.c: New test.
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c115
1 files changed, 80 insertions, 35 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index 0e5c696..ed43638 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#define INCLUDE_STRING
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -1924,7 +1925,10 @@ static void
maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
{
auto_diagnostic_group adg;
- bool warned = false;
+
+ /* Set if a warning has been issued for any argument (used to decide
+ whether to emit an informational note at the end). */
+ bool any_warned = false;
/* A string describing the attributes that the warnings issued by this
function apply to. Used to print one informational note per function
@@ -1974,27 +1978,60 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
else
access_size = rwm->get (sizidx)->size;
- bool warned = false;
+ /* Format the value or range to avoid an explosion of messages. */
+ char sizstr[80];
+ tree sizrng[2] = { size_zero_node, build_all_ones_cst (sizetype) };
+ if (get_size_range (access_size, sizrng, true))
+ {
+ const char *s0 = print_generic_expr_to_str (sizrng[0]);
+ if (tree_int_cst_equal (sizrng[0], sizrng[1]))
+ {
+ gcc_checking_assert (strlen (s0) < sizeof sizstr);
+ strcpy (sizstr, s0);
+ }
+ else
+ {
+ const char *s1 = print_generic_expr_to_str (sizrng[1]);
+ gcc_checking_assert (strlen (s0) + strlen (s1)
+ < sizeof sizstr - 4);
+ sprintf (sizstr, "[%s, %s]", s0, s1);
+ }
+ }
+ else
+ *sizstr = '\0';
+
+ /* Set if a warning has been issued for the current argument. */
+ bool arg_warned = false;
location_t loc = EXPR_LOCATION (exp);
tree ptr = access.second.ptr;
- tree sizrng[2] = { size_zero_node, build_all_ones_cst (sizetype) };
- if (get_size_range (access_size, sizrng, true)
+ if (*sizstr
&& tree_int_cst_sgn (sizrng[0]) < 0
&& tree_int_cst_sgn (sizrng[1]) < 0)
{
/* Warn about negative sizes. */
- if (tree_int_cst_equal (sizrng[0], sizrng[1]))
- warned = warning_at (loc, OPT_Wstringop_overflow_,
- "%Kargument %i value %E is negative",
- exp, sizidx + 1, access_size);
+ if (access.second.internal_p)
+ {
+ const std::string argtypestr
+ = access.second.array_as_string (ptrtype);
+
+ arg_warned = warning_at (loc, OPT_Wstringop_overflow_,
+ "%Kbound argument %i value %s is "
+ "negative for a variable length array "
+ "argument %i of type %s",
+ exp, sizidx + 1, sizstr,
+ ptridx + 1, argtypestr.c_str ());
+ }
else
- warned = warning_at (loc, OPT_Wstringop_overflow_,
- "%Kargument %i range [%E, %E] is negative",
- exp, sizidx + 1, sizrng[0], sizrng[1]);
- if (warned)
+ arg_warned = warning_at (loc, OPT_Wstringop_overflow_,
+ "%Kargument %i value %s is negative",
+ exp, sizidx + 1, sizstr);
+
+ if (arg_warned)
{
append_attrname (access, attrstr, sizeof attrstr);
- /* Avoid warning again for the same attribute. */
+ /* Remember a warning has been issued and avoid warning
+ again below for the same attribute. */
+ any_warned = true;
continue;
}
}
@@ -2006,7 +2043,6 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
/* Multiply ACCESS_SIZE by the size of the type the pointer
argument points to. If it's incomplete the size is used
as is. */
- access_size = NULL_TREE;
if (tree argsize = TYPE_SIZE_UNIT (argtype))
if (TREE_CODE (argsize) == INTEGER_CST)
{
@@ -2028,35 +2064,44 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
different from also declaring the pointer argument with
attribute nonnull when the function accepts null pointers
only when the corresponding size is zero. */
- if (tree_int_cst_equal (sizrng[0], sizrng[1]))
- warned = warning_at (loc, OPT_Wnonnull,
- "%Kargument %i is null but "
- "the corresponding size argument %i "
- "value is %E",
- exp, ptridx + 1, sizidx + 1, access_size);
+ if (access.second.internal_p)
+ {
+ const std::string argtypestr
+ = access.second.array_as_string (ptrtype);
+
+ arg_warned = warning_at (loc, OPT_Wnonnull,
+ "%Kargument %i of variable length "
+ "array %s is null but "
+ "the corresponding bound argument "
+ "%i value is %s",
+ exp, sizidx + 1, argtypestr.c_str (),
+ ptridx + 1, sizstr);
+ }
else
- warned = warning_at (loc, OPT_Wnonnull,
- "%Kargument %i is null but "
- "the corresponding size argument %i "
- "range is [%E, %E]",
- exp, ptridx + 1, sizidx + 1,
- sizrng[0], sizrng[1]);
+ arg_warned = warning_at (loc, OPT_Wnonnull,
+ "%Kargument %i is null but "
+ "the corresponding size argument "
+ "%i value is %s",
+ exp, ptridx + 1, sizidx + 1,
+ sizstr);
}
else if (access_size && access.second.static_p)
{
/* Warn about null pointers for [static N] array arguments
but do not warn for ordinary (i.e., nonstatic) arrays. */
- warned = warning_at (loc, OPT_Wnonnull,
- "%Kargument %i to %<%T[static %E]%> null "
- "where non-null expected",
- exp, ptridx + 1, argtype,
- sizrng[0]);
+ arg_warned = warning_at (loc, OPT_Wnonnull,
+ "%Kargument %i to %<%T[static %E]%> "
+ "is null where non-null expected",
+ exp, ptridx + 1, argtype,
+ access_size);
}
- if (warned)
+ if (arg_warned)
{
append_attrname (access, attrstr, sizeof attrstr);
- /* Avoid warning again for the same attribute. */
+ /* Remember a warning has been issued and avoid warning
+ again below for the same attribute. */
+ any_warned = true;
continue;
}
}
@@ -2101,7 +2146,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
if (TREE_NO_WARNING (exp))
{
- warned = true;
+ any_warned = true;
if (access.second.internal_p)
inform (loc, "referencing argument %u of type %qT",
@@ -2124,7 +2169,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
"in a call with type %qT and attribute %qs",
fntype, attrstr);
}
- else if (warned)
+ else if (any_warned)
{
if (fndecl)
inform (DECL_SOURCE_LOCATION (fndecl),