From patchwork Wed Mar 30 18:05:23 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 88943 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 854ADB6F10 for ; Thu, 31 Mar 2011 05:05:37 +1100 (EST) Received: (qmail 7701 invoked by alias); 30 Mar 2011 18:05:35 -0000 Received: (qmail 7689 invoked by uid 22791); 30 Mar 2011 18:05:34 -0000 X-SWARE-Spam-Status: No, hits=-6.3 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; Wed, 30 Mar 2011 18:05:26 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p2UI5Pjt001648 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 30 Mar 2011 14:05:25 -0400 Received: from [127.0.0.1] (ovpn-113-113.phx2.redhat.com [10.3.113.113]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p2UI5OfD000664 for ; Wed, 30 Mar 2011 14:05:24 -0400 Message-ID: <4D9370E3.9010602@redhat.com> Date: Wed, 30 Mar 2011 14:05:23 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.15) Gecko/20110307 Fedora/3.1.9-0.39.b3pre.fc14 Lightning/1.0b2 Thunderbird/3.1.9 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/48281 (ICE with nested initializer_list) 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 The testcase in 48281 started breaking in 4.6.0 because of my change to finish_compound_literal to stop putting constant compound literals into static variables, because it was interfering with constexpr. First I noticed that the crash was due to non-constant CONSTRUCTORs with TREE_CONSTANT set. So I fixed that, in constructor-const.patch. That change fixed the crash, but then we were just optimizing away the entire contents of the lists due to a bug I just filed as PR 48370. Fixing the bug in general will mean fixing 48370, but we can fix the regression by just reverting the change above; I dealt with a similar issue elsewhere by setting DECL_DECLARED_CONSTEXPR_P on the temporary variable so that constexpr evaluation can look at its initializer, so we can use the same approach here. I'm only doing this for arrays now so that we can continue to elide copies of class temporaries. While I was looking at this stuff, I decided to go ahead and initialize the initializer_list objects directly rather than mess with calling the constructor. Tested x86_64-pc-linux-gnu, applying to trunk (all three patches) and 4.6 (only the first patch). commit 15ce1df0c9f6259babc885e8947719a586a47103 Author: Jason Merrill Date: Wed Mar 30 11:57:50 2011 -0400 PR c++/48281 * semantics.c (finish_compound_literal): Do put static/constant arrays in static variables. commit 4069e2ded787088dcf1d4caf1aeccd26e00524c0 Author: Jason Merrill Date: Wed Mar 30 10:34:09 2011 -0400 * call.c (convert_like_real) [ck_list]: Build up the initializer_list object directly. * decl.c (build_init_list_var_init): Adjust. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index f7d108f..ad2de43 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5467,8 +5467,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (totype), 0); tree new_ctor = build_constructor (init_list_type_node, NULL); unsigned len = CONSTRUCTOR_NELTS (expr); - tree array, val; - VEC(tree,gc) *parms; + tree array, val, field; + VEC(constructor_elt,gc) *vec = NULL; unsigned ix; /* Convert all the elements. */ @@ -5490,16 +5490,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, array = build_array_of_n_type (elttype, len); array = finish_compound_literal (array, new_ctor); - parms = make_tree_vector (); - VEC_safe_push (tree, gc, parms, decay_conversion (array)); - VEC_safe_push (tree, gc, parms, size_int (len)); - /* Call the private constructor. */ - push_deferring_access_checks (dk_no_check); - new_ctor = build_special_member_call - (NULL_TREE, complete_ctor_identifier, &parms, totype, 0, complain); - release_tree_vector (parms); - pop_deferring_access_checks (); - return build_cplus_new (totype, new_ctor); + /* Build up the initializer_list object. */ + totype = complete_type (totype); + field = next_initializable_field (TYPE_FIELDS (totype)); + CONSTRUCTOR_APPEND_ELT (vec, field, decay_conversion (array)); + field = next_initializable_field (DECL_CHAIN (field)); + CONSTRUCTOR_APPEND_ELT (vec, field, size_int (len)); + new_ctor = build_constructor (totype, vec); + return get_target_expr (new_ctor); } case ck_aggr: diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d9c9ad8..bbccb67 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4562,7 +4562,7 @@ build_init_list_var_init (tree decl, tree type, tree init, tree *array_init, return error_mark_node; aggr_init = TARGET_EXPR_INITIAL (init); - array = AGGR_INIT_EXPR_ARG (aggr_init, 1); + array = CONSTRUCTOR_ELT (aggr_init, 0)->value; arrtype = TREE_TYPE (array); STRIP_NOPS (array); gcc_assert (TREE_CODE (array) == ADDR_EXPR); @@ -4574,7 +4574,7 @@ build_init_list_var_init (tree decl, tree type, tree init, tree *array_init, tree var = set_up_extended_ref_temp (decl, array, cleanup, array_init); var = build_address (var); var = convert (arrtype, var); - AGGR_INIT_EXPR_ARG (aggr_init, 1) = var; + CONSTRUCTOR_ELT (aggr_init, 0)->value = var; } return init; } commit 0d659efed9f80f72baf3f1a57549d8f9d56dbbe6 Author: Jason Merrill Date: Wed Mar 30 10:19:12 2011 -0400 * call.c (convert_like_real): Correct TREE_CONSTANT on CONSTRUCTOR. * decl.c (reshape_init_array_1): Likewise. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index a1cfa96..f7d108f 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5481,6 +5481,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, if (!BRACE_ENCLOSED_INITIALIZER_P (val)) check_narrowing (TREE_TYPE (sub), val); CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor), NULL_TREE, sub); + if (!TREE_CONSTANT (sub)) + TREE_CONSTANT (new_ctor) = false; } /* Build up the array. */ elttype = cp_build_qualified_type diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 16ccfaf..d9c9ad8 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4905,6 +4905,8 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d) return error_mark_node; CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), size_int (index), elt_init); + if (!TREE_CONSTANT (elt_init)) + TREE_CONSTANT (new_init) = false; } return new_init; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 9926d26..b88e190 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2329,7 +2329,34 @@ finish_compound_literal (tree type, tree compound_literal) if (TREE_CODE (type) == ARRAY_TYPE) cp_complete_array_type (&type, compound_literal, false); compound_literal = digest_init (type, compound_literal); - return get_target_expr (compound_literal); + /* Put static/constant array temporaries in static variables, but always + represent class temporaries with TARGET_EXPR so we elide copies. */ + if ((!at_function_scope_p () || CP_TYPE_CONST_P (type)) + && TREE_CODE (type) == ARRAY_TYPE + && initializer_constant_valid_p (compound_literal, type)) + { + tree decl = create_temporary_var (type); + DECL_INITIAL (decl) = compound_literal; + TREE_STATIC (decl) = 1; + if (literal_type_p (type) && CP_TYPE_CONST_NON_VOLATILE_P (type)) + { + /* 5.19 says that a constant expression can include an + lvalue-rvalue conversion applied to "a glvalue of literal type + that refers to a non-volatile temporary object initialized + with a constant expression". Rather than try to communicate + that this VAR_DECL is a temporary, just mark it constexpr. */ + DECL_DECLARED_CONSTEXPR_P (decl) = true; + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true; + TREE_CONSTANT (decl) = true; + } + cp_apply_type_quals_to_decl (cp_type_quals (type), decl); + decl = pushdecl_top_level (decl); + DECL_NAME (decl) = make_anon_name (); + SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl)); + return decl; + } + else + return get_target_expr (compound_literal); } /* Return the declaration for the function-name variable indicated by diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist46.C b/gcc/testsuite/g++.dg/cpp0x/initlist46.C new file mode 100644 index 0000000..2b9f07d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist46.C @@ -0,0 +1,14 @@ +// PR c++/48281 +// { dg-options "-std=c++0x -O2" } +// { dg-do run } + +#include + +typedef std::initializer_list int1; +typedef std::initializer_list int2; +static int2 ib = {{42,2,3,4,5},{2,3,4,5,1},{3,4,5,2,1}}; + +int main() +{ + return *(ib.begin()->begin()) != 42; +}