OSDN Git Service

Restore canonical type comparison for dependent type(def)s
[pf3gnuchains/gcc-fork.git] / gcc / cp / typeck.c
index e96272f..5f8d321 100644 (file)
@@ -64,11 +64,11 @@ static int convert_arguments (tree, VEC(tree,gc) **, tree, int,
 
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)
-   Returns the error_mark_node if the VALUE does not have
+   Returns error_mark_node if the VALUE does not have
    complete type when this function returns.  */
 
 tree
-require_complete_type (tree value)
+require_complete_type_sfinae (tree value, tsubst_flags_t complain)
 {
   tree type;
 
@@ -87,12 +87,18 @@ require_complete_type (tree value)
   if (COMPLETE_TYPE_P (type))
     return value;
 
-  if (complete_type_or_else (type, value))
+  if (complete_type_or_maybe_complain (type, value, complain))
     return value;
   else
     return error_mark_node;
 }
 
+tree
+require_complete_type (tree value)
+{
+  return require_complete_type_sfinae (value, tf_warning_or_error);
+}
+
 /* Try to complete TYPE, if it is incomplete.  For example, if TYPE is
    a template instantiation, do the instantiation.  Returns TYPE,
    whether or not it could be completed, unless something goes
@@ -632,8 +638,8 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
   if (c_dialect_objc () && TREE_CODE (t1) == POINTER_TYPE
       && TREE_CODE (t2) == POINTER_TYPE)
     {
-      if (objc_compare_types (t1, t2, -3, NULL_TREE))
-       return t1;
+      if (objc_have_common_type (t1, t2, -3, NULL_TREE))
+       return objc_common_type (t1, t2);
     }
 
   /* [expr.eq] permits the application of a pointer conversion to
@@ -1137,120 +1143,30 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
 static bool
 comp_template_parms_position (tree t1, tree t2)
 {
+  tree index1, index2;
   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);
+  index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
+  index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
 
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+  /* If T1 and T2 belong to template parm lists of different size,
+     let's assume they are different.  */
+  if (TEMPLATE_PARM_NUM_SIBLINGS (index1)
+      != TEMPLATE_PARM_NUM_SIBLINGS (index2))
     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)
+  /* Then compare their relative position.  */
+  if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
+      || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
+      || (TEMPLATE_PARM_PARAMETER_PACK (index1)
+         != TEMPLATE_PARM_PARAMETER_PACK (index2)))
     return false;
 
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1295,12 +1211,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   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).  */
@@ -1401,8 +1311,10 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      /* 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 false;
       break;
 
     case TYPENAME_TYPE:
@@ -1924,6 +1836,9 @@ decay_conversion (tree exp)
       return error_mark_node;
     }
 
+  /* FIXME remove? at least need to remember that this isn't really a
+     constant expression if EXP isn't decl_constant_var_p, like with
+     C_MAYBE_CONST_EXPR.  */
   exp = decl_constant_value (exp);
   if (error_operand_p (exp))
     return error_mark_node;
@@ -1942,7 +1857,7 @@ decay_conversion (tree exp)
   if (invalid_nonstatic_memfn_p (exp, tf_warning_or_error))
     return error_mark_node;
   if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
-    return cp_build_unary_op (ADDR_EXPR, exp, 0, tf_warning_or_error);
+    return cp_build_addr_expr (exp, tf_warning_or_error);
   if (code == ARRAY_TYPE)
     {
       tree adr;
@@ -1977,7 +1892,7 @@ decay_conversion (tree exp)
        }
       /* This way is better for a COMPONENT_REF since it can
         simplify the offset for a component.  */
-      adr = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error);
+      adr = cp_build_addr_expr (exp, tf_warning_or_error);
       return cp_convert (ptrtype, adr);
     }
 
@@ -2587,7 +2502,11 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
        return build_min_nt (COMPONENT_REF, object, name, NULL_TREE);
       object = build_non_dependent_expr (object);
     }
