https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98109

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2020-12-03
     Ever confirmed|0                           |1
           Keywords|                            |diagnostic
                 CC|                            |msebor at gcc dot gnu.org
             Blocks|                            |95507
             Status|UNCONFIRMED                 |NEW

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warings are caused by the null tests inserted by the sanitizer that jump
threading turns into calls with constant nulls.  See below.  Adding attribute
nonnull also to swap_1000 avoids both the warnings and the sanitization.

This is a known problem with the sanitizer and the late warnings and there
probably is a report like this one in Bugzilla somewhere.  I suppose the
warning code could look for calls __builtin___ubsan_handle_nonnull_arg (and
similar) preceding the statement it's about to diagnose and avoid triggering if
it's found.  Until something like this is implemented the guidance is to live
with these warnings when using the sanitizer or suppress them by -Wno-xxx.

$ gcc -O2 -S -Wall -fsanitize=undefined -fdump-tree-ubsan=/dev/stdout
-fdump-tree-dom2=/dev/stdout pr98109.c

;; Function swap_1000 (swap_1000, funcdef_no=0, decl_uid=2388, cgraph_uid=1,
symbol_order=0)

Introduced new external node (__builtin___ubsan_handle_nonnull_arg/3).

Symbols to be put in SSA form
{ D.2392 }
Incremental SSA update started at block: 0
Number of blocks in CFG: 15
Number of blocks to update: 14 ( 93%)


void swap_1000 (char * elem1, char * elem2, size_t element_size)
{
  char buffer[1000];

  <bb 2> :
  if (&buffer == 0B)
    goto <bb 4>; [0.05%]
  else
    goto <bb 3>; [99.95%]

  <bb 4> :
  __builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data0);

  <bb 3> :
  if (elem1_2(D) == 0B)
    goto <bb 6>; [0.05%]
  else
    goto <bb 5>; [99.95%]

  <bb 6> :
  __builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data1);

  <bb 5> :
  my_memcpy (&buffer, elem1_2(D), 1000);
  if (elem1_2(D) == 0B)
    goto <bb 8>; [0.05%]
  else
    goto <bb 7>; [99.95%]

  <bb 8> :
  __builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data2);

  <bb 7> :
  if (elem2_4(D) == 0B)
    goto <bb 10>; [0.05%]
  else
    goto <bb 9>; [99.95%]

  <bb 10> :
  __builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data3);

  <bb 9> :
  my_memcpy (elem1_2(D), elem2_4(D), 1000);
  if (elem2_4(D) == 0B)
    goto <bb 12>; [0.05%]
  else
    goto <bb 11>; [99.95%]

  <bb 12> :
  __builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data4);

  <bb 11> :
  if (&buffer == 0B)
    goto <bb 14>; [0.05%]
  else
    goto <bb 13>; [99.95%]

  <bb 14> :
  __builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data5);

  <bb 13> :
  my_memcpy (elem2_4(D), &buffer, 1000);
  buffer ={v} {CLOBBER};
  return;

}



;; Function swap_1000 (swap_1000, funcdef_no=0, decl_uid=2388, cgraph_uid=1,
symbol_order=0)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2 3 4 5 6 7 8
;; 2 succs { 8 3 }
;; 3 succs { 4 }
;; 4 succs { 7 5 }
;; 5 succs { 6 }
;; 6 succs { 1 }
;; 7 succs { 6 }
;; 8 succs { 4 }
void swap_1000 (char * elem1, char * elem2, size_t element_size)
{
  char buffer[1000];

  <bb 2> [local count: 1073741824]:
  if (elem1_2(D) == 0B)
    goto <bb 3>; [0.00%]
  else
    goto <bb 8>; [100.00%]

  <bb 3> [count: 0]:
  __builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data1);
  my_memcpy (&buffer, 0B, 1000);
  __builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data2);

  <bb 4> [local count: 1073741824]:
  if (elem2_4(D) == 0B)
    goto <bb 5>; [0.00%]
  else
    goto <bb 7>; [100.00%]

  <bb 5> [count: 0]:
  __builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data3);
  my_memcpy (elem1_2(D), 0B, 1000);
  __builtin___ubsan_handle_nonnull_arg (&*.Lubsan_data4);

  <bb 6> [local count: 1073741824]:
  my_memcpy (elem2_4(D), &buffer, 1000);
  buffer ={v} {CLOBBER};
  return;

  <bb 7> [local count: 1073741824]:
  my_memcpy (elem1_2(D), elem2_4(D), 1000);
  goto <bb 6>; [100.00%]

  <bb 8> [local count: 1073741824]:
  my_memcpy (&buffer, elem1_2(D), 1000);
  goto <bb 4>; [100.00%]

}


pr98109.c: In function ‘swap_1000’:
pr98109.c:11:5: warning: argument 2 is null but the corresponding size argument
3 value is 1000 [-Wnonnull]
   11 |     my_memcpy(buffer, elem1, 1000);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr98109.c:3:7: note: in a call to function ‘my_memcpy’ declared with attribute
‘access (read_only, 2, 3)’
    3 | void *my_memcpy(void *destination, const void *source, size_t size)
      |       ^~~~~~~~~
pr98109.c:12:5: warning: argument 2 is null but the corresponding size argument
3 value is 1000 [-Wnonnull]
   12 |     my_memcpy(elem1, elem2, 1000);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr98109.c:3:7: note: in a call to function ‘my_memcpy’ declared with attribute
‘access (read_only, 2, 3)’
    3 | void *my_memcpy(void *destination, const void *source, size_t size)
      |       ^~~~~~~~~


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95507
[Bug 95507] [meta-bug] bogus/missing -Wnonnull

Reply via email to