OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / cp / typeck.c
index eb28a3d..f51722a 100644 (file)
@@ -1,6 +1,6 @@
 /* Build expressions with type checking for C++ compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
@@ -31,10 +31,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
-#include "expr.h"
 #include "cp-tree.h"
-#include "tm_p.h"
 #include "flags.h"
 #include "output.h"
 #include "toplev.h"
@@ -42,12 +39,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "target.h"
 #include "convert.h"
-#include "c-common.h"
+#include "c-family/c-common.h"
 #include "params.h"
 
 static tree pfn_from_ptrmemfunc (tree);
 static tree delta_from_ptrmemfunc (tree);
-static tree convert_for_assignment (tree, tree, const char *, tree, int,
+static tree convert_for_assignment (tree, tree, impl_conv_rhs, tree, int,
                                    tsubst_flags_t, int);
 static tree cp_pointer_int_sum (enum tree_code, tree, tree);
 static tree rationalize_conditional_expr (enum tree_code, tree, 
@@ -56,11 +53,12 @@ static int comp_ptr_ttypes_real (tree, tree, int);
 static bool comp_except_types (tree, tree, bool);
 static bool comp_array_types (const_tree, const_tree, bool);
 static tree pointer_diff (tree, tree, tree);
-static tree get_delta_difference (tree, tree, bool, bool);
+static tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t);
 static void casts_away_constness_r (tree *, tree *);
 static bool casts_away_constness (tree, tree);
 static void maybe_warn_about_returning_address_of_local (tree);
 static tree lookup_destructor (tree, tree, tree);
+static void warn_args_num (location_t, tree, bool);
 static int convert_arguments (tree, VEC(tree,gc) **, tree, int,
                               tsubst_flags_t);
 
@@ -352,6 +350,17 @@ cp_common_type (tree t1, tree t2)
                    : long_long_integer_type_node);
          return build_type_attribute_variant (t, attributes);
        }
+      if (int128_integer_type_node != NULL_TREE
+         && (same_type_p (TYPE_MAIN_VARIANT (t1),
+                          int128_integer_type_node)
+             || same_type_p (TYPE_MAIN_VARIANT (t2),
+                             int128_integer_type_node)))
+       {
+         tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+                   ? int128_unsigned_type_node
+                   : int128_integer_type_node);
+         return build_type_attribute_variant (t, attributes);
+       }
 
       /* Go through the same procedure, but for longs.  */
       if (same_type_p (TYPE_MAIN_VARIANT (t1), long_unsigned_type_node)
@@ -421,10 +430,11 @@ type_after_usual_arithmetic_conversions (tree t1, tree t2)
 }
 
 /* Subroutine of composite_pointer_type to implement the recursive
-   case.  See that function for documentation fo the parameters.  */
+   case.  See that function for documentation of the parameters.  */
 
 static tree
-composite_pointer_type_r (tree t1, tree t2, const char* location,
+composite_pointer_type_r (tree t1, tree t2, 
+                         composite_pointer_operation operation,
                          tsubst_flags_t complain)
 {
   tree pointee1;
@@ -457,14 +467,33 @@ composite_pointer_type_r (tree t1, tree t2, const char* location,
            && TREE_CODE (pointee2) == POINTER_TYPE)
           || (TYPE_PTR_TO_MEMBER_P (pointee1)
               && TYPE_PTR_TO_MEMBER_P (pointee2)))
-    result_type = composite_pointer_type_r (pointee1, pointee2, location,
+    result_type = composite_pointer_type_r (pointee1, pointee2, operation,
                                            complain);
   else
     {
       if (complain & tf_error)
-       permerror (input_location, "%s between distinct pointer types %qT and %qT "
-                  "lacks a cast",
-                  location, t1, t2);
+        {
+          switch (operation)
+            {
+            case CPO_COMPARISON:
+              permerror (input_location, "comparison between "
+                         "distinct pointer types %qT and %qT lacks a cast",
+                         t1, t2);
+              break;
+            case CPO_CONVERSION:
+              permerror (input_location, "conversion between "
+                         "distinct pointer types %qT and %qT lacks a cast",
+                         t1, t2);
+              break;
+            case CPO_CONDITIONAL_EXPR:
+              permerror (input_location, "conditional expression between "
+                         "distinct pointer types %qT and %qT lacks a cast",
+                         t1, t2);
+              break;
+            default:
+              gcc_unreachable ();
+            }
+        }
       result_type = void_type_node;
     }
   result_type = cp_build_qualified_type (result_type,
@@ -477,9 +506,28 @@ composite_pointer_type_r (tree t1, tree t2, const char* location,
       if (!same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1),
                        TYPE_PTRMEM_CLASS_TYPE (t2))
          && (complain & tf_error))
-       permerror (input_location, "%s between distinct pointer types %qT and %qT "
-                  "lacks a cast",
-                  location, t1, t2);
+        {
+          switch (operation)
+            {
+            case CPO_COMPARISON:
+              permerror (input_location, "comparison between "
+                         "distinct pointer types %qT and %qT lacks a cast", 
+                         t1, t2);
+              break;
+            case CPO_CONVERSION:
+              permerror (input_location, "conversion between "
+                         "distinct pointer types %qT and %qT lacks a cast",
+                         t1, t2);
+              break;
+            case CPO_CONDITIONAL_EXPR:
+              permerror (input_location, "conditional expression between "
+                         "distinct pointer types %qT and %qT lacks a cast",
+                         t1, t2);
+              break;
+            default:
+              gcc_unreachable ();
+            }
+        }
       result_type = build_ptrmem_type (TYPE_PTRMEM_CLASS_TYPE (t1),
                                       result_type);
     }
@@ -492,15 +540,17 @@ composite_pointer_type_r (tree t1, tree t2, const char* location,
 }
 
 /* Return the composite pointer type (see [expr.rel]) for T1 and T2.
-   ARG1 and ARG2 are the values with those types.  The LOCATION is a
-   string describing the current location, in case an error occurs.
+   ARG1 and ARG2 are the values with those types.  The OPERATION is to
+   describe the operation between the pointer types,
+   in case an error occurs.
 
    This routine also implements the computation of a common type for
    pointers-to-members as per [expr.eq].  */
 
 tree
 composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
-                       const char* location, tsubst_flags_t complain)
+                       composite_pointer_operation operation, 
+                       tsubst_flags_t complain)
 {
   tree class1;
   tree class2;
@@ -539,9 +589,28 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
       tree result_type;
 
       if (TYPE_PTRFN_P (t2) && (complain & tf_error))
-       pedwarn (input_location, OPT_pedantic, "ISO C++ forbids %s "
-                "between pointer of type %<void *%> and pointer-to-function",
-                location);
+        {
+          switch (operation)
+              {
+              case CPO_COMPARISON:
+                pedwarn (input_location, OPT_pedantic, 
+                         "ISO C++ forbids comparison between "
+                         "pointer of type %<void *%> and pointer-to-function");
+                break;
+              case CPO_CONVERSION:
+                pedwarn (input_location, OPT_pedantic,
+                         "ISO C++ forbids conversion between "
+                         "pointer of type %<void *%> and pointer-to-function");
+                break;
+              case CPO_CONDITIONAL_EXPR:
+                pedwarn (input_location, OPT_pedantic,
+                         "ISO C++ forbids conditional expression between "
+                         "pointer of type %<void *%> and pointer-to-function");
+                break;
+              default:
+                gcc_unreachable ();
+              }
+        }
       result_type
        = cp_build_qualified_type (void_type_node,
                                   (cp_type_quals (TREE_TYPE (t1))
@@ -572,22 +641,37 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
 
       if (DERIVED_FROM_P (class1, class2))
        t2 = (build_pointer_type
-             (cp_build_qualified_type (class1, TYPE_QUALS (class2))));
+             (cp_build_qualified_type (class1, cp_type_quals (class2))));
       else if (DERIVED_FROM_P (class2, class1))
        t1 = (build_pointer_type
-             (cp_build_qualified_type (class2, TYPE_QUALS (class1))));
+             (cp_build_qualified_type (class2, cp_type_quals (class1))));
       else
-       {
-         if (complain & tf_error)
-           error ("%s between distinct pointer types %qT and %qT "
-                  "lacks a cast", location, t1, t2);
-         return error_mark_node;
-       }
+        {
+          if (complain & tf_error)
+            switch (operation)
+              {
+              case CPO_COMPARISON:
+                error ("comparison between distinct "
+                       "pointer types %qT and %qT lacks a cast", t1, t2);
+                break;
+              case CPO_CONVERSION:
+                error ("conversion between distinct "
+                       "pointer types %qT and %qT lacks a cast", t1, t2);
+                break;
+              case CPO_CONDITIONAL_EXPR:
+                error ("conditional expression between distinct "
+                       "pointer types %qT and %qT lacks a cast", t1, t2);
+                break;
+              default:
+                gcc_unreachable ();
+              }
+          return error_mark_node;
+        }
     }
   /* [expr.eq] permits the application of a pointer-to-member
      conversion to change the class type of one of the types.  */
   else if (TYPE_PTR_TO_MEMBER_P (t1)
-          && !same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1),
+           && !same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1),
                            TYPE_PTRMEM_CLASS_TYPE (t2)))
     {
       class1 = TYPE_PTRMEM_CLASS_TYPE (t1);
@@ -598,15 +682,33 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
       else if (DERIVED_FROM_P (class2, class1))
        t2 = build_ptrmem_type (class1, TYPE_PTRMEM_POINTED_TO_TYPE (t2));
       else
-       {
-         if (complain & tf_error)
-           error ("%s between distinct pointer-to-member types %qT and %qT "
-                  "lacks a cast", location, t1, t2);
-         return error_mark_node;
-       }
+        {
+          if (complain & tf_error)
+            switch (operation)
+              {
+              case CPO_COMPARISON:
+                error ("comparison between distinct "
+                       "pointer-to-member types %qT and %qT lacks a cast",
+                       t1, t2);
+                break;
+              case CPO_CONVERSION:
+                error ("conversion between distinct "
+                       "pointer-to-member types %qT and %qT lacks a cast",
+                       t1, t2);
+                break;
+              case CPO_CONDITIONAL_EXPR:
+                error ("conditional expression between distinct "
+                       "pointer-to-member types %qT and %qT lacks a cast",
+                       t1, t2);
+                break;
+              default:
+                gcc_unreachable ();
+              }
+          return error_mark_node;
+        }
     }
 
-  return composite_pointer_type_r (t1, t2, location, complain);
+  return composite_pointer_type_r (t1, t2, operation, complain);
 }
 
 /* Return the merged type of two types.
@@ -716,6 +818,7 @@ merge_types (tree t1, tree t2)
        tree valtype = merge_types (TREE_TYPE (t1), TREE_TYPE (t2));
        tree p1 = TYPE_ARG_TYPES (t1);
        tree p2 = TYPE_ARG_TYPES (t2);
+       tree parms;
        tree rval, raises;
 
        /* Save space: see if the result is identical to one of the args.  */
@@ -726,22 +829,17 @@ merge_types (tree t1, tree t2)
 
        /* Simple way if one arg fails to specify argument types.  */
        if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
-         {
-           rval = build_function_type (valtype, p2);
-           if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
-             rval = build_exception_variant (rval, raises);
-           return cp_build_type_attribute_variant (rval, attributes);
-         }
-       raises = TYPE_RAISES_EXCEPTIONS (t1);
-       if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
-         {
-           rval = build_function_type (valtype, p1);
-           if (raises)
-             rval = build_exception_variant (rval, raises);
-           return cp_build_type_attribute_variant (rval, attributes);
-         }
+         parms = p2;
+       else if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
+         parms = p1;
+       else
+         parms = commonparms (p1, p2);
 
