--- /dev/null
+/* PR middle-end/92942 - missing -Wstringop-overflow for allocations with
+ a negative lower bound size
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+#define SIZE_MAX __SIZE_MAX__
+#define UINT8_MAX __UINT8_MAX__
+#define UINT16_MAX __UINT16_MAX__
+
+typedef __SIZE_TYPE__ size_t;
+typedef __UINT8_TYPE__ uint8_t;
+typedef __UINT16_TYPE__ uint16_t;
+
+void* usr_alloc1 (size_t) __attribute__ ((alloc_size (1)));
+void* usr_alloc2 (size_t, size_t) __attribute__ ((alloc_size (1, 2)));
+
+void* malloc (size_t);
+void* memcpy (void*, const void*, size_t);
+void* memset (void*, int, size_t);
+char* strcpy (char*, const char*);
+
+void sink (void*);
+
+void malloc_uint_range_strcpy (unsigned n)
+{
+ void *p = malloc (5 < n ? 5 : n);
+
+ strcpy (p, "01234"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ strcpy (p, "0123");
+ sink (p);
+}
+
+void malloc_uint16_anti_range_memset (uint16_t n)
+{
+ if (5 <= n && n <= 9) return;
+ void *p = malloc (n);
+
+ if (UINT16_MAX < SIZE_MAX)
+ {
+ size_t sz = (uint16_t)-1 + (size_t)1;
+ memset (p, 0, sz); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+ }
+
+ memset (p, 0, 1);
+ sink (p);
+ memset (p, 0, 5);
+ sink (p);
+ memset (p, 0, 6);
+ sink (p);
+ memset (p, 0, UINT16_MAX - 1);
+ sink (p);
+ memset (p, 0, UINT16_MAX);
+ sink (p);
+}
+
+void malloc_int_strcpy (int n)
+{
+ void *p = malloc (7 < n ? 7 : n);
+
+ strcpy (p, "0123456"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ strcpy (p, "012345");
+ sink (p);
+}
+
+void vla_int_strcpy (int n)
+{
+ char a[9 < n ? 9 : n];
+
+ strcpy (a, "012345678"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (a);
+
+ strcpy (a, "01234567");
+ sink (a);
+}
+
+void usr_alloc1_int_strcpy (int n)
+{
+ void *p = usr_alloc1 (7 < n ? 7 : n);
+
+ strcpy (p, "0123456"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ strcpy (p, "012345");
+ sink (p);
+}
+
+void usr_alloc2_cst_ir_strcpy (int n)
+{
+ void *p = usr_alloc2 (1, 5 < n ? 5 : n);
+
+ strcpy (p, "01234"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ strcpy (p, "0123");
+ sink (p);
+}
+
+void usr_alloc2_ir_ir_strcpy (int m, int n)
+{
+ void *p = usr_alloc2 (3 < n ? 3 : n, 5 < n ? 5 : n);
+
+ strcpy (p, "0123456789abcde"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ strcpy (p, "0123456789abcd");
+ sink (p);
+}
+
+void usr_alloc2_uint8_memset (uint8_t m, uint8_t n)
+{
+ if (3 <= m && m <= 7) return;
+ if (5 <= n && n <= 9) return;
+ void *p = usr_alloc2 (m, n);
+
+ size_t sz = UINT8_MAX * UINT8_MAX + 1;
+ memset (p, 0, sz); // { dg-warning "\\\[-Wstringop-overflow" "" { xfail *-*-* } }
+ // { dg-warning "\\\[-Warray-bounds" "pr?????" { target *-*-* } .-1 }
+ sink (p);
+
+ memset (p, 0, sz - 1);
+ sink (p);
+ memset (p, 0, 64);
+ sink (p);
+ memset (p, 0, 63);
+ sink (p);
+ memset (p, 0, 16);
+ sink (p);
+ memset (p, 0, 15);
+ sink (p);
+ memset (p, 0, 14);
+ sink (p);
+ memset (p, 0, 3);
+ sink (p);
+}
+
+
+
+void malloc_int_memset (int n)
+{
+ void *p = malloc (11 < n ? 11 : n);
+
+ memset (p, 0, 12); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ memset (p, 0, 11);
+ sink (p);
+}
+
+void vla_int_memset (int n)
+{
+ char a[13 < n ? 13 : n];
+
+ memset (a, 0, 14); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (a);
+
+ memset (a, 0, 13);
+ sink (a);
+}
--- /dev/null
+/* Verify that an anti-range ~[A, B] with small positive A and B
+ is handled correctly and doesn't trigger warnings.
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __typeof__ (sizeof 0) size_t;
+
+int f (void*, size_t);
+int g (void*);
+
+// Test case distilled from gcc/cp/semantics.c
+
+int omp_reduction_id (int i, int j, const char *mm)
+{
+ const char *p = 0;
+ const char *m = 0;
+
+ switch (i)
+ {
+ case 1:
+ p = "min";
+ break;
+ case 2:
+ p = "max";
+ break;
+ default:
+ break;
+ }
+
+ if (j)
+ m = mm;
+
+ const char prefix[] = "omp declare reduction ";
+ size_t lenp = sizeof (prefix);
+
+ if (__builtin_strncmp (p, prefix, lenp - 1) == 0)
+ lenp = 1;
+
+ size_t len = __builtin_strlen (p);
+ size_t lenm = m ? __builtin_strlen (m) + 1 : 0;
+ char *name = ((char *) __builtin_alloca(lenp + len + lenm));
+
+ if (lenp > 1)
+ __builtin_memcpy (name, prefix, lenp - 1);
+
+ __builtin_memcpy (name + lenp - 1, p, len + 1);
+ if (m)
+ {
+ name[lenp + len - 1] = '~';
+ __builtin_memcpy (name + lenp + len, m, lenm);
+ }
+ return (__builtin_constant_p (name)
+ ? f (name, __builtin_strlen (name)) : g (name));
+}
+
+// Test case derived from gcc/d/dmd/root/filename.c.
+
+const char *ext (const char *str)
+{
+ size_t len = __builtin_strlen(str);
+
+ const char *e = str + len;
+ for (;;)
+ {
+ switch (*e)
+ {
+ case '.': return e + 1;
+ case '/': break;
+ default:
+ if (e == str)
+ break;
+ e--;
+ continue;
+ }
+ return 0;
+ }
+}
+
+const char *removeExt (const char *str)
+{
+ const char *e = ext (str);
+ if (e)
+ {
+ size_t len = (e - str) - 1;
+ char *n = (char *)__builtin_malloc (len + 1);
+ __builtin_memcpy(n, str, len);
+ n[len] = 0;
+ return n;
+ }
+ return 0;
+}