http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57230

--- Comment #8 from Zack Weinberg <zackw at panix dot com> ---
(In reply to Jakub Jelinek from comment #6)
> We have just one strlen pass instance, and even if we optimize the first
> strlen
> there, having strlen pass duplicate constant propagation functionality just
> to handle this weird testcase (storing strlen sizes inside of characters is
> nothing common) doesn't make sense.

I think I gave the wrong impression there; I was trying to exhibit a more
comprehensive *correctness* test for this transformation, using strlen() as a
convenient-to-hand function known in context to return a nonzero value.  Lemme
try again.

  extern __SIZE_TYPE__ strlen(const char *);
  extern int rand(void);
  extern void abort(void) __attribute__((noreturn));
  #define assert(x) do { if (!(x)) abort(); } while (0)

  /* Returns a value that might or might not be zero. */
  static inline char maybe_zero() { return rand() & 0x10; }
  /* Returns an unknown but definitely-nonzero value. */
  static inline char nonzero() { return (rand() & 0x10) | 0x01; }

  int main(void)
  {
    char s[] = "abc\0def";

    /* These operations do not change the length of the string. */
    s[0] = nonzero();  assert(strlen(s) == 3);
    s[1] = nonzero();  assert(strlen(s) == 3);
    s[2] = nonzero();  assert(strlen(s) == 3);
    s[3] = '\0';       assert(strlen(s) == 3);
    s[4] = '\0';       assert(strlen(s) == 3);
    s[4] = 'd';        assert(strlen(s) == 3);

    /* These operations change the length of the string, to a
       value (in principle) computable at compile time. */
    s[3] = nonzero();  assert(strlen(s) == 7);
    s[5] = '\0';       assert(strlen(s) == 5);
    s[2] = '\0';       assert(strlen(s) == 2);
    s[2] = 'c';        assert(strlen(s) == 5);
    s[5] = nonzero();  assert(strlen(s) == 7);

    /* This operation requires runtime recalculation of the
       length of the string. */
    s[4] = maybe_zero();
    assert(strlen(s) == (s[4] ? 7 : 4));
    return 0;
  }

Of all of that, the most important thing IMHO (given the original bug report)
is to verify that writing '\0' at a nonzero *offset* within a string does not
cause a subsequent strlen() to report the length of the string as zero.

Reply via email to