OSDN Git Service

2002-08-24 Matt Austern <austern@apple.com>
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index f17019c..2737bbe 100644 (file)
@@ -56,8 +56,6 @@ static void emit_associated_thunks PARAMS ((tree));
 static void genrtl_try_block PARAMS ((tree));
 static void genrtl_eh_spec_block PARAMS ((tree));
 static void genrtl_handler PARAMS ((tree));
-static void genrtl_ctor_stmt PARAMS ((tree));
-static void genrtl_subobject PARAMS ((tree));
 static void genrtl_named_return_value PARAMS ((void));
 static void cp_expand_stmt PARAMS ((tree));
 static void genrtl_start_function PARAMS ((tree));
@@ -66,19 +64,19 @@ static tree clear_decl_rtl PARAMS ((tree *, int *, void *));
 
 /* Finish processing the COND, the SUBSTMT condition for STMT.  */
 
-#define FINISH_COND(cond, stmt, substmt)               \
+#define FINISH_COND(COND, STMT, SUBSTMT)               \
   do {                                                 \
-    if (last_tree != stmt)                             \
+    if (last_tree != (STMT))                           \
       {                                                        \
-        RECHAIN_STMTS (stmt, substmt);                 \
-        if (!processing_template_decl)                  \
-          {                                             \
-           cond = build_tree_list (substmt, cond);     \
-           substmt = cond;                             \
-          }                                             \
+        RECHAIN_STMTS (STMT, SUBSTMT);                 \
+        if (!processing_template_decl)                 \
+          {                                            \
+           (COND) = build_tree_list (SUBSTMT, COND);   \
+           (SUBSTMT) = (COND);                         \
+          }                                            \
       }                                                        \
     else                                               \
-      substmt = cond;                                  \
+      (SUBSTMT) = (COND);                              \
   } while (0)
 
 /* Returns non-zero if the current statement is a full expression,
@@ -99,7 +97,7 @@ stmt_tree
 current_stmt_tree ()
 {
   return (cfun 
-         ? &cfun->language->x_stmt_tree 
+         ? &cfun->language->base.x_stmt_tree 
          : &scope_chain->x_stmt_tree);
 }
 
@@ -111,7 +109,7 @@ int
 anon_aggr_type_p (node)
      tree node;
 {
-  return (CLASS_TYPE_P (node) && TYPE_LANG_SPECIFIC(node)->anon_aggr);
+  return ANON_AGGR_TYPE_P (node);
 }
 
 /* Finish a scope.  */
@@ -205,6 +203,7 @@ finish_expr_stmt (expr)
      tree expr;
 {
   tree r = NULL_TREE;
+  tree expr_type = NULL_TREE;;
 
   if (expr != NULL_TREE)
     {
@@ -215,6 +214,9 @@ finish_expr_stmt (expr)
              || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE))
        expr = default_conversion (expr);
       
+      /* Remember the type of the expression.  */
+      expr_type = TREE_TYPE (expr);
+
       if (stmts_are_full_exprs_p ())
        expr = convert_to_void (expr, "statement");
       
@@ -225,7 +227,7 @@ finish_expr_stmt (expr)
 
   /* This was an expression-statement, so we save the type of the
      expression.  */
-  last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
+  last_expr_type = expr_type;
 
   return r;
 }
@@ -264,7 +266,6 @@ finish_then_clause (if_stmt)
      tree if_stmt;
 {
   RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
-  last_tree = if_stmt;
   return if_stmt;
 }
 
@@ -290,21 +291,8 @@ finish_else_clause (if_stmt)
 void 
 finish_if_stmt ()
 {
-  do_poplevel ();
   finish_stmt ();
-}
-
-void
-clear_out_block ()
-{
-  /* If COND wasn't a declaration, clear out the
-     block we made for it and start a new one here so the
-     optimization in expand_end_loop will work.  */
-  if (getdecls () == NULL_TREE)
-    {
-      do_poplevel ();
-      do_pushlevel ();
-    }
+  do_poplevel ();
 }
 
 /* Begin a while-statement.  Returns a newly created WHILE_STMT if
@@ -329,8 +317,26 @@ finish_while_stmt_cond (cond, while_stmt)
      tree while_stmt;
 {
   cond = maybe_convert_cond (cond);
-  FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt));
-  clear_out_block ();
+  if (getdecls () == NULL_TREE)
+    /* It was a simple condition; install it.  */
+    WHILE_COND (while_stmt) = cond;
+  else
+    {
+      /* If there was a declaration in the condition, we can't leave it
+        there; transform
+           while (A x = 42) { }
+        to
+           while (true) { A x = 42; if (!x) break; }  */
+      tree if_stmt;
+      WHILE_COND (while_stmt) = boolean_true_node;
+
+      if_stmt = begin_if_stmt ();
+      cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
+      finish_if_stmt_cond (cond, if_stmt);
+      finish_break_stmt ();
+      finish_then_clause (if_stmt);
+      finish_if_stmt ();
+    }
 }
 
 /* Finish a while-statement, which may be given by WHILE_STMT.  */
