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

Reply via email to