aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/tree.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-10-27 13:42:12 -0400
committerJason Merrill <jason@gcc.gnu.org>2014-10-27 13:42:12 -0400
commit3e605b20a0c804d57d4be0f4f2bbab8b4e42fce6 (patch)
treeac2bca0b20f76ea658c7bbcb7dda73ababce83b9 /gcc/cp/tree.c
parentddc8de034a1f79861fed57b231813a5c5c48a130 (diff)
downloadgcc-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.c98
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 */