From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12735 invoked by alias); 21 Nov 2017 13:52:44 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 12713 invoked by uid 89); 21 Nov 2017 13:52:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-16.7 required=5.0 tests=BAYES_00,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KB_WAM_FROM_NAME_SINGLEWORD,SPF_HELO_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=sk:fprofil, spots, 95 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 21 Nov 2017 13:52:39 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D6DC580465; Tue, 21 Nov 2017 13:52:38 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-116-247.ams2.redhat.com [10.36.116.247]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C8B6D5D997; Tue, 21 Nov 2017 13:52:36 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id vALDqYEn030202; Tue, 21 Nov 2017 14:52:34 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id vALDqW4W030201; Tue, 21 Nov 2017 14:52:32 +0100 Date: Tue, 21 Nov 2017 13:57:00 -0000 From: Jakub Jelinek To: Richard Biener , Jason Merrill Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix up -Wreturn-type (PR c++/83045) Message-ID: <20171121135232.GW14653@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.7.1 (2016-10-04) X-IsSubscribed: yes X-SW-Source: 2017-11/txt/msg01891.txt.bz2 Hi! The C++ FE now emits __builtin_unreachable () with BUILTINS_LOCATION on spots that return from functions/methods returning non-void without proper return. This breaks the -Wreturn-type warning, because we then don't see any return stmt without argument on the edges to exit, instead we see those __builtin_unreachable () calls at the end of blocks without successors. I wonder if the C++ FE addition of __builtin_unreachable () shouldn't be done only if (optimize). Anyway, this patch tweaks tree-cfg.c so that it recognizes those __builtin_unreachable () calls and reports the -Wreturn-type warning in those cases too (warning in the FE would be too early, we need to optimize away unreachable code). Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? The patch regresses g++.dg/gomp/declare-simd-1.C, but given that it revealed a real bug, I'm not trying to work around it in the patch and will fix it up incrementally instead. 2017-11-21 Jakub Jelinek PR c++/83045 * tree-cfg.c (pass_warn_function_return::execute): Formatting fix. Also warn if seen __builtin_unreachable () call with BUILTINS_LOCATION. Use LOCATION_LOCUS when comparing against UNKNOWN_LOCATION. * c-c++-common/pr61405.c (fn0, fn1): Add return stmts. * c-c++-common/Wlogical-op-2.c (fn): Likewise. * g++.dg/debug/pr53466.C: Add -Wno-return-type to dg-options. * g++.dg/opt/combine.C: Likewise. * g++.dg/ubsan/return-3.C: Likewise. * g++.dg/pr59445.C: Likewise. * g++.dg/pr49847.C: Likewise. * g++.dg/ipa/pr61800.C: Likewise. * g++.dg/ipa/pr63470.C: Likewise. * g++.dg/ipa/pr68672-1.C: Likewise. * g++.dg/pr58438.C: Likewise. * g++.dg/torture/pr59265.C: Likewise. * g++.dg/tree-ssa/ssa-dse-2.C: Likewise. * g++.old-deja/g++.eh/catch13.C: Likewise. * g++.old-deja/g++.eh/crash1.C: Likewise. * g++.dg/tm/pr60004.C: Expect -Wreturn-type warning. * g++.dg/torture/pr55740.C: Likewise. * g++.dg/torture/pr43257.C: Likewise. * g++.dg/torture/pr64280.C: Likewise. * g++.dg/torture/pr54684.C: Likewise. * g++.dg/torture/pr56694.C: Likewise. * g++.dg/torture/pr68470.C: Likewise. * g++.dg/torture/pr60648.C: Likewise. * g++.dg/torture/pr71281.C: Likewise. * g++.dg/torture/pr52772.C: Add -Wno-return-type dg-additional-options. * g++.dg/torture/pr64669.C: Likewise. * g++.dg/torture/pr58369.C: Likewise. * g++.dg/torture/pr33627.C: Likewise. * g++.dg/torture/predcom-1.C: Add #pragma GCC diagnostic ignored "-Wreturn-type". * g++.dg/lto/20090221_0.C: Likewise. * g++.dg/lto/20091026-1_1.C: Likewise. * g++.dg/lto/pr54625-1_1.C: Likewise. * g++.dg/warn/pr83045.C: New test. --- gcc/tree-cfg.c.jj 2017-11-20 19:55:36.723814204 +0100 +++ gcc/tree-cfg.c 2017-11-21 11:04:35.594567992 +0100 @@ -9049,7 +9049,8 @@ pass_warn_function_return::execute (func if ((gimple_code (last) == GIMPLE_RETURN || gimple_call_builtin_p (last, BUILT_IN_RETURN)) && location == UNKNOWN_LOCATION - && (location = gimple_location (last)) != UNKNOWN_LOCATION + && ((location = LOCATION_LOCUS (gimple_location (last))) + != UNKNOWN_LOCATION) && !optimize) break; /* When optimizing, replace return stmts in noreturn functions @@ -9075,7 +9076,6 @@ pass_warn_function_return::execute (func without returning a value. */ else if (warn_return_type > 0 && !TREE_NO_WARNING (fun->decl) - && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (fun)->preds) > 0 && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fun->decl)))) { FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (fun)->preds) @@ -9087,13 +9087,43 @@ pass_warn_function_return::execute (func && !gimple_no_warning_p (last)) { location = gimple_location (last); - if (location == UNKNOWN_LOCATION) + if (LOCATION_LOCUS (location) == UNKNOWN_LOCATION) location = fun->function_end_locus; - warning_at (location, OPT_Wreturn_type, "control reaches end of non-void function"); + warning_at (location, OPT_Wreturn_type, + "control reaches end of non-void function"); TREE_NO_WARNING (fun->decl) = 1; break; } } + /* The C++ FE turns fallthrough from the end of non-void function + into __builtin_unreachable () call with BUILTINS_LOCATION. + Recognize those too. */ + basic_block bb; + if (!TREE_NO_WARNING (fun->decl)) + FOR_EACH_BB_FN (bb, fun) + if (EDGE_COUNT (bb->succs) == 0) + { + gimple *last = last_stmt (bb); + if (last + && (LOCATION_LOCUS (gimple_location (last)) + == BUILTINS_LOCATION) + && gimple_call_builtin_p (last, BUILT_IN_UNREACHABLE)) + { + gimple_stmt_iterator gsi = gsi_for_stmt (last); + gsi_prev_nondebug (&gsi); + gimple *prev = gsi_stmt (gsi); + if (prev == NULL) + location = UNKNOWN_LOCATION; + else + location = gimple_location (prev); + if (LOCATION_LOCUS (location) == UNKNOWN_LOCATION) + location = fun->function_end_locus; + warning_at (location, OPT_Wreturn_type, + "control reaches end of non-void function"); + TREE_NO_WARNING (fun->decl) = 1; + break; + } + } } return 0; } --- gcc/testsuite/c-c++-common/pr61405.c.jj 2014-09-25 08:40:33.000000000 +0200 +++ gcc/testsuite/c-c++-common/pr61405.c 2017-11-21 10:36:48.632950988 +0100 @@ -16,6 +16,7 @@ fn0 (struct S *s) case B: return 2; } + return 3; } int @@ -28,4 +29,5 @@ fn1 (TS *s) case B: return 2; } + return 3; } --- gcc/testsuite/c-c++-common/Wlogical-op-2.c.jj 2017-05-11 09:42:25.000000000 +0200 +++ gcc/testsuite/c-c++-common/Wlogical-op-2.c 2017-11-21 10:36:09.366433942 +0100 @@ -9,4 +9,5 @@ fn (int a, int b) return a; if ((a + 1) || (a + 1)) /* { dg-warning "logical .or. of equal expressions" } */ return b; + return -1; } --- gcc/testsuite/g++.dg/debug/pr53466.C.jj 2012-05-30 14:38:56.000000000 +0200 +++ gcc/testsuite/g++.dg/debug/pr53466.C 2017-11-21 10:31:35.176806840 +0100 @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-foptimize-sibling-calls -fcompare-debug" } +// { dg-options "-foptimize-sibling-calls -fcompare-debug -Wno-return-type" } typedef union gimple_statement_d *gimple; typedef gimple gimple_seq_node; --- gcc/testsuite/g++.dg/opt/combine.C.jj 2017-11-06 17:23:29.000000000 +0100 +++ gcc/testsuite/g++.dg/opt/combine.C 2017-11-21 10:35:21.190026482 +0100 @@ -1,5 +1,5 @@ // { dg-do assemble { target fpic } } -// { dg-options "-O2 -fweb -fPIC -fvisibility=hidden" } +// { dg-options "-O2 -fweb -fPIC -fvisibility=hidden -Wno-return-type" } // { dg-require-visibility "" } class QBasicAtomicInt --- gcc/testsuite/g++.dg/ubsan/return-3.C.jj 2014-06-30 15:36:41.000000000 +0200 +++ gcc/testsuite/g++.dg/ubsan/return-3.C 2017-11-21 11:44:14.659408989 +0100 @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-fsanitize=return" } +// { dg-options "-fsanitize=return -Wno-return-type" } struct S { S (); ~S (); }; --- gcc/testsuite/g++.dg/tm/pr60004.C.jj 2014-01-31 22:22:02.000000000 +0100 +++ gcc/testsuite/g++.dg/tm/pr60004.C 2017-11-21 10:58:38.785906602 +0100 @@ -7,4 +7,4 @@ int f() { if (a == 5) return 1; } -} +} // { dg-warning "control reaches end of non-void function" } --- gcc/testsuite/g++.dg/pr59445.C.jj 2013-12-14 12:54:54.000000000 +0100 +++ gcc/testsuite/g++.dg/pr59445.C 2017-11-21 10:33:12.702606799 +0100 @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -Wno-return-type" } */ template struct A; template struct A<_Tp *> { --- gcc/testsuite/g++.dg/pr49847.C.jj 2014-03-03 08:24:12.000000000 +0100 +++ gcc/testsuite/g++.dg/pr49847.C 2017-11-21 10:32:07.166413212 +0100 @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O -fnon-call-exceptions" } */ +/* { dg-options "-O -fnon-call-exceptions -Wno-return-type" } */ int f (float g) { try { return g >= 0; } --- gcc/testsuite/g++.dg/ipa/pr61800.C.jj 2014-09-08 22:12:49.000000000 +0200 +++ gcc/testsuite/g++.dg/ipa/pr61800.C 2017-11-21 10:33:48.363168195 +0100 @@ -1,7 +1,7 @@ /* PR ipa/61800 */ /* { dg-do compile } */ /* { dg-require-visibility "" } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -Wno-return-type" } */ #pragma GCC visibility push(hidden) class A --- gcc/testsuite/g++.dg/ipa/pr63470.C.jj 2017-11-06 17:23:55.000000000 +0100 +++ gcc/testsuite/g++.dg/ipa/pr63470.C 2017-11-21 10:34:10.975890073 +0100 @@ -1,6 +1,6 @@ /* PR ipa/63470.C */ /* { dg-do compile } */ -/* { dg-options "-O2 -finline-functions" } */ +/* { dg-options "-O2 -finline-functions -Wno-return-type" } */ class A { --- gcc/testsuite/g++.dg/ipa/pr68672-1.C.jj 2016-02-12 12:57:18.000000000 +0100 +++ gcc/testsuite/g++.dg/ipa/pr68672-1.C 2017-11-21 10:34:55.532342056 +0100 @@ -1,6 +1,6 @@ // PR ipa/68672 // { dg-do compile } -// { dg-options "-O -finline-small-functions -fpartial-inlining --param=partial-inlining-entry-probability=100" } +// { dg-options "-O -finline-small-functions -fpartial-inlining --param=partial-inlining-entry-probability=100 -Wno-return-type" } void f2 (void *); void *a; --- gcc/testsuite/g++.dg/pr58438.C.jj 2013-09-19 13:20:30.000000000 +0200 +++ gcc/testsuite/g++.dg/pr58438.C 2017-11-21 10:32:45.940936097 +0100 @@ -1,5 +1,5 @@ /* { dg-do compile { target i?86-*-* x86_64-*-* } } */ -/* { dg-options "-march=amdfam10 -O3 -fprofile-generate" } */ +/* { dg-options "-march=amdfam10 -O3 -fprofile-generate -Wno-return-type" } */ enum gimple_code {}; struct A { gimple_code code; --- gcc/testsuite/g++.dg/torture/pr55740.C.jj 2012-12-20 19:10:21.000000000 +0100 +++ gcc/testsuite/g++.dg/torture/pr55740.C 2017-11-21 11:35:21.633993637 +0100 @@ -16,4 +16,4 @@ bool IsValidPath( char const * filename if ( *run ) ++run; } -} +} // { dg-warning "control reaches end of non-void function" } --- gcc/testsuite/g++.dg/torture/pr52772.C.jj 2017-11-06 17:23:50.000000000 +0100 +++ gcc/testsuite/g++.dg/torture/pr52772.C 2017-11-21 11:33:30.642365525 +0100 @@ -1,4 +1,5 @@ // { dg-do compile } +// { dg-additional-options "-Wno-return-type" } typedef __SIZE_TYPE__ size_t; --- gcc/testsuite/g++.dg/torture/pr43257.C.jj 2010-03-16 09:06:57.000000000 +0100 +++ gcc/testsuite/g++.dg/torture/pr43257.C 2017-11-21 11:30:24.103671196 +0100 @@ -7,7 +7,7 @@ static void *func (int n) { void *p; if (p == 0) throw ::A (); -} +} // { dg-warning "control reaches end of non-void function" } static void *func (int n, B const &) { --- gcc/testsuite/g++.dg/torture/pr64280.C.jj 2015-12-16 09:02:08.000000000 +0100 +++ gcc/testsuite/g++.dg/torture/pr64280.C 2017-11-21 11:39:56.060601647 +0100 @@ -39,4 +39,4 @@ F::m_fn2 () else D (); A b; -} +} // { dg-warning "control reaches end of non-void function" } --- gcc/testsuite/g++.dg/torture/pr54684.C.jj 2013-06-01 14:47:21.000000000 +0200 +++ gcc/testsuite/g++.dg/torture/pr54684.C 2017-11-21 11:34:46.567427070 +0100 @@ -60,4 +60,4 @@ bool visit_ref_for_mod_analysis (gimple ((void)(__builtin_expect(!(index >= 0), 0) ? __builtin_unreachable(), 0 : 0)); ipa_set_param_used (info, index, true); } -} +} // { dg-warning "control reaches end of non-void function" } --- gcc/testsuite/g++.dg/torture/pr56694.C.jj 2013-04-02 20:24:33.000000000 +0200 +++ gcc/testsuite/g++.dg/torture/pr56694.C 2017-11-21 11:36:30.401143656 +0100 @@ -20,7 +20,7 @@ inline GVector& GVector::operator+= (con if (m_num != v.m_num) throw GException::vector_mismatch(m_num, v.m_num); for (int i = 0; i < m_num; ++i) m_data[i] += v.m_data[i]; -}; +}; // { dg-warning "control reaches end of non-void function" } void eval(GVector* m_gradient, GVector* vect_cpy_grad, int n) { #pragma omp sections --- gcc/testsuite/g++.dg/torture/predcom-1.C.jj 2012-10-16 13:15:45.000000000 +0200 +++ gcc/testsuite/g++.dg/torture/predcom-1.C 2017-11-21 11:43:31.231944472 +0100 @@ -1,6 +1,8 @@ /* Test for ICE in predictive commoning with empty loop header block on arm-none-linux-*. */ +#pragma GCC diagnostic ignored "-Wreturn-type" + struct Foo { double *ptr; --- gcc/testsuite/g++.dg/torture/pr64669.C.jj 2017-11-06 17:23:50.000000000 +0100 +++ gcc/testsuite/g++.dg/torture/pr64669.C 2017-11-21 11:40:51.720913669 +0100 @@ -1,3 +1,5 @@ +// { dg-additional-options "-Wno-return-type" } + typedef unsigned int source_location; typedef source_location location_t; extern void error_at (location_t, const char *, ...) --- gcc/testsuite/g++.dg/torture/pr59265.C.jj 2015-06-30 14:08:38.000000000 +0200 +++ gcc/testsuite/g++.dg/torture/pr59265.C 2017-11-21 11:38:14.931851627 +0100 @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-fprofile-use -std=gnu++11" } +// { dg-options "-fprofile-use -std=gnu++11 -Wno-return-type" } class A { int m_fn1() const; --- gcc/testsuite/g++.dg/torture/pr68470.C.jj 2015-12-02 07:57:22.000000000 +0100 +++ gcc/testsuite/g++.dg/torture/pr68470.C 2017-11-21 11:41:37.588346735 +0100 @@ -11,7 +11,7 @@ struct D { C *m_fn2() { if (a) __builtin_abort(); - } + } // { dg-warning "control reaches end of non-void function" } }; D getd(); --- gcc/testsuite/g++.dg/torture/pr58369.C.jj 2013-11-12 11:31:20.000000000 +0100 +++ gcc/testsuite/g++.dg/torture/pr58369.C 2017-11-21 11:37:25.892457767 +0100 @@ -1,4 +1,5 @@ // { dg-do compile } +// { dg-additional-options "-Wno-return-type" } // Reduced from boost-1.54 int pow(int, int); --- gcc/testsuite/g++.dg/torture/pr33627.C.jj 2017-11-06 17:23:50.000000000 +0100 +++ gcc/testsuite/g++.dg/torture/pr33627.C 2017-11-21 11:00:49.833313133 +0100 @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-additional-options "-Wno-return-type" } */ typedef unsigned int UT_uint32; typedef UT_uint32 PT_DocPosition; --- gcc/testsuite/g++.dg/torture/pr60648.C.jj 2014-03-29 12:05:44.000000000 +0100 +++ gcc/testsuite/g++.dg/torture/pr60648.C 2017-11-21 11:38:56.152342130 +0100 @@ -51,7 +51,7 @@ inline component fn2 (direction p1) case P: return component (3); } -} +} // { dg-warning "control reaches end of non-void function" } void fn3 () { --- gcc/testsuite/g++.dg/torture/pr71281.C.jj 2016-06-07 14:56:41.000000000 +0200 +++ gcc/testsuite/g++.dg/torture/pr71281.C 2017-11-21 11:42:13.215906450 +0100 @@ -47,7 +47,7 @@ public: reference m_fn3(unsigned){ if (m_fn2()) fn1(); - } + } // { dg-warning "control reaches end of non-void function" } }; H>> c; --- gcc/testsuite/g++.dg/lto/20090221_0.C.jj 2009-10-05 10:07:09.000000000 +0200 +++ gcc/testsuite/g++.dg/lto/20090221_0.C 2017-11-21 11:27:35.272757994 +0100 @@ -25,6 +25,7 @@ struct Baz Baz(Bar &a):a(a) { } }; +#pragma GCC diagnostic ignored "-Wreturn-type" struct Zonk { Baz baz; --- gcc/testsuite/g++.dg/lto/20091026-1_1.C.jj 2009-11-04 08:15:17.000000000 +0100 +++ gcc/testsuite/g++.dg/lto/20091026-1_1.C 2017-11-21 11:27:15.416003429 +0100 @@ -1,4 +1,6 @@ #include "20091026-1_a.h" + +#pragma GCC diagnostic ignored "-Wreturn-type" extern cHead networks; class cNetworkType; inline cNetworkType *findNetwork(const char *s) --- gcc/testsuite/g++.dg/lto/pr54625-1_1.C.jj 2014-05-11 22:21:17.000000000 +0200 +++ gcc/testsuite/g++.dg/lto/pr54625-1_1.C 2017-11-21 11:28:07.741356673 +0100 @@ -1,5 +1,6 @@ extern "C" double sin (double); typedef double UnaryFunType (double); +#pragma GCC diagnostic ignored "-Wreturn-type" class A { public: --- gcc/testsuite/g++.old-deja/g++.eh/catch13.C.jj 2008-09-05 12:54:57.000000000 +0200 +++ gcc/testsuite/g++.old-deja/g++.eh/catch13.C 2017-11-21 11:51:07.315320730 +0100 @@ -1,5 +1,5 @@ // { dg-do assemble } -// { dg-options "-O2" } +// { dg-options "-O2 -Wno-return-type" } // Copyright (C) 2001 Free Software Foundation, Inc. // Contributed by Jakub Jelinek 2 May 2001 --- gcc/testsuite/g++.old-deja/g++.eh/crash1.C.jj 2008-09-05 12:54:57.000000000 +0200 +++ gcc/testsuite/g++.old-deja/g++.eh/crash1.C 2017-11-21 11:51:26.115088919 +0100 @@ -1,5 +1,5 @@ // { dg-do assemble } -// { dg-options "-O1 -fno-inline-functions" } +// { dg-options "-O1 -fno-inline-functions -Wno-return-type" } struct A { --- gcc/testsuite/g++.dg/tree-ssa/ssa-dse-2.C.jj 2017-05-12 14:34:48.000000000 +0200 +++ gcc/testsuite/g++.dg/tree-ssa/ssa-dse-2.C 2017-11-21 14:38:25.336407998 +0100 @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-dse2-details" } */ +/* { dg-options "-O2 -fdump-tree-dse2-details -Wno-return-type" } */ typedef __SIZE_TYPE__ size_t; extern "C" --- gcc/testsuite/g++.dg/warn/pr83045.C.jj 2017-11-21 09:55:55.273188978 +0100 +++ gcc/testsuite/g++.dg/warn/pr83045.C 2017-11-21 09:55:55.273188978 +0100 @@ -0,0 +1,19 @@ +// PR c++/83045 +// { dg-do compile } +// { dg-options "-Wreturn-type -O2" } + +void foo (void); + +int +bar (int a) +{ + if (a != 0) + foo (); +} /* { dg-warning "no return statement in function returning non-void" } */ + +int +baz (int a) +{ + if (a != 0) + __builtin_abort (); +} /* { dg-warning "control reaches end of non-void function" } */ Jakub