OSDN Git Service

cp/
[pf3gnuchains/gcc-fork.git] / gcc / cp / call.c
index a9c0367..837a65d 100644 (file)
@@ -190,14 +190,12 @@ static struct z_candidate *add_candidate
         conversion **, tree, tree, int);
 static tree source_type (conversion *);
 static void add_warning (struct z_candidate *, struct z_candidate *);
-static bool reference_related_p (tree, tree);
 static bool reference_compatible_p (tree, tree);
 static conversion *convert_class_to_reference (tree, tree, tree, int);
 static conversion *direct_reference_binding (tree, conversion *);
 static bool promoted_arithmetic_type_p (tree);
 static conversion *conditional_conversion (tree, tree);
 static char *name_as_c_string (tree, tree, bool *);
-static tree call_builtin_trap (void);
 static tree prep_operand (tree);
 static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree,
                            int, struct z_candidate **);
@@ -242,7 +240,7 @@ check_dtor_name (tree basetype, tree name)
       return false;
     }
 
-  if (!name)
+  if (!name || name == error_mark_node)
     return false;
   return same_type_p (TYPE_MAIN_VARIANT (basetype), TYPE_MAIN_VARIANT (name));
 }
@@ -315,6 +313,9 @@ build_call_a (tree function, int n, tree *argarray)
   gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE
              || TREE_CODE (fntype) == METHOD_TYPE);
   result_type = TREE_TYPE (fntype);
+  /* An rvalue has no cv-qualifiers.  */
+  if (SCALAR_TYPE_P (result_type) || VOID_TYPE_P (result_type))
+    result_type = cv_unqualified (result_type);
 
   if (TREE_CODE (function) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
@@ -363,7 +364,8 @@ build_call_a (tree function, int n, tree *argarray)
                                argarray[i], t);
        }
 
-  function = build_call_array (result_type, function, n, argarray);
+  function = build_call_array_loc (input_location,
+                                  result_type, function, n, argarray);
   TREE_HAS_CONSTRUCTOR (function) = is_constructor;
   TREE_NOTHROW (function) = nothrow;
 
@@ -894,10 +896,7 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
          || cp_type_quals (fbase) != cp_type_quals (tbase))
        return NULL;
 
-      from = cp_build_qualified_type (tbase, cp_type_quals (fbase));
-      from = build_method_type_directly (from,
-                                        TREE_TYPE (fromfn),
-                                        TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
+      from = build_memfn_type (fromfn, tbase, cp_type_quals (tbase));
       from = build_ptrmemfunc_type (build_pointer_type (from));
       conv = build_conv (ck_pmem, from, conv);
       conv->base_p = true;
@@ -966,7 +965,7 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
 
 /* Returns nonzero if T1 is reference-related to T2.  */
 
-static bool
+bool
 reference_related_p (tree t1, tree t2)
 {
   t1 = TYPE_MAIN_VARIANT (t1);
@@ -1110,6 +1109,11 @@ convert_class_to_reference (tree reference_type, tree s, tree expr, int flags)
                = TYPE_REF_IS_RVALUE (TREE_TYPE (TREE_TYPE (cand->fn)))
                  == TYPE_REF_IS_RVALUE (reference_type);
              cand->second_conv->bad_p |= cand->convs[0]->bad_p;
+
+              /* Don't allow binding of lvalues to rvalue references.  */
+              if (TYPE_REF_IS_RVALUE (reference_type)
+                  && !TYPE_REF_IS_RVALUE (TREE_TYPE (TREE_TYPE (cand->fn))))
+                cand->second_conv->bad_p = true;
            }
        }
     }
@@ -1137,13 +1141,13 @@ convert_class_to_reference (tree reference_type, tree s, tree expr, int flags)
                     build_identity_conv (TREE_TYPE (expr), expr));
   conv->cand = cand;
 
+  if (cand->viable == -1)
+    conv->bad_p = true;
+
   /* Merge it with the standard conversion sequence from the
      conversion function's return type to the desired type.  */
   cand->second_conv = merge_conversion_sequences (conv, cand->second_conv);
 
-  if (cand->viable == -1)
-    conv->bad_p = true;
-
   return cand->second_conv;
 }
 
@@ -1205,7 +1209,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
   tree tfrom;
   bool related_p;
   bool compatible_p;
