OSDN Git Service

2004-11-15 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index 0d4f4a7..a36a631 100644 (file)
 #include "tm.h"
 #include "tree.h"
 #include "cp-tree.h"
+#include "c-common.h"
 #include "tree-inline.h"
 #include "tree-mudflap.h"
 #include "except.h"
-#include "lex.h"
 #include "toplev.h"
 #include "flags.h"
 #include "rtl.h"
@@ -45,6 +45,8 @@
 #include "diagnostic.h"
 #include "cgraph.h"
 #include "tree-iterator.h"
+#include "vec.h"
+#include "target.h"
 
 /* There routines provide a modular interface to perform many parsing
    operations.  They may therefore be used during actual parsing, or
@@ -112,9 +114,36 @@ static tree finalize_nrv_r (tree *, int *, void *);
       In case of parsing error, we simply call `pop_deferring_access_checks'
       without `perform_deferred_access_checks'.  */
 
+typedef struct deferred_access GTY(())
+{
+  /* A TREE_LIST representing name-lookups for which we have deferred
+     checking access controls.  We cannot check the accessibility of
+     names used in a decl-specifier-seq until we know what is being
+     declared because code like:
+
+       class A { 
+         class B {};
+         B* f();
+       }
+
+       A::B* A::f() { return 0; }
+
+     is valid, even though `A::B' is not generally accessible.  
+
+     The TREE_PURPOSE of each node is the scope used to qualify the
+     name being looked up; the TREE_VALUE is the DECL to which the
+     name was resolved.  */
+  tree deferred_access_checks;
+  
+  /* The current mode of access checks.  */
+  enum deferring_kind deferring_access_checks_kind;
+  
+} deferred_access;
+DEF_VEC_GC_O (deferred_access);
+
 /* Data for deferred access checking.  */
-static GTY(()) deferred_access *deferred_access_stack;
-static GTY(()) deferred_access *deferred_access_free_list;
+static GTY(()) VEC (deferred_access) *deferred_access_stack;
+static GTY(()) unsigned deferred_access_no_check;
 
 /* Save the current deferred access states and start deferred
    access checking iff DEFER_P is true.  */
@@ -122,27 +151,18 @@ static GTY(()) deferred_access *deferred_access_free_list;
 void
 push_deferring_access_checks (deferring_kind deferring)
 {
-  deferred_access *d;
-
   /* For context like template instantiation, access checking
      disabling applies to all nested context.  */
-  if (deferred_access_stack
-      && deferred_access_stack->deferring_access_checks_kind == dk_no_check)
-    deferring = dk_no_check;
-
-  /* Recycle previously used free store if available.  */
-  if (deferred_access_free_list)
-    {
-      d = deferred_access_free_list;
-      deferred_access_free_list = d->next;
-    }
+  if (deferred_access_no_check || deferring == dk_no_check)
+    deferred_access_no_check++;
   else
-    d = ggc_alloc (sizeof (deferred_access));
+    {
+      deferred_access *ptr;
 
-  d->next = deferred_access_stack;
-  d->deferred_access_checks = NULL_TREE;
-  d->deferring_access_checks_kind = deferring;
-  deferred_access_stack = d;
+      ptr = VEC_safe_push (deferred_access, deferred_access_stack, NULL);
+      ptr->deferred_access_checks = NULL_TREE;
+      ptr->deferring_access_checks_kind = deferring;
+    }
 }
 
 /* Resume deferring access checks again after we stopped doing
@@ -151,8 +171,9 @@ push_deferring_access_checks (deferring_kind deferring)
 void
 resume_deferring_access_checks (void)
 {
-  if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred)
-    deferred_access_stack->deferring_access_checks_kind = dk_deferred;
+  if (!deferred_access_no_check)
+    VEC_last (deferred_access, deferred_access_stack)
+      ->deferring_access_checks_kind = dk_deferred;
 }
 
 /* Stop deferring access checks.  */
