OSDN Git Service

* g++.old-deja/g++.benjamin/16077.C: Adjust warnings.
[pf3gnuchains/gcc-fork.git] / gcc / cp / typeck.c
index 9b4fbf6..0cbff77 100644 (file)
@@ -1,22 +1,22 @@
 /* Build expressions with type checking for C++ compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
+along with GCC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
@@ -32,6 +32,8 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "rtl.h"
 #include "expr.h"
@@ -64,6 +66,7 @@ static void casts_away_constness_r PARAMS ((tree *, tree *));
 static int casts_away_constness PARAMS ((tree, tree));
 static void maybe_warn_about_returning_address_of_local PARAMS ((tree));
 static tree strip_all_pointer_quals PARAMS ((tree));
+static tree lookup_destructor (tree, tree, tree);
 
 /* Return the target type of TYPE, which means return T for:
    T*, T&, T[], T (...), and otherwise, just T.  */
@@ -943,6 +946,13 @@ comptypes (t1, t2, strict)
   if (TYPE_PTRMEMFUNC_P (t2))
     t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
 
+  /* TYPENAME_TYPEs should be resolved if the qualifying scope is the
+     current instantiation.  */
+  if (TREE_CODE (t1) == TYPENAME_TYPE)
+    t1 = resolve_typename_type_in_current_instantiation (t1);
+  if (TREE_CODE (t2) == TYPENAME_TYPE)
+    t2 = resolve_typename_type_in_current_instantiation (t2);
+
   /* Different classes of types can't be compatible.  */
   if (TREE_CODE (t1) != TREE_CODE (t2))
     return 0;