-
+  else if (c_dialect_objc ()
+          && TREE_CODE (name) == IDENTIFIER_NODE
+          && (expr = objc_maybe_build_component_ref (object, name)))
+    return expr;
+    
   /* [expr.ref]
 
      The type of the first expression shall be "class object" (of a
@@ -3039,7 +2958,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
        |= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
       TREE_THIS_VOLATILE (rval)
        |= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
-      ret = require_complete_type (fold_if_not_in_template (rval));
+      ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
+                                         complain);
       protected_set_expr_location (ret, loc);
       return ret;
     }
@@ -3211,8 +3131,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
         vtable entry is treated as a function pointer.  */
       if (TARGET_VTABLE_USES_DESCRIPTORS)
        e2 = build1 (NOP_EXPR, TREE_TYPE (e2),
-                    cp_build_unary_op (ADDR_EXPR, e2, /*noconvert=*/1,
-                                     tf_warning_or_error));
+                    cp_build_addr_expr (e2, tf_warning_or_error));
 
       e2 = fold_convert (TREE_TYPE (e3), e2);
       e1 = build_conditional_expr (e1, e2, e3, tf_warning_or_error);
@@ -3428,8 +3347,17 @@ warn_args_num (location_t loc, tree fndecl, bool too_many_p)
              "declared here");
     }
   else
-    error_at (loc, too_many_p ? G_("too many arguments to function")
-                             : G_("too few arguments to function"));
+    {
+      if (c_dialect_objc ()  &&  objc_message_selector ())
+       error_at (loc,
+                 too_many_p 
+                 ? G_("too many arguments to method %q#D")
+                 : G_("too few arguments to method %q#D"),
+                 objc_message_selector ());
+      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
@@ -3534,7 +3462,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
            /* Don't do ellipsis conversion for __built_in_constant_p
               as this will result in spurious errors for non-trivial
               types.  */
-           val = require_complete_type (val);
+           val = require_complete_type_sfinae (val, complain);
          else
            val = convert_arg_to_ellipsis (val);
 
@@ -4712,9 +4640,8 @@ build_x_unary_op (enum tree_code code, tree xarg, tsubst_flags_t complain)
              PTRMEM_OK_P (xarg) = ptrmem;
            }
        }
-      else if (TREE_CODE (xarg) == TARGET_EXPR && (complain & tf_warning))
-       warning (0, "taking address of temporary");
-      exp = cp_build_unary_op (ADDR_EXPR, xarg, 0, complain);
+
+      exp = cp_build_addr_expr_strict (xarg, complain);
     }
 
   if (processing_template_decl && exp != error_mark_node)
@@ -4791,6 +4718,287 @@ build_nop (tree type, tree expr)
   return build1 (NOP_EXPR, type, expr);
 }
 