@@ -415,12 +421,12 @@ begin_for_stmt ()
   r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE, 
                  NULL_TREE, NULL_TREE);
   NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0;
-  add_stmt (r);
   if (NEW_FOR_SCOPE_P (r))
     {
       do_pushlevel ();
       note_level_for_for ();
     }
+  add_stmt (r);
 
   return r;
 }
@@ -446,8 +452,26 @@ finish_for_cond (cond, for_stmt)
      tree for_stmt;
 {
   cond = maybe_convert_cond (cond);
-  FINISH_COND (cond, for_stmt, FOR_COND (for_stmt));
-  clear_out_block ();
+  if (getdecls () == NULL_TREE)
+    /* It was a simple condition; install it.  */
+    FOR_COND (for_stmt) = cond;
+  else
+    {
+      /* If there was a declaration in the condition, we can't leave it
+        there; transform
+           for (; A x = 42;) { }
+        to
+           for (;;) { A x = 42; if (!x) break; }  */
+      tree if_stmt;
+      FOR_COND (for_stmt) = NULL_TREE;
+
+      if_stmt = begin_if_stmt ();
+      cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
+      finish_if_stmt_cond (cond, if_stmt);
+      finish_break_stmt ();
+      finish_then_clause (if_stmt);
+      finish_if_stmt ();
+    }
 }
 
 /* Finish the increment-EXPRESSION in a for-statement, which may be
@@ -500,9 +524,9 @@ tree
 begin_switch_stmt ()
 {
   tree r;
-  r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE);
-  add_stmt (r);
   do_pushlevel ();
+  r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
+  add_stmt (r);
   return r;
 }
 
@@ -513,9 +537,9 @@ finish_switch_cond (cond, switch_stmt)
      tree cond;
      tree switch_stmt;
 {
+  tree orig_type = NULL;
   if (!processing_template_decl)
     {
-      tree type;
       tree index;
 
       /* Convert the condition to an integer or enumeration type.  */
@@ -525,23 +549,27 @@ finish_switch_cond (cond, switch_stmt)
          error ("switch quantity not an integer");
          cond = error_mark_node;
        }
+      orig_type = TREE_TYPE (cond);
       if (cond != error_mark_node)
        {
          cond = default_conversion (cond);
          cond = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (cond), cond));
        }
 
-      type = TREE_TYPE (cond);
-      index = get_unwidened (cond, NULL_TREE);
-      /* We can't strip a conversion from a signed type to an unsigned,
-        because if we did, int_fits_type_p would do the wrong thing
-        when checking case values for being in range,
-        and it's too hard to do the right thing.  */
-      if (TREE_UNSIGNED (TREE_TYPE (cond))
-         == TREE_UNSIGNED (TREE_TYPE (index)))
-       cond = index;
+      if (cond != error_mark_node)
+       {
+         index = get_unwidened (cond, NULL_TREE);
+         /* We can't strip a conversion from a signed type to an unsigned,
+            because if we did, int_fits_type_p would do the wrong thing
+            when checking case values for being in range,
+            and it's too hard to do the right thing.  */
+         if (TREE_UNSIGNED (TREE_TYPE (cond))
+             == TREE_UNSIGNED (TREE_TYPE (index)))
+           cond = index;
+       }
     }
   FINISH_COND (cond, switch_stmt, SWITCH_COND (switch_stmt));
+  SWITCH_TYPE (switch_stmt) = orig_type;
   push_switch (switch_stmt);
 }
 
@@ -554,8 +582,8 @@ finish_switch_stmt (switch_stmt)
 {
   RECHAIN_STMTS (switch_stmt, SWITCH_BODY (switch_stmt));
   pop_switch (); 
-  do_poplevel ();
   finish_stmt ();
+  do_poplevel ();
 }
 
 /* Generate the RTL for T, which is a TRY_BLOCK. */
