public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-4725] Detect overflow by atomic functions [PR102453].
@ 2021-10-26 22:54 Martin Sebor
  0 siblings, 0 replies; only message in thread
From: Martin Sebor @ 2021-10-26 22:54 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:88b504b7a8c5affb0ffa97990d22af2b199e36ed

commit r12-4725-g88b504b7a8c5affb0ffa97990d22af2b199e36ed
Author: Martin Sebor <msebor@redhat.com>
Date:   Tue Oct 26 14:34:16 2021 -0600

    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:
---
 gcc/gimple-ssa-warn-access.cc                |  91 ++++-
 gcc/testsuite/c-c++-common/gomp/atomic-4.c   |   2 +-
 gcc/testsuite/gcc.dg/Warray-bounds-90.c      | 147 ++++++++
 gcc/testsuite/gcc.dg/Wstringop-overflow-77.c | 516 ++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/Wstringop-overflow-78.c | 518 +++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/Wstringop-overflow-79.c |  70 ++++
 gcc/testsuite/gcc.dg/Wstringop-overflow-80.c |  70 ++++
 7 files changed, 1410 insertions(+), 4 deletions(-)

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 00c3ea0f505..88a2e72645b 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;
+
+  /* The 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" }
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-10-26 22:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-26 22:54 [gcc r12-4725] Detect overflow by atomic functions [PR102453] Martin Sebor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).