From patchwork Tue Feb 20 02:50:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 875384 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-473573-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="cSmksN9r"; 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 3zllTy2SGyz9ryg for ; Tue, 20 Feb 2018 13:50:30 +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:from :subject:to:message-id:date:mime-version:content-type; q=dns; s= default; b=vg1FZMFXJxXPdDsXe3aJs5Kgi001jM+zJYYSNchq9qkJEC+TyHwSK i2wCyRad1Pf7UgGkppeCzO3vpBdh/6GQk9NjSKwYL6ZgBV2aLxzlvLUzPiA0Djdp 9aATfWUftV2k+VEJUtigbXtuuc7thAuXYNtkW5ydhVB4K3oPu/MQ1s= 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:from :subject:to:message-id:date:mime-version:content-type; s= default; bh=AoAa7r8Xt8jCb7A4M9BSEtl/gYA=; b=cSmksN9r6PKCuO3LeJ34 4otxrcixxvixm3fDMlOHXZutiBrMVbKpF22ig3LWc5wsTsS4DRE31RohIfdYQL6o qxcvLf4P2q8kP4rUPY4j2SkNUPK1BgR86wMkdKWSQkdUMl1k5fb+0YtGA931b1NX Yds1/ajkcLlJaWFYm6N3Vnw= Received: (qmail 86550 invoked by alias); 20 Feb 2018 02:50:23 -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 86443 invoked by uid 89); 20 Feb 2018 02:50:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.6 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=UD:Wstringop-truncation.c X-HELO: mail-oi0-f49.google.com Received: from mail-oi0-f49.google.com (HELO mail-oi0-f49.google.com) (209.85.218.49) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 20 Feb 2018 02:50:11 +0000 Received: by mail-oi0-f49.google.com with SMTP id u6so8489758oiv.9 for ; Mon, 19 Feb 2018 18:50:10 -0800 (PST) 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; bh=fXFIGLzvx0MkS6c6t6QTH85reSgCpdE07sgu1MLExtE=; b=aBybkzbH0+GMrUlWDZfpKJhTPaE2oT5SNd96juyDyg4hHGZTLd5M5pNU9+ZROoBiMX 8O859zn5AdwRqwIFcItVoRhYKtOf5bkS3Je9ySX3nDsKfvLL1kuE7OtoEee+zemQgAqG eBDuSfh/X1gyAmspVi5M7WHn4+Z9xH1W6H8M41cjWyURz6vMBYlI9O1AjOoDECD8O/FQ o9CKTx+iu0uucm4xNtxuUqebkLXfxUFp8/U0KUONexe8CP52xHXTPQKfAC2cVgrcf/ej N2vZ57OK+C3iq30GUjzZd+GvxMTMTl4OCRemGaXV4KJ+0oa2MVunFQ7UwLW9hBfBT9d8 j9Bg== X-Gm-Message-State: APf1xPBin6gECp3TloN6roArME3LMoHZbnlJjAQ7F6gA25hxpe07UlHc CKrI9vUs97q/VmCpd6n1pSKKdg== X-Google-Smtp-Source: AH8x22482quOw1ldI18kP2ygoBQZaUzr39nHu+ORW/wfISMGrHWrn7sAZsEv4SDxJmA8ZoJ/eJ0tMg== X-Received: by 10.202.242.214 with SMTP id q205mr6853039oih.255.1519095008867; Mon, 19 Feb 2018 18:50:08 -0800 (PST) Received: from localhost.localdomain (75-171-228-29.hlrn.qwest.net. [75.171.228.29]) by smtp.gmail.com with ESMTPSA id u202sm12615948oie.51.2018.02.19.18.50.06 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 19 Feb 2018 18:50:07 -0800 (PST) From: Martin Sebor Subject: [PATCH] consider successor blocks when avoiding -Wstringop-truncation (PR 84468) To: Gcc Patch List Message-ID: Date: Mon, 19 Feb 2018 19:50:04 -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 PR 84468 points out a false positive in -Wstringop-truncation in code like this: struct A { char a[4]; }; void f (struct A *p, const struct A *q) { if (p->a) strncpy (p->a, q->a, sizeof p->a - 1); // warning here p->a[3] = '\0'; } The warning is due to the code checking only the same basic block as the one with the strncpy call for an assignment to the destination to avoid it, but failing to check the successor basic block if there is no subsequent statement in the current block. (Eliminating the conditional is being tracked in PR 21474.) The attached test case adds logic to avoid this false positive. I don't know under what circumstances there could be more than one successor block here so I don't handle that case. Tested on x86_64-linux. Martin PR tree-optimization/84468 - bogus -Wstringop-truncation despite assignment after conditional strncpy gcc/testsuite/ChangeLog: PR tree-optimization/84468 * gcc.dg/Wstringop-truncation.c: New test. gcc/ChangeLog: PR tree-optimization/84468 * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Also consider successor basic blocks. Index: gcc/tree-ssa-strlen.c =================================================================== --- gcc/tree-ssa-strlen.c (revision 257796) +++ gcc/tree-ssa-strlen.c (working copy) @@ -1851,8 +1851,18 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi avoid the truncation warning. */ gsi_next_nondebug (&gsi); gimple *next_stmt = gsi_stmt (gsi); + if (!next_stmt) + { + /* When there is no statement in the same basic block check + the immediate successor block. */ + basic_block bb = gimple_bb (stmt); + basic_block nextbb + = EDGE_COUNT (bb->succs) ? EDGE_SUCC (bb, 0)->dest : NULL; + gimple_stmt_iterator it = gsi_start_bb (nextbb); + next_stmt = gsi_stmt (it); + } - if (!gsi_end_p (gsi) && is_gimple_assign (next_stmt)) + if (next_stmt && is_gimple_assign (next_stmt)) { tree lhs = gimple_assign_lhs (next_stmt); tree_code code = TREE_CODE (lhs); Index: gcc/testsuite/gcc.dg/Wstringop-truncation.c =================================================================== --- gcc/testsuite/gcc.dg/Wstringop-truncation.c (nonexistent) +++ gcc/testsuite/gcc.dg/Wstringop-truncation.c (working copy) @@ -0,0 +1,116 @@ +/* PR tree-optimization/84468 - Inconsistent -Wstringop-truncation warnings + with -O2 + { dg-do compile } + { dg-options "-O2 -Wstringop-truncation -ftrack-macro-expansion=0" } */ + +#define strncpy __builtin_strncpy + +struct A +{ + char a[4]; +}; + +void no_pred_succ (struct A *p, const struct A *q) +{ + strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */ +} + + +void no_succ (struct A *p, const struct A *q) +{ + if (q->a) + strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */ +} + + +void succ (struct A *p, const struct A *q) +{ + /* Verify that the assignment suppresses the warning for the conditional + strcnpy call. The conditional should be folded to true since the + address of an array can never be null (see bug 84470). */ + if (q->a) + strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-bogus "\\\[-Wstringop-truncation" } */ + + p->a[sizeof p->a - 1] = 0; +} + + +void succ_2 (struct A *p, const struct A *q, int i) +{ + /* Same as above but with a conditional that cannot be eliminated. */ + if (i < 0) + strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-bogus "\\\[-Wstringop-truncation" } */ + + p->a[sizeof p->a - 1] = 0; +} + + +int next_succ (struct A *p, const struct A *q, int i, int j) +{ + /* Same as above but with a nested conditionals with else clauses. */ + if (i < 0) + { + if (j < 0) + strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-bogus "\\\[-Wstringop-truncation" } */ + } + else + __builtin_strcpy (p->a, q->a); + + p->a[sizeof p->a - 1] = 0; + return 0; +} + + +int next_succ_1 (struct A *p, const struct A *q, int i, int j) +{ + /* Same as above but with a nested conditionals with else clauses. */ + if (i < 0) + { + if (j < 0) + strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-bogus "\\\[-Wstringop-truncation" } */ + else + strncpy (p->a, q->a, sizeof p->a - 2); /* { dg-bogus "\\\[-Wstringop-truncation" } */ + } + + p->a[sizeof p->a - 2] = 0; + return 1; +} + + +int next_succ_2 (struct A *p, const struct A *q, int i, int j) +{ + /* Same as above but with a nested conditionals with else clauses. */ + if (i < 0) + { + if (j < 0) + strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-bogus "\\\[-Wstringop-truncation" } */ + else + strncpy (p->a, q->a, sizeof p->a - 2); /* { dg-bogus "\\\[-Wstringop-truncation" } */ + } + else + __builtin_strcpy (p->a, q->a); + + p->a[sizeof p->a - 2] = 0; + return 2; +} + + +void cond_succ_warn (struct A *p, const struct A *q, int i) +{ + /* Verify that a conditional assignment doesn't suppress the warning. */ + strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */ + + if (i < 0) + p->a[sizeof p->a - 1] = 0; +} + +void cond_succ_nowarn (struct A *p, const struct A *q) +{ + /* Verify that distinct but provably equivalent conditionals are + recognized and don't trigger the warning. */ + if (p != q) + strncpy (p->a, q->a, sizeof p->a - 1); + + if (p->a != q->a) + p->a[sizeof p->a - 1] = 0; +}