From patchwork Mon Oct 11 21:25:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 46114 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 25F09385803B for ; Mon, 11 Oct 2021 21:26:02 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 25F09385803B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1633987562; bh=5S7eiL+DTavS8tmii5kpE+iQo9Gc4xg4Z6YYQk4qtxc=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=JiBxNakIQXNhlMGlUiQJ4lmQfQBDarygKcWPTeyIyhQT1mXXqyxRk2g2obBrYIBWq IC9ROdbhz6EufCEyhykMB36kyFOJVu3IAfMamCKjT7zNEtHTV5E0+FL02qHLE+m7Dp qSlESj9OG8z7IHTNMcYA6Pg2babyFjnzWwClga7o= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-ot1-x336.google.com (mail-ot1-x336.google.com [IPv6:2607:f8b0:4864:20::336]) by sourceware.org (Postfix) with ESMTPS id CDFC53858C3A for ; Mon, 11 Oct 2021 21:25:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org CDFC53858C3A Received: by mail-ot1-x336.google.com with SMTP id u20-20020a9d7214000000b0054e170300adso23256081otj.13 for ; Mon, 11 Oct 2021 14:25:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-language; bh=5S7eiL+DTavS8tmii5kpE+iQo9Gc4xg4Z6YYQk4qtxc=; b=JdOBacqLxJvJDdLcd90yPncN0OAUDOmrDc3gVAmVoTJ0bMCCE+Eay4RGpr0ExESabO HwWaL2tY85bIt8JkBtxUpFrZJr1Wwovn2SbHINQj8jsZtOUp/pw3vQCJBsOiDm9Gd3o/ Epi6kSoSS8gLrYubCzWIrTT0eu6pSFlL6EZ59FGS/ak82yOeGnbNTfXSsMOfkUNLM5G8 PGN1rdeCOG9LaPaw3apBN6++uy7r0HSRvVs13UvCnPShOyv795wPvSVAmj+esfio/Z1U JP269oWXoD7FxqmZKPNcxNScbjdLN+6IgAZJhsQmGB8z1sOBp7UCPEgcwvgT1ytzbm42 t/Hg== X-Gm-Message-State: AOAM5315QQeHhQFL4orzo45i+Wgtw8CsYGjjoTC9jpy13537SE4nYv+i 1T9MFpZ2x6kAqNCwPbjDKBw= X-Google-Smtp-Source: ABdhPJzTVTfBMeJep+MHPTKgIDMAFPNtHGsi+lFEMtFZCTHFgcq/krGAq/od6YF7+LxIvjPhsbrjxQ== X-Received: by 2002:a05:6830:24b6:: with SMTP id v22mr1472128ots.57.1633987516226; Mon, 11 Oct 2021 14:25:16 -0700 (PDT) Received: from [192.168.0.41] (184-96-250-116.hlrn.qwest.net. [184.96.250.116]) by smtp.gmail.com with ESMTPSA id k9sm1964235otr.66.2021.10.11.14.25.15 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 11 Oct 2021 14:25:15 -0700 (PDT) To: gcc-patches , Richard Biener Subject: [PATCH] detect out-of-bounds stores by atomic functions [PR102453] Message-ID: <72c637b5-f6cc-22d6-af62-65166f5ab069@gmail.com> Date: Mon, 11 Oct 2021 15:25:14 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Martin Sebor via Gcc-patches From: Martin Sebor Reply-To: Martin Sebor Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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. 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 * attr-fnspec.h (attr_fnspec): Make members modifiable or static. (attr_fnspec::arg_access_size_constant_p): New function. (attr_fnspec::atomic_p): New function. * builtins.c (atomic_builtin_fnspec): New function. * gimple-ssa-warn-access.cc (pass_waccess::check_builtin): Handle atomic built-ins. * tree-ssa-alias.c (attr_fnspec::verify): Handle new characters. 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/attr-fnspec.h b/gcc/attr-fnspec.h index 1154c30e7b0..9da29902bcd 100644 --- a/gcc/attr-fnspec.h +++ b/gcc/attr-fnspec.h @@ -22,8 +22,11 @@ describing side effects of a function as follows: character 0 specifies properties of return values as follows: - '1'...'4' specifies number of argument function returns (as in memset) + '1'...'4' specifies the 1-based argument number the function returns + (e.g., '1' for memset) 'm' specifies that returned value is noalias (as in malloc) + 'A' specifies that the function atomically accesses a constant + 1 << N bytes where N is indicated by character 3+2i '.' specifies that nothing is known. character 1 specifies additional function properties ' ' specifies that nothing is known @@ -41,9 +44,9 @@ written and does not escape 'w' or 'W' specifies that the memory pointed to by the parameter does not escape - '1'....'9' specifies that the memory pointed to by the parameter is - copied to memory pointed to by different parameter - (as in memcpy). + '1'....'9' specifies the 1-based parameter number into which the memory + pointed to by the argument is copied (e.g., '1' for memcpy + and '2' for bcopy). '.' specifies that nothing is known. The uppercase letter in addition specifies that the memory pointed to by the parameter is not dereferenced. For 'r' only read applies @@ -54,8 +57,9 @@ ' ' nothing is known 't' the size of value written/read corresponds to the size of of the pointed-to type of the argument type - '1'...'9' specifies the size of value written/read is given by the - specified argument + '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 */ #ifndef ATTR_FNSPEC_H @@ -67,14 +71,14 @@ private: /* fn spec attribute string. */ const char *str; /* length of the fn spec string. */ - const unsigned len; + unsigned len; /* Number of characters specifying return value. */ - const unsigned int return_desc_size = 2; + static constexpr unsigned int return_desc_size = 2; /* Number of characters specifying size. */ - const unsigned int arg_desc_size = 2; + static constexpr unsigned int arg_desc_size = 2; /* Return start of specifier of arg i. */ - unsigned int arg_idx (int i) + static unsigned int arg_idx (int i) { return return_desc_size + arg_desc_size * i; } @@ -195,9 +199,22 @@ public: return str[idx + 1] == 't'; } - /* Return true if memory pointer to by argument is copied to a memory + /* Return true if the size of the memory acccess for the argument is + constant and if so set *SIZE to the constant. */ + bool + arg_access_size_constant_p (unsigned int i, unsigned int *size) + { + if (!atomic_p ()) + return false; + unsigned int idx = arg_idx (i); + gcc_checking_assert (arg_specified_p (i)); + *size = 1 << (str[idx + 1] - '0'); + return true; + } + + /* Return true if memory pointed to by argument is copied to a memory pointed to by a different argument (as in memcpy). - In this case set ARG. */ + In this case set ARG to the zero-based argument number. */ bool arg_copied_to_arg_p (unsigned int i, unsigned int *arg) { @@ -264,6 +281,13 @@ public: return str[1] == 'C' || str[1] == 'P'; } + /* Return true of the function is an __atomic or __sync built-in. */ + bool + atomic_p () const + { + return str[0] == 'A'; + } + /* Check validity of the string. */ void verify (); @@ -277,5 +301,6 @@ public: extern attr_fnspec gimple_call_fnspec (const gcall *stmt); extern attr_fnspec builtin_fnspec (tree); +extern attr_fnspec atomic_builtin_fnspec (tree); #endif /* ATTR_FNSPEC_H */ diff --git a/gcc/builtins.c b/gcc/builtins.c index f1c3fea3583..b44b566888b 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -10957,9 +10957,11 @@ access_ref::offset_bounded () const return wi::to_offset (min) <= offrng[0] && offrng[1] <= wi::to_offset (max); } -/* If CALLEE has known side effects, fill in INFO and return true. - See tree-ssa-structalias.c:find_func_aliases - for the list of builtins we might need to handle here. */ +/* If CALLEE has known side effects, return an attr_fnspec object describing + those effects. Otherwise return an empty attr_fnspec whose known_p() is + false. + See tree-ssa-structalias.c:find_func_aliases for the list of builtins we + might need to handle here. */ attr_fnspec builtin_fnspec (tree callee) @@ -11138,3 +11140,70 @@ builtin_fnspec (tree callee) return ""; } } + +/* For an atomic or sync built-in CALLEE with known side effects, return + an attr_fnspec object describing those effects. Otherwise return + an empty attr_fnspec whose known_p() is false. */ + +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; \ + 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: \ + return "Ap" "W" lgsz; \ + case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_ ## N: \ + case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_ ## N: \ + return "Ap" "W" lgsz; \ + case BUILT_IN_SYNC_LOCK_RELEASE_ ## N: \ + return "Ap" "W" lgsz; \ + case BUILT_IN_ATOMIC_EXCHANGE_ ## N: \ + return "Ap" "W" lgsz; \ + case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_ ## N: \ + return "Ap" "W" lgsz "W" lgsz; \ + case BUILT_IN_ATOMIC_STORE_ ## N: \ + return "Ap" "W" lgsz; \ + 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_XOR_ ## N: \ + case BUILT_IN_ATOMIC_FETCH_OR_ ## N: \ + return "Ap" "W" lgsz \ + + case BUILTIN_ACCESS_SIZE_FNSPEC (1, "0"); + break; + case BUILTIN_ACCESS_SIZE_FNSPEC (2, "1"); + break; + case BUILTIN_ACCESS_SIZE_FNSPEC (4, "2"); + break; + case BUILTIN_ACCESS_SIZE_FNSPEC (8, "3"); + break; + case BUILTIN_ACCESS_SIZE_FNSPEC (16, "4"); + break; + + default: + return ""; + } +} diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 00c3ea0f505..ffe45fef93c 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -51,6 +51,7 @@ #include "attribs.h" #include "demangle.h" #include "pointer-query.h" +#include "attr-fnspec.h" /* Return true if tree node X has an associated location. */ @@ -2795,10 +2796,52 @@ pass_waccess::check_builtin (gcall *stmt) } default: - return false; + break; } - return true; + /* Try to determine the function's properties from its fnspec. */ + attr_fnspec fnspec = gimple_call_fnspec (stmt); + if (!fnspec.known_p () && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) + fnspec = atomic_builtin_fnspec (callee); + + if (!fnspec.known_p ()) + return false; + + bool handled = false; + unsigned nargs = gimple_call_num_args (stmt); + for (unsigned i = 0; i != nargs; ++i) + { + if (!fnspec.arg_specified_p (i) + || !fnspec.arg_direct_p (i)) + continue; + + tree len = NULL_TREE; + unsigned ni; + + if (fnspec.arg_access_size_constant_p (i, &ni)) + len = build_int_cstu (sizetype, ni); + else if (fnspec.arg_access_size_given_by_type_p (i)) + { + /* TODO: Determine access size from parameter type? */ + } + + unsigned di; + if (len && fnspec.arg_copied_to_arg_p (i, &di)) + { + tree dst = call_arg (stmt, di); + tree src = call_arg (stmt, i); + check_memop_access (stmt, dst, src, len); + handled = true; + } + + if (len && fnspec.arg_maybe_written_p (i)) + { + tree dst = gimple_call_arg (stmt, i); + check_memop_access (stmt, dst, NULL_TREE, len); + handled = true; + } + } + return handled; } /* 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" } +} diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index ce667ff32b9..2d143f23354 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -3850,13 +3850,16 @@ attr_fnspec::verify () if (!len) return; + const bool atomic_func = atomic_p (); + /* Check return value specifier. */ if (len < return_desc_size) err = true; else if ((len - return_desc_size) % arg_desc_size) err = true; else if ((str[0] < '1' || str[0] > '4') - && str[0] != '.' && str[0] != 'm') + && str[0] != '.' && str[0] != 'm' + && !atomic_func) err = true; switch (str[1]) @@ -3873,6 +3876,10 @@ attr_fnspec::verify () if (err) internal_error ("invalid fn spec attribute \"%s\"", str); + /* Either the minimum access size expressed as (1 << N) or the one-based + argument number that specifies the access size. */ + const char mindig = atomic_func ? '0' : '1'; + /* Now check all parameters. */ for (unsigned int i = 0; arg_specified_p (i); i++) { @@ -3888,14 +3895,16 @@ attr_fnspec::verify () case 'w': case 'W': case '.': - if ((str[idx + 1] >= '1' && str[idx + 1] <= '9') + if ((str[idx + 1] >= mindig && str[idx + 1] <= '9') || str[idx + 1] == 't') { if (str[idx] != 'r' && str[idx] != 'R' && str[idx] != 'w' && str[idx] != 'W' && str[idx] != 'o' && str[idx] != 'O') err = true; - if (str[idx + 1] != 't' + if (!atomic_func + /* Size is not constant and hardwired into attribute. */ + && str[idx + 1] != 't' /* Size specified is scalar, so it should be described by ". " if specified at all. */ && (arg_specified_p (str[idx + 1] - '1') @@ -3906,7 +3915,7 @@ attr_fnspec::verify () err = true; break; default: - if (str[idx] < '1' || str[idx] > '9') + if (str[idx] < mindig || str[idx] > '9') err = true; } if (err)