-  cp_lvalue_kind lvalue_p = clk_none;
+  cp_lvalue_kind is_lvalue = clk_none;
 
   if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
     {
@@ -1218,14 +1222,30 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
   if (TREE_CODE (from) == REFERENCE_TYPE)
     {
       /* Anything with reference type is an lvalue.  */
-      lvalue_p = clk_ordinary;
+      is_lvalue = clk_ordinary;
       from = TREE_TYPE (from);
     }
-  else if (expr)
-    lvalue_p = real_lvalue_p (expr);
+
+  if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
+    {
+      maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
+      conv = implicit_conversion (to, from, expr, c_cast_p,
+                                 flags);
+      if (!CLASS_TYPE_P (to)
+         && CONSTRUCTOR_NELTS (expr) == 1)
+       {
+         expr = CONSTRUCTOR_ELT (expr, 0)->value;
+         if (error_operand_p (expr))
+           return NULL;
+         from = TREE_TYPE (expr);
+       }
+    }
+
+  if (is_lvalue == clk_none && expr)
+    is_lvalue = real_lvalue_p (expr);
 
   tfrom = from;
-  if ((lvalue_p & clk_bitfield) != 0)
+  if ((is_lvalue & clk_bitfield) != 0)
     tfrom = unlowered_expr_type (expr);
 
   /* Figure out whether or not the types are reference-related and
@@ -1242,12 +1262,15 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
   /* Directly bind reference when target expression's type is compatible with
      the reference and expression is an lvalue. In DR391, the wording in
      [8.5.3/5 dcl.init.ref] is changed to also require direct bindings for
-     const and rvalue references to rvalues of compatible class type. */
+     const and rvalue references to rvalues of compatible class type.
+     We should also do direct bindings for non-class "rvalues" derived from
+     rvalue references.  */
   if (compatible_p
-      && (lvalue_p
-         || (!(flags & LOOKUP_NO_TEMP_BIND)
-             && (CP_TYPE_CONST_NON_VOLATILE_P(to) || TYPE_REF_IS_RVALUE (rto))
-             && CLASS_TYPE_P (from))))
+      && (is_lvalue
+         || (((CP_TYPE_CONST_NON_VOLATILE_P (to)
+               && !(flags & LOOKUP_NO_TEMP_BIND))
+              || TYPE_REF_IS_RVALUE (rto))
+             && (CLASS_TYPE_P (from) || (expr && lvalue_p (expr))))))
     {
       /* [dcl.init.ref]
 
@@ -1274,10 +1297,10 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
        conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
       else
        conv->rvaluedness_matches_p 
-          = (TYPE_REF_IS_RVALUE (rto) == !lvalue_p);
+          = (TYPE_REF_IS_RVALUE (rto) == !is_lvalue);
 
-      if ((lvalue_p & clk_bitfield) != 0
-         || ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to)))
+      if ((is_lvalue & clk_bitfield) != 0
+         || ((is_lvalue & clk_packed) != 0 && !TYPE_PACKED (to)))
        /* For the purposes of overload resolution, we ignore the fact
           this expression is a bitfield or packed field. (In particular,
           [over.ics.ref] says specifically that a function with a
@@ -1291,6 +1314,11 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
           actually occurs.  */
        conv->need_temporary_p = true;
 
+      /* Don't allow binding of lvalues to rvalue references.  */
+      if (is_lvalue && TYPE_REF_IS_RVALUE (rto)
+          && !(flags & LOOKUP_PREFER_RVALUE))
+       conv->bad_p = true;
+
       return conv;
     }
   /* [class.conv.fct] A conversion function is never used to convert a
@@ -1363,8 +1391,9 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
   if (!(flags & LOOKUP_COPY_PARM))
     flags |= LOOKUP_ONLYCONVERTING;
 
-  conv = implicit_conversion (to, from, expr, c_cast_p,
-                             flags);
+  if (!conv)
+    conv = implicit_conversion (to, from, expr, c_cast_p,
+                               flags);
   if (!conv)
     return NULL;
 
@@ -1400,9 +1429,37 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
   if (conv)
     return conv;
 
-  if (is_std_init_list (to) && expr
-      && BRACE_ENCLOSED_INITIALIZER_P (expr))
-    return build_list_conv (to, expr, flags);
+  if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
+    {
+      if (is_std_init_list (to))
+       return build_list_conv (to, expr, flags);
+
+      /* Allow conversion from an initializer-list with one element to a
+        scalar type.  */
+      if (SCALAR_TYPE_P (to))
+       {
+         int nelts = CONSTRUCTOR_NELTS (expr);
+         tree elt;
+
+         if (nelts == 0)
+           elt = integer_zero_node;
+         else if (nelts == 1)
+           elt = CONSTRUCTOR_ELT (expr, 0)->value;
+         else
+           elt = error_mark_node;
+
+         conv = implicit_conversion (to, TREE_TYPE (elt), elt,
+                                     c_cast_p, flags);
+         if (conv)
+           {
+             conv->check_narrowing = true;
+             if (BRACE_ENCLOSED_INITIALIZER_P (elt))
+               /* Too many levels of braces, i.e. '{{1}}'.  */
+               conv->bad_p = true;
+             return conv;
+           }
+       }
+    }
 
   if (expr != NULL_TREE
       && (MAYBE_CLASS_TYPE_P (from)
@@ -1576,7 +1633,8 @@ add_function_candidate (struct z_candidate **candidates,
              parmtype = build_pointer_type (parmtype);
            }
 
-         if (ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn))
+         if (ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn)
+             && (len-skip == 1))
            {
              /* Hack: Direct-initialize copy parm (i.e. suppress
                 LOOKUP_ONLYCONVERTING) to make explicit conversion ops
@@ -1723,7 +1781,14 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
 
   num_convs =  args[2] ? 3 : (args[1] ? 2 : 1);
   convs = alloc_conversions (num_convs);
-  flags |= LOOKUP_ONLYCONVERTING;
+
+  /* TRUTH_*_EXPR do "contextual conversion to bool", which means explicit
+     conversion ops are allowed.  We handle that here by just checking for
+     boolean_type_node because other operators don't ask for it.  COND_EXPR
+     also does contextual conversion to bool for the first operand, but we
+     handle that in build_conditional_expr, and type1 here is operand 2.  */
+  if (type1 != boolean_type_node)
+    flags |= LOOKUP_ONLYCONVERTING;
 
   for (i = 0; i < 2; ++i)
     {
@@ -2392,9 +2457,10 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
 {
   int ntparms = DECL_NTPARMS (tmpl);
   tree targs = make_tree_vec (ntparms);
-  unsigned int nargs;
-  int skip_without_in_chrg;
-  tree first_arg_without_in_chrg;
+  unsigned int len = VEC_length (tree, arglist);
+  unsigned int nargs = (first_arg == NULL_TREE ? 0 : 1) + len;
+  unsigned int skip_without_in_chrg = 0;
+  tree first_arg_without_in_chrg = first_arg;
   tree *args_without_in_chrg;
   unsigned int nargs_without_in_chrg;
   unsigned int ia, ix;
@@ -2403,12 +2469,6 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
   int i;
   tree fn;
 
-  nargs = (first_arg == NULL_TREE ? 0 : 1) + VEC_length (tree, arglist);
-
-  skip_without_in_chrg = 0;
-
-  first_arg_without_in_chrg = first_arg;
-
   /* We don't do deduction on the in-charge parameter, the VTT
      parameter or 'this'.  */
   if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl))
@@ -2429,9 +2489,11 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
        ++skip_without_in_chrg;
     }
 