@@ -1856,30 +1866,12 @@ build_class_member_access_expr (tree object, tree member,
   if (object == error_mark_node || member == error_mark_node)
     return error_mark_node;
 
+  if (TREE_CODE (member) == PSEUDO_DTOR_EXPR)
+    return member;
+
   my_friendly_assert (DECL_P (member) || BASELINK_P (member),
                      20020801);
 
-  /* Transform `(a, b).x' into `a, b.x' and `(a ? b : c).x' into 
-     `a ? b.x : c.x'.  These transformations should not really be
-     necessary, but they are.  */
-  if (TREE_CODE (object) == COMPOUND_EXPR)
-    {
-      result = build_class_member_access_expr (TREE_OPERAND (object, 1),
-                                              member, access_path, 
-                                              preserve_reference);
-      return build (COMPOUND_EXPR, TREE_TYPE (result), 
-                   TREE_OPERAND (object, 0), result);
-    }
-  else if (TREE_CODE (object) == COND_EXPR)
-    return (build_conditional_expr
-           (TREE_OPERAND (object, 0),
-            build_class_member_access_expr (TREE_OPERAND (object, 1),
-                                            member, access_path,
-                                            preserve_reference),
-            build_class_member_access_expr (TREE_OPERAND (object, 2),
-                                            member, access_path,
-                                            preserve_reference)));
-
   /* [expr.ref]
 
      The type of the first expression shall be "class object" (of a
@@ -1919,6 +1911,15 @@ build_class_member_access_expr (tree object, tree member,
       return error_mark_node;
     }
 
+  /* Transform `(a, b).x' into `(*(a, &b)).x', `(a ? b : c).x' into
+     `(*(a ?  &b : &c)).x', and so on.  A COND_EXPR is only an lvalue
+     in the frontend; only _DECLs and _REFs are lvalues in the backend.  */
+  {
+    tree temp = unary_complex_lvalue (ADDR_EXPR, object);
+    if (temp)
+      object = build_indirect_ref (temp, NULL);
+  }
+
   /* In [expr.ref], there is an explicit list of the valid choices for
      MEMBER.  We check for each of those cases here.  */
   if (TREE_CODE (member) == VAR_DECL)
@@ -1969,8 +1970,11 @@ build_class_member_access_expr (tree object, tree member,
          my_friendly_assert (object != error_mark_node,
                              20020801);
        }
-      
-      /* Issue a warning about access a member of a NULL object.  */
+
+      /* Complain about other invalid uses of offsetof, even though they will
+        give the right answer.  Note that we complain whether or not they
+        actually used the offsetof macro, since there's no way to know at this
+        point.  So we just give a warning, instead of a pedwarn.  */
       if (null_object_p && CLASSTYPE_NON_POD_P (object_type))
        {
          warning ("invalid access to non-static data member `%D' of NULL object", 
@@ -1982,7 +1986,15 @@ build_class_member_access_expr (tree object, tree member,
         OBJECT so that it refers to the class containing the
         anonymous union.  Generate a reference to the anonymous union
         itself, and recur to find MEMBER.  */
-      if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member)))
+      if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member))
+         /* When this code is called from build_field_call, the
+            object already has the type of the anonymous union.
+            That is because the COMPONENT_REF was already
+            constructed, and was then disassembled before calling
+            build_field_call.  After the function-call code is
+            cleaned up, this waste can be eliminated.  */
+         && (!same_type_ignoring_top_level_qualifiers_p 
+             (TREE_TYPE (object), DECL_CONTEXT (member))))
        {
          tree anonymous_union;
 
@@ -2024,6 +2036,7 @@ build_class_member_access_expr (tree object, tree member,
     {
       /* The member is a (possibly overloaded) member function.  */
       tree functions;
+      tree type;
 
       /* If the MEMBER is exactly one static member function, then we
         know the type of the expression.  Otherwise, we must wait
@@ -2031,19 +2044,12 @@ build_class_member_access_expr (tree object, tree member,
       functions = BASELINK_FUNCTIONS (member);
       if (TREE_CODE (functions) == FUNCTION_DECL
          && DECL_STATIC_FUNCTION_P (functions))
-       {
-         /* A static member function.  */
-         result = functions;
-         mark_used (result);
-         /* If OBJECT has side-effects, they are supposed to occur.  */
-         if (TREE_SIDE_EFFECTS (object))
-           result = build (COMPOUND_EXPR, TREE_TYPE (result),
-                           object, result);
-       }
+       type = TREE_TYPE (functions);
       else
-       /* Note that we do not convert OBJECT to the BASELINK_BINFO
-          base.  That will happen when the function is called.  */
-       result = build (COMPONENT_REF, unknown_type_node, object, member);
+       type = unknown_type_node;
+      /* Note that we do not convert OBJECT to the BASELINK_BINFO
+        base.  That will happen when the function is called.  */
+      result = build (COMPONENT_REF, type, object, member);
     }
   else if (TREE_CODE (member) == CONST_DECL)
     {
@@ -2070,6 +2076,34 @@ build_class_member_access_expr (tree object, tree member,
   return result;
 }
 
+/* Return the destructor denoted by OBJECT.SCOPE::~DTOR_NAME, or, if
+   SCOPE is NULL, by OBJECT.~DTOR_NAME.  */
+
+static tree
+lookup_destructor (tree object, tree scope, tree dtor_name)
+{
+  tree object_type = TREE_TYPE (object);
+  tree dtor_type = TREE_OPERAND (dtor_name, 0);
+
+  if (scope && !check_dtor_name (scope, dtor_name))
+    {
+      error ("qualified type `%T' does not match destructor name `~%T'",
+            scope, dtor_type);
+      return error_mark_node;
+    }
+  if (!same_type_p (dtor_type, TYPE_MAIN_VARIANT (object_type)))
+    {
+      error ("destructor name `%T' does not match type `%T' of expression",
+            dtor_type, object_type);
+      return error_mark_node;
+    }
+  if (!TYPE_HAS_DESTRUCTOR (object_type))
+    return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
+                 dtor_type);
+  return lookup_member (object_type, complete_dtor_identifier,
+                       /*protect=*/1, /*want_type=*/false);
+}
+
 /* This function is called by the parser to process a class member
    access expression of the form OBJECT.NAME.  NAME is a node used by
    the parser to represent a name; it is not yet a DECL.  It may,
@@ -2165,38 +2199,29 @@ finish_class_member_access_expr (tree object, tree name)
          if (!access_path || access_path == error_mark_node)
            return error_mark_node;
 
-         /* Look up the member.  */
-         member = lookup_member (access_path, name, /*protect=*/1, 
-                                 /*want_type=*/0);
-         if (member == NULL_TREE)
+         if (TREE_CODE (name) == BIT_NOT_EXPR)
+           member = lookup_destructor (object, scope, name);
+         else
            {
-             error ("'%D' has no member named '%E'", object_type, name);
-             return error_mark_node;
+             /* Look up the member.  */
+             member = lookup_member (access_path, name, /*protect=*/1, 
+                                     /*want_type=*/false);
+             if (member == NULL_TREE)
+               {
+                 error ("'%D' has no member named '%E'", object_type, name);
+                 return error_mark_node;
+               }
+             if (member == error_mark_node)
+               return error_mark_node;
            }
-         else if (member == error_mark_node)
-           return error_mark_node;
        }
       else if (TREE_CODE (name) == BIT_NOT_EXPR)