@@ -160,8 +181,9 @@ resume_deferring_access_checks (void)
 void
 stop_deferring_access_checks (void)
 {
-  if (deferred_access_stack->deferring_access_checks_kind == dk_deferred)
-    deferred_access_stack->deferring_access_checks_kind = dk_no_deferred;
+  if (!deferred_access_no_check)
+    VEC_last (deferred_access, deferred_access_stack)
+      ->deferring_access_checks_kind = dk_no_deferred;
 }
 
 /* Discard the current deferred access checks and restore the
@@ -170,15 +192,10 @@ stop_deferring_access_checks (void)
 void
 pop_deferring_access_checks (void)
 {
-  deferred_access *d = deferred_access_stack;
-  deferred_access_stack = d->next;
-
-  /* Remove references to access checks TREE_LIST.  */
-  d->deferred_access_checks = NULL_TREE;
-
-  /* Store in free list for later use.  */
-  d->next = deferred_access_free_list;
-  deferred_access_free_list = d;
+  if (deferred_access_no_check)
+    deferred_access_no_check--;
+  else
+    VEC_pop (deferred_access, deferred_access_stack);
 }
 
 /* Returns a TREE_LIST representing the deferred checks.  
@@ -189,7 +206,11 @@ pop_deferring_access_checks (void)
 tree
 get_deferred_access_checks (void)
 {
-  return deferred_access_stack->deferred_access_checks;
+  if (deferred_access_no_check)
+    return NULL;
+  else
+    return (VEC_last (deferred_access, deferred_access_stack)
+           ->deferred_access_checks);
 }
 
 /* Take current deferred checks and combine with the
@@ -199,27 +220,48 @@ get_deferred_access_checks (void)
 void
 pop_to_parent_deferring_access_checks (void)
 {
-  tree deferred_check = get_deferred_access_checks ();
-  deferred_access *d1 = deferred_access_stack;
-  deferred_access *d2 = deferred_access_stack->next;
-  deferred_access *d3 = deferred_access_stack->next->next;
-
-  /* Temporary swap the order of the top two states, just to make
-     sure the garbage collector will not reclaim the memory during 
-     processing below.  */
-  deferred_access_stack = d2;
-  d2->next = d1;
-  d1->next = d3;
+  if (deferred_access_no_check)
+    deferred_access_no_check--;
+  else
+    {
+      tree checks;
+      deferred_access *ptr;
 
-  for ( ; deferred_check; deferred_check = TREE_CHAIN (deferred_check))
-    /* Perform deferred check if required.  */
-    perform_or_defer_access_check (TREE_PURPOSE (deferred_check), 
-                                  TREE_VALUE (deferred_check));
+      checks = (VEC_last (deferred_access, deferred_access_stack)
+               ->deferred_access_checks);
 
-  deferred_access_stack = d1;
-  d1->next = d2;
-  d2->next = d3;
-  pop_deferring_access_checks ();
+      VEC_pop (deferred_access, deferred_access_stack);
+      ptr = VEC_last (deferred_access, deferred_access_stack);
+      if (ptr->deferring_access_checks_kind == dk_no_deferred)
+       {
+         /* Check access.  */
+         for (; checks; checks = TREE_CHAIN (checks)) 
+           enforce_access (TREE_PURPOSE (checks), 
+                           TREE_VALUE (checks));
+       }
+      else
+       {
+         /* Merge with parent.  */
+         tree next;
+         tree original = ptr->deferred_access_checks;
+         
+         for (; checks; checks = next)
+           {
+             tree probe;
+             
+             next = TREE_CHAIN (checks);
+
+             for (probe = original; probe; probe = TREE_CHAIN (probe))
+               if (TREE_VALUE (probe) == TREE_VALUE (checks)
+                   && TREE_PURPOSE (probe) == TREE_PURPOSE (checks))
+                 goto found;
+             /* Insert into parent's checks.  */
+             TREE_CHAIN (checks) = ptr->deferred_access_checks;
+             ptr->deferred_access_checks = checks;
+           found:;
+           }
+       }
+    }
 }
 
 /* Perform the deferred access checks.
@@ -242,7 +284,9 @@ void
 perform_deferred_access_checks (void)
 {
   tree deferred_check;
-  for (deferred_check = deferred_access_stack->deferred_access_checks;
+
+  for (deferred_check = (VEC_last (deferred_access, deferred_access_stack)
+                        ->deferred_access_checks);
        deferred_check;
        deferred_check = TREE_CHAIN (deferred_check))
     /* Check access.  */
@@ -257,29 +301,33 @@ void
 perform_or_defer_access_check (tree binfo, tree decl)
 {
   tree check;
+  deferred_access *ptr;
+
+  /* Exit if we are in a context that no access checking is performed.
+     */
+  if (deferred_access_no_check)
+    return;
+  
+  gcc_assert (TREE_CODE (binfo) == TREE_BINFO);
 
-  my_friendly_assert (TREE_CODE (binfo) == TREE_VEC, 20030623);
+  ptr = VEC_last (deferred_access, deferred_access_stack);
   
   /* If we are not supposed to defer access checks, just check now.  */
-  if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred)
+  if (ptr->deferring_access_checks_kind == dk_no_deferred)
     {
       enforce_access (binfo, decl);
       return;
     }
-  /* Exit if we are in a context that no access checking is performed.  */
-  else if (deferred_access_stack->deferring_access_checks_kind == dk_no_check)
-    return;
-
+  
   /* See if we are already going to perform this check.  */
-  for (check = deferred_access_stack->deferred_access_checks;
+  for (check = ptr->deferred_access_checks;
        check;
        check = TREE_CHAIN (check))
     if (TREE_VALUE (check) == decl && TREE_PURPOSE (check) == binfo)
       return;
   /* If not, record the check.  */
-  deferred_access_stack->deferred_access_checks
-    = tree_cons (binfo, decl,
-                deferred_access_stack->deferred_access_checks);
+  ptr->deferred_access_checks
+    = tree_cons (binfo, decl, ptr->deferred_access_checks);
 }
 
 /* Returns nonzero if the current statement is a full expression,
@@ -310,18 +358,34 @@ static tree
 maybe_cleanup_point_expr (tree expr)
 {
   if (!processing_template_decl && stmts_are_full_exprs_p ())
-    expr = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (expr), expr));
+    expr = fold_build_cleanup_point_expr (TREE_TYPE (expr), expr);
   return expr;
 }
 
+/* Like maybe_cleanup_point_expr except have the type of the new expression be
+   void so we don't need to create a temporary variable to hold the inner
+   expression.  The reason why we do this is because the original type might be
+   an aggregate and we cannot create a temporary variable for that type.  */
+
+static tree
+maybe_cleanup_point_expr_void (tree expr)
+{
+  if (!processing_template_decl && stmts_are_full_exprs_p ())
+    expr = fold_build_cleanup_point_expr (void_type_node, expr);
+  return expr;
+}
+
+
+
 /* Create a declaration statement for the declaration given by the DECL.  */
 
 void