@@ -773,21 +801,6 @@ finish_handler (handler)
   RECHAIN_STMTS (handler, HANDLER_BODY (handler));
 }
 
-/* Generate the RTL for T, which is a CTOR_STMT. */
-
-static void
-genrtl_ctor_stmt (t)
-     tree t;
-{
-  if (CTOR_BEGIN_P (t))
-    begin_protect_partials ();
-  else
-    /* After this point, any exceptions will cause the
-       destructor to be executed, so we no longer need to worry
-       about destroying the various subobjects ourselves.  */
-    end_protect_partials ();
-}
-
 /* Begin a compound-statement.  If HAS_NO_SCOPE is non-zero, the
    compound-statement does not define a scope.  Returns a new
    COMPOUND_STMT if appropriate.  */
@@ -872,9 +885,6 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
   tree r;
   tree t;
 
-  if (TREE_CHAIN (string))
-    string = combine_strings (string);
-
   if (cv_qualifier != NULL_TREE
       && cv_qualifier != ridpointers[(int) RID_VOLATILE])
     {
@@ -940,7 +950,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
             DECL_RTL for the OPERAND -- which we don't have at this
             point.  */
          if (!allows_reg && DECL_P (operand))
-           mark_addressable (operand);
+           cxx_mark_addressable (operand);
        }
     }
 
@@ -972,35 +982,25 @@ finish_label_decl (name)
   add_decl_stmt (decl);
 }
 
-/* Generate the RTL for a SUBOBJECT. */
-
-static void 
-genrtl_subobject (cleanup)
-     tree cleanup;
-{
-  add_partial_entry (cleanup);
-}
-
-/* We're in a constructor, and have just constructed a a subobject of
-   *THIS.  CLEANUP is code to run if an exception is thrown before the
-   end of the current function is reached.   */
+/* When DECL goes out of scope, make sure that CLEANUP is executed.  */
 
 void 
-finish_subobject (cleanup)
+finish_decl_cleanup (decl, cleanup)
+     tree decl;
      tree cleanup;
 {
-  tree r = build_stmt (SUBOBJECT, cleanup);
-  add_stmt (r);
+  add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
 }
 
-/* When DECL goes out of scope, make sure that CLEANUP is executed.  */
+/* If the current scope exits with an exception, run CLEANUP.  */
 
-void 
-finish_decl_cleanup (decl, cleanup)
-     tree decl;
+void
+finish_eh_cleanup (cleanup)
      tree cleanup;
 {
-  add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+  tree r = build_stmt (CLEANUP_STMT, NULL_TREE, cleanup);
+  CLEANUP_EH_ONLY (r) = 1;
+  add_stmt (r);
 }
 
 /* Generate the RTL for a RETURN_INIT. */
@@ -1085,6 +1085,15 @@ finish_named_return_value (return_id, init)
   DECL_UNINLINABLE (current_function_decl) = 1;
 }
 