-       rval = build_function_type (valtype, commonparms (p1, p2));
+       rval = build_function_type (valtype, parms);
+       gcc_assert (type_memfn_quals (t1) == type_memfn_quals (t2));
+       rval = apply_memfn_quals (rval, type_memfn_quals (t1));
+       raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1),
+                                            TYPE_RAISES_EXCEPTIONS (t2));
        t1 = build_exception_variant (rval, raises);
        break;
       }
@@ -751,7 +849,8 @@ merge_types (tree t1, tree t2)
        /* Get this value the long way, since TYPE_METHOD_BASETYPE
           is just the main variant of this.  */
        tree basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));
-       tree raises = TYPE_RAISES_EXCEPTIONS (t1);
+       tree raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1),
+                                                 TYPE_RAISES_EXCEPTIONS (t2));
        tree t3;
 
        /* If this was a member function type, get back to the
@@ -785,6 +884,19 @@ merge_types (tree t1, tree t2)
     return cp_build_type_attribute_variant (t1, attributes);
 }
 
+/* Return the ARRAY_TYPE type without its domain.  */
+
+tree
+strip_array_domain (tree type)
+{
+  tree t2;
+  gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
+  if (TYPE_DOMAIN (type) == NULL_TREE)
+    return type;
+  t2 = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
+  return cp_build_type_attribute_variant (t2, TYPE_ATTRIBUTES (type));
+}
+
 /* Wrapper around cp_common_type that is used by c-common.c and other
    front end optimizations that remove promotions.  
 
@@ -820,7 +932,7 @@ common_pointer_type (tree t1, tree t2)
               || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2)));
 
   return composite_pointer_type (t1, t2, error_mark_node, error_mark_node,
-                                 "conversion", tf_warning_or_error);
+                                 CPO_CONVERSION, tf_warning_or_error);
 }
 \f
 /* Compare two exception specifier types for exactness or subsetness, if
@@ -869,13 +981,14 @@ comp_except_types (tree a, tree b, bool exact)
 }
 
 /* Return true if TYPE1 and TYPE2 are equivalent exception specifiers.
-   If EXACT is false, T2 can be stricter than T1 (according to 15.4/7),
-   otherwise it must be exact. Exception lists are unordered, but
-   we've already filtered out duplicates. Most lists will be in order,
-   we should try to make use of that.  */
+   If EXACT is ce_derived, T2 can be stricter than T1 (according to 15.4/5).
+   If EXACT is ce_normal, the compatibility rules in 15.4/3 apply.
+   If EXACT is ce_exact, the specs must be exactly the same. Exception lists
+   are unordered, but we've already filtered out duplicates. Most lists will
+   be in order, we should try to make use of that.  */
 
 bool
-comp_except_specs (const_tree t1, const_tree t2, bool exact)
+comp_except_specs (const_tree t1, const_tree t2, int exact)
 {
   const_tree probe;
   const_tree base;
@@ -884,14 +997,42 @@ comp_except_specs (const_tree t1, const_tree t2, bool exact)
   if (t1 == t2)
     return true;
 
+  /* First handle noexcept.  */
+  if (exact < ce_exact)
+    {
+      /* noexcept(false) is compatible with any throwing dynamic-exc-spec
+        and stricter than any spec.  */
+      if (t1 == noexcept_false_spec)
+       return !nothrow_spec_p (t2) || exact == ce_derived;
+      /* Even a derived noexcept(false) is compatible with a throwing
+        dynamic spec.  */
+      if (t2 == noexcept_false_spec)
+       return !nothrow_spec_p (t1);
+
+      /* Otherwise, if we aren't looking for an exact match, noexcept is
+        equivalent to throw().  */
+      if (t1 == noexcept_true_spec)
+       t1 = empty_except_spec;
+      if (t2 == noexcept_true_spec)
+       t2 = empty_except_spec;
+    }
+
+  /* If any noexcept is left, it is only comparable to itself;
+     either we're looking for an exact match or we're redeclaring a
+     template with dependent noexcept.  */
+  if ((t1 && TREE_PURPOSE (t1))
+      || (t2 && TREE_PURPOSE (t2)))
+    return (t1 && t2
+           && cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)));
+
   if (t1 == NULL_TREE)                    /* T1 is ...  */
-    return t2 == NULL_TREE || !exact;
+    return t2 == NULL_TREE || exact == ce_derived;
   if (!TREE_VALUE (t1))                           /* t1 is EMPTY */
     return t2 != NULL_TREE && !TREE_VALUE (t2);
   if (t2 == NULL_TREE)                    /* T2 is ...  */
     return false;
   if (TREE_VALUE (t1) && !TREE_VALUE (t2)) /* T2 is EMPTY, T1 is not */
-    return !exact;
+    return exact == ce_derived;
 
   /* Neither set is ... or EMPTY, make sure each part of T2 is in T1.
      Count how many we find, to determine exactness. For exact matching and
@@ -906,7 +1047,7 @@ comp_except_specs (const_tree t1, const_tree t2, bool exact)
 
          if (comp_except_types (a, b, exact))
            {
-             if (probe == base && exact)
+             if (probe == base && exact > ce_derived)
                base = TREE_CHAIN (probe);
              length++;
              break;
@@ -915,7 +1056,7 @@ comp_except_specs (const_tree t1, const_tree t2, bool exact)
       if (probe == NULL_TREE)
        return false;
     }
-  return !exact || base == NULL_TREE || length == list_length (t1);
+  return exact == ce_derived || base == NULL_TREE || length == list_length (t1);
 }
 
 /* Compare the array types T1 and T2.  ALLOW_REDECLARATION is true if
@@ -980,6 +1121,130 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
   return true;
 }
 
+/* Compare the relative position of T1 and T2 into their respective
+   template parameter list.
+   T1 and T2 must be template parameter types.
+   Return TRUE if T1 and T2 have the same position, FALSE otherwise.  */
+
+static bool
+comp_template_parms_position (tree t1, tree t2)
+{
+  gcc_assert (t1 && t2
+             && TREE_CODE (t1) == TREE_CODE (t2)
+             && (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
+                 || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
+                 || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
+
+      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
+         || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
+          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
+              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
+       return false;
+
+      return true;
+}
+
+/* Subroutine of incompatible_dependent_types_p.
+   Return the template parameter of the dependent type T.
+   If T is a typedef, return the template parameters of
+   the _decl_ of the typedef. T must be a dependent type.  */
+
+static tree
+get_template_parms_of_dependent_type (tree t)
+{
+  tree tinfo = NULL_TREE, tparms = NULL_TREE;
+
+  /* First, try the obvious case of getting the
+     template info from T itself.  */
+  if ((tinfo = get_template_info (t)))
+    ;
+  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
+  else if (typedef_variant_p (t)
+          && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
+    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
+  /* If T is a TYPENAME_TYPE which context is a template type
+     parameter, get the template parameters from that context.  */
+  else if (TYPE_CONTEXT (t)
+          && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
+   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
+  else if (TYPE_CONTEXT (t)
+          && !NAMESPACE_SCOPE_P (t))
+    tinfo = get_template_info (TYPE_CONTEXT (t));
+
+  if (tinfo)
+    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
+
+  return tparms;
+}
+
+/* Subroutine of structural_comptypes.
+   Compare the dependent types T1 and T2.
+   Return TRUE if we are sure they can't be equal, FALSE otherwise.
+   The whole point of this function is to support cases where either T1 or
+   T2 is a typedef. In those cases, we need to compare the template parameters
+   of the _decl_ of the typedef. If those don't match then we know T1
+   and T2 cannot be equal.  */
+
+static bool
+incompatible_dependent_types_p (tree t1, tree t2)
+{
+  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
+  bool t1_typedef_variant_p, t2_typedef_variant_p;
+
+  if (!uses_template_parms (t1) || !uses_template_parms (t2))
+    return false;
+
+  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
+    {
+      /* If T1 and T2 don't have the same relative position in their
+        template parameters set, they can't be equal.  */
+      if (!comp_template_parms_position (t1, t2))
+       return true;
+    }
+
+  t1_typedef_variant_p = typedef_variant_p (t1);
+  t2_typedef_variant_p = typedef_variant_p (t2);
+
+  /* Either T1 or T2 must be a typedef.  */
+  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+    return false;
+
+  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
+    /* Either T1 or T2 is not a typedef so we cannot compare the
+       the template parms of the typedefs of T1 and T2.
+       At this point, if the main variant type of T1 and T2 are equal
+       it means the two types can't be incompatible, from the perspective
+       of this function.  */
+    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+      return false;
+
+  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
+     Let's compare their template parameters.  */
+
+  tparms1 = get_template_parms_of_dependent_type (t1);
+  tparms2 = get_template_parms_of_dependent_type (t2);
+
+  /* If T2 is a template type parm and if we could not get the template
+     parms it belongs to, that means we have not finished parsing the
+     full set of template parameters of the template declaration it
+     belongs to yet. If we could get the template parms T1 belongs to,
+     that mostly means T1 and T2 belongs to templates that are
+     different and incompatible.  */
+  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
+      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
+      && tparms1 != tparms2)
+    return true;
+
+  if (tparms1 == NULL_TREE
+      || tparms2 == NULL_TREE
+      || tparms1 == tparms2)
+    return false;
+
+  /* And now compare the mighty template parms!  */
+  return !comp_template_parms (tparms1, tparms2);
+}
+
 /* Subroutine in comptypes.  */
 
 static bool
@@ -1014,11 +1279,20 @@ structural_comptypes (tree t1, tree t2, int strict)
   /* Qualifiers must match.  For array types, we will check when we
      recur on the array element types.  */
   if (TREE_CODE (t1) != ARRAY_TYPE
-      && TYPE_QUALS (t1) != TYPE_QUALS (t2))
+      && cp_type_quals (t1) != cp_type_quals (t2))
+    return false;
+  if (TREE_CODE (t1) == FUNCTION_TYPE
+      && type_memfn_quals (t1) != type_memfn_quals (t2))
     return false;
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
+  /* If T1 and T2 are dependent typedefs then check upfront that
+     the template parameters of their typedef DECLs match before
+     going down checking their subtypes.  */
+  if (incompatible_dependent_types_p (t1, t2))
+    return false;
+
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1027,6 +1301,7 @@ structural_comptypes (tree t1, tree t2, int strict)
       && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
     return true;
 
+
   /* Compare the types.  Break out if they could be the same.  */
   switch (TREE_CODE (t1))
     {
@@ -1056,10 +1331,7 @@ structural_comptypes (tree t1, tree t2, int strict)
 
     case TEMPLATE_TEMPLATE_PARM:
     case BOUND_TEMPLATE_TEMPLATE_PARM:
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-         || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
+      if (!comp_template_parms_position (t1, t2))
        return false;
       if (!comp_template_parms
          (DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
@@ -1121,11 +1393,8 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-         || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-       return false;
+      /* If incompatible_dependent_types_p called earlier didn't decide
+         T1 and T2 were different, they might be equal.  */
       break;
 
     case TYPENAME_TYPE:
@@ -1161,6 +1430,10 @@ structural_comptypes (tree t1, tree t2, int strict)
     case DECLTYPE_TYPE:
       if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t1)
           != DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t2)
+         || (DECLTYPE_FOR_LAMBDA_CAPTURE (t1)
+             != DECLTYPE_FOR_LAMBDA_CAPTURE (t2))
+         || (DECLTYPE_FOR_LAMBDA_RETURN (t1)
+             != DECLTYPE_FOR_LAMBDA_RETURN (t2))
           || !cp_tree_equal (DECLTYPE_TYPE_EXPR (t1), 
                              DECLTYPE_TYPE_EXPR (t2)))
         return false;
@@ -1349,7 +1622,7 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain)
       return value;
     }
 
-  return c_sizeof_or_alignof_type (complete_type (type),
+  return c_sizeof_or_alignof_type (input_location, complete_type (type),
                                   op == SIZEOF_EXPR,
                                   complain);
 }
@@ -1388,6 +1661,15 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain)
       return e;
     }
 