+  if (len < skip_without_in_chrg)
+    return NULL;
+
   nargs_without_in_chrg = ((first_arg_without_in_chrg != NULL_TREE ? 1 : 0)
-                          + (VEC_length (tree, arglist)
-                             - skip_without_in_chrg));
+                          + (len - skip_without_in_chrg));
   args_without_in_chrg = XALLOCAVEC (tree, nargs_without_in_chrg);
   ia = 0;
   if (first_arg_without_in_chrg != NULL_TREE)
@@ -2516,7 +2578,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
        for this will point at template <class T> template <> S<T>::f(int),
        so that we can find the definition.  For the purposes of
        overload resolution, however, we want the original TMPL.  */
-    cand->template_decl = tree_cons (tmpl, targs, NULL_TREE);
+    cand->template_decl = build_template_info (tmpl, targs);
   else
     cand->template_decl = DECL_TEMPLATE_INFO (fn);
 
@@ -2656,6 +2718,8 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate)
     inform (input_location, "%s %T <conversion>", msgstr, candidate->fn);
   else if (candidate->viable == -1)
     inform (input_location, "%s %+#D <near match>", msgstr, candidate->fn);
+  else if (DECL_DELETED_FN (candidate->fn))
+    inform (input_location, "%s %+#D <deleted>", msgstr, candidate->fn);
   else
     inform (input_location, "%s %+#D", msgstr, candidate->fn);
 }
@@ -2667,6 +2731,23 @@ print_z_candidates (struct z_candidate *candidates)
   struct z_candidate *cand1;
   struct z_candidate **cand2;
 
+  if (!candidates)
+    return;
+
+  /* Remove deleted candidates.  */
+  cand1 = candidates;
+  for (cand2 = &cand1; *cand2; )
+    {
+      if (TREE_CODE ((*cand2)->fn) == FUNCTION_DECL
+         && DECL_DELETED_FN ((*cand2)->fn))
+       *cand2 = (*cand2)->next;
+      else
+       cand2 = &(*cand2)->next;
+    }
+  /* ...if there are any non-deleted ones.  */
+  if (cand1)
+    candidates = cand1;
+
   /* There may be duplicates in the set of candidates.  We put off
      checking this condition as long as possible, since we have no way
      to eliminate duplicates from a set of functions in less than n^2
@@ -2689,9 +2770,6 @@ print_z_candidates (struct z_candidate *candidates)
        }
     }
 
-  if (!candidates)
-    return;
-
   str = _("candidates are:");
   print_z_candidate (str, candidates);
   if (candidates->next)
@@ -2874,11 +2952,16 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
       for (fns = TREE_VALUE (conv_fns); fns; fns = OVL_NEXT (fns))
        {
          tree fn = OVL_CURRENT (fns);
+         tree first = first_arg;
 
          if (DECL_NONCONVERTING_P (fn)
              && (flags & LOOKUP_ONLYCONVERTING))
            continue;
 
+         /* Lambdas have a static conversion op.  */
+         if (DECL_STATIC_FUNCTION_P (fn))
+           first = NULL_TREE;
+
          /* [over.match.funcs] For conversion functions, the function
             is considered to be a member of the class of the implicit
             object argument for the purpose of defining the type of
@@ -2889,14 +2972,14 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
          if (TREE_CODE (fn) == TEMPLATE_DECL)
            cand = add_template_candidate (&candidates, fn, fromtype,
                                           NULL_TREE,
-                                          first_arg, NULL, totype,
+                                          first, NULL, totype,
                                           TYPE_BINFO (fromtype),
                                           conversion_path,
                                           flags,
                                           DEDUCE_CONV);
          else
            cand = add_function_candidate (&candidates, fn, fromtype,
-                                          first_arg, NULL,
+                                          first, NULL,
                                           TYPE_BINFO (fromtype),
                                           conversion_path,
                                           flags);
@@ -3303,20 +3386,30 @@ build_op_call (tree obj, VEC(tree,gc) **args, tsubst_flags_t complain)
       for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
        {
          tree fn = OVL_CURRENT (fns);
+
+         tree lfirst = first_mem_arg;
+         if (DECL_STATIC_FUNCTION_P (fn))
+           lfirst = NULL_TREE;
+
          if (TREE_CODE (fn) == TEMPLATE_DECL)
            add_template_candidate (&candidates, fn, base, NULL_TREE,
-                                   first_mem_arg, *args, NULL_TREE,
+                                   lfirst, *args, NULL_TREE,
                                    TYPE_BINFO (type),
                                    TYPE_BINFO (type),
                                    LOOKUP_NORMAL, DEDUCE_CALL);
          else
            add_function_candidate
-             (&candidates, fn, base, first_mem_arg, *args, TYPE_BINFO (type),
+             (&candidates, fn, base, lfirst, *args, TYPE_BINFO (type),
               TYPE_BINFO (type), LOOKUP_NORMAL);
        }
     }
 
-  convs = lookup_conversions (type);
+  /* Rather than mess with handling static conversion ops here, just don't
+     look at conversions in lambdas.  */
+  if (LAMBDA_TYPE_P (type))
+    convs = NULL_TREE;
+  else
+    convs = lookup_conversions (type);
 
   for (; convs; convs = TREE_CHAIN (convs))
     {
@@ -3511,6 +3604,7 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
   tree arg2_type;
   tree arg3_type;
   tree result = NULL_TREE;
+  tree result_save;
   tree result_type = NULL_TREE;
   bool lvalue_p = true;
   struct z_candidate *candidates = 0;
@@ -3538,7 +3632,8 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
 
      The first expression is implicitly converted to bool (clause
      _conv_).  */
-  arg1 = perform_implicit_conversion (boolean_type_node, arg1, complain);
+  arg1 = perform_implicit_conversion_flags (boolean_type_node, arg1, complain,
+                                           LOOKUP_NORMAL);
 
   /* If something has already gone wrong, just pass that fact up the
      tree.  */
@@ -3736,7 +3831,7 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
       bool any_viable_p;
 
       /* Rearrange the arguments so that add_builtin_candidate only has
-        to know about two args.  In build_builtin_candidates, the
+        to know about two args.  In build_builtin_candidate, the
         arguments are unscrambled.  */
       args[0] = arg2;
       args[1] = arg3;
@@ -3782,8 +3877,10 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
       arg1 = convert_like (conv, arg1, complain);
       conv = cand->convs[1];
       arg2 = convert_like (conv, arg2, complain);
+      arg2_type = TREE_TYPE (arg2);
       conv = cand->convs[2];
       arg3 = convert_like (conv, arg3, complain);
+      arg3_type = TREE_TYPE (arg3);
     }
 
   /* [expr.cond]
@@ -3802,7 +3899,7 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
     arg2_type = TREE_TYPE (arg2);
 
   arg3 = force_rvalue (arg3);
-  if (!CLASS_TYPE_P (arg2_type))
+  if (!CLASS_TYPE_P (arg3_type))
     arg3_type = TREE_TYPE (arg3);
 
   if (arg2 == error_mark_node || arg3 == error_mark_node)
@@ -3877,7 +3974,7 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
           || (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type)))
     {
       result_type = composite_pointer_type (arg2_type, arg3_type, arg2,
-                                           arg3, "conditional expression",
+                                           arg3, CPO_CONDITIONAL_EXPR,
                                            complain);
       if (result_type == error_mark_node)
        return error_mark_node;
@@ -3894,8 +3991,13 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
     }
 
  valid_operands:
-  result = fold_if_not_in_template (build3 (COND_EXPR, result_type, arg1,
-                                           arg2, arg3));
+  result_save = build3 (COND_EXPR, result_type, arg1, arg2, arg3);
+  result = fold_if_not_in_template (result_save);
+
+  if (cp_unevaluated_operand && TREE_CODE (result) == CALL_EXPR)
+    /* Avoid folding to a CALL_EXPR within decltype (c++/42013).  */
+    result = result_save;
+
   /* We can't use result_type below, as fold might have returned a
      throw_expr.  */
 