-       {
-         /* A destructor.  */
-         if (TYPE_IDENTIFIER (object_type) != TREE_OPERAND (name, 0))
-           {
-             error ("destructor specifier `%T::~%T' must have matching names",
-                    object_type, TREE_OPERAND (name, 0));
-             return error_mark_node;
-           }
-         if (! TYPE_HAS_DESTRUCTOR (object_type))
-           {
-             error ("type `%T' has no destructor", object_type);
-             return error_mark_node;
-           }
-         member = CLASSTYPE_DESTRUCTORS (object_type);
-       }
+       member = lookup_destructor (object, /*scope=*/NULL_TREE, name);
       else if (TREE_CODE (name) == IDENTIFIER_NODE)
        {
          /* An unqualified name.  */
          member = lookup_member (object_type, name, /*protect=*/1, 
-                                 /*want_type=*/0);
+                                 /*want_type=*/false);
          if (member == NULL_TREE)
            {
              error ("'%D' has no member named '%E'", object_type, name);
@@ -2232,6 +2257,9 @@ finish_class_member_access_expr (tree object, tree name)
        }
     }
 
+  if (TREE_DEPRECATED (member))
+    warn_deprecated_use (member);
+
   return build_class_member_access_expr (object, member, access_path,
                                         /*preserve_reference=*/false);
 }
@@ -2257,7 +2285,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
   ptrmem_type = TREE_TYPE (ptrmem);
   my_friendly_assert (TYPE_PTRMEMFUNC_P (ptrmem_type), 20020804);
   member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
-                         /*want_type=*/0);
+                         /*want_type=*/false);
   member_type = cp_build_qualified_type (TREE_TYPE (member),
                                         cp_type_quals (ptrmem_type));
   return fold (build (COMPONENT_REF, member_type, ptrmem, member));
@@ -2280,8 +2308,8 @@ build_x_indirect_ref (ptr, errorstring)
   if (processing_template_decl)
     return build_min_nt (INDIRECT_REF, ptr);
 
-  rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
-                        NULL_TREE);
+  rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
+                      NULL_TREE);
   if (rval)
     return rval;
   return build_indirect_ref (ptr, errorstring);
@@ -2324,8 +2352,7 @@ build_indirect_ref (ptr, errorstring)
           return error_mark_node;
         }
       else if (TREE_CODE (pointer) == ADDR_EXPR
-         && !flag_volatile
-         && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))
+              && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))
        /* The POINTER was something like `&x'.  We simplify `*&x' to
           `x'.  */
        return TREE_OPERAND (pointer, 0);
@@ -2339,8 +2366,7 @@ build_indirect_ref (ptr, errorstring)
          TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
          TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
          TREE_SIDE_EFFECTS (ref)