+  /* To get the size of a static data member declared as an array of
+     unknown bound, we need to instantiate it.  */
+  if (TREE_CODE (e) == VAR_DECL
+      && VAR_HAD_UNKNOWN_BOUND (e)
+      && DECL_TEMPLATE_INSTANTIATION (e))
+    instantiate_decl (e, /*defer_ok*/true, /*expl_inst_mem*/false);
+
+  e = mark_type_use (e);
+
   if (TREE_CODE (e) == COMPONENT_REF
       && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL
       && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
@@ -1443,6 +1725,8 @@ cxx_alignof_expr (tree e, tsubst_flags_t complain)
       return e;
     }
 
+  e = mark_type_use (e);
+
   if (TREE_CODE (e) == VAR_DECL)
     t = size_int (DECL_ALIGN_UNIT (e));
   else if (TREE_CODE (e) == COMPONENT_REF
@@ -1592,7 +1876,9 @@ unlowered_expr_type (const_tree exp)
    in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and
    function-to-pointer conversions.  In addition, manifest constants
    are replaced by their values, and bitfield references are converted
-   to their declared types.
+   to their declared types. Note that this function does not perform the
+   lvalue-to-rvalue conversion for class types. If you need that conversion
+   to for class types, then you probably need to use force_rvalue.
 
    Although the returned value is being used as an rvalue, this
    function does not wrap the returned expression in a
@@ -1609,6 +1895,9 @@ decay_conversion (tree exp)
   if (type == error_mark_node)
     return error_mark_node;
 
+  exp = mark_rvalue_use (exp);
+
+  exp = resolve_nondeduced_context (exp);
   if (type_unknown_p (exp))
     {
       cxx_incomplete_type_error (exp, TREE_TYPE (exp));
@@ -1685,8 +1974,8 @@ decay_conversion (tree exp)
 
      Non-class rvalues always have cv-unqualified types.  */
   type = TREE_TYPE (exp);
-  if (!CLASS_TYPE_P (type) && cp_type_quals (type))
-    exp = build_nop (TYPE_MAIN_VARIANT (type), exp);
+  if (!CLASS_TYPE_P (type) && cv_qualified_p (type))
+    exp = build_nop (cv_unqualified (type), exp);
 
   return exp;
 }
@@ -1732,6 +2021,8 @@ perform_integral_promotions (tree expr)
   tree type;
   tree promoted_type;
 
+  expr = mark_rvalue_use (expr);
+
   /* [conv.prom]
 
      If the bitfield has an enumerated type, it is treated as any
@@ -1773,7 +2064,7 @@ string_conv_p (const_tree totype, const_tree exp, int warn)
   else
     {
       /* Is this a string constant which has decayed to 'const char *'?  */
-      t = build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST));
+      t = build_pointer_type (cp_build_qualified_type (t, TYPE_QUAL_CONST));
       if (!same_type_p (TREE_TYPE (exp), t))
        return 0;
       STRIP_NOPS (exp);
@@ -1845,7 +2136,7 @@ lookup_anon_field (tree t, tree type)
 {
   tree field;
 
-  for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+  for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
     {
       if (TREE_STATIC (field))
        continue;
@@ -1950,7 +2241,7 @@ build_class_member_access_expr (tree object, tree member,
   {
     tree temp = unary_complex_lvalue (ADDR_EXPR, object);
     if (temp)
-      object = cp_build_indirect_ref (temp, NULL, complain);
+      object = cp_build_indirect_ref (temp, RO_NULL, complain);
   }
 
   /* In [expr.ref], there is an explicit list of the valid choices for
@@ -1959,6 +2250,7 @@ build_class_member_access_expr (tree object, tree member,
     {
       /* A static data member.  */
       result = member;
+      mark_exp_read (object);
       /* If OBJECT has side-effects, they are supposed to occur.  */
       if (TREE_SIDE_EFFECTS (object))
        result = build2 (COMPOUND_EXPR, TREE_TYPE (result), object, result);
@@ -2017,9 +2309,9 @@ build_class_member_access_expr (tree object, tree member,
         in various testsuite cases where a null object is passed where a
         vtable access is required.  */
       if (null_object_p && warn_invalid_offsetof
-         && CLASSTYPE_NON_POD_P (object_type)
+         && CLASSTYPE_NON_STD_LAYOUT (object_type)
          && !DECL_FIELD_IS_BASE (member)
-         && !skip_evaluation
+         && cp_unevaluated_operand == 0
          && (complain & tf_warning))
        {
          warning (OPT_Winvalid_offsetof, 
@@ -2331,6 +2623,14 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
          gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE
                      || TREE_CODE (name) == BIT_NOT_EXPR);
 
+         if (constructor_name_p (name, scope))
+           {
+             if (complain & tf_error)
+               error ("cannot call constructor %<%T::%D%> directly",
+                      scope, name);
+             return error_mark_node;
+           }
+
          /* Find the base of OBJECT_TYPE corresponding to SCOPE.  */
          access_path = lookup_base (object_type, scope, ba_check, NULL);
          if (access_path == error_mark_node)
@@ -2429,7 +2729,8 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
                          /*want_type=*/false);
   member_type = cp_build_qualified_type (TREE_TYPE (member),
                                         cp_type_quals (ptrmem_type));
-  return fold_build3 (COMPONENT_REF, member_type,
+  return fold_build3_loc (input_location,
+                     COMPONENT_REF, member_type,
                      ptrmem, member, NULL_TREE);
 }
 
@@ -2441,7 +2742,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
    Must also handle REFERENCE_TYPEs for C++.  */
 
 tree
-build_x_indirect_ref (tree expr, const char *errorstring, 
+build_x_indirect_ref (tree expr, ref_operator errorstring, 
                       tsubst_flags_t complain)
 {
   tree orig_expr = expr;
@@ -2449,6 +2750,10 @@ build_x_indirect_ref (tree expr, const char *errorstring,
 
   if (processing_template_decl)
     {
+      /* Retain the type if we know the operand is a pointer so that
+        describable_type doesn't make auto deduction break.  */
+      if (TREE_TYPE (expr) && POINTER_TYPE_P (TREE_TYPE (expr)))
+       return build_min (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr);
       if (type_dependent_expression_p (expr))
        return build_min_nt (INDIRECT_REF, expr);
       expr = build_non_dependent_expr (expr);
@@ -2468,13 +2773,13 @@ build_x_indirect_ref (tree expr, const char *errorstring,
 /* Helper function called from c-common.  */
 tree
 build_indirect_ref (location_t loc __attribute__ ((__unused__)),
-                   tree ptr, const char *errorstring)
+                   tree ptr, ref_operator errorstring)
 {
   return cp_build_indirect_ref (ptr, errorstring, tf_warning_or_error);
 }
 
 tree
-cp_build_indirect_ref (tree ptr, const char *errorstring, 
+cp_build_indirect_ref (tree ptr, ref_operator errorstring, 
                        tsubst_flags_t complain)
 {
   tree pointer, type;
@@ -2542,14 +2847,38 @@ cp_build_indirect_ref (tree ptr, const char *errorstring,
   /* `pointer' won't be an error_mark_node if we were given a
      pointer to member, so it's cool to check for this here.  */
   else if (TYPE_PTR_TO_MEMBER_P (type))
-    error ("invalid use of %qs on pointer to member", errorstring);
+    switch (errorstring)
+      {
+         case RO_ARRAY_INDEXING:
+           error ("invalid use of array indexing on pointer to member");
+           break;
+         case RO_UNARY_STAR:
+           error ("invalid use of unary %<*%> on pointer to member");
+           break;
+         case RO_IMPLICIT_CONVERSION:
+           error ("invalid use of implicit conversion on pointer to member");
+           break;
+         default:
+           gcc_unreachable ();
+      }
   else if (pointer != error_mark_node)
-    {
-      if (errorstring)
-       error ("invalid type argument of %qs", errorstring);
-      else
-       error ("invalid type argument");
-    }
+    switch (errorstring)
+      {
+         case RO_NULL:
+           error ("invalid type argument");
+           break;
+         case RO_ARRAY_INDEXING:
+           error ("invalid type argument of array indexing");
+           break;
+         case RO_UNARY_STAR:
+           error ("invalid type argument of unary %<*%>");
+           break;
+         case RO_IMPLICIT_CONVERSION:
+           error ("invalid type argument of implicit conversion");
+           break;
+         default:
+           gcc_unreachable ();
+      }
   return error_mark_node;
 }
 
@@ -2569,13 +2898,15 @@ cp_build_indirect_ref (tree ptr, const char *errorstring,
    LOC is the location to use in building the array reference.  */
 
 tree
-build_array_ref (tree array, tree idx, location_t loc)
+cp_build_array_ref (location_t loc, tree array, tree idx,
+                   tsubst_flags_t complain)
 {
   tree ret;
 
   if (idx == 0)
     {
-      error_at (loc, "subscript missing in array reference");
+      if (complain & tf_error)
+       error_at (loc, "subscript missing in array reference");
       return error_mark_node;
     }
 
@@ -2589,7 +2920,8 @@ build_array_ref (tree array, tree idx, location_t loc)
     {
     case COMPOUND_EXPR:
       {
-       tree value = build_array_ref (TREE_OPERAND (array, 1), idx, loc);
+       tree value = cp_build_array_ref (loc, TREE_OPERAND (array, 1), idx,
+                                        complain);
        ret = build2 (COMPOUND_EXPR, TREE_TYPE (value),
                      TREE_OPERAND (array, 0), value);
        SET_EXPR_LOCATION (ret, loc);
@@ -2599,9 +2931,11 @@ build_array_ref (tree array, tree idx, location_t loc)
     case COND_EXPR:
       ret = build_conditional_expr
              (TREE_OPERAND (array, 0),
-             build_array_ref (TREE_OPERAND (array, 1), idx, loc),
-             build_array_ref (TREE_OPERAND (array, 2), idx, loc),
-             tf_warning_or_error);
+              cp_build_array_ref (loc, TREE_OPERAND (array, 1), idx,
+                                  complain),
+              cp_build_array_ref (loc, TREE_OPERAND (array, 2), idx,
+                                  complain),
+              tf_warning_or_error);
       protected_set_expr_location (ret, loc);
       return ret;
 
@@ -2617,7 +2951,8 @@ build_array_ref (tree array, tree idx, location_t loc)
 
       if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (idx)))
        {
-         error_at (loc, "array subscript is not an integer");
+         if (complain & tf_error)
+           error_at (loc, "array subscript is not an integer");
          return error_mark_node;
        }
 
@@ -2653,7 +2988,7 @@ build_array_ref (tree array, tree idx, location_t loc)
            return error_mark_node;
        }
 
-      if (!lvalue_p (array))
+      if (!lvalue_p (array) && (complain & tf_error))
        pedwarn (loc, OPT_pedantic, 
                 "ISO C++ forbids subscripting non-lvalue array");
 
@@ -2665,7 +3000,8 @@ build_array_ref (tree array, tree idx, location_t loc)
          tree foo = array;
          while (TREE_CODE (foo) == COMPONENT_REF)
            foo = TREE_OPERAND (foo, 0);
-         if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
+         if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)
+             && (complain & tf_warning))
            warning_at (loc, OPT_Wextra,
                        "subscripting array declared %<register%>");
        }
@@ -2702,12 +3038,14 @@ build_array_ref (tree array, tree idx, location_t loc)
 
     if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE)
       {
-       error_at (loc, "subscripted value is neither array nor pointer");
+       if (complain & tf_error)
+         error_at (loc, "subscripted value is neither array nor pointer");
        return error_mark_node;
       }
     if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE)
       {
-       error_at (loc, "array subscript is not an integer");
+       if (complain & tf_error)
+         error_at (loc, "array subscript is not an integer");
        return error_mark_node;
       }
 
@@ -2715,13 +3053,21 @@ build_array_ref (tree array, tree idx, location_t loc)
 
     ret = cp_build_indirect_ref (cp_build_binary_op (input_location,
                                                     PLUS_EXPR, ar, ind,
-                                                    tf_warning_or_error),
-                                 "array indexing",
-                                 tf_warning_or_error);
+                                                    complain),
+                                 RO_ARRAY_INDEXING,
+                                 complain);
     protected_set_expr_location (ret, loc);
     return ret;
   }
 }
+
+/* Entry point for Obj-C++.  */
+
+tree
+build_array_ref (location_t loc, tree array, tree idx)
+{
+  return cp_build_array_ref (loc, array, idx, tf_warning_or_error);
+}
 \f
 /* Resolve a pointer to member function.  INSTANCE is the object
    instance to use, if the member points to a virtual member.
@@ -2825,16 +3171,17 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
       /* Next extract the vtable pointer from the object.  */
       vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
                     instance_ptr);
