From patchwork Thu Aug 19 16:52:39 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 62201 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]) by ozlabs.org (Postfix) with SMTP id 47E4BB70E0 for ; Fri, 20 Aug 2010 02:52:51 +1000 (EST) Received: (qmail 3882 invoked by alias); 19 Aug 2010 16:52:47 -0000 Received: (qmail 3873 invoked by uid 22791); 19 Aug 2010 16:52:46 -0000 X-SWARE-Spam-Status: No, hits=-6.0 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_BF, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 19 Aug 2010 16:52:41 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o7JGqemN000754 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 19 Aug 2010 12:52:40 -0400 Received: from [IPv6:::1] (ovpn-113-45.phx2.redhat.com [10.3.113.45]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o7JGqdZZ003857 for ; Thu, 19 Aug 2010 12:52:40 -0400 Message-ID: <4C6D6157.3010106@redhat.com> Date: Thu, 19 Aug 2010 12:52:39 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.11) Gecko/20100814 Lightning/1.0b1 Shredder/3.0.7pre MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH to improve -Wnoexcept with templates 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 A noexcept testcase I got from someone on the C++ committee led me to notice that -Wnoexcept wasn't warning about non-throwing functions that aren't defined yet, including templates. This patch remembers such functions and checks them again at EOF. Tested x86_64-pc-linux-gnu, applied to trunk. commit 6630348bb4c308683991664058a972dca541a53f Author: Jason Merrill Date: Wed Aug 11 13:44:19 2010 -0400 * except.c (pending_noexcept, pending_noexcept_checks): New. (perform_deferred_noexcept_checks): New. (maybe_noexcept_warning): Split from... (finish_noexcept_expr): ...here. Adjust. * decl2.c (cp_write_global_declarations): Call perform_deferred_noexcept_checks. * cp-tree.h: And declare it. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index baa6656..dce28df 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4883,6 +4883,7 @@ extern tree build_throw (tree); extern int nothrow_libfn_p (const_tree); extern void check_handlers (tree); extern tree finish_noexcept_expr (tree, tsubst_flags_t); +extern void perform_deferred_noexcept_checks (void); extern bool nothrow_spec_p (const_tree); extern bool type_noexcept_p (const_tree); extern bool type_throw_all_p (const_tree); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index a768877..fed3452 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3934,6 +3934,8 @@ cp_write_global_declarations (void) VEC_length (tree, pending_statics)); } + perform_deferred_noexcept_checks (); + /* Generate hidden aliases for Java. */ if (candidates) { diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 79bab76..20b44e3 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1069,6 +1069,51 @@ check_noexcept_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, return NULL_TREE; } +/* If a function that causes a noexcept-expression to be false isn't + defined yet, remember it and check it for TREE_NOTHROW again at EOF. */ + +typedef struct GTY(()) pending_noexcept { + tree fn; + location_t loc; +} pending_noexcept; +DEF_VEC_O(pending_noexcept); +DEF_VEC_ALLOC_O(pending_noexcept,gc); +static GTY(()) VEC(pending_noexcept,gc) *pending_noexcept_checks; + +/* FN is a FUNCTION_DECL that caused a noexcept-expr to be false. Warn if + it can't throw. */ + +static void +maybe_noexcept_warning (tree fn) +{ + if (TREE_NOTHROW (fn)) + { + warning (OPT_Wnoexcept, "noexcept-expression evaluates to % " + "because of a call to %qD", fn); + warning (OPT_Wnoexcept, "but %q+D does not throw; perhaps " + "it should be declared %", fn); + } +} + +/* Check any functions that weren't defined earlier when they caused a + noexcept expression to evaluate to false. */ + +void +perform_deferred_noexcept_checks (void) +{ + int i; + pending_noexcept *p; + location_t saved_loc = input_location; + for (i = 0; + VEC_iterate (pending_noexcept, pending_noexcept_checks, i, p); + ++i) + { + input_location = p->loc; + maybe_noexcept_warning (p->fn); + } + input_location = saved_loc; +} + /* Evaluate noexcept ( EXPR ). */ tree @@ -1082,13 +1127,20 @@ finish_noexcept_expr (tree expr, tsubst_flags_t complain) fn = cp_walk_tree_without_duplicates (&expr, check_noexcept_r, 0); if (fn) { - if ((complain & tf_warning) && TREE_CODE (fn) == FUNCTION_DECL - && TREE_NOTHROW (fn) && !DECL_ARTIFICIAL (fn)) + if ((complain & tf_warning) && warn_noexcept + && TREE_CODE (fn) == FUNCTION_DECL) { - warning (OPT_Wnoexcept, "noexcept-expression evaluates to % " - "because of a call to %qD", fn); - warning (OPT_Wnoexcept, "but %q+D does not throw; perhaps " - "it should be declared %", fn); + if (!DECL_INITIAL (fn)) + { + /* Not defined yet; check again at EOF. */ + pending_noexcept *p + = VEC_safe_push (pending_noexcept, gc, + pending_noexcept_checks, NULL); + p->fn = fn; + p->loc = input_location; + } + else + maybe_noexcept_warning (fn); } return boolean_false_node; } diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept09.C b/gcc/testsuite/g++.dg/cpp0x/noexcept09.C new file mode 100644 index 0000000..2a4525c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept09.C @@ -0,0 +1,14 @@ +// Test that -Wnoexcept works with templates +// { dg-options "-std=c++0x -Wnoexcept" } + +template +T f (T t) { return t; } // { dg-warning "does not throw" } + +#define SA(X) static_assert(X, #X) + +SA (!noexcept(f(1))); // { dg-warning "noexcept" } + +int main() +{ + f(1); // Use f(int) so it gets instantiated +}