+/* Take the address of ARG, whatever that means under C++ semantics.
+   If STRICT_LVALUE is true, require an lvalue; otherwise, allow xvalues
+   and class rvalues as well.
+
+   Nothing should call this function directly; instead, callers should use
+   cp_build_addr_expr or cp_build_addr_expr_strict.  */
+
+static tree
+cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
+{
+  tree argtype;
+  tree val;
+
+  if (!arg || error_operand_p (arg))
+    return error_mark_node;
+
+  arg = mark_lvalue_use (arg);
+  argtype = lvalue_type (arg);
+
+  gcc_assert (TREE_CODE (arg) != IDENTIFIER_NODE
+             || !IDENTIFIER_OPNAME_P (arg));
+
+  if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
+      && !really_overloaded_fn (TREE_OPERAND (arg, 1)))
+    {
+      /* They're trying to take the address of a unique non-static
+        member function.  This is ill-formed (except in MS-land),
+        but let's try to DTRT.
+        Note: We only handle unique functions here because we don't
+        want to complain if there's a static overload; non-unique
+        cases will be handled by instantiate_type.  But we need to
+        handle this case here to allow casts on the resulting PMF.
+        We could defer this in non-MS mode, but it's easier to give
+        a useful error here.  */
+
+      /* Inside constant member functions, the `this' pointer
+        contains an extra const qualifier.  TYPE_MAIN_VARIANT
+        is used here to remove this const from the diagnostics
+        and the created OFFSET_REF.  */
+      tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0)));
+      tree fn = get_first_fn (TREE_OPERAND (arg, 1));
+      mark_used (fn);
+
+      if (! flag_ms_extensions)
+       {
+         tree name = DECL_NAME (fn);
+         if (!(complain & tf_error))
+           return error_mark_node;
+         else if (current_class_type
+                  && TREE_OPERAND (arg, 0) == current_class_ref)
+           /* An expression like &memfn.  */
+           permerror (input_location, "ISO C++ forbids taking the address of an unqualified"
+                      " or parenthesized non-static member function to form"
+                      " a pointer to member function.  Say %<&%T::%D%>",
+                      base, name);
+         else
+           permerror (input_location, "ISO C++ forbids taking the address of a bound member"
+                      " function to form a pointer to member function."
+                      "  Say %<&%T::%D%>",
+                      base, name);
+       }
+      arg = build_offset_ref (base, fn, /*address_p=*/true);
+    }
+
+  /* Uninstantiated types are all functions.  Taking the
+     address of a function is a no-op, so just return the
+     argument.  */
+  if (type_unknown_p (arg))
+    return build1 (ADDR_EXPR, unknown_type_node, arg);
+
+  if (TREE_CODE (arg) == OFFSET_REF)
+    /* We want a pointer to member; bypass all the code for actually taking
+       the address of something.  */
+    goto offset_ref;
+
+  /* Anything not already handled and not a true memory reference
+     is an error.  */
+  if (TREE_CODE (argtype) != FUNCTION_TYPE
+      && TREE_CODE (argtype) != METHOD_TYPE)
+    {
+      cp_lvalue_kind kind = lvalue_kind (arg);
+      if (kind == clk_none)
+       {
+         if (complain & tf_error)
+           lvalue_error (lv_addressof);
+         return error_mark_node;
+       }
+      if (strict_lvalue && (kind & (clk_rvalueref|clk_class)))
+       {
+         if (!(complain & tf_error))
+           return error_mark_node;
+         if (kind & clk_class)
+           /* Make this a permerror because we used to accept it.  */
+           permerror (input_location, "taking address of temporary");
+         else
+           error ("taking address of xvalue (rvalue reference)");
+       }
+    }
+
+  if (TREE_CODE (argtype) == REFERENCE_TYPE)
+    {
+      tree type = build_pointer_type (TREE_TYPE (argtype));
+      arg = build1 (CONVERT_EXPR, type, arg);
+      return arg;
+    }
+  else if (pedantic && DECL_MAIN_P (arg))
+    {
+      /* ARM $3.4 */
+      /* Apparently a lot of autoconf scripts for C++ packages do this,
+        so only complain if -pedantic.  */
+      if (complain & (flag_pedantic_errors ? tf_error : tf_warning))
+       pedwarn (input_location, OPT_pedantic,
+                "ISO C++ forbids taking address of function %<::main%>");
+      else if (flag_pedantic_errors)
+       return error_mark_node;
+    }
+
+  /* Let &* cancel out to simplify resulting code.  */
+  if (TREE_CODE (arg) == INDIRECT_REF)
+    {
+      /* We don't need to have `current_class_ptr' wrapped in a
+        NON_LVALUE_EXPR node.  */
+      if (arg == current_class_ref)
+       return current_class_ptr;
+
+      arg = TREE_OPERAND (arg, 0);
+      if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
+       {
+         tree type = build_pointer_type (TREE_TYPE (TREE_TYPE (arg)));
+         arg = build1 (CONVERT_EXPR, type, arg);
+       }
+      else
+       /* Don't let this be an lvalue.  */
+       arg = rvalue (arg);
+      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))
+      && COMPLETE_TYPE_P (TREE_TYPE (val))
+      && 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);
+    }
+
+  /* Handle complex lvalues (when permitted)
+     by reduction to simpler cases.  */
+  val = unary_complex_lvalue (ADDR_EXPR, arg);
+  if (val != 0)
+    return val;
+
+  switch (TREE_CODE (arg))
+    {
+    CASE_CONVERT:
+    case FLOAT_EXPR:
+    case FIX_TRUNC_EXPR:
+      /* Even if we're not being pedantic, we cannot allow this
+        extension when we're instantiating in a SFINAE
+        context.  */
+      if (! lvalue_p (arg) && complain == tf_none)
+       {
+         if (complain & tf_error)
+           permerror (input_location, "ISO C++ forbids taking the address of a cast to a non-lvalue expression");
+         else
+           return error_mark_node;
+       }
+      break;
+
+    case BASELINK:
+      arg = BASELINK_FUNCTIONS (arg);
+      /* Fall through.  */
+
+    case OVERLOAD:
+      arg = OVL_CURRENT (arg);
+      break;
+
+    case OFFSET_REF:
+    offset_ref:
+      /* Turn a reference to a non-static data member into a
+        pointer-to-member.  */
+      {
+       tree type;
+       tree t;
+
+       gcc_assert (PTRMEM_OK_P (arg));
+
+       t = TREE_OPERAND (arg, 1);
+       if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
+         {
+           if (complain & tf_error)
+             error ("cannot create pointer to reference member %qD", t);
+           return error_mark_node;
+         }
+
+       type = build_ptrmem_type (context_for_name_lookup (t),
+                                 TREE_TYPE (t));
+       t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
+       return t;
+      }
+
+    default:
+      break;
+    }
+
+  if (argtype != error_mark_node)
+    argtype = build_pointer_type (argtype);
+
+  /* In a template, we are processing a non-dependent expression
+     so we can just form an ADDR_EXPR with the correct type.  */
+  if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF)
+    {
+      val = build_address (arg);
+      if (TREE_CODE (arg) == OFFSET_REF)
+       PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
+    }
+  else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
+    {
+      tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
+
+      /* We can only get here with a single static member
+        function.  */
+      gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
+                 && DECL_STATIC_FUNCTION_P (fn));
+      mark_used (fn);
+      val = build_address (fn);
+      if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
+       /* Do not lose object's side effects.  */
+       val = build2 (COMPOUND_EXPR, TREE_TYPE (val),
+                     TREE_OPERAND (arg, 0), val);
+    }
+  else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+    {
+      if (complain & tf_error)
+       error ("attempt to take address of bit-field structure member %qD",
+              TREE_OPERAND (arg, 1));
+      return error_mark_node;
+    }
+  else
+    {
+      tree object = TREE_OPERAND (arg, 0);
+      tree field = TREE_OPERAND (arg, 1);
+      gcc_assert (same_type_ignoring_top_level_qualifiers_p
+                 (TREE_TYPE (object), decl_type_context (field)));
+      val = build_address (arg);
+    }
+
+  if (TREE_CODE (argtype) == POINTER_TYPE
+      && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
+    {
+      build_ptrmemfunc_type (argtype);
+      val = build_ptrmemfunc (argtype, val, 0,
+                             /*c_cast_p=*/false,
+                             tf_warning_or_error);
+    }
+
+  return val;
+}
+
+/* Take the address of ARG if it has one, even if it's an rvalue.  */
+
+tree
+cp_build_addr_expr (tree arg, tsubst_flags_t complain)
+{
+  return cp_build_addr_expr_1 (arg, 0, complain);
+}
+
+/* Take the address of ARG, but only if it's an lvalue.  */
+
+tree
+cp_build_addr_expr_strict (tree arg, tsubst_flags_t complain)
+{
+  return cp_build_addr_expr_1 (arg, 1, complain);
+}
+
 /* C++: Must handle pointers to members.
 
    Perhaps type instantiation should be extended to handle conversion
@@ -5057,238 +5265,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
     case ADDR_EXPR:
       /* Note that this operation never does default_conversion
         regardless of NOCONVERT.  */