@@ -4017,10 +4119,32 @@ add_candidates (tree fns, const VEC(tree,gc) *args,
     }
 }
 
+/* Even unsigned enum types promote to signed int.  We don't want to
+   issue -Wsign-compare warnings for this case.  Here ORIG_ARG is the
+   original argument and ARG is the argument after any conversions
+   have been applied.  We set TREE_NO_WARNING if we have added a cast
+   from an unsigned enum type to a signed integer type.  */
+
+static void
+avoid_sign_compare_warnings (tree orig_arg, tree arg)
+{
+  if (orig_arg != NULL_TREE
+      && arg != NULL_TREE
+      && orig_arg != arg
+      && TREE_CODE (TREE_TYPE (orig_arg)) == ENUMERAL_TYPE
+      && TYPE_UNSIGNED (TREE_TYPE (orig_arg))
+      && INTEGRAL_TYPE_P (TREE_TYPE (arg))
+      && !TYPE_UNSIGNED (TREE_TYPE (arg)))
+    TREE_NO_WARNING (arg) = 1;
+}
+
 tree
 build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
              bool *overloaded_p, tsubst_flags_t complain)
 {
+  tree orig_arg1 = arg1;
+  tree orig_arg2 = arg2;
+  tree orig_arg3 = arg3;
   struct z_candidate *candidates = 0, *cand;
   VEC(tree,gc) *arglist;
   tree fnname;
@@ -4080,14 +4204,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
   arg3 = prep_operand (arg3);
 
   if (code == COND_EXPR)
-    {
-      if (arg2 == NULL_TREE
-         || TREE_CODE (TREE_TYPE (arg2)) == VOID_TYPE
-         || TREE_CODE (TREE_TYPE (arg3)) == VOID_TYPE
-         || (! IS_OVERLOAD_TYPE (TREE_TYPE (arg2))
-             && ! IS_OVERLOAD_TYPE (TREE_TYPE (arg3))))
-       goto builtin;
-    }
+    /* Use build_conditional_expr instead.  */
+    gcc_unreachable ();
   else if (! IS_OVERLOAD_TYPE (TREE_TYPE (arg1))
           && (! arg2 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg2))))
     goto builtin;
@@ -4129,22 +4247,9 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
                        flags, &candidates);
     }
 
-  /* Rearrange the arguments for ?: so that add_builtin_candidate only has
-     to know about two args; a builtin candidate will always have a first
-     parameter of type bool.  We'll handle that in
-     build_builtin_candidate.  */
-  if (code == COND_EXPR)
-    {
-      args[0] = arg2;
-      args[1] = arg3;
-      args[2] = arg1;
-    }
-  else
-    {
-      args[0] = arg1;
-      args[1] = arg2;
-      args[2] = NULL_TREE;
-    }
+  args[0] = arg1;
+  args[1] = arg2;
+  args[2] = NULL_TREE;
 
   add_builtin_candidates (&candidates, code, code2, fnname, args, flags);
 
@@ -4178,13 +4283,23 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
          if (!(complain & tf_error))
            return error_mark_node;
 
