From patchwork Thu Dec 16 19:56:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 49026 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 1F5AF385801A for ; Thu, 16 Dec 2021 19:56:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1F5AF385801A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1639684611; bh=5MBik/RgSioqQjbXEeaB3YImIeTg09ex/e2aguggjeg=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=rucnW0Bxm2+r7F3qGbitxMw8Renhw22k9iI2ZVxF4eJYpoRrNvEVGAHuaOSnga1RT QTp6lLXklchwJAluZvLOuFb2hApmO7GDlSyDC1EEvrt1rHkTnhosfsVfQ8dhtv+W9D +hCzJy/lpxqfzJ3uXQUNiWmPDMW5xZ8af1SC8NJ4= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-oi1-x22c.google.com (mail-oi1-x22c.google.com [IPv6:2607:f8b0:4864:20::22c]) by sourceware.org (Postfix) with ESMTPS id 52DBF3858412 for ; Thu, 16 Dec 2021 19:56:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 52DBF3858412 Received: by mail-oi1-x22c.google.com with SMTP id m6so485069oim.2 for ; Thu, 16 Dec 2021 11:56:20 -0800 (PST) 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=5MBik/RgSioqQjbXEeaB3YImIeTg09ex/e2aguggjeg=; b=TsHISYAuCcApX16POovmhaIsJtK3yZ7bjQa+im8LAm7+XmzJL9zwKK6+NkgAhuhcxr n5HwCJi3+95sVl3CtqfkLyg5NuEhr6FPschkaJ+AtDrN3btCIcgq3J//7q6WB+h1Eyh7 22VyOsjSe9P3NZTXWtmDbAsDzhvJglWj9xB1/NrxQ03Ak+2JR3/J9nNGMvhTVzYdu/Kr aDPxKjqOYpUPw+CPOqHg4luswnZGyUKgff5LMbvaCAJL0MIX/j5le3ykQ1ZOV8rZlsZ2 UlhHhgIaQBwtVJDPfQClk1f9z2O//r3Se7w68LSoR7jnq5AFV9D84qdpgF1c/GIKiivq FPeQ== X-Gm-Message-State: AOAM530lpuJ+0RwxEBc6gVHymnNhNcNJ7Gc7b5sfHP83AHfZ8+a1E34O 7EEkoHGVnwkgwC+oh0ZqFXwjOr6My5g= X-Google-Smtp-Source: ABdhPJyP+Flf4l0JWSM06vLYrmrbBgh+VsDQoW4iFwpG8O3a0jOVYs4no09hYzSy1mCMwv/Ejwys/w== X-Received: by 2002:aca:ac8e:: with SMTP id v136mr5472973oie.19.1639684578417; Thu, 16 Dec 2021 11:56:18 -0800 (PST) Received: from [192.168.0.41] (184-96-227-137.hlrn.qwest.net. [184.96.227.137]) by smtp.gmail.com with ESMTPSA id f20sm1251201oiw.48.2021.12.16.11.56.17 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 16 Dec 2021 11:56:17 -0800 (PST) To: gcc-patches Subject: [PATCH] Use enclosing object size if it's smaller than member [PR 101475] Message-ID: Date: Thu, 16 Dec 2021 12:56:16 -0700 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.5 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" Enabling vectorization at -O2 caused quite a few tests for warnings to start failing in GCC 12. These tests were xfailed and bugs were opened to track the problems until they can be fully analyzed and ultimately fixed before GCC 12 is released. I've now started going through these and the first such bug I tackled is PR 102944. As it turns out, the xfails there are all due to a known limitation tracked in PR 101475: when determining the size of a destination for A COMPONENT_REF, unless asked for the size of the complete object, compute_objsize() only considers the size of the referenced member, even when the member is larger than the object would allow. This prevents warnings from diagnosing unvectorized past-the-end accesses to objects in backing buffers (such as in character arrays or allocated chunks of memory). Many (though not all) accesses that are vectorized are diagnosed because there the COMPONENT_REF is replaced by a MEM_REF. But because vectorization depends on target-specific things like alignment requirements, what is and isn't diagnosed also tends to be target-specific, making these tests quite brittle.. The attached patch corrects this oversight by using the complete object's size instead of the member when the former is smaller. Besides improving the out-of-bounds access detection it also makes the tests behave more consistently across targets. Tested on x86_64-linux and by building Glibc and verifying that the change triggers no new warnings. Martin Use enclosing object size if it's smaller than member [PR 101475]. Resolves: PR middle-end/101475 - missing -Wstringop-overflow storing a compound literal gcc/ChangeLog: PR middle-end/101475 * pointer-query.cc (handle_component_ref): Use the size of the enclosing object if it's smaller than the member. gcc/testsuite/ChangeLog: PR middle-end/101475 * gcc.dg/Wstringop-overflow-68.c: Adjust, remove xfails. * gcc.dg/Wstringop-overflow-88.c: New test. diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index 4bedf7fca47..644b4de9bcb 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -1914,36 +1914,40 @@ handle_component_ref (tree cref, gimple *stmt, bool addr, int ostype, gcc_assert (TREE_CODE (cref) == COMPONENT_REF); const tree base = TREE_OPERAND (cref, 0); + const tree field = TREE_OPERAND (cref, 1); + access_ref base_ref = *pref; + + /* Unconditionally determine the size of the base object (it could + be smaller than the referenced member). */ + if (!compute_objsize_r (base, stmt, addr, 0, &base_ref, snlim, qry)) + return false; + + /* Add the offset of the member to the offset into the object computed + so far. */ + tree offset = byte_position (field); + if (TREE_CODE (offset) == INTEGER_CST) + base_ref.add_offset (wi::to_offset (offset)); + else + base_ref.add_max_offset (); + + if (!base_ref.ref) + /* PREF->REF may have been already set to an SSA_NAME earlier + to provide better context for diagnostics. In that case, + leave it unchanged. */ + base_ref.ref = base; + const tree base_type = TREE_TYPE (base); if (TREE_CODE (base_type) == UNION_TYPE) /* In accesses through union types consider the entire unions rather than just their members. */ ostype = 0; - tree field = TREE_OPERAND (cref, 1); - if (ostype == 0) { /* In OSTYPE zero (for raw memory functions like memcpy), use the maximum size instead if the identity of the enclosing object cannot be determined. */ - if (!compute_objsize_r (base, stmt, addr, ostype, pref, snlim, qry)) - return false; - - /* Otherwise, use the size of the enclosing object and add - the offset of the member to the offset computed so far. */ - tree offset = byte_position (field); - if (TREE_CODE (offset) == INTEGER_CST) - pref->add_offset (wi::to_offset (offset)); - else - pref->add_max_offset (); - - if (!pref->ref) - /* PREF->REF may have been already set to an SSA_NAME earlier - to provide better context for diagnostics. In that case, - leave it unchanged. */ - pref->ref = base; - + *pref = base_ref; return true; } @@ -1958,6 +1962,11 @@ handle_component_ref (tree cref, gimple *stmt, bool addr, int ostype, } set_component_ref_size (cref, pref); + + if (base_ref.size_remaining () < pref->size_remaining ()) + /* Use the base object if it's smaller than the member. */ + *pref = base_ref; + return true; } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c index 05ea56fca67..4d132394f0f 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c @@ -2,7 +2,7 @@ a larger scalar into a smaller array Verify overflow by aggregate stores. { dg-do compile } - { dg-options "-O2" } */ + { dg-options "-O2 -fno-tree-vectorize" } */ #define A(N) (A ## N) #define Ac1 (AC1){ 0 } @@ -57,19 +57,20 @@ void warn_comp_lit_zero (void) void warn_comp_lit (void) { - *(AC2*)a1 = Ac2; // { dg-warning "writing 2 bytes into a region of size 1" "pr101475" { xfail *-*-* } } - // After vectorization, below codes are optimized to - // MEM [(char *)&a2] = { 0, 1, 2, 3 }; - // MEM [(char *)&a3] = { 0, 1, 2, 3 }; - // MEM [(char *)&a4] = { 0, 1, 2, 3, 4, 5, 6, 7 }; - // MEM [(char *)&a7] = { 0, 1, 2, 3, 4, 5, 6, 7 }; - // MEM [(char *)&a15] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; - // and warning should be expected, refer to PR102722. - *(AC4*)a2 = Ac4; // { dg-warning "writing 4 bytes into a region of size 2" "pr101475" { xfail { ! { vect_slp_v4qi_store_unalign_1 } } } } - *(AC4*)a3 = Ac4; // { dg-warning "writing 4 bytes into a region of size 3" "pr101475" { xfail { ! { vect_slp_v4qi_store_unalign_1 } } } } - *(AC8*)a4 = Ac8; // { dg-warning "writing 8 bytes into a region of size 4" "pr101475" { xfail { ! { vect_slp_v8qi_store_unalign_1 } } } } - *(AC8*)a7 = Ac8; // { dg-warning "writing 8 bytes into a region of size 7" "pr101475" { xfail { ! { vect_slp_v8qi_store_unalign_1 } } } } - *(AC16*)a15 = Ac16; // { dg-warning "writing 16 bytes into a region of size 15" "pr101475" { xfail { ! { vect_slp_v16qi_store_unalign_1 } } } } + /* Ideally only one warning would be issued for each of the stores + mentioning the size of the rest of the source being assigned to + the destination that doesn't fit. But without vectorization + the assignment is a series of one-character stores, except in + the first instance multiple warnings end up being issued for + each assignment, each saying "writing 1 byte into a region of + size 0". That's suboptimal and should be improved. See also + PR 92110. */ + *(AC2*)a1 = Ac2; // { dg-warning "writing (2 bytes|1 byte) into a region of size (1|0)" "pr101475" } + *(AC4*)a2 = Ac4; // { dg-warning "writing (4 bytes|1 byte) into a region of size (2|0)" "pr101475" } + *(AC4*)a3 = Ac4; // { dg-warning "writing (4 bytes|1 byte) into a region of size (3|0)" "pr101475" } + *(AC8*)a4 = Ac8; // { dg-warning "writing (8 bytes|1 byte) into a region of size (4|0)" "pr101475" } + *(AC8*)a7 = Ac8; // { dg-warning "writing (8 bytes|1 byte) into a region of size (7|0)" "pr101475" } + *(AC16*)a15 = Ac16; // { dg-warning "writing (16 bytes|1 byte) into a region of size (15|0)" "pr101475" } } void warn_aggr_decl (void) diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-88.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-88.c new file mode 100644 index 00000000000..c6b443e4d3d --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-88.c @@ -0,0 +1,327 @@ +/* PR middle-end/101475 - missing -Wstringop-overflow storing a compound + literal + { dg-do compile } + { dg-options "-O2 -fno-tree-vectorize" } */ + +extern char ea1[1], ea2[2], ea3[3], ea4[4]; + +/* The trailing A member of all of Sx, S0, and S1 is treated the same: + as a flexible array member. */ +struct Sx { char n, a[]; }; +struct S0 { char n, a[0]; }; +struct S1 { char n, a[1]; }; +/* The trailing A member in both S2 and S3 is treated as an ordinary + array with exactly two elements and accesses to elements beyond + the last are diagnosed regardless of whether they are within + the bounds the enclosing object. */ +struct S2 { char n, a[2]; }; +struct S3 { char n, a[3]; }; + + +void fx_ea1 (void) +{ + struct Sx *p = (struct Sx*)ea1; + p->n = 0; + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f0_ea1 (void) +{ + struct S0 *p = (struct S0*)ea1; + p->n = 0; + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f1_ea1 (void) +{ + struct S1 *p = (struct S1*)ea1; + p->n = 0; + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f2_ea1 (void) +{ + struct S2 *p = (struct S2*)ea1; + p->n = 0; + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f3_ea1 (void) +{ + struct S3 *p = (struct S3*)ea1; + p->n = 0; + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + + +void fx_ea1_p1 (void) +{ + struct Sx *p = (struct Sx*)(ea1 + 1); + p->n = 0; // { dg-warning "-Wstringop-overflow" } + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f0_ea1_p1 (void) +{ + struct S0 *p = (struct S0*)(ea1 + 1); + p->n = 0; // { dg-warning "-Wstringop-overflow" } + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f1_ea1_p1 (void) +{ + struct S1 *p = (struct S1*)(ea1 + 1); + p->n = 0; // { dg-warning "-Wstringop-overflow" } + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f2_ea1_p1 (void) +{ + struct S2 *p = (struct S2*)(ea1 + 1); + p->n = 0; // { dg-warning "-Wstringop-overflow" } + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f3_ea1_p1 (void) +{ + struct S3 *p = (struct S3*)(ea1 + 1); + p->n = 0; // { dg-warning "-Wstringop-overflow" } + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + + +void fx_ea2 (void) +{ + struct Sx *p = (struct Sx*)ea2; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f0_ea2 (void) +{ + struct S0 *p = (struct S0*)ea2; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f1_ea2 (void) +{ + struct S1 *p = (struct S1*)ea2; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f2_ea2 (void) +{ + struct S2 *p = (struct S2*)ea2; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f3_ea2 (void) +{ + struct S3 *p = (struct S3*)ea2; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + + +void fx_ea2_p1 (void) +{ + struct Sx *p = (struct Sx*)(ea2 + 1); + p->n = 0; + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f0_ea2_p1 (void) +{ + struct S0 *p = (struct S0*)(ea2 + 1); + p->n = 0; + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f1_ea2_p1 (void) +{ + struct S1 *p = (struct S1*)(ea2 + 1); + p->n = 0; + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f2_ea2_p1 (void) +{ + struct S2 *p = (struct S2*)(ea2 + 1); + p->n = 0; + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f3_ea2_p1 (void) +{ + struct S3 *p = (struct S3*)(ea2 + 1); + p->n = 0; + p->a[0] = 0; // { dg-warning "-Wstringop-overflow" } + p->a[1] = 1; // { dg-warning "-Wstringop-overflow" } + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + + +void fx_ea3 (void) +{ + struct Sx *p = (struct Sx*)ea3; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f0_ea3 (void) +{ + struct S0 *p = (struct S0*)ea3; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f1_ea3 (void) +{ + struct S1 *p = (struct S1*)ea3; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f2_ea3 (void) +{ + struct S2 *p = (struct S2*)ea3; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f3_ea3 (void) +{ + struct S3 *p = (struct S3*)ea3; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + + +void fx_ea4 (void) +{ + struct Sx *p = (struct Sx*)ea4; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; + p->a[2] = 2; + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f0_ea4 (void) +{ + struct S0 *p = (struct S0*)ea4; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; + p->a[2] = 2; + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f1_ea4 (void) +{ + struct S1 *p = (struct S1*)ea4; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; + p->a[2] = 2; + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f2_ea4 (void) +{ + struct S2 *p = (struct S2*)ea4; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; + /* Even though the offset of p->a[2] is within the bounds of EA4 + the warning triggers because it only considers trailing arrays + of at mnost one element as "poor man's flexible arrays." */ + p->a[2] = 2; // { dg-warning "-Wstringop-overflow" } + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +} + +void f3_ea4 (void) +{ + struct S3 *p = (struct S3*)ea4; + p->n = 0; + p->a[0] = 0; + p->a[1] = 1; + p->a[2] = 2; + p->a[3] = 3; // { dg-warning "-Wstringop-overflow" } +}