-
-      argtype = lvalue_type (arg);
-
-      arg = mark_lvalue_use (arg);
-
-      if (TREE_CODE (arg) == OFFSET_REF)
-       goto offset_ref;
-
-      if (TREE_CODE (argtype) == REFERENCE_TYPE)
-       {
-         tree type = build_pointer_type (TREE_TYPE (argtype));
-         arg = build1 (CONVERT_EXPR, type, arg);
-         return arg;
-       }
-      else if (pedantic && DECL_MAIN_P (arg))
-        {
-          /* ARM $3.4 */
-         /* Apparently a lot of autoconf scripts for C++ packages do this,
-            so only complain if -pedantic.  */
-          if (complain & (flag_pedantic_errors ? tf_error : tf_warning))
-            pedwarn (input_location, OPT_pedantic,
-                    "ISO C++ forbids taking address of function %<::main%>");
-          else if (flag_pedantic_errors)
-            return error_mark_node;
-        }
-
-      /* Let &* cancel out to simplify resulting code.  */
-      if (TREE_CODE (arg) == INDIRECT_REF)
-       {
-         /* We don't need to have `current_class_ptr' wrapped in a
-            NON_LVALUE_EXPR node.  */
-         if (arg == current_class_ref)
-           return current_class_ptr;
-
-         arg = TREE_OPERAND (arg, 0);
-         if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
-           {
-             tree type = build_pointer_type (TREE_TYPE (TREE_TYPE (arg)));
-             arg = build1 (CONVERT_EXPR, type, arg);
-           }
-         else
-           /* Don't let this be an lvalue.  */
-           arg = rvalue (arg);
-         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.  */
-
-      gcc_assert (TREE_CODE (arg) != IDENTIFIER_NODE
-                 || !IDENTIFIER_OPNAME_P (arg));
-
-      if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
-         && !really_overloaded_fn (TREE_OPERAND (arg, 1)))
-       {
-         /* They're trying to take the address of a unique non-static
-            member function.  This is ill-formed (except in MS-land),
-            but let's try to DTRT.
-            Note: We only handle unique functions here because we don't
-            want to complain if there's a static overload; non-unique
-            cases will be handled by instantiate_type.  But we need to
-            handle this case here to allow casts on the resulting PMF.
-            We could defer this in non-MS mode, but it's easier to give
-            a useful error here.  */
-
-         /* Inside constant member functions, the `this' pointer
-            contains an extra const qualifier.  TYPE_MAIN_VARIANT
-            is used here to remove this const from the diagnostics
-            and the created OFFSET_REF.  */
-         tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0)));
-         tree fn = get_first_fn (TREE_OPERAND (arg, 1));
-         mark_used (fn);
-
-         if (! flag_ms_extensions)
-           {
-             tree name = DECL_NAME (fn);
-              if (!(complain & tf_error))
-                return error_mark_node;
-             else if (current_class_type
-                       && TREE_OPERAND (arg, 0) == current_class_ref)
-                  /* An expression like &memfn.  */
-                permerror (input_location, "ISO C++ forbids taking the address of an unqualified"
-                           " or parenthesized non-static member function to form"
-                           " a pointer to member function.  Say %<&%T::%D%>",
-                           base, name);
-             else
-               permerror (input_location, "ISO C++ forbids taking the address of a bound member"
-                          " function to form a pointer to member function."
-                          "  Say %<&%T::%D%>",
-                          base, name);
-           }
-         arg = build_offset_ref (base, fn, /*address_p=*/true);
-       }
-
-    offset_ref:
-      if (type_unknown_p (arg))
-       return build1 (ADDR_EXPR, unknown_type_node, arg);
-
-      /* Handle complex lvalues (when permitted)
-        by reduction to simpler cases.  */
-      val = unary_complex_lvalue (code, arg);
-      if (val != 0)
-       return val;
-
-      switch (TREE_CODE (arg))
-       {
-       CASE_CONVERT:
-       case FLOAT_EXPR:
-       case FIX_TRUNC_EXPR:
-          /* Even if we're not being pedantic, we cannot allow this
-             extension when we're instantiating in a SFINAE
-             context.  */
-         if (! lvalue_p (arg) && complain == tf_none)
-            {
-              if (complain & tf_error)
-                permerror (input_location, "ISO C++ forbids taking the address of a cast to a non-lvalue expression");
-              else
-                return error_mark_node;
-            }
-         break;
-
-       case BASELINK:
-         arg = BASELINK_FUNCTIONS (arg);
-         /* Fall through.  */
-
-       case OVERLOAD:
-         arg = OVL_CURRENT (arg);
-         break;
-
-       case OFFSET_REF:
-         /* Turn a reference to a non-static data member into a
-            pointer-to-member.  */
-         {
-           tree type;
-           tree t;
-
-           if (!PTRMEM_OK_P (arg))
-             return cp_build_unary_op (code, arg, 0, complain);
-
-           t = TREE_OPERAND (arg, 1);
-           if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
-             {
-                if (complain & tf_error)
-                  error ("cannot create pointer to reference member %qD", t);
-               return error_mark_node;
-             }
-
-           type = build_ptrmem_type (context_for_name_lookup (t),
-                                     TREE_TYPE (t));
-           t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
-           return t;
-         }
-
-       default:
-         break;
-       }
-
-      /* Anything not already handled and not a true memory reference
-        is an error.  */
-      if (TREE_CODE (argtype) != FUNCTION_TYPE
-         && TREE_CODE (argtype) != METHOD_TYPE
-         && TREE_CODE (arg) != OFFSET_REF
-         && !lvalue_or_else (arg, lv_addressof, complain))
-       return error_mark_node;
-
-      if (argtype != error_mark_node)
-       argtype = build_pointer_type (argtype);
-
-      /* In a template, we are processing a non-dependent expression
-        so we can just form an ADDR_EXPR with the correct type.  */
-      if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF)
-       {
-         val = build_address (arg);
-         if (TREE_CODE (arg) == OFFSET_REF)
-           PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
-       }
-      else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
-       {
-         tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
-
-         /* We can only get here with a single static member
-            function.  */
-         gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
-                     && DECL_STATIC_FUNCTION_P (fn));
-         mark_used (fn);
-         val = build_address (fn);
-         if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
-           /* Do not lose object's side effects.  */
-           val = build2 (COMPOUND_EXPR, TREE_TYPE (val),
-                         TREE_OPERAND (arg, 0), val);
-       }
-      else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
-       {
-          if (complain & tf_error)
-            error ("attempt to take address of bit-field structure member %qD",
-                   TREE_OPERAND (arg, 1));
-         return error_mark_node;
-       }
-      else
-       {
-         tree object = TREE_OPERAND (arg, 0);
-         tree field = TREE_OPERAND (arg, 1);
-         gcc_assert (same_type_ignoring_top_level_qualifiers_p
-                     (TREE_TYPE (object), decl_type_context (field)));
-         val = build_address (arg);
-       }
-
-      if (TREE_CODE (argtype) == POINTER_TYPE
-         && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
-       {
-         build_ptrmemfunc_type (argtype);
-         val = build_ptrmemfunc (argtype, val, 0,
-                                 /*c_cast_p=*/false,
-                                 tf_warning_or_error);
-       }
-
-      return val;
+      return cp_build_addr_expr (arg, complain);
 
     default:
       break;
@@ -6119,7 +6096,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
        warning (0, "casting %qT to %qT does not dereference pointer",
                 intype, type);
 
-      expr = cp_build_unary_op (ADDR_EXPR, expr, 0, complain);
+      expr = cp_build_addr_expr (expr, complain);
 
       if (warn_strict_aliasing > 2)
        strict_aliasing_warning (TREE_TYPE (expr), type, expr);
@@ -6357,8 +6334,8 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
        }
       if (reference_type)
        {
-         expr = cp_build_unary_op (ADDR_EXPR, expr, 0, 
-                                    complain? tf_warning_or_error : tf_none);
+         expr = cp_build_addr_expr (expr,
+                                    complain ? tf_warning_or_error : tf_none);
          expr = build_nop (reference_type, expr);
          return convert_from_reference (expr);
        }