-      vtbl = cp_build_indirect_ref (vtbl, NULL, tf_warning_or_error);
+      vtbl = cp_build_indirect_ref (vtbl, RO_NULL, tf_warning_or_error);
       /* If the object is not dynamic the access invokes undefined
         behavior.  As it is not executed in this case silence the
         spurious warnings it may provoke.  */
       TREE_NO_WARNING (vtbl) = 1;
 
       /* Finally, extract the function pointer from the vtable.  */
-      e2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
+      e2 = fold_build2_loc (input_location,
+                       POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
                        fold_convert (sizetype, idx));
-      e2 = cp_build_indirect_ref (e2, NULL, tf_warning_or_error);
+      e2 = cp_build_indirect_ref (e2, RO_NULL, tf_warning_or_error);
       TREE_CONSTANT (e2) = 1;
 
       /* When using function descriptors, the address of the
@@ -2860,14 +3207,16 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
 
 /* Used by the C-common bits.  */
 tree
-build_function_call (tree function, tree params)
+build_function_call (location_t loc ATTRIBUTE_UNUSED, 
+                    tree function, tree params)
 {
   return cp_build_function_call (function, params, tf_warning_or_error);
 }
 
 /* Used by the C-common bits.  */
 tree
-build_function_call_vec (tree function, VEC(tree,gc) *params,
+build_function_call_vec (location_t loc ATTRIBUTE_UNUSED,
+                        tree function, VEC(tree,gc) *params,
                         VEC(tree,gc) *origtypes ATTRIBUTE_UNUSED)
 {
   VEC(tree,gc) *orig_params = params;
@@ -2898,6 +3247,25 @@ cp_build_function_call (tree function, tree params, tsubst_flags_t complain)
   return ret;
 }
 
+/* Build a function call using varargs.  */
+
+tree
+cp_build_function_call_nary (tree function, tsubst_flags_t complain, ...)
+{
+  VEC(tree,gc) *vec;
+  va_list args;
+  tree ret, t;
+
+  vec = make_tree_vector ();
+  va_start (args, complain);
+  for (t = va_arg (args, tree); t != NULL_TREE; t = va_arg (args, tree))
+    VEC_safe_push (tree, gc, vec, t);
+  va_end (args);
+  ret = cp_build_function_call_vec (function, &vec, complain);
+  release_tree_vector (vec);
+  return ret;
+}
+
 /* Build a function call using a vector of arguments.  PARAMS may be
    NULL if there are no parameters.  This changes the contents of
    PARAMS.  */
@@ -2907,7 +3275,6 @@ cp_build_function_call_vec (tree function, VEC(tree,gc) **params,
                            tsubst_flags_t complain)
 {
   tree fntype, fndecl;
-  tree name = NULL_TREE;
   int is_method;
   tree original = function;
   int nargs;
@@ -2930,8 +3297,6 @@ cp_build_function_call_vec (tree function, VEC(tree,gc) **params,
 
   if (TREE_CODE (function) == FUNCTION_DECL)
     {
-      name = DECL_NAME (function);
-
       mark_used (function);
       fndecl = function;
 
@@ -3006,6 +3371,44 @@ cp_build_function_call_vec (tree function, VEC(tree,gc) **params,
   return ret;
 }
 \f
+/* Subroutine of convert_arguments.
+   Warn about wrong number of args are genereted. */
+
+static void
+warn_args_num (location_t loc, tree fndecl, bool too_many_p)
+{
+  if (fndecl)
+    {
+      if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
+       {
+         if (DECL_NAME (fndecl) == NULL_TREE
+             || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
+           error_at (loc,
+                     too_many_p
+                     ? G_("too many arguments to constructor %q#D")
+                     : G_("too few arguments to constructor %q#D"),
+                     fndecl);
+         else
+           error_at (loc,
+                     too_many_p
+                     ? G_("too many arguments to member function %q#D")
+                     : G_("too few arguments to member function %q#D"),
+                     fndecl);
+       }
+      else
+       error_at (loc,
+                 too_many_p
+                 ? G_("too many arguments to function %q#D")
+                 : G_("too few arguments to function %q#D"),
+                 fndecl);
+      inform (DECL_SOURCE_LOCATION (fndecl),
+             "declared here");
+    }
+  else
+    error_at (loc, too_many_p ? G_("too many arguments to function")
+                             : G_("too few arguments to function"));
+}
+
 /* Convert the actual parameter expressions in the list VALUES to the
    types in the list TYPELIST.  The converted expressions are stored
    back in the VALUES vector.
@@ -3027,26 +3430,11 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
                   int flags, tsubst_flags_t complain)
 {
   tree typetail;
-  const char *called_thing = 0;
   unsigned int i;
 
   /* Argument passing is always copy-initialization.  */
   flags |= LOOKUP_ONLYCONVERTING;
 
-  if (fndecl)
-    {
-      if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
-       {
-         if (DECL_NAME (fndecl) == NULL_TREE
-             || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
-           called_thing = "constructor";
-         else
-           called_thing = "member function";
-       }
-      else
-       called_thing = "function";
-    }
-
   for (i = 0, typetail = typelist;
        i < VEC_length (tree, *values);
        i++)
@@ -3061,14 +3449,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
        {
           if (complain & tf_error)
             {
-              if (fndecl)
-                {
-                  error ("too many arguments to %s %q+#D", 
-                         called_thing, fndecl);
-                  error ("at this point in file");
-                }
-              else
-                error ("too many arguments to function");
+             warn_args_num (input_location, fndecl, /*too_many_p=*/true);
               return i;
             }
           else
@@ -3114,7 +3495,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
            {
              parmval = convert_for_initialization
                (NULL_TREE, type, val, flags,
-                "argument passing", fndecl, i, complain);
+                ICR_ARGPASS, fndecl, i, complain);
              parmval = convert_for_arg_passing (type, parmval);
            }
 
@@ -3128,7 +3509,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
          if (fndecl && DECL_BUILT_IN (fndecl)
              && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
            /* Don't do ellipsis conversion for __built_in_constant_p
-              as this will result in spurious warnings for non-POD
+              as this will result in spurious errors for non-trivial
               types.  */
            val = require_complete_type (val);
          else
@@ -3173,16 +3554,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
       else
        {
           if (complain & tf_error)
-            {
-              if (fndecl)
-                {
-                  error ("too few arguments to %s %q+#D", 
-                         called_thing, fndecl);
-                  error ("at this point in file");
-                }
-              else
-                error ("too few arguments to function");
-            }
+           warn_args_num (input_location, fndecl, /*too_many_p=*/false);
          return -1;
        }
     }
@@ -3232,6 +3604,7 @@ build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code,
      misinterpret.  But don't warn about obj << x + y, since that is a
      common idiom for I/O.  */
   if (warn_parentheses
+      && (complain & tf_warning)
       && !processing_template_decl
       && !error_operand_p (arg1)
       && !error_operand_p (arg2)
@@ -3413,7 +3786,6 @@ cp_build_binary_op (location_t location,
 
   /* If an error was already reported for one of the arguments,
      avoid reporting another error.  */
-
   if (code0 == ERROR_MARK || code1 == ERROR_MARK)
     return error_mark_node;
 
@@ -3424,6 +3796,25 @@ cp_build_binary_op (location_t location,
       return error_mark_node;
     }
 
+  /* Issue warnings about peculiar, but valid, uses of NULL.  */
+  if ((orig_op0 == null_node || orig_op1 == null_node)
+      /* It's reasonable to use pointer values as operands of &&
+        and ||, so NULL is no exception.  */
+      && code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR 
+      && ( /* Both are NULL (or 0) and the operation was not a
+             comparison or a pointer subtraction.  */
+         (null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1) 
+          && code != EQ_EXPR && code != NE_EXPR && code != MINUS_EXPR) 
+         /* Or if one of OP0 or OP1 is neither a pointer nor NULL.  */
+         || (!null_ptr_cst_p (orig_op0)
+             && !TYPE_PTR_P (type0) && !TYPE_PTR_TO_MEMBER_P (type0))
+         || (!null_ptr_cst_p (orig_op1) 
+             && !TYPE_PTR_P (type1) && !TYPE_PTR_TO_MEMBER_P (type1)))
+      && (complain & tf_warning))
+    /* Some sort of arithmetic operation involving NULL was
+       performed.  */
+    warning (OPT_Wpointer_arith, "NULL used in arithmetic");
+
   switch (code)
     {
     case MINUS_EXPR:
@@ -3553,13 +3944,15 @@ cp_build_binary_op (location_t location,
            {
              if (tree_int_cst_lt (op1, integer_zero_node))
                {
-                 if (complain & tf_warning)
+                 if ((complain & tf_warning)
+                     && c_inhibit_evaluation_warnings == 0)
                    warning (0, "right shift count is negative");
                }
              else
                {
                  if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0
-                     && (complain & tf_warning))
+                     && (complain & tf_warning)
+                     && c_inhibit_evaluation_warnings == 0)
                    warning (0, "right shift count >= width of type");
                }
            }
@@ -3580,12 +3973,14 @@ cp_build_binary_op (location_t location,
            {
              if (tree_int_cst_lt (op1, integer_zero_node))
                {
-                 if (complain & tf_warning)
+                 if ((complain & tf_warning)
+                     && c_inhibit_evaluation_warnings == 0)
                    warning (0, "left shift count is negative");
                }
              else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
                {
-                 if (complain & tf_warning)
+                 if ((complain & tf_warning)
+                     && c_inhibit_evaluation_warnings == 0)
                    warning (0, "left shift count >= width of type");
                }
            }
@@ -3647,7 +4042,7 @@ cp_build_binary_op (location_t location,
       else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE)
               || (TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1)))
        result_type = composite_pointer_type (type0, type1, op0, op1,
-                                             "comparison", complain);
+                                             CPO_COMPARISON, complain);
       else if ((code0 == POINTER_TYPE || TYPE_PTRMEM_P (type0))
               && null_ptr_cst_p (op1))
        {
@@ -3672,6 +4067,9 @@ cp_build_binary_op (location_t location,
            }
          result_type = type1;
        }
+      else if (null_ptr_cst_p (op0) && null_ptr_cst_p (op1))
+       /* One of the operands must be of nullptr_t type.  */
+        result_type = TREE_TYPE (nullptr_node);
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
          result_type = type0;
@@ -3736,8 +4134,8 @@ cp_build_binary_op (location_t location,
          tree delta0;
          tree delta1;
 
-         type = composite_pointer_type (type0, type1, op0, op1, "comparison",
-                                        complain);
+         type = composite_pointer_type (type0, type1, op0, op1, 
+                                        CPO_COMPARISON, complain);
 
          if (!same_type_p (TREE_TYPE (op0), type))
            op0 = cp_convert_and_check (type, op0);
@@ -3848,7 +4246,7 @@ cp_build_binary_op (location_t location,
        shorten = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        result_type = composite_pointer_type (type0, type1, op0, op1,
-                                             "comparison", complain);
+                                             CPO_COMPARISON, complain);
       break;
 
     case LE_EXPR:
@@ -3863,18 +4261,21 @@ cp_build_binary_op (location_t location,
        }
 
       build_type = boolean_type_node;
-      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
-          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+          || code0 == ENUMERAL_TYPE)
+          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+              || code1 == ENUMERAL_TYPE))
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        result_type = composite_pointer_type (type0, type1, op0, op1,
-                                             "comparison", complain);
-      else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
-              && integer_zerop (op1))
+                                             CPO_COMPARISON, complain);
+      else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1))
        result_type = type0;
