On Wed, Mar 14, 2018 at 6:33 PM, Jakub Jelinek <ja...@redhat.com> wrote: > The following patch is an attempt to fix PLACEHOLDER_EXPR handling. > As e.g. > struct Y > { > static Y bar (Y y) { return y; } > int i; > int n = bar (Y{2,i}).m + bar {Y{2,i,i}).n; > int m = i; > }; > is rejected - one can't use incomplete ctors which would need NSDMIs > until the class is defined, I believe PLACEHOLDER_EXPRs can't be arbitrarily > intermixed, rather some CONSTRUCTORs into which we've added the NSDMI > expressions can contain PLACEHOLDER_EXPRs and other PLACEHOLDER_EXPRs can be > only found inside such CONSTRUCTORs added earlier. > > So, this patch adds a new flag on CONSTRUCTORs, which acts as a barrier > boundary for replace_placeholders, where we replace just PLACEHOLDER_EXPRs > from the outermost expressions and don't dive into CONSTRUCTORs into which > we've added other PLACEHOLDER_EXPRs - those will be handled later on > separately, by cp_gimplify_init_expr calling replace_placeholders. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2018-03-14 Jakub Jelinek <ja...@redhat.com> > > PR c++/79937 > PR c++/82410 > * cp-tree.h (CONSTRUCTOR_PLACEHOLDER_BOUNDARY): Define. > (find_placeholder): Declare. > * tree.c (struct replace_placeholders_t): Add exp member. > (replace_placeholders_r): Don't walk into ctors with > CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag set, unless they are equal to > d->exp. > (replace_placeholders): Initialize data.exp. > (find_placeholders_r, find_placeholders): New functions. > * typeck2.c (process_init_constructor_record, > process_init_constructor_union): Set CONSTRUCTOR_PLACEHOLDER_BOUNDARY > if adding NSDMI on which find_placeholder returns true. > > * g++.dg/cpp1y/pr79937-1.C: New test. > * g++.dg/cpp1y/pr79937-2.C: New test. > * g++.dg/cpp1y/pr79937-3.C: New test. > * g++.dg/cpp1y/pr79937-4.C: New test. > * g++.dg/cpp1y/pr82410.C: New test. > > --- gcc/cp/cp-tree.h.jj 2018-03-14 16:21:50.745925263 +0100 > +++ gcc/cp/cp-tree.h 2018-03-14 15:57:51.171323825 +0100 > @@ -425,6 +425,7 @@ extern GTY(()) tree cp_global_trees[CPTI > DECL_VTABLE_OR_VTT_P (in VAR_DECL) > FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) > CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR) > + CONSTRUCTOR_PLACEHOLDER_BOUNDARY (in CONSTRUCTOR) > 6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE) > DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL) > TYPE_MARKED_P (in _TYPE) > @@ -4144,6 +4145,12 @@ more_aggr_init_expr_args_p (const aggr_i > #define CONSTRUCTOR_C99_COMPOUND_LITERAL(NODE) \ > (TREE_LANG_FLAG_3 (CONSTRUCTOR_CHECK (NODE))) > > +/* True if this CONSTRUCTOR contains PLACEHOLDER_EXPRs referencing the > + CONSTRUCTOR's type not nested inside another CONSTRUCTOR marked with > + CONSTRUCTOR_PLACEHOLDER_BOUNDARY. */ > +#define CONSTRUCTOR_PLACEHOLDER_BOUNDARY(NODE) \ > + (TREE_LANG_FLAG_5 (CONSTRUCTOR_CHECK (NODE))) > + > #define DIRECT_LIST_INIT_P(NODE) \ > (BRACE_ENCLOSED_INITIALIZER_P (NODE) && CONSTRUCTOR_IS_DIRECT_INIT (NODE)) > > @@ -7021,6 +7028,7 @@ extern tree array_type_nelts_top (tree) > extern tree break_out_target_exprs (tree); > extern tree build_ctor_subob_ref (tree, tree, tree); > extern tree replace_placeholders (tree, tree, bool * = NULL); > +extern bool find_placeholders (tree); > extern tree get_type_decl (tree); > extern tree decl_namespace_context (tree); > extern bool decl_anon_ns_mem_p (const_tree); > --- gcc/cp/tree.c.jj 2018-03-14 11:49:58.926816421 +0100 > +++ gcc/cp/tree.c 2018-03-14 16:24:29.036987505 +0100 > @@ -3096,6 +3096,7 @@ build_ctor_subob_ref (tree index, tree t > struct replace_placeholders_t > { > tree obj; /* The object to be substituted for a PLACEHOLDER_EXPR. > */ > + tree exp; /* The outermost exp. */ > bool seen; /* Whether we've encountered a PLACEHOLDER_EXPR. */ > hash_set<tree> *pset; /* To avoid walking same trees multiple > times. */ > }; > @@ -3134,7 +3135,12 @@ replace_placeholders_r (tree* t, int* wa > { > constructor_elt *ce; > vec<constructor_elt,va_gc> *v = CONSTRUCTOR_ELTS (*t); > - if (d->pset->add (*t)) > + /* Don't walk into CONSTRUCTOR_PLACEHOLDER_BOUNDARY ctors > + other than the d->exp one, those have PLACEHOLDER_EXPRs > + related to another object. */ > + if ((CONSTRUCTOR_PLACEHOLDER_BOUNDARY (*t) > + && *t != d->exp) > + || d->pset->add (*t)) > { > *walk_subtrees = false; > return NULL_TREE; > @@ -3192,16 +3198,70 @@ replace_placeholders (tree exp, tree obj > return exp; > > tree *tp = &exp; > - hash_set<tree> pset; > - replace_placeholders_t data = { obj, false, &pset }; > + /* Use exp instead of *(type *)&exp. */ > + while (TREE_CODE (exp) == INDIRECT_REF) > + { > + tree t = TREE_OPERAND (exp, 0); > + STRIP_NOPS (t); > + if (TREE_CODE (t) == ADDR_EXPR > + && (t = TREE_OPERAND (t, 0)) > + && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (exp), > + TREE_TYPE (t))) > + exp = t; > + else > + break; > + }
What's the motivation for this? I suspect that it should only apply if REFERENCE_REF_P. Jason