-           = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer)
-              || flag_volatile);
+           = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer));
          return ref;
        }
     }
@@ -2538,6 +2564,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
       tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
 
       tree instance_ptr = *instance_ptrptr;
+      tree instance_save_expr = 0;
       if (instance_ptr == error_mark_node)
        {
          if (TREE_CODE (function) == PTRMEM_CST)
@@ -2557,7 +2584,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
        }
 
       if (TREE_SIDE_EFFECTS (instance_ptr))
-       instance_ptr = save_expr (instance_ptr);
+       instance_ptr = instance_save_expr = save_expr (instance_ptr);
 
       if (TREE_SIDE_EFFECTS (function))
        function = save_expr (function);
@@ -2618,9 +2645,9 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
       
       /* Make sure this doesn't get evaluated first inside one of the
         branches of the COND_EXPR.  */
-      if (TREE_CODE (instance_ptr) == SAVE_EXPR)
+      if (instance_save_expr)
        e1 = build (COMPOUND_EXPR, TREE_TYPE (e1),
-                   instance_ptr, e1);
+                   instance_save_expr, e1);
 
       function = e1;
     }
@@ -2628,9 +2655,8 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
 }
 
 tree
-build_function_call_real (function, params, require_complete, flags)
+build_function_call (function, params)
      tree function, params;
-     int require_complete, flags;
 {
   register tree fntype, fndecl;
   register tree value_type;
@@ -2704,20 +2730,10 @@ build_function_call_real (function, params, require_complete, flags)
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
 
-  if (flags & LOOKUP_COMPLAIN)
-    coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
-                                       params, fndecl, LOOKUP_NORMAL);
-  else
-    coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
-                                       params, fndecl, 0);
-
+  coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
+                                     params, fndecl, LOOKUP_NORMAL);
   if (coerced_params == error_mark_node)
-    {
-      if (flags & LOOKUP_SPECULATIVELY)
-       return NULL_TREE;
-      else
-       return error_mark_node;
-    }
+    return error_mark_node;
 
   /* Check for errors in format strings.  */
 
@@ -2743,23 +2759,13 @@ build_function_call_real (function, params, require_complete, flags)
   result = fold (build_call (function, coerced_params));
   value_type = TREE_TYPE (result);
 
-  if (require_complete)
-    {
-      if (TREE_CODE (value_type) == VOID_TYPE)
-       return result;
-      result = require_complete_type (result);
-    }
+  if (TREE_CODE (value_type) == VOID_TYPE)
+    return result;
+  result = require_complete_type (result);
   if (IS_AGGR_TYPE (value_type))
     result = build_cplus_new (value_type, result);
   return convert_from_reference (result);
 }
-
-tree
-build_function_call (function, params)
-     tree function, params;
-{
-  return build_function_call_real (function, params, 1, LOOKUP_NORMAL);
-}
 \f
 /* Convert the actual parameter expressions in the list VALUES
    to the types in the list TYPELIST.
@@ -2900,7 +2906,8 @@ convert_arguments (typelist, values, fndecl, flags)
   if (typetail != 0 && typetail != void_list_node)
     {
       /* See if there are default arguments that can be used */
