loongson-community / gcc

GCC source tree for Loongson
GNU General Public License v2.0
17 stars 1 forks source link

[tree-ssa-strlen] strlen(s) return value can be assumed to be less than the size of s #8

Open xiangzhai opened 6 years ago

xiangzhai commented 6 years ago

Hi fellows,

As PR78450 mentioned:

$ /opt/loongson-gnu-5.5/bin/mips64-linux-gnu-gcc -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout x.c

;; Function f (f, funcdef_no=0, decl_uid=1488, cgraph_uid=0, symbol_order=2)

f (int i)
{
  <bb 2>:
  return;

}

;; Function g (g, funcdef_no=1, decl_uid=1495, cgraph_uid=1, symbol_order=5)

Removing basic block 3
g (int i)
{
  unsigned int n;
  const char * s;
  long unsigned int _4;

  <bb 2>:
  if (i_2(D) < 0)
    goto <bb 4>;
  else
    goto <bb 3>;

  <bb 3>:

  <bb 4>:
  # s_1 = PHI <&a3(2), &b4(3)>
  _4 = __builtin_strlen (s_1);
  n_5 = (unsigned int) _4;
  if (n_5 > 3)
    goto <bb 5>;
  else
    goto <bb 6>;

  <bb 5>:
  __builtin_abort ();

  <bb 6>:
  return;

}

But GCC 8.x works correctly:

$ /opt/mips-gnu-git/bin/mips64-linux-gnu-gcc -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout x.c

;; Function f (f, funcdef_no=0, decl_uid=1584, cgraph_uid=0, symbol_order=2)

f (int i)
{
  <bb 2> [local count: 1073741825]:
  return;

}

;; Function g (g, funcdef_no=3, decl_uid=1591, cgraph_uid=1, symbol_order=5)

g (int i)
{
  <bb 2> [local count: 1073741825]:
  return;

}

Testcase:

$ cat x.c 
const char a[] = "123";
const char b[] = "1234";

void f (int i)
{
  const char *s = i < 0 ? a : b;
  unsigned n = __builtin_strlen (s);
  if (4 < n)
    __builtin_abort ();
}

char a3[3];
char b4[4];

void g (int i)
{
  const char *s = i < 0 ? a3 : b4;
  unsigned n = __builtin_strlen (s);
  if (3 < n)
    __builtin_abort ();
}

Martin fixed the bug for GCC 8.x, but after GCC 5.x wi::to_widest was migrated to wi::to_wide, so backport patch failed to build:

../../gcc/wide-int.h: In instantiation of ‘wide_int_storage::wide_int_storage(const T&) [with T = generic_wide_int<wi::extended_tree<192> >]’:
../../gcc/wide-int.h:718:15:   required from ‘generic_wide_int<T>::generic_wide_int(const T&) [with T = generic_wide_int<wi::extended_tree<192> >; storage = wide_int_storage]’
../../gcc/tree-ssa-strlen.c:1130:38:   required from here
../../gcc/system.h:749:15: error: size of array is negative
   typedef int assertion1[(X) ? 1 : -1] ATTRIBUTE_UNUSED
               ^
../../gcc/wide-int.h:1028:5: note: in expansion of macro ‘STATIC_ASSERT’
   { STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::CONST_PRECISION); }
     ^~~~~~~~~~~~~

Regards, Leslie Zhai