-         /* Look for an `operator++ (int)'.  If they didn't have
-            one, then we fall back to the old way of doing things.  */
+         /* Look for an `operator++ (int)'. Pre-1985 C++ didn't
+            distinguish between prefix and postfix ++ and
+            operator++() was used for both, so we allow this with
+            -fpermissive.  */
          if (flags & LOOKUP_COMPLAIN)
-           permerror (input_location, "no %<%D(int)%> declared for postfix %qs, "
-                      "trying prefix operator instead",
-                      fnname,
-                      operator_name_info[code].name);
+           {
+             const char *msg = (flag_permissive) 
+               ? G_("no %<%D(int)%> declared for postfix %qs,"
+                    " trying prefix operator instead")
+               : G_("no %<%D(int)%> declared for postfix %qs");
+             permerror (input_location, msg, fnname,
+                        operator_name_info[code].name);
+           }
+
+         if (!flag_permissive)
+           return error_mark_node;
+
          if (code == POSTINCREMENT_EXPR)
            code = PREINCREMENT_EXPR;
          else
@@ -4322,6 +4437,10 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
     return result;
 
  builtin:
+  avoid_sign_compare_warnings (orig_arg1, arg1);
+  avoid_sign_compare_warnings (orig_arg2, arg2);
+  avoid_sign_compare_warnings (orig_arg3, arg3);
+
   switch (code)
     {
     case MODIFY_EXPR:
@@ -4370,10 +4489,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
       return cp_build_unary_op (code, arg1, candidates != 0, complain);
 
     case ARRAY_REF:
-      return build_array_ref (arg1, arg2, input_location);
-
-    case COND_EXPR:
-      return build_conditional_expr (arg1, arg2, arg3, complain);
+      return build_array_ref (input_location, arg1, arg2);
 
     case MEMBER_REF:
       return build_m_component_ref (cp_build_indirect_ref (arg1, NULL, 
@@ -4392,6 +4508,33 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
   return NULL_TREE;
 }
 
+/* Returns true iff T, an element of an OVERLOAD chain, is a usual
+   deallocation function (3.7.4.2 [basic.stc.dynamic.deallocation]).  */
+
+static bool
+non_placement_deallocation_fn_p (tree t)
+{
+  /* A template instance is never a usual deallocation function,
+     regardless of its signature.  */
+  if (TREE_CODE (t) == TEMPLATE_DECL
+      || primary_template_instantiation_p (t))
+    return false;
+
+  /* If a class T has a member deallocation function named operator delete
+     with exactly one parameter, then that function is a usual
+     (non-placement) deallocation function. If class T does not declare
+     such an operator delete but does declare a member deallocation
+     function named operator delete with exactly two parameters, the second
+     of which has type std::size_t (18.2), then this function is a usual
+     deallocation function.  */
+  t = FUNCTION_ARG_CHAIN (t);
+  if (t == void_list_node
+      || (t && same_type_p (TREE_VALUE (t), size_type_node)
+         && TREE_CHAIN (t) == void_list_node))
+    return true;
+  return false;
+}
+
 /* Build a call to operator delete.  This has to be handled very specially,
    because the restrictions on what signatures match are different from all
    other call instances.  For a normal delete, only a delete taking (void *)
@@ -4417,8 +4560,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
                      tree alloc_fn)
 {
   tree fn = NULL_TREE;
-  tree fns, fnname, argtypes, type;
-  int pass;
+  tree fns, fnname, type, t;
 
   if (addr == error_mark_node)
     return error_mark_node;
@@ -4453,78 +4595,86 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
 
   if (placement)
     {
-      /* Get the parameter types for the allocation function that is
-        being called.  */
-      gcc_assert (alloc_fn != NULL_TREE);
-      argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
-    }
-  else
-    {
-      /* First try it without the size argument.  */
-      argtypes = void_list_node;
-    }
-
-  /* We make two tries at finding a matching `operator delete'.  On
-     the first pass, we look for a one-operator (or placement)
-     operator delete.  If we're not doing placement delete, then on
-     the second pass we look for a two-argument delete.  */
-  for (pass = 0; pass < (placement ? 1 : 2); ++pass)
-    {
-      /* Go through the `operator delete' functions looking for one
-        with a matching type.  */
-      for (fn = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
-          fn;
-          fn = OVL_NEXT (fn))
+      /* "A declaration of a placement deallocation function matches the
+        declaration of a placement allocation function if it has the same
+        number of parameters and, after parameter transformations (8.3.5),
+        all parameter types except the first are identical."
+
+        So we build up the function type we want and ask instantiate_type
+        to get it for us.  */
+      t = FUNCTION_ARG_CHAIN (alloc_fn);
+      t = tree_cons (NULL_TREE, ptr_type_node, t);
+      t = build_function_type (void_type_node, t);
+
+      fn = instantiate_type (t, fns, tf_none);
+      if (fn == error_mark_node)
+       return NULL_TREE;
+
+      if (BASELINK_P (fn))
+       fn = BASELINK_FUNCTIONS (fn);
+
+      /* "If the lookup finds the two-parameter form of a usual deallocation
+        function (3.7.4.2) and that function, considered as a placement
+        deallocation function, would have been selected as a match for the
+        allocation function, the program is ill-formed."  */
+      if (non_placement_deallocation_fn_p (fn))
        {
-         tree t;
-
-         /* The first argument must be "void *".  */
-         t = TYPE_ARG_TYPES (TREE_TYPE (OVL_CURRENT (fn)));
-         if (!same_type_p (TREE_VALUE (t), ptr_type_node))
-           continue;
-         t = TREE_CHAIN (t);
-         /* On the first pass, check the rest of the arguments.  */
-         if (pass == 0)
+         /* But if the class has an operator delete (void *), then that is
+            the usual deallocation function, so we shouldn't complain
+            about using the operator delete (void *, size_t).  */
+         for (t = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
+              t; t = OVL_NEXT (t))
            {
-             tree a = argtypes;
-             while (a && t)
-               {
-                 if (!same_type_p (TREE_VALUE (a), TREE_VALUE (t)))
-                   break;
-                 a = TREE_CHAIN (a);
-                 t = TREE_CHAIN (t);
-               }
-             if (!a && !t)
-               break;
+             tree elt = OVL_CURRENT (t);
+             if (non_placement_deallocation_fn_p (elt)
+                 && FUNCTION_ARG_CHAIN (elt) == void_list_node)
+               goto ok;
            }
-         /* On the second pass, look for a function with exactly two
-            arguments: "void *" and "size_t".  */
-         else if (pass == 1
-                  /* For "operator delete(void *, ...)" there will be
-                     no second argument, but we will not get an exact
-                     match above.  */
-                  && t
-                  && same_type_p (TREE_VALUE (t), size_type_node)
-                  && TREE_CHAIN (t) == void_list_node)
-           break;
+         permerror (0, "non-placement deallocation function %q+D", fn);
+         permerror (input_location, "selected for placement delete");
+       ok:;
        }
-
-      /* If we found a match, we're done.  */
-      if (fn)
-       break;
     }
+  else
+    /* "Any non-placement deallocation function matches a non-placement
+       allocation function. If the lookup finds a single matching
+       deallocation function, that function will be called; otherwise, no
+       deallocation function will be called."  */
+    for (t = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
+        t; t = OVL_NEXT (t))
+      {
+       tree elt = OVL_CURRENT (t);
+       if (non_placement_deallocation_fn_p (elt))
+         {
+           fn = elt;
+           /* "If a class T has a member deallocation function named
+              operator delete with exactly one parameter, then that
+              function is a usual (non-placement) deallocation
+              function. If class T does not declare such an operator
+              delete but does declare a member deallocation function named
+              operator delete with exactly two parameters, the second of
+              which has type std::size_t (18.2), then this function is a
+              usual deallocation function."
+
+              So (void*) beats (void*, size_t).  */
+           if (FUNCTION_ARG_CHAIN (fn) == void_list_node)
+             break;
+         }
+      }
 
   /* If we have a matching function, call it.  */
   if (fn)
     {
-      /* Make sure we have the actual function, and not an
-        OVERLOAD.  */
-      fn = OVL_CURRENT (fn);
+      gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
 
       /* If the FN is a member function, make sure that it is
         accessible.  */
-      if (DECL_CLASS_SCOPE_P (fn))
-       perform_or_defer_access_check (TYPE_BINFO (type), fn, fn);
+      if (BASELINK_P (fns))
+       perform_or_defer_access_check (BASELINK_BINFO (fns), fn, fn);
+
+      /* Core issue 901: It's ok to new a type with deleted delete.  */
+      if (DECL_DELETED_FN (fn) && alloc_fn)
+       return NULL_TREE;
 
       if (placement)
        {
@@ -4544,7 +4694,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
          tree ret;
          VEC(tree,gc) *args = VEC_alloc (tree, gc, 2);
          VEC_quick_push (tree, args, addr);
-         if (pass != 0)
+         if (FUNCTION_ARG_CHAIN (fn) != void_list_node)
            VEC_quick_push (tree, args, size);
          ret = cp_build_function_call_vec (fn, &args, tf_warning_or_error);
          VEC_free (tree, gc, args);
@@ -4669,12 +4819,21 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 
   if (convs->bad_p
       && convs->kind != ck_user
+      && convs->kind != ck_list
       && convs->kind != ck_ambig
       && convs->kind != ck_ref_bind
       && convs->kind != ck_rvalue
       && convs->kind != ck_base)
     {
       conversion *t = convs;
+
+      /* Give a helpful error if this is bad because of excess braces.  */
+      if (BRACE_ENCLOSED_INITIALIZER_P (expr)
+         && SCALAR_TYPE_P (totype)
+         && CONSTRUCTOR_NELTS (expr) > 0
+         && BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT (expr, 0)->value))
+       permerror (input_location, "too many braces around initializer for %qT", totype);
+
       for (; t; t = convs->u.next)
        {
          if (t->kind == ck_user || !t->bad_p)
@@ -4748,6 +4907,17 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
        return expr;
       }
     case ck_identity:
+      if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+       {
+         int nelts = CONSTRUCTOR_NELTS (expr);
+         if (nelts == 0)
+           expr = integer_zero_node;
+         else if (nelts == 1)
+           expr = CONSTRUCTOR_ELT (expr, 0)->value;
+         else
+           gcc_unreachable ();
+       }
+
       if (type_unknown_p (expr))
        expr = instantiate_type (totype, expr, complain);
       /* Convert a constant to its underlying value, unless we are
@@ -4865,6 +5035,19 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
       {
        tree ref_type = totype;
 
+       if (convs->bad_p && TYPE_REF_IS_RVALUE (ref_type)
+           && real_lvalue_p (expr))
+         {
+           if (complain & tf_error)
+             {
+               error ("cannot bind %qT lvalue to %qT",
+                      TREE_TYPE (expr), totype);
+               if (fn)
+                 error ("  initializing argument %P of %q+D", argnum, fn);
+             }
+           return error_mark_node;
+         }
+
        /* If necessary, create a temporary. 
 
            VA_ARG_EXPR and CONSTRUCTOR expressions are special cases
@@ -4968,18 +5151,6 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
   return expr;
 }
 
-/* Build a call to __builtin_trap.  */
-
-static tree
-call_builtin_trap (void)
-{
-  tree fn = implicit_built_in_decls[BUILT_IN_TRAP];
-
-  gcc_assert (fn != NULL);
-  fn = build_call_n (fn, 0);
-  return fn;
-}
-
 /* ARG is being passed to a varargs function.  Perform any conversions
    required.  Return the converted value.  */
 
@@ -5000,7 +5171,8 @@ convert_arg_to_ellipsis (tree arg)
      promoted type before the call.  */
   if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
       && (TYPE_PRECISION (TREE_TYPE (arg))
-         < TYPE_PRECISION (double_type_node)))
+         < TYPE_PRECISION (double_type_node))
+      && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (arg))))
     arg = convert_to_real (double_type_node, arg);
   else if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg)))
     arg = perform_integral_promotions (arg);