-add_decl_stmt (tree decl)
+add_decl_expr (tree decl)
 {
-  tree r = build_stmt (DECL_STMT, decl);
-  if (DECL_INITIAL (decl))
-    r = maybe_cleanup_point_expr (r);
+  tree r = build_stmt (DECL_EXPR, decl);
+  if (DECL_INITIAL (decl)
+      || (DECL_SIZE (decl) && TREE_SIDE_EFFECTS (DECL_SIZE (decl))))
+    r = maybe_cleanup_point_expr_void (r);
   add_stmt (r);
 }
 
@@ -337,7 +401,7 @@ anon_aggr_type_p (tree node)
 
 /* Finish a scope.  */
 
-static tree
+tree
 do_poplevel (tree stmt_list)
 {
   tree block = NULL;
@@ -383,7 +447,7 @@ push_cleanup (tree decl, tree cleanup, bool eh_only)
 /* Begin a conditional that might contain a declaration.  When generating
    normal code, we want the declaration to appear before the statement
    containing the conditional.  When generating template code, we want the
-   conditional to be rendered as the raw DECL_STMT.  */
+   conditional to be rendered as the raw DECL_EXPR.  */
 
 static void
 begin_cond (tree *cond_p)
@@ -400,7 +464,7 @@ finish_cond (tree *cond_p, tree expr)
   if (processing_template_decl)
     {
       tree cond = pop_stmt_list (*cond_p);
-      if (TREE_CODE (cond) == DECL_STMT)
+      if (TREE_CODE (cond) == DECL_EXPR)
        expr = cond;
     }
   *cond_p = expr;
@@ -502,12 +566,12 @@ finish_expr_stmt (tree expr)
        convert_to_void (build_non_dependent_expr (expr), "statement");
 
       /* Simplification of inner statement expressions, compound exprs,
-        etc can result in the us already having an EXPR_STMT.  */
+        etc can result in us already having an EXPR_STMT.  */
       if (TREE_CODE (expr) != CLEANUP_POINT_EXPR)
        {
          if (TREE_CODE (expr) != EXPR_STMT)
            expr = build_stmt (EXPR_STMT, expr);
-         expr = maybe_cleanup_point_expr (expr);
+         expr = maybe_cleanup_point_expr_void (expr);
        }
 
       r = add_stmt (expr);
@@ -657,18 +721,20 @@ finish_return_stmt (tree expr)
   expr = check_return_expr (expr);
   if (!processing_template_decl)
     {
-      if (DECL_DESTRUCTOR_P (current_function_decl))
+      if (DECL_DESTRUCTOR_P (current_function_decl)
+         || (DECL_CONSTRUCTOR_P (current_function_decl) 
+             && targetm.cxx.cdtor_returns_this ()))
        {
          /* Similarly, all destructors must run destructors for
             base-classes before returning.  So, all returns in a
             destructor get sent to the DTOR_LABEL; finish_function emits
             code to return a value there.  */
-         return finish_goto_stmt (dtor_label);
+         return finish_goto_stmt (cdtor_label);
        }
     }
 
   r = build_stmt (RETURN_EXPR, expr);
-  r = maybe_cleanup_point_expr (r);
+  r = maybe_cleanup_point_expr_void (r);
   r = add_stmt (r);
   finish_stmt ();
 
@@ -732,7 +798,15 @@ finish_for_expr (tree expr, tree for_stmt)
       cxx_incomplete_type_error (expr, TREE_TYPE (expr));
       expr = error_mark_node;
     }
-  expr = maybe_cleanup_point_expr (expr);
+  if (!processing_template_decl)
+    {
+      if (warn_sequence_point)
+        verify_sequence_points (expr);
+      expr = convert_to_void (expr, "3rd expression in for");
+    }
+  else if (!type_dependent_expression_p (expr))
+    convert_to_void (build_non_dependent_expr (expr), "3rd expression in for");
+  expr = maybe_cleanup_point_expr_void (expr);
   FOR_EXPR (for_stmt) = expr;
 }
 
@@ -987,7 +1061,7 @@ finish_handler (tree handler)
 }
 
 /* Begin a compound statement.  FLAGS contains some bits that control the
-   behaviour and context.  If BCS_NO_SCOPE is set, the compound statement
+   behavior and context.  If BCS_NO_SCOPE is set, the compound statement
    does not define a scope.  If BCS_FN_BODY is set, this is the outermost
    block of a function.  If BCS_TRY_BLOCK is set, this is the block 
    created on behalf of a TRY statement.  Returns a token to be passed to
@@ -1020,7 +1094,7 @@ begin_compound_stmt (unsigned int flags)
      processing templates.  */
   if (processing_template_decl)
     {
-      r = build (BIND_EXPR, NULL, NULL, r, NULL);
+      r = build3 (BIND_EXPR, NULL, NULL, r, NULL);
       BIND_EXPR_TRY_BLOCK (r) = (flags & BCS_TRY_BLOCK) != 0;
       BIND_EXPR_BODY_BLOCK (r) = (flags & BCS_FN_BODY) != 0;
       TREE_SIDE_EFFECTS (r) = 1;
@@ -1039,7 +1113,13 @@ finish_compound_stmt (tree stmt)
   else if (STATEMENT_LIST_NO_SCOPE (stmt))
     stmt = pop_stmt_list (stmt);
   else
-    stmt = do_poplevel (stmt);
+    {
+      /* Destroy any ObjC "super" receivers that may have been
+        created.  */
+      objc_clear_super_receiver ();
+
+      stmt = do_poplevel (stmt);
+    }
 
   /* ??? See c_end_compound_stmt wrt statement expressions.  */
   add_stmt (stmt);
@@ -1074,8 +1154,8 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
             resolve the overloading.  */
          if (TREE_TYPE (converted_operand) == unknown_type_node)
            {
-             error ("type of asm operand `%E' could not be determined", 
-                       TREE_VALUE (t));
+             error ("type of asm operand %qE could not be determined", 
+                     TREE_VALUE (t));
              converted_operand = error_mark_node;
            }
          TREE_VALUE (t) = converted_operand;
@@ -1122,6 +1202,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
                  output_operands, input_operands,
                  clobbers);
   ASM_VOLATILE_P (r) = volatile_p;
