diff options
author | Jason Merrill <jason@redhat.com> | 2014-10-27 13:42:12 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2014-10-27 13:42:12 -0400 |
commit | 3e605b20a0c804d57d4be0f4f2bbab8b4e42fce6 (patch) | |
tree | ac2bca0b20f76ea658c7bbcb7dda73ababce83b9 /gcc/cp/tree.c | |
parent | ddc8de034a1f79861fed57b231813a5c5c48a130 (diff) | |
download | gcc-3e605b20a0c804d57d4be0f4f2bbab8b4e42fce6.zip gcc-3e605b20a0c804d57d4be0f4f2bbab8b4e42fce6.tar.gz gcc-3e605b20a0c804d57d4be0f4f2bbab8b4e42fce6.tar.bz2 |
Implement N3653 (Member initializers and aggregates) and fix references to 'this' in constexpr constructors.
Implement N3653 (Member initializers and aggregates) and fix
references to 'this' in constexpr constructors.
* class.c (check_field_decls): In C++14 an NSDMI does not make the
class non-aggregate.
* constexpr.c (struct constexpr_ctx): New.
(cxx_bind_parameters_in_call): Handle 'this'.
(cxx_eval_call_expression): Create new constexpr_ctx.
(cxx_eval_component_reference): Check CONSTRUCTOR_NO_IMPLICIT_ZERO.
(initialized_type, init_subob_ctx, verify_ctor_sanity): New.
(cxx_eval_bare_aggregate): Use them. Build CONSTRUCTOR early.
(cxx_eval_vec_init_1): Likewise.
(cxx_eval_constant_expression) [PARM_DECL]: Allow 'this'.
[TARGET_EXPR]: Build new constexpr_ctx.
[PLACEHOLDER_EXPR]: New.
(cxx_eval_outermost_constant_expr): Build new constexpr_ctx. Add
object parameter.
(is_sub_constant_expr): Build new constexpr_ctx.
(potential_constant_expression_1): Handle PLACEHOLDER_EXPR.
Allow 'this'.
* cp-gimplify.c (cp_gimplify_init_expr): Call replace_placeholders.
* cp-tree.h (CONSTRUCTOR_NO_IMPLICIT_ZERO): New.
* error.c (dump_expr): Handle PLACEHOLDER_EXPR.
* init.c (get_nsdmi): Generate PLACEHOLDER_EXPR.
* tree.c (lvalue_kind): Handle PLACEHOLDER_EXPR.
(build_ctor_subob_ref, replace_placeholders): New.
* typeck2.c (store_init_value): Use replace_placeholders.
(process_init_constructor_record): Make zero-init before NSDMI
explicit.
From-SVN: r216750
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r-- | gcc/cp/tree.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 9008cdb..ef7f675 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -158,6 +158,7 @@ lvalue_kind (const_tree ref) case ARRAY_NOTATION_REF: case PARM_DECL: case RESULT_DECL: + case PLACEHOLDER_EXPR: return clk_ordinary; /* A scope ref in a template, left as SCOPE_REF to support later @@ -2450,6 +2451,103 @@ break_out_target_exprs (tree t) return t; } +/* Build an expression for the subobject of OBJ at CONSTRUCTOR index INDEX, + which we expect to have type TYPE. */ + +tree +build_ctor_subob_ref (tree index, tree type, tree obj) +{ + if (index == NULL_TREE) + /* Can't refer to a particular member of a vector. */ + obj = NULL_TREE; + else if (TREE_CODE (index) == INTEGER_CST) + obj = cp_build_array_ref (input_location, obj, index, tf_none); + else + obj = build_class_member_access_expr (obj, index, NULL_TREE, + /*reference*/false, tf_none); + if (obj) + gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, + TREE_TYPE (obj))); + return obj; +} + +/* Like substitute_placeholder_in_expr, but handle C++ tree codes and + build up subexpressions as we go deeper. */ + +struct replace_placeholders_t +{ + tree obj; + hash_set<tree> *pset; +}; + +static tree +replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) +{ + tree obj = static_cast<tree>(data_); + + if (TREE_CONSTANT (*t)) + { + *walk_subtrees = false; + return NULL_TREE; + } + + switch (TREE_CODE (*t)) + { + case PLACEHOLDER_EXPR: + gcc_assert (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (*t), TREE_TYPE (obj))); + *t = obj; + *walk_subtrees = false; + break; + + case TARGET_EXPR: + /* Don't mess with placeholders in an unrelated object. */ + *walk_subtrees = false; + break; + + case CONSTRUCTOR: + { + constructor_elt *ce; + vec<constructor_elt,va_gc> *v = CONSTRUCTOR_ELTS (*t); + for (unsigned i = 0; vec_safe_iterate (v, i, &ce); ++i) + { + tree *valp = &ce->value; + tree type = TREE_TYPE (*valp); + tree subob = obj; + + if (TREE_CODE (*valp) == CONSTRUCTOR + && AGGREGATE_TYPE_P (type)) + { + subob = build_ctor_subob_ref (ce->index, type, obj); + if (TREE_CODE (*valp) == TARGET_EXPR) + valp = &TARGET_EXPR_INITIAL (*valp); + } + + cp_walk_tree (valp, replace_placeholders_r, + subob, NULL); + } + *walk_subtrees = false; + break; + } + + default: + break; + } + + return NULL_TREE; +} + +tree +replace_placeholders (tree exp, tree obj) +{ + hash_set<tree> pset; + tree *tp = &exp; + if (TREE_CODE (exp) == TARGET_EXPR) + tp = &TARGET_EXPR_INITIAL (exp); + cp_walk_tree (tp, replace_placeholders_r, obj, NULL); + return exp; +} + /* Similar to `build_nt', but for template definitions of dependent expressions */ |