From patchwork Fri Aug 30 11:24:20 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Carlini X-Patchwork-Id: 271236 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 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "www.sourceware.org", Issuer "StartCom Class 1 Primary Intermediate Server CA" (not verified)) by ozlabs.org (Postfix) with ESMTPS id D575C2C00C3 for ; Fri, 30 Aug 2013 21:24:36 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; q=dns; s=default; b=KsBLSrNTlbPspH6jm sxmFooTbz4PF1ZJlkSz5V1iMdo/QLRShD1tTeT0yEvdyru4uQocRmHnDjf3acy2A aPjNpFIc/2EXEpdWhLv7wJAHiibJaElKy7d0pyCiGQ2k4ygieD9Pmwy5uiZeKvEk h8ajkUqhfQq+K8G1Ur23YrXNLU= 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 :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; s=default; bh=bG/wn/JHLsCczK9ACyprtrX +rdI=; b=i6LPfc4Bdzdhv+D4KUtPMwrlBWQOyV98xLNqb0zETpamgEBC9GrbLu0 aq+3Divet32l/wU6yuzDIQ5vXGMRCUr3LNXKIKT69CcaDJHcHFXr82xr+EzK0H7Y pqzwXGktP0CMPvc5vZL4slmomd2i2h+jotlfuZBEWtqTkebq0S/c= Received: (qmail 25630 invoked by alias); 30 Aug 2013 11:24:28 -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 25621 invoked by uid 89); 30 Aug 2013 11:24:28 -0000 Received: from aserp1040.oracle.com (HELO aserp1040.oracle.com) (141.146.126.69) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 30 Aug 2013 11:24:28 +0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-7.9 required=5.0 tests=AWL, BAYES_00, KHOP_THREADED, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, RP_MATCHES_RCVD, SPF_PASS, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 X-HELO: aserp1040.oracle.com Received: from ucsinet22.oracle.com (ucsinet22.oracle.com [156.151.31.94]) by aserp1040.oracle.com (Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.1) with ESMTP id r7UBONVx032603 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 30 Aug 2013 11:24:24 GMT Received: from aserz7021.oracle.com (aserz7021.oracle.com [141.146.126.230]) by ucsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r7UBOM2A029070 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 30 Aug 2013 11:24:23 GMT Received: from abhmt111.oracle.com (abhmt111.oracle.com [141.146.116.63]) by aserz7021.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r7UBOMax003703; Fri, 30 Aug 2013 11:24:22 GMT Received: from poldo4.casa (/79.36.29.22) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 30 Aug 2013 04:24:22 -0700 Message-ID: <522080E4.3050703@oracle.com> Date: Fri, 30 Aug 2013 13:24:20 +0200 From: Paolo Carlini User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130801 Thunderbird/17.0.8 MIME-Version: 1.0 To: Jason Merrill CC: "gcc-patches@gcc.gnu.org" Subject: Re: [C++ Patch] PR 51424 References: <521F67C1.20104@oracle.com> <521FA395.4070600@redhat.com> <522060B0.20801@oracle.com> In-Reply-To: <522060B0.20801@oracle.com> Hi again, On 08/30/2013 11:06 AM, Paolo Carlini wrote: > I could, for example pass down a separate bit, instead of playing > again with the LOOKUP_* bits. At some point yesterday I even had that > version tested ;) In practice, something like the attached. By the way, as regards this comment in cp-tree.h: /* These are uses as bits in flags passed to various functions to control their behavior. Despite the LOOKUP_ prefix, many of these do not control name lookup. ??? Functions using these flags should probably be modified to accept explicit boolean flags for the behaviors relevant to them. */ I think I could rather easily remove LOOKUP_ALREADY_DIGESTED, because it's only used between check_initializer and store_init_value. Thanks! Paolo. //////////////////////////// Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 202101) +++ cp/cp-tree.h (working copy) @@ -5359,7 +5359,7 @@ extern tree do_friend (tree, tree, tree, tree, /* in init.c */ extern tree expand_member_init (tree); extern void emit_mem_initializers (tree); -extern tree build_aggr_init (tree, tree, int, +extern tree build_aggr_init (tree, tree, int, bool, tsubst_flags_t); extern int is_class_type (tree, int); extern tree get_type_value (tree); Index: cp/decl.c =================================================================== --- cp/decl.c (revision 202101) +++ cp/decl.c (working copy) @@ -5539,7 +5539,8 @@ build_aggr_init_full_exprs (tree decl, tree init, { gcc_assert (stmts_are_full_exprs_p ()); - return build_aggr_init (decl, init, flags, tf_warning_or_error); + return build_aggr_init (decl, init, flags, /*delegating_cons_p=*/false, + tf_warning_or_error); } /* Verify INIT (the initializer for DECL), and record the Index: cp/init.c =================================================================== --- cp/init.c (revision 202101) +++ cp/init.c (working copy) @@ -32,8 +32,10 @@ along with GCC; see the file COPYING3. If not see static bool begin_init_stmts (tree *, tree *); static tree finish_init_stmts (bool, tree, tree); static void construct_virtual_base (tree, tree); -static void expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t); -static void expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t); +static void expand_aggr_init_1 (tree, tree, tree, tree, int, bool, + tsubst_flags_t); +static void expand_default_init (tree, tree, tree, tree, int, bool, + tsubst_flags_t); static void perform_member_init (tree, tree); static tree build_builtin_delete_call (tree); static int member_init_ok_or_else (tree, tree, tree); @@ -501,7 +503,8 @@ perform_target_ctor (tree init) tree type = current_class_type; finish_expr_stmt (build_aggr_init (decl, init, LOOKUP_NORMAL, - tf_warning_or_error)); + /*delegating_cons_p=*/true, + tf_warning_or_error)); if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) { tree expr = build_delete (type, decl, sfk_complete_destructor, @@ -693,6 +696,7 @@ perform_member_init (tree member, tree init) "uninitialized member %qD with % type %qT", member, type); finish_expr_stmt (build_aggr_init (decl, init, flags, + /*delegating_cons_p=*/false, tf_warning_or_error)); } } @@ -1076,6 +1080,7 @@ emit_mem_initializers (tree mem_inits) tf_warning_or_error), arguments, flags, + /*delegating_cons_p=*/false, tf_warning_or_error); expand_cleanup_for_base (subobject, NULL_TREE); } @@ -1242,7 +1247,7 @@ construct_virtual_base (tree vbase, tree arguments exp = convert_to_base_statically (current_class_ref, vbase); expand_aggr_init_1 (vbase, current_class_ref, exp, arguments, - 0, tf_warning_or_error); + 0, /*delegating_cons_p=*/false, tf_warning_or_error); finish_then_clause (inner_if_stmt); finish_if_stmt (inner_if_stmt); @@ -1448,7 +1453,8 @@ expand_member_init (tree name) perform the initialization, but not both, as it would be ambiguous. */ tree -build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) +build_aggr_init (tree exp, tree init, int flags, bool delegating_cons_p, + tsubst_flags_t complain) { tree stmt_expr; tree compound_stmt; @@ -1513,7 +1519,7 @@ tree destroy_temps = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = 0; expand_aggr_init_1 (TYPE_BINFO (type), exp, exp, - init, LOOKUP_NORMAL|flags, complain); + init, LOOKUP_NORMAL|flags, delegating_cons_p, complain); stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt); current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps; TREE_READONLY (exp) = was_const; @@ -1524,7 +1530,7 @@ tree static void expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, - tsubst_flags_t complain) + bool delegating_cons_p, tsubst_flags_t complain) { tree type = TREE_TYPE (exp); tree ctor_name; @@ -1641,6 +1647,14 @@ expand_default_init (tree binfo, tree true_exp, tr complete = build_special_member_call (exp, complete_ctor_identifier, &parms2, binfo, flags, complain); + + if ((complain & tf_error) + && delegating_cons_p + && TREE_CODE (complete) == CALL_EXPR + && (DECL_ABSTRACT_ORIGIN (TREE_OPERAND (CALL_EXPR_FN (complete), 0)) + == current_function_decl)) + error ("constructor delegates to itself"); + complete = fold_build_cleanup_point_expr (void_type_node, complete); release_tree_vector (parms2); @@ -1662,8 +1676,16 @@ expand_default_init (tree binfo, tree true_exp, tr ctor_name = base_ctor_identifier; rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags, complain); - } + if ((complain & tf_error) + && delegating_cons_p + && ctor_name == complete_ctor_identifier + && TREE_CODE (rval) == CALL_EXPR + && (DECL_ABSTRACT_ORIGIN (TREE_OPERAND (CALL_EXPR_FN (rval), 0)) + == current_function_decl)) + error ("constructor delegates to itself"); + } + if (parms != NULL) release_tree_vector (parms); @@ -1705,7 +1727,7 @@ expand_default_init (tree binfo, tree true_exp, tr static void expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, - tsubst_flags_t complain) + bool delegating_cons_p, tsubst_flags_t complain) { tree type = TREE_TYPE (exp); @@ -1762,7 +1784,8 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tre /* We know that expand_default_init can handle everything we want at this point. */ - expand_default_init (binfo, true_exp, exp, init, flags, complain); + expand_default_init (binfo, true_exp, exp, init, flags, delegating_cons_p, + complain); } /* Report an error if TYPE is not a user-defined, class type. If @@ -3497,7 +3520,9 @@ build_vec_init (tree base, tree maxindex, tree ini if (digested) one_init = build2 (INIT_EXPR, type, baseref, elt); else if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) - one_init = build_aggr_init (baseref, elt, 0, complain); + one_init = build_aggr_init (baseref, elt, 0, + /*delegating_cons_p=*/false, + complain); else one_init = cp_build_modify_expr (baseref, NOP_EXPR, elt, complain); @@ -3632,7 +3657,9 @@ build_vec_init (tree base, tree maxindex, tree ini elt_init = cp_build_modify_expr (to, NOP_EXPR, from, complain); else if (type_build_ctor_call (type)) - elt_init = build_aggr_init (to, from, 0, complain); + elt_init = build_aggr_init (to, from, 0, + /*delegating_cons_p=*/false, + complain); else if (from) elt_init = cp_build_modify_expr (to, NOP_EXPR, from, complain); @@ -3659,7 +3686,9 @@ build_vec_init (tree base, tree maxindex, tree ini { gcc_assert (type_build_ctor_call (type) || init); if (CLASS_TYPE_P (type)) - elt_init = build_aggr_init (to, init, 0, complain); + elt_init = build_aggr_init (to, init, 0, + /*delegating_cons_p=*/false, + complain); else { if (TREE_CODE (init) == TREE_LIST) Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 202101) +++ cp/semantics.c (working copy) @@ -3777,6 +3777,7 @@ simplify_aggr_init_expr (tree *tp) push_deferring_access_checks (dk_no_check); call_expr = build_aggr_init (slot, call_expr, DIRECT_BIND | LOOKUP_ONLYCONVERTING, + /*delegating_cons_p=*/false, tf_warning_or_error); pop_deferring_access_checks (); call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot); Index: testsuite/g++.dg/cpp0x/dc8.C =================================================================== --- testsuite/g++.dg/cpp0x/dc8.C (revision 0) +++ testsuite/g++.dg/cpp0x/dc8.C (working copy) @@ -0,0 +1,66 @@ +// PR c++/51424 +// { dg-do compile { target c++11 } } + +template +struct S +{ + S() : S() {} // { dg-error "delegates to itself" } + S(int x) : S(x) {} // { dg-error "delegates to itself" } +}; + +struct B1 +{ + B1() : B1() {} // { dg-error "delegates to itself" } + B1(int y) : B1(y) {} // { dg-error "delegates to itself" } +}; + +struct V1 : virtual B1 +{ + V1() : B1() {} + V1(int x) : B1(x) {} +}; + +struct B2 +{ + B2() : B2() {} // { dg-error "delegates to itself" } + B2(int y) : B2(y) {} // { dg-error "delegates to itself" } +}; + +struct V2 : virtual B2 +{ + V2() : V2() {} // { dg-error "delegates to itself" } + V2(int x) : V2(x) {} // { dg-error "delegates to itself" } +}; + +struct B3 +{ + B3() {} + B3(int y) {} +}; + +struct V3 : virtual B3 +{ + V3() : V3() {} // { dg-error "delegates to itself" } + V3(int x) : V3(x) {} // { dg-error "delegates to itself" } +}; + +struct CE1 +{ + constexpr CE1() : CE1() {} // { dg-error "delegates to itself" } + constexpr CE1(int x) : CE1(x) {} // { dg-error "delegates to itself" } +}; + +struct CEB2 +{ + constexpr CEB2() : CEB2() {} // { dg-error "delegates to itself" } + constexpr CEB2(int x) : CEB2(x) {} // { dg-error "delegates to itself" } +}; + +struct CE2 : CEB2 +{ + constexpr CE2() : CEB2() {} + constexpr CE2(int x) : CEB2(x) {} +}; + +S s1; +S s2(1); Index: testsuite/g++.dg/template/meminit1.C =================================================================== --- testsuite/g++.dg/template/meminit1.C (revision 202101) +++ testsuite/g++.dg/template/meminit1.C (working copy) @@ -3,6 +3,6 @@ template struct S { S() : S() {} // { dg-message "delegating constructors" } -}; +}; // { dg-error "delegates to itself" "" { target *-*-* } 5 } S s;