+  r = maybe_cleanup_point_expr_void (r);
   return add_stmt (r);
 }
 
@@ -1142,7 +1223,7 @@ void
 finish_label_decl (tree name)
 {
   tree decl = declare_local_label (name);
-  add_decl_stmt (decl);
+  add_decl_expr (decl);
 }
 
 /* When DECL goes out of scope, make sure that CLEANUP is executed.  */
@@ -1183,9 +1264,9 @@ finish_mem_initializers (tree mem_inits)
 tree
 finish_parenthesized_expr (tree expr)
 {
-  if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expr))))
+  if (EXPR_P (expr))
     /* This inhibits warnings in c_common_truthvalue_conversion.  */
-    C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK); 
+    TREE_NO_WARNING (expr) = 1;
 
   if (TREE_CODE (expr) == OFFSET_REF)
     /* [expr.unary.op]/3 The qualified id of a pointer-to-member must not be
@@ -1200,16 +1281,16 @@ finish_parenthesized_expr (tree expr)
 tree
 finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
 {
-  my_friendly_assert (TREE_CODE (decl) == FIELD_DECL, 20020909);
+  gcc_assert (TREE_CODE (decl) == FIELD_DECL);
 
   if (!object)
     {
       if (current_function_decl 
          && DECL_STATIC_FUNCTION_P (current_function_decl))
-       cp_error_at ("invalid use of member `%D' in static member function",
+       cp_error_at ("invalid use of member %qD in static member function",
                     decl);
       else
-       cp_error_at ("invalid use of non-static data member `%D'", decl);
+       cp_error_at ("invalid use of non-static data member %qD", decl);
       error ("from this location");
 
       return error_mark_node;
@@ -1248,7 +1329,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
 
          if (!access_type)
            {
-             cp_error_at ("object missing in reference to `%D'", decl);
+             cp_error_at ("object missing in reference to %qD", decl);
              error ("from this location");
              return error_mark_node;
            }
@@ -1291,6 +1372,10 @@ check_accessibility_of_qualified_id (tree decl,
 {
   tree scope;
   tree qualifying_type = NULL_TREE;
+
+  /* If we're not checking, return immediately.  */
+  if (deferred_access_no_check)
+    return;
   
   /* Determine the SCOPE of DECL.  */
   scope = context_for_name_lookup (decl);
@@ -1331,7 +1416,9 @@ check_accessibility_of_qualified_id (tree decl,
        its bases.  */
     qualifying_type = currently_open_derived_class (scope);
 
-  if (qualifying_type)
+  if (qualifying_type && IS_AGGR_TYPE_CODE (TREE_CODE (qualifying_type)))
+    /* It is possible for qualifying type to be a TEMPLATE_TYPE_PARM
+       or similar in a default argument value.  */
     perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl);
 }
 
@@ -1364,19 +1451,16 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
                                          qualifying_class);
   else if (BASELINK_P (expr) && !processing_template_decl)
     {
-      tree fn;
       tree fns;
 
       /* See if any of the functions are non-static members.  */
       fns = BASELINK_FUNCTIONS (expr);
       if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
        fns = TREE_OPERAND (fns, 0);
-      for (fn = fns; fn; fn = OVL_NEXT (fn))
-       if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
-         break;
       /* If so, the expression may be relative to the current
         class.  */
-      if (fn && current_class_type 
+      if (!shared_member_p (fns)
+         && current_class_type 
          && DERIVED_FROM_P (qualifying_class, current_class_type))
        expr = (build_class_member_access_expr 
                (maybe_dummy_object (qualifying_class, NULL),
@@ -1440,9 +1524,9 @@ finish_stmt_expr_expr (tree expr, tree stmt_expr)
              expr = build_special_member_call
                (NULL_TREE, complete_ctor_identifier,
                 build_tree_list (NULL_TREE, expr),
-                TYPE_BINFO (type), LOOKUP_NORMAL);
+                type, LOOKUP_NORMAL);
              expr = build_cplus_new (type, expr);
-             my_friendly_assert (TREE_CODE (expr) == TARGET_EXPR, 20030729);
+             gcc_assert (TREE_CODE (expr) == TARGET_EXPR);
            }
        }
 
@@ -1508,7 +1592,7 @@ finish_stmt_expr (tree stmt_expr, bool has_no_scope)
              result_stmt_p = &TREE_OPERAND (t, 0);
              break;
            default:
-             abort ();
+             gcc_unreachable ();
            }
        }
       type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt));