-      else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
-              && integer_zerop (op0))
+      else if (code1 == POINTER_TYPE && null_ptr_cst_p (op0))
        result_type = type1;
+      else if (null_ptr_cst_p (op0) && null_ptr_cst_p (op1))
+       /* One of the operands must be of nullptr_t type.  */
+        result_type = TREE_TYPE (nullptr_node);
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
          result_type = type0;
@@ -3966,7 +4367,83 @@ cp_build_binary_op (location_t location,
 
   if (arithmetic_types_p)
     {
-      int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
+      bool first_complex = (code0 == COMPLEX_TYPE);
+      bool second_complex = (code1 == COMPLEX_TYPE);
+      int none_complex = (!first_complex && !second_complex);
+
+      /* Adapted from patch for c/24581.  */
+      if (first_complex != second_complex
+         && (code == PLUS_EXPR
+             || code == MINUS_EXPR
+             || code == MULT_EXPR
+             || (code == TRUNC_DIV_EXPR && first_complex))
+         && TREE_CODE (TREE_TYPE (result_type)) == REAL_TYPE
+         && flag_signed_zeros)
+       {
+         /* An operation on mixed real/complex operands must be
+            handled specially, but the language-independent code can
+            more easily optimize the plain complex arithmetic if
+            -fno-signed-zeros.  */
+         tree real_type = TREE_TYPE (result_type);
+         tree real, imag;
+         if (first_complex)
+           {
+             if (TREE_TYPE (op0) != result_type)
+               op0 = cp_convert_and_check (result_type, op0);
+             if (TREE_TYPE (op1) != real_type)
+               op1 = cp_convert_and_check (real_type, op1);
+           }
+         else
+           {
+             if (TREE_TYPE (op0) != real_type)
+               op0 = cp_convert_and_check (real_type, op0);
+             if (TREE_TYPE (op1) != result_type)
+               op1 = cp_convert_and_check (result_type, op1);
+           }
+         if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
+           return error_mark_node;
+         if (first_complex)
+           {
+             op0 = save_expr (op0);
+             real = cp_build_unary_op (REALPART_EXPR, op0, 1, complain);
+             imag = cp_build_unary_op (IMAGPART_EXPR, op0, 1, complain);
+             switch (code)
+               {
+               case MULT_EXPR:
+               case TRUNC_DIV_EXPR:
+                 imag = build2 (resultcode, real_type, imag, op1);
+                 /* Fall through.  */
+               case PLUS_EXPR:
+               case MINUS_EXPR:
+                 real = build2 (resultcode, real_type, real, op1);
+                 break;
+               default:
+                 gcc_unreachable();
+               }
+           }
+         else
+           {
+             op1 = save_expr (op1);
+             real = cp_build_unary_op (REALPART_EXPR, op1, 1, complain);
+             imag = cp_build_unary_op (IMAGPART_EXPR, op1, 1, complain);
+             switch (code)
+               {
+               case MULT_EXPR:
+                 imag = build2 (resultcode, real_type, op0, imag);
+                 /* Fall through.  */
+               case PLUS_EXPR:
+                 real = build2 (resultcode, real_type, op0, real);
+                 break;
+               case MINUS_EXPR:
+                 real = build2 (resultcode, real_type, op0, real);
+                 imag = build1 (NEGATE_EXPR, real_type, imag);
+                 break;
+               default:
+                 gcc_unreachable();
+               }
+           }
+         return build2 (COMPLEX_EXPR, result_type, real, imag);
+       }
 
       /* For certain operations (which identify themselves by shorten != 0)
         if both args were extended from the same smaller type,
@@ -4008,35 +4485,19 @@ cp_build_binary_op (location_t location,
 
       if ((short_compare || code == MIN_EXPR || code == MAX_EXPR)
          && warn_sign_compare
+         && !TREE_NO_WARNING (orig_op0)
+         && !TREE_NO_WARNING (orig_op1)
          /* Do not warn until the template is instantiated; we cannot
             bound the ranges of the arguments until that point.  */
          && !processing_template_decl
-          && (complain & tf_warning))
+          && (complain & tf_warning)
+         && c_inhibit_evaluation_warnings == 0)
        {
          warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1, 
                                 result_type, resultcode);
        }
     }
 
-  /* Issue warnings about peculiar, but valid, uses of NULL.  */
-  if ((orig_op0 == null_node || orig_op1 == null_node)
-      /* It's reasonable to use pointer values as operands of &&
-        and ||, so NULL is no exception.  */
-      && code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR 
-      && ( /* Both are NULL (or 0) and the operation was not a comparison.  */
-         (null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1) 
-          && code != EQ_EXPR && code != NE_EXPR) 
-         /* Or if one of OP0 or OP1 is neither a pointer nor NULL.  */
-         || (!null_ptr_cst_p (orig_op0) && TREE_CODE (TREE_TYPE (op0)) != POINTER_TYPE)
-         || (!null_ptr_cst_p (orig_op1) && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE))
-      && (complain & tf_warning))
-    /* Some sort of arithmetic operation involving NULL was
-       performed.  Note that pointer-difference and pointer-addition
-       have already been handled above, and so we don't end up here in
-       that case.  */
-    warning (OPT_Wpointer_arith, "NULL used in arithmetic");
-  
-
   /* If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
      Then the expression will be built.
      It will be given type FINAL_TYPE if that is nonzero;
@@ -4063,7 +4524,7 @@ cp_build_binary_op (location_t location,
   if (TREE_OVERFLOW_P (result) 
       && !TREE_OVERFLOW_P (op0) 
       && !TREE_OVERFLOW_P (op1))
-    overflow_warning (result);
+    overflow_warning (location, result);
 
   return result;
 }
@@ -4083,7 +4544,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
      pointer_int_sum() anyway.  */
   complete_type (TREE_TYPE (res_type));
 
-  return pointer_int_sum (resultcode, ptrop,
+  return pointer_int_sum (input_location, resultcode, ptrop,
                          fold_if_not_in_template (intop));
 }
 
@@ -4175,9 +4636,10 @@ build_x_unary_op (enum tree_code code, tree xarg, tsubst_flags_t complain)
          tree fn = get_first_fn (xarg);
          if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn))
            {
-             const char *type =
-               (DECL_CONSTRUCTOR_P (fn) ? "constructor" : "destructor");
-             error ("taking address of %s %qE", type, xarg);
+             error (DECL_CONSTRUCTOR_P (fn)
+                     ? G_("taking address of constructor %qE")
+                     : G_("taking address of destructor %qE"),
+                     xarg);
              return error_mark_node;
            }
        }
@@ -4256,27 +4718,37 @@ condition_conversion (tree expr)
   tree t;
   if (processing_template_decl)
     return expr;
-  t = perform_implicit_conversion (boolean_type_node, expr, 
-                                  tf_warning_or_error);
+  t = perform_implicit_conversion_flags (boolean_type_node, expr,
+                                        tf_warning_or_error, LOOKUP_NORMAL);
   t = fold_build_cleanup_point_expr (boolean_type_node, t);
   return t;
 }
 
-/* Return an ADDR_EXPR giving the address of T.  This function
-   attempts no optimizations or simplifications; it is a low-level
-   primitive.  */
+/* Returns the address of T.  This function will fold away
+   ADDR_EXPR of INDIRECT_REF.  */
 
 tree
 build_address (tree t)
 {
-  tree addr;
-
   if (error_operand_p (t) || !cxx_mark_addressable (t))
     return error_mark_node;
+  t = build_fold_addr_expr (t);
+  if (TREE_CODE (t) != ADDR_EXPR)
+    t = rvalue (t);
+  return t;
+}
 
-  addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
+/* Returns the address of T with type TYPE.  */
 
-  return addr;
+tree
+build_typed_address (tree t, tree type)
+{
+  if (error_operand_p (t) || !cxx_mark_addressable (t))
+    return error_mark_node;
+  t = build_fold_addr_expr_with_type (t, type);
+  if (TREE_CODE (t) != ADDR_EXPR)
+    t = rvalue (t);
+  return t;
 }
 
 /* Return a NOP_EXPR converting EXPR to TYPE.  */
@@ -4309,7 +4781,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
   tree val;
   const char *invalid_op_diag;
 
-  if (error_operand_p (arg))
+  if (!arg || error_operand_p (arg))
     return error_mark_node;
 
   if ((invalid_op_diag
@@ -4334,8 +4806,8 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
        arg = build_expr_type_conversion (flags, arg, true);
        if (!arg)
          errstring = (code == NEGATE_EXPR
-                      ? "wrong type argument to unary minus"
-                      : "wrong type argument to unary plus");
+                      ? _("wrong type argument to unary minus")
+                      : _("wrong type argument to unary plus"));
        else
          {
            if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg)))
@@ -4356,16 +4828,16 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
            arg = default_conversion (arg);
        }
       else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM
-                                                  | WANT_VECTOR,
+                                                  | WANT_VECTOR_OR_COMPLEX,
                                                   arg, true)))
-       errstring = "wrong type argument to bit-complement";
+       errstring = _("wrong type argument to bit-complement");
       else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg)))
        arg = perform_integral_promotions (arg);
       break;
 
     case ABS_EXPR:
       if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true)))
-       errstring = "wrong type argument to abs";
+       errstring = _("wrong type argument to abs");
       else if (!noconvert)
        arg = default_conversion (arg);
       break;
@@ -4373,7 +4845,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
     case CONJ_EXPR:
       /* Conjugating a real value is a no-op, but allow it anyway.  */
       if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true)))
-       errstring = "wrong type argument to conjugation";
+       errstring = _("wrong type argument to conjugation");
       else if (!noconvert)
        arg = default_conversion (arg);
       break;
@@ -4381,10 +4853,10 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
     case TRUTH_NOT_EXPR:
       arg = perform_implicit_conversion (boolean_type_node, arg,
                                         complain);
-      val = invert_truthvalue (arg);
+      val = invert_truthvalue_loc (input_location, arg);
       if (arg != error_mark_node)
        return val;
-      errstring = "in argument to unary !";
+      errstring = _("in argument to unary !");
       break;
 
     case NOP_EXPR:
@@ -4423,6 +4895,8 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
       if (val != 0)
        return val;
 
+      arg = mark_lvalue_use (arg);
+
       /* Increment or decrement the real part of the value,
         and don't change the imaginary part.  */
       if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
@@ -4445,13 +4919,13 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
                                              arg, true)))
        {
          if (code == PREINCREMENT_EXPR)
-           errstring ="no pre-increment operator for type";
+           errstring = _("no pre-increment operator for type");
          else if (code == POSTINCREMENT_EXPR)
-           errstring ="no post-increment operator for type";
+           errstring = _("no post-increment operator for type");
          else if (code == PREDECREMENT_EXPR)
-           errstring ="no pre-decrement operator for type";
+           errstring = _("no pre-decrement operator for type");
          else
-           errstring ="no post-decrement operator for type";
+           errstring = _("no post-decrement operator for type");
          break;
        }
       else if (arg == error_mark_node)
@@ -4465,7 +4939,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
           if (complain & tf_error)
             readonly_error (arg, ((code == PREINCREMENT_EXPR
                                    || code == POSTINCREMENT_EXPR)
-                                  ? "increment" : "decrement"));
+                                  ? REK_INCREMENT : REK_DECREMENT));
           else
             return error_mark_node;
         }
@@ -4532,7 +5006,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
          return error_mark_node;
 
        /* Forbid using -- on `bool'.  */