+/* Begin processing a mem-initializer-list.  */
+
+void
+begin_mem_initializers ()
+{
+  if (! DECL_CONSTRUCTOR_P (current_function_decl))
+    error ("only constructors take base initializers");
+}
+
 /* The INIT_LIST is a list of mem-initializers, in the order they were
    written by the user.  The TREE_VALUE of each node is a list of
    initializers for a particular subobject.  The TREE_PURPOSE is a
@@ -1141,90 +1150,11 @@ finish_mem_initializers (init_list)
        }
     }
 
-  setup_vtbl_ptr (member_init_list, base_init_list);
-}
-
-/* Do the initialization work necessary at the beginning of a constructor
-   or destructor.  This means processing member initializers and setting
-   vtable pointers.
-
-   ??? The call to keep_next_level at the end applies to all functions, but
-   should probably go somewhere else.  */
-
-void
-setup_vtbl_ptr (member_init_list, base_init_list)
-     tree member_init_list;
-     tree base_init_list;
-{
-  my_friendly_assert (doing_semantic_analysis_p (), 19990919);
-  my_friendly_assert (!vtbls_set_up_p, 20011220);
-
   if (processing_template_decl)
     add_stmt (build_min_nt (CTOR_INITIALIZER,
                            member_init_list, base_init_list));
-  else if (DECL_CONSTRUCTOR_P (current_function_decl))
-    {
-      tree ctor_stmt;
-
-      /* Mark the beginning of the constructor.  */
-      ctor_stmt = build_stmt (CTOR_STMT);
-      CTOR_BEGIN_P (ctor_stmt) = 1;
-      add_stmt (ctor_stmt);
-         
-      /* And actually initialize the base-classes and members.  */
-      emit_base_init (member_init_list, base_init_list);
-    }
-  else if (DECL_DESTRUCTOR_P (current_function_decl))
-    {
-      tree if_stmt;
-      tree compound_stmt;
-
-      /* If the dtor is empty, and we know there is not any possible
-        way we could use any vtable entries, before they are possibly
-        set by a base class dtor, we don't have to setup the vtables,
-        as we know that any base class dtor will set up any vtables
-        it needs.  We avoid MI, because one base class dtor can do a
-        virtual dispatch to an overridden function that would need to
-        have a non-related vtable set up, we cannot avoid setting up
-        vtables in that case.  We could change this to see if there
-        is just one vtable.
-
-         ??? In the destructor for a class, the vtables are set
-         appropriately for that class.  There will be no non-related
-         vtables.  jason 2001-12-11.  */
-      if_stmt = begin_if_stmt ();
-
-      /* If it is not safe to avoid setting up the vtables, then
-        someone will change the condition to be boolean_true_node.  
-         (Actually, for now, we do not have code to set the condition
-        appropriately, so we just assume that we always need to
-        initialize the vtables.)  */
-      finish_if_stmt_cond (boolean_true_node, if_stmt);
-      current_vcalls_possible_p = &IF_COND (if_stmt);
-
-      compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
-
-      /* Make all virtual function table pointers in non-virtual base
-        classes point to CURRENT_CLASS_TYPE's virtual function
-        tables.  */
-      initialize_vtbl_ptrs (current_class_ptr);
-
-      finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
-      finish_then_clause (if_stmt);
-      finish_if_stmt ();
-
-      /* And insert cleanups for our bases and members so that they
-         will be properly destroyed if we throw.  */
-      push_base_cleanups ();
-    }
-
-  /* Always keep the BLOCK node associated with the outermost pair of
-     curly braces of a function.  These are needed for correct
-     operation of dwarfout.c.  */
-  keep_next_level (1);
-
-  /* The virtual function tables are set up now.  */
-  vtbls_set_up_p = 1;
+  else
+    emit_base_init (member_init_list, base_init_list);
 }
 
 /* Returns the stack of SCOPE_STMTs for the current function.  */
@@ -1232,7 +1162,7 @@ setup_vtbl_ptr (member_init_list, base_init_list)
 tree *
 current_scope_stmt_stack ()
 {
-  return &cfun->language->x_scope_stmt_stack;
+  return &cfun->language->base.x_scope_stmt_stack;
 }
 
 /* Finish a parenthesized expression EXPR.  */
@@ -1242,7 +1172,7 @@ finish_parenthesized_expr (expr)
      tree expr;
 {
   if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expr))))
-    /* This inhibits warnings in truthvalue_conversion.  */
+    /* This inhibits warnings in c_common_truthvalue_conversion.  */
     C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK); 
 
   if (TREE_CODE (expr) == OFFSET_REF)
@@ -1284,7 +1214,7 @@ begin_global_stmt_expr ()
 
   keep_next_level (1);
   
-  return (last_tree != NULL_TREE) ? last_tree : expand_start_stmt_expr(); 
+  return last_tree ? last_tree : expand_start_stmt_expr(/*has_scope=*/1); 
 }
 
 /* Finish the STMT_EXPR last begun with begin_global_stmt_expr.  */
@@ -1334,32 +1264,86 @@ finish_stmt_expr (rtl_expr)
   return result;
 }
 
-/* Finish a call to FN with ARGS.  Returns a representation of the
-   call.  */
+/* Generate an expression for `FN (ARGS)'.
+
+   If DISALLOW_VIRTUAL is true, the call to FN will be not generated
+   as a virtual call, even if FN is virtual.  (This flag is set when
+   encountering an expression where the function name is explicitly
+   qualified.  For example a call to `X::f' never generates a virtual
+   call.)
+
+   Returns code for the call.  */
 
 tree 
