aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r--gcc/cp/init.c50
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));