@@ -1527,7 +1611,7 @@ finish_stmt_expr (tree stmt_expr, bool has_no_scope)
         the statement expression itself as the target's init
         expr. Finally, return the target expression.  */
       tree init, target_expr = EXPR_STMT_EXPR (result_stmt);
-      my_friendly_assert (TREE_CODE (target_expr) == TARGET_EXPR, 20030729);
+      gcc_assert (TREE_CODE (target_expr) == TARGET_EXPR);
 
       /* The initializer will be void if the initialization is done by
         AGGR_INIT_EXPR; propagate that out to the statement-expression as
@@ -1546,10 +1630,8 @@ finish_stmt_expr (tree stmt_expr, bool has_no_scope)
             returning a value directly, give it the appropriate type.  */
          if (VOID_TYPE_P (TREE_TYPE (result)))
            TREE_TYPE (result) = type;
-         else if (same_type_p (TREE_TYPE (result), type))
-           ;
          else
-           abort ();
+           gcc_assert (same_type_p (TREE_TYPE (result), type));
        }
       else if (TREE_CODE (result) == STATEMENT_LIST)
        /* We need to wrap a STATEMENT_LIST in a BIND_EXPR so it can have a
@@ -1627,8 +1709,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
     return error_mark_node;
 
   /* ARGS should be a list of arguments.  */
-  my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
-                     20020712);
+  gcc_assert (!args || TREE_CODE (args) == TREE_LIST);
 
   orig_fn = fn;
   orig_args = args;
@@ -1746,8 +1827,8 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
 
   if (processing_template_decl)
     {
-      result = build (CALL_EXPR, TREE_TYPE (result), orig_fn,
-                     orig_args, NULL_TREE);
+      result = build3 (CALL_EXPR, TREE_TYPE (result), orig_fn,
+                      orig_args, NULL_TREE);
       KOENIG_LOOKUP_P (result) = koenig_p;
     }
   return result;
@@ -1777,15 +1858,15 @@ finish_this_expr (void)
   else if (current_function_decl
           && DECL_STATIC_FUNCTION_P (current_function_decl))
     {
-      error ("`this' is unavailable for static member functions");
+      error ("%<this%> is unavailable for static member functions");
       result = error_mark_node;
     }
   else
     {
       if (current_function_decl)
-       error ("invalid use of `this' in non-member function");
+       error ("invalid use of %<this%> in non-member function");
       else
-       error ("invalid use of `this' at top level");
+       error ("invalid use of %<this%> at top level");
       result = error_mark_node;
     }
 
@@ -1803,7 +1884,7 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
   if (destructor == error_mark_node)
     return error_mark_node;
 
-  my_friendly_assert (TYPE_P (destructor), 20010905);
+  gcc_assert (TYPE_P (destructor));
 
   if (!processing_template_decl)
     {
@@ -1829,12 +1910,12 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
       if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object), 
                                                      destructor))
        {
-         error ("`%E' is not of type `%T'", object, destructor);
+         error ("%qE is not of type %qT", object, destructor);
          return error_mark_node;
        }
     }
 
-  return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope, destructor);
+  return build3 (PSEUDO_DTOR_EXPR, void_type_node, object, scope, destructor);
 }
 
 /* Finish an expression of the form CODE EXPR.  */
@@ -1923,7 +2004,7 @@ finish_template_type_parm (tree aggr, tree identifier)
 {
   if (aggr != class_type_node)
     {
-      pedwarn ("template type parameters must use the keyword `class' or `typename'");
+      pedwarn ("template type parameters must use the keyword %<class%> or %<typename%>");
       aggr = class_type_node;
     }
 
@@ -1943,7 +2024,7 @@ finish_template_template_parm (tree aggr, tree identifier)
   DECL_ARTIFICIAL (decl) = 1;
   end_template_decl ();
 
-  my_friendly_assert (DECL_TEMPLATE_PARMS (tmpl), 20010110);
+  gcc_assert (DECL_TEMPLATE_PARMS (tmpl));
 
   return finish_template_type_parm (aggr, tmpl);
 }
@@ -1967,10 +2048,10 @@ check_template_template_default_arg (tree argument)
             that the user is using a template instantiation.  */
          if (CLASSTYPE_TEMPLATE_INFO (t) 
              && CLASSTYPE_TEMPLATE_INSTANTIATION (t))
-           error ("invalid use of type `%T' as a default value for a "
+           error ("invalid use of type %qT as a default value for a "
                   "template template-parameter", t);
          else
-           error ("invalid use of `%D' as a default value for a template "
+           error ("invalid use of %qD as a default value for a template "
                   "template-parameter", argument);
        }
       else
@@ -1991,7 +2072,7 @@ begin_class_definition (tree t)
 
   if (processing_template_parmlist)
     {
-      error ("definition of `%#T' inside template parameter list", t);
+      error ("definition of %q#T inside template parameter list", t);
       return error_mark_node;
     }
   /* A non-implicit typename comes from code like:
@@ -2002,7 +2083,7 @@ begin_class_definition (tree t)
      This is erroneous.  */
   else if (TREE_CODE (t) == TYPENAME_TYPE)
     {
-      error ("invalid definition of qualified type `%T'", t);
+      error ("invalid definition of qualified type %qT", t);
       t = error_mark_node;
     }
 
@@ -2016,8 +2097,8 @@ begin_class_definition (tree t)
      that's an error.  */
   if (COMPLETE_TYPE_P (t))
     {
-      error ("redefinition of `%#T'", t);
-      cp_error_at ("previous definition of `%#T'", t);
+      error ("redefinition of %q#T", t);
+      cp_error_at ("previous definition of %q#T", t);
       return error_mark_node;
     }
 
@@ -2047,9 +2128,10 @@ begin_class_definition (tree t)
      before.  */
   if (! TYPE_ANONYMOUS_P (t))
     {
-      CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
+      struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename));
+      CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only;
       SET_CLASSTYPE_INTERFACE_UNKNOWN_X
