From patchwork Wed Sep 14 16:10:46 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Edlinger X-Patchwork-Id: 669973 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 3sZ64247qzz9sDG for ; Thu, 15 Sep 2016 02:11:29 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=r6BVzHel; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:references:in-reply-to:content-type :mime-version; q=dns; s=default; b=n9ZM7bApuQHAwA6n+bE7NH8DtD5FR NeSi6IKy9XbUlPGgnYbXMDmRTuyHByA4v6epLrsYq+PisLM3mvBvkLhrkwAsYXFr cSY3fbB/XekrM3BrBWy9CpVfEINjbMTkdJHO2cV/FqDbqltzLYDqKP386WJGdDMD hRFUyYMisOte18= 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 :to:subject:date:message-id:references:in-reply-to:content-type :mime-version; s=default; bh=ZRMuD09l7rkspHC+OuzaIrFBuW4=; b=r6B VzHelsN1W5iVBGFU0tdsxAgSmLr5F1vNJZOJh6yfg0bsvgn1ujiUZfmaVaZobSpg 0YjLCJikfEyPDy4L+mPBE766tRYkGAEKz6DFhdqDxA4B+HINTgxgFkjJmdYy/zqh suE/K3EgeydMQzwzNsTAYXyVothbfrcsHZMlNqY0= Received: (qmail 109762 invoked by alias); 14 Sep 2016 16:11:16 -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 109743 invoked by uid 89); 14 Sep 2016 16:11:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=no version=3.3.2 spammy=UD:cl, H*c:sk:HMHPRHH, Hx-spam-relays-external:65.54.190.124, H*RU:sk:bay004- X-Spam-User: qpsmtpd, 2 recipients X-HELO: BAY004-OMC2S22.hotmail.com Received: from bay004-omc2s22.hotmail.com (HELO BAY004-OMC2S22.hotmail.com) (65.54.190.97) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 14 Sep 2016 16:11:05 +0000 Received: from EUR01-HE1-obe.outbound.protection.outlook.com ([65.54.190.124]) by BAY004-OMC2S22.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.23008); Wed, 14 Sep 2016 09:11:03 -0700 Received: from VE1EUR01FT007.eop-EUR01.prod.protection.outlook.com (10.152.2.58) by VE1EUR01HT110.eop-EUR01.prod.protection.outlook.com (10.152.3.75) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.619.6; Wed, 14 Sep 2016 16:10:46 +0000 Received: from AM4PR0701MB2162.eurprd07.prod.outlook.com (10.152.2.54) by VE1EUR01FT007.mail.protection.outlook.com (10.152.2.88) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.619.6 via Frontend Transport; Wed, 14 Sep 2016 16:10:46 +0000 Received: from AM4PR0701MB2162.eurprd07.prod.outlook.com ([10.167.132.147]) by AM4PR0701MB2162.eurprd07.prod.outlook.com ([10.167.132.147]) with mapi id 15.01.0619.011; Wed, 14 Sep 2016 16:10:46 +0000 From: Bernd Edlinger To: Jeff Law , "gcc-patches@gcc.gnu.org" , Joseph Myers , "Jason Merrill" , "fortran@gcc.gnu.org" Subject: [PATCH, updated] Add a warning for suspicious use of conditional expressions in boolean context Date: Wed, 14 Sep 2016 16:10:46 +0000 Message-ID: References: <4fd68972-b48b-560a-b8e2-ae7d607b9b87@redhat.com> <48602fe1-c295-fce5-a6fe-e7e259532f44@redhat.com> In-Reply-To: authentication-results: spf=softfail (sender IP is 10.152.2.54) smtp.mailfrom=hotmail.de; redhat.com; dkim=none (message not signed) header.d=none; redhat.com; dmarc=none action=none header.from=hotmail.de; received-spf: SoftFail (protection.outlook.com: domain of transitioning hotmail.de discourages use of 10.152.2.54 as permitted sender) x-ms-exchange-messagesentrepresentingtype: 1 x-eopattributedmessage: 0 x-microsoft-exchange-diagnostics: 1; VE1EUR01HT110; 6:6ONmWVe5JIojlTIh+a7IVslPIKZ5b+/wsY/2qotbH4lUhOyaqZzZA1HFHSnq0bJ5b2580+MnFdjFB3EtA0TJV/5hf8ZJA4R2QhWBIKOshPY8VLYjVUDliApLa4lHky20t4Gs/6/xiXsXR1eQ3gaN4hgw8t43+8plnGhhOD4vQOCvyeaaBM/MGGzP3JcxKhusjmRbtDahQ8Q2cPNEFwaYqr0TnXN4GAbBqaBVp3hQ81SW3DmG/VtmbZFPw6UVLQ/3T0qAEZON9tFPx8n504Lus2fhWsepdgthTd9r8mbdD5yv/BKKwKiVQg45yOlGa3MK; 5:KB954g+cx4OdvKkOIc72Q6UuJ8E/j8cX31AoEvYlJcUGNYZy7U4rEknI+9BqRZQ7nqmMW6FtvLMdMdBR3TIU+opT5I2iumgAhMj8uiBqCyjIDKZ+ALofTceZGBr4IRplLqKeYgewmT6smrhbtKMVNg==; 24:jB3FjNEaytAOtziwP1Sa4J7ANCpLWW7LtLlMTOg1MHHtPwAuSxXQvrU1JXT66Gr4cadwaRObkZ7Ie1lQW+i5AqWU/Ku+1Eeo24SiZZpjCLQ=; 7:LjY13TwA+BSv8ueG6byaWnbZJSX5TykfvX8PN8lg9jmrRhFCkb1ErMJSMqzK5YlLVjRxb39jmc79BfqwD1ZWaLoOIXAgPQ4sNXZUDB6SckjRV+SsFwjIiBi22doS54jUpgpIAi3fqFKY46bs30KuPgJ4QY30xanorm1kvTEuhR2lv6XyQpRpwmHSeIvjI65sj8DcVrfP2QjsWH3pXx72vNzl1JNf0pWDcsA0O100jXO6qlMCmJWVi5RAFZjIM9m6 x-forefront-antispam-report: EFV:NLI; SFV:NSPM; SFS:(10019020)(98900003); DIR:OUT; SFP:1102; SCL:1; SRVR:VE1EUR01HT110; H:AM4PR0701MB2162.eurprd07.prod.outlook.com; FPR:; SPF:None; LANG:en; x-ms-office365-filtering-correlation-id: 1d1c6128-9d69-45b3-39f6-08d3dcb9aecd x-microsoft-antispam: UriScan:; BCL:0; PCL:0; RULEID:(1601124038)(1603103081)(1601125047); SRVR:VE1EUR01HT110; x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(432015012)(102415321)(82015046); SRVR:VE1EUR01HT110; BCL:0; PCL:0; RULEID:; SRVR:VE1EUR01HT110; x-forefront-prvs: 006546F32A spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-originalarrivaltime: 14 Sep 2016 16:10:46.1498 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Internet X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-Transport-CrossTenantHeadersStamped: VE1EUR01HT110 Hi Jeff, it turned out, that the changed symmetric condition in the warning hit at several places, but also caused two false positives which I had to address first. I tried also building a recent glibc, which hit a false positive when using __builtin_isinf_sign in boolean context, which is used extensively by glibc. Furtunately there were zero new warnings in linux, well done Linus ;) glibc's math.h has this definition: # if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ # define isinf(x) __builtin_isinf_sign (x) and __builtin_isinf_sign(x) is internally folded as isinf(x) ? (signbit(x) ? -1 : 1) : 0 which can trigger the warning if used in a boolean context. We do not want to warn for if (isinf(x)) of course. The other false positive was in dwarf2out, where we have this: ../../gcc-trunk/gcc/dwarf2out.c:26166:35: error: ?: using integer constants in boolean context [-Werror=int-in-bool-context] if (s->refcount == ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) ? 1 : 2)) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~ and: #define DEBUG_STR_SECTION_FLAGS \ (HAVE_GAS_SHF_MERGE && flag_merge_debug_strings \ ? SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1 \ : SECTION_DEBUG) which got folded in C++ to if (s->refcount == ((flag_merge_debug_strings ? SECTION_MERGE : 0) ? 1 : 2)) Because SECTION_MERGE = 0x08000, the condition for the warning is satisfied here, but that is only an artifact that is created by the folding of the outer COND_EXPR. Additional to what you suggested, I relaxed the condition even more, because I think it is also suspicious, if one of the branches is known to be outside [0:1] and the other is unknown. That caused another warning in the fortran FE, which was caused by wrong placement of braces in gfc_simplify_repeat. We have: #define mpz_sgn(Z) ((Z)->size < 0 ? -1 : (Z)->size > 0) Therefore the condition must be .. && mpz_sgn(X) != 0) Previously that did not match, because -1 is outside [0:1] but (Z)->size > 0 is unknown. To suppress the bogus C++ warnings I had to suppress the warning when the condition is fully folded in cp_convert_and_check and c_common_truthvalue_conversion is called for the second time. To suppress the bogus C warning on __builtin_isinf_sign I found no other way than changing the expansion of that to isinf(x) ? (signbit(x) ? -1 : 1) + 0 : 0 which is just enough to hide the inner COND_EXPR from c_common_truthvalue_conversion, but gets immediately folded away by fold_binary so it will cause no different code. Furthermore the C++ test case df-warn-signedunsigned1.C also triggered the warning, because here we have: #define MAK (fl < 0 ? 1 : (fl ? -1 : 0)) And thus "if (MAK)" should be written as if (MAK != 0) Finally, what I already wrote in my previous mail the macros in gensupport.c mix binary and ternary logic and should be cleaned up. Bootstrap and reg-test with all languages on x86_64-pc-linux-gnu. Is it OK for trunk? Thanks Bernd. gcc: 2016-09-14 Bernd Edlinger PR c++/77434 * doc/invoke.texi: Document -Wcond-in-bool-context. * gensupport.c (TRISTATE_AND, TRISTATE_OR, TRISTATE_NOT): Fix a warning. * tree.h (integer_zerop_or_onep): New helper function. PR middle-end/77421 * dwarf2out.c (output_loc_operands): Fix an assertion. c-family: 2016-09-14 Bernd Edlinger PR c++/77434 * c.opt (Wcond-in-bool-context): New warning. * c-common.c (c_common_truthvalue_conversion): Warn on integer constants in boolean context. cp: 2016-09-14 Bernd Edlinger PR c++/77434 * cvt.c (cp_convert_and_check): Suppress Wint-in-bool-context here. fortran: 2016-09-14 Bernd Edlinger PR c++/77434 * simplify.c (gfc_simplify_repeat): Fix a warning. testsuite: 2016-09-14 Bernd Edlinger PR c++/77434 * c-c++-common/Wcond-in-bool-context.c: New test. * g++.dg/delayedfold/df-warn-signedunsigned1.C: Fix a warning. Index: gcc/builtins.c =================================================================== --- gcc/builtins.c (revision 240135) +++ gcc/builtins.c (working copy) @@ -7887,15 +7887,18 @@ fold_builtin_classify (location_t loc, tree fndecl tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg); signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node, - signbit_call, integer_zero_node); + signbit_call, integer_zero_node); isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node, - isinf_call, integer_zero_node); + isinf_call, integer_zero_node); - tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call, - integer_minus_one_node, integer_one_node); tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, - isinf_call, tmp, - integer_zero_node); + signbit_call, integer_minus_one_node, + integer_one_node); + /* Avoid a possible -Wint-in-bool-context warning in C. */ + tmp = fold_build2_loc (loc, PLUS_EXPR, integer_type_node, tmp, + integer_zero_node); + tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, + isinf_call, tmp, integer_zero_node); } return tmp; Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 240135) +++ gcc/c-family/c-common.c (working copy) @@ -4652,6 +4652,17 @@ c_common_truthvalue_conversion (location_t locatio TREE_OPERAND (expr, 0)); case COND_EXPR: + if (warn_int_in_bool_context) + { + tree val1 = fold_for_warn (TREE_OPERAND (expr, 1)); + tree val2 = fold_for_warn (TREE_OPERAND (expr, 2)); + if ((TREE_CODE (val1) == INTEGER_CST + && !integer_zerop_or_onep (val1)) + || (TREE_CODE (val2) == INTEGER_CST + && !integer_zerop_or_onep (val2))) + warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context, + "?: using integer constants in boolean context"); + } /* Distribute the conversion into the arms of a COND_EXPR. */ if (c_dialect_cxx ()) { Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 240135) +++ gcc/c-family/c.opt (working copy) @@ -545,6 +545,10 @@ Wint-conversion C ObjC Var(warn_int_conversion) Init(1) Warning Warn about incompatible integer to pointer and pointer to integer conversions. +Wint-in-bool-context +C ObjC C++ ObjC++ Var(warn_int_in_bool_context) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) +Warn for suspicious integer expressions in boolean context. + Wint-to-pointer-cast C ObjC C++ ObjC++ Var(warn_int_to_pointer_cast) Init(1) Warning Warn when there is a cast to a pointer from an integer of a different size. Index: gcc/cp/cvt.c =================================================================== --- gcc/cp/cvt.c (revision 240135) +++ gcc/cp/cvt.c (working copy) @@ -645,6 +645,7 @@ cp_convert_and_check (tree type, tree expr, tsubst { /* Avoid bogus -Wparentheses warnings. */ warning_sentinel w (warn_parentheses); + warning_sentinel c (warn_int_in_bool_context); folded_result = cp_convert (type, folded, tf_none); } folded_result = fold_simple (folded_result); Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 240135) +++ gcc/doc/invoke.texi (working copy) @@ -273,7 +273,7 @@ Objective-C and Objective-C++ Dialects}. -Wframe-larger-than=@var{len} -Wno-free-nonheap-object -Wjump-misses-init @gol -Wignored-qualifiers -Wignored-attributes -Wincompatible-pointer-types @gol -Wimplicit -Wimplicit-function-declaration -Wimplicit-int @gol --Winit-self -Winline -Wno-int-conversion @gol +-Winit-self -Winline -Wno-int-conversion -Wint-in-bool-context @gol -Wno-int-to-pointer-cast -Winvalid-memory-model -Wno-invalid-offsetof @gol -Winvalid-pch -Wlarger-than=@var{len} @gol -Wlogical-op -Wlogical-not-parentheses -Wlong-long @gol @@ -5837,6 +5837,14 @@ warning about it. The restrictions on @code{offsetof} may be relaxed in a future version of the C++ standard. +@item -Wint-in-bool-context +@opindex Wint-in-bool-context +@opindex Wno-int-in-bool-context +Warn for suspicious use of integer values where boolean values are expected, +such as conditional expressions (?:) using non-boolean integer constants in +boolean context, like @code{if (a <= b ? 2 : 3)}. +This warning is enabled by @option{-Wall}. + @item -Wno-int-to-pointer-cast @opindex Wno-int-to-pointer-cast @opindex Wint-to-pointer-cast Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c (revision 240135) +++ gcc/dwarf2out.c (working copy) @@ -2051,9 +2051,9 @@ output_loc_operands (dw_loc_descr_ref loc, int for /* Make sure the offset has been computed and that we can encode it as an operand. */ gcc_assert (die_offset > 0 - && die_offset <= (loc->dw_loc_opc == DW_OP_call2) + && die_offset <= (loc->dw_loc_opc == DW_OP_call2 ? 0xffff - : 0xffffffff); + : 0xffffffff)); dw2_asm_output_data ((loc->dw_loc_opc == DW_OP_call2) ? 2 : 4, die_offset, NULL); } Index: gcc/fortran/simplify.c =================================================================== --- gcc/fortran/simplify.c (revision 240135) +++ gcc/fortran/simplify.c (working copy) @@ -5127,7 +5127,7 @@ gfc_simplify_repeat (gfc_expr *e, gfc_expr *n) if (len || (e->ts.u.cl->length && - mpz_sgn (e->ts.u.cl->length->value.integer)) != 0) + mpz_sgn (e->ts.u.cl->length->value.integer) != 0)) { const char *res = gfc_extract_int (n, &ncop); gcc_assert (res == NULL); Index: gcc/gensupport.c =================================================================== --- gcc/gensupport.c (revision 240135) +++ gcc/gensupport.c (working copy) @@ -201,15 +201,15 @@ add_implicit_parallel (rtvec vec) #define TRISTATE_AND(a,b) \ ((a) == I ? ((b) == N ? N : I) : \ (b) == I ? ((a) == N ? N : I) : \ - (a) && (b)) + (a) == Y && (b) == Y ? Y : N) #define TRISTATE_OR(a,b) \ ((a) == I ? ((b) == Y ? Y : I) : \ (b) == I ? ((a) == Y ? Y : I) : \ - (a) || (b)) + (a) == Y || (b) == Y ? Y : N) #define TRISTATE_NOT(a) \ - ((a) == I ? I : !(a)) + ((a) == I ? I : (a) == Y ? N : Y) /* 0 means no warning about that code yet, 1 means warned. */ static char did_you_mean_codes[NUM_RTX_CODE]; Index: gcc/testsuite/c-c++-common/Wint-in-bool-context.c =================================================================== --- gcc/testsuite/c-c++-common/Wint-in-bool-context.c (revision 0) +++ gcc/testsuite/c-c++-common/Wint-in-bool-context.c (working copy) @@ -0,0 +1,32 @@ +/* PR c++/77434 */ +/* { dg-options "-Wint-in-bool-context" } */ +/* { dg-do compile } */ + +int foo (int a, int b) +{ + if (a > 0 && a <= (b == 1) ? 1 : 2) /* { dg-warning "boolean context" } */ + return 1; + + if (a > 0 && a <= (b == 2) ? 1 : 1) /* { dg-bogus "boolean context" } */ + return 2; + + if (a > 0 && a <= (b == 3) ? 0 : 2) /* { dg-warning "boolean context" } */ + return 3; + + if (a == (((b == 3) ? 1|2|4 : 1) & 2 ? 0 : 2)) /* { dg-bogus "boolean context" } */ + return 4; + + if (a <= b ? 1000-1 : 0 && (!a || !b)) /* { dg-warning "boolean context" } */ + return 5; + + if (a ? a : 1+1) /* { dg-warning "boolean context" } */ + return 6; + + if (a ? b : 0) /* { dg-bogus "boolean context" } */ + return 7; + + if (__builtin_isinf_sign ((float)a/b)) /* { dg-bogus "boolean context" } */ + return 8; + + return 0; +} Index: gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C =================================================================== --- gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C (revision 240135) +++ gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C (working copy) @@ -7,7 +7,7 @@ extern int fl; int foo (int sz) { - if (MAK) return 1; + if (MAK != 0) return 1; return 0; } Index: gcc/tree.h =================================================================== --- gcc/tree.h (revision 240135) +++ gcc/tree.h (working copy) @@ -4361,6 +4361,15 @@ extern int integer_nonzerop (const_tree); extern int integer_truep (const_tree); +/* integer_zerop_or_onep (tree x) is nonzero if X is an integer constant + of value 0 or 1. */ + +static inline int +integer_zerop_or_onep (const_tree x) +{ + return integer_zerop (x) || integer_onep (x); +} + extern bool cst_and_fits_in_hwi (const_tree); extern tree num_ending_zeros (const_tree);