From patchwork Fri Sep 25 18:58:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 1371538 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=b5RfPux7; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Byh5j4RSqz9sTC for ; Sat, 26 Sep 2020 04:58:47 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C644B398B158; Fri, 25 Sep 2020 18:58:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C644B398B158 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1601060325; bh=Tzomif+oE8+ktXIBo0PDyUYocB3jA2+J20X4KyIU3/0=; h=Subject:To:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=b5RfPux7NemZV++SbakILXbcaGFxln1G3vI6oF3x4B+YvmX8vMqGcaWSYiixR9MXa BTVACaLizVwolwvX4H2kzQ6MK96QlSTtIVgwitc49NSS7NpfLnoyY5bWYxWOHFrA5l rlvT3LlRS8W4zWzCEMAW3dieoC86VgPcuE/0WGQI= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-ot1-x32f.google.com (mail-ot1-x32f.google.com [IPv6:2607:f8b0:4864:20::32f]) by sourceware.org (Postfix) with ESMTPS id 7E04B3860C3D; Fri, 25 Sep 2020 18:58:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 7E04B3860C3D Received: by mail-ot1-x32f.google.com with SMTP id y5so3293321otg.5; Fri, 25 Sep 2020 11:58:41 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:subject:to:message-id:date:user-agent :mime-version:content-language; bh=Tzomif+oE8+ktXIBo0PDyUYocB3jA2+J20X4KyIU3/0=; b=gOP4nTShwfnCcy9P/vO6xxNyDcGrBJVjmv6JQI2yV1+jxn6ODLhWcMzPfYNKN575vS FWA+TQliTX6h+5twqqZmc/25A3DaapGYFZg3QlJlFYURiaP4B5g1mnHSEvIM+eD13Dl0 EkZ+cr7QfN8LHLdnKRGZ0x+a9yZ4cacR7bbZkchOAucQy95wHOcTv+Q8V4sePtp+ivhg xXR1wsPTXkCdOYVDpqe4DeWVpgBRMgJ1OR4P5yYIwHfZcUdgo9JLwE5Pqnq43mmo7VNT U3amstyQG1F1W/ekSFPy8vz+3kKyK3rpLNG1fh06pcZrf+tTQAd4FYi9hVUiRUPM2ErD M8Mg== X-Gm-Message-State: AOAM530yGo7c6anhgrSBstzPlZ1zUCWAcMXWratNLYD4aRMEtrwoS13s MG1sGFw5Fn0JlI3kYyFszpW8fev7e18hKw== X-Google-Smtp-Source: ABdhPJyGaEzowX3PneKtm5iI1+2LZHnxX4fWGN6lFFTMHrPjmnQnafg3hnP5Z0I5NbcUTsHU/Batqg== X-Received: by 2002:a9d:1c8f:: with SMTP id l15mr1212425ota.241.1601060320522; Fri, 25 Sep 2020 11:58:40 -0700 (PDT) Received: from [192.168.0.41] (174-16-106-113.hlrn.qwest.net. [174.16.106.113]) by smtp.gmail.com with ESMTPSA id e19sm845332ote.37.2020.09.25.11.58.39 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 25 Sep 2020 11:58:39 -0700 (PDT) Subject: [PATCH] make handling of zero-length arrays in C++ pretty printer more robust (PR 97201) To: gcc-patches , Jason Merrill , libstdc++ Message-ID: <26ef4aff-92f2-2ec9-7074-c78413ab9777@gmail.com> Date: Fri, 25 Sep 2020 12:58:38 -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=-9.3 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.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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@gcc.gnu.org Sender: "Gcc-patches" The C and C++ representations of zero-length arrays are different: C uses a null upper bound of the type's domain while C++ uses SIZE_MAX. This makes the middle end logic more complicated (and prone to mistakes) because it has to be prepared for both. A recent change to -Warray-bounds has the middle end create a zero-length array to print in a warning message. I forgot about this gotcha and, as a result, when the warning triggers under these conditions in C++, it causes an ICE in the C++ pretty printer that in turn isn't prepared for the C form of the domain. In my mind, the "right fix" is to make the representation the same between the front ends, but I'm certain that such a change would cause more problems before it solved them. Another solution might be to provide APIs for creating (and querying) arrays and have them call language hooks in cases where the representation might differ. But that would likely be quite intrusive as well. So with that in mind, for the time being, the attached patch just continues to deal with the difference by teaching the C++ pretty printer to also recognize the C form of the zero-length domain. While testing the one line fix I noticed that -Warray-bounds (and therefore, I assume also all other warnings that detect out of bounds accesses to allocated objects) triggers only for the ordinary form of operator new and not for the nothrow overload, for instance. That's because the ordinary form is recognized as a built-in which has the alloc_size attribute attached to it. But because the other forms are neither built-in nor declared in with the same attribute, the warning doesn't trigger. So the patch also adds the attribute to the declarations of these overloads in . In addition, it adds attribute malloc to a couple of overloads of the operator that it's missing from. Tested on x86_64-linux. Martin PR c++/97201 - ICE in -Warray-bounds writing to result of operator new(0) gcc/cp/ChangeLog: PR c++/97201 * error.c (dump_type_suffix): Handle both the C and C++ forms of zero-length arrays. libstdc++-v3/ChangeLog: PR c++/97201 * libsupc++/new (operator new): Add attribute alloc_size and malloc. gcc/testsuite/ChangeLog: PR c++/97201 * g++.dg/warn/Warray-bounds-10.C: New test. * g++.dg/warn/Warray-bounds-11.C: New test. * g++.dg/warn/Warray-bounds-12.C: New test. * g++.dg/warn/Warray-bounds-13.C: New test. diff --git a/gcc/cp/error.c b/gcc/cp/error.c index ecb41e82d8c..11ed3aedc8d 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -951,8 +951,11 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t, int flags) if (tree dtype = TYPE_DOMAIN (t)) { tree max = TYPE_MAX_VALUE (dtype); - /* Zero-length arrays have an upper bound of SIZE_MAX. */ - if (integer_all_onesp (max)) + /* Zero-length arrays have a null upper bound in C and SIZE_MAX + in C++. Handle both since the type might be constructed by + the middle end and end up here as a result of a warning (see + PR c++/97201). */ + if (!max || integer_all_onesp (max)) pp_character (pp, '0'); else if (tree_fits_shwi_p (max)) pp_wide_integer (pp, tree_to_shwi (max) + 1); diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-10.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-10.C new file mode 100644 index 00000000000..22466977b68 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-10.C @@ -0,0 +1,64 @@ +/* PR c++/97201 - ICE in -Warray-bounds writing to result of operator new(0) + Verify that out-of-bounds accesses to memory returned by default operator + new() are diagnosed. + { dg-do compile } + { dg-options "-O2 -Wall -Warray-bounds -ftrack-macro-expansion=0" } */ + +typedef __INT32_TYPE__ int32_t; + +void sink (void*); + +#define OP_NEW(n) operator new (n) +#define T(T, n, i) do { \ + T *p = (T*) OP_NEW (n); \ + p[i] = 0; \ + sink (p); \ + } while (0) + +void warn_op_new () +{ + T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } + // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 } + T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } + T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } + T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } + + T (int32_t, 4, 0); + + T (int32_t, 0, 1); // { dg-warning "array subscript 1 is outside array bounds of 'int32_t \\\[0]'" } + T (int32_t, 1, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 2, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 3, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 4, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 5, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[5]" } + T (int32_t, 6, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[6]" } + T (int32_t, 7, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[7]" } + + T (int32_t, 8, 1); +} + + +void warn_op_array_new () +{ +#undef OP_NEW +#define OP_NEW(n) operator new[] (n) + + T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } + // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 } + T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } + T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } + T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } + + T (int32_t, 4, 0); + + T (int32_t, 0, 1); // { dg-warning "array subscript 1 is outside array bounds of 'int32_t \\\[0]'" } + T (int32_t, 1, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 2, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 3, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 4, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 5, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[5]" } + T (int32_t, 6, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[6]" } + T (int32_t, 7, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[7]" } + + T (int32_t, 8, 1); +} diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C new file mode 100644 index 00000000000..9875e29085d --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C @@ -0,0 +1,66 @@ +/* PR c++/97201 - ICE in -Warray-bounds writing to result of operator new(0) + Verify that out-of-bounds accesses to memory returned by nothrow operator + new() are diagnosed. + { dg-do compile } + { dg-options "-O2 -Wall -Warray-bounds -ftrack-macro-expansion=0" } */ + +#include + +typedef __INT32_TYPE__ int32_t; + +void sink (void*); + +#define OP_NEW(n) operator new (n, std::nothrow) +#define T(T, n, i) do { \ + T *p = (T*) OP_NEW (n); \ + p[i] = 0; \ + sink (p); \ + } while (0) + +void warn_op_new () +{ + T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } + // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(std::size_t, const std::nothrow_t.\\\)'" "note" { target *-*-* } .-1 } + T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } + T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } + T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } + + T (int32_t, 4, 0); + + T (int32_t, 0, 1); // { dg-warning "array subscript 1 is outside array bounds of 'int32_t \\\[0]'" } + T (int32_t, 1, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 2, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 3, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 4, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 5, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[5]" } + T (int32_t, 6, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[6]" } + T (int32_t, 7, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[7]" } + + T (int32_t, 8, 1); +} + + +void warn_op_array_new () +{ +#undef OP_NEW +#define OP_NEW(n) operator new[] (n, std::nothrow) + + T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } + // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(std::size_t, const std::nothrow_t&\\\)'" "note" { target *-*-* } .-1 } + T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } + T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } + T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } + + T (int32_t, 4, 0); + + T (int32_t, 0, 1); // { dg-warning "array subscript 1 is outside array bounds of 'int32_t \\\[0]'" } + T (int32_t, 1, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 2, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 3, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 4, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 5, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[5]" } + T (int32_t, 6, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[6]" } + T (int32_t, 7, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[7]" } + + T (int32_t, 8, 1); +} diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-12.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-12.C new file mode 100644 index 00000000000..9e8b6048944 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-12.C @@ -0,0 +1,66 @@ +/* PR c++/97201 - ICE in -Warray-bounds writing to result of operator new(0) + Verify that out-of-bounds accesses to memory returned by the new expression + are diagnosed. + { dg-do compile } + { dg-options "-O2 -Wall -Warray-bounds -ftrack-macro-expansion=0" } */ + +typedef __INT32_TYPE__ int32_t; + +template struct S { char a[N]; }; + +void sink (void*); + +#define NEW(n) new S +#define T(T, n, i) do { \ + T *p = (T*)NEW (n); \ + p[i] = 0; \ + sink (p); \ + } while (0) + +void warn_new () +{ + T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } + // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 } + T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } + T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } + T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } + + T (int32_t, 4, 0); + + T (int32_t, 0, 1); // { dg-warning "array subscript 1 is outside array bounds of 'int32_t \\\[0]'" } + T (int32_t, 1, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 2, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 3, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 4, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 5, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[5]" } + T (int32_t, 6, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[6]" } + T (int32_t, 7, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[7]" } + + T (int32_t, 8, 1); +} + + +void warn_array_new () +{ +#undef NEW +#define NEW(n) new char [n] + + T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } + // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 } + T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } + T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } + T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } + + T (int32_t, 4, 0); + + T (int32_t, 0, 1); // { dg-warning "array subscript 1 is outside array bounds of 'int32_t \\\[0]'" } + T (int32_t, 1, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 2, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 3, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 4, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 5, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[5]" } + T (int32_t, 6, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[6]" } + T (int32_t, 7, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[7]" } + + T (int32_t, 8, 1); +} diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C new file mode 100644 index 00000000000..42fb809de3c --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C @@ -0,0 +1,70 @@ +/* PR c++/97201 - ICE in -Warray-bounds writing to result of operator new(0) + Verify that out-of-bounds accesses to memory returned by the nothrow form + of the new expression are diagnosed. + { dg-do compile } + { dg-options "-O2 -Wall -Warray-bounds -ftrack-macro-expansion=0" } */ + +#include + +typedef __INT32_TYPE__ int32_t; + +void sink (void*); + +template struct S { char a[N]; }; + +void sink (void*); + +#define NEW(n) new (std::nothrow) S +#define T(T, n, i) do { \ + T *p = (T*)NEW (n); \ + p[i] = 0; \ + sink (p); \ + } while (0) + +void warn_nothrow_new () +{ + T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } + // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(std::size_t, const std::nothrow_t.\\\)'" "note" { target *-*-* } .-1 } + T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } + T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } + T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } + + T (int32_t, 4, 0); + + T (int32_t, 0, 1); // { dg-warning "array subscript 1 is outside array bounds of 'int32_t \\\[0]'" } + T (int32_t, 1, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 2, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 3, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 4, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 5, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[5]" } + T (int32_t, 6, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[6]" } + T (int32_t, 7, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[7]" } + + T (int32_t, 8, 1); +} + + +void warn_nothrow_array_new () +{ +#undef NEW +#define NEW(n) new (std::nothrow) char [n] + + T (int32_t, 0, 0); // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" } + // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(std::size_t, const std::nothrow_t&\\\)'" "note" { target *-*-* } .-1 } + T (int32_t, 1, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" } + T (int32_t, 2, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" } + T (int32_t, 3, 0); // { dg-warning "array subscript 'int32_t {aka int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" } + + T (int32_t, 4, 0); + + T (int32_t, 0, 1); // { dg-warning "array subscript 1 is outside array bounds of 'int32_t \\\[0]'" } + T (int32_t, 1, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 2, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 3, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 4, 1); // { dg-warning "array subscript 1 is outside array bounds " } + T (int32_t, 5, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[5]" } + T (int32_t, 6, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[6]" } + T (int32_t, 7, 1); // { dg-warning "array subscript 'int32_t {aka int}\\\[1]' is partly outside array bounds of 'unsigned char \\\[7]" } + + T (int32_t, 8, 1); +} diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new index 21848a573d1..15edf8ad6a9 100644 --- a/libstdc++-v3/libsupc++/new +++ b/libstdc++-v3/libsupc++/new @@ -138,26 +138,26 @@ void operator delete[](void*, std::size_t) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); #endif _GLIBCXX_NODISCARD void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT - __attribute__((__externally_visible__, __malloc__)); + __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); _GLIBCXX_NODISCARD void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT - __attribute__((__externally_visible__, __malloc__)); + __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); #if __cpp_aligned_new _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t) - __attribute__((__externally_visible__)); + __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&) - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __malloc__)); + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); void operator delete(void*, std::align_val_t) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); void operator delete(void*, std::align_val_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t) - __attribute__((__externally_visible__)); + __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __malloc__)); + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); void operator delete[](void*, std::align_val_t) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); void operator delete[](void*, std::align_val_t, const std::nothrow_t&)