-       if (same_type_p (declared_type, boolean_type_node))
+       if (TREE_CODE (declared_type) == BOOLEAN_TYPE)
          {
            if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR)
              {
@@ -4556,6 +5030,8 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
 
       argtype = lvalue_type (arg);
 
+      arg = mark_lvalue_use (arg);
+
       if (TREE_CODE (arg) == OFFSET_REF)
        goto offset_ref;
 
@@ -4597,6 +5073,20 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
          return arg;
        }
 
+      /* ??? Cope with user tricks that amount to offsetof.  */
+      if (TREE_CODE (argtype) != FUNCTION_TYPE
+         && TREE_CODE (argtype) != METHOD_TYPE
+         && argtype != unknown_type_node
+         && (val = get_base_address (arg))
+         && TREE_CODE (val) == INDIRECT_REF
+         && TREE_CONSTANT (TREE_OPERAND (val, 0)))
+       {
+         tree type = build_pointer_type (argtype);
+         tree op0 = fold_convert (type, TREE_OPERAND (val, 0));
+         tree op1 = fold_convert (sizetype, fold_offsetof (arg, val));
+         return fold_build2 (POINTER_PLUS_EXPR, type, op0, op1);
+       }
+
       /* Uninstantiated types are all functions.  Taking the
         address of a function is a no-op, so just return the
         argument.  */
@@ -4764,7 +5254,8 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
        {
          build_ptrmemfunc_type (argtype);
          val = build_ptrmemfunc (argtype, val, 0,
-                                 /*c_cast_p=*/false);
+                                 /*c_cast_p=*/false,
+                                 tf_warning_or_error);
        }
 
       return val;
@@ -4998,14 +5489,30 @@ build_x_conditional_expr (tree ifexp, tree op1, tree op2,
 /* Given a list of expressions, return a compound expression
    that performs them all and returns the value of the last of them.  */
 
-tree build_x_compound_expr_from_list (tree list, const char *msg)
+tree
+build_x_compound_expr_from_list (tree list, expr_list_kind exp)
 {
   tree expr = TREE_VALUE (list);
 
   if (TREE_CHAIN (list))
     {
-      if (msg)
-       permerror (input_location, "%s expression list treated as compound expression", msg);
+      switch (exp)
+       {
+         case ELK_INIT:
+           permerror (input_location, "expression list treated as compound "
+                                      "expression in initializer");
+           break;
+         case ELK_MEM_INIT:
+           permerror (input_location, "expression list treated as compound "
+                                      "expression in mem-initializer");
+           break;
+         case ELK_FUNC_CAST:
+           permerror (input_location, "expression list treated as compound "
+                                      "expression in functional cast");
+           break;
+         default:
+           gcc_unreachable ();
+       }
 
       for (list = TREE_CHAIN (list); list; list = TREE_CHAIN (list))
        expr = build_x_compound_expr (expr, TREE_VALUE (list), 
@@ -5075,7 +5582,7 @@ build_x_compound_expr (tree op1, tree op2, tsubst_flags_t complain)
 /* Like cp_build_compound_expr, but for the c-common bits.  */
 
 tree
-build_compound_expr (tree lhs, tree rhs)
+build_compound_expr (location_t loc ATTRIBUTE_UNUSED, tree lhs, tree rhs)
 {
   return cp_build_compound_expr (lhs, rhs, tf_warning_or_error);
 }
@@ -5085,7 +5592,7 @@ build_compound_expr (tree lhs, tree rhs)
 tree
 cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain)
 {
-  lhs = convert_to_void (lhs, "left-hand operand of comma", complain);
+  lhs = convert_to_void (lhs, ICV_LEFT_OF_COMMA, complain);
 
   if (lhs == error_mark_node || rhs == error_mark_node)
     return error_mark_node;
@@ -5163,7 +5670,7 @@ check_for_casting_away_constness (tree src_type, tree dest_type,
 
 tree
 convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
-               bool c_cast_p)
+               bool c_cast_p, tsubst_flags_t complain)
 {
   if (TYPE_PTRMEM_P (type))
     {
@@ -5174,7 +5681,10 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
       delta = get_delta_difference (TYPE_PTRMEM_CLASS_TYPE (TREE_TYPE (expr)),
                                    TYPE_PTRMEM_CLASS_TYPE (type),
                                    allow_inverse_p,
-                                   c_cast_p);
+                                   c_cast_p, complain);
+      if (delta == error_mark_node)
+       return error_mark_node;
+
       if (!integer_zerop (delta))
        {
          tree cond, op1, op2;
@@ -5189,7 +5699,8 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
                                    PLUS_EXPR, op1, delta,
                                    tf_warning_or_error);
 
-         expr = fold_build3 (COND_EXPR, ptrdiff_type_node, cond, op1, op2);
+         expr = fold_build3_loc (input_location,
+                             COND_EXPR, ptrdiff_type_node, cond, op1, op2);
                         
        }
 
@@ -5197,7 +5708,7 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
     }
   else
     return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr,
-                            allow_inverse_p, c_cast_p);
+                            allow_inverse_p, c_cast_p, complain);
 }
 
 /* If EXPR is an INTEGER_CST and ORIG is an arithmetic constant, return
@@ -5272,7 +5783,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
   if (TREE_CODE (type) == REFERENCE_TYPE
       && CLASS_TYPE_P (TREE_TYPE (type))
       && CLASS_TYPE_P (intype)
-      && real_lvalue_p (expr)
+      && (TYPE_REF_IS_RVALUE (type) || real_lvalue_p (expr))
       && DERIVED_FROM_P (intype, TREE_TYPE (type))
       && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
                      build_pointer_type (TYPE_MAIN_VARIANT
@@ -5298,11 +5809,31 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
                              base, /*nonnull=*/false);
       /* Convert the pointer to a reference -- but then remember that
         there are no expressions with reference type in C++.  */
-      return convert_from_reference (build_nop (type, expr));
+      return convert_from_reference (cp_fold_convert (type, expr));
+    }
+
+  /* "An lvalue of type cv1 T1 can be cast to type rvalue reference to
+     cv2 T2 if cv2 T2 is reference-compatible with cv1 T1 (8.5.3)."  */
+  if (TREE_CODE (type) == REFERENCE_TYPE
+      && TYPE_REF_IS_RVALUE (type)
+      && real_lvalue_p (expr)
+      && reference_related_p (TREE_TYPE (type), intype)
+      && (c_cast_p || at_least_as_qualified_p (TREE_TYPE (type), intype)))
+    {
+      expr = build_typed_address (expr, type);
+      return convert_from_reference (expr);
     }
 
   orig = expr;
 
+  /* Resolve overloaded address here rather than once in
+     implicit_conversion and again in the inverse code below.  */
+  if (TYPE_PTRMEMFUNC_P (type) && type_unknown_p (expr))
+    {
+      expr = instantiate_type (type, expr, complain);
+      intype = TREE_TYPE (expr);
+    }
+
   /* [expr.static.cast]
 
      An expression e can be explicitly converted to a type T using a
@@ -5331,7 +5862,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
 
      Any expression can be explicitly converted to type cv void.  */
   if (TREE_CODE (type) == VOID_TYPE)
-    return convert_to_void (expr, /*implicit=*/NULL, complain);
+    return convert_to_void (expr, ICV_CAST, complain);
 
   /* [expr.static.cast]
 
@@ -5413,7 +5944,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
          if (!c_cast_p)
            check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR);
          return convert_ptrmem (type, expr, /*allow_inverse_p=*/1,
-                                c_cast_p);
+                                c_cast_p, tf_warning_or_error);
        }
     }
 
@@ -5557,12 +6088,17 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
                 intype, type);
 
       expr = cp_build_unary_op (ADDR_EXPR, expr, 0, complain);
+
+      if (warn_strict_aliasing > 2)
+       strict_aliasing_warning (TREE_TYPE (expr), type, expr);
+
       if (expr != error_mark_node)
        expr = build_reinterpret_cast_1
          (build_pointer_type (TREE_TYPE (type)), expr, c_cast_p,
           valid_p, complain);
       if (expr != error_mark_node)
-       expr = cp_build_indirect_ref (expr, 0, complain);
+       /* cp_build_indirect_ref isn't right for rvalue refs.  */
+       expr = convert_from_reference (fold_convert (type, expr));
       return expr;
     }
 
@@ -5596,8 +6132,11 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
 
   /* [expr.reinterpret.cast]
      A pointer can be converted to any integral type large enough to
-     hold it.  */
-  if (CP_INTEGRAL_TYPE_P (type) && TYPE_PTR_P (intype))
+     hold it. ... A value of type std::nullptr_t can be converted to
+     an integral type; the conversion has the same meaning and
+     validity as a conversion of (void*)0 to the integral type.  */
+  if (CP_INTEGRAL_TYPE_P (type)
+      && (TYPE_PTR_P (intype) || NULLPTR_TYPE_P (intype)))
     {
       if (TYPE_PRECISION (type) < TYPE_PRECISION (intype))
         {
@@ -5607,6 +6146,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
           else
             return error_mark_node;
         }
+      if (NULLPTR_TYPE_P (intype))
+        return build_int_cst (type, 0);
     }
   /* [expr.reinterpret.cast]
      A value of integral or enumeration type can be explicitly
@@ -5832,7 +6373,7 @@ build_const_cast (tree type, tree expr, tsubst_flags_t complain)
 /* Like cp_build_c_cast, but for the c-common bits.  */
 
 tree
-build_c_cast (tree type, tree expr)
+build_c_cast (location_t loc ATTRIBUTE_UNUSED, tree type, tree expr)
 {
   return cp_build_c_cast (type, expr, tf_warning_or_error);
 }
@@ -5901,6 +6442,15 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
       return error_mark_node;
     }
 
+  if (TREE_CODE (type) == POINTER_TYPE
+      && TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
+      /* Casting to an integer of smaller size is an error detected elsewhere.  */
+      && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (value))
+      /* Don't warn about converting any constant.  */
+      && !TREE_CONSTANT (value))
+    warning_at (input_location, OPT_Wint_to_pointer_cast, 
+               "cast to pointer from integer of different size");
+
   /* A C-style cast can be a const_cast.  */
   result = build_const_cast_1 (type, value, /*complain=*/false,
                               &valid_p);
@@ -5949,7 +6499,8 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
 tree
 build_modify_expr (location_t location ATTRIBUTE_UNUSED,
                   tree lhs, tree lhs_origtype ATTRIBUTE_UNUSED,
-                  enum tree_code modifycode, tree rhs,
+                  enum tree_code modifycode, 
+                  location_t rhs_location ATTRIBUTE_UNUSED, tree rhs,
                   tree rhs_origtype ATTRIBUTE_UNUSED)
 {
   return cp_build_modify_expr (lhs, modifycode, rhs, tf_warning_or_error);
@@ -6077,8 +6628,11 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
 
   if (modifycode == INIT_EXPR)
     {
-      if (TREE_CODE (rhs) == CONSTRUCTOR)
+      if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
+       /* Do the default thing.  */;
+      else if (TREE_CODE (rhs) == CONSTRUCTOR)
        {
+         /* Compound literal.  */
          if (! same_type_p (TREE_TYPE (rhs), lhstype))
            /* Call convert to generate an error; see PR 11063.  */
            rhs = convert (lhstype, rhs);
@@ -6169,7 +6723,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
              && C_TYPE_FIELDS_READONLY (lhstype))))
     {
       if (complain & tf_error)
-       readonly_error (lhs, "assignment");
+       readonly_error (lhs, REK_ASSIGNMENT);
       else
        return error_mark_node;
     }
