public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-2544] Let -Wuninitialized assume built-ins don't change const arguments [PR101584].
@ 2021-07-27 22:05 Martin Sebor
  0 siblings, 0 replies; only message in thread
From: Martin Sebor @ 2021-07-27 22:05 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:6aacd901b800ee8a2a03123669b299a08aad0504

commit r12-2544-g6aacd901b800ee8a2a03123669b299a08aad0504
Author: Martin Sebor <msebor@redhat.com>
Date:   Tue Jul 27 16:02:54 2021 -0600

    Let -Wuninitialized assume built-ins don't change const arguments [PR101584].
    
    PR tree-optimization/101584 - missing -Wuninitialized with an allocated object after a built-in call
    
    gcc/ChangeLog:
    
            PR tree-optimization/101584
            * tree-ssa-uninit.c (builtin_call_nomodifying_p): New function.
            (check_defs): Call it.
    
    gcc/testsuite/ChangeLog:
    
            PR tree-optimization/101584
            * gcc.dg/uninit-38.c: Remove assertions.
            * gcc.dg/uninit-41.c: New test.

Diff:
---
 gcc/testsuite/gcc.dg/uninit-38.c |  39 +------------
 gcc/testsuite/gcc.dg/uninit-41.c | 121 +++++++++++++++++++++++++++++++++++++++
 gcc/tree-ssa-uninit.c            |  67 ++++++++++++++++++++++
 3 files changed, 190 insertions(+), 37 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/uninit-38.c b/gcc/testsuite/gcc.dg/uninit-38.c
index 8dacc8c63a6..0d70bcd8e98 100644
--- a/gcc/testsuite/gcc.dg/uninit-38.c
+++ b/gcc/testsuite/gcc.dg/uninit-38.c
@@ -1,5 +1,5 @@
-/* Verify that dereferencing uninitialized allocated objects and VLAs
-   correctly reflects offsets into the objects.
+/* Verify that dereferencing uninitialized VLAs correctly reflects
+   offsets into the objects.
    The test's main purpose is to exercise the formatting of MEM_REFs.
    If -Wuninitialized gets smarter and detects uninitialized accesses
    before they're turned into MEM_REFs the test will likely need to
@@ -18,41 +18,6 @@ extern void* malloc (size_t);
 
 void sink (void*, ...);
 
-#undef T
-#define T(Type, idx, off)			\
-  __attribute__ ((noipa))			\
-  void UNIQ (test_)(int n)			\
-  {						\
-    void *p = malloc (n);			\
-    Type *q = (Type*)((char*)p + off);		\
-    sink (p, q[idx]);				\
-  }						\
-  typedef void dummy_type
-
-T (int, 0, 0);      // { dg-warning "'\\*\\(int \\*\\)p' is used uninitialized" }
-T (int, 0, 1);      // { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)'" }
-T (int, 0, 2);      // { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)p \\+ 2\\)'" }
-T (int, 0, 3);      // { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)p \\+ 3\\)'" }
-T (int, 0, 4);      // { dg-warning "'\\(\\(int \\*\\)p\\)\\\[1]'" }
-T (int, 0, 5);      // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)\\)\\\[1]'" }
-T (int, 0, 6);      // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 2\\)\\)\\\[1]'" }
-T (int, 0, 7);      // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 3\\)\\)\\\[1]'" }
-T (int, 0, 8);      // { dg-warning "'\\(\\(int \\*\\)p\\)\\\[2]'" }
-T (int, 0, 9);      // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)\\)\\\[2]'" }
-
-
-T (int, 1, 0);      // { dg-warning "'\\(\\(int \\*\\)p\\)\\\[1]' is used uninitialized" }
-T (int, 1, 1);      // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)\\)\\\[1]'" }
-T (int, 1, 2);      // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 2\\)\\)\\\[1]'" }
-T (int, 1, 3);      // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 3\\)\\)\\\[1]'" }
-T (int, 1, 4);      // { dg-warning "'\\(\\(int \\*\\)p\\)\\\[2]'" }
-T (int, 1, 5);      // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)\\)\\\[2]'" }
-T (int, 1, 6);      // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 2\\)\\)\\\[2]'" }
-T (int, 1, 7);      // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 3\\)\\)\\\[2]'" }
-T (int, 1, 8);      // { dg-warning "'\\(\\(int \\*\\)p\\)\\\[3]'" }
-T (int, 1, 9);      // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)\\)\\\[3]'" }
-
-#undef T
 #define T(Type, idx, off)			\
   __attribute__ ((noipa))			\
   void UNIQ (test_)(int n)			\
diff --git a/gcc/testsuite/gcc.dg/uninit-41.c b/gcc/testsuite/gcc.dg/uninit-41.c
new file mode 100644
index 00000000000..b485611e994
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-41.c
@@ -0,0 +1,121 @@
+/* Verify that calls to non-modifying built-ins aren't considered
+   potentially modifying.
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* alloca (size_t);
+void* calloc (size_t, size_t);
+void* malloc (size_t);
+int printf (const char *, ...);
+int scanf (const char *, ...);
+int sprintf (char *, const char *, ...);
+int snprintf (char *, size_t, const char *, ...);
+int puts (const char *);
+char* strcpy (char*, const char*);
+size_t strlen (const char*);
+
+void noproto ();
+
+void sink (int, ...);
+
+extern char a[];
+
+void nowarn_noproto (const char *fmt)
+{
+  int i;
+  noproto (&i);
+  sink (i);
+}
+
+void nowarn_scanf (const char *fmt)
+{
+  int i;
+  scanf ("%i", &i);
+  sink (i);
+}
+
+void test_puts_sprintf_alloca (const char *fmt)
+{
+  char *p;
+  {
+    p = alloca (8);
+    sprintf (a, fmt, p);                // fmt might contain %n
+    puts (p);
+  }
+
+  {
+    p = alloca (8);
+    snprintf (0, 0, fmt, p);            // same as above
+    puts (p);
+  }
+}
+
+void test_puts_alloca (const char *s)
+{
+  char *p = alloca (8);
+
+  {
+    char a[] = "foo";
+    puts (a);
+  }
+
+  puts (p);                             // { dg-warning "-Wuninitialized" }
+
+  {
+    p = alloca (strlen (s) + 1);
+    strcpy (p, s);
+    puts (p);
+  }
+
+  {
+    /* Verify that the puts() calls above isn't considered to have
+       potentially modified *P, and same for the one below.  */
+    p = alloca (strlen (s));
+    puts (p);                           // { dg-warning "-Wuninitialized" }
+    puts (p + 1);                       // { dg-warning "-Wuninitialized" }
+  }
+}
+
+
+void test_puts_malloc (const char *s, const char *t)
+{
+  char *p;
+
+  {
+    p = malloc (strlen (s) + 1);
+    strcpy (p, s);
+    puts (p);
+  }
+
+  {
+    p = malloc (strlen (t));
+    puts (p);                           // { dg-warning "-Wuninitialized" }
+  }
+}
+
+
+void test_puts_vla (const char *s, const char *t)
+{
+  {
+    char a[strlen (s) + 1];
+    strcpy (a, s);
+    puts (a);
+  }
+
+  {
+    char b[strlen (t)];
+    puts (b);                           // { dg-warning "-Wuninitialized" }
+  }
+}
+
+
+void test_printf_puts (const char *s)
+{
+  char *p = __builtin_malloc (1);
+
+  printf ("%s", s);
+
+  puts (p);                             // { dg-warning "-Wuninitialized" }
+}
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 718b32691c1..ab64a680568 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -219,6 +219,70 @@ struct check_defs_data
   bool found_may_defs;
 };
 