-finish_call_expr (fn, args, koenig)
-     tree fn;
-     tree args;
-     int koenig;
+finish_call_expr (tree fn, tree args, bool disallow_virtual)
 {
-  tree result;
+  if (fn == error_mark_node || args == error_mark_node)
+    return error_mark_node;
+
+  if (processing_template_decl)
+    return build_nt (CALL_EXPR, fn, args, NULL_TREE);
+
+  /* ARGS should be a list of arguments.  */
+  my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
+                     20020712);
 
-  if (koenig)
+  if (BASELINK_P (fn))
     {
-      if (TREE_CODE (fn) == BIT_NOT_EXPR)
-       fn = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND (fn, 0));
-      else if (TREE_CODE (fn) != TEMPLATE_ID_EXPR)
-       fn = do_identifier (fn, 2, args);
-    }
-  result = build_x_function_call (fn, args, current_class_ref);
+      tree object;
+
+      /* A call to a member function.  From [over.call.func]:
+
+          If the keyword this is in scope and refers to the class of
+          that member function, or a derived class thereof, then the
+          function call is transformed into a qualified function call
+          using (*this) as the postfix-expression to the left of the
+          . operator.... [Otherwise] a contrived object of type T
+          becomes the implied object argument.  
+
+        This paragraph is unclear about this situation:
+
+         struct A { void f(); };
+         struct B : public A {};
+         struct C : public A { void g() { B::f(); }};
+
+       In particular, for `B::f', this paragraph does not make clear
+       whether "the class of that member function" refers to `A' or 
+       to `B'.  We believe it refers to `B'.  */
+      if (current_class_type 
+         && DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
+                            current_class_type)
+         && current_class_ref)
+       object = current_class_ref;
+      else
+       {
+         tree representative_fn;
 
-  if (TREE_CODE (result) == CALL_EXPR
-      && (! TREE_TYPE (result)
-          || TREE_CODE (TREE_TYPE (result)) != VOID_TYPE))
-    result = require_complete_type (result);
+         representative_fn = BASELINK_FUNCTIONS (fn);
+         if (TREE_CODE (representative_fn) == TEMPLATE_ID_EXPR)
+           representative_fn = TREE_OPERAND (representative_fn, 0);
+         representative_fn = get_first_fn (representative_fn);
+         object = build_dummy_object (DECL_CONTEXT (representative_fn));
+       }
 
-  return result;
+      return build_new_method_call (object, fn, args, NULL_TREE,
+                                   (disallow_virtual 
+                                    ? LOOKUP_NONVIRTUAL : 0));
+    }
+  else if (is_overloaded_fn (fn))
+    /* A call to a namespace-scope function.  */
+    return build_new_function_call (fn, args);
+  else if (CLASS_TYPE_P (TREE_TYPE (fn)))
+    {
+      /* If the "function" is really an object of class type, it might
+        have an overloaded `operator ()'.  */
+      tree result;
+      result = build_opfncall (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
+      if (result)
+       return result;
+    }
+
+  /* A call where the function is unknown.  */
+  return build_function_call (fn, args);
 }
 
 /* Finish a call to a postfix increment or decrement or EXPR.  (Which
@@ -1419,14 +1403,6 @@ finish_object_call_expr (fn, object, args)
      tree object;
      tree args;
 {
-#if 0
-  /* This is a future direction of this code, but because
-     build_x_function_call cannot always undo what is done in
-     build_component_ref entirely yet, we cannot do this.  */
-
-  tree real_fn = build_component_ref (object, fn, NULL_TREE, 1);
-  return finish_call_expr (real_fn, args);
-#else
   if (DECL_DECLARES_TYPE_P (fn))
     {
       if (processing_template_decl)
@@ -1445,9 +1421,11 @@ finish_object_call_expr (fn, object, args)
          return error_mark_node;
        }
     }
-
-  return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
-#endif
+  
+  if (name_p (fn))
+    return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
+  else
+    return build_new_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
 }
 
 /* Finish a qualified member function call using OBJECT and ARGS as
@@ -1488,22 +1466,6 @@ finish_pseudo_destructor_call_expr (object, scope, destructor)
   return cp_convert (void_type_node, object);
 }
 
-/* Finish a call to a globally qualified member function FN using
-   ARGS.  Returns an expression for the call.  */
-
-tree 
-finish_qualified_call_expr (fn, args)
-     tree fn;
-     tree args;
-{
-  if (processing_template_decl)
-    return build_min_nt (CALL_EXPR, fn, args, NULL_TREE);
-  else
-    return build_member_call (TREE_OPERAND (fn, 0),
-                             TREE_OPERAND (fn, 1),
-                             args);
-}
-
 /* Finish an expression of the form CODE EXPR.  */
 
 tree
