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

            Bug ID: 92624
           Summary: inconsistent folding of strcmp calls with unterminated
                    arrays
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

This shows an inconsistency in how GCC handles code with undefined behavior
that is easily detectable in all four functions below.  But by "taking
shortcuts" in some cases (and folding the result of the call when both
arguments are known to point to the same array) while being more careful in
others (even though the contents of the const arrays are known, they are also
known not to be nul-terminated), it introduces an inconsistency in how the
undefined behavior is handled: in the former case it's safely avoided while in
the latter, by calling the library function, the result is unpredictable.

At the same time, in the latter case the problem can be detected before
expansion and diagnosed by -Wstringop-overflow (once pr88226 is resolved), in
the former it won't be.

This is one of the kinds of problems that will need to be dealt with if/when
more consistency in dealing with undefined behavior is introduced (as has been
discussed).

$ cat t.c && gcc -O2 -S -Wall -Wextra  -fdump-tree-optimized=/dev/stdout t.c
const char a[] = { '1', '2' };
const char b[] = { '1', '2' };

int f0 (void)
{
  const char *p = a, *q = b;
  return __builtin_strcmp (p, q);   // not folded
}

int f1 (void)
{
  const char *p = a, *q = a;
  return __builtin_strcmp (p, q);   // folded to zero
}


int g0 (void)
{
  const char *p = a, *q = b;
  return __builtin_strncmp (p, q, 4);   // not folded
}

int g1 (void)
{
  const char *p = a, *q = a;
  return __builtin_strncmp (p, q, 4);   // folded to zero
}


;; Function f0 (f0, funcdef_no=0, decl_uid=1932, cgraph_uid=1, symbol_order=2)

f0 ()
{
  int _2;

  <bb 2> [local count: 1073741824]:
  _2 = __builtin_strcmp (&a, &b); [tail call]
  return _2;

}



;; Function f1 (f1, funcdef_no=1, decl_uid=1937, cgraph_uid=2, symbol_order=3)

f1 ()
{
  <bb 2> [local count: 1073741824]:
  return 0;

}



;; Function g0 (g0, funcdef_no=2, decl_uid=1942, cgraph_uid=3, symbol_order=4)

g0 ()
{
  int _2;

  <bb 2> [local count: 1073741824]:
  _2 = __builtin_strncmp (&a, &b, 4); [tail call]
  return _2;

}



;; Function g1 (g1, funcdef_no=5, decl_uid=1947, cgraph_uid=4, symbol_order=5)

g1 ()
{
  <bb 2> [local count: 1073741824]:
  return 0;

}

Reply via email to