@@ -6688,12 +6665,19 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
     }
   else
     {
-      lhs = require_complete_type (lhs);
+      lhs = require_complete_type_sfinae (lhs, complain);
       if (lhs == error_mark_node)
        return error_mark_node;
 
       if (modifycode == NOP_EXPR)
        {
+         if (c_dialect_objc ())
+           {
+             result = objc_maybe_build_modify_expr (lhs, rhs);
+             if (result)
+               return result;
+           }
+
          /* `operator=' is not an inheritable operator.  */
          if (! MAYBE_CLASS_TYPE_P (lhstype))
            /* Do the default thing.  */;
@@ -6732,6 +6716,12 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
 
          /* Now it looks like a plain assignment.  */
          modifycode = NOP_EXPR;
+         if (c_dialect_objc ())
+           {
+             result = objc_maybe_build_modify_expr (lhs, newrhs);
+             if (result)
+               return result;
+           }
        }
       gcc_assert (TREE_CODE (lhstype) != REFERENCE_TYPE);
       gcc_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE);
@@ -7448,8 +7438,7 @@ convert_for_assignment (tree type, tree rhs,
       && TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE
       && (complain & tf_warning))
     {
-      location_t loc = EXPR_HAS_LOCATION (rhs) 
-       ? EXPR_LOCATION (rhs) : input_location;
+      location_t loc = EXPR_LOC_OR_HERE (rhs);
 
       warning_at (loc, OPT_Wparentheses,
                  "suggest parentheses around assignment used as truth value");
@@ -7536,7 +7525,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
     }
 
   if (exp != 0)