@@ -1538,6 +1500,20 @@ finish_id_expr (expr)
   return expr;
 }
 
+/* Return the declaration for the function-name variable indicated by
+   ID.  */
+
+tree
+finish_fname (tree id)
+{
+  tree decl;
+  
+  decl = fname_decl (C_RID_CODE (id), id);
+  if (processing_template_decl)
+    decl = build_min_nt (LOOKUP_EXPR, DECL_NAME (decl));
+  return decl;
+}
+
 static tree current_type_lookups;
 
 /* Perform deferred access control for types used in the type of a
@@ -1577,32 +1553,13 @@ decl_type_access_control (decl)
      added to type_lookups after typed_declspecs saved the copy that
      ended up in current_type_lookups.  */
   type_lookups = current_type_lookups;
-  
-  current_type_lookups = NULL_TREE;
 }
 
-/* Record the lookups, if we're doing deferred access control.  */
-
 void
 save_type_access_control (lookups)
      tree lookups;
 {
-  if (type_lookups != error_mark_node)
-    {
-      my_friendly_assert (!current_type_lookups, 20010301);
-      current_type_lookups = lookups;
-    }
-  else
-    my_friendly_assert (!lookups || lookups == error_mark_node, 20010301);
-}
-
-/* Set things up so that the next deferred access control will succeed.
-   This is needed for friend declarations see grokdeclarator for details.  */
-
-void
-skip_type_access_control ()
-{
-  type_lookups = NULL_TREE;
+  current_type_lookups = lookups;
 }
 
 /* Reset the deferred access control.  */
@@ -1614,20 +1571,17 @@ reset_type_access_control ()
   current_type_lookups = NULL_TREE;
 }
 
-/* Begin a function definition declared with DECL_SPECS and
-   DECLARATOR.  Returns non-zero if the function-declaration is
-   legal.  */
+/* Begin a function definition declared with DECL_SPECS, ATTRIBUTES,
+   and DECLARATOR.  Returns non-zero if the function-declaration is
+   valid.  */
 
 int
-begin_function_definition (decl_specs, declarator)
+begin_function_definition (decl_specs, attributes, declarator)
      tree decl_specs;
+     tree attributes;
      tree declarator;
 {
-  tree specs;
-  tree attrs;
-
-  split_specs_attrs (decl_specs, &specs, &attrs);
-  if (!start_function (specs, declarator, attrs, SF_DEFAULT))
+  if (!start_function (decl_specs, declarator, attributes, SF_DEFAULT))
     return 0;
 
   deferred_type_access_control ();
@@ -1722,6 +1676,25 @@ finish_template_template_parm (aggr, identifier)
   return finish_template_type_parm (aggr, tmpl);
 }
 
+/* ARGUMENT is the default-argument value for a template template
+   parameter.  If ARGUMENT is invalid, issue error messages and return
+   the ERROR_MARK_NODE.  Otherwise, ARGUMENT itself is returned.  */
+
+tree
+check_template_template_default_arg (tree argument)
+{
+  if (TREE_CODE (argument) != TEMPLATE_DECL
+      && TREE_CODE (argument) != TEMPLATE_TEMPLATE_PARM
+      && TREE_CODE (argument) != TYPE_DECL
+      && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
+    {
+      error ("invalid default template argument");
+      return error_mark_node;
+    }
+
+  return argument;
+}
+
 /* Finish a parameter list, indicated by PARMS.  If ELLIPSIS is
    non-zero, the parameter list was terminated by a `...'.  */
 
@@ -1748,6 +1721,9 @@ tree
 begin_class_definition (t)
      tree t;
 {
+  if (t == error_mark_node)
+    return error_mark_node;
+
   /* Check the bases are accessible. */
   decl_type_access_control (TYPE_NAME (t));
   reset_type_access_control ();
@@ -1923,7 +1899,7 @@ finish_member_declaration (decl)
           struct S { enum E { }; int E } s;
           s.E = 3;
 
-        is legal.  In addition, the FIELD_DECLs must be maintained in
+        is valid.  In addition, the FIELD_DECLs must be maintained in
         declaration order so that class layout works as expected.
         However, we don't need that order until class layout, so we
         save a little time by putting FIELD_DECLs on in reverse order
@@ -1957,6 +1933,9 @@ finish_class_definition (t, attributes, semi, pop_scope_p)
      int semi;
      int pop_scope_p;
 {
+  if (t == error_mark_node)
+    return error_mark_node;
+
   /* finish_struct nukes this anyway; if finish_exception does too,
      then it can go.  */
   if (semi)
@@ -1964,8 +1943,8 @@ finish_class_definition (t, attributes, semi, pop_scope_p)
 
   /* If we got any attributes in class_head, xref_tag will stick them in
      TREE_TYPE of the type.  Grab them now.  */
-  attributes = chainon (TREE_TYPE (t), attributes);
-  TREE_TYPE (t) = NULL_TREE;
+  attributes = chainon (TYPE_ATTRIBUTES (t), attributes);
+  TYPE_ATTRIBUTES (t) = NULL_TREE;
 
   if (TREE_CODE (t) == ENUMERAL_TYPE)
     ;
@@ -1980,8 +1959,6 @@ finish_class_definition (t, attributes, semi, pop_scope_p)
     check_for_missing_semicolon (t); 
   if (pop_scope_p)
     pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (t)));
-  if (current_function_decl)
-    type_lookups = error_mark_node;
   if (current_scope () == current_function_decl)
     do_pending_defargs ();
 
@@ -1998,16 +1975,6 @@ begin_inline_definitions ()
     do_pending_inlines ();
 }
 