-       (t, interface_unknown);
+       (t, finfo->interface_unknown);
     }
   reset_specialization();
   
@@ -2073,7 +2155,7 @@ finish_member_declaration (tree decl)
     return;
 
   /* We should see only one DECL at a time.  */
-  my_friendly_assert (TREE_CHAIN (decl) == NULL_TREE, 0);
+  gcc_assert (TREE_CHAIN (decl) == NULL_TREE);
 
   /* Set up access control for DECL.  */
   TREE_PRIVATE (decl) 
@@ -2104,7 +2186,7 @@ finish_member_declaration (tree decl)
     {
       /* We also need to add this function to the
         CLASSTYPE_METHOD_VEC.  */
-      add_method (current_class_type, decl, /*error_p=*/0);
+      add_method (current_class_type, decl);
 
       TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
       TYPE_METHODS (current_class_type) = decl;
@@ -2147,36 +2229,6 @@ finish_member_declaration (tree decl)
     }
 }
 
-/* Finish processing the declaration of a member class template
-   TYPES whose template parameters are given by PARMS.  */
-
-tree
-finish_member_class_template (tree types)
-{
-  tree t;
-
-  /* If there are declared, but undefined, partial specializations
-     mixed in with the typespecs they will not yet have passed through
-     maybe_process_partial_specialization, so we do that here.  */
-  for (t = types; t != NULL_TREE; t = TREE_CHAIN (t))
-    if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_VALUE (t))))
-      maybe_process_partial_specialization (TREE_VALUE (t));
-
-  grok_x_components (types);
-  if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
-    /* The component was in fact a friend declaration.  We avoid
-       finish_member_template_decl performing certain checks by
-       unsetting TYPES.  */
-    types = NULL_TREE;
-  
-  finish_member_template_decl (types);
-
-  /* As with other component type declarations, we do
-     not store the new DECL on the list of
-     component_decls.  */
-  return NULL_TREE;
-}
-
 /* Finish processing a complete template declaration.  The PARMS are
    the template parameters.  */
 
@@ -2212,7 +2264,8 @@ finish_template_type (tree name, tree args, int entering_scope)
    Return a TREE_LIST containing the ACCESS_SPECIFIER and the
    BASE_CLASS, or NULL_TREE if an error occurred.  The
    ACCESS_SPECIFIER is one of
-   access_{default,public,protected_private}[_virtual]_node.*/
+   access_{default,public,protected_private}_node.  For a virtual base
+   we set TREE_TYPE.  */
 
 tree 
 finish_base_specifier (tree base, tree access, bool virtual_p)
@@ -2230,11 +2283,12 @@ finish_base_specifier (tree base, tree access, bool virtual_p)
     {
       if (cp_type_quals (base) != 0)
         {
-          error ("base class `%T' has cv qualifiers", base);
+          error ("base class %qT has cv qualifiers", base);
           base = TYPE_MAIN_VARIANT (base);
         }
       result = build_tree_list (access, base);
-      TREE_VIA_VIRTUAL (result) = virtual_p;
+      if (virtual_p)
+       TREE_TYPE (result) = integer_type_node;
     }
 
   return result;
@@ -2265,22 +2319,28 @@ check_multiple_declarators (void)
     error ("multiple declarators in template declaration");
 }
 
-/* Issue a diagnostic that NAME cannot be found in SCOPE.  */
+/* Issue a diagnostic that NAME cannot be found in SCOPE.  DECL is
+   what we found when we tried to do the lookup.  */
 
 void
-qualified_name_lookup_error (tree scope, tree name)
+qualified_name_lookup_error (tree scope, tree name, tree decl)
 {
   if (TYPE_P (scope))
     {
       if (!COMPLETE_TYPE_P (scope))
-       error ("incomplete type `%T' used in nested name specifier", scope);
+       error ("incomplete type %qT used in nested name specifier", scope);
+      else if (TREE_CODE (decl) == TREE_LIST)
+       {
+         error ("reference to %<%T::%D%> is ambiguous", scope, name);
+         print_candidates (decl);
+       }
       else
-       error ("`%D' is not a member of `%T'", name, scope);
+       error ("%qD is not a member of %qT", name, scope);
     }
   else if (scope != global_namespace)
-    error ("`%D' is not a member of `%D'", name, scope);
+    error ("%qD is not a member of %qD", name, scope);
   else
-    error ("`::%D' has not been declared", name);
+    error ("%<::%D%> has not been declared", name);
 }
              
 /* ID_EXPRESSION is a representation of parsed, but unprocessed,
@@ -2349,7 +2409,7 @@ finish_id_expression (tree id_expression,
              /* If the qualifying type is non-dependent (and the name
                 does not name a conversion operator to a dependent
                 type), issue an error.  */
-             qualified_name_lookup_error (scope, id_expression);
+             qualified_name_lookup_error (scope, id_expression, decl);
              return error_mark_node;
            }
          else if (!scope)