-    exp = require_complete_type (exp);
+    exp = require_complete_type_sfinae (exp, complain);
   if (exp == error_mark_node)
     return error_mark_node;
 
@@ -7925,12 +7914,13 @@ comp_ptr_ttypes_real (tree to, tree from, int constp)
          /* In Objective-C++, some types may have been 'volatilized' by
             the compiler for EH; when comparing them here, the volatile
             qualification must be ignored.  */
-         bool objc_quals_match = objc_type_quals_match (to, from);
+         tree nv_to = objc_non_volatilized_type (to);
+         tree nv_from = objc_non_volatilized_type (from);
 
-         if (!at_least_as_qualified_p (to, from) && !objc_quals_match)
+         if (!at_least_as_qualified_p (nv_to, nv_from))
            return 0;
 
-         if (!at_least_as_qualified_p (from, to) && !objc_quals_match)
+         if (!at_least_as_qualified_p (nv_from, nv_to))
            {
              if (constp == 0)
                return 0;
@@ -7938,7 +7928,7 @@ comp_ptr_ttypes_real (tree to, tree from, int constp)
            }
 
          if (constp > 0)
-           constp &= TYPE_READONLY (to);
+           constp &= TYPE_READONLY (nv_to);
        }
 
       if (TREE_CODE (to) == VECTOR_TYPE)
@@ -8315,11 +8305,24 @@ non_reference (tree t)
 int
 lvalue_or_else (tree ref, enum lvalue_use use, tsubst_flags_t complain)
 {
-  int win = lvalue_p (ref);
-
-  if (!win && (complain & tf_error))
-    lvalue_error (use);
+  cp_lvalue_kind kind = lvalue_kind (ref);
 
-  return win;
+  if (kind == clk_none)
+    {
+      if (complain & tf_error)
+       lvalue_error (use);
+      return 0;
+    }
+  else if (kind & (clk_rvalueref|clk_class))
+    {
+      if (!(complain & tf_error))
+       return 0;
+      if (kind & clk_class)
+       /* Make this a permerror because we used to accept it.  */
+       permerror (input_location, "using temporary as lvalue");
+      else
+       error ("using xvalue (rvalue reference) as lvalue");
+    }
+  return 1;
 }