@@ -6186,8 +6740,21 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
     {
       int from_array;
 
-      if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
-                               TYPE_MAIN_VARIANT (TREE_TYPE (rhs))))
+      if (BRACE_ENCLOSED_INITIALIZER_P (newrhs))
+       {
+         if (modifycode != INIT_EXPR)
+           {
+             if (complain & tf_error)
+               error ("assigning to an array from an initializer list");
+             return error_mark_node;
+           }
+         if (check_array_initializer (lhs, lhstype, newrhs))
+           return error_mark_node;
+         newrhs = digest_init (lhstype, newrhs);
+       }
+
+      else if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
+                                    TYPE_MAIN_VARIANT (TREE_TYPE (newrhs))))
        {
          if (complain & tf_error)
            error ("incompatible types in assignment of %qT to %qT",
@@ -6196,7 +6763,8 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
        }
 
       /* Allow array assignment in compiler-generated code.  */
-      if (!current_function_decl || !DECL_ARTIFICIAL (current_function_decl))
+      else if (!current_function_decl
+              || !DECL_ARTIFICIAL (current_function_decl))
        {
           /* This routine is used for both initialization and assignment.
              Make sure the diagnostic message differentiates the context.  */
@@ -6221,10 +6789,10 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
     /* Calls with INIT_EXPR are all direct-initialization, so don't set
        LOOKUP_ONLYCONVERTING.  */
     newrhs = convert_for_initialization (lhs, olhstype, newrhs, LOOKUP_NORMAL,
-                                        "initialization", NULL_TREE, 0,
+                                        ICR_INIT, NULL_TREE, 0,
                                          complain);
   else
-    newrhs = convert_for_assignment (olhstype, newrhs, "assignment",
+    newrhs = convert_for_assignment (olhstype, newrhs, ICR_ASSIGN,
                                     NULL_TREE, 0, complain, LOOKUP_IMPLICIT);
 
   if (!same_type_p (lhstype, olhstype))
@@ -6291,20 +6859,32 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
 
 /* Helper function for get_delta_difference which assumes FROM is a base
    class of TO.  Returns a delta for the conversion of pointer-to-member
-   of FROM to pointer-to-member of TO.  If the conversion is invalid,
+   of FROM to pointer-to-member of TO.  If the conversion is invalid and 
+   tf_error is not set in COMPLAIN returns error_mark_node, otherwise
    returns zero.  If FROM is not a base class of TO, returns NULL_TREE.
-   If C_CAST_P is true, this conversion is taking place as part of a C-style
-   cast.  */
+   If C_CAST_P is true, this conversion is taking place as part of a 
+   C-style cast.  */
 
 static tree
-get_delta_difference_1 (tree from, tree to, bool c_cast_p)
+get_delta_difference_1 (tree from, tree to, bool c_cast_p,
+                       tsubst_flags_t complain)
 {
   tree binfo;
   base_kind kind;
+  base_access access = c_cast_p ? ba_unique : ba_check;
+
+  /* Note: ba_quiet does not distinguish between access control and
+     ambiguity.  */
+  if (!(complain & tf_error))
+    access |= ba_quiet;
+
+  binfo = lookup_base (to, from, access, &kind);
 
-  binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check, &kind);
   if (kind == bk_inaccessible || kind == bk_ambig)
     {
+      if (!(complain & tf_error))
+       return error_mark_node;
+
       error ("   in pointer to member function conversion");
       return size_zero_node;
     }
@@ -6316,22 +6896,26 @@ get_delta_difference_1 (tree from, tree to, bool c_cast_p)
        /* FROM is a virtual base class of TO.  Issue an error or warning
           depending on whether or not this is a reinterpret cast.  */
        {
+         if (!(complain & tf_error))
+           return error_mark_node;
+
          error ("pointer to member conversion via virtual base %qT",
                 BINFO_TYPE (binfo_from_vbase (binfo)));
 
          return size_zero_node;
        }
       }
-    else
-      return NULL_TREE;
+  else
+    return NULL_TREE;
 }
 
 /* Get difference in deltas for different pointer to member function
-   types.  Returns an integer constant of type PTRDIFF_TYPE_NODE.  If
-   the conversion is invalid, the constant is zero.  If
-   ALLOW_INVERSE_P is true, then allow reverse conversions as well.
-   If C_CAST_P is true this conversion is taking place as part of a
-   C-style cast.
+   types.  If the conversion is invalid and tf_error is not set in
+   COMPLAIN, returns error_mark_node, otherwise returns an integer
+   constant of type PTRDIFF_TYPE_NODE and its value is zero if the
+   conversion is invalid.  If ALLOW_INVERSE_P is true, then allow reverse
+   conversions as well.  If C_CAST_P is true this conversion is taking
+   place as part of a C-style cast.
 
    Note that the naming of FROM and TO is kind of backwards; the return
    value is what we add to a TO in order to get a FROM.  They are named
@@ -6341,7 +6925,7 @@ get_delta_difference_1 (tree from, tree to, bool c_cast_p)
 static tree
 get_delta_difference (tree from, tree to,
                      bool allow_inverse_p,
-                     bool c_cast_p)
+                     bool c_cast_p, tsubst_flags_t complain)
 {
   tree result;
 
@@ -6349,24 +6933,37 @@ get_delta_difference (tree from, tree to,
     /* Pointer to member of incomplete class is permitted*/
     result = size_zero_node;
   else
-    result = get_delta_difference_1 (from, to, c_cast_p);
+    result = get_delta_difference_1 (from, to, c_cast_p, complain);
+
+  if (result == error_mark_node)
+    return error_mark_node;
 
   if (!result)
   {
     if (!allow_inverse_p)
       {
+       if (!(complain & tf_error))
+         return error_mark_node;
+
        error_not_base_type (from, to);
        error ("   in pointer to member conversion");
-       result = size_zero_node;
+       result = size_zero_node;
       }
     else
       {
-       result = get_delta_difference_1 (to, from, c_cast_p);
+       result = get_delta_difference_1 (to, from, c_cast_p, complain);
+
+       if (result == error_mark_node)
+         return error_mark_node;
 
        if (result)
-         result = size_diffop (size_zero_node, result);
+         result = size_diffop_loc (input_location,
+                                   size_zero_node, result);
        else
          {
+           if (!(complain & tf_error))
+             return error_mark_node;
+
            error_not_base_type (from, to);
            error ("   in pointer to member conversion");
            result = size_zero_node;
@@ -6391,7 +6988,7 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn)
 
   /* Pull the FIELD_DECLs out of the type.  */
   pfn_field = TYPE_FIELDS (type);
-  delta_field = TREE_CHAIN (pfn_field);
+  delta_field = DECL_CHAIN (pfn_field);
 
   /* Make sure DELTA has the type we want.  */
   delta = convert_and_check (delta_type_node, delta);
@@ -6425,7 +7022,8 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn)
    Return error_mark_node, if something goes wrong.  */
 
 tree
-build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p)
+build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p,
+                 tsubst_flags_t complain)
 {
   tree fn;
   tree pfn_type;
@@ -6452,7 +7050,9 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p)
       n = get_delta_difference (TYPE_PTRMEMFUNC_OBJECT_TYPE (pfn_type),
                                TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type),
                                force,
-                               c_cast_p);
+                               c_cast_p, complain);
+      if (n == error_mark_node)
+       return error_mark_node;
 
       /* We don't have to do any conversion to convert a
         pointer-to-member to its own type.  But, we don't want to
@@ -6492,9 +7092,9 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p)
     }
 
   /* Handle null pointer to member function conversions.  */
-  if (integer_zerop (pfn))
+  if (null_ptr_cst_p (pfn))
     {
-      pfn = build_c_cast (type, integer_zero_node);
+      pfn = build_c_cast (input_location, type, integer_zero_node);
       return build_ptrmemfunc1 (to_type,
                                integer_zero_node,
                                pfn);
@@ -6535,7 +7135,7 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
 
   /* First, calculate the adjustment to the function's class.  */
   *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0,
-                                /*c_cast_p=*/0);
+                                /*c_cast_p=*/0, tf_warning_or_error);
 
   if (!DECL_VIRTUAL_P (fn))
     *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
