diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 784f3aab15d..3f3a8ee33f5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2010-11-06 Jason Merrill + + * init.c (perform_member_init): Use build_vec_init_expr for + value-init of arrays, too. + * cp-gimplify.c (cp_gimplify_expr): Use VEC_INIT_EXPR_VALUE_INIT. + * cp-tree.h (VEC_INIT_EXPR_IS_CONSTEXPR): New macro. + (VEC_INIT_EXPR_VALUE_INIT): New macro. + * semantics.c (potential_constant_expression): No longer static. + Check VEC_INIT_EXPR_IS_CONSTEXPR. + * tree.c (build_vec_init_expr): Handle value-init. Set + VEC_INIT_EXPR_IS_CONSTEXPR and VEC_INIT_EXPR_VALUE_INIT. + 2010-11-06 Nathan Froyd PR c++/45332 diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 705979d6c55..557430d6c83 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -535,7 +535,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) gcc_assert (EXPR_HAS_LOCATION (*expr_p)); input_location = EXPR_LOCATION (*expr_p); *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE, - init, /*explicit_value_init_p*/false, + init, VEC_INIT_EXPR_VALUE_INIT (*expr_p), from_array, tf_warning_or_error); ret = GS_OK; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8f5227800f5..241805ca36b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -72,6 +72,7 @@ c-common.h, not after. CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR) LAMBDA_EXPR_CAPTURES_THIS_P (in LAMBDA_EXPR) DECLTYPE_FOR_LAMBDA_CAPTURE (in DECLTYPE_TYPE) + VEC_INIT_EXPR_IS_CONSTEXPR (in VEC_INIT_EXPR) 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -2898,6 +2899,15 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define VEC_INIT_EXPR_SLOT(NODE) TREE_OPERAND (NODE, 0) #define VEC_INIT_EXPR_INIT(NODE) TREE_OPERAND (NODE, 1) +/* Indicates that a VEC_INIT_EXPR is a potential constant expression. + Only set when the current function is constexpr. */ +#define VEC_INIT_EXPR_IS_CONSTEXPR(NODE) \ + TREE_LANG_FLAG_0 (VEC_INIT_EXPR_CHECK (NODE)) + +/* Indicates that a VEC_INIT_EXPR is expressing value-initialization. */ +#define VEC_INIT_EXPR_VALUE_INIT(NODE) \ + TREE_LANG_FLAG_1 (VEC_INIT_EXPR_CHECK (NODE)) + /* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a TEMPLATE_DECL. This macro determines whether or not a given class type is really a template type, as opposed to an instantiation or @@ -5240,6 +5250,7 @@ extern bool literal_type_p (tree); extern tree validate_constexpr_fundecl (tree); extern tree register_constexpr_fundef (tree, tree); extern tree ensure_literal_type_for_constexpr_object (tree); +extern bool potential_constant_expression (tree, tsubst_flags_t); extern tree cxx_constant_value (tree); extern tree maybe_constant_value (tree); extern tree maybe_constant_init (tree); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index ab834bf65ef..0ecd61d3aed 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -453,10 +453,8 @@ perform_member_init (tree member, tree init) /* mem() means value-initialization. */ if (TREE_CODE (type) == ARRAY_TYPE) { - init = build_vec_init (decl, NULL_TREE, NULL_TREE, - /*explicit_value_init_p=*/true, - /* from_array=*/0, - tf_warning_or_error); + init = build_vec_init_expr (type, init); + init = build2 (INIT_EXPR, type, decl, init); finish_expr_stmt (init); } else diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 558be885275..fd7da34475a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5324,8 +5324,6 @@ typedef struct GTY(()) constexpr_fundef { static GTY ((param_is (constexpr_fundef))) htab_t constexpr_fundef_table; -static bool potential_constant_expression (tree, tsubst_flags_t); - /* Utility function used for managing the constexpr function table. Return true if the entries pointed to by P and Q are for the same constexpr function. */ @@ -7066,7 +7064,7 @@ morally_constexpr_builtin_function_p (tree decl) logical OR (5.15), and conditional (5.16) operations that are not evaluated are not considered. */ -static bool +bool potential_constant_expression (tree t, tsubst_flags_t flags) { int i; @@ -7451,11 +7449,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags) return false; case VEC_INIT_EXPR: - /* We should only see this in a defaulted constructor for a class - with a non-static data member of array type; if we get here we - know this is a potential constant expression. */ - gcc_assert (DECL_DEFAULTED_FN (current_function_decl)); - return true; + return VEC_INIT_EXPR_IS_CONSTEXPR (t); default: sorry ("unexpected ast of kind %s", tree_code_name[TREE_CODE (t)]); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index d1d306e3a2a..5440e10204e 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -462,34 +462,54 @@ build_vec_init_expr (tree type, tree init) { tree slot; tree inner_type = strip_array_types (type); - - gcc_assert (init == NULL_TREE - || (same_type_ignoring_top_level_qualifiers_p - (type, TREE_TYPE (init)))); + tree elt_init = integer_zero_node; + bool value_init = false; /* Since we're deferring building the actual constructor calls until gimplification time, we need to build one now and throw it away so that the relevant constructor gets mark_used before cgraph decides what functions are needed. Here we assume that init is either - NULL_TREE or another array to copy. */ - if (CLASS_TYPE_P (inner_type)) + NULL_TREE, void_type_node (indicating value-initialization), or + another array to copy. */ + if (init == void_type_node) { - VEC(tree,gc) *argvec = make_tree_vector (); - if (init) + elt_init = build_value_init (inner_type, tf_warning_or_error); + value_init = true; + init = NULL_TREE; + } + else + { + gcc_assert (init == NULL_TREE + || (same_type_ignoring_top_level_qualifiers_p + (type, TREE_TYPE (init)))); + + if (CLASS_TYPE_P (inner_type)) { - tree dummy = build_dummy_object (inner_type); - if (!real_lvalue_p (init)) - dummy = move (dummy); - VEC_quick_push (tree, argvec, dummy); + VEC(tree,gc) *argvec = make_tree_vector (); + if (init) + { + tree dummy = build_dummy_object (inner_type); + if (!real_lvalue_p (init)) + dummy = move (dummy); + VEC_quick_push (tree, argvec, dummy); + } + elt_init + = build_special_member_call (NULL_TREE, complete_ctor_identifier, + &argvec, inner_type, LOOKUP_NORMAL, + tf_warning_or_error); } - build_special_member_call (NULL_TREE, complete_ctor_identifier, - &argvec, inner_type, LOOKUP_NORMAL, - tf_warning_or_error); } slot = build_local_temp (type); init = build2 (VEC_INIT_EXPR, type, slot, init); SET_EXPR_LOCATION (init, input_location); + + if (current_function_decl + && DECL_DECLARED_CONSTEXPR_P (current_function_decl) + && potential_constant_expression (elt_init, tf_warning_or_error)) + VEC_INIT_EXPR_IS_CONSTEXPR (init) = true; + VEC_INIT_EXPR_VALUE_INIT (init) = value_init; + init = build_target_expr (slot, init); TARGET_EXPR_IMPLICIT_P (init) = 1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 98a866bb2c5..c5ccdb80005 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2010-11-06 Jason Merrill + + * g++.dg/cpp0x/constexpr-ctor3.C: New. + 2010-11-06 Simon Martin PR c/43384 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C new file mode 100644 index 00000000000..50d4d8526dc --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C @@ -0,0 +1,9 @@ +// { dg-options -std=c++0x } + +struct A +{ + int arr[1]; + + constexpr A() + : arr() { } +};