http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49079
Summary: [4.6/4.7 Regression] Bogus constant folding Product: gcc Version: 4.6.1 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: tree-optimization AssignedTo: unassig...@gcc.gnu.org ReportedBy: rgue...@gcc.gnu.org libustr testing fails because we constant fold the s2 initializer in the following testcase despite the fact it can be modified by ustr_sc_ensure_owner. extern void abort (void); typedef long unsigned int size_t; struct Ustr { unsigned char data[1]; }; size_t ustr_xi__pow2(int, unsigned char); int ustr_sized(const struct Ustr *); int ustr_cmp_fast_buf(const struct Ustr*, const void*,size_t); const char *ustr_cstr(const struct Ustr *); int ustr_sc_ensure_owner(struct Ustr **); extern inline __attribute__ ((__gnu_inline__)) size_t ustr_xi__embed_val_get(const unsigned char *data, size_t len) { size_t ret = 0; switch (len) { case 0: return (-1); case 8: ret |= (((size_t)data[7]) << 56); ret |= (((size_t)data[6]) << 48); ret |= (((size_t)data[5]) << 40); ret |= (((size_t)data[4]) << 32); case 4: ret |= (((size_t)data[3]) << 24); ret |= (((size_t)data[2]) << 16); case 2: ret |= (((size_t)data[1]) << 8); case 1: ret |= (((size_t)data[0]) << 0); break; default: abort(); } return (ret); } extern inline __attribute__ ((__gnu_inline__)) size_t ustr_len(const struct Ustr *s1) { int usized; if (!s1->data[0]) return (0); usized = ustr_sized(s1); return (ustr_xi__embed_val_get(s1->data + 1 + ustr_xi__pow2(usized, (s1)->data[0] >> 2), ustr_xi__pow2(usized, (s1)->data[0]))); } extern inline __attribute__ ((__gnu_inline__)) int ustr_cmp_fast(const struct Ustr *s1,const struct Ustr*s2) { if (s1 == s2) return (0); return (ustr_cmp_fast_buf(s1, ustr_cstr(s2), ustr_len(s2))); } extern inline __attribute__ ((__gnu_inline__)) int ustr_cmp_eq(const struct Ustr *s1, const struct Ustr *s2) { return (!ustr_cmp_fast(s1, s2)); } static struct Ustr *s2 = ((struct Ustr *) "\x01" "\x02" "s2" "\0<ii-CONST_EOS-ii>"); int main() { ustr_sc_ensure_owner(&s2); if (!ustr_cmp_eq(s2, ((struct Ustr *) "\x01" "\x0002" "s2" "\0<ii-CONST_EOS-ii>"))) abort (); return 0; } It seems to need the several steps of inlining to reproduce, sofar I wasn't successfull in making a very simple testcase. The folding happens when inlining ustr_cmp_eq to main.