@@ -6623,14 +7223,15 @@ delta_from_ptrmemfunc (tree t)
 }
 
 /* Convert value RHS to type TYPE as preparation for an assignment to
-   an lvalue of type TYPE.  ERRTYPE is a string to use in error
-   messages: "assignment", "return", etc.  If FNDECL is non-NULL, we
-   are doing the conversion in order to pass the PARMNUMth argument of
-   FNDECL.  */
+   an lvalue of type TYPE.  ERRTYPE indicates what kind of error the
+   implicit conversion is.  If FNDECL is non-NULL, we are doing the
+   conversion in order to pass the PARMNUMth argument of FNDECL.
+   If FNDECL is NULL, we are doing the conversion in function pointer
+   argument passing, conversion in initialization, etc. */
 
 static tree
 convert_for_assignment (tree type, tree rhs,
-                       const char *errtype, tree fndecl, int parmnum,
+                       impl_conv_rhs errtype, tree fndecl, int parmnum,
                        tsubst_flags_t complain, int flags)
 {
   tree rhstype;
@@ -6645,7 +7246,10 @@ convert_for_assignment (tree type, tree rhs,
 
   if (TREE_CODE (type) == VECTOR_TYPE && coder == VECTOR_TYPE
       && vector_types_convertible_p (type, rhstype, true))
-    return convert (type, rhs);
+    {
+      rhs = mark_rvalue_use (rhs);
+      return convert (type, rhs);
+    }
 
   if (rhs == error_mark_node || rhstype == error_mark_node)
     return error_mark_node;
@@ -6667,27 +7271,32 @@ convert_for_assignment (tree type, tree rhs,
   if (c_dialect_objc ())
     {
       int parmno;
+      tree selector;
       tree rname = fndecl;
 
-      if (!strcmp (errtype, "assignment"))
-       parmno = -1;
-      else if (!strcmp (errtype, "initialization"))
-       parmno = -2;
-      else
-       {
-         tree selector = objc_message_selector ();
-
-         parmno = parmnum;
-
-         if (selector && parmno > 1)
-           {
-             rname = selector;
-             parmno -= 1;
-           }
+      switch (errtype)
+        {
+         case ICR_ASSIGN:
+           parmno = -1;
+           break;
+         case ICR_INIT:
+           parmno = -2;
+           break;
+         default:
+           selector = objc_message_selector ();
+           parmno = parmnum;
+           if (selector && parmno > 1)
+             {
+               rname = selector;
+               parmno -= 1;
+             }
        }
 
       if (objc_compare_types (type, rhstype, parmno, rname))
-       return convert (type, rhs);
+       {
+         rhs = mark_rvalue_use (rhs);
+         return convert (type, rhs);
+       }
     }
 
   /* [expr.ass]
@@ -6720,8 +7329,35 @@ convert_for_assignment (tree type, tree rhs,
                error ("cannot convert %qT to %qT for argument %qP to %qD",
                       rhstype, type, parmnum, fndecl);
              else
-               error ("cannot convert %qT to %qT in %s", rhstype, type,
-                      errtype);
+               switch (errtype)
+                 {
+                   case ICR_DEFAULT_ARGUMENT:
+                     error ("cannot convert %qT to %qT in default argument",
+                            rhstype, type);
+                     break;
+                   case ICR_ARGPASS:
+                     error ("cannot convert %qT to %qT in argument passing",
+                            rhstype, type);
+                     break;
+                   case ICR_CONVERTING:
+                     error ("cannot convert %qT to %qT",
+                            rhstype, type);
+                     break;
+                   case ICR_INIT:
+                     error ("cannot convert %qT to %qT in initialization",
+                            rhstype, type);
+                     break;
+                   case ICR_RETURN:
+                     error ("cannot convert %qT to %qT in return",
+                            rhstype, type);
+                     break;
+                   case ICR_ASSIGN:
+                     error ("cannot convert %qT to %qT in assignment",
+                            rhstype, type);
+                     break;
+                   default:
+                     gcc_unreachable();
+                 }
            }
          return error_mark_node;
        }
@@ -6733,22 +7369,58 @@ convert_for_assignment (tree type, tree rhs,
          && coder == codel
          && check_missing_format_attribute (type, rhstype)
          && (complain & tf_warning))
-       warning (OPT_Wmissing_format_attribute,
-                "%s might be a candidate for a format attribute",
-                errtype);
+       switch (errtype)
+         {
+           case ICR_ARGPASS:
+           case ICR_DEFAULT_ARGUMENT:
+             if (fndecl)
+               warning (OPT_Wmissing_format_attribute,
+                        "parameter %qP of %qD might be a candidate "
+                        "for a format attribute", parmnum, fndecl);
+             else
+               warning (OPT_Wmissing_format_attribute,
+                        "parameter might be a candidate "
+                        "for a format attribute");
+             break;
+           case ICR_CONVERTING:
+             warning (OPT_Wmissing_format_attribute,
+                      "target of conversion might be might be a candidate "
+                      "for a format attribute");
+             break;
+           case ICR_INIT:
+             warning (OPT_Wmissing_format_attribute,
+                      "target of initialization might be a candidate "
+                      "for a format attribute");
+             break;
+           case ICR_RETURN:
+             warning (OPT_Wmissing_format_attribute,
+                      "return type might be a candidate "
+                      "for a format attribute");
+             break;
+           case ICR_ASSIGN:
+             warning (OPT_Wmissing_format_attribute,
+                      "left-hand side of assignment might be a candidate "
+                      "for a format attribute");
+             break;
+           default:
+             gcc_unreachable();
+         }
     }
 
   /* If -Wparentheses, warn about a = b = c when a has type bool and b
      does not.  */
   if (warn_parentheses
-      && type == boolean_type_node
+      && TREE_CODE (type) == BOOLEAN_TYPE
       && TREE_CODE (rhs) == MODIFY_EXPR
       && !TREE_NO_WARNING (rhs)
-      && TREE_TYPE (rhs) != boolean_type_node
+      && TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE
       && (complain & tf_warning))
     {
-      warning (OPT_Wparentheses,
-              "suggest parentheses around assignment used as truth value");
+      location_t loc = EXPR_HAS_LOCATION (rhs) 
+       ? EXPR_LOCATION (rhs) : input_location;
+
+      warning_at (loc, OPT_Wparentheses,
+                 "suggest parentheses around assignment used as truth value");
       TREE_NO_WARNING (rhs) = 1;
     }
 
@@ -6758,7 +7430,7 @@ convert_for_assignment (tree type, tree rhs,
 
 /* Convert RHS to be of type TYPE.
    If EXP is nonzero, it is the target of the initialization.
-   ERRTYPE is a string to use in error messages.
+   ERRTYPE indicates what kind of error the implicit conversion is.
 
    Two major differences between the behavior of
    `convert_for_assignment' and `convert_for_initialization'
@@ -6774,7 +7446,7 @@ convert_for_assignment (tree type, tree rhs,
 
 tree
 convert_for_initialization (tree exp, tree type, tree rhs, int flags,
-                           const char *errtype, tree fndecl, int parmnum,
+                           impl_conv_rhs errtype, tree fndecl, int parmnum,
                             tsubst_flags_t complain)
 {
   enum tree_code codel = TREE_CODE (type);
@@ -6820,7 +7492,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
       if (fndecl)
        savew = warningcount, savee = errorcount;
       rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE,
-                                 /*cleanup=*/NULL);
+                                 /*cleanup=*/NULL, complain);
       if (fndecl)
        {
          if (warningcount > savew)
@@ -6840,6 +7512,11 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
 
   type = complete_type (type);
 
+  if (DIRECT_INIT_EXPR_P (type, rhs))
+    /* Don't try to do copy-initialization if we already have
+       direct-initialization.  */
+    return rhs;
+
   if (MAYBE_CLASS_TYPE_P (type))
     return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
 
@@ -6952,6 +7629,31 @@ check_return_expr (tree retval, bool *no_warning)
       return NULL_TREE;
     }
 
+  /* As an extension, deduce lambda return type from a return statement
+     anywhere in the body.  */
+  if (retval && LAMBDA_FUNCTION_P (current_function_decl))
+    {
+      tree lambda = CLASSTYPE_LAMBDA_EXPR (current_class_type);
+      if (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda))
+       {
+         tree type = lambda_return_type (retval);
+         tree oldtype = LAMBDA_EXPR_RETURN_TYPE (lambda);
+
+         if (VOID_TYPE_P (type))
+           { /* Nothing.  */ }
+         else if (oldtype == NULL_TREE)
+           {
+             pedwarn (input_location, OPT_pedantic, "lambda return type "
+                      "can only be deduced when the return statement is "
+                      "the only statement in the function body");
+             apply_lambda_return_type (lambda, type);
+           }
+         else if (!same_type_p (type, oldtype))
+           error ("inconsistent types %qT and %qT deduced for "
+                  "lambda return type", type, oldtype);
+       }
+    }
+
   if (processing_template_decl)
     {
       current_function_returns_value = 1;
@@ -7126,7 +7828,7 @@ check_return_expr (tree retval, bool *no_warning)
       if ((cxx_dialect != cxx98) 
           && named_return_value_okay_p
           /* The variable must not have the `volatile' qualifier.  */
-         && !(cp_type_quals (TREE_TYPE (retval)) & TYPE_QUAL_VOLATILE)
+         && !CP_TYPE_VOLATILE_P (TREE_TYPE (retval))
          /* The return type must be a class type.  */
          && CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
        flags = flags | LOOKUP_PREFER_RVALUE;
@@ -7135,7 +7837,7 @@ check_return_expr (tree retval, bool *no_warning)
         to the type of return value's location to handle the
         case that functype is smaller than the valtype.  */
       retval = convert_for_initialization
-       (NULL_TREE, functype, retval, flags, "return", NULL_TREE, 0,
+       (NULL_TREE, functype, retval, flags, ICR_RETURN, NULL_TREE, 0,
          tf_warning_or_error);
       retval = convert (valtype, retval);
 
@@ -7227,6 +7929,44 @@ comp_ptr_ttypes (tree to, tree from)
   return comp_ptr_ttypes_real (to, from, 1);
 }
 
+/* Returns true iff FNTYPE is a non-class type that involves
+   error_mark_node.  We can get FUNCTION_TYPE with buried error_mark_node
+   if a parameter type is ill-formed.  */
+
+bool
+error_type_p (const_tree type)
+{
+  tree t;
+
+  switch (TREE_CODE (type))
+    {
+    case ERROR_MARK:
+      return true;
+
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+    case OFFSET_TYPE:
+      return error_type_p (TREE_TYPE (type));
+
+    case FUNCTION_TYPE:
+    case METHOD_TYPE:
+      if (error_type_p (TREE_TYPE (type)))
+       return true;
+      for (t = TYPE_ARG_TYPES (type); t; t = TREE_CHAIN (t))
+       if (error_type_p (TREE_VALUE (t)))
+         return true;
+      return false;
+
+    case RECORD_TYPE:
+      if (TYPE_PTRMEMFUNC_P (type))
+       return error_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type));
+      return false;
+
+    default:
+      return false;
+    }
+}
+
 /* Returns 1 if to and from are (possibly multi-level) pointers to the same
    type or inheritance-related types, regardless of cv-quals.  */
 
@@ -7236,9 +7976,10 @@ ptr_reasonably_similar (const_tree to, const_tree from)
   for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
     {
       /* Any target type is similar enough to void.  */
-      if (TREE_CODE (to) == VOID_TYPE
-         || TREE_CODE (from) == VOID_TYPE)
-       return 1;
+      if (TREE_CODE (to) == VOID_TYPE)
+       return !error_type_p (from);
+      if (TREE_CODE (from) == VOID_TYPE)
+       return !error_type_p (to);
 
       if (TREE_CODE (to) != TREE_CODE (from))
        return 0;
@@ -7258,7 +7999,7 @@ ptr_reasonably_similar (const_tree to, const_tree from)
        return 1;
 
       if (TREE_CODE (to) == FUNCTION_TYPE)
-       return 1;
+       return !error_type_p (to) && !error_type_p (from);
 
       if (TREE_CODE (to) != POINTER_TYPE)
        return comptypes
@@ -7301,24 +8042,59 @@ comp_ptr_ttypes_const (tree to, tree from)
 int
 cp_type_quals (const_tree type)
 {
+  int quals;
   /* This CONST_CAST is okay because strip_array_types returns its
      argument unmodified and we assign it to a const_tree.  */
-  type = strip_array_types (CONST_CAST_TREE(type));
-  if (type == error_mark_node)
+  type = strip_array_types (CONST_CAST_TREE (type));
+  if (type == error_mark_node
+      /* Quals on a FUNCTION_TYPE are memfn quals.  */
+      || TREE_CODE (type) == FUNCTION_TYPE)
     return TYPE_UNQUALIFIED;
-  return TYPE_QUALS (type);
+  quals = TYPE_QUALS (type);
+  /* METHOD and REFERENCE_TYPEs should never have quals.  */
+  gcc_assert ((TREE_CODE (type) != METHOD_TYPE
+              && TREE_CODE (type) != REFERENCE_TYPE)
+             || ((quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE))
+                 == TYPE_UNQUALIFIED));
+  return quals;
 }
 
-/* Returns nonzero if the TYPE is const from a C++ perspective: look inside
-   arrays.  */
+/* Returns the function-cv-quals for TYPE, which must be a FUNCTION_TYPE or
+   METHOD_TYPE.  */
+
+int
+type_memfn_quals (const_tree type)
+{
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    return TYPE_QUALS (type);
+  else if (TREE_CODE (type) == METHOD_TYPE)
+    return cp_type_quals (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))));
+  else
+    gcc_unreachable ();
+}
+
+/* Returns the FUNCTION_TYPE TYPE with its function-cv-quals changed to
+   MEMFN_QUALS.  */
+
+tree
+apply_memfn_quals (tree type, cp_cv_quals memfn_quals)
+{
+  /* Could handle METHOD_TYPE here if necessary.  */
+  gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
+  if (TYPE_QUALS (type) == memfn_quals)
+    return type;
+  /* This should really have a different TYPE_MAIN_VARIANT, but that gets
+     complex.  */
+  return build_qualified_type (type, memfn_quals);
+}
+
+/* Returns nonzero if TYPE is const or volatile.  */
 
 bool
-cp_type_readonly (const_tree type)
+cv_qualified_p (const_tree type)
 {
-  /* This CONST_CAST is okay because strip_array_types returns its
-     argument unmodified and we assign it to a const_tree.  */
-  type = strip_array_types (CONST_CAST_TREE(type));
-  return TYPE_READONLY (type);
+  int quals = cp_type_quals (type);
+  return (quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE)) != 0;
 }
 
 /* Returns nonzero if the TYPE contains a mutable member.  */
@@ -7356,23 +8132,8 @@ cp_apply_type_quals_to_decl (int type_quals, tree decl)
   if (TREE_CODE (decl) == TYPE_DECL)
     return;
 
-  if (TREE_CODE (type) == FUNCTION_TYPE
-      && type_quals != TYPE_UNQUALIFIED)
-    {
-      /* This was an error in C++98 (cv-qualifiers cannot be added to
-        a function type), but DR 295 makes the code well-formed by
-        dropping the extra qualifiers. */
-      if (pedantic)
-       {
-         tree bad_type = build_qualified_type (type, type_quals);
-         pedwarn (input_location, OPT_pedantic, 
-                  "ignoring %qV qualifiers added to function type %qT",
-                  bad_type, type);
-       }
-
-      TREE_TYPE (decl) = TYPE_MAIN_VARIANT (type);
-      return;
-    }
+  gcc_assert (!(TREE_CODE (type) == FUNCTION_TYPE
+               && type_quals != TYPE_UNQUALIFIED));
 
   /* Avoid setting TREE_READONLY incorrectly.  */
   if (/* If the object has a constructor, the constructor may modify
@@ -7529,3 +8290,4 @@ lvalue_or_else (tree ref, enum lvalue_use use, tsubst_flags_t complain)
 
   return win;
 }
+