@@ -2403,7 +2463,7 @@ finish_id_expression (tree id_expression,
          && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))) 
        {
          if (!allow_non_integral_constant_expression_p)
-           error ("template parameter `%D' of type `%T' is not allowed in "
+           error ("template parameter %qD of type %qT is not allowed in "
                   "an integral constant expression because it is not of "
                   "integral or enumeration type", decl, TREE_TYPE (decl));
          *non_integral_constant_expression_p = true;
@@ -2515,8 +2575,8 @@ finish_id_expression (tree id_expression,
              if (TYPE_P (scope) && dependent_type_p (scope))
                return build_nt (SCOPE_REF, scope, id_expression);
              else if (TYPE_P (scope) && DECL_P (decl))
-               return build (SCOPE_REF, TREE_TYPE (decl), scope,
-                             id_expression);
+               return build2 (SCOPE_REF, TREE_TYPE (decl), scope,
+                              id_expression);
              else
                return decl;
            }
@@ -2542,41 +2602,31 @@ finish_id_expression (tree id_expression,
       /* Only certain kinds of names are allowed in constant
        expression.  Enumerators and template parameters 
        have already been handled above.  */
-      if (integral_constant_expression_p)
+      if (integral_constant_expression_p
+         && !DECL_INTEGRAL_CONSTANT_VAR_P (decl))
        {
-           /* Const variables or static data members of integral or
-             enumeration types initialized with constant expressions
-             are OK.  */
-         if (TREE_CODE (decl) == VAR_DECL
-             && CP_TYPE_CONST_P (TREE_TYPE (decl))
-             && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
-             && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
-           ;
-         else
+         if (!allow_non_integral_constant_expression_p)
            {
-             if (!allow_non_integral_constant_expression_p)
-               {
-                 error ("`%D' cannot appear in a constant-expression", decl);
-                 return error_mark_node;
-               }
-             *non_integral_constant_expression_p = true;
+             error ("%qD cannot appear in a constant-expression", decl);
+             return error_mark_node;
            }
+         *non_integral_constant_expression_p = true;
        }
       
       if (TREE_CODE (decl) == NAMESPACE_DECL)
        {
-         error ("use of namespace `%D' as expression", decl);
+         error ("use of namespace %qD as expression", decl);
          return error_mark_node;
        }
       else if (DECL_CLASS_TEMPLATE_P (decl))
        {
-         error ("use of class template `%T' as expression", decl);
+         error ("use of class template %qT as expression", decl);
          return error_mark_node;
        }
       else if (TREE_CODE (decl) == TREE_LIST)
        {
          /* Ambiguous reference to base members.  */
-         error ("request for member `%D' is ambiguous in "
+         error ("request for member %qD is ambiguous in "
                 "multiple inheritance lattice", id_expression);
          print_candidates (decl);
          return error_mark_node;
@@ -2602,7 +2652,7 @@ finish_id_expression (tree id_expression,
          else if (!processing_template_decl)
            decl = convert_from_reference (decl);
          else if (TYPE_P (scope))
-           decl = build (SCOPE_REF, TREE_TYPE (decl), scope, decl);
+           decl = build2 (SCOPE_REF, TREE_TYPE (decl), scope, decl);
        }
       else if (TREE_CODE (decl) == FIELD_DECL)
        decl = finish_non_static_data_member (decl, current_class_ref,
@@ -2618,7 +2668,8 @@ finish_id_expression (tree id_expression,
            mark_used (first_fn);
 
          if (TREE_CODE (first_fn) == FUNCTION_DECL
-             && DECL_FUNCTION_MEMBER_P (first_fn))
+             && DECL_FUNCTION_MEMBER_P (first_fn)
+             && !shared_member_p (decl))
            {
              /* A set of member functions.  */
              decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0);
@@ -2638,8 +2689,8 @@ finish_id_expression (tree id_expression,
                {
                  error ("use of %s from containing function",
                         (TREE_CODE (decl) == VAR_DECL
-                         ? "`auto' variable" : "parameter"));
-                 cp_error_at ("  `%#D' declared here", decl);
+                         ? "%<auto%> variable" : "parameter"));
+                 cp_error_at ("  %q#D declared here", decl);
                  return error_mark_node;
                }
            }
@@ -2690,7 +2741,7 @@ finish_typeof (tree expr)
 
   if (!type || type == unknown_type_node)
     {
-      error ("type of `%E' is unknown", expr);
+      error ("type of %qE is unknown", expr);
       return error_mark_node;
     }
 
@@ -2749,12 +2800,11 @@ simplify_aggr_init_expr (tree *tp)
   else if (1)
     style = pcc;
 #endif
-  else if (TREE_ADDRESSABLE (type))
-    style = arg;
   else
-    /* We shouldn't build an AGGR_INIT_EXPR if we don't need any special
-       handling.  See build_cplus_new.  */
-    abort ();
+    {
+      gcc_assert (TREE_ADDRESSABLE (type));
+      style = arg;
+    }
 
   if (style == ctor || style == arg)
     {
@@ -2771,20 +2821,18 @@ simplify_aggr_init_expr (tree *tp)
        {
          /* The return type might have different cv-quals from the slot.  */
          tree fntype = TREE_TYPE (TREE_TYPE (fn));
-#ifdef ENABLE_CHECKING
-         if (TREE_CODE (fntype) != FUNCTION_TYPE
-             && TREE_CODE (fntype) != METHOD_TYPE)
-           abort ();
-#endif
+         
+         gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE
+                     || TREE_CODE (fntype) == METHOD_TYPE);
          addr = convert (build_pointer_type (TREE_TYPE (fntype)), addr);
        }
 
       args = tree_cons (NULL_TREE, addr, args);
     }
 
-  call_expr = build (CALL_EXPR, 
-                    TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
-                    fn, args, NULL_TREE);
+  call_expr = build3 (CALL_EXPR, 
+                     TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
+                     fn, args, NULL_TREE);
 
   if (style == arg)
     /* Tell the backend that we've added our return slot to the argument
@@ -2833,7 +2881,7 @@ emit_associated_thunks (tree fn)
                }
            }
          else
-           my_friendly_assert (!DECL_THUNKS (thunk), 20031023);
+           gcc_assert (!DECL_THUNKS (thunk));
        }
     }
 }
@@ -2864,23 +2912,14 @@ expand_body (tree fn)
   /* Emit any thunks that should be emitted at the same time as FN.  */
   emit_associated_thunks (fn);
 
-  tree_rest_of_compilation (fn, function_depth > 1);
-
-  current_function_decl = saved_function;
-
-  extract_interface_info ();
+  /* This function is only called from cgraph, or recursively from
+     emit_associated_thunks.  In neither case should we be currently
+     generating trees for a function.  */
+  gcc_assert (function_depth == 0);
 
-  /* If this function is marked with the constructor attribute, add it
-     to the list of functions to be called along with constructors
-     from static duration objects.  */
-  if (DECL_STATIC_CONSTRUCTOR (fn))
-    static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
+  tree_rest_of_compilation (fn);
 
-  /* If this function is marked with the destructor attribute, add it
-     to the list of functions to be called along with destructors from
-     static duration objects.  */
-  if (DECL_STATIC_DESTRUCTOR (fn))
-    static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
+  current_function_decl = saved_function;
 
   if (DECL_CLONED_FUNCTION_P (fn))
     {
@@ -2935,15 +2974,45 @@ expand_or_defer_fn (tree fn)
       return;
     }
 
+  /* If this function is marked with the constructor attribute, add it
+     to the list of functions to be called along with constructors
+     from static duration objects.  */
+  if (DECL_STATIC_CONSTRUCTOR (fn))
+    static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
+
+  /* If this function is marked with the destructor attribute, add it
+     to the list of functions to be called along with destructors from
+     static duration objects.  */
+  if (DECL_STATIC_DESTRUCTOR (fn))
+    static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
+
+  /* We make a decision about linkage for these functions at the end
+     of the compilation.  Until that point, we do not want the back
+     end to output them -- but we do want it to see the bodies of
+     these functions so that it can inline them as appropriate.  */
+  if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn))
+    {
+      if (!at_eof)
+       {
+         DECL_EXTERNAL (fn) = 1;
+         DECL_NOT_REALLY_EXTERN (fn) = 1;
+         note_vague_linkage_fn (fn);
+       }
+      else
+       import_export_decl (fn);
+
+      /* If the user wants us to keep all inline functions, then mark
+        this function as needed so that finish_file will make sure to
+        output it later.  */
+      if (flag_keep_inline_functions && DECL_DECLARED_INLINE_P (fn))
+       mark_needed (fn);
+    }
+
   /* There's no reason to do any of the work here if we're only doing
      semantic analysis; this code just generates RTL.  */
   if (flag_syntax_only)
     return;
 
-  /* Compute the appropriate object-file linkage for inline functions.  */
-  if (DECL_DECLARED_INLINE_P (fn))
-    import_export_decl (fn);
-
   function_depth++;
 
   /* Expand or defer, at the whim of the compilation unit manager.  */
@@ -2981,17 +3050,17 @@ finalize_nrv_r (tree* tp, int* walk_subtrees, void* data)
   else if (TREE_CODE (*tp) == CLEANUP_STMT
           && CLEANUP_DECL (*tp) == dp->var)
     CLEANUP_EH_ONLY (*tp) = 1;
-  /* Replace the DECL_STMT for the NRV with an initialization of the
+  /* Replace the DECL_EXPR for the NRV with an initialization of the
      RESULT_DECL, if needed.  */
-  else if (TREE_CODE (*tp) == DECL_STMT
-          && DECL_STMT_DECL (*tp) == dp->var)
+  else if (TREE_CODE (*tp) == DECL_EXPR
+          && DECL_EXPR_DECL (*tp) == dp->var)
     {
       tree init;
       if (DECL_INITIAL (dp->var)
          && DECL_INITIAL (dp->var) != error_mark_node)
        {
-         init = build (INIT_EXPR, void_type_node, dp->result,
-                       DECL_INITIAL (dp->var));
+         init = build2 (INIT_EXPR, void_type_node, dp->result,
+                        DECL_INITIAL (dp->var));
          DECL_INITIAL (dp->var) = error_mark_node;
        }
       else
@@ -3028,6 +3097,8 @@ finalize_nrv (tree *tp, tree var, tree result)
 
   /* Copy debugging information from VAR to RESULT.  */
   DECL_NAME (result) = DECL_NAME (var);
+  DECL_ARTIFICIAL (result) = DECL_ARTIFICIAL (var);
+  DECL_IGNORED_P (result) = DECL_IGNORED_P (var);
   DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (var);
   DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (var);
   /* Don't forget that we take its address.  */