-      if (TREE_PURPOSE (typetail))
+      if (TREE_PURPOSE (typetail) 
+         && TREE_CODE (TREE_PURPOSE (typetail)) != DEFAULT_ARG)
        {
          for (; typetail != void_list_node; ++i)
            {
@@ -2950,6 +2957,183 @@ build_x_binary_op (code, arg1, arg2)
   return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
 }
 
+#if 0
+
+tree
+build_template_expr (enum tree_code code, tree op0, tree op1, tree op2)
+{
+  tree type;
+
+  /* If any of the operands is erroneous the result is erroneous too.  */
+  if (error_operand_p (op0)
+      || (op1 && error_operand_p (op1))
+      || (op2 && error_operand_p (op2)))
+    return error_mark_node;
+      
+  if (dependent_type_p (TREE_TYPE (op0))
+      || (op1 && dependent_type_p (TREE_TYPE (op1)))
+      || (op2 && dependent_type_p (TREE_TYPE (op2))))
+    /* If at least one operand has a dependent type, we cannot
+       determine the type of the expression until instantiation time.  */
+    type = NULL_TREE;
+  else
+    {
+      struct z_candidate *cand;
+      tree op0_type;
+      tree op1_type;
+      tree op2_type;
+
+      /* None of the operands is dependent, so we can compute the type
+        of the expression at this point.  We must compute the type so
+        that in things like:
+
+          template <int I>
+          void f() { S<sizeof(I + 3)> s; ... }
+
+        we can tell that the type of "s" is non-dependent.
+
+        If we're processing a template argument, we do not want to
+        actually change the operands in any way.  Adding conversions,
+        performing constant folding, etc., would all change mangled
+        names.  For example, in:
+        
+          template <int I>
+          void f(S<sizeof(3 + 4 + I)>);
+        
+        we need to determine that "3 + 4 + I" has type "int", without
+        actually turning the expression into "7 + I".  */
+      cand = find_overloaded_op (code, op0, op1, op2);
+      if (cand) 
+       /* If an overloaded operator was found, the expression will
+          have the type returned by the function.  */
+       type = non_reference (TREE_TYPE (cand->fn));
+      else
+       {
+         /* There is no overloaded operator so we can just use the
+            default rules for determining the type of the operand.  */
+         op0_type = TREE_TYPE (op0);
+         op1_type = op1 ? TREE_TYPE (op1) : NULL_TREE;
+         op2_type = op2 ? TREE_TYPE (op2) : NULL_TREE;
+         type = NULL_TREE;
+
+         switch (code)
+           {
+           case MODIFY_EXPR:
+             /* [expr.ass]
+
+                The result of the assignment operation is the value
+                stored in the left operand.  */
+             type = op0_type;
+             break;
+           case COMPONENT_REF:
+             /* Implement this case.  */
+             break;
+           case POSTINCREMENT_EXPR:
+           case POSTDECREMENT_EXPR:
+             /* [expr.post.incr]
+
+                The type of the result is the cv-unqualified version
+                of the type of the operand.  */
+             type = TYPE_MAIN_VARIANT (op0_type);
+             break;
+           case PREINCREMENT_EXPR:
+           case PREDECREMENT_EXPR:
+             /* [expr.pre.incr]
+
+                The value is the new value of the operand.  */
+             type = op0_type;
+             break;
+           case INDIRECT_REF:
+             /* [expr.unary.op]
+
+                If the type of the expression is "pointer to T", the
+                type of the result is "T".  */
+             type = TREE_TYPE (op0_type);
+             break;
+           case ADDR_EXPR:
+             /* [expr.unary.op]
+
+                If the type of the expression is "T", the type of the
+                result is "pointer to T".  */
+             /* FIXME: Handle the pointer-to-member case.  */
+             break;
+           case MEMBER_REF:
+             /* FIXME: Implement this case.  */
+             break;
+           case LSHIFT_EXPR:
+           case RSHIFT_EXPR:
+             /* [expr.shift]
+
+                The type of the result is that of the promoted left
+                operand.  */
+             break;
+           case PLUS_EXPR:
+           case MINUS_EXPR:
+             /* FIXME: Be careful of special pointer-arithmetic
+                cases.  */
+             /* Fall through. */
+           case MAX_EXPR:
+           case MIN_EXPR:
+             /* These are GNU extensions; the result type is computed
+                as it would be for other arithmetic operators.  */
+             /* Fall through. */
+           case BIT_AND_EXPR:
+           case BIT_XOR_EXPR:
+           case BIT_IOR_EXPR:
+           case MULT_EXPR:
+           case TRUNC_DIV_EXPR:
+           case TRUNC_MOD_EXPR:
+             /* [expr.bit.and], [expr.xor], [expr.or], [expr.mul]
+
+                The usual arithmetic conversions are performed on the
+                operands and determine the type of the result.  */
+             /* FIXME: Check that this is possible.  */
+             type = type_after_usual_arithmetic_conversions (t1, t2);
+             break;
+           case GT_EXPR:
+           case LT_EXPR:
+           case GE_EXPR:
+           case LE_EXPR:
+           case EQ_EXPR:
+           case NE_EXPR:
+             /* [expr.rel]
+
+                The type of the result is bool.  */
+             type = boolean_type_node;
+             break;
+           case TRUTH_ANDIF_EXPR:
+           case TRUTH_ORIF_EXPR:
+             /* [expr.log.and], [expr.log.org]
+                
+                The result is a bool.  */
+             type = boolean_type_node;
+             break;
+           case COND_EXPR:
+             /* FIXME: Handle special rules for conditioanl
+                expressions.  */
+             break;
+           case COMPOUND_EXPR:
+             type = op1_type;
+             break;
+           default:
+             abort ();
+           }
+         /* If the type of the expression could not be determined,
+            something is wrong.  */
+         if (!type)
+           abort ();
+         /* If the type is erroneous, the expression is erroneous
+            too.  */
+         if (type == error_mark_node)
+           return error_mark_node;
+       }
+    }
+  
+  return build_min (code, type, op0, op1, op2, NULL_TREE);
+}
+
+#endif
+
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
    This function differs from `build' in several ways:
@@ -3884,7 +4068,45 @@ condition_conversion (expr)
   t = fold (build1 (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.  */
+
+tree
+build_address (tree t)
+{
+  tree addr;
+
+  if (error_operand_p (t) || !cxx_mark_addressable (t))
+    return error_mark_node;
+
+  addr = build1 (ADDR_EXPR, 
+                build_pointer_type (TREE_TYPE (t)),
+                t);
+  if (staticp (t))
+    TREE_CONSTANT (addr) = 1;
+
+  return addr;
+}
+
+/* Return a NOP_EXPR converting EXPR to TYPE.  */
+
+tree
+build_nop (tree type, tree expr)
+{
+  tree nop;
+
+  if (type == error_mark_node || error_operand_p (expr))
+    return expr;
+    
+  nop = build1 (NOP_EXPR, type, expr);
+  if (TREE_CONSTANT (expr))
+    TREE_CONSTANT (nop) = 1;
+  
+  return nop;
+}
+
 /* C++: Must handle pointers to members.
 
    Perhaps type instantiation should be extended to handle conversion
@@ -3916,7 +4138,7 @@ build_unary_op (code, xarg, noconvert)
         is enough to prevent anybody from looking inside for
         associativity, but won't generate any code.  */
       if (!(arg = build_expr_type_conversion
-           (WANT_ARITH | WANT_ENUM | WANT_POINTER, arg, 1)))
+           (WANT_ARITH | WANT_ENUM | WANT_POINTER, arg, true)))
        errstring = "wrong type argument to unary plus";
       else
        {
@@ -3928,7 +4150,7 @@ build_unary_op (code, xarg, noconvert)
       break;
 
     case NEGATE_EXPR:
-      if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1)))
+      if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true)))
        errstring = "wrong type argument to unary minus";
       else if (!noconvert)
        arg = default_conversion (arg);
@@ -3942,14 +4164,14 @@ build_unary_op (code, xarg, noconvert)
            arg = default_conversion (arg);
        }
       else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM,
-                                                  arg, 1)))
+                                                  arg, true)))
        errstring = "wrong type argument to bit-complement";
       else if (!noconvert)
        arg = default_conversion (arg);
       break;
 
     case ABS_EXPR:
-      if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1)))
+      if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true)))
        errstring = "wrong type argument to abs";
       else if (!noconvert)
        arg = default_conversion (arg);
@@ -3957,7 +4179,7 @@ build_unary_op (code, xarg, 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, 1)))
+      if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true)))
        errstring = "wrong type argument to conjugation";
       else if (!noconvert)
        arg = default_conversion (arg);
@@ -4017,7 +4239,7 @@ build_unary_op (code, xarg, noconvert)
       /* Report invalid types.  */
 
       if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_POINTER,
-                                             arg, 1)))
+                                             arg, true)))
        {
          if (code == PREINCREMENT_EXPR)
            errstring ="no pre-increment operator for type";
@@ -4226,7 +4448,7 @@ build_unary_op (code, xarg, noconvert)
              if (current_class_type
                  && TREE_OPERAND (arg, 0) == current_class_ref)
                /* An expression like &memfn.  */
-               pedwarn ("ISO C++ forbids taking the address of an unqualified non-static member function to form a pointer to member function.  Say `&%T::%D'", base, name);
+               pedwarn ("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
                pedwarn ("ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say `&%T::%D'", base, name);
            }
@@ -4274,13 +4496,14 @@ build_unary_op (code, xarg, noconvert)
       if (argtype != error_mark_node)
        argtype = build_pointer_type (argtype);
 
-      if (!cxx_mark_addressable (arg))
-       return error_mark_node;
-
       {
        tree addr;
 
        if (TREE_CODE (arg) == COMPONENT_REF
+           && TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
+         arg = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
+
+       if (TREE_CODE (arg) == COMPONENT_REF
            && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
          {
            error ("attempt to take address of bit-field structure member `%D'",
@@ -4306,12 +4529,7 @@ build_unary_op (code, xarg, noconvert)
                                cp_convert (argtype, byte_position (field))));
          }
        else
-         addr = build1 (ADDR_EXPR, argtype, arg);
-
-       /* Address of a static or external variable or
-          function counts as a constant */
-       if (staticp (arg))
-         TREE_CONSTANT (addr) = 1;
+         addr = build_address (arg);
 
        if (TREE_CODE (argtype) == POINTER_TYPE
            && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
@@ -4575,8 +4793,8 @@ build_x_compound_expr (list)
   if (rest == NULL_TREE)
     return build_compound_expr (list);
 
-  result = build_opfncall (COMPOUND_EXPR, LOOKUP_NORMAL,
-                          TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
+  result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL,
+                        TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
   if (result)
     return build_x_compound_expr (tree_cons (NULL_TREE, result,
                                                  TREE_CHAIN (rest)));
@@ -5208,8 +5426,8 @@ build_modify_expr (lhs, modifycode, rhs)
            /* Do the default thing */;
          else
            {
-             result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
-                                      lhs, rhs, make_node (NOP_EXPR));
+             result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL,
+                                    lhs, rhs, make_node (NOP_EXPR));
              if (result == NULL_TREE)
                return error_mark_node;
              return result;
@@ -5300,7 +5518,7 @@ build_modify_expr (lhs, modifycode, rhs)
          || TREE_CODE (TREE_TYPE (lhs)) == METHOD_TYPE
          /* If it's an aggregate and any field is const, then it is
             effectively const.  */
-         || (IS_AGGR_TYPE_CODE (TREE_CODE (lhstype))
+         || (CLASS_TYPE_P (lhstype)
              && C_TYPE_FIELDS_READONLY (lhstype))))
     readonly_error (lhs, "assignment", 0);
 
@@ -5353,7 +5571,7 @@ build_modify_expr (lhs, modifycode, rhs)
 
       from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
                   ? 1 + (modifycode != INIT_EXPR): 0;
-      return build_vec_init (lhs, newrhs, from_array);
+      return build_vec_init (lhs, NULL_TREE, newrhs, from_array);
     }
 
   if (modifycode == INIT_EXPR)
@@ -5461,8 +5679,8 @@ build_x_modify_expr (lhs, modifycode, rhs)
 
   if (modifycode != NOP_EXPR)
     {
-      tree rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
-                                 make_node (modifycode));
+      tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
+                               make_node (modifycode));
       if (rval)
        return rval;
     }