+/* Return true if STMT is a call to built-in function all of whose
+   by-reference arguments are const-qualified (i.e., the function can
+   be assumed not to modify them).  */
+
+static bool
+builtin_call_nomodifying_p (gimple *stmt)
+{
+  if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+    return false;
+
+  tree fndecl = gimple_call_fndecl (stmt);
+  if (!fndecl)
+    return false;
+
+  tree fntype = TREE_TYPE (fndecl);
+  if (!fntype)
+    return false;
+
+  /* Check the called function's signature for non-constc pointers.
+     If one is found, return false.  */
+  unsigned argno = 0;
+  tree argtype;
+  function_args_iterator it;
+  FOREACH_FUNCTION_ARGS (fntype, argtype, it)
+    {
+      if (VOID_TYPE_P (argtype))
+	return true;
+
+      ++argno;
+
+      if (!POINTER_TYPE_P (argtype))
+	continue;
+
+      if (TYPE_READONLY (TREE_TYPE (argtype)))
+	continue;
+
+      return false;
+    }
+
+  /* If the number of actual arguments to the call is less than or
+     equal to the number of parameters, return false.  */
+  unsigned nargs = gimple_call_num_args (stmt);
+  if (nargs <= argno)
+    return false;
+
+  /* Check arguments passed through the ellipsis in calls to variadic
+     functions for pointers.  If one is found that's a non-constant
+     pointer, return false.  */
+  for (; argno < nargs; ++argno)
+    {
+      tree arg = gimple_call_arg (stmt, argno);
+      argtype = TREE_TYPE (arg);
+      if (!POINTER_TYPE_P (argtype))
+	continue;
+
+      if (TYPE_READONLY (TREE_TYPE (argtype)))
+	continue;
+
+      return false;
+    }
+
+  return true;
+}
+
 /* Callback for walk_aliased_vdefs.  */
 
 static bool
@@ -261,6 +325,9 @@ check_defs (ao_ref *ref, tree vdef, void *data_)
       return false;
     }
 
+  if (builtin_call_nomodifying_p (def_stmt))
+    return false;
+
   /* Found a may-def on this path.  */
   data->found_may_defs = true;
   return true;


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-07-27 22:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-27 22:05 [gcc r12-2544] Let -Wuninitialized assume built-ins don't change const arguments [PR101584] Martin Sebor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).