-/* Finish processing the inline function definitions cached during the
-   processing of a class definition.  */
-
-void
-finish_inline_definitions ()
-{
-  if (current_class_type == NULL_TREE)
-    clear_inline_text_obstack (); 
-}
-
 /* Finish processing the declaration of a member class template
    TYPES whose template parameters are given by PARMS.  */
 
@@ -2116,7 +2083,12 @@ finish_base_specifier (access_specifier, base_class)
 {
   tree result;
 
-  if (! is_aggr_type (base_class, 1))
+  if (base_class == error_mark_node)
+    {
+      error ("invalid base-class specification");
+      result = NULL_TREE;
+    }
+  else if (! is_aggr_type (base_class, 1))
     result = NULL_TREE;
   else
     {
@@ -2144,11 +2116,9 @@ check_multiple_declarators ()
      contain at most one declarator.  
 
      We don't just use PROCESSING_TEMPLATE_DECL for the first
-     condition since that would disallow the perfectly legal code, 
+     condition since that would disallow the perfectly valid code, 
      like `template <class T> struct S { int i, j; };'.  */
-  tree scope = current_scope ();
-
-  if (scope && TREE_CODE (scope) == FUNCTION_DECL)
+  if (at_function_scope_p ())
     /* It's OK to write `template <class T> void f() { int i, j;}'.  */
     return;
      
@@ -2190,7 +2160,7 @@ finish_sizeof (t)
   if (processing_template_decl)
     return build_min_nt (SIZEOF_EXPR, t);
 
-  return TYPE_P (t) ? c_sizeof (t) : expr_sizeof (t);
+  return TYPE_P (t) ? cxx_sizeof (t) : expr_sizeof (t);
 }
 
 /* Implement the __alignof keyword: Return the minimum required
@@ -2203,7 +2173,7 @@ finish_alignof (t)
   if (processing_template_decl)
     return build_min_nt (ALIGNOF_EXPR, t);
 
-  return TYPE_P (t) ? c_alignof (t) : c_alignof_expr (t);
+  return TYPE_P (t) ? cxx_alignof (t) : c_alignof_expr (t);
 }
 
 /* Generate RTL for the statement T, and its substatements, and any
@@ -2215,14 +2185,6 @@ cp_expand_stmt (t)
 {
   switch (TREE_CODE (t))
     {
-    case CLEANUP_STMT:
-      genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
-      break;
-
-    case CTOR_STMT:
-      genrtl_ctor_stmt (t);
-      break;
-
     case TRY_BLOCK:
       genrtl_try_block (t);
       break;
@@ -2235,10 +2197,6 @@ cp_expand_stmt (t)
       genrtl_handler (t);
       break;
 
-    case SUBOBJECT:
-      genrtl_subobject (SUBOBJECT_CLEANUP (t));
-      break;
-
     case RETURN_INIT:
       genrtl_named_return_value ();
       break;
@@ -2247,7 +2205,7 @@ cp_expand_stmt (t)
       break;
     
     default:
-      my_friendly_abort (19990810);
+      abort ();
       break;
     }
 }
@@ -2293,7 +2251,7 @@ simplify_aggr_init_exprs_r (tp, walk_subtrees, data)
     {
       /* Replace the first argument with the address of the third
         argument to the AGGR_INIT_EXPR.  */
-      mark_addressable (slot);
+      cxx_mark_addressable (slot);
       args = tree_cons (NULL_TREE, 
                        build1 (ADDR_EXPR, 
                                build_pointer_type (TREE_TYPE (slot)),
@@ -2393,6 +2351,7 @@ expand_body (fn)
 {
   int saved_lineno;
   const char *saved_input_filename;
+  tree saved_function;
 
   /* When the parser calls us after finishing the body of a template
      function, we don't really want to expand the body.  When we're
@@ -2470,8 +2429,15 @@ expand_body (fn)
   if (DECL_EXTERNAL (fn))
     return;
 
-  /* Emit any thunks that should be emitted at the same time as FN.  */
-  emit_associated_thunks (fn);
+  /* Save the current file name and line number.  When we expand the
+     body of the function, we'll set LINENO and INPUT_FILENAME so that
+     error-mesages come out in the right places.  */
+  saved_lineno = lineno;
+  saved_input_filename = input_filename;
+  saved_function = current_function_decl;
+  lineno = DECL_SOURCE_LINE (fn);
+  input_filename = DECL_SOURCE_FILE (fn);
+  current_function_decl = fn;
 
   timevar_push (TV_INTEGRATION);
 
@@ -2481,14 +2447,6 @@ expand_body (fn)
   timevar_pop (TV_INTEGRATION);
   timevar_push (TV_EXPAND);
 
-  /* Save the current file name and line number.  When we expand the
-     body of the function, we'll set LINENO and INPUT_FILENAME so that
-     error-mesages come out in the right places.  */
-  saved_lineno = lineno;
-  saved_input_filename = input_filename;
-  lineno = DECL_SOURCE_LINE (fn);
-  input_filename = DECL_SOURCE_FILE (fn);
-
   genrtl_start_function (fn);
   current_function_is_thunk = DECL_THUNK_P (fn);
 
@@ -2520,11 +2478,15 @@ expand_body (fn)
     DECL_SAVED_TREE (fn) = NULL_TREE;
 
   /* And restore the current source position.  */
+  current_function_decl = saved_function;
   lineno = saved_lineno;
   input_filename = saved_input_filename;
   extract_interface_info ();
 
   timevar_pop (TV_EXPAND);
+
+  /* Emit any thunks that should be emitted at the same time as FN.  */
+  emit_associated_thunks (fn);
 }
 
 /* Helper function for walk_tree, used by finish_function to override all
@@ -2544,10 +2506,10 @@ nullify_returns_r (tp, walk_subtrees, data)
   if (TYPE_P (*tp))
     *walk_subtrees = 0;
   else if (TREE_CODE (*tp) == RETURN_STMT)
-    RETURN_EXPR (*tp) = NULL_TREE;
+    RETURN_STMT_EXPR (*tp) = NULL_TREE;
   else if (TREE_CODE (*tp) == CLEANUP_STMT
           && CLEANUP_DECL (*tp) == nrv)
-    CLEANUP_EXPR (*tp) = NULL_TREE;
+    CLEANUP_EH_ONLY (*tp) = 1;
 
   /* Keep iterating.  */
   return NULL_TREE;
@@ -2594,15 +2556,13 @@ genrtl_start_function (fn)
       if (!current_function_cannot_inline)
        current_function_cannot_inline = cp_function_chain->cannot_inline;
 
-      /* We don't need the saved data anymore.  */
-      free (DECL_SAVED_FUNCTION_DATA (fn));
-      DECL_SAVED_FUNCTION_DATA (fn) = NULL;
+      /* We don't need the saved data anymore.  Unless this is an inline
+         function; we need the named return value info for
+         cp_copy_res_decl_for_inlining.  */
+      if (! DECL_INLINE (fn))
+       DECL_SAVED_FUNCTION_DATA (fn) = NULL;
     }
 
-  /* Tell the cross-reference machinery that we're defining this
-     function.  */
-  GNU_xref_function (fn, DECL_ARGUMENTS (fn));
-
   /* Keep track of how many functions we're presently expanding.  */
   ++function_depth;