Bug 78917 - missing -Wnonnull passing null to a nonnull function
Summary: missing -Wnonnull passing null to a nonnull function
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wnonnull
  Show dependency treegraph
 
Reported: 2016-12-24 00:01 UTC by Martin Sebor
Modified: 2020-11-03 05:03 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 10.1.0, 11.0, 7.3.0, 8.2.0, 9.1.0
Last reconfirmed: 2020-06-03 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2016-12-24 00:01:52 UTC
While experimenting with the enhanced -Wnonnull warning added in GCC 7.0 (bug 17308) I noticed that it fails to detect the following trivial case of  passing a null pointer to a function declared nonnull.  This is different from bug 78914 where the null pointer is being dereferenced directly.

$ cat z.c && gcc -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout z.c
int g (int i, int j)
{
  char *p = i <= 0 ? (char*)0 : "123";
  char *q = 0 != i ? (char*)0 : "4567";
  char *r = i ? q : p;

  return __builtin_strlen (r);
}

z.c: In function ‘g’:
z.c:1:19: warning: unused parameter ‘j’ [-Wunused-parameter]
 int g (int i, int j)
                   ^

;; Function g (g, funcdef_no=0, decl_uid=1796, cgraph_uid=0, symbol_order=0)

g (int i, int j)
{
  long unsigned int _1;
  int _7;

  <bb 2> [100.00%]:
  _1 = __builtin_strlen (0B);
  _7 = (int) _1;
  return _7;

}
Comment 1 Eric Gallager 2017-08-28 19:53:02 UTC
Confirmed, although I'm wondering how this is different from bug 78998? Sure, the original source is slightly different, but they optimize to pretty much the same thing... doing -fdump-tree-optimized to text files instead of /dev/stdout and then comparing them gives:

$ diff -u 78998_opt.txt 78917_opt.txt
--- 78998_opt.txt	2017-08-28 15:50:10.000000000 -0400
+++ 78917_opt.txt	2017-08-28 15:50:23.000000000 -0400
@@ -1,15 +1,15 @@
 
-;; Function f (f, funcdef_no=0, decl_uid=1769, cgraph_uid=0, symbol_order=0)
+;; Function g (g, funcdef_no=0, decl_uid=1770, cgraph_uid=0, symbol_order=0)
 
-f (int i)
+g (int i, int j)
 {
   long unsigned int _1;
-  int _6;
+  int _7;
 
   <bb 2> [100.00%] [count: INV]:
   _1 = __builtin_strlen (0B); [tail call]
-  _6 = (int) _1;
-  return _6;
+  _7 = (int) _1;
+  return _7;
 
 }
 
$
Comment 2 Martin Sebor 2018-08-11 19:13:30 UTC
Another test case:

$ cat f.c && gcc -O2 -S -Wall -Wextra f.c
int f (int i)
{
  const char * p = __builtin_strchr (i ? "123" : "456", '2');
  return __builtin_strlen (p);
}

The strlen argument is a phi with a null operand so that should make it easy to detect:

  # prephitmp_11 = PHI <_10(3), 0B(2)>
  _1 = __builtin_strlen (prephitmp_11);
Comment 3 Eric Gallager 2019-05-11 03:28:55 UTC
(In reply to Martin Sebor from comment #2)
> Another test case:
> 
> $ cat f.c && gcc -O2 -S -Wall -Wextra f.c
> int f (int i)
> {
>   const char * p = __builtin_strchr (i ? "123" : "456", '2');
>   return __builtin_strlen (p);
> }
> 
> The strlen argument is a phi with a null operand so that should make it easy
> to detect:
> 
>   # prephitmp_11 = PHI <_10(3), 0B(2)>
>   _1 = __builtin_strlen (prephitmp_11);

OK, this second testcase is different enough, so I guess this bug can stay separate
Comment 4 Martin Sebor 2020-06-03 20:08:09 UTC
No improvement in GCC 10 or 11 (trunk).