aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2020-10-06 17:59:07 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2020-10-07 09:39:37 -0400
commit2f7c50b7091c09d665aaf27173aacf34c9904e4c (patch)
treec6b83159151e44279b7b1c6c41d2d2deef7e252a
parent7345c89ecb1a31ce96c6789bffc7183268a040b3 (diff)
downloadgcc-2f7c50b7091c09d665aaf27173aacf34c9904e4c.zip
gcc-2f7c50b7091c09d665aaf27173aacf34c9904e4c.tar.gz
gcc-2f7c50b7091c09d665aaf27173aacf34c9904e4c.tar.bz2
analyzer: handle C++ argument numbers and "this" [PR97116]
gcc/analyzer/ChangeLog: PR analyzer/97116 * sm-malloc.cc (method_p): New. (describe_argument_index): New. (inform_nonnull_attribute): Use describe_argument_index. (possible_null_arg::describe_final_event): Likewise. (null_arg::describe_final_event): Likewise. gcc/testsuite/ChangeLog: PR analyzer/97116 * g++.dg/analyzer/pr97116.C: New test.
-rw-r--r--gcc/analyzer/sm-malloc.cc61
-rw-r--r--gcc/testsuite/g++.dg/analyzer/pr97116.C39
2 files changed, 86 insertions, 14 deletions
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 6293d78..fd12a35 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -562,15 +562,40 @@ public:
};
+/* Return true if FNDECL is a C++ method. */
+
+static bool
+method_p (tree fndecl)
+{
+ return TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE;
+}
+
+/* Return a 1-based description of ARG_IDX (0-based) of FNDECL.
+ Compare with %P in the C++ FE (implemented in cp/error.c: parm_to_string
+ as called from cp_printer). */
+
+static label_text
+describe_argument_index (tree fndecl, int arg_idx)
+{
+ if (method_p (fndecl))
+ if (arg_idx == 0)
+ return label_text::borrow ("'this'");
+ pretty_printer pp;
+ pp_printf (&pp, "%u", arg_idx + 1 - method_p (fndecl));
+ return label_text::take (xstrdup (pp_formatted_text (&pp)));
+}
+
/* Subroutine for use by possible_null_arg::emit and null_arg::emit.
Issue a note informing that the pertinent argument must be non-NULL. */
static void
inform_nonnull_attribute (tree fndecl, int arg_idx)
{
+ label_text arg_desc = describe_argument_index (fndecl, arg_idx);
inform (DECL_SOURCE_LOCATION (fndecl),
- "argument %u of %qD must be non-null",
- arg_idx + 1, fndecl);
+ "argument %s of %qD must be non-null",
+ arg_desc.m_buffer, fndecl);
+ arg_desc.maybe_free ();
/* Ideally we would use the location of the parm and underline the
attribute also - but we don't have the location_t values at this point
in the middle-end.
@@ -618,15 +643,19 @@ public:
label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE
{
+ label_text arg_desc = describe_argument_index (m_fndecl, m_arg_idx);
+ label_text result;
if (m_origin_of_unchecked_event.known_p ())
- return ev.formatted_print ("argument %u (%qE) from %@ could be NULL"
- " where non-null expected",
- m_arg_idx + 1, ev.m_expr,
- &m_origin_of_unchecked_event);
+ result = ev.formatted_print ("argument %s (%qE) from %@ could be NULL"
+ " where non-null expected",
+ arg_desc.m_buffer, ev.m_expr,
+ &m_origin_of_unchecked_event);
else
- return ev.formatted_print ("argument %u (%qE) could be NULL"
- " where non-null expected",
- m_arg_idx + 1, ev.m_expr);
+ result = ev.formatted_print ("argument %s (%qE) could be NULL"
+ " where non-null expected",
+ arg_desc.m_buffer, ev.m_expr);
+ arg_desc.maybe_free ();
+ return result;
}
private:
@@ -714,13 +743,17 @@ public:
label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE
{
+ label_text arg_desc = describe_argument_index (m_fndecl, m_arg_idx);
+ label_text result;
if (zerop (ev.m_expr))
- return ev.formatted_print ("argument %u NULL where non-null expected",
- m_arg_idx + 1);
+ result = ev.formatted_print ("argument %s NULL where non-null expected",
+ arg_desc.m_buffer);
else
- return ev.formatted_print ("argument %u (%qE) NULL"
- " where non-null expected",
- m_arg_idx + 1, ev.m_expr);
+ result = ev.formatted_print ("argument %s (%qE) NULL"
+ " where non-null expected",
+ arg_desc.m_buffer, ev.m_expr);
+ arg_desc.maybe_free ();
+ return result;
}
private:
diff --git a/gcc/testsuite/g++.dg/analyzer/pr97116.C b/gcc/testsuite/g++.dg/analyzer/pr97116.C
new file mode 100644
index 0000000..d8e08a7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/pr97116.C
@@ -0,0 +1,39 @@
+#include <new>
+#include <cstddef>
+
+struct foo
+{
+ foo (int i) : m_i (i) {} // { dg-message "argument 'this' of 'foo::foo\\(int\\)' must be non-null" "note" }
+
+ int get () const { return m_i; } // { dg-message "argument 'this' of '\[^\n\]*' must be non-null" "note" }
+
+ int meth_1 (int, void *ptr) __attribute__((nonnull)); // { dg-message "argument 2 of '\[^\n\]*' must be non-null" "note" }
+ int meth_2 (int, void *ptr) __attribute__((nonnull(3))); // { dg-message "argument 2 of '\[^\n\]*' must be non-null" "note" }
+
+ int m_i;
+};
+
+void test_1 (void)
+{
+ foo *p = new(NULL) foo (42); // { dg-warning "non-null expected" "warning" }
+ // { dg-message "argument 'this' \\(\[^\n\]*\\) NULL where non-null expected" "final event" { target *-*-* } .-1 }
+}
+
+int test_2 (void)
+{
+ foo *p = NULL;
+ return p->get (); // { dg-warning "non-null expected" "warning" }
+ // { dg-message "argument 'this' \\('p'\\) NULL where non-null expected" "final event" { target *-*-* } .-1 }
+}
+
+int test_meth_1 (foo *f)
+{
+ return f->meth_1 (42, NULL); // { dg-warning "non-null expected" "warning" }
+ // { dg-message "argument 2 NULL where non-null expected" "final event" { target *-*-* } .-1 }
+}
+
+int test_meth_2 (foo *f)
+{
+ return f->meth_2 (42, NULL); // { dg-warning "non-null expected" "warning" }
+ // { dg-message "argument 2 NULL where non-null expected" "final event" { target *-*-* } .-1 }
+}