@@ -5008,20 +5180,23 @@ convert_arg_to_ellipsis (tree arg)
   arg = require_complete_type (arg);
 
   if (arg != error_mark_node
-      && !pod_type_p (TREE_TYPE (arg)))
+      && (type_has_nontrivial_copy_init (TREE_TYPE (arg))
+         || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (arg))))
     {
-      /* Undefined behavior [expr.call] 5.2.2/7.  We used to just warn
-        here and do a bitwise copy, but now cp_expr_size will abort if we
-        try to do that.
+      /* [expr.call] 5.2.2/7:
+        Passing a potentially-evaluated argument of class type (Clause 9)
+        with a non-trivial copy constructor or a non-trivial destructor
+        with no corresponding parameter is conditionally-supported, with
+        implementation-defined semantics.
+
+        We used to just warn here and do a bitwise copy, but now
+        cp_expr_size will abort if we try to do that.
+
         If the call appears in the context of a sizeof expression,
-        there is no need to emit a warning, since the expression won't be
-        evaluated. We keep the builtin_trap just as a safety check.  */
-      if (!skip_evaluation)
-       warning (0, "cannot pass objects of non-POD type %q#T through %<...%>; "
-                "call will abort at runtime", TREE_TYPE (arg));
-      arg = call_builtin_trap ();
-      arg = build2 (COMPOUND_EXPR, integer_type_node, arg,
-                   integer_zero_node);
+        it is not potentially-evaluated.  */
+      if (cp_unevaluated_operand == 0)
+       error ("cannot pass objects of non-trivially-copyable "
+              "type %q#T through %<...%>", TREE_TYPE (arg));
     }
 
   return arg;
