From patchwork Mon Nov 27 19:24:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 841839 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-467983-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="SmwQgad9"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3ylxZx0Vp2z9s72 for ; Tue, 28 Nov 2017 06:25:12 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=gQ+mnahWoh2dohMBx+HRWh25PtwIKakmHFtPKE5dSLUPJmOSzD EeXo9CL2odf+Vox56O4QJh6kvBjgNsRpt0f/Q9Ui8GZCr1mypVfN/ELrnHFqRxLf 10C0+hJ5O4TEDp79Y5jS6Pxj+l4IddqwBKnKyohsPXjnJLZipkCsgT/ac= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=SaxFtLxanxUKgwb6CjXsbIJ5hdI=; b=SmwQgad9VMFjVTRbLgiW 4MW6rQaTxGTUKBHRQ2CGPU5/9XlmSvsQKocnSIjkSk17EDUNTfdakiVGDhDIqXZS Xfoz2KEtrJxL3n0xVjJ6C6ciIxWWu6zivHFYW9p2vfGDQD2x4qQ72/GXJfempntX FC4nAzL/rv5xpk3ygVjTHYs= Received: (qmail 50339 invoked by alias); 27 Nov 2017 19:25:03 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 50328 invoked by uid 89); 27 Nov 2017 19:25:03 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-15.1 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KB_WAM_FROM_NAME_SINGLEWORD, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=diagnosed, carr, sk:array_t X-HELO: mail-ot0-f177.google.com Received: from mail-ot0-f177.google.com (HELO mail-ot0-f177.google.com) (74.125.82.177) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 27 Nov 2017 19:24:59 +0000 Received: by mail-ot0-f177.google.com with SMTP id b49so25216450otj.5 for ; Mon, 27 Nov 2017 11:24:59 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version; bh=22cBczZCTATGizRSjro4dKjiow6wTHDyWJwAtLSCkog=; b=NvbzzQ6u59RZchNJ0jR8dycyEzx6poxwdjZjwwJrwSnFtRE7pelykqH/sbsglaA1dn 0alwwtgA1TrvK5hG8zlkwYywr94mQf2TunwJx+4NDmy5gw3U3Ejz6sJwPTSpSc448QEy AmqFS54gRhWfDf1rJEufQsdqHg5Xz2F7DE+SjzOpzFcuhWFsMR0GdRQ1HEZGgjgyRRmH NwFIpzpjNa/a92jVvWB+5DxMPUIJ3Xhk4Kqi+16Sf8JYtw2HR6Kcnok1JPa6PphSLwRk EQAZ835V3m07mzDaQKdqsj8ZGPax1dT9ETgL428Z+oOV8TfRqSNBtv9wewMzAd9W7nez fxhA== X-Gm-Message-State: AJaThX63FGdEV4CUuF+Vv7UwTFmQZPuHJJ3962l1yqPdZeJ1JrJtahU4 +f9Km/qlXayjZqz8JWU/Xdw= X-Google-Smtp-Source: AGs4zMYdGmw7SdP6oTktxNsOQrNDMFT+9KHK6AaIWlfKY+4mzFY8DRBjnd/++5nzRk+csPQ7a4ztEw== X-Received: by 10.157.54.37 with SMTP id w34mr12046356otb.201.1511810698222; Mon, 27 Nov 2017 11:24:58 -0800 (PST) Received: from localhost.localdomain (75-171-240-43.hlrn.qwest.net. [75.171.240.43]) by smtp.gmail.com with ESMTPSA id 203sm11512780oie.27.2017.11.27.11.24.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 27 Nov 2017 11:24:56 -0800 (PST) To: Gcc Patch List , Jason Merrill From: Martin Sebor Subject: [PATCH] handle invalid array index in warn_placement_new_too_small (PR 83058) Message-ID: <42cfde95-0480-8781-0413-23f2de315735@gmail.com> Date: Mon, 27 Nov 2017 12:24:55 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 MIME-Version: 1.0 X-IsSubscribed: yes Bug 83058 - [6/7/8 Regression] ICE on C++ code with negative array index: in warn_placement_new_too_small, at cp/init.c:2666, reports an ICE for an invalid placement new expression with a negative array index. The ICE was caused by calling tree_to_uhwi (nelts) without first checking to make sure nelts is fits in an unsigned HOST_WIDE_INT. While testing the code for similar boundary conditions I also found a few other cases that the code doesn't handle entirely correctly. To avoid the ICE the attached patch uses offset_int instead of HOST_WIDE_INT to track offsets and sizes. It also improves the handling of the other edge cases. Martin PR c++/83058 - [6/7/8 Regression] ICE on C++ code with negative array index: in warn_placement_new_too_small gcc/cp/ChangeLog: PR c++/83058 * init.c (warn_placement_new_too_small): Use offset_int instead of HOST_WIDE_INT. gcc/testsuite/ChangeLog: PR c++/83058 * g++.dg/warn/Wplacement-new-size-5.C: New test. Index: gcc/cp/init.c =================================================================== --- gcc/cp/init.c (revision 255173) +++ gcc/cp/init.c (working copy) @@ -2498,9 +2498,9 @@ warn_placement_new_too_small (tree type, tree nelt /* The number of bytes to add to or subtract from the size of the provided buffer based on an offset into an array or an array element reference. - Although intermediate results may be negative (as in a[3] - 2) the final - result cannot be. */ - HOST_WIDE_INT adjust = 0; + Although intermediate results may be negative (as in a[3] - 2) a valid + final result cannot be. */ + offset_int adjust = 0; /* True when the size of the entire destination object should be used to compute the possibly optimistic estimate of the available space. */ bool use_obj_size = false; @@ -2524,7 +2524,7 @@ warn_placement_new_too_small (tree type, tree nelt is a constant. */ if (TREE_CODE (oper) == POINTER_PLUS_EXPR) { - /* If the offset is comple-time constant, use it to compute a more + /* If the offset is compile-time constant, use it to compute a more accurate estimate of the size of the buffer. Since the operand of POINTER_PLUS_EXPR is represented as an unsigned type, convert it to signed first. @@ -2532,7 +2532,7 @@ warn_placement_new_too_small (tree type, tree nelt estimate (this may lead to false negatives). */ tree adj = TREE_OPERAND (oper, 1); if (CONSTANT_CLASS_P (adj)) - adjust += tree_to_shwi (convert (ssizetype, adj)); + adjust += wi::to_offset (convert (ssizetype, adj)); else use_obj_size = true; @@ -2559,9 +2559,9 @@ warn_placement_new_too_small (tree type, tree nelt not a compile-time constant, use the index to determine the size of the buffer. Otherwise, use the entire array as an optimistic estimate of the size. */ - const_tree adj = TREE_OPERAND (oper, 1); + const_tree adj = fold_non_dependent_expr (TREE_OPERAND (oper, 1)); if (!use_obj_size && CONSTANT_CLASS_P (adj)) - adjust += tree_to_shwi (adj); + adjust += wi::to_offset (adj); else { use_obj_size = true; @@ -2580,10 +2580,18 @@ warn_placement_new_too_small (tree type, tree nelt members from arrays of unspecified size. */ bool compref = TREE_CODE (oper) == COMPONENT_REF; + /* For COMPONENT_REF (i.e., a struct member) the size of the entire + enclosing struct. Used to validate the adjustment (offset) into + an array at the end of a struct. */ + offset_int compsize = 0; + /* Descend into a struct or union to find the member whose address is being used as the argument. */ if (TREE_CODE (oper) == COMPONENT_REF) { + tree comptype = TREE_TYPE (TREE_OPERAND (oper, 0)); + compsize = wi::to_offset (TYPE_SIZE_UNIT (comptype)); + tree op0 = oper; while (TREE_CODE (op0 = TREE_OPERAND (op0, 0)) == COMPONENT_REF); if (VAR_P (op0)) @@ -2591,7 +2599,8 @@ warn_placement_new_too_small (tree type, tree nelt oper = TREE_OPERAND (oper, 1); } - if ((addr_expr || !POINTER_TYPE_P (TREE_TYPE (oper))) + tree opertype = TREE_TYPE (oper); + if ((addr_expr || !POINTER_TYPE_P (opertype)) && (VAR_P (oper) || TREE_CODE (oper) == FIELD_DECL || TREE_CODE (oper) == PARM_DECL)) @@ -2598,7 +2607,7 @@ warn_placement_new_too_small (tree type, tree nelt { /* A possibly optimistic estimate of the number of bytes available in the destination buffer. */ - unsigned HOST_WIDE_INT bytes_avail = 0; + offset_int bytes_avail = 0; /* True when the estimate above is in fact the exact size of the destination buffer rather than an estimate. */ bool exact_size = true; @@ -2613,47 +2622,42 @@ warn_placement_new_too_small (tree type, tree nelt /* Use the size of the entire array object when the expression refers to a variable or its size depends on an expression that's not a compile-time constant. */ - bytes_avail = tree_to_uhwi (DECL_SIZE_UNIT (oper)); + bytes_avail = wi::to_offset (DECL_SIZE_UNIT (oper)); exact_size = !use_obj_size; } - else if (TYPE_SIZE_UNIT (TREE_TYPE (oper)) - && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (oper)))) + else if (tree opersize = TYPE_SIZE_UNIT (opertype)) { /* Use the size of the type of the destination buffer object - as the optimistic estimate of the available space in it. */ - bytes_avail = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (oper))); + as the optimistic estimate of the available space in it. + Use the maximum possible size for zero-size arrays and + flexible array members (except of initialized objects + thereof). */ + if (TREE_CODE (opersize) == INTEGER_CST) + bytes_avail = wi::to_offset (opersize); } - else if (var_decl) - { - /* Constructing into a buffer provided by the flexible array - member of a declared object (which is permitted as a G++ - extension). If the array member has been initialized, - determine its size from the initializer. Otherwise, - the array size is zero. */ - bytes_avail = 0; - if (tree init = find_field_init (oper, DECL_INITIAL (var_decl))) - bytes_avail = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (init))); - } - else + if (bytes_avail == 0) { - /* Bail if neither the size of the object nor its type is known. */ - return; + if (var_decl) + { + /* Constructing into a buffer provided by the flexible array + member of a declared object (which is permitted as a G++ + extension). If the array member has been initialized, + determine its size from the initializer. Otherwise, + the array size is zero. */ + if (tree init = find_field_init (oper, DECL_INITIAL (var_decl))) + bytes_avail = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (init))); + } + else + bytes_avail = (wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node)) + - compsize); } - tree_code oper_code = TREE_CODE (TREE_TYPE (oper)); + tree_code oper_code = TREE_CODE (opertype); if (compref && oper_code == ARRAY_TYPE) { - /* Avoid diagnosing flexible array members (which are accepted - as an extension and diagnosed with -Wpedantic) and zero-length - arrays (also an extension). - Overflowing construction in one-element arrays is diagnosed - only at level 2. */ - if (bytes_avail == 0 && !var_decl) - return; - - tree nelts = array_type_nelts_top (TREE_TYPE (oper)); + tree nelts = array_type_nelts_top (opertype); tree nelts_cst = maybe_constant_value (nelts); if (TREE_CODE (nelts_cst) == INTEGER_CST && integer_onep (nelts_cst) @@ -2662,29 +2666,35 @@ warn_placement_new_too_small (tree type, tree nelt return; } - /* The size of the buffer can only be adjusted down but not up. */ - gcc_checking_assert (0 <= adjust); - /* Reduce the size of the buffer by the adjustment computed above from the offset and/or the index into the array. */ - if (bytes_avail < static_cast(adjust)) + if (bytes_avail < adjust || adjust < 0) bytes_avail = 0; else - bytes_avail -= adjust; + { + tree elttype = (TREE_CODE (opertype) == ARRAY_TYPE + ? TREE_TYPE (opertype) : opertype); + if (tree eltsize = TYPE_SIZE_UNIT (elttype)) + { + bytes_avail -= adjust * wi::to_offset (eltsize); + if (bytes_avail < 0) + bytes_avail = 0; + } + } /* The minimum amount of space needed for the allocation. This is an optimistic estimate that makes it possible to detect placement new invocation for some undersize buffers but not others. */ - unsigned HOST_WIDE_INT bytes_need; + offset_int bytes_need; if (CONSTANT_CLASS_P (size)) - bytes_need = tree_to_uhwi (size); + bytes_need = wi::to_offset (size); else if (nelts && CONSTANT_CLASS_P (nelts)) - bytes_need = tree_to_uhwi (nelts) - * tree_to_uhwi (TYPE_SIZE_UNIT (type)); + bytes_need = (wi::to_offset (nelts) + * wi::to_offset (TYPE_SIZE_UNIT (type))); else if (tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))) - bytes_need = tree_to_uhwi (TYPE_SIZE_UNIT (type)); + bytes_need = wi::to_offset (TYPE_SIZE_UNIT (type)); else { /* The type is a VLA. */ @@ -2703,9 +2713,8 @@ warn_placement_new_too_small (tree type, tree nelt : "placement new constructing an object of type " "%<%T [%wu]%> and size %qwu in a region of type %qT " "and size at most %qwu", - type, tree_to_uhwi (nelts), bytes_need, - TREE_TYPE (oper), - bytes_avail); + type, tree_to_uhwi (nelts), bytes_need.to_uhwi (), + opertype, bytes_avail.to_uhwi ()); else warning_at (loc, OPT_Wplacement_new_, exact_size ? @@ -2715,8 +2724,8 @@ warn_placement_new_too_small (tree type, tree nelt : "placement new constructing an array of objects " "of type %qT and size %qwu in a region of type %qT " "and size at most %qwu", - type, bytes_need, TREE_TYPE (oper), - bytes_avail); + type, bytes_need.to_uhwi (), opertype, + bytes_avail.to_uhwi ()); else warning_at (loc, OPT_Wplacement_new_, exact_size ? @@ -2725,8 +2734,8 @@ warn_placement_new_too_small (tree type, tree nelt : "placement new constructing an object of type %qT " "and size %qwu in a region of type %qT and size " "at most %qwu", - type, bytes_need, TREE_TYPE (oper), - bytes_avail); + type, bytes_need.to_uhwi (), opertype, + bytes_avail.to_uhwi ()); } } } Index: gcc/testsuite/g++.dg/warn/Wplacement-new-size-5.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wplacement-new-size-5.C (nonexistent) +++ gcc/testsuite/g++.dg/warn/Wplacement-new-size-5.C (working copy) @@ -0,0 +1,241 @@ +// PR c++/83058 - ICE on C++ code with negative array index: in +// warn_placement_new_too_small +// { dg-do compile } +// { dg-additional-options "-Wplacement-new -Wno-pedantic" } + +#define SIZE_MAX __SIZE_MAX__ +#define DIFF_MAX __PTRDIFF_MAX__ +#define DIFF_MIN (-DIFF_MAX - 1) + +void* operator new (__SIZE_TYPE__ n, void *p) { return p; } +void* operator new[] (__SIZE_TYPE__ n, void *p) { return p; } + +struct A { }; + +char carr[2]; +int iarr[2]; + +struct C0 { char i, carr[0]; }; +struct I0 { int i, iarr[0]; }; +struct CX { char i, carr[]; }; +struct IX { int i, iarr[]; }; + +void test_single (C0 *pc, CX *qc, I0 *pi, IX *qi, int n) +{ + new (&carr[DIFF_MIN]) A (); // { dg-warning "placement new constructing an object of type .A. and size .1. in a region of type .char \\\[2]. and size .0." } + new (&carr[-1]) A; // { dg-warning "\\\[-Wplacement-new" } + new (carr -1 ) A; // { dg-warning "\\\[-Wplacement-new" } + new (&carr[0]) A; + new (carr) A; + new (&carr[1]) A; + new (carr + 1) A; + new (&carr[n]) A; + new (carr + n) A; + new (&carr[DIFF_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + new (carr + DIFF_MAX) A; // { dg-warning "\\\[-Wplacement-new" } + new (&carr[SIZE_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + new (carr + SIZE_MAX) A; // { dg-warning "\\\[-Wplacement-new" } + + new (&pc->carr[DIFF_MIN]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&pc->carr[-1]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&pc->carr[0]) A; + new (&pc->carr[9]) A; + new (&pc->carr[n]) A; + new (&pc->carr[DIFF_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&pc->carr[SIZE_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + + { + /* The highest index at which a single A can be constructed. */ + enum { MAX = DIFF_MAX - sizeof *pc - sizeof (A) }; + new (&pc->carr[MAX]) A; + new (&pc->carr[MAX + 1]) A; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&qc->carr[DIFF_MIN]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&qc->carr[-1]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&qc->carr[0]) A; + new (&qc->carr[9]) A; + new (&qc->carr[n]) A; + new (&qc->carr[DIFF_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&qc->carr[SIZE_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + + { + /* The highest index at which a single A can be constructed. */ + enum { MAX = DIFF_MAX - sizeof *qc - sizeof (A) }; + new (&qc->carr[MAX]) A; + new (&qc->carr[MAX + 1]) A; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&pi->iarr[DIFF_MIN]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&pi->iarr[-1]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&pi->iarr[0]) A; + new (&pi->iarr[9]) A; + new (&pi->iarr[n]) A; + new (&pi->iarr[DIFF_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&pi->iarr[SIZE_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + + { + enum { MAX = (DIFF_MAX - sizeof *pi) / sizeof *pi->iarr }; + new (&pi->iarr[MAX]) A; + new (&pi->iarr[MAX + 1]) A; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&qi->iarr[DIFF_MIN]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&qi->iarr[-1]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&qi->iarr[0]) A; + new (&qi->iarr[9]) A; + new (&qi->iarr[n]) A; + new (&qi->iarr[DIFF_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&qi->iarr[SIZE_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + + { + enum { MAX = (DIFF_MAX - sizeof *qi) / sizeof *qi->iarr }; + new (&qi->iarr[MAX]) A; + new (&qi->iarr[MAX + 1]) A; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&iarr[DIFF_MIN]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&iarr[-1]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&iarr[1]) A; + new (&iarr[n]) A; + new (&iarr[DIFF_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + new (&iarr[SIZE_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } +} + +void test_array_1 (C0 *pc, CX *qc, I0 *pi, IX *qi) +{ + enum { N = 1 }; + + new (&carr[DIFF_MIN]) A[N]; // { dg-warning "placement new constructing an object of type .A \\\[\[0-9\]+]. and size .\[0-9\]+. in a region of type .char \\\[2]. and size .0." } + new (&carr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&carr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&carr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + + new (&pc->carr[DIFF_MIN]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pc->carr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pc->carr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pc->carr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + + { + enum { MAX = DIFF_MAX - sizeof *pc - sizeof (A[N]) }; + new (&pc->carr[MAX]) A[N]; + new (&pc->carr[MAX + 1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&qc->carr[DIFF_MIN]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qc->carr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qc->carr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qc->carr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + + { + enum { MAX = DIFF_MAX - sizeof *qc - sizeof (A[N]) }; + new (&qc->carr[MAX]) A[N]; + new (&qc->carr[MAX + 1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&pi->iarr[DIFF_MIN]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pi->iarr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pi->iarr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pi->iarr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + + { + enum { MAX = (DIFF_MAX - sizeof *pi) / sizeof *pi->iarr }; + new (&pi->iarr[MAX]) A[N]; + new (&pi->iarr[MAX + 1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&qi->iarr[DIFF_MIN]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qi->iarr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qi->iarr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qi->iarr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + + { + enum { MAX = (DIFF_MAX - sizeof *qi) / sizeof *qi->iarr }; + new (&qi->iarr[MAX]) A[N]; + new (&qi->iarr[MAX + 1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&iarr[DIFF_MIN]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&iarr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&iarr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&iarr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } +} + + +void test_array_3 (C0 *pc, CX *qc, I0 *pi, IX *qi) +{ + enum { N = 3 }; + + new (&carr[DIFF_MIN]) A[N]; // { dg-warning "placement new constructing an object of type .A \\\[\[0-9\]+]. and size .\[0-9\]+. in a region of type .char \\\[2]. and size .0." } + new (&carr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&carr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&carr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + + new (&pc->carr[DIFF_MIN]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pc->carr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pc->carr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pc->carr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + + { + enum { MAX = DIFF_MAX - sizeof *pc - sizeof (A[N]) }; + new (&pc->carr[MAX]) A[N]; + new (&pc->carr[MAX + 1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&qc->carr[DIFF_MIN]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qc->carr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qc->carr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qc->carr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + + { + enum { MAX = DIFF_MAX - sizeof *qc - sizeof (A[N]) }; + new (&qc->carr[MAX]) A[N]; + new (&qc->carr[MAX + 1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&pi->iarr[DIFF_MIN]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pi->iarr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pi->iarr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&pi->iarr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + + { + enum { MAX = (DIFF_MAX - sizeof *pi) / sizeof *pi->iarr }; + new (&pi->iarr[MAX]) A[N]; + new (&pi->iarr[MAX + 1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&qi->iarr[DIFF_MIN]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qi->iarr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qi->iarr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&qi->iarr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + + { + enum { MAX = (DIFF_MAX - sizeof *qi) / sizeof *qi->iarr }; + new (&qi->iarr[MAX]) A[N]; + new (&qi->iarr[MAX + 1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + } + + new (&iarr[DIFF_MIN]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&iarr[-1]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&iarr[DIFF_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } + new (&iarr[SIZE_MAX]) A[N]; // { dg-warning "\\\[-Wplacement-new" } +} + + +void test_vla (unsigned n) +{ + char cvla[n]; + + new (&cvla[DIFF_MIN]) A; // { dg-warning "placement new constructing an object of type .A. and size .1. in a region of type .char \\\[n]. and size .0." } + new (&cvla[-1]) A; // { dg-warning "\\\[-Wplacement-new" } + new (cvla -1) A; // { dg-warning "\\\[-Wplacement-new" } + new (&cvla[0]) A; + new (&cvla[9]) A; + new (&cvla[n - 1]) A; + new (cvla + n - 1) A; + new (&cvla[DIFF_MAX - 1]) A; + new (&cvla[DIFF_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + new (cvla + DIFF_MAX) A; // { dg-warning "\\\[-Wplacement-new" } + new (&cvla[SIZE_MAX]) A; // { dg-warning "\\\[-Wplacement-new" } + new (cvla + SIZE_MAX) A; // { dg-warning "\\\[-Wplacement-new" } +}