diff options
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r-- | gcc/cp/init.c | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 83e685c..56a5df8 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -535,6 +535,8 @@ perform_target_ctor (tree init) /* Return the non-static data initializer for FIELD_DECL MEMBER. */ +static GTY(()) hash_map<tree, tree> *nsdmi_inst; + tree get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) { @@ -542,31 +544,36 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) tree save_ccp = current_class_ptr; tree save_ccr = current_class_ref; - if (!in_ctor) - { - /* Use a PLACEHOLDER_EXPR when we don't have a 'this' parameter to - refer to; constexpr evaluation knows what to do with it. */ - current_class_ref = build0 (PLACEHOLDER_EXPR, DECL_CONTEXT (member)); - current_class_ptr = build_address (current_class_ref); - } - if (DECL_LANG_SPECIFIC (member) && DECL_TEMPLATE_INFO (member)) { init = DECL_INITIAL (DECL_TI_TEMPLATE (member)); + location_t expr_loc + = EXPR_LOC_OR_LOC (init, DECL_SOURCE_LOCATION (member)); + tree *slot; if (TREE_CODE (init) == DEFAULT_ARG) /* Unparsed. */; + else if (nsdmi_inst && (slot = nsdmi_inst->get (member))) + init = *slot; /* Check recursive instantiation. */ else if (DECL_INSTANTIATING_NSDMI_P (member)) { if (complain & tf_error) - error ("recursive instantiation of default member " - "initializer for %qD", member); + error_at (expr_loc, "recursive instantiation of default member " + "initializer for %qD", member); init = error_mark_node; } else { + int un = cp_unevaluated_operand; + cp_unevaluated_operand = 0; + + location_t sloc = input_location; + input_location = expr_loc; + DECL_INSTANTIATING_NSDMI_P (member) = 1; + inject_this_parameter (DECL_CONTEXT (member), TYPE_UNQUALIFIED); + /* Do deferred instantiation of the NSDMI. */ init = (tsubst_copy_and_build (init, DECL_TI_ARGS (member), @@ -575,6 +582,16 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) init = digest_nsdmi_init (member, init, complain); DECL_INSTANTIATING_NSDMI_P (member) = 0; + + if (init != error_mark_node) + { + if (!nsdmi_inst) + nsdmi_inst = hash_map<tree,tree>::create_ggc (37); + nsdmi_inst->put (member, init); + } + + input_location = sloc; + cp_unevaluated_operand = un; } } else @@ -592,6 +609,19 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) init = error_mark_node; } + if (in_ctor) + { + current_class_ptr = save_ccp; + current_class_ref = save_ccr; + } + else + { + /* Use a PLACEHOLDER_EXPR when we don't have a 'this' parameter to + refer to; constexpr evaluation knows what to do with it. */ + current_class_ref = build0 (PLACEHOLDER_EXPR, DECL_CONTEXT (member)); + current_class_ptr = build_address (current_class_ref); + } + /* Strip redundant TARGET_EXPR so we don't need to remap it, and so the aggregate init code below will see a CONSTRUCTOR. */ bool simple_target = (init && SIMPLE_TARGET_EXPR_P (init)); |