@@ -5040,21 +5215,21 @@ build_x_va_arg (tree expr, tree type)
   if (expr == error_mark_node || !type)
     return error_mark_node;
 
-  if (! pod_type_p (type))
+  if (type_has_nontrivial_copy_init (type)
+      || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+      || TREE_CODE (type) == REFERENCE_TYPE)
     {
       /* Remove reference types so we don't ICE later on.  */
       tree type1 = non_reference (type);
-      /* Undefined behavior [expr.call] 5.2.2/7.  */
-      warning (0, "cannot receive objects of non-POD type %q#T through %<...%>; "
-              "call will abort at runtime", type);
+      /* conditionally-supported behavior [expr.call] 5.2.2/7.  */
+      error ("cannot receive objects of non-trivially-copyable type %q#T "
+            "through %<...%>; ", type);
       expr = convert (build_pointer_type (type1), null_node);
-      expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr),
-                    call_builtin_trap (), expr);
       expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
       return expr;
     }
 
-  return build_va_arg (expr, type);
+  return build_va_arg (input_location, expr, type);
 }
 
 /* TYPE has been given to va_arg.  Apply the default conversions which
@@ -5301,8 +5476,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
            alcarray[ix + 1] = arg;
          argarray = alcarray;
        }
-      expr = build_call_array (return_type, build_addr_func (fn), nargs,
-                              argarray);
+      expr = build_call_array_loc (input_location,
+                                  return_type, build_addr_func (fn), nargs,
+                                  argarray);
       if (TREE_THIS_VOLATILE (fn) && cfun)
        current_function_returns_abnormally = 1;
       if (!VOID_TYPE_P (return_type))
@@ -5460,6 +5636,28 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
          && !TREE_ADDRESSABLE (type))
        conv = conv->u.next;
 
+      /* Warn about initializer_list deduction that isn't currently in the
+        working draft.  */
+      if (cxx_dialect > cxx98
+         && flag_deduce_init_list
+         && cand->template_decl
+         && is_std_init_list (non_reference (type)))
+       {
+         tree tmpl = TI_TEMPLATE (cand->template_decl);
+         tree realparm = chain_index (j, DECL_ARGUMENTS (cand->fn));
+         tree patparm = get_pattern_parm (realparm, tmpl);
+
+         if (!is_std_init_list (non_reference (TREE_TYPE (patparm))))
+           {
+             pedwarn (input_location, 0, "deducing %qT as %qT",
+                      non_reference (TREE_TYPE (patparm)),
+                      non_reference (type));
+             pedwarn (input_location, 0, "  in call to %q+D", cand->fn);
+             pedwarn (input_location, 0,
+                      "  (you can disable this with -fno-deduce-init-list)");
+           }
+       }
+
       val = convert_like_with_context
        (conv, VEC_index (tree, args, arg_index), fn, i - is_method,
         complain);
@@ -5595,11 +5793,11 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
          arg1 = arg;
          arg0 = cp_build_unary_op (ADDR_EXPR, to, 0, complain);
 
