DR 1030 PR c++/51253
authorJason Merrill <jason@redhat.com>
Fri, 11 Apr 2014 17:08:47 +0000 (13:08 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 11 Apr 2014 17:08:47 +0000 (13:08 -0400)
DR 1030
PR c++/51253
* cp-tree.h (CALL_EXPR_LIST_INIT_P): New.
* call.c (struct z_candidate): Add flags field.
(add_candidate): Add flags parm.
(add_function_candidate, add_conv_candidate, build_builtin_candidate)
(add_template_candidate_real): Pass it.
(build_over_call): Set CALL_EXPR_LIST_INIT_P.
* tree.c (build_aggr_init_expr): Copy it.
* semantics.c (simplify_aggr_init_expr): Preevaluate args if it's set.

From-SVN: r209309

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/semantics.c
gcc/cp/tree.c

index afbf24a..77473fe 100644 (file)
@@ -1,3 +1,16 @@
+2014-04-11  Jason Merrill  <jason@redhat.com>
+
+       DR 1030
+       PR c++/51253
+       * cp-tree.h (CALL_EXPR_LIST_INIT_P): New.
+       * call.c (struct z_candidate): Add flags field.
+       (add_candidate): Add flags parm.
+       (add_function_candidate, add_conv_candidate, build_builtin_candidate)
+       (add_template_candidate_real): Pass it.
+       (build_over_call): Set CALL_EXPR_LIST_INIT_P.
+       * tree.c (build_aggr_init_expr): Copy it.
+       * semantics.c (simplify_aggr_init_expr): Preevaluate args if it's set.
+
 2014-04-10  Richard Biener  <rguenther@suse.de>
            Jakub Jelinek  <jakub@redhat.com>
 
index ae0d4ff..7c0dcc2 100644 (file)
@@ -206,7 +206,7 @@ static conversion *maybe_handle_ref_bind (conversion **);
 static void maybe_handle_implicit_object (conversion **);
 static struct z_candidate *add_candidate
        (struct z_candidate **, tree, tree, const vec<tree, va_gc> *, size_t,
-        conversion **, tree, tree, int, struct rejection_reason *);
+        conversion **, tree, tree, int, struct rejection_reason *, int);
 static tree source_type (conversion *);
 static void add_warning (struct z_candidate *, struct z_candidate *);
 static bool reference_compatible_p (tree, tree);
@@ -520,7 +520,6 @@ struct z_candidate {
      sequence from the type returned by FN to the desired destination
      type.  */
   conversion *second_conv;
-  int viable;
   struct rejection_reason *reason;
   /* If FN is a member function, the binfo indicating the path used to
      qualify the name of FN at the call site.  This path is used to
@@ -538,6 +537,10 @@ struct z_candidate {
   tree explicit_targs;
   candidate_warning *warnings;
   z_candidate *next;
+  int viable;
+
+  /* The flags active in add_candidate.  */
+  int flags;
 };
 
 /* Returns true iff T is a null pointer constant in the sense of
@@ -1810,7 +1813,8 @@ add_candidate (struct z_candidate **candidates,
               tree fn, tree first_arg, const vec<tree, va_gc> *args,
               size_t num_convs, conversion **convs,
               tree access_path, tree conversion_path,
-              int viable, struct rejection_reason *reason)
+              int viable, struct rejection_reason *reason,
+              int flags)
 {
   struct z_candidate *cand = (struct z_candidate *)
     conversion_obstack_alloc (sizeof (struct z_candidate));
@@ -1825,6 +1829,7 @@ add_candidate (struct z_candidate **candidates,
   cand->viable = viable;
   cand->reason = reason;
   cand->next = *candidates;
+  cand->flags = flags;
   *candidates = cand;
 
   return cand;
@@ -2061,7 +2066,7 @@ add_function_candidate (struct z_candidate **candidates,
 
  out:
   return add_candidate (candidates, fn, orig_first_arg, args, len, convs,
-                       access_path, conversion_path, viable, reason);
+                       access_path, conversion_path, viable, reason, flags);
 }
 
 /* Create an overload candidate for the conversion function FN which will
@@ -2163,7 +2168,7 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
     }
 
   return add_candidate (candidates, totype, first_arg, arglist, len, convs,
-                       access_path, conversion_path, viable, reason);
+                       access_path, conversion_path, viable, reason, flags);
 }
 
 static void
@@ -2238,7 +2243,7 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
                 num_convs, convs,
                 /*access_path=*/NULL_TREE,
                 /*conversion_path=*/NULL_TREE,
-                viable, reason);
+                viable, reason, flags);
 }
 
 static bool
@@ -3056,7 +3061,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
   return cand;
  fail:
   return add_candidate (candidates, tmpl, first_arg, arglist, nargs, NULL,
-                       access_path, conversion_path, 0, reason);
+                       access_path, conversion_path, 0, reason, flags);
 }
 
 
@@ -7219,7 +7224,11 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
        return error_mark_node;
     }
 
