Attached is a revised patch for just the access warning pass
to diagnose out-of-bounds stores by atomic functions, with
no attr-fnspec changes.
Is this okay for trunk?
Martin
PS Just to clarify the effect of the original patch in case
it wasn't: it didn't enable optimizations of atomic built-ins.
It just made it possible, by first calling the new
atomic_builtin_fnspec() to get the fnspec, and then by actually
doing something with it. The original patch did not modify
builtin_fnspec() to call the new atomic_builtin_fnspec(). But
since you seem to have reservations about exposing the attribute
in any form I have withdrawn the original patch and replaced it
with the more limited one.
On 10/13/21 2:15 AM, Richard Biener wrote:
On Tue, Oct 12, 2021 at 9:44 PM Martin Sebor <mse...@gmail.com> wrote:
On 10/12/21 12:52 AM, Richard Biener wrote:
On Mon, Oct 11, 2021 at 11:25 PM Martin Sebor <mse...@gmail.com> wrote:
The attached change extends GCC's warnings for out-of-bounds
stores to cover atomic (and __sync) built-ins.
Rather than hardcoding the properties of these built-ins just
for the sake of the out-of-bounds detection, on the assumption
that it might be useful for future optimizations as well, I took
the approach of extending class attr_fnspec to express their
special property that they encode the size of the access in their
name.
I also took the liberty of making attr_fnspec assignable (something
the rest of my patch relies on), and updating some comments for
the characters the class uses to encode function properties, based
on my understanding of their purpose.
Tested on x86_64-linux.
Hmm, so you place 'A' at an odd place (where the return value is specified),
but you do not actually specify the behavior on the return value. Shoudln't
+ 'A' specifies that the function atomically accesses a constant
+ 1 << N bytes where N is indicated by character 3+2i
maybe read
'A' specifies that the function returns the memory pointed to
by argument
one of size 1 << N bytes where N is indicated by
character 3 +2i accessed atomically
?
I didn't think the return value would be interesting because in
general (parallel accesses) it's not related (in an observable
way) to the value of the dereferenced operand. Not all
the built-ins also return a value (e.g., atomic_store), and
whether or not one does return the argument would need to be
encoded somehow because it cannot be determined from the return
type (__atomic_compare_exchange and __atomic_test_and_set return
bool that's not necessarily the value of the operand). Also,
since the functions return the operand value either before or
after the update, we'd need another letter to describe that.
(This alone could be dealt with simply by using 'A' and 'a',
but that's not enough for the other cases.)
So with all these possibilities I don't think encoding
the return value at this point is worthwhile. If/when this
enhancement turns out to be used for optimization and we think
encoding the return value would be helpful, I'd say let's
revisit it then. The accessor APIs should make it a fairly
straightforward exercise.
I though it would be useful for points-to analysis since knowing how
the return value is composed improves the points-to result for it.
Note that IPA mod-ref now synthesizes fn-spec and might make use
of 'A' if it were not narrowly defined. Sure it's probably difficult to
fully specify the RMW cycle that's eventually done but since we
have a way to specify a non-constant size of accesses as passed
by a parameter it would be nice to allow specifying a constant size
anyhow. It just occured to me we could use "fake" parameters to
encode those, so for
void foo (int *);
use like ". R2c4" saying that parameter 1 is read with the size
specified by (non-existing) parameter 2 which is specified as
'c'onstant 1 << 4.
Alternatively a constant size specification could use alternate
encoding 'a' to 'f'. That said, if 'A' is not suppose to specify
the return value it shouldn't be in the return value specification...
I also wonder if it's necessary to constrain this to 'atomic' accesses
for the purpose of the patch and whether that detail could be omitted to
eventually make more use of it?
I pondered the same question but I couldn't think of any other
built-ins with similar semantics (read-write-modify, return
a result either pre- or post-modification), so I opted for
simplicity. I am open to generalizing it if/when there is
a function I could test it with, although I'm not sure
the current encoding scheme has enough letters and letter
positions to describe the effects in their full generality.
Likewise
+ '0'...'9' specifies the size of value written/read is given either
+ by the specified argument, or for atomic functions, by
+ 2 ^ N where N is the constant value denoted by the character
should mention (excluding '0') for the argument position.
Sure, I'll update the comment if you think this change is worth
pursuing.
/* length of the fn spec string. */
- const unsigned len;
+ unsigned len;
why that?
The const member is what prevents the struct from being assignable,
which is what the rest of the patch depends on.
+ /* Return true of the function is an __atomic or __sync built-in. */
you didn't specify that for 'A' ...
+ bool
+ atomic_p () const
+ {
+ return str[0] == 'A';
+ }
+attr_fnspec
+atomic_builtin_fnspec (tree callee)
+{
+ switch (DECL_FUNCTION_CODE (callee))
+ {
+#define BUILTIN_ACCESS_SIZE_FNSPEC(N, lgsz) \
+ BUILT_IN_ATOMIC_LOAD_ ## N: \
+ return "Ap" "R" lgsz;
note that doing this for atomics makes those no longer a compiler barrier
for (aliased) loads and stores which means they are no longer a reliable
way to implement locks. That's a reason why I never pushed a
PTA/alias patch I have to open-code this.
Thus, do we really want to do this?
That's my question to you :) If you don't think this attr_fnspec
extension would be useful for optimization I'll drop this part
of the patch and open-code it separately only for the out-of-bounds
diagnostics. I'd started out that way but the fnspec class made
the code cleaner and if it could be used elsewhere so much
the better. Please let me know.
Well - as said, we're relying on the property of a function call being
a barrier for global/escaped memory for things like pthread_mutex_lock
and at least some of the atomic builtins might be used as locking primitives
and most definitely that would break. For example
int cnt;
int lock;
void foo(int n)
{
for (int i = 0; i < n; ++i)
{
int val = 0;
int ret;
if (__atomic_compare_exchange (&lock, &val, 1, false, __ATOMIC_ACQ))
{
cnt++;
}
}
}
will see PRE applied to the load of 'cnt' with your patch(?), that is, the lock
is not a barrier for protected loads and stores. Of course you have to provide
some incentive to perform an invalid optimization and the trivial one like
initialization before the locked area that can be CSEd is probably invalid
since the init then has data races.
So yes, I think we should be very careful here. The reason why I chickened
out myself doing the obvious improvement for the atomic builtins...
Any opinions from others?
Richard.
Martin
Detect overflow by atomic functions [PR102453].
Resolves:
PR middle-end/102453 - buffer overflow by atomic built-ins not diagnosed
gcc/ChangeLog:
PR middle-end/102453
* gimple-ssa-warn-access.cc (pass_waccess::check_atomic_builtin): New.
(pass_waccess::check_atomic_builtin): Call it.
gcc/testsuite/ChangeLog:
PR middle-end/102453
* gcc.dg/Warray-bounds-90.c: New test.
* gcc.dg/Wstringop-overflow-77.c: New test.
* gcc.dg/Wstringop-overflow-78.c: New test.
* gcc.dg/Wstringop-overflow-79.c: New test.
* gcc.dg/Wstringop-overflow-80.c: New test.
* c-c++-common/gomp/atomic-4.c: Avoid an out-of-bounds access.
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 00c3ea0f505..e5555a4f6ec 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -2109,6 +2109,9 @@ private:
pass_waccess (pass_waccess &) = delete;
void operator= (pass_waccess &) = delete;
+ /* Check a call to an atomic built-in function. */
+ bool check_atomic_builtin (gcall *);
+
/* Check a call to a built-in function. */
bool check_builtin (gcall *);
@@ -2681,6 +2684,87 @@ pass_waccess::check_memop_access (gimple *stmt, tree dest, tree src, tree size)
srcsize, dstsize, data.mode, &data);
}
+/* Check a call STMT to an atomic or sync built-in. */
+
+bool
+pass_waccess::check_atomic_builtin (gcall *stmt)
+{
+ tree callee = gimple_call_fndecl (stmt);
+ if (!callee)
+ return false;
+
+ /* Tyhe size in bytes of the access by the function, and the number
+ of the second argument to check (if any). */
+ unsigned bytes = 0, arg2 = UINT_MAX;
+
+ switch (DECL_FUNCTION_CODE (callee))
+ {
+#define BUILTIN_ACCESS_SIZE_FNSPEC(N) \
+ BUILT_IN_ATOMIC_LOAD_ ## N: \
+ case BUILT_IN_SYNC_FETCH_AND_ADD_ ## N: \
+ case BUILT_IN_SYNC_FETCH_AND_SUB_ ## N: \
+ case BUILT_IN_SYNC_FETCH_AND_OR_ ## N: \
+ case BUILT_IN_SYNC_FETCH_AND_AND_ ## N: \
+ case BUILT_IN_SYNC_FETCH_AND_XOR_ ## N: \
+ case BUILT_IN_SYNC_FETCH_AND_NAND_ ## N: \
+ case BUILT_IN_SYNC_ADD_AND_FETCH_ ## N: \
+ case BUILT_IN_SYNC_SUB_AND_FETCH_ ## N: \
+ case BUILT_IN_SYNC_OR_AND_FETCH_ ## N: \
+ case BUILT_IN_SYNC_AND_AND_FETCH_ ## N: \
+ case BUILT_IN_SYNC_XOR_AND_FETCH_ ## N: \
+ case BUILT_IN_SYNC_NAND_AND_FETCH_ ## N: \
+ case BUILT_IN_SYNC_LOCK_TEST_AND_SET_ ## N: \
+ case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_ ## N: \
+ case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_ ## N: \
+ case BUILT_IN_SYNC_LOCK_RELEASE_ ## N: \
+ case BUILT_IN_ATOMIC_EXCHANGE_ ## N: \
+ case BUILT_IN_ATOMIC_STORE_ ## N: \
+ case BUILT_IN_ATOMIC_ADD_FETCH_ ## N: \
+ case BUILT_IN_ATOMIC_SUB_FETCH_ ## N: \
+ case BUILT_IN_ATOMIC_AND_FETCH_ ## N: \
+ case BUILT_IN_ATOMIC_NAND_FETCH_ ## N: \
+ case BUILT_IN_ATOMIC_XOR_FETCH_ ## N: \
+ case BUILT_IN_ATOMIC_OR_FETCH_ ## N: \
+ case BUILT_IN_ATOMIC_FETCH_ADD_ ## N: \
+ case BUILT_IN_ATOMIC_FETCH_SUB_ ## N: \
+ case BUILT_IN_ATOMIC_FETCH_AND_ ## N: \
+ case BUILT_IN_ATOMIC_FETCH_NAND_ ## N: \
+ case BUILT_IN_ATOMIC_FETCH_OR_ ## N: \
+ case BUILT_IN_ATOMIC_FETCH_XOR_ ## N: \
+ bytes = N; \
+ break; \
+ case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_ ## N: \
+ bytes = N; \
+ arg2 = 1
+
+ case BUILTIN_ACCESS_SIZE_FNSPEC (1);
+ break;
+ case BUILTIN_ACCESS_SIZE_FNSPEC (2);
+ break;
+ case BUILTIN_ACCESS_SIZE_FNSPEC (4);
+ break;
+ case BUILTIN_ACCESS_SIZE_FNSPEC (8);
+ break;
+ case BUILTIN_ACCESS_SIZE_FNSPEC (16);
+ break;
+
+ default:
+ return false;
+ }
+
+ tree size = build_int_cstu (sizetype, bytes);
+ tree dst = gimple_call_arg (stmt, 0);
+ check_memop_access (stmt, dst, NULL_TREE, size);
+
+ if (arg2 != UINT_MAX)
+ {
+ tree dst = gimple_call_arg (stmt, arg2);
+ check_memop_access (stmt, dst, NULL_TREE, size);
+ }
+
+ return true;
+}
+
/* Check call STMT to a built-in function for invalid accesses. Return
true if a call has been handled. */
@@ -2795,10 +2879,11 @@ pass_waccess::check_builtin (gcall *stmt)
}
default:
- return false;
+ if (check_atomic_builtin (stmt))
+ return true;
+ break;
}
-
- return true;
+ return false;
}
/* Returns the type of the argument ARGNO to function with type FNTYPE
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-4.c b/gcc/testsuite/c-c++-common/gomp/atomic-4.c
index 7f27370d535..5dd18d1d5fa 100644
--- a/gcc/testsuite/c-c++-common/gomp/atomic-4.c
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-4.c
@@ -8,7 +8,7 @@ int *bar(void);
void f1(void)
{
#pragma omp atomic
- a[4] += 1;
+ a[3] += 1;
#pragma omp atomic
*p += 1;
#pragma omp atomic
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-90.c b/gcc/testsuite/gcc.dg/Warray-bounds-90.c
new file mode 100644
index 00000000000..2e72a3daa1c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-90.c
@@ -0,0 +1,147 @@
+/* PR middle-end/102453 - buffer overflow by atomic built-ins not diagnosed
+ Verify that out-of-bounds accesses by atomic functions are diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+#define load __atomic_load
+#define store __atomic_store
+#define add_fetch __atomic_add_fetch
+#define sub_fetch __atomic_sub_fetch
+#define and_fetch __atomic_and_fetch
+#define or_fetch __atomic_or_fetch
+#define xor_fetch __atomic_xor_fetch
+#define nand_fetch __atomic_nand_fetch
+
+typedef __SIZE_TYPE__ size_t;
+
+void sink (void*, ...);
+#define sink(...) sink (0, __VA_ARGS__)
+
+extern _Bool eb;
+extern char ec;
+extern short int esi;
+extern int ei;
+extern long int eli;
+extern long long int elli;
+
+extern const _Bool ecb;
+extern const char ecc;
+extern const short int ecsi;
+extern const int eci;
+extern const long int ecli;
+extern const long long int eclli;
+
+extern _Atomic _Bool eab;
+extern _Atomic char eac;
+extern _Atomic short int easi;
+extern _Atomic int eai;
+extern _Atomic long int eali;
+extern _Atomic long long int ealli;
+
+extern _Atomic const _Bool eacb;
+extern _Atomic const char eacc;
+extern _Atomic const short int eacsi;
+extern _Atomic const int eaci;
+extern _Atomic const long int eacli;
+extern _Atomic const long long int eaclli;
+
+
+void nowarn_atomic_load (void)
+{
+ load (&eacb, &eb, 0);
+ load (&eacc, &ec, 0);
+ load (&eacsi, &esi, 0);
+ load (&eaci, &ei, 0);
+ load (&eacli, &eli, 0);
+ load (&eaclli, &elli, 0);
+}
+
+
+void warn_atomic_load_note (void)
+{
+ int i; // { dg-message "'i'" }
+
+ int *pi = (int*)((char*)&i + 1);
+ load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" }
+ sink (&i);
+
+ pi = (int*)((char*)&i + 2);
+ load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" }
+ sink (&i);
+
+ pi = &i + 1;
+ load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" }
+ sink (&i);
+}
+
+
+void warn_atomic_load (void)
+{
+ bool *pb = &eb + 1;
+ load (&eacb, pb, 0); // { dg-warning "-Warray-bounds" }
+
+ char *pc = &ec + 1;
+ load (&eacc, pc, 0); // { dg-warning "-Warray-bounds" }
+
+ short *psi = (short*)((char*)&esi + 1);
+ load (&eacsi, psi, 0); // { dg-warning "-Warray-bounds" }
+ psi = (short*)((char*)&esi + 2);
+ load (&eacsi, psi, 0); // { dg-warning "-Warray-bounds" }
+
+ int *pi = (int*)((char*)&ei + 1);
+ load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" }
+ pi = (int*)((char*)&ei + 2);
+ load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" }
+ pi = (int*)((char*)&ei + sizeof ei);
+ load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" }
+
+ long *pli = (long*)((char*)&eli + 1);
+ load (&eacli, pli, 0); // { dg-warning "-Warray-bounds" }
+ pli = (long*)((char*)&eli + 1);
+ load (&eacli, pli, 0); // { dg-warning "-Warray-bounds" }
+ pli = &eli + 1;
+ load (&eacli, pli, 0); // { dg-warning "-Warray-bounds" }
+
+ long long *plli = (long long*)((char*)&elli + 1);
+ load (&eaclli, plli, 0); // { dg-warning "-Warray-bounds" }
+ plli = (long long*)((char*)&elli + 1);
+ load (&eacli, plli, 0); // { dg-warning "-Warray-bounds" }
+ plli = &elli + 1;
+ load (&eaclli, plli, 0); // { dg-warning "-Warray-bounds" }
+}
+
+
+void warn_atomic_store (void)
+{
+ const bool *pb = &eb + 1;
+ store (&eab, pb, 0); // { dg-warning "-Warray-bounds" }
+
+ const char *pc = &ec + 1;
+ store (&eac, pc, 0); // { dg-warning "-Warray-bounds" }
+
+ const short *psi = (const short*)((const char*)&ecsi + 1);
+ store (&easi, psi, 0); // { dg-warning "-Warray-bounds" }
+ psi = (const short*)((const char*)&esi + 2);
+ store (&easi, psi, 0); // { dg-warning "-Warray-bounds" }
+
+ const int *pi = (const int*)((const char*)&eci + 1);
+ store (&eai, pi, 0); // { dg-warning "-Warray-bounds" }
+ pi = (const int*)((const char*)&ei + 2);
+ store (&eai, pi, 0); // { dg-warning "-Warray-bounds" }
+ pi = (const int*)((const char*)&ei + sizeof ei);
+ store (&eai, pi, 0); // { dg-warning "-Warray-bounds" }
+
+ const long *pli = (const long*)((const char*)&eli + 1);
+ store (&eali, pli, 0); // { dg-warning "-Warray-bounds" }
+ pli = (const long*)((const char*)&eli + sizeof (eli));
+ store (&eali, pli, 0); // { dg-warning "-Warray-bounds" }
+
+ const long long *plli = (const long long*)((const char*)&elli + 1);
+ store (&ealli, plli, 0); // { dg-warning "-Warray-bounds" }
+ plli = (const long long*)((const char*)&elli + sizeof elli);
+ store (&ealli, plli, 0); // { dg-warning "-Warray-bounds" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-77.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-77.c
new file mode 100644
index 00000000000..732f56849ae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-77.c
@@ -0,0 +1,516 @@
+/* PR middle-end/102453 - buffer overflow by atomic built-ins not diagnosed
+ Verify that out-of-bounds accesses by atomic functions are diagnosed with
+ optimization disabled.
+ { dg-do compile }
+ { dg-options "-O0 -Wall -ftrack-macro-expansion=0" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+#define add_fetch(p, q) __atomic_add_fetch (p, q, 0)
+#define sub_fetch(p, q) __atomic_sub_fetch (p, q, 0)
+#define and_fetch(p, q) __atomic_and_fetch (p, q, 0)
+#define or_fetch(p, q) __atomic_or_fetch (p, q, 0)
+#define xor_fetch(p, q) __atomic_xor_fetch (p, q, 0)
+#define nand_fetch(p, q) __atomic_nand_fetch (p, q, 0)
+#define exchange(p, q, r) __atomic_exchange (p, q, r, 0)
+#define exchange_n(p, n) __atomic_exchange_n (p, n, 0)
+#define cmpxchg(p, q, r) __atomic_compare_exchange (p, q, r, 0, 0, 0)
+
+typedef __SIZE_TYPE__ size_t;
+
+void sink (void*, ...);
+#define sink(...) sink (0, __VA_ARGS__)
+
+extern _Bool eb;
+extern char ec;
+extern short int esi;
+extern int ei;
+extern long int eli;
+extern long long int elli;
+
+extern const _Bool ecb;
+extern const char ecc;
+extern const short int ecsi;
+extern const int eci;
+extern const long int ecli;
+extern const long long int eclli;
+
+extern _Atomic _Bool eab;
+extern _Atomic char eac;
+extern _Atomic short int easi;
+extern _Atomic int eai;
+extern _Atomic long int eali;
+extern _Atomic long long int ealli;
+
+extern _Atomic const _Bool eacb;
+extern _Atomic const char eacc;
+extern _Atomic const short int eacsi;
+extern _Atomic const int eaci;
+extern _Atomic const long int eacli;
+extern _Atomic const long long int eaclli;
+
+
+void nowarn_atomic_add_fetch (void)
+{
+ add_fetch (&eac, ecc);
+ add_fetch (&easi, esi);
+ add_fetch (&eai, ei);
+ add_fetch (&eali, eli);
+ add_fetch (&ealli, elli);
+}
+
+
+void warn_atomic_add_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ add_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ add_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ add_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ add_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ add_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ add_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+void nowarn_atomic_sub_fetch (void)
+{
+ _Atomic char *pc = &eac;
+ sub_fetch (pc, ecc);
+
+ _Atomic short *psi = &easi;
+ sub_fetch (psi, esi);
+
+ _Atomic int *pi = &eai;
+ sub_fetch (pi, ei);
+
+ _Atomic long *pli = &eali;
+ sub_fetch (pli, eli);
+
+ _Atomic long long *plli = &ealli;
+ sub_fetch (plli, elli);
+}
+
+
+void warn_atomic_sub_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ sub_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ sub_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ sub_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ sub_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ sub_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ sub_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+void nowarn_atomic_and_fetch (void)
+{
+ _Atomic char *pc = &eac;
+ and_fetch (pc, ecc);
+
+ _Atomic short *psi = &easi;
+ and_fetch (psi, esi);
+
+ _Atomic int *pi = &eai;
+ and_fetch (pi, ei);
+
+ _Atomic long *pli = &eali;
+ and_fetch (pli, eli);
+
+ _Atomic long long *plli = &ealli;
+ and_fetch (plli, elli);
+}
+
+
+void warn_atomic_and_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ and_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ and_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ and_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ and_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ and_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ and_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+void nowarn_atomic_or_fetch (void)
+{
+ _Atomic char *pc = &eac;
+ or_fetch (pc, ecc);
+
+ _Atomic short *psi = &easi;
+ or_fetch (psi, esi);
+
+ _Atomic int *pi = &eai;
+ or_fetch (pi, ei);
+
+ _Atomic long *pli = &eali;
+ or_fetch (pli, eli);
+
+ _Atomic long long *plli = &ealli;
+ or_fetch (plli, elli);
+}
+
+
+void warn_atomic_or_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ or_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ or_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ or_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ or_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ or_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ or_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+void nowarn_atomic_xor_fetch (void)
+{
+ _Atomic char *pc = &eac;
+ xor_fetch (pc, ecc);
+
+ _Atomic short *psi = &easi;
+ xor_fetch (psi, esi);
+
+ _Atomic int *pi = &eai;
+ xor_fetch (pi, ei);
+
+ _Atomic long *pli = &eali;
+ xor_fetch (pli, eli);
+
+ _Atomic long long *plli = &ealli;
+ xor_fetch (plli, elli);
+}
+
+
+void warn_atomic_xor_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ xor_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ xor_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 1);
+ xor_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ xor_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&eali + 1);
+ xor_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ xor_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+void nowarn_atomic_nand_fetch (void)
+{
+ _Atomic char *pc = &eac;
+ nand_fetch (pc, ecc);
+
+ _Atomic short *psi = &easi;
+ nand_fetch (psi, esi);
+
+ _Atomic int *pi = &eai;
+ nand_fetch (pi, ei);
+
+ _Atomic long *pli = &eali;
+ nand_fetch (pli, eli);
+
+ _Atomic long long *plli = &ealli;
+ nand_fetch (plli, elli);
+}
+
+
+void warn_atomic_nand_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ nand_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ nand_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 1);
+ nand_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ nand_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&eai + 1);
+ nand_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ nand_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+void nowarn_atomic_exchange (void)
+{
+ char rc;
+ _Atomic char *pc = &eac;
+ exchange (pc, &ecc, &rc);
+
+ short rsi;
+ _Atomic short *psi = &easi;
+ exchange (psi, &esi, &rsi);
+
+ int ri;
+ _Atomic int *pi = &eai;
+ exchange (pi, &ei, &ri);
+
+ long rli;
+ _Atomic long *pli = &eali;
+ exchange (pli, &eli, &rli);
+
+ long long rlli;
+ _Atomic long long *plli = &ealli;
+ exchange (plli, &elli, &rlli);
+
+ sink (&rc, &rsi, &ri, &rli, &rlli);
+}
+
+void warn_atomic_exchange (void)
+{
+ char rc;
+ _Atomic char *pc = &eac + 1;
+ exchange (pc, &ecc, &rc); // { dg-warning "-Wstringop-overflow" }
+
+ short rsi[2];
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ exchange (psi, &ecsi, rsi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ exchange (psi, &ecsi, rsi + 1); // { dg-warning "-Wstringop-overflow" }
+
+ int ri[3];
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ exchange (pi, &eci, ri); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ exchange (pi, &eci, ri + 1); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ exchange (pi, &eci, ri + 2); // { dg-warning "-Wstringop-overflow" }
+
+ long rli[3];
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ exchange (pli, &ecli, rli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ exchange (pli, &ecli, rli + 1); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ exchange (pli, &ecli, rli + 2); // { dg-warning "-Wstringop-overflow" }
+
+ long long rlli[3];
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ exchange (plli, &eclli, rlli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ exchange (plli, &eclli, rlli + 1); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ exchange (plli, &eclli, rlli + 2); // { dg-warning "-Wstringop-overflow" }
+
+ sink (&rc, rsi, ri, rli, rlli);
+}
+
+
+void nowarn_atomic_exchange_n (_Atomic unsigned char *pauc,
+ _Atomic unsigned short *pausi,
+ _Atomic unsigned int *paui,
+ _Atomic unsigned long *pauli,
+ _Atomic unsigned long long *paulli)
+{
+ char rc = exchange_n (&eac, ecc);
+ short rsi = exchange_n (&easi, esi);
+ int ri = exchange_n (&eai, ei);
+ long rli = exchange_n (&eali, eli);
+ long long rlli = exchange_n (&ealli, elli);
+
+ sink (rc, rsi, ri, rli, rlli);
+
+ char ruc = exchange_n (pauc, ecc);
+ short rusi = exchange_n (pausi, esi);
+ int rui = exchange_n (paui, ei);
+ long ruli = exchange_n (pauli, eli);
+ long long rulli = exchange_n (paulli, elli);
+
+ sink (ruc, rusi, rui, ruli, rulli);
+}
+
+
+void warn_atomic_exchange_n (void)
+{
+ _Atomic char *pc = &eac + 1;
+ char rc = exchange_n (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ short rsi[2];
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ rsi[0] = exchange_n (psi, ecsi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ rsi[1] = exchange_n (psi, ecsi); // { dg-warning "-Wstringop-overflow" }
+
+ int ri[3];
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ ri[0] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ ri[1] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ ri[2] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" }
+
+ long rli[3];
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ rli[0] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ rli[1] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ rli[2] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" }
+
+ long long rlli[3];
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ rlli[0] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ rlli[1] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ rlli[2] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" }
+
+ sink (&rc, rsi, ri, rli, rlli);
+}
+
+
+void warn_atomic_compare_exchange (void)
+{
+ _Atomic char *pc = &eac + 1;
+ cmpxchg (pc, &ec, &ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ cmpxchg (psi, &esi, &ecsi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ cmpxchg (psi, &esi, &ecsi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-78.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-78.c
new file mode 100644
index 00000000000..a25a418ed76
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-78.c
@@ -0,0 +1,518 @@
+/* PR middle-end/102453 - buffer overflow by atomic built-ins not diagnosed
+ Verify that out-of-bounds accesses by atomic functions are diagnosed with
+ optimization enabled.
+ { dg-do compile }
+ { dg-options "-O3 -Wall -ftrack-macro-expansion=0" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+#define NOIPA __attribute__ ((noipa))
+
+#define add_fetch(p, q) __atomic_add_fetch (p, q, 0)
+#define sub_fetch(p, q) __atomic_sub_fetch (p, q, 0)
+#define and_fetch(p, q) __atomic_and_fetch (p, q, 0)
+#define or_fetch(p, q) __atomic_or_fetch (p, q, 0)
+#define xor_fetch(p, q) __atomic_xor_fetch (p, q, 0)
+#define nand_fetch(p, q) __atomic_nand_fetch (p, q, 0)
+#define exchange(p, q, r) __atomic_exchange (p, q, r, 0)
+#define exchange_n(p, n) __atomic_exchange_n (p, n, 0)
+#define cmpxchg(p, q, r) __atomic_compare_exchange (p, q, r, __COUNTER__, 0, 0)
+
+typedef __SIZE_TYPE__ size_t;
+
+void sink (void*, ...);
+#define sink(...) sink (0, __VA_ARGS__)
+
+extern _Bool eb;
+extern char ec;
+extern short int esi;
+extern int ei;
+extern long int eli;
+extern long long int elli;
+
+extern const _Bool ecb;
+extern const char ecc;
+extern const short int ecsi;
+extern const int eci;
+extern const long int ecli;
+extern const long long int eclli;
+
+extern _Atomic _Bool eab;
+extern _Atomic char eac;
+extern _Atomic short int easi;
+extern _Atomic int eai;
+extern _Atomic long int eali;
+extern _Atomic long long int ealli;
+
+extern _Atomic const _Bool eacb;
+extern _Atomic const char eacc;
+extern _Atomic const short int eacsi;
+extern _Atomic const int eaci;
+extern _Atomic const long int eacli;
+extern _Atomic const long long int eaclli;
+
+
+NOIPA void nowarn_atomic_add_fetch (void)
+{
+ add_fetch (&eac, ecc);
+ add_fetch (&easi, esi);
+ add_fetch (&eai, ei);
+ add_fetch (&eali, eli);
+ add_fetch (&ealli, elli);
+}
+
+
+NOIPA void warn_atomic_add_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ add_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ add_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ add_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ add_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ add_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ add_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+NOIPA void nowarn_atomic_sub_fetch (void)
+{
+ _Atomic char *pc = &eac;
+ sub_fetch (pc, ecc);
+
+ _Atomic short *psi = &easi;
+ sub_fetch (psi, esi);
+
+ _Atomic int *pi = &eai;
+ sub_fetch (pi, ei);
+
+ _Atomic long *pli = &eali;
+ sub_fetch (pli, eli);
+
+ _Atomic long long *plli = &ealli;
+ sub_fetch (plli, elli);
+}
+
+
+NOIPA void warn_atomic_sub_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ sub_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ sub_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ sub_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ sub_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ sub_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ sub_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+NOIPA void nowarn_atomic_and_fetch (void)
+{
+ _Atomic char *pc = &eac;
+ and_fetch (pc, ecc);
+
+ _Atomic short *psi = &easi;
+ and_fetch (psi, esi);
+
+ _Atomic int *pi = &eai;
+ and_fetch (pi, ei);
+
+ _Atomic long *pli = &eali;
+ and_fetch (pli, eli);
+
+ _Atomic long long *plli = &ealli;
+ and_fetch (plli, elli);
+}
+
+
+NOIPA void warn_atomic_and_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ and_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ and_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ and_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ and_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ and_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ and_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+NOIPA void nowarn_atomic_or_fetch (void)
+{
+ _Atomic char *pc = &eac;
+ or_fetch (pc, ecc);
+
+ _Atomic short *psi = &easi;
+ or_fetch (psi, esi);
+
+ _Atomic int *pi = &eai;
+ or_fetch (pi, ei);
+
+ _Atomic long *pli = &eali;
+ or_fetch (pli, eli);
+
+ _Atomic long long *plli = &ealli;
+ or_fetch (plli, elli);
+}
+
+
+NOIPA void warn_atomic_or_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ or_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ or_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ or_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ or_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ or_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ or_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+NOIPA void nowarn_atomic_xor_fetch (void)
+{
+ _Atomic char *pc = &eac;
+ xor_fetch (pc, ecc);
+
+ _Atomic short *psi = &easi;
+ xor_fetch (psi, esi);
+
+ _Atomic int *pi = &eai;
+ xor_fetch (pi, ei);
+
+ _Atomic long *pli = &eali;
+ xor_fetch (pli, eli);
+
+ _Atomic long long *plli = &ealli;
+ xor_fetch (plli, elli);
+}
+
+
+NOIPA void warn_atomic_xor_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ xor_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ xor_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 1);
+ xor_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ xor_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&eali + 1);
+ xor_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ xor_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+NOIPA void nowarn_atomic_nand_fetch (void)
+{
+ _Atomic char *pc = &eac;
+ nand_fetch (pc, ecc);
+
+ _Atomic short *psi = &easi;
+ nand_fetch (psi, esi);
+
+ _Atomic int *pi = &eai;
+ nand_fetch (pi, ei);
+
+ _Atomic long *pli = &eali;
+ nand_fetch (pli, eli);
+
+ _Atomic long long *plli = &ealli;
+ nand_fetch (plli, elli);
+}
+
+
+NOIPA void warn_atomic_nand_fetch (void)
+{
+ _Atomic char *pc = &eac + 1;
+ nand_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ nand_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 1);
+ nand_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ nand_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&eai + 1);
+ nand_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ nand_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+NOIPA void nowarn_atomic_exchange (void)
+{
+ char rc;
+ _Atomic char *pc = &eac;
+ exchange (pc, &ecc, &rc);
+
+ short rsi;
+ _Atomic short *psi = &easi;
+ exchange (psi, &esi, &rsi);
+
+ int ri;
+ _Atomic int *pi = &eai;
+ exchange (pi, &ei, &ri);
+
+ long rli;
+ _Atomic long *pli = &eali;
+ exchange (pli, &eli, &rli);
+
+ long long rlli;
+ _Atomic long long *plli = &ealli;
+ exchange (plli, &elli, &rlli);
+
+ sink (&rc, &rsi, &ri, &rli, &rlli);
+}
+
+NOIPA void warn_atomic_exchange (void)
+{
+ char rc;
+ _Atomic char *pc = &eac + 1;
+ exchange (pc, &ecc, &rc); // { dg-warning "-Wstringop-overflow" }
+
+ short rsi[2];
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ exchange (psi, &ecsi, rsi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ exchange (psi, &ecsi, rsi + 1); // { dg-warning "-Wstringop-overflow" }
+
+ int ri[3];
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ exchange (pi, &eci, ri); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ exchange (pi, &eci, ri + 1); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ exchange (pi, &eci, ri + 2); // { dg-warning "-Wstringop-overflow" }
+
+ long rli[3];
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ exchange (pli, &ecli, rli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ exchange (pli, &ecli, rli + 1); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ exchange (pli, &ecli, rli + 2); // { dg-warning "-Wstringop-overflow" }
+
+ long long rlli[3];
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ exchange (plli, &eclli, rlli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ exchange (plli, &eclli, rlli + 1); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ exchange (plli, &eclli, rlli + 2); // { dg-warning "-Wstringop-overflow" }
+
+ sink (&rc, rsi, ri, rli, rlli);
+}
+
+
+NOIPA void nowarn_atomic_exchange_n (_Atomic unsigned char *pauc,
+ _Atomic unsigned short *pausi,
+ _Atomic unsigned int *paui,
+ _Atomic unsigned long *pauli,
+ _Atomic unsigned long long *paulli)
+{
+ char rc = exchange_n (&eac, ecc);
+ short rsi = exchange_n (&easi, esi);
+ int ri = exchange_n (&eai, ei);
+ long rli = exchange_n (&eali, eli);
+ long long rlli = exchange_n (&ealli, elli);
+
+ sink (rc, rsi, ri, rli, rlli);
+
+ char ruc = exchange_n (pauc, ecc);
+ short rusi = exchange_n (pausi, esi);
+ int rui = exchange_n (paui, ei);
+ long ruli = exchange_n (pauli, eli);
+ long long rulli = exchange_n (paulli, elli);
+
+ sink (ruc, rusi, rui, ruli, rulli);
+}
+
+
+NOIPA void warn_atomic_exchange_n (void)
+{
+ _Atomic char *pc = &eac + 1;
+ char rc = exchange_n (pc, ecc); // { dg-warning "-Wstringop-overflow" }
+
+ short rsi[2];
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ rsi[0] = exchange_n (psi, ecsi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ rsi[1] = exchange_n (psi, ecsi); // { dg-warning "-Wstringop-overflow" }
+
+ int ri[3];
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ ri[0] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ ri[1] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ ri[2] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" }
+
+ long rli[3];
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ rli[0] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ rli[1] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ rli[2] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" }
+
+ long long rlli[3];
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ rlli[0] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ rlli[1] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ rlli[2] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" }
+
+ sink (&rc, rsi, ri, rli, rlli);
+}
+
+
+NOIPA void warn_atomic_compare_exchange (void)
+{
+ _Atomic char *pc = &eac + 1;
+ cmpxchg (pc, &ec, &ecc); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic short *psi = (_Atomic short*)((char*)&easi + 1);
+ cmpxchg (psi, &esi, &ecsi); // { dg-warning "-Wstringop-overflow" }
+ psi = (_Atomic short*)((char*)&easi + 2);
+ cmpxchg (psi, &esi, &ecsi); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic int *pi = (_Atomic int*)((char*)&eai + 1);
+ cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + 2);
+ cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" }
+ pi = (_Atomic int*)((char*)&eai + sizeof eai);
+ cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long *pli = (_Atomic long*)((char*)&eali + 1);
+ cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" }
+ pli = (_Atomic long*)((char*)&eali + 1);
+ cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" }
+ pli = &eali + 1;
+ cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" }
+
+ _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1);
+ cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" }
+ plli = (_Atomic long long*)((char*)&ealli + 1);
+ cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" }
+ plli = &ealli + 1;
+ cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-79.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-79.c
new file mode 100644
index 00000000000..15eb26fbdb7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-79.c
@@ -0,0 +1,70 @@
+/* Verify that a separate note is issued for each offset into the same
+ object after a -Wstringop-overflow. Since all arguments are known
+ the test doesn't need optimization. Wstringop-overflow-79.c verifies
+ they're also issued at -O2.
+ { dg-do compile }
+ { dg-options "-O0 -Wno-array-bounds" } */
+
+extern char a[8]; // dg-message at offset \\\[3, 6] into destination object 'a'" "note 1" }
+ // dg-message at offset \\\[5, 8] into destination object 'a'" "note 2" { target *-*-* } .-1 }
+
+void test_2_notes (int i)
+{
+ char *p = i ? a + 3 : a + 5;
+ __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+extern char b[8]; // dg-message at offset \\\[3, 6] into destination object 'b'" "note 1" }
+ // dg-message at offset \\\[4, 7] into destination object 'b'" "note 2" { target *-*-* } .-1 }
+ // dg-message at offset \\\[5, 8] into destination object 'b'" "note 3" { target *-*-* } .-2 }
+
+void test_3_notes (int i)
+{
+ char *p = i < 0 ? b + 3 : 0 < i ? b + 5 : b + 4;
+ __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+extern char c[8]; // dg-message at offset \\\[3, 6] into destination object 'c'" "note 1" }
+ // dg-message at offset \\\[4, 7] into destination object 'c'" "note 2" { target *-*-* } .-1 }
+ // dg-message at offset \\\[5, 8] into destination object 'c'" "note 3" { target *-*-* } .-2 }
+ // dg-message at offset \\\[6, 8] into destination object 'c'" "note 3" { target *-*-* } .-2 }
+
+void test_4_notes (int i)
+{
+ char *p;
+ if (i < -1)
+ p = c + 3;
+ else if (i < 0)
+ p = c + 4;
+ else if (0 < i)
+ p = c + 6;
+ else
+ p = c + 5;
+
+ __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+extern char d[8]; // dg-message at offset \\\[3, 6] into destination object 'd'" "note 1" }
+ // dg-message at offset \\\[4, 7] into destination object 'd'" "note 2" { target *-*-* } .-1 }
+ // dg-message at offset \\\[5, 8] into destination object 'd'" "note 3" { target *-*-* } .-2 }
+ // dg-message at offset \\\[6, 8] into destination object 'd'" "note 3" { target *-*-* } .-3 }
+ // dg-message at offset \\\[7, 8] into destination object 'd'" "note 3" { target *-*-* } .-4 }
+
+void test_5_notes (int i)
+{
+ char *p;
+ switch (i)
+ {
+ case -9: p = d + 3; break;
+ case -5: p = d + 4; break;
+ case 0: p = d + 5; break;
+ case 3: p = d + 6; break;
+ case 4: p = d + 7; break;
+ default: return;
+ }
+
+ __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-80.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-80.c
new file mode 100644
index 00000000000..1628c2f0159
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-80.c
@@ -0,0 +1,70 @@
+/* Verify that a separate note is issued for each offset into the same
+ object after a -Wstringop-overflow. Even though the warnings don't
+ need optimization the test enables it to verify they're still issued
+ with it. Wstringop-overflow-78.c verifies they're issued at -O0.
+ { dg-do compile }
+ { dg-options "-O2 -Wno-array-bounds" } */
+
+extern char a[8]; // dg-message at offset \\\[3, 6] into destination object 'a'" "note 1" }
+ // dg-message at offset \\\[5, 8] into destination object 'a'" "note 2" { target *-*-* } .-1 }
+
+void test_2_notes (int i)
+{
+ char *p = i ? a + 3 : a + 5;
+ __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+extern char b[8]; // dg-message at offset \\\[3, 6] into destination object 'b'" "note 1" }
+ // dg-message at offset \\\[4, 7] into destination object 'b'" "note 2" { target *-*-* } .-1 }
+ // dg-message at offset \\\[5, 8] into destination object 'b'" "note 3" { target *-*-* } .-2 }
+
+void test_3_notes (int i)
+{
+ char *p = i < 0 ? b + 3 : 0 < i ? b + 5 : b + 4;
+ __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+extern char c[8]; // dg-message at offset \\\[3, 6] into destination object 'c'" "note 1" }
+ // dg-message at offset \\\[4, 7] into destination object 'c'" "note 2" { target *-*-* } .-1 }
+ // dg-message at offset \\\[5, 8] into destination object 'c'" "note 3" { target *-*-* } .-2 }
+ // dg-message at offset \\\[6, 8] into destination object 'c'" "note 3" { target *-*-* } .-2 }
+
+void test_4_notes (int i)
+{
+ char *p;
+ if (i < -1)
+ p = c + 3;
+ else if (i < 0)
+ p = c + 4;
+ else if (0 < i)
+ p = c + 6;
+ else
+ p = c + 5;
+
+ __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" }
+}
+
+
+extern char d[8]; // dg-message at offset \\\[3, 6] into destination object 'd'" "note 1" }
+ // dg-message at offset \\\[4, 7] into destination object 'd'" "note 2" { target *-*-* } .-1 }
+ // dg-message at offset \\\[5, 8] into destination object 'd'" "note 3" { target *-*-* } .-2 }
+ // dg-message at offset \\\[6, 8] into destination object 'd'" "note 3" { target *-*-* } .-3 }
+ // dg-message at offset \\\[7, 8] into destination object 'd'" "note 3" { target *-*-* } .-4 }
+
+void test_5_notes (int i)
+{
+ char *p;
+ switch (i)
+ {
+ case -9: p = d + 3; break;
+ case -5: p = d + 4; break;
+ case 0: p = d + 5; break;
+ case 3: p = d + 6; break;
+ case 4: p = d + 7; break;
+ default: return;
+ }
+
+ __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" }
+}