@@ -5511,9 +5729,8 @@ get_delta_difference (from, to, force)
       if (virt_binfo)
         {
           /* This is a reinterpret cast, we choose to do nothing.  */
-          warning ("pointer to member cast via virtual base `%T' of `%T'",
-                     BINFO_TYPE (virt_binfo),
-                     BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
+          warning ("pointer to member cast via virtual base `%T'",
+                  BINFO_TYPE (virt_binfo));
           return delta;
         }
       delta = BINFO_OFFSET (binfo);
@@ -5530,13 +5747,11 @@ get_delta_difference (from, to, force)
     {
       /* This is a reinterpret cast, we choose to do nothing.  */
       if (force)
-        warning ("pointer to member cast via virtual base `%T' of `%T'",
-                    BINFO_TYPE (virt_binfo),
-                    BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
+        warning ("pointer to member cast via virtual base `%T'",
+                BINFO_TYPE (virt_binfo));
       else
-       error ("pointer to member conversion via virtual base `%T' of `%T'",
-                 BINFO_TYPE (virt_binfo),
-                  BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
+       error ("pointer to member conversion via virtual base `%T'",
+              BINFO_TYPE (virt_binfo));
       return delta;
     }
   delta = BINFO_OFFSET (binfo);
@@ -5592,11 +5807,17 @@ build_ptrmemfunc (type, pfn, force)
      int force;
 {
   tree fn;
-  tree pfn_type = TREE_TYPE (pfn);
-  tree to_type = build_ptrmemfunc_type (type);
+  tree pfn_type;
+  tree to_type;
+
+  if (error_operand_p (pfn))
+    return error_mark_node;
+
+  pfn_type = TREE_TYPE (pfn);
+  to_type = build_ptrmemfunc_type (type);
 
   /* Handle multiple conversions of pointer to member functions.  */
-  if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
+  if (TYPE_PTRMEMFUNC_P (pfn_type))
     {
       tree delta = NULL_TREE;
       tree npfn = NULL_TREE;
@@ -5855,8 +6076,16 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
   /* Simplify the RHS if possible.  */
   if (TREE_CODE (rhs) == CONST_DECL)
     rhs = DECL_INITIAL (rhs);
-  else if (coder != ARRAY_TYPE)
-    rhs = decl_constant_value (rhs);
+  
+  /* We do not use decl_constant_value here because of this case:
+
+       const char* const s = "s";
+     The conversion rules for a string literal are more lax than for a
+     variable; in particular, a string literal can be converted to a
+     "char *" but the variable "s" cannot be converted in the same
+     way.  If the conversion is allowed, the optimization should be
+     performed while creating the converted expression.  */
 
   /* [expr.ass]
 
@@ -5969,7 +6198,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
 
       if (fndecl)
        savew = warningcount, savee = errorcount;
-      rhs = initialize_reference (type, rhs);
+      rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE);
       if (fndecl)
        {
          if (warningcount > savew)
@@ -6047,8 +6276,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
          tree type = TREE_TYPE (o[i]);
          if (type != error_mark_node
              && (CP_TYPE_CONST_P (type)
-                 || (IS_AGGR_TYPE_CODE (TREE_CODE (type))
-                     && C_TYPE_FIELDS_READONLY (type))))
+                 || (CLASS_TYPE_P (type) && C_TYPE_FIELDS_READONLY (type))))
            readonly_error (o[i], "modification by `asm'", 1);
        }
     }
@@ -6158,6 +6386,12 @@ check_return_expr (retval)
       return NULL_TREE;
     }
 
+  if (processing_template_decl)
+    {
+      current_function_returns_value = 1;
+      return retval;
+    }
+  
   /* When no explicit return-value is given in a function with a named
      return value, the named return value is used.  */
   result = DECL_RESULT (current_function_decl);
@@ -6461,6 +6695,8 @@ cp_type_quals (type)
      tree type;
 {
   type = strip_array_types (type);
+  if (type == error_mark_node)
+    return TYPE_UNQUALIFIED;
   return TYPE_QUALS (type);
 }