-  return build_cxx_call (fn, nargs, argarray, complain|decltype_flag);
+  tree call = build_cxx_call (fn, nargs, argarray, complain|decltype_flag);
+  if (TREE_CODE (call) == CALL_EXPR
+      && (cand->flags & LOOKUP_LIST_INIT_CTOR))
+    CALL_EXPR_LIST_INIT_P (call) = true;
+  return call;
 }
 
 /* Build and return a call to FN, using NARGS arguments in ARGARRAY.
index e9fe86e..bafc32d 100644 (file)
@@ -101,12 +101,14 @@ c-common.h, not after.
       FNDECL_USED_AUTO (in FUNCTION_DECL)
       DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE)
       REF_PARENTHESIZED_P (in COMPONENT_REF, SCOPE_REF)
+      AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR)
    3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
       ICS_BAD_FLAG (in _CONV)
       FN_TRY_BLOCK_P (in TRY_BLOCK)
       IDENTIFIER_CTOR_OR_DTOR_P (in IDENTIFIER_NODE)
       BIND_EXPR_BODY_BLOCK (in BIND_EXPR)
       DECL_NON_TRIVIALLY_INITIALIZED_P (in VAR_DECL)
+      CALL_EXPR_LIST_INIT_P (in CALL_EXPR, AGGR_INIT_EXPR)
    4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
          or FIELD_DECL).
       IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
@@ -3026,6 +3028,10 @@ extern void decl_shadowed_for_var_insert (tree, tree);
    should be performed at instantiation time.  */
 #define KOENIG_LOOKUP_P(NODE) TREE_LANG_FLAG_0 (CALL_EXPR_CHECK (NODE))
 
+/* True if CALL_EXPR expresses list-initialization of an object.  */
+#define CALL_EXPR_LIST_INIT_P(NODE) \
+  TREE_LANG_FLAG_3 (TREE_CHECK2 ((NODE),CALL_EXPR,AGGR_INIT_EXPR))
+
 /* Indicates whether a string literal has been parenthesized. Such
    usages are disallowed in certain circumstances.  */
 
index 3619e27..795086a 100644 (file)
@@ -3867,6 +3867,7 @@ simplify_aggr_init_expr (tree *tp)
                                    aggr_init_expr_nargs (aggr_init_expr),
                                    AGGR_INIT_EXPR_ARGP (aggr_init_expr));
   TREE_NOTHROW (call_expr) = TREE_NOTHROW (aggr_init_expr);
+  tree ret = call_expr;
 
   if (style == ctor)
     {
@@ -3882,7 +3883,7 @@ simplify_aggr_init_expr (tree *tp)
         expand_call{,_inline}.  */
       cxx_mark_addressable (slot);
       CALL_EXPR_RETURN_SLOT_OPT (call_expr) = true;
-      call_expr = build2 (INIT_EXPR, TREE_TYPE (call_expr), slot, call_expr);
+      ret = build2 (INIT_EXPR, TREE_TYPE (ret), slot, ret);
     }
   else if (style == pcc)
     {
@@ -3890,11 +3891,25 @@ simplify_aggr_init_expr (tree *tp)
         need to copy the returned value out of the static buffer into the
         SLOT.  */
       push_deferring_access_checks (dk_no_check);
-      call_expr = build_aggr_init (slot, call_expr,
-                                  DIRECT_BIND | LOOKUP_ONLYCONVERTING,
-                                   tf_warning_or_error);
+      ret = build_aggr_init (slot, ret,
+                            DIRECT_BIND | LOOKUP_ONLYCONVERTING,
+                            tf_warning_or_error);
       pop_deferring_access_checks ();
-      call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot);
+      ret = build2 (COMPOUND_EXPR, TREE_TYPE (slot), ret, slot);
+    }
+
+  /* DR 1030 says that we need to evaluate the elements of an
+     initializer-list in forward order even when it's used as arguments to
+     a constructor.  So if the target wants to evaluate them in reverse
+     order and there's more than one argument other than 'this', force
+     pre-evaluation.  */
+  if (PUSH_ARGS_REVERSED && CALL_EXPR_LIST_INIT_P (aggr_init_expr)
+      && aggr_init_expr_nargs (aggr_init_expr) > 2)
+    {
+      tree preinit;
+      stabilize_call (call_expr, &preinit);
+      if (preinit)
+       ret = build2 (COMPOUND_EXPR, TREE_TYPE (ret), preinit, ret);
     }
 
   if (AGGR_INIT_ZERO_FIRST (aggr_init_expr))
@@ -3902,11 +3917,10 @@ simplify_aggr_init_expr (tree *tp)
       tree init = build_zero_init (type, NULL_TREE,
                                   /*static_storage_p=*/false);
       init = build2 (INIT_EXPR, void_type_node, slot, init);
-      call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (call_expr),
-                         init, call_expr);
+      ret = build2 (COMPOUND_EXPR, TREE_TYPE (ret), init, ret);
     }
 
-  *tp = call_expr;
+  *tp = ret;
 }
 
 /* Emit all thunks to FN that should be emitted when FN is emitted.  */
index 3429d23..4b39b90 100644 (file)
@@ -453,6 +453,7 @@ build_aggr_init_expr (tree type, tree init)
       TREE_SIDE_EFFECTS (rval) = 1;
       AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
       TREE_NOTHROW (rval) = TREE_NOTHROW (init);
+      CALL_EXPR_LIST_INIT_P (rval) = CALL_EXPR_LIST_INIT_P (init);
     }
   else
     rval = init;