-         if (!(optimize && flag_tree_ter))
+         if (!can_trust_pointer_alignment ())
            {
-             /* When TER is off get_pointer_alignment returns 0, so a call
+             /* If we can't be sure about pointer alignment, a call
                 to __builtin_memcpy is expanded as a call to memcpy, which
-                is invalid with identical args.  When TER is on it is
+                is invalid with identical args.  Otherwise it is
                 expanded as a block move, which should be safe.  */
              arg0 = save_expr (arg0);
              arg1 = save_expr (arg1);
@@ -6371,7 +6569,6 @@ maybe_handle_ref_bind (conversion **ics)
       conversion *old_ics = *ics;
       *ics = old_ics->u.next;
       (*ics)->user_conv_p = old_ics->user_conv_p;
-      (*ics)->bad_p = old_ics->bad_p;
       return old_ics;
     }
 
@@ -6412,6 +6609,14 @@ compare_ics (conversion *ics1, conversion *ics2)
   ref_conv1 = maybe_handle_ref_bind (&ics1);
   ref_conv2 = maybe_handle_ref_bind (&ics2);
 
+  /* List-initialization sequence L1 is a better conversion sequence than
+     list-initialization sequence L2 if L1 converts to
+     std::initializer_list<X> for some X and L2 does not.  */
+  if (ics1->kind == ck_list && ics2->kind != ck_list)
+    return 1;
+  if (ics2->kind == ck_list && ics1->kind != ck_list)
+    return -1;
+
   /* [over.ics.rank]
 
      When  comparing  the  basic forms of implicit conversion sequences (as
@@ -6447,8 +6652,9 @@ compare_ics (conversion *ics1, conversion *ics2)
       /* We couldn't make up our minds; try to figure it out below.  */
     }
 
-  if (ics1->ellipsis_p)
-    /* Both conversions are ellipsis conversions.  */
+  if (ics1->ellipsis_p || ics1->kind == ck_list)
+    /* Both conversions are ellipsis conversions or both are building a
+       std::initializer_list.  */
     return 0;
 
   /* User-defined  conversion sequence U1 is a better conversion sequence
@@ -6462,26 +6668,13 @@ compare_ics (conversion *ics1, conversion *ics2)
       conversion *t1;
       conversion *t2;
 
-      for (t1 = ics1; t1->kind != ck_user && t1->kind != ck_list; t1 = t1->u.next)
+      for (t1 = ics1; t1->kind != ck_user; t1 = t1->u.next)
        if (t1->kind == ck_ambig || t1->kind == ck_aggr)
          return 0;
-      for (t2 = ics2; t2->kind != ck_user && t2->kind != ck_list; t2 = t2->u.next)
+      for (t2 = ics2; t2->kind != ck_user; t2 = t2->u.next)
        if (t2->kind == ck_ambig || t2->kind == ck_aggr)
          return 0;
 
-      /* Conversion to std::initializer_list is better than other
-        user-defined conversions.  */
-      if (t1->kind == ck_list
-         || t2->kind == ck_list)
-       {
-         if (t2->kind != ck_list)
-           return 1;
-         else if (t1->kind != ck_list)
-           return -1;
-         else
-           return 0;
-       }
-
       if (t1->cand->fn != t2->cand->fn)
        return 0;
 
@@ -7185,7 +7378,7 @@ tourney (struct z_candidate *candidates)
 bool
 can_convert (tree to, tree from)
 {
-  return can_convert_arg (to, from, NULL_TREE, LOOKUP_NORMAL);
+  return can_convert_arg (to, from, NULL_TREE, LOOKUP_IMPLICIT);
 }
 
 /* Returns nonzero if ARG (of type FROM) can be converted to TO.  */
@@ -7213,7 +7406,7 @@ can_convert_arg (tree to, tree from, tree arg, int flags)
 /* Like can_convert_arg, but allows dubious conversions as well.  */
 
 bool
-can_convert_arg_bad (tree to, tree from, tree arg)
+can_convert_arg_bad (tree to, tree from, tree arg, int flags)
 {
   conversion *t;
   void *p;
@@ -7222,7 +7415,7 @@ can_convert_arg_bad (tree to, tree from, tree arg)
   p = conversion_obstack_alloc (0);
   /* Try to perform the conversion.  */
   t  = implicit_conversion (to, from, arg, /*c_cast_p=*/false,
-                           LOOKUP_NORMAL);
+                           flags);
   /* Free all the conversions we allocated.  */
   obstack_free (&conversion_obstack, p);
 
@@ -7459,7 +7652,8 @@ set_up_extended_ref_temp (tree decl, tree expr, tree *cleanup, tree *initp)
    Return the converted expression.  */
 
 tree
-initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
+initialize_reference (tree type, tree expr, tree decl, tree *cleanup,
+                     tsubst_flags_t complain)
 {
   conversion *conv;
   void *p;
@@ -7474,15 +7668,19 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
                            LOOKUP_NORMAL);
   if (!conv || conv->bad_p)
     {
-      if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
-         && !real_lvalue_p (expr))
-       error ("invalid initialization of non-const reference of "
-              "type %qT from a temporary of type %qT",
-              type, TREE_TYPE (expr));
-      else
-       error ("invalid initialization of reference of type "
-              "%qT from expression of type %qT", type,
-              TREE_TYPE (expr));
+      if (complain & tf_error)
+       {
+         if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
+             && !TYPE_REF_IS_RVALUE (type)
+             && !real_lvalue_p (expr))
+           error ("invalid initialization of non-const reference of "
+                  "type %qT from an rvalue of type %qT",
+                  type, TREE_TYPE (expr));
+         else
+           error ("invalid initialization of reference of type "
+                  "%qT from expression of type %qT", type,
+                  TREE_TYPE (expr));
+       }
       return error_mark_node;
     }
 
@@ -7548,7 +7746,7 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
        expr = error_mark_node;
       else
        {
-         if (!real_lvalue_p (expr))
+         if (!lvalue_or_rvalue_with_address_p (expr))
            {
              tree init;
              var = set_up_extended_ref_temp (decl, expr, cleanup, &init);