OSDN Git Service

PR c++/51475 - ICE with invalid initializer-list
[pf3gnuchains/gcc-fork.git] / gcc / cp / call.c
index ce8933a..dd716a4 100644 (file)
@@ -111,12 +111,15 @@ struct conversion {
     /* The next conversion in the chain.  Since the conversions are
        arranged from outermost to innermost, the NEXT conversion will
        actually be performed before this conversion.  This variant is
-       used only when KIND is neither ck_identity nor ck_ambig.  */
+       used only when KIND is neither ck_identity, ck_ambig nor
+       ck_list.  Please use the next_conversion function instead
+       of using this field directly.  */
     conversion *next;
     /* The expression at the beginning of the conversion chain.  This
        variant is used only if KIND is ck_identity or ck_ambig.  */
     tree expr;
-    /* The array of conversions for an initializer_list.  */
+    /* The array of conversions for an initializer_list, so this
+       variant is used only when KIN D is ck_list.  */
     conversion **list;
   } u;
   /* The function candidate corresponding to this conversion
@@ -193,6 +196,7 @@ static conversion *standard_conversion (tree, tree, tree, bool, int);
 static conversion *reference_binding (tree, tree, tree, bool, int);
 static conversion *build_conv (conversion_kind, tree, conversion *);
 static conversion *build_list_conv (tree, tree, int);
+static conversion *next_conversion (conversion *);
 static bool is_subseq (conversion *, conversion *);
 static conversion *maybe_handle_ref_bind (conversion **);
 static void maybe_handle_implicit_object (conversion **);
@@ -549,10 +553,8 @@ null_ptr_cst_p (tree t)
     {
       /* Core issue 903 says only literal 0 is a null pointer constant.  */
       if (cxx_dialect < cxx0x)
-       {
-         t = integral_constant_value (t);
-         STRIP_NOPS (t);
-       }
+       t = integral_constant_value (t);
+      STRIP_NOPS (t);
       if (integer_zerop (t) && !TREE_OVERFLOW (t))
        return true;
     }
@@ -835,6 +837,21 @@ build_list_conv (tree type, tree ctor, int flags)
   return t;
 }
 
+/* Return the next conversion of the conversion chain (if applicable),
+   or NULL otherwise.  Please use this function instead of directly
+   accessing fields of struct conversion.  */
+
+static conversion *
+next_conversion (conversion *conv)
+{
+  if (conv == NULL
+      || conv->kind == ck_identity
+      || conv->kind == ck_ambig
+      || conv->kind == ck_list)
+    return NULL;
+  return conv->u.next;
+}
+
 /* Subroutine of build_aggr_conv: check whether CTOR, a braced-init-list,
    is a valid aggregate initializer for array type ATYPE.  */
 
@@ -3373,7 +3390,7 @@ static struct z_candidate *
 build_user_type_conversion_1 (tree totype, tree expr, int flags)
 {
   struct z_candidate *candidates, *cand;
-  tree fromtype = TREE_TYPE (expr);
+  tree fromtype;
   tree ctors = NULL_TREE;
   tree conv_fns = NULL_TREE;
   conversion *conv = NULL;
@@ -3382,6 +3399,11 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
   bool any_viable_p;
   int convflags;
 
+  if (!expr)
+    return NULL;
+
+  fromtype = TREE_TYPE (expr);
+
   /* We represent conversion within a hierarchy using RVALUE_CONV and
      BASE_CONV, as specified by [over.best.ics]; these become plain
      constructor calls, as specified in [dcl.init].  */
@@ -3826,6 +3848,9 @@ build_new_function_call (tree fn, VEC(tree,gc) **args, bool koenig_p,
        return error_mark_node;
     }
 
+  if (flag_tm)
+    tm_malloc_replacement (fn);
+
   /* If this function was found without using argument dependent
      lookup, then we want to ignore any undeclared friend
      functions.  */
@@ -5544,7 +5569,8 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
     }
 
   /* Issue warnings if "false" is converted to a NULL pointer */
