From patchwork Tue Jun 22 04:26:58 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 56397 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 1D393B6EE9 for ; Tue, 22 Jun 2010 14:27:12 +1000 (EST) Received: (qmail 12458 invoked by alias); 22 Jun 2010 04:27:09 -0000 Received: (qmail 12447 invoked by uid 22791); 22 Jun 2010 04:27:07 -0000 X-SWARE-Spam-Status: No, hits=-5.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, 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; Tue, 22 Jun 2010 04:27:01 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o5M4Qxcn015723 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 22 Jun 2010 00:27:00 -0400 Received: from [IPv6:::1] (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o5M4QwQQ009496 for ; Tue, 22 Jun 2010 00:26:59 -0400 Message-ID: <4C203B92.8060401@redhat.com> Date: Tue, 22 Jun 2010 00:26:58 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.10) Gecko/20100619 Lightning/1.0b1 Shredder/3.0.6pre MIME-Version: 1.0 To: gcc-patches List Subject: C++0x PATCH to comparison of noexcept specifications 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 While working on implicit move constructors, I've been running the testsuite with -std=gnu++0x, which turned up a bug whereby overriding a base method which can throw any exception with a derived method which is noexcept was giving an error about a looser exception spec. Fixed thus. Tested x86_64-pc-linux-gnu, applied to trunk. commit cc07b6735584fe5ee4f692c05d7a0a6abe1a4dbd Author: Jason Merrill Date: Mon Jun 21 22:04:14 2010 -0400 * typeck.c (comp_except_specs): Fix ce_derived with noexcept. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index beef388..4383ef5 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -993,35 +993,37 @@ comp_except_specs (const_tree t1, const_tree t2, int exact) const_tree probe; const_tree base; int length = 0; - const_tree noexcept_spec = NULL_TREE; - const_tree other_spec; if (t1 == t2) return true; - /* First test noexcept compatibility. */ - if (t1 && TREE_PURPOSE (t1)) - noexcept_spec = t1, other_spec = t2; - else if (t2 && TREE_PURPOSE (t2)) - noexcept_spec = t2, other_spec = t1; - if (noexcept_spec) - { - tree p = TREE_PURPOSE (noexcept_spec); - /* Two noexcept-specs are equivalent iff their exprs are. */ - if (other_spec && TREE_PURPOSE (other_spec)) - return cp_tree_equal (p, TREE_PURPOSE (other_spec)); - /* noexcept(true) is compatible with throw(). */ - else if (exact < ce_exact && p == boolean_true_node) - return nothrow_spec_p (other_spec); - /* noexcept(false) is compatible with any throwing - dynamic-exception-spec. */ - else if (exact < ce_exact && p == boolean_false_node) - return !nothrow_spec_p (other_spec); - /* A dependent noexcept-spec is not compatible with any - dynamic-exception-spec. */ - else - return false; - } + /* First handle noexcept. */ + if (exact < ce_exact) + { + /* noexcept(false) is compatible with any throwing dynamic-exc-spec + and stricter than any spec. */ + if (t1 == noexcept_false_spec) + return !nothrow_spec_p (t2) || exact == ce_derived; + /* Even a derived noexcept(false) is compatible with a throwing + dynamic spec. */ + if (t2 == noexcept_false_spec) + return !nothrow_spec_p (t1); + + /* Otherwise, if we aren't looking for an exact match, noexcept is + equivalent to throw(). */ + if (t1 == noexcept_true_spec) + t1 = empty_except_spec; + if (t2 == noexcept_true_spec) + t2 = empty_except_spec; + } + + /* If any noexcept is left, it is only comparable to itself; + either we're looking for an exact match or we're redeclaring a + template with dependent noexcept. */ + if ((t1 && TREE_PURPOSE (t1)) + || (t2 && TREE_PURPOSE (t2))) + return (t1 && t2 + && cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2))); if (t1 == NULL_TREE) /* T1 is ... */ return t2 == NULL_TREE || exact == ce_derived; diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept08.C b/gcc/testsuite/g++.dg/cpp0x/noexcept08.C new file mode 100644 index 0000000..c450332 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept08.C @@ -0,0 +1,56 @@ +// { dg-options "-std=c++0x" } +// { dg-prune-output "overriding" } + +struct A +{ + virtual void f(); + virtual void g() throw(); + virtual void h() noexcept; + virtual void i() noexcept(false); + virtual void j() throw(int); +}; + +struct B: A +{ + void f() noexcept; + void g() noexcept; + void h() noexcept; + void i() noexcept; + void j() noexcept; +}; + +struct C: A +{ + void f() throw(); + void g() throw(); + void h() throw(); + void i() throw(); + void j() throw(); +}; + +struct D: A +{ + void f() noexcept(false); + void g() noexcept(false); // { dg-error "looser" } + void h() noexcept(false); // { dg-error "looser" } + void i() noexcept(false); + void j() noexcept(false); // compatible; treated as throw(int) +}; + +struct E: A +{ + void f() throw(int); + void g() throw(int); // { dg-error "looser" } + void h() throw(int); // { dg-error "looser" } + void i() throw(int); + void j() throw(int); +}; + +struct F: A +{ + void f(); + void g(); // { dg-error "looser" } + void h(); // { dg-error "looser" } + void i(); + void j(); // { dg-error "looser" } +};