-  else if (expr == boolean_false_node && TYPE_PTR_P (totype))
+  else if (TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE
+          && TYPE_PTR_P (totype))
     {
       if (fn)
        warning_at (input_location, OPT_Wconversion_null,
@@ -5596,7 +5622,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
          && BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT (expr, 0)->value))
        permerror (input_location, "too many braces around initializer for %qT", totype);
 
-      for (; t; t = t->u.next)
+      for (; t ; t = next_conversion (t))
        {
          if (t->kind == ck_user && t->cand->reason)
            {
@@ -6971,8 +6997,10 @@ build_special_member_call (tree instance, tree name, VEC(tree,gc) **args,
                            current_in_charge_parm, integer_zero_node),
                    current_vtt_parm,
                    vtt);
-      gcc_assert (BINFO_SUBVTT_INDEX (binfo));
-      sub_vtt = fold_build_pointer_plus (vtt, BINFO_SUBVTT_INDEX (binfo));
+      if (BINFO_SUBVTT_INDEX (binfo))
+       sub_vtt = fold_build_pointer_plus (vtt, BINFO_SUBVTT_INDEX (binfo));
+      else
+       sub_vtt = vtt;
 
       if (args == NULL)
        {
@@ -7189,6 +7217,7 @@ build_new_method_call_1 (tree instance, tree fns, VEC(tree,gc) **args,
       && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0)))
     {
       tree init_list = VEC_index (tree, *args, 0);
+      tree init = NULL_TREE;
 
       gcc_assert (VEC_length (tree, *args) == 1
                  && !(flags & LOOKUP_ONLYCONVERTING));
@@ -7200,8 +7229,16 @@ build_new_method_call_1 (tree instance, tree fns, VEC(tree,gc) **args,
       if (CONSTRUCTOR_NELTS (init_list) == 0
          && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
          && !processing_template_decl)
+       init = build_value_init (basetype, complain);
+
+      /* If BASETYPE is an aggregate, we need to do aggregate
+        initialization.  */
+      else if (CP_AGGREGATE_TYPE_P (basetype))
+       init = digest_init (basetype, init_list, complain);
+
+      if (init)
        {
-         tree ob, init = build_value_init (basetype, complain);
+         tree ob;
          if (integer_zerop (instance_ptr))
            return get_target_expr_sfinae (init, complain);
          ob = build_fold_indirect_ref (instance_ptr);
@@ -7210,6 +7247,7 @@ build_new_method_call_1 (tree instance, tree fns, VEC(tree,gc) **args,
          return init;
        }
 
+      /* Otherwise go ahead with overload resolution.  */
       add_list_candidates (fns, first_mem_arg, init_list,
                           basetype, explicit_targs, template_only,
                           conversion_path, access_binfo, flags, &candidates);
@@ -8105,6 +8143,22 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
   if (winner)
     return winner;
 
+  /* DR 495 moved this tiebreaker above the template ones.  */
+  /* or, if not that,
+     the  context  is  an  initialization by user-defined conversion (see
+     _dcl.init_  and  _over.match.user_)  and  the  standard   conversion
+     sequence  from  the return type of F1 to the destination type (i.e.,
+     the type of the entity being initialized)  is  a  better  conversion
+     sequence  than the standard conversion sequence from the return type
+     of F2 to the destination type.  */
+
+  if (cand1->second_conv)
+    {
+      winner = compare_ics (cand1->second_conv, cand2->second_conv);
+      if (winner)
+       return winner;
+    }
+
   /* or, if not that,
      F1 is a non-template function and F2 is a template function
      specialization.  */
@@ -8133,21 +8187,6 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
        return winner;
     }
 
-  /* or, if not that,
-     the  context  is  an  initialization by user-defined conversion (see
-     _dcl.init_  and  _over.match.user_)  and  the  standard   conversion
-     sequence  from  the return type of F1 to the destination type (i.e.,
-     the type of the entity being initialized)  is  a  better  conversion
-     sequence  than the standard conversion sequence from the return type
-     of F2 to the destination type.  */
-
-  if (cand1->second_conv)
-    {
-      winner = compare_ics (cand1->second_conv, cand2->second_conv);
-      if (winner)
-       return winner;
-    }
-
   /* Check whether we can discard a builtin candidate, either because we
      have two identical ones or matching builtin and non-builtin candidates.
 
@@ -8417,10 +8456,7 @@ perform_implicit_conversion_flags (tree type, tree expr, tsubst_flags_t complain
        }
       expr = error_mark_node;
     }
-  else if (processing_template_decl
-          /* As a kludge, we always perform conversions between scalar
-             types, as IMPLICIT_CONV_EXPR confuses c_finish_omp_for.  */
-          && !(SCALAR_TYPE_P (type) && SCALAR_TYPE_P (TREE_TYPE (expr))))
+  else if (processing_template_decl && conv->kind != ck_identity)
     {
       /* In a template, we are only concerned about determining the
         type of non-dependent expressions, so we do not have to
@@ -8502,6 +8538,44 @@ perform_direct_initialization_if_possible (tree type,
   return expr;
 }
 
+/* When initializing a reference that lasts longer than a full-expression,
+   this special rule applies:
+
+     [class.temporary]
+
+     The temporary to which the reference is bound or the temporary
+     that is the complete object to which the reference is bound
+     persists for the lifetime of the reference.
+
+     The temporaries created during the evaluation of the expression
+     initializing the reference, except the temporary to which the
+     reference is bound, are destroyed at the end of the
+     full-expression in which they are created.
+
+   In that case, we store the converted expression into a new
+   VAR_DECL in a new scope.
+
+   However, we want to be careful not to create temporaries when
+   they are not required.  For example, given:
+
+     struct B {};
+     struct D : public B {};
+     D f();
+     const B& b = f();
+
+   there is no need to copy the return value from "f"; we can just
+   extend its lifetime.  Similarly, given:
+
+     struct S {};
+     struct T { operator S(); };
+     T t;
+     const S& s = t;
+
+  we can extend the lifetime of the return value of the conversion
+  operator.
+
+  The next several functions are involved in this lifetime extension.  */
+
 /* DECL is a VAR_DECL whose type is a REFERENCE_TYPE.  The reference
    is being bound to a temporary.  Create and return a new VAR_DECL
    with the indicated TYPE; this variable will store the value to
@@ -8519,6 +8593,7 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type)
   if (TREE_STATIC (decl))
     {
       /* Namespace-scope or local static; give it a mangled name.  */
+      /* FIXME share comdat with decl?  */
       tree name;
 
       TREE_STATIC (var) = 1;
@@ -8540,8 +8615,9 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type)
    cleanup for the new variable is returned through CLEANUP, and the
    code to initialize the new variable is returned through INITP.  */
 
-tree
-set_up_extended_ref_temp (tree decl, tree expr, tree *cleanup, tree *initp)
+static tree
+set_up_extended_ref_temp (tree decl, tree expr, VEC(tree,gc) **cleanups,
+                         tree *initp)
 {
   tree init;
   tree type;
@@ -8562,6 +8638,18 @@ set_up_extended_ref_temp (tree decl, tree expr, tree *cleanup, tree *initp)
   if (TREE_CODE (expr) != TARGET_EXPR)
     expr = get_target_expr (expr);
 
+  if (TREE_CODE (decl) == FIELD_DECL
+      && extra_warnings && !TREE_NO_WARNING (decl))
+    {
+      warning (OPT_Wextra, "a temporary bound to %qD only persists "
+              "until the constructor exits", decl);
+      TREE_NO_WARNING (decl) = true;
+    }
+
+  /* Recursively extend temps in this initializer.  */
+  TARGET_EXPR_INITIAL (expr)
+    = extend_ref_init_temps (decl, TARGET_EXPR_INITIAL (expr), cleanups);
+
   /* If the initializer is constant, put it in DECL_INITIAL so we get
      static initialization and use in constant expressions.  */
   init = maybe_constant_init (expr);
@@ -8595,7 +8683,11 @@ set_up_extended_ref_temp (tree decl, tree expr, tree *cleanup, tree *initp)
       if (TREE_STATIC (var))
        init = add_stmt_to_compound (init, register_dtor_fn (var));
       else
-       *cleanup = cxx_maybe_build_cleanup (var, tf_warning_or_error);
+       {
+         tree cleanup = cxx_maybe_build_cleanup (var, tf_warning_or_error);
+         if (cleanup)
+           VEC_safe_push (tree, gc, *cleanups, cleanup);
+       }
 
       /* We must be careful to destroy the temporary only
         after its initialization has taken place.  If the
@@ -8629,18 +8721,10 @@ set_up_extended_ref_temp (tree decl, tree expr, tree *cleanup, tree *initp)
 }
 
 /* Convert EXPR to the indicated reference TYPE, in a way suitable for
-   initializing a variable of that TYPE.  If DECL is non-NULL, it is
-   the VAR_DECL being initialized with the EXPR.  (In that case, the
-   type of DECL will be TYPE.)  If DECL is non-NULL, then CLEANUP must
-   also be non-NULL, and with *CLEANUP initialized to NULL.  Upon
-   return, if *CLEANUP is no longer NULL, it will be an expression
-   that should be pushed as a cleanup after the returned expression
-   is used to initialize DECL.
-
-   Return the converted expression.  */
+   initializing a variable of that TYPE.  */
 
 tree
-initialize_reference (tree type, tree expr, tree decl, tree *cleanup,
+initialize_reference (tree type, tree expr,
                      int flags, tsubst_flags_t complain)
 {
   conversion *conv;
@@ -8674,103 +8758,77 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup,
       return error_mark_node;
     }
 
-  /* If DECL is non-NULL, then this special rule applies:
-
-       [class.temporary]
-
-       The temporary to which the reference is bound or the temporary
-       that is the complete object to which the reference is bound
-       persists for the lifetime of the reference.
+  gcc_assert (conv->kind == ck_ref_bind);
 
-       The temporaries created during the evaluation of the expression
-       initializing the reference, except the temporary to which the
-       reference is bound, are destroyed at the end of the
-       full-expression in which they are created.
+  /* Perform the conversion.  */
+  expr = convert_like (conv, expr, complain);
 
-     In that case, we store the converted expression into a new
-     VAR_DECL in a new scope.
+  /* Free all the conversions we allocated.  */
+  obstack_free (&conversion_obstack, p);
 
-     However, we want to be careful not to create temporaries when
-     they are not required.  For example, given:
+  return expr;
+}
 
-       struct B {};
-       struct D : public B {};
-       D f();
-       const B& b = f();
+/* Subroutine of extend_ref_init_temps.  Possibly extend one initializer,
+   which is bound either to a reference or a std::initializer_list.  */
 
-     there is no need to copy the return value from "f"; we can just
-     extend its lifetime.  Similarly, given:
+static tree
+extend_ref_init_temps_1 (tree decl, tree init, VEC(tree,gc) **cleanups)
+{
+  tree sub = init;
+  tree *p;
+  STRIP_NOPS (sub);
+  if (TREE_CODE (sub) != ADDR_EXPR)
+    return init;
+  /* Deal with binding to a subobject.  */
+  for (p = &TREE_OPERAND (sub, 0); TREE_CODE (*p) == COMPONENT_REF; )
+    p = &TREE_OPERAND (*p, 0);
+  if (TREE_CODE (*p) == TARGET_EXPR)
+    {
+      tree subinit = NULL_TREE;
+      *p = set_up_extended_ref_temp (decl, *p, cleanups, &subinit);
+      if (subinit)
+       init = build2 (COMPOUND_EXPR, TREE_TYPE (init), subinit, init);
+    }
+  return init;
+}
 
-       struct S {};
-       struct T { operator S(); };
-       T t;
-       const S& s = t;
+/* INIT is part of the initializer for DECL.  If there are any
+   reference or initializer lists being initialized, extend their
+   lifetime to match that of DECL.  */
 
-    we can extend the lifetime of the return value of the conversion
-    operator.  */
-  gcc_assert (conv->kind == ck_ref_bind);
-  if (decl)
+tree
+extend_ref_init_temps (tree decl, tree init, VEC(tree,gc) **cleanups)
+{
+  tree type = TREE_TYPE (init);
+  if (processing_template_decl)
+    return init;
+  if (TREE_CODE (type) == REFERENCE_TYPE)
+    init = extend_ref_init_temps_1 (decl, init, cleanups);
+  else if (is_std_init_list (type))
     {
-      tree var;
-      tree base_conv_type;
-
-      gcc_assert (complain == tf_warning_or_error);
-
-      /* Skip over the REF_BIND.  */
-      conv = conv->u.next;
-      /* If the next conversion is a BASE_CONV, skip that too -- but
-        remember that the conversion was required.  */
-      if (conv->kind == ck_base)
-       {
-         base_conv_type = conv->type;
-         conv = conv->u.next;
-       }
-      else
-       base_conv_type = NULL_TREE;
-      /* Perform the remainder of the conversion.  */
-      expr = convert_like_real (conv, expr,
-                               /*fn=*/NULL_TREE, /*argnum=*/0,
-                               /*inner=*/-1,
-                               /*issue_conversion_warnings=*/true,
-                               /*c_cast_p=*/false,
-                               complain);
-      if (error_operand_p (expr))
-       expr = error_mark_node;
-      else
+      /* The temporary array underlying a std::initializer_list
+        is handled like a reference temporary.  */
+      tree ctor = init;
+      if (TREE_CODE (ctor) == TARGET_EXPR)
+       ctor = TARGET_EXPR_INITIAL (ctor);
+      if (TREE_CODE (ctor) == CONSTRUCTOR)
        {
-         if (!lvalue_or_rvalue_with_address_p (expr))
-           {
-             tree init;
-             var = set_up_extended_ref_temp (decl, expr, cleanup, &init);
-             /* Use its address to initialize the reference variable.  */
-             expr = build_address (var);
-             if (base_conv_type)
-               expr = convert_to_base (expr,
-                                       build_pointer_type (base_conv_type),
-                                       /*check_access=*/true,
-                                       /*nonnull=*/true, complain);
-             if (init)
-               expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
-           }
-         else
-           /* Take the address of EXPR.  */
-           expr = cp_build_addr_expr (expr, complain);
-         /* If a BASE_CONV was required, perform it now.  */
-         if (base_conv_type)
-           expr = (perform_implicit_conversion
-                   (build_pointer_type (base_conv_type), expr,
-                    complain));
-         expr = build_nop (type, expr);
+         tree array = CONSTRUCTOR_ELT (ctor, 0)->value;
+         array = extend_ref_init_temps_1 (decl, array, cleanups);
+         CONSTRUCTOR_ELT (ctor, 0)->value = array;
        }
     }
-  else
-    /* Perform the conversion.  */
-    expr = convert_like (conv, expr, complain);
-
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
+  else if (TREE_CODE (init) == CONSTRUCTOR)
+    {
+      unsigned i;
+      constructor_elt *p;
+      VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS (init);
+      FOR_EACH_VEC_ELT (constructor_elt, elts, i, p)
+       p->value = extend_ref_init_temps (decl, p->value, cleanups);
+    }
 
-  return expr;
+  return init;
 }
 
 /* Returns true iff TYPE is some variant of std::initializer_list.  */