[llvm-commits] CVS: gcc-3.4/gcc/cp/cp-lang.c cp-tree.h decl.c decl2.c method.c pt.c rtti.c semantics.c typeck.c

John Criswell criswell at cs.uiuc.edu
Thu Feb 5 10:09:28 PST 2004


Changes in directory gcc-3.4/gcc/cp:

cp-lang.c updated: 1.2 -> 1.3
cp-tree.h updated: 1.2 -> 1.3
decl.c updated: 1.2 -> 1.3
decl2.c updated: 1.2 -> 1.3
method.c updated: 1.2 -> 1.3
pt.c updated: 1.2 -> 1.3
rtti.c updated: 1.2 -> 1.3
semantics.c updated: 1.2 -> 1.3
typeck.c updated: 1.2 -> 1.3

---
Log message:

Commit of merge from September 24, 2003 of mainline GCC.  This merge now
works reasonably on Linux/x86 and probably works on Solaris/Sparc.



---
Diffs of the changes:  (+772 -1011)

Index: gcc-3.4/gcc/cp/cp-lang.c
diff -u gcc-3.4/gcc/cp/cp-lang.c:1.2 gcc-3.4/gcc/cp/cp-lang.c:1.3
--- gcc-3.4/gcc/cp/cp-lang.c:1.2	Thu Jan  8 17:03:40 2004
+++ gcc-3.4/gcc/cp/cp-lang.c	Thu Feb  5 10:05:46 2004
@@ -32,6 +32,11 @@
 #include "diagnostic.h"
 #include "cxx-pretty-print.h"
 
+#include "llvm-out.h"
+#ifdef EMIT_LLVM
+#include "llvm-internals.h"
+#endif
+
 enum c_language_kind c_language = clk_cxx;
 
 static HOST_WIDE_INT cxx_get_alias_set (tree);
@@ -42,6 +47,10 @@
 static bool cp_var_mod_type_p (tree);
 static void cxx_initialize_diagnostics (diagnostic_context *);
 
+#if EMIT_LLVM
+void llvm_cxx_expand_function_start ();
+#endif
+
 #undef LANG_HOOKS_NAME
 #define LANG_HOOKS_NAME "GNU C++"
 #undef LANG_HOOKS_TREE_SIZE
@@ -110,6 +119,12 @@
 #define LANG_HOOKS_DECL_PRINTABLE_NAME	cxx_printable_name
 #undef LANG_HOOKS_PRINT_ERROR_FUNCTION
 #define LANG_HOOKS_PRINT_ERROR_FUNCTION	cxx_print_error_function
+#undef LANG_HOOKS_BUILTIN_TYPE_DECLS
+#define LANG_HOOKS_BUILTIN_TYPE_DECLS cxx_builtin_type_decls
+#undef LANG_HOOKS_PUSHLEVEL
+#define LANG_HOOKS_PUSHLEVEL lhd_do_nothing_i
+#undef LANG_HOOKS_POPLEVEL
+#define LANG_HOOKS_POPLEVEL lhd_do_nothing_iii_return_null_tree
 #undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
 #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL cxx_warn_unused_global_decl
 #undef LANG_HOOKS_WRITE_GLOBALS
@@ -123,6 +138,18 @@
 #undef LANG_HOOKS_FUNCTION_FINAL
 #define LANG_HOOKS_FUNCTION_FINAL cxx_pop_function_context
 
+#undef LANG_HOOKS_RTL_EXPAND_START
+#define LANG_HOOKS_RTL_EXPAND_START cxx_expand_function_start
+#undef LANG_HOOKS_RTL_EXPAND_STMT
+#define LANG_HOOKS_RTL_EXPAND_STMT expand_stmt
+
+#ifdef EMIT_LLVM
+#undef LANG_HOOKS_LLVM_IR_EXPAND_START
+#define LANG_HOOKS_LLVM_IR_EXPAND_START llvm_cxx_expand_function_start
+#undef LANG_HOOKS_LLVM_IR_EXPAND_STMT
+#define LANG_HOOKS_LLVM_IR_EXPAND_STMT llvm_expand_stmt
+#endif
+
 /* Attribute hooks.  */
 #undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
 #define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
@@ -166,10 +193,12 @@
 #undef LANG_HOOKS_EXPR_SIZE
 #define LANG_HOOKS_EXPR_SIZE cp_expr_size
 
+#undef LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR
+#define LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR cxx_callgraph_analyze_expr
 #undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
 #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION expand_body
-#undef LANG_HOOKS_CALLGRAPH_LOWER_FUNCTION
-#define LANG_HOOKS_CALLGRAPH_LOWER_FUNCTION lower_function
+#undef LANG_HOOKS_LLVM_CALLGRAPH_EXPAND_FUNCTION
+#define LANG_HOOKS_LLVM_CALLGRAPH_EXPAND_FUNCTION expand_body
 
 #undef LANG_HOOKS_MAKE_TYPE
 #define LANG_HOOKS_MAKE_TYPE cxx_make_type
@@ -187,6 +216,8 @@
 #define LANG_HOOKS_INCOMPLETE_TYPE_ERROR cxx_incomplete_type_error
 #undef LANG_HOOKS_TYPE_PROMOTES_TO
 #define LANG_HOOKS_TYPE_PROMOTES_TO cxx_type_promotes_to
+#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
+#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
 
 /* Each front end provides its own hooks, for toplev.c.  */
 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;


Index: gcc-3.4/gcc/cp/cp-tree.h
diff -u gcc-3.4/gcc/cp/cp-tree.h:1.2 gcc-3.4/gcc/cp/cp-tree.h:1.3
--- gcc-3.4/gcc/cp/cp-tree.h:1.2	Thu Jan  8 17:03:40 2004
+++ gcc-3.4/gcc/cp/cp-tree.h	Thu Feb  5 10:05:46 2004
@@ -39,6 +39,7 @@
       IDENTIFIER_MARKED (IDENTIFIER_NODEs)
       NEW_EXPR_USE_GLOBAL (in NEW_EXPR).
       DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
+      COMPOUND_EXPR_OVERLOADED (in COMPOUND_EXPR).
       TREE_INDIRECT_USING (in NAMESPACE_DECL).
       ICS_USER_FLAG (in _CONV)
       CLEANUP_P (in TRY_BLOCK)
@@ -46,6 +47,7 @@
       PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
       PARMLIST_ELLIPSIS_P (in PARMLIST)
       DECL_PRETTY_FUNCTION_P (in VAR_DECL)
+      KOENIG_LOOKUP_P (in CALL_EXPR)
    1: IDENTIFIER_VIRTUAL_P.
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -796,7 +798,6 @@
   int returns_abnormally;
   int in_function_try_handler;
   int in_base_initializer;
-  int x_expanding_p;
 
   /* True if this function can throw an exception.  */
   bool can_throw : 1;
@@ -858,17 +859,6 @@
 #define current_function_returns_abnormally \
   cp_function_chain->returns_abnormally
 
-/* Nonzero if we should generate RTL for functions that we process.
-   When this is zero, we just accumulate tree structure, without
-   interacting with the back end.  */
-
-#define expanding_p cp_function_chain->x_expanding_p
-
-/* Nonzero if we are in the semantic analysis phase for the current
-   function.  */
-
-#define doing_semantic_analysis_p() (!expanding_p)
-
 /* Nonzero if we are processing a base initializer.  Zero elsewhere.  */
 #define in_base_initializer cp_function_chain->in_base_initializer
 
@@ -2293,6 +2283,14 @@
 #define DELETE_EXPR_USE_GLOBAL(NODE)	TREE_LANG_FLAG_0 (NODE)
 #define DELETE_EXPR_USE_VEC(NODE)	TREE_LANG_FLAG_1 (NODE)
 
+/* Indicates that this is a non-dependent COMPOUND_EXPR which will
+   resolve to a function call.  */
+#define COMPOUND_EXPR_OVERLOADED(NODE)	TREE_LANG_FLAG_0 (NODE)
+
+/* In a CALL_EXPR appearing in a template, true if Koenig lookup
+   should be performed at instantiation time.  */
+#define KOENIG_LOOKUP_P(NODE) TREE_LANG_FLAG_0(NODE)
+
 /* Nonzero if this AGGR_INIT_EXPR provides for initialization via a
    constructor call, rather than an ordinary function call.  */
 #define AGGR_INIT_VIA_CTOR_P(NODE) \
@@ -2932,15 +2930,27 @@
 
 /* The kinds of scopes we recognize.  */
 typedef enum scope_kind {
-  sk_block,          /* An ordinary block scope.  */
+  sk_block = 0,      /* An ordinary block scope.  This enumerator must
+			have the value zero because "cp_binding_level"
+			is initialized by using "memset" to set the
+			contents to zero, and the default scope kind
+			is "sk_block".  */
+  sk_cleanup,        /* A scope for (pseudo-)scope for cleanup.  It is
+                        peusdo in that it is transparent to name lookup
+                        activities.  */
   sk_try,	     /* A try-block.  */
   sk_catch,          /* A catch-block.  */
   sk_for,            /* The scope of the variable declared in a
 			for-init-statement.  */
+  sk_function_parms, /* The scope containing function parameters.  */
+  sk_class,          /* The scope containing the members of a class.  */
+  sk_namespace,      /* The scope containing the members of a
+			namespace, including the global scope.  */
   sk_template_parms, /* A scope for template parameters.  */
-  sk_template_spec   /* A scope corresponding to a template
-			specialization.  There is never anything in
-			this scope.  */
+  sk_template_spec   /* Like sk_template_parms, but for an explicit
+			specialization.  Since, by definition, an
+			explicit specialization is introduced by
+			"template <>", this scope is always empty.  */
 } scope_kind;
 
 /* Various kinds of template specialization, instantiation, etc.  */
@@ -3027,9 +3037,13 @@
 				   (lookup_template_class use) */
   tf_stmt_expr_cmpd = 1 << 6,   /* tsubsting the compound statement of
 				   a statement expr.  */
-  tf_stmt_expr_body = 1 << 7    /* tsubsting the statements in the
+  tf_stmt_expr_body = 1 << 7,   /* tsubsting the statements in the
 			       	   body of the compound statement of a
 			       	   statement expr.  */
+  tf_conv = 1 << 8              /* We are determining what kind of
+				   conversion might be permissible,
+				   not actually performing the
+				   conversion.  */
 } tsubst_flags_t;
 
 /* The kind of checking we can do looking in a class hierarchy.  */
@@ -3084,7 +3098,7 @@
 extern GTY(()) tree anonymous_namespace_name;
 
 /* is_in_anonymous_namespace - Return true if the specified decl nodes is in an
-   anonymous namespace! */
+    anonymous namespace! */
 extern int is_in_anonymous_namespace(tree decl);
 
 /* The number of function bodies which we are currently processing.
@@ -3528,7 +3542,7 @@
 extern tree convert_for_arg_passing (tree, tree);
 extern tree cp_convert_parm_for_inlining        (tree, tree, tree);
 extern bool is_properly_derived_from (tree, tree);
-extern tree initialize_reference (tree, tree, tree);
+extern tree initialize_reference (tree, tree, tree, tree *);
 extern tree make_temporary_var_for_ref_to_temp (tree, tree);
 extern tree strip_top_quals (tree);
 extern tree perform_implicit_conversion (tree, tree);
@@ -3602,7 +3616,6 @@
 extern int global_bindings_p			(void);
 extern int kept_level_p				(void);
 extern tree getdecls				(void);
-extern void pushlevel				(int);
 extern void insert_block			(tree);
 extern void set_block				(tree);
 extern tree pushdecl				(tree);
@@ -3615,11 +3628,12 @@
 extern void cxx_mark_function_context		(struct function *);
 extern int toplevel_bindings_p			(void);
 extern int namespace_bindings_p			(void);
-extern void keep_next_level			(int);
+extern void keep_next_level (bool);
+extern scope_kind innermost_scope_kind          (void);
 extern int template_parm_scope_p		(void);
 extern void set_class_shadows			(tree);
 extern void maybe_push_cleanup_level		(tree);
-extern void begin_scope                         (scope_kind);
+extern cxx_scope *begin_scope (scope_kind, tree);
 extern void finish_scope                        (void);
 extern void resume_level			(struct cp_binding_level *);
 extern void delete_block			(tree);
@@ -3748,7 +3762,8 @@
 extern tmpl_spec_kind current_tmpl_spec_kind    (int);
 extern tree cp_fname_init			(const char *);
 extern tree check_elaborated_type_specifier     (enum tag_types, tree, bool);
-extern int add_binding                          (cxx_binding *, tree);
+extern tree cxx_builtin_type_decls              (void);
+
 extern bool have_extern_spec;
 
 /* in decl2.c */
@@ -3801,7 +3816,7 @@
 extern tree get_guard (tree);
 extern tree get_guard_cond (tree);
 extern tree set_guard (tree);
-extern void lower_function (tree);
+extern tree cxx_callgraph_analyze_expr (tree *, int *, tree);
 
 /* XXX Not i18n clean.  */
 #define cp_deprecated(STR)						\
@@ -4114,7 +4129,7 @@
 extern tree finish_stmt_expr_expr 		(tree);
 extern tree finish_stmt_expr                    (tree, bool);
 extern tree perform_koenig_lookup               (tree, tree);
-extern tree finish_call_expr                    (tree, tree, bool);
+extern tree finish_call_expr                    (tree, tree, bool, bool);
 extern tree finish_increment_expr               (tree, enum tree_code);
 extern tree finish_this_expr                    (void);
 extern tree finish_object_call_expr             (tree, tree, tree);
@@ -4141,11 +4156,10 @@
 						 bool, bool, bool *, 
 						 const char **);
 extern tree finish_typeof			(tree);
-extern tree finish_sizeof			(tree);
-extern tree finish_alignof			(tree);
 extern void finish_decl_cleanup                 (tree, tree);
 extern void finish_eh_cleanup                   (tree);
 extern void expand_body                         (tree);
+extern void cxx_expand_function_start		(void);
 extern tree nullify_returns_r		      (tree *, int *, void *);
 extern void do_pushlevel                        (scope_kind);
 extern tree do_poplevel                         (void);
@@ -4170,13 +4184,10 @@
 extern tree canonical_type_variant              (tree);
 extern tree copy_base_binfos			(tree, tree, tree);
 extern int member_p				(tree);
-extern cp_lvalue_kind real_lvalue_p		(tree);
-extern int non_cast_lvalue_p			(tree);
-extern cp_lvalue_kind real_non_cast_lvalue_p    (tree);
-extern int non_cast_lvalue_or_else		(tree, const char *);
-extern tree build_min				(enum tree_code, tree,
-							 ...);
+extern cp_lvalue_kind real_lvalue_p             (tree);
+extern tree build_min				(enum tree_code, tree, ...);
 extern tree build_min_nt			(enum tree_code, ...);
+extern tree build_min_non_dep			(enum tree_code, tree, ...);
 extern tree build_cplus_new			(tree, tree);
 extern tree get_target_expr			(tree);
 extern tree build_cplus_staticfn_type		(tree, tree, tree);
@@ -4254,8 +4265,8 @@
 extern bool compparms				(tree, tree);
 extern int comp_cv_qualification                (tree, tree);
 extern int comp_cv_qual_signature               (tree, tree);
-extern tree expr_sizeof				(tree);
-extern tree cxx_sizeof_or_alignof_type    (tree, enum tree_code, int);
+extern tree cxx_sizeof_or_alignof_expr    (tree, enum tree_code);
+extern tree cxx_sizeof_or_alignof_type    (tree, enum tree_code, bool);
 #define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false)
 extern tree inline_conversion			(tree);
 extern tree decay_conversion			(tree);


Index: gcc-3.4/gcc/cp/decl.c
diff -u gcc-3.4/gcc/cp/decl.c:1.2 gcc-3.4/gcc/cp/decl.c:1.3
--- gcc-3.4/gcc/cp/decl.c:1.2	Thu Jan  8 17:03:40 2004
+++ gcc-3.4/gcc/cp/decl.c	Thu Feb  5 10:05:46 2004
@@ -56,7 +56,6 @@
 static tree grokparms (tree);
 static const char *redeclaration_error_message (tree, tree);
 
-static void push_binding_level (cxx_scope *);
 static void pop_binding_level (void);
 static void suspend_binding_level (void);
 static void resume_binding_level (struct cp_binding_level *);
@@ -69,7 +68,7 @@
 static tree lookup_tag_reverse (tree, tree);
 static void push_local_name (tree);
 static void warn_extern_redeclared_static (tree, tree);
-static tree grok_reference_init (tree, tree, tree);
+static tree grok_reference_init (tree, tree, tree, tree *);
 static tree grokfndecl (tree, tree, tree, tree, int,
 			enum overload_flags, tree,
 			tree, int, int, int, int, int, int, tree);
@@ -118,7 +117,7 @@
 static void maybe_deduce_size_from_array_init (tree, tree);
 static void layout_var_decl (tree);
 static void maybe_commonize_var (tree);
-static tree check_initializer (tree, tree, int);
+static tree check_initializer (tree, tree, int, tree *);
 static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
 static void save_function_data (tree);
 static void check_function_type (tree, tree);
@@ -371,51 +370,27 @@
        TREE_LIST; the TREE_VALUE is the actual declaration.  */
     tree dead_vars_from_for;
 
-    /* 1 for the level that holds the parameters of a function.
-       2 for the level that holds a class declaration.  */
-    unsigned parm_flag : 2;
-
-    /* 1 means make a BLOCK for this level regardless of all else.
-       2 for temporary binding contours created by the compiler.  */
-    unsigned keep : 2;
+    /* Binding depth at which this level began.  */
+    int binding_depth;
+
+    /* The kind of scope that this object represents.  However, a
+       SK_TEMPLATE_SPEC scope is represented with KIND set to
+       SK_TEMPALTE_PARMS and EXPLICIT_SPEC_P set to true.  */
+    enum scope_kind kind : 4;
+
+    /* True if this scope is an SK_TEMPLATE_SPEC scope.  This field is
+       only valid if KIND == SK_TEMPLATE_PARMS.  */
+    bool explicit_spec_p : 1;
 
-    /* Nonzero if this level "doesn't exist" for tags.  */
-    unsigned tag_transparent : 1;
+    /* true means make a BLOCK for this level regardless of all else.  */
+    unsigned keep : 1;
 
     /* Nonzero if this level can safely have additional
        cleanup-needing variables added to it.  */
     unsigned more_cleanups_ok : 1;
     unsigned have_cleanups : 1;
 
-    /* Nonzero if this scope is for storing the decls for template
-       parameters and generic decls; these decls will be discarded and
-       replaced with a TEMPLATE_DECL.  */
-    unsigned template_parms_p : 1;
-
-    /* Nonzero if this scope corresponds to the `<>' in a
-       `template <>' clause.  Whenever this flag is set,
-       TEMPLATE_PARMS_P will be set as well.  */
-    unsigned template_spec_p : 1;
-
-    /* This is set for a namespace binding level.  */
-    unsigned namespace_p : 1;
-
-    /* True if this level is that of a for-statement where we need to
-       worry about ambiguous (ARM or ISO) scope rules.  */
-    unsigned is_for_scope : 1;
-
-    /* True if this level corresponds to a TRY block.  Currently this
-       information is only available while building the tree structure.  */
-    unsigned is_try_scope : 1;
-
-    /* True if this level corresponds to a CATCH block.  Currently this
-       information is only available while building the tree structure.  */
-    unsigned is_catch_scope : 1;
-
-    /* Three bits left for this word.  */
-
-    /* Binding depth at which this level began.  */
-    unsigned binding_depth;
+    /* 22 bits left to fill a 32-bit word.  */
   };
 
 #define NULL_BINDING_LEVEL ((struct cp_binding_level *) NULL)
@@ -435,9 +410,9 @@
 
 static GTY((deletable (""))) struct cp_binding_level *free_binding_level;
 
-/* Nonzero means unconditionally make a BLOCK for the next level pushed.  */
+/* true means unconditionally make a BLOCK for the next level pushed.  */
 
-static int keep_next_level_flag;
+static bool keep_next_level_flag;
 
 /* A TREE_LIST of VAR_DECLs.  The TREE_PURPOSE is a RECORD_TYPE or
    UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type.  At the
@@ -469,28 +444,24 @@
 static const char *
 cxx_scope_descriptor (cxx_scope *scope)
 {
-  const char *desc;
-
-  if (scope->namespace_p)
-    desc = "namespace-scope";
-  else if (scope->parm_flag == 1)
-    desc = "function-prototype-scope";
-  else if (scope->parm_flag == 2)
-    desc = "class-scope";
-  else if (scope->is_for_scope)
-    desc = "for-scope";
-  else if (scope->is_try_scope)
-    desc = "try-scope";
-  else if (scope->is_catch_scope)
-    desc = "catch-scope";
-  else if (scope->template_spec_p)
-    desc = "template-explicit-spec-scope";
-  else if (scope->template_parms_p)
-    desc = "template-prototype-scope";
-  else
-    desc = "block-scope";
+  /* The order of this table must match the "scope_kind"
+     enumerators.  */
+  static const char* scope_kind_names[] = {
+    "block-scope",
+    "cleanup-scope",
+    "try-scope",
+    "catch-scope",
+    "for-scope",
+    "function-parameter-scope",
+    "class-scope",
+    "namespace-scope",
+    "template-parameter-scope",
+    "template-explicit-spec-scope"
+  };
+  const scope_kind kind = scope->explicit_spec_p
+    ? sk_template_spec : scope->kind;
 
-  return desc;
+  return scope_kind_names[kind];
 }
 
 /* Output a debugging information about SCOPE when performning
@@ -506,10 +477,27 @@
     verbatim ("%s %s %p %d\n", action, desc, (void *) scope, line);
 }
 
-/* Construct a scope that may be TAG-TRANSPARENT, the sub-blocks of
-   which may be KEPT.  */
-static inline cxx_scope *
-make_cxx_scope (bool tag_transparent, int keep)
+/* Return the estimated initial size of the hashtable of a NAMESPACE
+   scope.  */
+
+static inline size_t
+namespace_scope_ht_size (tree ns)
+{
+  tree name = DECL_NAME (ns);
+
+  return name == std_identifier
+    ? NAMESPACE_STD_HT_SIZE
+    : (name == global_scope_name
+       ? GLOBAL_SCOPE_HT_SIZE
+       : NAMESPACE_ORDINARY_HT_SIZE);
+}
+
+/* Create a new KIND scope and make it the top of the active scopes stack.
+   ENTITY is the scope of the associated C++ entity (namespace, class,
+   function); it is NULL otherwise.  */
+
+cxx_scope *
+begin_scope (scope_kind kind, tree entity)
 {
   cxx_scope *scope;
   
@@ -521,31 +509,62 @@
     }
   else
     scope = ggc_alloc (sizeof (cxx_scope));
-
   memset (scope, 0, sizeof (cxx_scope));
-  scope->tag_transparent = tag_transparent;
-  scope->keep = keep;
+
+  scope->this_entity = entity;
   scope->more_cleanups_ok = true;
+  switch (kind)
+    {
+    case sk_cleanup:
+      scope->keep = true;
+      break;
+      
+    case sk_template_spec:
+      scope->explicit_spec_p = true;
+      kind = sk_template_parms;
+      /* fall through */
+    case sk_template_parms:
+    case sk_block:
+    case sk_try:
+    case sk_catch:
+    case sk_for:
+    case sk_class:
+    case sk_function_parms:
+      scope->keep = keep_next_level_flag;
+      break;
 
-  return scope;
-}
+    case sk_namespace:
+      scope->type_decls = binding_table_new (namespace_scope_ht_size (entity));
+      NAMESPACE_LEVEL (entity) = scope;
+      VARRAY_TREE_INIT (scope->static_decls,
+                        DECL_NAME (entity) == std_identifier
+                        || DECL_NAME (entity) == global_scope_name
+                        ? 200 : 10,
+                        "Static declarations");
+      break;
 
-static void
-push_binding_level (cxx_scope *newlevel)
-{
-  /* Add this level to the front of the chain (stack) of levels that
-     are active.  */
-  newlevel->level_chain = current_binding_level;
-  current_binding_level = newlevel;
+    default:
+      /* Should not happen.  */
+      my_friendly_assert (false, 20030922);
+      break;
+    }
+  scope->kind = kind;
+
+  /* Add it to the front of currently active scopes stack.  */
+  scope->level_chain = current_binding_level;
+  current_binding_level = scope;
+  keep_next_level_flag = false;
 
   if (ENABLE_SCOPE_CHECKING)
     {
-      newlevel->binding_depth = binding_depth;
+      scope->binding_depth = binding_depth;
       indent (binding_depth);
-      cxx_scope_debug (newlevel, input_location.line, "push");
+      cxx_scope_debug (scope, input_location.line, "push");
       is_class_level = 0;
       binding_depth++;
     }
+
+  return scope;
 }
 
 /* Find the innermost enclosing class scope, and reset
@@ -556,9 +575,9 @@
 {
   struct cp_binding_level *level = current_binding_level;
 
-  while (level && level->parm_flag != 2)
+  while (level && level->kind != sk_class)
     level = level->level_chain;
-  if (level && level->parm_flag == 2)
+  if (level && level->kind == sk_class)
     class_binding_level = level;
   else
     class_binding_level = 0;
@@ -587,7 +606,7 @@
     register struct cp_binding_level *level = current_binding_level;
     current_binding_level = current_binding_level->level_chain;
     level->level_chain = free_binding_level;
-    if (level->parm_flag == 2)
+    if (level->kind == sk_class)
       level->type_decls = NULL;
     else
       binding_table_free (level->type_decls);
@@ -660,7 +679,7 @@
   struct cp_binding_level *b;
 
   b = current_binding_level;
-  while (b->parm_flag == 2)
+  while (b->kind == sk_class)
     b = b->level_chain;
 
   return b;
@@ -677,7 +696,7 @@
 {
   struct cp_binding_level *b = innermost_nonclass_level ();
 
-  return b->namespace_p || b->template_parms_p;
+  return b->kind == sk_namespace || b->kind == sk_template_parms;
 }
 
 /* Nonzero if this is a namespace scope, or if we are defining a class
@@ -689,15 +708,15 @@
 {
   struct cp_binding_level *b = innermost_nonclass_level ();
 
-  return b->namespace_p;
+  return b->kind == sk_namespace;
 }
 
-/* If KEEP is nonzero, make a BLOCK node for the next binding level,
+/* If KEEP is true, make a BLOCK node for the next binding level,
    unconditionally.  Otherwise, use the normal logic to decide whether
    or not to create a BLOCK.  */
 
 void
-keep_next_level (int keep)
+keep_next_level (bool keep)
 {
   keep_next_level_flag = keep;
 }
@@ -709,9 +728,17 @@
 {
   return (current_binding_level->blocks != NULL_TREE
 	  || current_binding_level->keep
+          || current_binding_level->kind == sk_cleanup
 	  || current_binding_level->names != NULL_TREE
-	  || (current_binding_level->type_decls != NULL
-	      && !current_binding_level->tag_transparent));
+	  || current_binding_level->type_decls != NULL);
+}
+
+/* Returns the kind of the innermost scope.  */
+
+scope_kind
+innermost_scope_kind (void)
+{
+  return current_binding_level->kind;
 }
 
 /* Returns nonzero if this scope was created to store template
@@ -720,7 +747,7 @@
 int
 template_parm_scope_p (void)
 {
-  return current_binding_level->template_parms_p;
+  return innermost_scope_kind () == sk_template_parms;
 }
 
 /* Returns the kind of template specialization we are currently
@@ -736,7 +763,9 @@
   struct cp_binding_level *b;
 
   /* Scan through the template parameter scopes.  */
-  for (b = current_binding_level; b->template_parms_p; b = b->level_chain)
+  for (b = current_binding_level; 
+       b->kind == sk_template_parms; 
+       b = b->level_chain)
     {
       /* If we see a specialization scope inside a parameter scope,
 	 then something is wrong.  That corresponds to a declaration
@@ -747,7 +776,7 @@
 	 which is always invalid since [temp.expl.spec] forbids the
 	 specialization of a class member template if the enclosing
 	 class templates are not explicitly specialized as well.  */
-      if (b->template_spec_p)
+      if (b->explicit_spec_p)
 	{
 	  if (n_template_parm_scopes == 0)
 	    innermost_specialization_p = 1;
@@ -817,20 +846,6 @@
   class_binding_level->class_shadowed = shadows;
 }
 
-/* Enter a new binding level.
-   If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
-   not for that of tags.  */
-
-void
-pushlevel (int tag_transparent)
-{
-  if (cfun && !doing_semantic_analysis_p ())
-    return;
-
-  push_binding_level (make_cxx_scope (tag_transparent, keep_next_level_flag));
-  keep_next_level_flag = 0;
-}
-
 /* We're defining an object of type TYPE.  If it needs a cleanup, but
    we're not allowed to add any more objects with cleanups to the current
    scope, create a new binding level.  */
@@ -841,50 +856,11 @@
   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
       && current_binding_level->more_cleanups_ok == 0)
     {
-      keep_next_level (2);
-      pushlevel (1);
+      begin_scope (sk_cleanup, NULL);
       clear_last_expr ();
       add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1);
     }
 }
-  
-/* Enter a new scope.  The KIND indicates what kind of scope is being
-   created.  */
-
-void
-begin_scope (scope_kind sk)
-{
-  pushlevel (0);
-
-  switch (sk)
-    {
-    case sk_block:
-      break;
-
-    case sk_try:
-      current_binding_level->is_try_scope = 1;
-      break;
-
-    case sk_catch:
-      current_binding_level->is_catch_scope = 1;
-      break;
-
-    case sk_for:
-      current_binding_level->is_for_scope = 1;
-      break;
-
-    case sk_template_spec:
-      current_binding_level->template_spec_p = 1;
-      /* Fall through.  */
-
-    case sk_template_parms:
-      current_binding_level->template_parms_p = 1;
-      break;
-
-    default:
-      abort ();
-    }
-}
 
 /* Exit the current scope.  */
 
@@ -912,82 +888,6 @@
   IDENTIFIER_BINDING (id) = binding;
 }
 
-/* ID is already bound in the current scope.  But, DECL is an
-   additional binding for ID in the same scope.  This is the `struct
-   stat' hack whereby a non-typedef class-name or enum-name can be
-   bound at the same level as some other kind of entity.  It's the
-   responsibility of the caller to check that inserting this name is
-   valid here.  Returns nonzero if the new binding was successful.  */
-
-int
-add_binding (cxx_binding *binding, tree decl)
-{
-  tree bval = BINDING_VALUE (binding);
-  int ok = 1;
-
-  timevar_push (TV_NAME_LOOKUP);
-  if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
-    /* The new name is the type name.  */
-    BINDING_TYPE (binding) = decl;
-  else if (!bval)
-    /* This situation arises when push_class_level_binding moves an
-       inherited type-binding out of the way to make room for a new
-       value binding.  */
-    BINDING_VALUE (binding) = decl;
-  else if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval))
-    {
-      /* The old binding was a type name.  It was placed in
-	 BINDING_VALUE because it was thought, at the point it was
-	 declared, to be the only entity with such a name.  Move the
-	 type name into the type slot; it is now hidden by the new
-	 binding.  */
-      BINDING_TYPE (binding) = bval;
-      BINDING_VALUE (binding) = decl;
-      INHERITED_VALUE_BINDING_P (binding) = 0;
-    }
-  else if (TREE_CODE (bval) == TYPE_DECL
-	   && TREE_CODE (decl) == TYPE_DECL
-	   && DECL_NAME (decl) == DECL_NAME (bval)
-	   && (same_type_p (TREE_TYPE (decl), TREE_TYPE (bval))
-	       /* If either type involves template parameters, we must
-		  wait until instantiation.  */
-	       || uses_template_parms (TREE_TYPE (decl))
-	       || uses_template_parms (TREE_TYPE (bval))))
-    /* We have two typedef-names, both naming the same type to have
-       the same name.  This is OK because of:
-
-         [dcl.typedef]
-
-	 In a given scope, a typedef specifier can be used to redefine
-	 the name of any type declared in that scope to refer to the
-	 type to which it already refers.  */
-    ok = 0;
-  /* There can be two block-scope declarations of the same variable,
-     so long as they are `extern' declarations.  However, there cannot
-     be two declarations of the same static data member:
-
-       [class.mem]
-
-       A member shall not be declared twice in the
-       member-specification.  */
-  else if (TREE_CODE (decl) == VAR_DECL && TREE_CODE (bval) == VAR_DECL
-	   && DECL_EXTERNAL (decl) && DECL_EXTERNAL (bval)
-	   && !DECL_CLASS_SCOPE_P (decl))
-    {
-      duplicate_decls (decl, BINDING_VALUE (binding));
-      ok = 0;
-    }
-  else
-    {
-      error ("declaration of `%#D'", decl);
-      cp_error_at ("conflicts with previous declaration `%#D'",
-		   BINDING_VALUE (binding));
-      ok = 0;
-    }
-
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok);
-}
-
 /* Add DECL to the list of things declared in B.  */
 
 static void
@@ -1014,7 +914,7 @@
       b->names_size++;
 
       /* If appropriate, add decl to separate list of statics */
-      if (b->namespace_p)
+      if (b->kind == sk_namespace)
 	if ((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
 	    || (TREE_CODE (decl) == FUNCTION_DECL
 		&& (!TREE_PUBLIC (decl) || DECL_DECLARED_INLINE_P (decl))))
@@ -1034,14 +934,12 @@
 
   /* Skip over any local classes.  This makes sense if we call
      push_local_binding with a friend decl of a local class.  */
-  b = current_binding_level;
-  while (b->parm_flag == 2)
-    b = b->level_chain;
+  b = innermost_nonclass_level ();
 
   if (lookup_name_current_level (id))
     {
       /* Supplement the existing binding.  */
-      if (!add_binding (IDENTIFIER_BINDING (id), decl))
+      if (!supplement_binding (IDENTIFIER_BINDING (id), decl))
 	/* It didn't work.  Something else must be bound at this
 	   level.  Do not add DECL to the list of things to pop
 	   later.  */
@@ -1080,7 +978,7 @@
 
   if (binding && BINDING_SCOPE (binding) == class_binding_level)
     /* Supplement the existing binding.  */
-    result = add_binding (IDENTIFIER_BINDING (id), decl);
+    result = supplement_binding (IDENTIFIER_BINDING (id), decl);
   else
     /* Create a new binding.  */
     push_binding (id, decl, class_binding_level);
@@ -1168,7 +1066,7 @@
 static void
 pop_label (tree label, tree old_value)
 {
-  if (!processing_template_decl && doing_semantic_analysis_p ())
+  if (!processing_template_decl)
     {
       if (DECL_INITIAL (label) == NULL_TREE)
 	{
@@ -1238,15 +1136,13 @@
   tree block = NULL_TREE;
   tree decl;
   int leaving_for_scope;
+  scope_kind kind;
 
   timevar_push (TV_NAME_LOOKUP);
-  if (cfun && !doing_semantic_analysis_p ())
-    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
 
-  my_friendly_assert (current_binding_level->parm_flag != 2,
-		      19990916);
+  my_friendly_assert (current_binding_level->kind != sk_class, 19990916);
 
-  real_functionbody = (current_binding_level->keep == 2
+  real_functionbody = (current_binding_level->kind == sk_cleanup
 		       ? ((functionbody = 0), tmp) : functionbody);
   subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
 
@@ -1258,7 +1154,7 @@
      rather than the end.  This hack is no longer used.  */
   my_friendly_assert (keep == 0 || keep == 1, 0);
 
-  if (current_binding_level->keep == 1)
+  if (current_binding_level->keep)
     keep = 1;
 
   /* Any uses of undefined labels, and any defined labels, now operate
@@ -1275,9 +1171,9 @@
 	    if (labels->binding_level == current_binding_level)
 	      {
 		tree decl;
-		if (current_binding_level->is_try_scope)
+		if (current_binding_level->kind == sk_try)
 		  labels->in_try_scope = 1;
-		if (current_binding_level->is_catch_scope)
+		if (current_binding_level->kind == sk_catch)
 		  labels->in_catch_scope = 1;
 		for (decl = labels->names_in_scope; decl;
 		     decl = TREE_CHAIN (decl))
@@ -1359,7 +1255,7 @@
      ended.  We only use the new rules if flag_new_for_scope is
      nonzero.  */
   leaving_for_scope
-    = current_binding_level->is_for_scope && flag_new_for_scope == 1;
+    = current_binding_level->kind == sk_for && flag_new_for_scope == 1;
 
   /* Remove declarations for all the DECLs in this level.  */
   for (link = decls; link; link = TREE_CHAIN (link))
@@ -1490,7 +1386,7 @@
       pop_labels (block);
     }
 
-  tmp = current_binding_level->keep;
+  kind = current_binding_level->kind;
 
   pop_binding_level ();
   if (functionbody)
@@ -1515,7 +1411,7 @@
     TREE_USED (block) = 1;
 
   /* Take care of compiler's internal binding structures.  */
-  if (tmp == 2)
+  if (kind == sk_cleanup)
     {
       tree scope_stmts;
 
@@ -1576,7 +1472,6 @@
 {
   /* The RTL expansion machinery requires us to provide this callback,
      but it is not applicable in function-at-a-time mode.  */
-  my_friendly_assert (cfun && !doing_semantic_analysis_p (), 20000911);
 }
 
 /* Do a pushlevel for class declarations.  */
@@ -1587,11 +1482,7 @@
   if (ENABLE_SCOPE_CHECKING)
     is_class_level = 1;
 
-  push_binding_level (make_cxx_scope (false, 0));
-
-  class_binding_level = current_binding_level;
-  class_binding_level->parm_flag = 2;
-  class_binding_level->this_entity = current_class_type;
+  class_binding_level = begin_scope (sk_class, current_class_type);
 }
 
 /* ...and a poplevel for class declarations.  */
@@ -1623,7 +1514,7 @@
       /* Find the next enclosing class, and recreate
 	 IDENTIFIER_CLASS_VALUEs appropriate for that class.  */
       b = level->level_chain;
-      while (b && b->parm_flag != 2)
+      while (b && b->kind != sk_class)
 	b = b->level_chain;
 
       if (b)
@@ -1898,8 +1789,6 @@
   tree t;
   int i = 0, len;
   fprintf (stderr, " blocks=" HOST_PTR_PRINTF, (void *) lvl->blocks);
-  if (lvl->tag_transparent)
-    fprintf (stderr, " tag-transparent");
   if (lvl->more_cleanups_ok)
     fprintf (stderr, " more-cleanups-ok");
   if (lvl->have_cleanups)
@@ -2005,32 +1894,17 @@
    the identifier is polymorphic, with three possible values:
    NULL_TREE, a list of "cxx_binding"s.  */
 
-
-/* Push the initial binding contour of NAMESPACE-scope.  Any subsequent
-   push of NS is actually a resume.  */
-static void
-initial_push_namespace_scope (tree ns)
-{
-  tree name = DECL_NAME (ns);
-  cxx_scope *scope;
-
-  pushlevel (0);
-  scope = current_binding_level;
-  scope->namespace_p = true;
-  scope->type_decls = binding_table_new (name == std_identifier
-                                         ? NAMESPACE_STD_HT_SIZE
-                                         : (name == global_scope_name
-                                            ? GLOBAL_SCOPE_HT_SIZE
-                                            : NAMESPACE_ORDINARY_HT_SIZE));
-  VARRAY_TREE_INIT (scope->static_decls,
-                    name == std_identifier || name == global_scope_name
-                    ? 200 : 10,
-                    "Static declarations");
-  scope->this_entity = ns;
-  NAMESPACE_LEVEL (ns) = scope;
-}
-
-
+/*
+ * Function: is_in_anonymous_namespace ()
+ *
+ * Description:
+ *  This function takes a GCC internal tree and determines whether it was
+ *  declared an anonymous namespace.
+ *
+ * Return value:
+ *  0 - This tree was not declared in an anonymous namespace.
+ *  1 - This tree was declared in an anonymous namespace.
+ */
 int is_in_anonymous_namespace(tree decl) {
   tree Context;
   if (decl && DECL_P(decl))
@@ -2062,9 +1936,8 @@
 }
 
 
-
-/* Push into the scope of the NAME namespace.  If NAME is NULL_TREE, then
-   we use the anonymous namespace.  */
+/* Push into the scope of the NAME namespace.  If NAME is NULL_TREE, then we
+   select a name that is unique to this compilation unit.  */
 
 void
 push_namespace (tree name)
@@ -2121,7 +1994,7 @@
       d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
       DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace);
       d = pushdecl (d);
-      initial_push_namespace_scope (d);
+      begin_scope (sk_namespace, d);
     }
   else
     resume_binding_level (NAMESPACE_LEVEL (d));
@@ -2282,13 +2155,13 @@
 	 inserted into namespace level, finish_file wouldn't find them
 	 when doing pending instantiations. Therefore, don't stop at
 	 namespace level, but continue until :: .  */
-      if (global_scope_p (b) || (pseudo && b->template_parms_p))
+      if (global_scope_p (b) || (pseudo && b->kind == sk_template_parms))
 	break;
 
       old_bindings = store_bindings (b->names, old_bindings);
       /* We also need to check class_shadowed to save class-level type
 	 bindings, since pushclass doesn't fill in b->names.  */
-      if (b->parm_flag == 2)
+      if (b->kind == sk_class)
 	old_bindings = store_bindings (b->class_shadowed, old_bindings);
 
       /* Unwind type-value slots back to top level.  */
@@ -2359,7 +2232,7 @@
 {
   tree type;
 
-  if (!b->namespace_p)
+  if (b->kind != sk_namespace)
     {
       /* Shadow the marker, not the real thing, so that the marker
 	 gets restored later.  */
@@ -2375,7 +2248,7 @@
       if (decl)
 	{
 	  if (BINDING_VALUE (binding))
-	    add_binding (binding, decl);
+	    supplement_binding (binding, decl);
 	  else
 	    BINDING_VALUE (binding) = decl;
 	}
@@ -2426,7 +2299,7 @@
     verbatim ("XXX entering pop_everything ()\n");
   while (!toplevel_bindings_p ())
     {
-      if (current_binding_level->parm_flag == 2)
+      if (current_binding_level->kind == sk_class)
 	pop_nested_class ();
       else
 	poplevel (0, 0, 0);
@@ -2482,8 +2355,8 @@
 	     friend case, push_template_decl will already have put the
 	     friend into global scope, if appropriate.  */
 	  if (TREE_CODE (type) != ENUMERAL_TYPE
-	      && !globalize && b->template_parms_p
-	      && b->level_chain->parm_flag == 2)
+	      && !globalize && b->kind == sk_template_parms
+	      && b->level_chain->kind == sk_class)
 	    {
 	      finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
 	      /* Put this UDT in the table of UDTs for the class, since
@@ -2567,7 +2440,7 @@
 }
 
 /* Push a tag name NAME for struct/class/union/enum type TYPE.
-   Normally put it into the inner-most non-tag-transparent scope,
+   Normally put it into the inner-most non-sk_cleanup scope,
    but if GLOBALIZE is true, put it in the inner-most non-class scope.
    The latter is needed for implicit declarations.  */
 
@@ -2578,8 +2451,8 @@
 
   timevar_push (TV_NAME_LOOKUP);
   b = current_binding_level;
-  while (b->tag_transparent
-	 || (b->parm_flag == 2
+  while (b->kind == sk_cleanup
+	 || (b->kind == sk_class
 	     && (globalize
 		 /* We may be defining a new type in the initializer
 		    of a static member variable. We allow this when
@@ -2616,8 +2489,9 @@
 	  if (!context)
 	    context = current_namespace;
 
-	  if ((b->template_parms_p && b->level_chain->parm_flag == 2)
-	      || b->parm_flag == 2)
+	  if (b->kind == sk_class
+	      || (b->kind == sk_template_parms 
+		  && b->level_chain->kind == sk_class))
 	    in_class = 1;
 
 	  if (current_lang_name == lang_name_java)
@@ -2631,7 +2505,7 @@
 	  d = maybe_process_template_type_declaration (type,
 						       globalize, b);
 
-	  if (b->parm_flag == 2)
+	  if (b->kind == sk_class)
 	    {
 	      if (!PROCESSING_REAL_TEMPLATE_DECL_P ())
 		/* Put this TYPE_DECL on the TYPE_FIELDS list for the
@@ -2661,14 +2535,12 @@
 	      && !processing_template_decl)
 	    VARRAY_PUSH_TREE (local_classes, type);
         }
-      if (b->parm_flag == 2)
+      if (b->kind == sk_class
+	  && !COMPLETE_TYPE_P (current_class_type))
 	{
-	  if (!COMPLETE_TYPE_P (current_class_type))
-	    {
-	      maybe_add_class_template_decl_list (current_class_type,
-						  type, /*friend_p=*/0);
-	      CLASSTYPE_NESTED_UTDS (current_class_type) = b->type_decls;
-	    }
+	  maybe_add_class_template_decl_list (current_class_type,
+					      type, /*friend_p=*/0);
+	  CLASSTYPE_NESTED_UTDS (current_class_type) = b->type_decls;
 	}
     }
 
@@ -2721,7 +2593,7 @@
     return;
 
   b = current_binding_level;
-  while (b->tag_transparent)
+  while (b->kind == sk_cleanup)
     b = b->level_chain;
   if (b->type_decls != NULL)
     binding_table_remove_anonymous_types (b->type_decls);
@@ -2851,7 +2723,8 @@
 
   if (TREE_CODE (newdecl) == TYPE_DECL
       || TREE_CODE (newdecl) == TEMPLATE_DECL
-      || TREE_CODE (newdecl) == CONST_DECL)
+      || TREE_CODE (newdecl) == CONST_DECL
+      || TREE_CODE (newdecl) == NAMESPACE_DECL)
     return;
 
   /* Don't get confused by static member functions; that's a different
@@ -2922,19 +2795,18 @@
 	       && DECL_UNINLINABLE (olddecl)
 	       && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
 	{
-	  warning ("%Hfunction '%D' redeclared as inline",
-                   &DECL_SOURCE_LOCATION (newdecl), newdecl);
-	  warning ("%Hprevious declaration of '%D' with attribute noinline",
-                   &DECL_SOURCE_LOCATION (olddecl), olddecl);
+	  warning ("%Jfunction '%D' redeclared as inline", newdecl, newdecl);
+	  warning ("%Jprevious declaration of '%D' with attribute noinline",
+                   olddecl, olddecl);
 	}
       else if (DECL_DECLARED_INLINE_P (olddecl)
 	       && DECL_UNINLINABLE (newdecl)
 	       && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
 	{
-	  warning ("%Hfunction '%D' redeclared with attribute noinline",
-                   &DECL_SOURCE_LOCATION (newdecl), newdecl);
-	  warning ("%Hprevious declaration of '%D' was inline",
-                   &DECL_SOURCE_LOCATION (olddecl), olddecl);
+	  warning ("%Jfunction '%D' redeclared with attribute noinline",
+		   newdecl, newdecl);
+	  warning ("%Jprevious declaration of '%D' was inline",
+		   olddecl, olddecl);
 	}
     }
 
@@ -2979,9 +2851,9 @@
           if (DECL_ANTICIPATED (olddecl))
             ;  /* Do nothing yet.  */
 	  else if ((DECL_EXTERN_C_P (newdecl)
-	       && DECL_EXTERN_C_P (olddecl))
-	      || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
-			    TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
+		    && DECL_EXTERN_C_P (olddecl))
+		   || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
+				 TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
 	    {
 	      /* A near match; override the builtin.  */
 
@@ -3010,6 +2882,10 @@
       else if (DECL_ANTICIPATED (olddecl))
 	TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
 
+      /* Whether or not the builtin can throw exceptions has no
+	 bearing on this declarator.  */
+      TREE_NOTHROW (olddecl) = 0;
+
       if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
 	{
 	  /* If a builtin function is redeclared as `static', merge
@@ -3119,8 +2995,10 @@
       else if (current_class_type == NULL_TREE
 	  || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
 	{
-	  error ("conflicting types for `%#D'", newdecl);
-	  cp_error_at ("previous declaration as `%#D'", olddecl);
+	  error ("conflicting declaration '%#D'", newdecl);
+	  cp_error_at ("'%D' has a previous declaration as `%#D'",
+                       olddecl, olddecl);
+          return false;
 	}
     }
   else if (TREE_CODE (newdecl) == FUNCTION_DECL
@@ -3174,8 +3052,7 @@
 	{
 	  /* Prototype decl follows defn w/o prototype.  */
 	  cp_warning_at ("prototype for `%#D'", newdecl);
-	  warning ("%Hfollows non-prototype definition here",
-		   &DECL_SOURCE_LOCATION (olddecl));
+	  warning ("%Jfollows non-prototype definition here", olddecl);
 	}
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
 	       && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
@@ -3230,10 +3107,8 @@
 	      && ! DECL_DECLARED_INLINE_P (olddecl)
 	      && TREE_ADDRESSABLE (olddecl) && warn_inline)
 	    {
-	      warning ("`%#D' was used before it was declared inline",
-			  newdecl);
-	      warning ("%Hprevious non-inline declaration here",
-		       &DECL_SOURCE_LOCATION (olddecl));
+	      warning ("`%#D' was used before it was declared inline", newdecl);
+	      warning ("%Jprevious non-inline declaration here", olddecl);
 	    }
 	}
     }
@@ -3679,10 +3554,6 @@
   int need_new_binding;
 
   timevar_push (TV_NAME_LOOKUP);
-  /* We shouldn't be calling pushdecl when we're generating RTL for a
-     function that we already did semantic analysis on previously.  */
-  my_friendly_assert (!cfun || doing_semantic_analysis_p (),
-		      19990913);
 
   need_new_binding = 1;
 
@@ -4063,10 +3934,10 @@
 		  b = b->level_chain;
 
 		  /* ARM $8.3 */
-		  if (b->parm_flag == 1)
+		  if (b->kind == sk_function_parms)
 		    {
 		      error ("declaration of `%#D' shadows a parameter",
-				name);
+			     name);
 		      err = true;
 		    }
 		}
@@ -4127,7 +3998,7 @@
 
   timevar_push (TV_NAME_LOOKUP);
   current_function_decl = NULL_TREE;
-  if (level->parm_flag == 2)
+  if (level->kind == sk_class)
     {
       b = class_binding_level;
       class_binding_level = level;
@@ -4694,9 +4565,6 @@
   tree decl;
 
   decl = build_decl (LABEL_DECL, id, void_type_node);
-  if (expanding_p)
-    /* Make sure every label has an rtx.  */
-    label_rtx (decl);
 
   DECL_CONTEXT (decl) = current_function_decl;
   DECL_MODE (decl) = VOIDmode;
@@ -4865,7 +4733,7 @@
 
       if (b == level)
 	break;
-      if ((b->is_try_scope || b->is_catch_scope) && ! saw_eh)
+      if ((b->kind == sk_try || b->kind == sk_catch) && ! saw_eh)
 	{
 	  if (! identified)
 	    {
@@ -4878,7 +4746,7 @@
 		pedwarn ("%H  from here", locus);
 	      identified = 1;
 	    }
-	  if (b->is_try_scope)
+	  if (b->kind == sk_try)
 	    error ("  enters try block");
 	  else
 	    error ("  enters catch block");
@@ -4970,7 +4838,7 @@
 
       if (u > 1 && DECL_ARTIFICIAL (b))
 	/* Can't skip init of __exception_info.  */
-	error ("%H  enters catch block", &DECL_SOURCE_LOCATION (b));
+	error ("%J  enters catch block", b);
       else if (u > 1)
 	cp_error_at ("  skips initialization of `%#D'", b);
       else
@@ -4984,8 +4852,7 @@
 }
 
 /* Define a label, specifying the location in the source file.
-   Return the LABEL_DECL node for the label, if the definition is valid.
-   Otherwise return 0.  */
+   Return the LABEL_DECL node for the label.  */
 
 tree
 define_label (location_t location, tree name)
@@ -5001,17 +4868,16 @@
 
   /* After labels, make any new cleanups in the function go into their
      own new (temporary) binding contour.  */
-  for (p = current_binding_level; !(p->parm_flag); p = p->level_chain)
+  for (p = current_binding_level; 
+       p->kind != sk_function_parms; 
+       p = p->level_chain)
     p->more_cleanups_ok = 0;
 
   if (name == get_identifier ("wchar_t"))
     pedwarn ("label named wchar_t");
 
   if (DECL_INITIAL (decl) != NULL_TREE)
-    {
-      error ("duplicate label `%D'", decl);
-      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
-    }
+    error ("duplicate label `%D'", decl);
   else
     {
       /* Mark label as having been defined.  */
@@ -5024,9 +4890,10 @@
 	  ent->binding_level = current_binding_level;
 	}
       check_previous_gotos (decl);
-      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
     }
+
   timevar_pop (TV_NAME_LOOKUP);
+  return decl;
 }
 
 struct cp_switch
@@ -5118,7 +4985,9 @@
 
   /* After labels, make any new cleanups in the function go into their
      own new (temporary) binding contour.  */
-  for (p = current_binding_level; !(p->parm_flag); p = p->level_chain)
+  for (p = current_binding_level; 
+       p->kind != sk_function_parms; 
+       p = p->level_chain)
     p->more_cleanups_ok = 0;
 
   return r;
@@ -5198,7 +5067,7 @@
    return the structure (or union or enum) definition for that name.
    Searches binding levels from BINDING_SCOPE up to the global level.
    If THISLEVEL_ONLY is nonzero, searches only the specified context
-   (but skips any tag-transparent contexts to find one that is
+   (but skips any sk_cleanup contexts to find one that is
    meaningful for tags).
    FORM says which kind of type the caller wants;
    it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
@@ -5227,7 +5096,7 @@
           if (type != NULL)
             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
         }
-      else if (level->namespace_p)
+      else if (level->kind == sk_namespace)
 	/* Do namespace lookup.  */
 	for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
 	  {
@@ -5286,9 +5155,9 @@
               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->type);
             }
 	  }
-      if (thislevel_only && ! level->tag_transparent)
+      if (thislevel_only && level->kind != sk_cleanup)
 	{
-	  if (level->template_parms_p && allow_template_parms_p)
+	  if (level->kind == sk_template_parms && allow_template_parms_p)
 	    {
 	      /* We must deal with cases like this:
 
@@ -5751,7 +5620,7 @@
 
       /* Add all _DECLs seen through local using-directives.  */
       for (level = current_binding_level;
-	   !level->namespace_p;
+	   level->kind != sk_namespace;
 	   level = level->level_chain)
 	if (!lookup_using_namespace (name, &binding, level->using_directives,
                                      scope, flags, spacesp))
@@ -5936,7 +5805,7 @@
       struct cp_binding_level *level;
 
       for (level = current_binding_level; 
-	   level && !level->namespace_p; 
+	   level && level->kind != sk_namespace;
 	   level = level->level_chain)
 	{
 	  tree class_type;
@@ -5944,7 +5813,7 @@
 	  
 	  /* A conversion operator can only be declared in a class 
 	     scope.  */
-	  if (level->parm_flag != 2)
+	  if (level->kind != sk_class)
 	    continue;
 	  
 	  /* Lookup the conversion operator in the class.  */
@@ -6034,11 +5903,9 @@
   tree t = NULL_TREE;
 
   timevar_push (TV_NAME_LOOKUP);
-  b = current_binding_level;
-  while (b->parm_flag == 2)
-    b = b->level_chain;
+  b = innermost_nonclass_level ();
 
-  if (b->namespace_p)
+  if (b->kind == sk_namespace)
     {
       t = IDENTIFIER_NAMESPACE_VALUE (name);
 
@@ -6054,7 +5921,7 @@
 	  if (BINDING_SCOPE (IDENTIFIER_BINDING (name)) == b)
 	    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name));
 
-	  if (b->keep == 2)
+	  if (b->kind == sk_cleanup)
 	    b = b->level_chain;
 	  else
 	    break;
@@ -6072,7 +5939,8 @@
   register tree t = NULL_TREE;
 
   timevar_push (TV_NAME_LOOKUP);
-  my_friendly_assert (! current_binding_level->namespace_p, 980716);
+  my_friendly_assert (current_binding_level->kind != sk_namespace, 
+		      980716);
 
   if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
       && REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node)
@@ -6083,7 +5951,7 @@
 	  if (purpose_member (name, b->type_shadowed))
 	    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
                                     REAL_IDENTIFIER_TYPE_VALUE (name));
-	  if (b->keep == 2)
+	  if (b->kind == sk_cleanup)
 	    b = b->level_chain;
 	  else
 	    break;
@@ -6094,6 +5962,19 @@
 }
 
 
+
+/* A chain of TYPE_DECLs for the builtin types.  */
+
+static GTY(()) tree builtin_type_decls;
+
+/* Return a chain of TYPE_DECLs for the builtin types.  */
+
+tree
+cxx_builtin_type_decls ()
+{
+  return builtin_type_decls;
+}
+
 /* Push the declarations of builtin types into the namespace.
    RID_INDEX is the index of the builtin type in the array
    RID_POINTERS.  NAME is the name used when looking up the builtin
@@ -6121,8 +6002,7 @@
     {
       tdecl = build_decl (TYPE_DECL, tname, type);
       DECL_ARTIFICIAL (tdecl) = 1;
-      if (tname)
-	SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
+      SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
     }
   if (rname)
     {
@@ -6136,6 +6016,12 @@
 
   if (!TYPE_NAME (type))
     TYPE_NAME (type) = tdecl;
+
+  if (tdecl)
+    {
+      TREE_CHAIN (tdecl) = builtin_type_decls;
+      builtin_type_decls = tdecl;
+    }
 }
 
 /* Record one of the standard Java types.
@@ -6266,7 +6152,7 @@
   my_friendly_assert (global_namespace == NULL_TREE, 375);
   global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
                                       void_type_node);
-  initial_push_namespace_scope (global_namespace);
+  begin_scope (sk_namespace, global_namespace);
 
   current_lang_name = NULL_TREE;
 
@@ -6504,7 +6390,7 @@
   if (current_function_decl)
     {
       struct cp_binding_level *b = current_binding_level;
-      while (b->level_chain->parm_flag == 0)
+      while (b->level_chain->kind != sk_function_parms)
 	b = b->level_chain;
       pushdecl_with_scope (decl, b);
     }	
@@ -6548,9 +6434,13 @@
   if (libname)
     SET_DECL_ASSEMBLER_NAME (decl, get_identifier (libname));
   if (EMIT_LLVM)
+  {
     llvm_make_decl_llvm(decl, NULL);
+  }
   else
+  {
     make_decl_rtl (decl, NULL);
+  }
 
   /* Warn if a function in the namespace for users
      is used without an occasion to consider it declared.  */
@@ -6742,8 +6632,8 @@
 
   /* ISO C++ 9.5.3.  Anonymous unions may not have function members.  */
   if (TYPE_METHODS (t))
-    error ("%Han anonymous union cannot have function members",
-	   &DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (t)));
+    error ("%Jan anonymous union cannot have function members",
+	   TYPE_MAIN_DECL (t));
 
   /* Anonymous aggregates cannot have fields with ctors, dtors or complex
      assignment operators (because they cannot have these methods themselves).
@@ -7076,8 +6966,7 @@
       && DECL_DECLARED_INLINE_P (decl)
       && DECL_UNINLINABLE (decl)
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
-    warning ("%Hinline function '%D' given attribute noinline",
-             &DECL_SOURCE_LOCATION (decl), decl);
+    warning ("%Jinline function '%D' given attribute noinline", decl, decl);
 
   if (context && COMPLETE_TYPE_P (complete_type (context)))
     {
@@ -7228,14 +7117,18 @@
     DECL_INITIAL (decl) = NULL_TREE;
 }
 
-/* Handle initialization of references.
-   These three arguments are from `cp_finish_decl', and have the
-   same meaning here that they do there.
+/* Handle initialization of references.  DECL, TYPE, and INIT have the
+   same meaning as in cp_finish_decl.  *CLEANUP must be NULL on entry,
+   but will be set to a new CLEANUP_STMT if a temporary is created
+   that must be destroeyd subsequently.
+
+   Returns an initializer expression to use to initialize DECL, or
+   NULL if the initialization can be performed statically.
 
    Quotes on semantics can be found in ARM 8.4.3.  */
 
 static tree
-grok_reference_init (tree decl, tree type, tree init)
+grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
 {
   tree tmp;
 
@@ -7272,7 +7165,7 @@
      DECL_INITIAL for local references (instead assigning to them
      explicitly); we need to allow the temporary to be initialized
      first.  */
-  tmp = initialize_reference (type, init, decl);
+  tmp = initialize_reference (type, init, decl, cleanup);
 
   if (tmp == error_mark_node)
     return NULL_TREE;
@@ -7442,8 +7335,8 @@
 	      TREE_PUBLIC (decl) = 0;
 	      DECL_COMMON (decl) = 0;
 	      cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
-	      warning ("%H  you can work around this by removing the initializer",
-		       &DECL_SOURCE_LOCATION (decl));
+	      warning ("%J  you can work around this by removing the initializer",
+		       decl);
 	    }
 	}
     }
@@ -7692,13 +7585,14 @@
 }
 
 /* Verify INIT (the initializer for DECL), and record the
-   initialization in DECL_INITIAL, if appropriate.  
+   initialization in DECL_INITIAL, if appropriate.  CLEANUP is as for
+   grok_reference_init.
 
    If the return value is non-NULL, it is an expression that must be
    evaluated dynamically to initialize DECL.  */
 
 static tree
-check_initializer (tree decl, tree init, int flags)
+check_initializer (tree decl, tree init, int flags, tree *cleanup)
 {
   tree type = TREE_TYPE (decl);
 
@@ -7748,7 +7642,7 @@
       init = NULL_TREE;
     }
   else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
-    init = grok_reference_init (decl, type, init);
+    init = grok_reference_init (decl, type, init, cleanup);
   else if (init)
     {
       if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
@@ -7951,7 +7845,7 @@
       return;
     }
 
-  if (current_binding_level->is_for_scope)
+  if (current_binding_level->kind == sk_for)
     {
       struct cp_binding_level *outer
 	= current_binding_level->level_chain;
@@ -7974,7 +7868,7 @@
 	{
 	  BINDING_VALUE (outer_binding)
 	    = DECL_SHADOWED_FOR_VAR (BINDING_VALUE (outer_binding));
-	  current_binding_level->is_for_scope = 0;
+	  current_binding_level->kind = sk_block;
 	}
     }
   timevar_pop (TV_NAME_LOOKUP);
@@ -8055,8 +7949,9 @@
 void
 cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
 {
-  register tree type;
+  tree type;
   tree ttype = NULL_TREE;
+  tree cleanup;
   const char *asmspec = NULL;
   int was_readonly = 0;
 
@@ -8069,6 +7964,9 @@
 
   my_friendly_assert (TREE_CODE (decl) != RESULT_DECL, 20030619);
 
+  /* Assume no cleanup is required.  */
+  cleanup = NULL_TREE;
+
   /* If a name was specified, get the string.  */
   if (global_scope_p (current_binding_level))
     asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
@@ -8184,7 +8082,7 @@
 	     is *not* defined.  */
 	  && (!DECL_EXTERNAL (decl) || init))
 	{
-	  init = check_initializer (decl, init, flags);
+	  init = check_initializer (decl, init, flags, &cleanup);
 	  /* Thread-local storage cannot be dynamically initialized.  */
 	  if (DECL_THREAD_LOCAL (decl) && init)
 	    {
@@ -8263,8 +8161,7 @@
 	  if (DECL_FUNCTION_SCOPE_P (decl))
 	    {
 	      /* This is a local declaration.  */
-	      if (doing_semantic_analysis_p ())
-		maybe_inject_for_scope_var (decl);
+	      maybe_inject_for_scope_var (decl);
 	      /* Initialize the local variable.  */
 	      if (processing_template_decl)
 		{
@@ -8300,6 +8197,11 @@
       }
     }
 
+  /* If a CLEANUP_STMT was created to destroy a temporary bound to a
+     reference, insert it in the statement-tree now.  */
+  if (cleanup)
+    add_stmt (cleanup);
+
  finish_end:
 
   if (was_readonly)
@@ -11173,8 +11075,7 @@
 	{
 	  decl = build_decl (TYPE_DECL, declarator, type);
 	  if (in_namespace || ctype)
-	    error ("%Htypedef name may not be a nested-name-specifier",
-		   &DECL_SOURCE_LOCATION (decl));
+	    error ("%Jtypedef name may not be a nested-name-specifier", decl);
 	  if (!current_function_decl)
 	    DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
 	}
@@ -11220,8 +11121,8 @@
 	  if (ctype == NULL_TREE)
 	    {
 	      if (TREE_CODE (type) != METHOD_TYPE)
-		error ("%Hinvalid type qualifier for non-member function type",
-		       &DECL_SOURCE_LOCATION (decl));
+		error ("%Jinvalid type qualifier for non-member function type",
+		       decl);
 	      else
 		ctype = TYPE_METHOD_BASETYPE (type);
 	    }
@@ -13057,8 +12958,7 @@
   if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
     {
       error ("multiple definition of `%#T'", enumtype);
-      error ("%Hprevious definition here",
-	     &DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (enumtype)));
+      error ("%Jprevious definition here", TYPE_MAIN_DECL (enumtype));
       /* Clear out TYPE_VALUES, and start again.  */
       TYPE_VALUES (enumtype) = NULL_TREE;
     }
@@ -13500,8 +13400,7 @@
 
   if (DECL_DECLARED_INLINE_P (decl1)
       && lookup_attribute ("noinline", attrs))
-    warning ("%Hinline function '%D' given attribute noinline",
-             &DECL_SOURCE_LOCATION (decl1), decl1);
+    warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
 
   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
     /* This is a constructor, we must ensure that any default args
@@ -13595,7 +13494,7 @@
      CFUN set up, and our per-function variables initialized.
      FIXME factor out the non-RTL stuff.  */
   bl = current_binding_level;
-  init_function_start (decl1);
+  allocate_struct_function (decl1);
   current_binding_level = bl;
 
   /* Even though we're inside a function body, we still don't want to
@@ -13744,8 +13643,7 @@
 	DECL_INTERFACE_KNOWN (decl1) = 1;
     }
 
-  pushlevel (0);
-  current_binding_level->parm_flag = 1;
+  begin_scope (sk_function_parms, decl1);
 
   ++function_depth;
 
@@ -13866,9 +13764,6 @@
   f->bindings = NULL;
   f->x_local_names = NULL;
 
-  /* When we get back here again, we will be expanding.  */
-  f->x_expanding_p = 1;
-
   /* If we've already decided that we cannot inline this function, we
      must remember that fact when we actually go to expand the
      function.  */
@@ -14000,7 +13895,7 @@
     /* 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);
+    keep_next_level (true);
 
   stmt = begin_compound_stmt (/*has_no_scope=*/false);
   COMPOUND_STMT_BODY_BLOCK (stmt) = 1;
@@ -14120,7 +14015,7 @@
   /* If the current binding level isn't the outermost binding level
      for this function, either there is a bug, or we have experienced
      syntax errors and the statement tree is malformed.  */
-  if (current_binding_level->parm_flag != 1)
+  if (current_binding_level->kind != sk_function_parms)
     {
       /* Make sure we have already experienced errors.  */
       if (errorcount == 0)
@@ -14130,9 +14025,9 @@
          levels.  */
       DECL_SAVED_TREE (fndecl) = build_stmt (COMPOUND_STMT, NULL_TREE);
 
-      while (current_binding_level->parm_flag != 1)
+      while (current_binding_level->kind != sk_function_parms)
 	{
-	  if (current_binding_level->parm_flag == 2)
+	  if (current_binding_level->kind == sk_class)
 	    pop_nested_class ();
 	  else
 	    poplevel (0, 0, 0);
@@ -14140,6 +14035,10 @@
     }
   poplevel (1, 0, 1);
 
+  /* Statements should always be full-expressions at the outermost set
+     of curly braces for a function.  */
+  my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
+
   /* Set up the named return value optimization, if we can.  Here, we
      eliminate the copy from the nrv into the RESULT_DECL and any cleanup
      for the nrv.  genrtl_start_function and declare_return_variable
@@ -14152,7 +14051,7 @@
       if (r != error_mark_node
 	  /* This is only worth doing for fns that return in memory--and
 	     simpler, since we don't have to worry about promoted modes.  */
-	  && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)))
+	  && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)), fndecl)
 	  /* Only allow this for variables declared in the outer scope of
 	     the function so we know that their lifetime always ends with a
 	     return; see g++.dg/opt/nrv6.C.  We could be more flexible if
@@ -14210,13 +14109,11 @@
 	 inline function, as we might never be compiled separately.  */
       && (DECL_INLINE (fndecl) || processing_template_decl))
     warning ("no return statement in function returning non-void");
-    
-  /* Clear out memory we no longer need.  */
-  free_after_parsing (cfun);
-  /* Since we never call rest_of_compilation, we never clear
-     CFUN.  Do so explicitly.  */
-  free_after_compilation (cfun);
+
+  /* We're leaving the context of this function, so zap cfun.  It's still in
+     DECL_SAVED_INSNS, and we'll restore it in tree_rest_of_compilation.  */
   cfun = NULL;
+  current_function_decl = NULL;
 
   /* If this is an in-class inline definition, we may have to pop the
      bindings for the template parameters that we added in
@@ -14323,8 +14220,7 @@
   cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0);
 
   /* Make a place for the parms */
-  pushlevel (0);
-  current_binding_level->parm_flag = 1;
+  begin_scope (sk_function_parms, fndecl);
 
   DECL_IN_AGGR_P (fndecl) = 1;
   return fndecl;
@@ -14528,13 +14424,34 @@
     = ggc_alloc_cleared (sizeof (struct language_function));
   f->language = p;
 
-  /* It takes an explicit call to expand_body to generate RTL for a
-     function.  */
-  expanding_p = 0;
-
   /* Whenever we start a new function, we destroy temporaries in the
      usual way.  */
   current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+
+  if (f->decl)
+    {
+      tree fn = f->decl;
+
+      current_function_is_thunk = DECL_THUNK_P (fn);
+
+      if (DECL_SAVED_FUNCTION_DATA (fn))
+	{
+	  /* If we already parsed this function, and we're just expanding it
+	     now, restore saved state.  */
+	  *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
+
+	  /* If we decided that we didn't want to inline this function,
+	     make sure the back-end knows that.  */
+	  if (!current_function_cannot_inline)
+	    current_function_cannot_inline = cp_function_chain->cannot_inline;
+
+	  /* 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;
+	}
+    }
 }
 
 /* Free the language-specific parts of F, now that we've finished


Index: gcc-3.4/gcc/cp/decl2.c
diff -u gcc-3.4/gcc/cp/decl2.c:1.2 gcc-3.4/gcc/cp/decl2.c:1.3
--- gcc-3.4/gcc/cp/decl2.c:1.2	Thu Jan  8 17:05:28 2004
+++ gcc-3.4/gcc/cp/decl2.c	Thu Feb  5 10:05:46 2004
@@ -467,8 +467,8 @@
       expr = build_array_ref (array_expr, index_exp);
     }
   if (processing_template_decl && expr != error_mark_node)
-    return build_min (ARRAY_REF, TREE_TYPE (expr), orig_array_expr, 
-		      orig_index_exp);
+    return build_min_non_dep (ARRAY_REF, expr,
+			      orig_array_expr, orig_index_exp);
   return expr;
 }
 
@@ -1625,6 +1625,17 @@
     }
 }
 
+/* Return true if VAR has already been provided to the back end; in that
+   case VAR should not be modified further by the front end.  */
+static bool
+var_finalized_p (tree var)
+{
+  if (flag_unit_at_a_time)
+    return cgraph_varpool_node (var)->finalized;
+  else
+    return TREE_ASM_WRITTEN (var);
+}
+
 /* If necessary, write out the vtables for the dynamic class CTYPE.
    Returns true if any vtables were emitted.  */
 
@@ -1638,7 +1649,7 @@
   /* If the vtables for this class have already been emitted there is
      nothing more to do.  */
   primary_vtbl = CLASSTYPE_VTABLES (ctype);
-  if (TREE_ASM_WRITTEN (primary_vtbl))
+  if (var_finalized_p (primary_vtbl))
     return false;
   /* Ignore dummy vtables made by get_vtable_decl.  */
   if (TREE_TYPE (primary_vtbl) == void_type_node)
@@ -2462,7 +2473,7 @@
   tree v;
 
   for (v = vars; v; v = TREE_CHAIN (v))
-    if (! TREE_ASM_WRITTEN (TREE_VALUE (v)))
+    if (!var_finalized_p (TREE_VALUE (v)))
       rest_of_decl_compilation (TREE_VALUE (v), 0, 1, 1);
 }
 
@@ -2563,63 +2574,30 @@
   return 0;
 }
 
-/* Callgraph code does not understand the member pointers.  Mark the methods
-   referenced as used.  */
-static tree
-mark_member_pointers_and_eh_handlers (tree *tp,
-				      int *walk_subtrees,
-		      		      void *data ATTRIBUTE_UNUSED)
+/* Called via LANGHOOK_CALLGRAPH_ANALYZE_EXPR.  It is supposed to mark
+   decls referenced from frontend specific constructs; it will be called
+   only for language-specific tree nodes.
+
+   Here we must deal with member pointers.  */
+
+tree
+cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+			    tree from ATTRIBUTE_UNUSED)
 {
-  /* Avoid useless walking of complex type and declaration nodes.  */
-  if (TYPE_P (*tp) || DECL_P (*tp))
-    {
-      *walk_subtrees = 0;
-      return 0;
-    }
-  switch (TREE_CODE (*tp))
+  tree t = *tp;
+
+  switch (TREE_CODE (t))
     {
     case PTRMEM_CST:
-      if (TYPE_PTRMEMFUNC_P (TREE_TYPE (*tp)))
-	cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (*tp)), 1);
+      if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
+	cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
       break;
 
-    /* EH handlers will emit EH tables referencing typeinfo.  */
-    case HANDLER:
-      if (HANDLER_TYPE (*tp))
-	{
-	  tree tinfo = eh_type_info (HANDLER_TYPE (*tp));
-
-	  cgraph_varpool_mark_needed_node (cgraph_varpool_node (tinfo));
-	}
-      break;
-
-    case EH_SPEC_BLOCK:
-	{
-	  tree type;
-
-	  for (type = EH_SPEC_RAISES ((*tp)); type;
-	       type = TREE_CHAIN (type))
-	    {
-	       tree tinfo = eh_type_info (TREE_VALUE (type));
-
-	       cgraph_varpool_mark_needed_node (cgraph_varpool_node (tinfo));
-	    }
-	}
-      break;
     default:
       break;
     }
-  return 0;
-}
 
-/* Called via LANGHOOK_CALLGRAPH_LOWER_FUNCTION.  It is supposed to lower
-   frontend specific constructs that would otherwise confuse the middle end.  */
-void
-lower_function (tree fn)
-{
-  walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
-		  		mark_member_pointers_and_eh_handlers,
-				NULL);
+  return NULL;
 }
 
 /* This routine is called from the last rule in yyparse ().
@@ -2737,12 +2715,12 @@
   	 them to the beginning of the array, then get rid of the
   	 leftovers.  */
       n_new = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) - n_old;
-      memmove (&VARRAY_TREE (unemitted_tinfo_decls, 0),
-  	       &VARRAY_TREE (unemitted_tinfo_decls, n_old),
-  	       n_new * sizeof (tree));
+      if (n_new)
+	memmove (&VARRAY_TREE (unemitted_tinfo_decls, 0),
+		 &VARRAY_TREE (unemitted_tinfo_decls, n_old),
+		 n_new * sizeof (tree));
       memset (&VARRAY_TREE (unemitted_tinfo_decls, n_new),
-  	      0,
-  	      n_old * sizeof (tree));
+  	      0, n_old * sizeof (tree));
       VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) = n_new;
 
       /* The list of objects with static storage duration is built up
@@ -2885,7 +2863,7 @@
       for (i = 0; i < pending_statics_used; ++i) 
 	{
 	  tree decl = VARRAY_TREE (pending_statics, i);
-	  if (TREE_ASM_WRITTEN (decl))
+	  if (var_finalized_p (decl))
 	    continue;
 	  import_export_decl (decl);
 	  if (DECL_NOT_REALLY_EXTERN (decl) && ! DECL_IN_AGGR_P (decl))
@@ -2895,6 +2873,9 @@
 	  && wrapup_global_declarations (&VARRAY_TREE (pending_statics, 0),
 					 pending_statics_used))
 	reconsider = true;
+
+      if (cgraph_assemble_pending_functions ())
+	reconsider = true;
     } 
   while (reconsider);
 
@@ -3039,7 +3020,7 @@
 
   expr = build_function_call (fn, args);
   if (processing_template_decl && expr != error_mark_node)
-    return build_min (CALL_EXPR, TREE_TYPE (expr), orig_fn, orig_args);
+    return build_min_non_dep (CALL_EXPR, expr, orig_fn, orig_args);
   return expr;
 }
 
@@ -3253,10 +3234,8 @@
       if (flags & LOOKUP_COMPLAIN)
         {
           error ("`%D' denotes an ambiguous type",name);
-          error ("%H  first type here",
-		 &DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (BINDING_TYPE (old))));
-          error ("%H  other type here",
-		 &DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)));
+          error ("%J  first type here", TYPE_MAIN_DECL (BINDING_TYPE (old)));
+          error ("%J  other type here", TYPE_MAIN_DECL (type));
         }
     }
   return old;
@@ -3509,6 +3488,8 @@
   /* We must find only functions, or exactly one non-function.  */
   if (!k->functions) 
     k->functions = fn;
+  else if (fn == k->functions)
+    ;
   else if (is_overloaded_fn (k->functions) && is_overloaded_fn (fn))
     k->functions = build_overload (fn, k->functions);
   else


Index: gcc-3.4/gcc/cp/method.c
diff -u gcc-3.4/gcc/cp/method.c:1.2 gcc-3.4/gcc/cp/method.c:1.3
--- gcc-3.4/gcc/cp/method.c:1.2	Thu Jan  8 17:05:28 2004
+++ gcc-3.4/gcc/cp/method.c	Thu Feb  5 10:05:46 2004
@@ -431,6 +431,7 @@
 	  tree x = copy_node (a);
 	  TREE_CHAIN (x) = t;
 	  DECL_CONTEXT (x) = thunk_fndecl;
+	  SET_DECL_RTL (x, NULL_RTX);
 	  t = x;
 	}
       a = nreverse (t);


Index: gcc-3.4/gcc/cp/pt.c
diff -u gcc-3.4/gcc/cp/pt.c:1.2 gcc-3.4/gcc/cp/pt.c:1.3
--- gcc-3.4/gcc/cp/pt.c:1.2	Thu Jan  8 17:05:28 2004
+++ gcc-3.4/gcc/cp/pt.c	Thu Feb  5 10:05:47 2004
@@ -94,7 +94,7 @@
 static int resolve_overloaded_unification (tree, tree, tree, tree,
 					   unification_kind_t, int);
 static int try_one_overload (tree, tree, tree, tree, tree,
-			     unification_kind_t, int);
+			     unification_kind_t, int, bool);
 static int unify (tree, tree, tree, tree, int);
 static void add_pending_template (tree);
 static void reopen_tinst_level (tree);
@@ -353,7 +353,8 @@
 		 parms, current_template_parms);
   TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1;
 
-  pushlevel (0);
+  begin_scope (TREE_VEC_LENGTH (parms) ? sk_template_parms : sk_template_spec,
+               NULL);
   for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) 
     {
       tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
@@ -610,7 +611,7 @@
 
      pushtag contains special code to call pushdecl_with_scope on the
      TEMPLATE_DECL for S2.  */
-  begin_scope (sk_template_parms);
+  begin_scope (sk_template_parms, NULL);
   ++processing_template_decl;
   ++processing_template_parmlist;
   note_template_header (0);
@@ -654,7 +655,7 @@
 void
 begin_specialization (void)
 {
-  begin_scope (sk_template_spec);
+  begin_scope (sk_template_spec, NULL);
   note_template_header (1);
   check_specialization_scope ();
 }
@@ -2947,8 +2948,7 @@
 	     A template-parameter may not be given default arguments
 	     by two different declarations in the same scope.  */
 	  error ("redefinition of default argument for `%#D'", parm);
-	  error ("%H  original definition appeared here",
-		 &DECL_SOURCE_LOCATION (tmpl_parm));
+	  error ("%J  original definition appeared here", tmpl_parm);
 	  return;
 	}
 
@@ -3210,9 +3210,12 @@
 	tree type_referred_to = TREE_TYPE (type);
 
 	/* If this expression already has reference type, get the
-	   underling object.  */
+	   underlying object.  */
 	if (TREE_CODE (expr_type) == REFERENCE_TYPE) 
 	  {
+	    if (TREE_CODE (expr) == NOP_EXPR
+		&& TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
+	      STRIP_NOPS (expr);
 	    my_friendly_assert (TREE_CODE (expr) == ADDR_EXPR, 20000604);
 	    expr = TREE_OPERAND (expr, 0);
 	    expr_type = TREE_TYPE (expr);
@@ -3266,7 +3269,7 @@
 	  }
 
 	cxx_mark_addressable (expr);
-	return build1 (ADDR_EXPR, type, expr);
+	return build_nop (type, build_address (expr));
       }
       break;
 
@@ -3852,7 +3855,8 @@
     return error_mark_node;
 
   my_friendly_assert (!arglist || TREE_CODE (arglist) == TREE_VEC, 20030726);
-  if (fns == NULL_TREE)
+  if (fns == NULL_TREE 
+      || TREE_CODE (fns) == FUNCTION_DECL)
     {
       error ("non-template used as template");
       return error_mark_node;
@@ -4998,6 +5002,8 @@
       DECL_USE_TEMPLATE (tmpl) = 0;
       DECL_TEMPLATE_INFO (tmpl) = NULL_TREE;
       CLASSTYPE_USE_TEMPLATE (TREE_TYPE (tmpl)) = 0;
+      CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl))
+	= INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl)));
 
       /* Inject this template into the global scope.  */
       friend_type = TREE_TYPE (pushdecl_top_level (tmpl));
@@ -5251,12 +5257,14 @@
 		  if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag))
 		    /* Unfortunately, lookup_template_class sets
 		       CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
-		       instantiation (i.e., for the type of a member template
-		       class nested within a template class.)  This behavior is
-		       required for maybe_process_partial_specialization to work
-		       correctly, but is not accurate in this case; the TAG is not
-		       an instantiation of anything.  (The corresponding
-		       TEMPLATE_DECL is an instantiation, but the TYPE is not.) */
+		       instantiation (i.e., for the type of a member
+		       template class nested within a template class.)
+		       This behavior is required for
+		       maybe_process_partial_specialization to work
+		       correctly, but is not accurate in this case;
+		       the TAG is not an instantiation of anything.
+		       (The corresponding TEMPLATE_DECL is an
+		       instantiation, but the TYPE is not.) */
 		    CLASSTYPE_USE_TEMPLATE (newtag) = 0;
 
 		  /* Now, we call pushtag to put this NEWTAG into the scope of
@@ -5273,8 +5281,13 @@
 		   || DECL_FUNCTION_TEMPLATE_P (t))
 	    {
 	      /* Build new TYPE_METHODS.  */
-
-	      tree r = tsubst (t, args, tf_error, NULL_TREE);
+	      tree r;
+	      
+	      if (TREE_CODE (t) == TEMPLATE_DECL)
+		processing_template_decl++;
+	      r = tsubst (t, args, tf_error, NULL_TREE);
+	      if (TREE_CODE (t) == TEMPLATE_DECL)
+		processing_template_decl--;
 	      set_current_access_from_decl (r);
 	      grok_special_member_properties (r);
 	      finish_member_declaration (r);
@@ -7089,7 +7102,17 @@
   my_friendly_assert (!dependent_type_p (scope), 20030729);
   
   if (!BASELINK_P (name) && !DECL_P (expr))
-    expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
+    {
+      expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
+      if (TREE_CODE (TREE_CODE (expr) == TEMPLATE_DECL
+		     ? DECL_TEMPLATE_RESULT (expr) : expr) == TYPE_DECL)
+	{
+	  if (complain & tf_error)
+	    error ("`%E' names a type, but a non-type is expected",
+		   qualified_id);
+	  return error_mark_node;
+	}
+    }
   
   if (DECL_P (expr))
     check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
@@ -7303,7 +7326,6 @@
     case ROUND_DIV_EXPR:
     case EXACT_DIV_EXPR:
     case BIT_AND_EXPR:
-    case BIT_ANDTC_EXPR:
     case BIT_IOR_EXPR:
     case BIT_XOR_EXPR:
     case TRUNC_MOD_EXPR:
@@ -7548,7 +7570,8 @@
 	    
 	    scope = tsubst_expr (scope, args, complain, in_decl);
 	    decl = lookup_qualified_name (scope, name,
-					  /*is_type_p=*/0, /*complain=*/false);
+					  /*is_type_p=*/false,
+					  /*complain=*/false);
 	    if (decl == error_mark_node)
 	      qualified_name_lookup_error (scope, name);
 	    else
@@ -7973,6 +7996,8 @@
       else
 	op1 = tsubst_non_call_postfix_expression (op1, args, complain, 
 						  in_decl);
+      if (TREE_CODE (op1) == LABEL_DECL)
+	return finish_label_address_expr (DECL_NAME (op1));
       return build_x_unary_op (ADDR_EXPR, op1);
 
     case PLUS_EXPR:
@@ -7984,7 +8009,6 @@
     case ROUND_DIV_EXPR:
     case EXACT_DIV_EXPR:
     case BIT_AND_EXPR:
-    case BIT_ANDTC_EXPR:
     case BIT_IOR_EXPR:
     case BIT_XOR_EXPR:
     case TRUNC_MOD_EXPR:
@@ -8046,10 +8070,10 @@
 	  op1 = RECUR (op1);
 	  --skip_evaluation;
 	}
-      if (TREE_CODE (t) == SIZEOF_EXPR)
-	return finish_sizeof (op1);
+      if (TYPE_P (op1))
+	return cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), true);
       else
-	return finish_alignof (op1);
+	return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t));
 
     case MODOP_EXPR:
       return build_x_modify_expr
@@ -8091,18 +8115,9 @@
 	bool koenig_p;
 
 	function = TREE_OPERAND (t, 0);
-	/* To determine whether or not we should perform Koenig lookup
-	   we must look at the form of the FUNCTION.  */
-	koenig_p = !(/* Koenig lookup does not apply to qualified
-			names.  */
-		     TREE_CODE (function) == SCOPE_REF
-		     /* Or to references to members of classes.  */
-		     || TREE_CODE (function) == COMPONENT_REF
-		     /* If it is a FUNCTION_DECL or a baselink, then
-			the name was already resolved when the
-			template was parsed.  */
-		     || TREE_CODE (function) == FUNCTION_DECL
-		     || TREE_CODE (function) == BASELINK);
+	/* When we parsed the expression,  we determined whether or
+	   not Koenig lookup should be performed.  */
+	koenig_p = KOENIG_LOOKUP_P (t);
 	if (TREE_CODE (function) == SCOPE_REF)
 	  {
 	    qualified_p = true;
@@ -8118,23 +8133,22 @@
 	    function = tsubst_copy_and_build (function, args, complain, 
 					      in_decl,
 					      !qualified_p);
+	    if (BASELINK_P (function))
+	      qualified_p = true;
 	  }
 
 	call_args = RECUR (TREE_OPERAND (t, 1));
 	  
-	if (BASELINK_P (function))
-	  qualified_p = 1;
-
 	if (koenig_p
-	    && TREE_CODE (function) != TEMPLATE_ID_EXPR
 	    && (is_overloaded_fn (function)
 		|| DECL_P (function)
 		|| TREE_CODE (function) == IDENTIFIER_NODE))
+	  function = perform_koenig_lookup (function, call_args);
+
+	if (TREE_CODE (function) == IDENTIFIER_NODE)
 	  {
-	    if (call_args)
-	      function = perform_koenig_lookup (function, call_args);
-	    else if (TREE_CODE (function) == IDENTIFIER_NODE)
-	      function = unqualified_name_lookup_error (function);
+	    unqualified_name_lookup_error (function);
+	    return error_mark_node;
 	  }
 
 	/* Remember that there was a reference to this entity.  */
@@ -8152,7 +8166,8 @@
 		   call_args, NULL_TREE, 
 		   qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
 	return finish_call_expr (function, call_args, 
-				 /*disallow_virtual=*/qualified_p);
+				 /*disallow_virtual=*/qualified_p,
+				 koenig_p);
       }
 
     case COND_EXPR:
@@ -8232,7 +8247,8 @@
 	    tmpl = TREE_OPERAND (TREE_OPERAND (member, 1), 0);
 	    args = TREE_OPERAND (TREE_OPERAND (member, 1), 1);
 	    member = lookup_qualified_name (TREE_OPERAND (member, 0), tmpl, 
-					    /*is_type=*/0, /*complain=*/false);
+					    /*is_type_p=*/false,
+					    /*complain=*/false);
 	    if (BASELINK_P (member))
 	      BASELINK_FUNCTIONS (member) 
 		= build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
@@ -8918,9 +8934,15 @@
 {
   tree tempargs = copy_node (targs);
   int good = 0;
+  bool addr_p;
 
   if (TREE_CODE (arg) == ADDR_EXPR)
-    arg = TREE_OPERAND (arg, 0);
+    {
+      arg = TREE_OPERAND (arg, 0);
+      addr_p = true;
+    }
+  else
+    addr_p = false;
 
   if (TREE_CODE (arg) == COMPONENT_REF)
     /* Handle `&x' where `x' is some static or non-static member
@@ -8956,10 +8978,8 @@
 	  if (subargs)
 	    {
 	      elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
-	      if (TREE_CODE (elem) == METHOD_TYPE)
-		elem = build_ptrmemfunc_type (build_pointer_type (elem));
-	      good += try_one_overload (tparms, targs, tempargs, parm, elem,
-					strict, sub_strict);
+	      good += try_one_overload (tparms, targs, tempargs, parm, 
+					elem, strict, sub_strict, addr_p);
 	    }
 	}
     }
@@ -8967,14 +8987,9 @@
 	   || TREE_CODE (arg) == FUNCTION_DECL)
     {
       for (; arg; arg = OVL_NEXT (arg))
-	{
-	  tree type = TREE_TYPE (OVL_CURRENT (arg));
-	  if (TREE_CODE (type) == METHOD_TYPE)
-	    type = build_ptrmemfunc_type (build_pointer_type (type));
-	  good += try_one_overload (tparms, targs, tempargs, parm,
-				    type,
-				    strict, sub_strict);
-	}
+	good += try_one_overload (tparms, targs, tempargs, parm,
+				  TREE_TYPE (OVL_CURRENT (arg)),
+				  strict, sub_strict, addr_p);
     }
   else
     abort ();
@@ -9003,6 +9018,9 @@
 /* Subroutine of resolve_overloaded_unification; does deduction for a single
    overload.  Fills TARGS with any deduced arguments, or error_mark_node if
    different overloads deduce different arguments for a given parm.
+   ADDR_P is true if the expression for which deduction is being
+   performed was of the form "& fn" rather than simply "fn".
+
    Returns 1 on success.  */
 
 static int
@@ -9012,7 +9030,8 @@
                   tree parm, 
                   tree arg, 
                   unification_kind_t strict,
-		  int sub_strict)
+		  int sub_strict,
+		  bool addr_p)
 {
   int nargs;
   tree tempargs;
@@ -9028,6 +9047,11 @@
   if (uses_template_parms (arg))
     return 1;
 
+  if (TREE_CODE (arg) == METHOD_TYPE)
+    arg = build_ptrmemfunc_type (build_pointer_type (arg));
+  else if (addr_p)
+    arg = build_pointer_type (arg);
+
   sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
 
   /* We don't copy orig_targs for this because if we have already deduced
@@ -10594,7 +10618,14 @@
      details.  */
   DECL_TI_TEMPLATE (new_decl) = DECL_TI_TEMPLATE (decl);
   COPY_DECL_ASSEMBLER_NAME (decl, new_decl);
-  COPY_DECL_RTL (decl, new_decl);
+  if (EMIT_LLVM)
+  {
+    COPY_DECL_LLVM (decl, new_decl);
+  }
+  else
+  {
+    COPY_DECL_RTL (decl, new_decl);
+  }
   DECL_USE_TEMPLATE (new_decl) = DECL_USE_TEMPLATE (decl);
 
   /* Call duplicate decls to merge the old and new declarations.  */
@@ -10724,10 +10755,14 @@
 
   timevar_push (TV_PARSE);
 
-  /* We may be in the middle of deferred access check.  Disable
-     it now.  */
+  /* We may be in the middle of deferred access check.  Disable it now.  */
   push_deferring_access_checks (dk_no_deferred);
 
+  /* Our caller does not expect collection to happen, which it might if
+     we decide to compile the function to rtl now.  Arrange for a new
+     gc context to be created if so.  */
+  function_depth++;
+
   /* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern
      for the instantiation.  */
   td = template_for_substitution (d);
@@ -10972,6 +11007,7 @@
   input_location = saved_loc;
   pop_deferring_access_checks ();
   pop_tinst_level ();
+  function_depth--;
 
   timevar_pop (TV_PARSE);
 
@@ -11333,7 +11369,8 @@
   /* ... or any of the template arguments is a dependent type or
 	an expression that is type-dependent or value-dependent.   */
   else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
-      && any_dependent_template_arguments_p (CLASSTYPE_TI_ARGS (type)))
+	   && (any_dependent_template_arguments_p 
+	       (INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)))))
     return true;
   
   /* All TYPEOF_TYPEs are dependent; if the argument of the `typeof'
@@ -11805,6 +11842,11 @@
      types.  */
   if (TREE_CODE (expr) == OVERLOAD)
     return expr;
+  /* Preserve string constants; conversions from string constants to
+     "char *" are allowed, even though normally a "const char *"
+     cannot be used to initialize a "char *".  */
+  if (TREE_CODE (expr) == STRING_CST)
+    return expr;
 
   if (TREE_CODE (expr) == COND_EXPR)
     return build (COND_EXPR,
@@ -11812,7 +11854,8 @@
 		  TREE_OPERAND (expr, 0),
 		  build_non_dependent_expr (TREE_OPERAND (expr, 1)),
 		  build_non_dependent_expr (TREE_OPERAND (expr, 2)));
-  if (TREE_CODE (expr) == COMPOUND_EXPR)
+  if (TREE_CODE (expr) == COMPOUND_EXPR
+      && !COMPOUND_EXPR_OVERLOADED (expr))
     return build (COMPOUND_EXPR,
 		  TREE_TYPE (expr),
 		  TREE_OPERAND (expr, 0),


Index: gcc-3.4/gcc/cp/rtti.c
diff -u gcc-3.4/gcc/cp/rtti.c:1.2 gcc-3.4/gcc/cp/rtti.c:1.3
--- gcc-3.4/gcc/cp/rtti.c:1.2	Fri Jan  9 10:54:32 2004
+++ gcc-3.4/gcc/cp/rtti.c	Thu Feb  5 10:05:47 2004
@@ -358,8 +358,9 @@
       TREE_READONLY (d) = 1;
       TREE_STATIC (d) = 1;
       DECL_EXTERNAL (d) = 1;
-      SET_DECL_ASSEMBLER_NAME (d, name);
       DECL_COMDAT (d) = 1;
+      TREE_PUBLIC (d) = 1;
+      SET_DECL_ASSEMBLER_NAME (d, name);
 
       pushdecl_top_level_and_finish (d, NULL_TREE);
 
@@ -373,6 +374,10 @@
       my_friendly_assert (unemitted_tinfo_decls != 0, 20030312);
       VARRAY_PUSH_TREE (unemitted_tinfo_decls, d);
 
+      /*
+       * LLVM_TODO:
+       *  I don't know if this should be here or not.
+       */
       if (is_in_anonymous_namespace(TYPE_CONTEXT(type)))
         TREE_PUBLIC(d) = 0;
     }
@@ -655,6 +660,7 @@
 		   (NULL_TREE, ptrdiff_type_node, void_list_node))));
 	      tmp = build_function_type (ptr_type_node, tmp);
 	      dcast_fn = build_library_fn_ptr (name, tmp);
+	      DECL_IS_PURE (dcast_fn) = 1;
               pop_nested_namespace (ns);
               dynamic_cast_node = dcast_fn;
 	    }
@@ -689,7 +695,12 @@
     return error_mark_node;
   
   if (processing_template_decl)
-    return build_min (DYNAMIC_CAST_EXPR, type, expr);
+    {
+      expr = build_min (DYNAMIC_CAST_EXPR, type, expr);
+      TREE_SIDE_EFFECTS (expr) = 1;
+      
+      return expr;
+    }
 
   return convert_from_reference (build_dynamic_cast_1 (type, expr));
 }


Index: gcc-3.4/gcc/cp/semantics.c
diff -u gcc-3.4/gcc/cp/semantics.c:1.2 gcc-3.4/gcc/cp/semantics.c:1.3
--- gcc-3.4/gcc/cp/semantics.c:1.2	Thu Jan  8 17:05:28 2004
+++ gcc-3.4/gcc/cp/semantics.c	Thu Feb  5 10:05:47 2004
@@ -61,9 +61,6 @@
 static void genrtl_eh_spec_block (tree);
 static void genrtl_handler (tree);
 static void cp_expand_stmt (tree);
-static struct llvm_function *genrtl_start_function (tree);
-static void genrtl_finish_function (struct llvm_function *, tree);
-static tree clear_decl_rtl (tree *, int *, void *);
 
 /* Finish processing the COND, the SUBSTMT condition for STMT.  */
 
@@ -364,7 +361,7 @@
     {
       if (!processing_template_decl)
 	add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
-      begin_scope (sk);
+      begin_scope (sk, NULL);
     }
 }
 
@@ -380,13 +377,17 @@
      mark the used labels as used.  */
   if (TREE_CODE (destination) == LABEL_DECL)
     TREE_USED (destination) = 1;
-    
-  if (TREE_CODE (destination) != LABEL_DECL)
-    /* We don't inline calls to functions with computed gotos.
-       Those functions are typically up to some funny business,
-       and may be depending on the labels being at particular
-       addresses, or some such.  */
-    DECL_UNINLINABLE (current_function_decl) = 1;
+  else
+    {
+      /* The DESTINATION is being used as an rvalue.  */
+      if (!processing_template_decl)
+	destination = decay_conversion (destination);
+      /* We don't inline calls to functions with computed gotos.
+	 Those functions are typically up to some funny business,
+	 and may be depending on the labels being at particular
+	 addresses, or some such.  */
+      DECL_UNINLINABLE (current_function_decl) = 1;
+    }
   
   check_goto (destination);
 
@@ -1004,7 +1005,7 @@
        statement-expression.  But, if it's a statement-expression with
        a scopeless block, there's nothing to keep, and we don't want
        to accidentally keep a block *inside* the scopeless block.  */ 
-    keep_next_level (0);
+    keep_next_level (false);
 
   return r;
 }
@@ -1408,7 +1409,7 @@
 
   last_expr_type = NULL_TREE;
   
-  keep_next_level (1);
+  keep_next_level (true);
 
   return last_tree; 
 }
@@ -1534,8 +1535,9 @@
 }
 
 /* Perform Koenig lookup.  FN is the postfix-expression representing
-   the call; ARGS are the arguments to the call.  Returns the
-   functions to be considered by overload resolution.  */
+   the function (or functions) to call; ARGS are the arguments to the
+   call.  Returns the functions to be considered by overload
+   resolution.  */
 
 tree
 perform_koenig_lookup (tree fn, tree args)
@@ -1585,7 +1587,7 @@
    Returns code for the call.  */
 
 tree 
-finish_call_expr (tree fn, tree args, bool disallow_virtual)
+finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
 {
   tree result;
   tree orig_fn;
@@ -1605,7 +1607,11 @@
     {
       if (type_dependent_expression_p (fn)
 	  || any_type_dependent_arguments_p (args))
-	return build_nt (CALL_EXPR, fn, args);
+	{
+	  result = build_nt (CALL_EXPR, fn, args);
+	  KOENIG_LOOKUP_P (result) = koenig_p;
+	  return result;
+	}
       if (!BASELINK_P (fn)
 	  && TREE_CODE (fn) != PSEUDO_DTOR_EXPR
 	  && TREE_TYPE (fn) != unknown_type_node)
@@ -1618,12 +1624,11 @@
      to refer to it.  */
   if (!BASELINK_P (fn) && is_overloaded_fn (fn))
     {
-      tree f;
+      tree f = fn;
 
-      if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
-	f = get_first_fn (TREE_OPERAND (fn, 0));
-      else
-	f = get_first_fn (fn);
+      if (TREE_CODE (f) == TEMPLATE_ID_EXPR)
+	f = TREE_OPERAND (f, 0);
+      f = get_first_fn (f);
       if (DECL_FUNCTION_MEMBER_P (f))
 	{
 	  tree type = currently_open_derived_class (DECL_CONTEXT (f));
@@ -1707,7 +1712,10 @@
     result = build_function_call (fn, args);
 
   if (processing_template_decl)
-    return build (CALL_EXPR, TREE_TYPE (result), orig_fn, orig_args);
+    {
+      result = build (CALL_EXPR, TREE_TYPE (result), orig_fn, orig_args);
+      KOENIG_LOOKUP_P (result) = koenig_p;
+    }
   return result;
 }
 
@@ -2661,26 +2669,6 @@
   return type;
 }
 
-/* Compute the value of the `sizeof' operator.  */
-
-tree
-finish_sizeof (tree t)
-{
-  return TYPE_P (t) ? cxx_sizeof (t) : expr_sizeof (t);
-}
-
-/* Implement the __alignof keyword: Return the minimum required
-   alignment of T, measured in bytes.  */
-
-tree
-finish_alignof (tree t)
-{
-  if (processing_template_decl)
-    return build_min (ALIGNOF_EXPR, size_type_node, t);
-
-  return TYPE_P (t) ? cxx_alignof (t) : c_alignof_expr (t);
-}
-
 /* Generate RTL for the statement T, and its substatements, and any
    other statements at its nesting level.  */
 
@@ -2859,14 +2847,7 @@
 void
 expand_body (tree fn)
 {
-  location_t saved_loc;
   tree saved_function;
-#if EMIT_LLVM
-  struct llvm_function *LLVMFn;
-#endif
-
-  if (flag_unit_at_a_time && !cgraph_global_info_ready)
-    abort ();
 
   /* Compute the appropriate object-file linkage for inline
      functions.  */
@@ -2879,75 +2860,57 @@
      we're not planning on emitting it, in case we get a chance to
      inline it.  */
   if (DECL_EXTERNAL (fn))
+  {
     return;
+  }
 
-  /* Save the current file name and line number.  When we expand the
-     body of the function, we'll set INPUT_LOCATION so that
-     error-messages come out in the right places.  */
-  saved_loc = input_location;
+  /* ??? When is this needed?  */
   saved_function = current_function_decl;
-  input_location = DECL_SOURCE_LOCATION (fn);
-  current_function_decl = fn;
 
   timevar_push (TV_INTEGRATION);
-
-  /* Optimize the body of the function before expanding it.  */
   optimize_function (fn);
-
   timevar_pop (TV_INTEGRATION);
-  timevar_push (TV_EXPAND);
-
-#if EMIT_LLVM
-  LLVMFn =
-#endif
-  genrtl_start_function (fn);
-
-  current_function_is_thunk = DECL_THUNK_P (fn);
-
-  /* Expand the body.  */
-#if EMIT_LLVM
-  llvm_expand_stmt(LLVMFn, DECL_SAVED_TREE (fn));
-#else
-  expand_stmt (DECL_SAVED_TREE (fn));
-#endif
 
-  /* Statements should always be full-expressions at the outermost set
-     of curly braces for a function.  */
-  my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
-
-  /* The outermost statement for a function contains the line number
-     recorded when we finished processing the function.  */
-  input_line = STMT_LINENO (DECL_SAVED_TREE (fn));
+  tree_rest_of_compilation (fn, function_depth > 1);
 
-  /* Generate code for the function.  */
-  genrtl_finish_function (
-#if EMIT_LLVM
-			  LLVMFn,
-#endif
-			  fn);
-
-  /* If possible, obliterate the body of the function so that it can
-     be garbage collected.  */
-  if (dump_enabled_p (TDI_all))
-    /* Keep the body; we're going to dump it.  */
-    ;
-  else if (DECL_INLINE (fn) && flag_inline_trees)
-    /* We might need the body of this function so that we can expand
-       it inline somewhere else.  */
-    ;
-  else
-    /* We don't need the body; blow it away.  */
-    DECL_SAVED_TREE (fn) = NULL_TREE;
-
-  /* And restore the current source position.  */
   current_function_decl = saved_function;
-  input_location = saved_loc;
-  extract_interface_info ();
 
-  timevar_pop (TV_EXPAND);
+  extract_interface_info ();
 
   /* Emit any thunks that should be emitted at the same time as FN.  */
   emit_associated_thunks (fn);
+
+  /* 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);
+
+  if (DECL_CLONED_FUNCTION_P (fn))
+    {
+      /* If this is a clone, go through the other clones now and mark
+         their parameters used.  We have to do that here, as we don't
+         know whether any particular clone will be expanded, and
+         therefore cannot pick one arbitrarily.  */ 
+      tree probe;
+
+      for (probe = TREE_CHAIN (DECL_CLONED_FUNCTION (fn));
+	   probe && DECL_CLONED_FUNCTION_P (probe);
+	   probe = TREE_CHAIN (probe))
+	{
+	  tree parms;
+
+	  for (parms = DECL_ARGUMENTS (probe);
+	       parms; parms = TREE_CHAIN (parms))
+	    TREE_USED (parms) = 1;
+	}
+    }
 }
 
 /* Generate RTL for FN.  */
@@ -2993,62 +2956,16 @@
   if (flag_syntax_only)
     return;
 
-  if (flag_unit_at_a_time && cgraph_global_info_ready)
-    abort ();
-
-  if (flag_unit_at_a_time && !cgraph_global_info_ready)
-    {
-      if (at_eof)
-	{
-	  /* Compute the appropriate object-file linkage for inline
-	     functions.  */
-	  if (DECL_DECLARED_INLINE_P (fn))
-	    import_export_decl (fn);
-	  cgraph_finalize_function (fn, DECL_SAVED_TREE (fn));
-	}
-      else
-	{
-	  if (!DECL_EXTERNAL (fn))
-	    {
-	      DECL_NOT_REALLY_EXTERN (fn) = 1;
-	      DECL_EXTERNAL (fn) = 1;
-	    }
-	  /* Remember this function.  In finish_file we'll decide if
-	     we actually need to write this function out.  */
-	  defer_fn (fn);
-	  /* Let the back-end know that this function exists.  */
-	  (*debug_hooks->deferred_inline_function) (fn);
-	}
-      return;
-    }
+  /* Compute the appropriate object-file linkage for inline functions.  */
+  if (DECL_DECLARED_INLINE_P (fn))
+    import_export_decl (fn);
 
+  function_depth++;
 
-  /* If possible, avoid generating RTL for this function.  Instead,
-     just record it as an inline function, and wait until end-of-file
-     to decide whether to write it out or not.  */
-  if (/* We have to generate RTL if it's not an inline function.  */
-      (DECL_INLINE (fn) || DECL_COMDAT (fn))
-      /* Or if we have to emit code for inline functions anyhow.  */
-      && !flag_keep_inline_functions
-      /* Or if we actually have a reference to the function.  */
-      && !DECL_NEEDED_P (fn))
-    {
-      /* Set DECL_EXTERNAL so that assemble_external will be called as
-	 necessary.  We'll clear it again in finish_file.  */
-      if (!DECL_EXTERNAL (fn))
-	{
-	  DECL_NOT_REALLY_EXTERN (fn) = 1;
-	  DECL_EXTERNAL (fn) = 1;
-	}
-      /* Remember this function.  In finish_file we'll decide if
-	 we actually need to write this function out.  */
-      defer_fn (fn);
-      /* Let the back-end know that this function exists.  */
-      (*debug_hooks->deferred_inline_function) (fn);
-      return;
-    }
+  /* Expand or defer, at the whim of the compilation unit manager.  */
+  cgraph_finalize_function (fn, function_depth > 1);
 
-  expand_body (fn);
+  function_depth--;
 }
 
 /* Helper function for walk_tree, used by finish_function to override all
@@ -3076,231 +2993,25 @@
 
 /* Start generating the RTL for FN.  */
 
-static struct llvm_function *
-genrtl_start_function (tree fn)
+void
+cxx_expand_function_start (void)
 {
-#if EMIT_LLVM
-  struct llvm_function *LLVMFn;
-#endif
-
-  /* Tell everybody what function we're processing.  */
-  current_function_decl = fn;
-  /* Get the RTL machinery going for this function.  */
-  init_function_start (fn);
-  /* Let everybody know that we're expanding this function, not doing
-     semantic analysis.  */
-  expanding_p = 1;
-
-  /* Even though we're inside a function body, we still don't want to
-     call expand_expr to calculate the size of a variable-sized array.
-     We haven't necessarily assigned RTL to all variables yet, so it's
-     not safe to try to expand expressions involving them.  */
-  immediate_size_expand = 0;
-  cfun->x_dont_save_pending_sizes_p = 1;
-
-  /* Let the user know we're compiling this function.  */
-  announce_function (fn);
-
-  /* Initialize the per-function data.  */
-  my_friendly_assert (!DECL_PENDING_INLINE_P (fn), 20000911);
-  if (DECL_SAVED_FUNCTION_DATA (fn))
-    {
-      /* If we already parsed this function, and we're just expanding it
-	 now, restore saved state.  */
-      *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
-
-      /* This function is being processed in whole-function mode; we
-	 already did semantic analysis.  */
-      cfun->x_whole_function_mode_p = 1;
-
-      /* If we decided that we didn't want to inline this function,
-	 make sure the back-end knows that.  */
-      if (!current_function_cannot_inline)
-	current_function_cannot_inline = cp_function_chain->cannot_inline;
-
-      /* 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;
-    }
-
-  /* Keep track of how many functions we're presently expanding.  */
-  ++function_depth;
-
-#if EMIT_LLVM
-  /* Create a binding level for the parameters.  */
-  LLVMFn = llvm_expand_function_start (fn, /*parms_have_cleanups=*/0);
-
-  /* If the named return value optimization has been applied to this function,
-   * set the LLVM value of the named returned value equal to the llvm of the
-   * DECL_RESULT.
-   */
-  if (current_function_return_value)
-    COPY_DECL_LLVM (DECL_RESULT (fn), current_function_return_value);
-
-  /* If this function is `main'.  */
-  if (DECL_MAIN_P (fn))
-    llvm_expand_main_function (LLVMFn);
-
-  return LLVMFn;
-#else
-  /* Create a binding level for the parameters.  */
-  expand_function_start (fn, /*parms_have_cleanups=*/0);
-  /* If this function is `main'.  */
-  if (DECL_MAIN_P (fn))
-    expand_main_function ();
-
   /* Give our named return value the same RTL as our RESULT_DECL.  */
   if (current_function_return_value)
-    COPY_DECL_RTL (DECL_RESULT (fn), current_function_return_value);
-#endif
+    COPY_DECL_RTL (DECL_RESULT (cfun->decl), current_function_return_value);
 }
 
-/* Finish generating the RTL for FN.  */
-
-static void
-genrtl_finish_function (struct llvm_function *LLVMFn, tree fn)
-{
-#if 0
-  tree t;
-
-  if (write_symbols != NO_DEBUG)
-    {
-      /* Keep this code around in case we later want to control debug info
-	 based on whether a type is "used".  (jason 1999-11-11) */
-
-      tree ttype = target_type (fntype);
-      tree parmdecl;
-
-      if (IS_AGGR_TYPE (ttype))
-	/* Let debugger know it should output info for this type.  */
-	note_debug_info_needed (ttype);
-
-      for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
-	{
-	  ttype = target_type (TREE_TYPE (parmdecl));
-	  if (IS_AGGR_TYPE (ttype))
-	    /* Let debugger know it should output info for this type.  */
-	    note_debug_info_needed (ttype);
-	}
-    }
-#endif
-
-  /* Clean house because we will need to reorder insns here.  */
-  do_pending_stack_adjust ();
-
-  /* If we have a named return value, we need to force a return so that
-     the return register is USEd.  */
-  if (DECL_NAME (DECL_RESULT (fn)))
-    emit_jump (return_label);
-
-  /* We hard-wired immediate_size_expand to zero in start_function.
-     Expand_function_end will decrement this variable.  So, we set the
-     variable to one here, so that after the decrement it will remain
-     zero.  */
-  immediate_size_expand = 1;
-
-  if (EMIT_LLVM) 
-    llvm_expand_function_end (LLVMFn, fn, 0);
-  else {
-    /* Generate rtl for function exit.  */
-    expand_function_end ();
-  }
-
-  /* If this is a nested function (like a template instantiation that
-     we're compiling in the midst of compiling something else), push a
-     new GC context.  That will keep local variables on the stack from
-     being collected while we're doing the compilation of this
-     function.  */
-  if (function_depth > 1)
-    ggc_push_context ();
-
-  /* There's no need to defer outputting this function any more; we
-     know we want to output it.  */
-  DECL_DEFER_OUTPUT (fn) = 0;
-
 #if EMIT_LLVM
-  if (EMIT_CODE_INCREMENTALLY) llvm_function_print(LLVMFn, llvm_out_file);
-  cfun = 0;
-#else
-  /* Run the optimizers and output the assembler code for this
-     function.  */
-  rest_of_compilation (fn);
-#endif
-
-  /* Undo the call to ggc_push_context above.  */
-  if (function_depth > 1)
-    ggc_pop_context ();
-
-#if 0
-  /* Keep this code around in case we later want to control debug info
-     based on whether a type is "used".  (jason 1999-11-11) */
-
-  if (ctype && TREE_ASM_WRITTEN (fn))
-    note_debug_info_needed (ctype);
-#endif
-
-  /* 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);
-
-  --function_depth;
-
-  /* In C++, we should never be saving RTL for the function.  */
-  my_friendly_assert (!DECL_SAVED_INSNS (fn), 20010903);
-
-#if !EMIT_LLVM
-  /* Since we don't need the RTL for this function anymore, stop
-     pointing to it.  That's especially important for LABEL_DECLs,
-     since you can reach all the instructions in the function from the
-     CODE_LABEL stored in the DECL_RTL for the LABEL_DECL.  Walk the
-     BLOCK-tree, clearing DECL_RTL for LABEL_DECLs and non-static
-     local variables.  */
-  walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
-				clear_decl_rtl,
-				NULL);
-
-  /* Clear out the RTL for the arguments.  */
-  for (t = DECL_ARGUMENTS (fn); t; t = TREE_CHAIN (t))
-    {
-      SET_DECL_RTL (t, NULL_RTX);
-      DECL_INCOMING_RTL (t) = NULL_RTX;
-    }
-#endif
-
-  if (!(flag_inline_trees && DECL_INLINE (fn)))
-    /* DECL_INITIAL must remain nonzero so we know this was an
-       actual function definition.  */
-    DECL_INITIAL (fn) = error_mark_node;
-  
-  /* Let the error reporting routines know that we're outside a
-     function.  For a nested function, this value is used in
-     pop_cp_function_context and then reset via pop_function_context.  */
-  current_function_decl = NULL_TREE;
-}
-
-/* Clear out the DECL_RTL for the non-static variables in BLOCK and
-   its sub-blocks.  */
-
-#if !EMIT_LLVM
-static tree
-clear_decl_rtl (tree* tp, 
-                int* walk_subtrees ATTRIBUTE_UNUSED , 
-                void* data ATTRIBUTE_UNUSED )
+/*
+ * Description:
+ *  This function is the LLVM version of cxx_expand_function_start().
+ */
+void
+llvm_cxx_expand_function_start (void)
 {
-  if (nonstatic_local_decl_p (*tp)) 
-    SET_DECL_RTL (*tp, NULL_RTX);
-    
-  return NULL_TREE;
+  /* Give our named return value the same LLVM as our RESULT_DECL.  */
+  if (current_function_return_value)
+    COPY_DECL_LLVM (DECL_RESULT (cfun->decl), current_function_return_value);
 }
 #endif
 


Index: gcc-3.4/gcc/cp/typeck.c
diff -u gcc-3.4/gcc/cp/typeck.c:1.2 gcc-3.4/gcc/cp/typeck.c:1.3
--- gcc-3.4/gcc/cp/typeck.c:1.2	Thu Jan  8 17:05:28 2004
+++ gcc-3.4/gcc/cp/typeck.c	Thu Feb  5 10:05:47 2004
@@ -902,11 +902,8 @@
   if (t1 == t2)
     return true;
 
-  /* This should never happen.  */
-  my_friendly_assert (t1 != error_mark_node, 307);
-
   /* Suppress errors caused by previously reported errors */
-  if (t2 == error_mark_node)
+  if (t1 == error_mark_node || t2 == error_mark_node)
     return false;
   
   my_friendly_assert (TYPE_P (t1) && TYPE_P (t2), 20030623);
@@ -1172,23 +1169,33 @@
 	 they fail to match.  */
       if (!t1 || !t2)
 	return false;
-      if (!same_type_p (TREE_VALUE (t2), TREE_VALUE (t1)))
+      if (!same_type_p (TREE_VALUE (t1), TREE_VALUE (t2)))
 	return false;
     }
   return true;
 }
 
 
+/* Process a sizeof or alignof expression where the operand is a
+   type.  */
+
 tree
-cxx_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
+cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain)
 {
   enum tree_code type_code;
   tree value;
   const char *op_name;
 
   my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
+  if (type == error_mark_node)
+    return error_mark_node;
+  
   if (processing_template_decl)
-    return build_min (op, size_type_node, type);
+    {
+      value = build_min (op, size_type_node, type);
+      TREE_READONLY (value) = 1;
+      return value;
+    }
   
   op_name = operator_name_info[(int) op].name;
 
@@ -1207,30 +1214,46 @@
   return value;
 }
 
+/* Process a sizeof or alignof expression where the operand is an
+   expression.  */
+
 tree
-expr_sizeof (tree e)
+cxx_sizeof_or_alignof_expr (tree e, enum tree_code op)
 {
+  const char *op_name = operator_name_info[(int) op].name;
+  
+  if (e == error_mark_node)
+    return error_mark_node;
+  
   if (processing_template_decl)
-    return build_min (SIZEOF_EXPR, size_type_node, e);
-
+    {
+      e = build_min (op, size_type_node, e);
+      TREE_SIDE_EFFECTS (e) = 0;
+      TREE_READONLY (e) = 1;
+      
+      return e;
+    }
+  
   if (TREE_CODE (e) == COMPONENT_REF
       && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
-    error ("sizeof applied to a bit-field");
-  if (is_overloaded_fn (e))
     {
-      pedwarn ("ISO C++ forbids applying `sizeof' to an expression of function type");
-      return c_sizeof (char_type_node);
+      error ("invalid application of `%s' to a bit-field", op_name);
+      e = char_type_node;
+    }
+  else if (is_overloaded_fn (e))
+    {
+      pedwarn ("ISO C++ forbids applying `%s' to an expression of function type", op_name);
+      e = char_type_node;
     }
   else if (type_unknown_p (e))
     {
       cxx_incomplete_type_error (e, TREE_TYPE (e));
-      return c_sizeof (char_type_node);
+      e = char_type_node;
     }
-
-  if (e == error_mark_node)
-    return e;
-
-  return cxx_sizeof (TREE_TYPE (e));
+  else
+    e = TREE_TYPE (e);
+  
+  return cxx_sizeof_or_alignof_type (e, op, true);
 }
   
 
@@ -1912,8 +1935,8 @@
   expr = build_class_member_access_expr (object, member, access_path,
 					 /*preserve_reference=*/false);
   if (processing_template_decl && expr != error_mark_node)
-    return build_min (COMPONENT_REF, TREE_TYPE (expr), orig_object, 
-		      orig_name);
+    return build_min_non_dep (COMPONENT_REF, expr,
+			      orig_object, orig_name);
   return expr;
 }
 
@@ -1970,7 +1993,7 @@
     rval = build_indirect_ref (expr, errorstring);
 
   if (processing_template_decl && rval != error_mark_node)
-    return build_min (INDIRECT_REF, TREE_TYPE (rval), orig_expr);
+    return build_min_non_dep (INDIRECT_REF, rval, orig_expr);
   else
     return rval;
 }
@@ -2515,8 +2538,12 @@
 
 	  if (!COMPLETE_TYPE_P (complete_type (type)))
 	    {
-	      error ("parameter type of called function is incomplete");
-	      parmval = val;
+	      if (fndecl)
+		error ("parameter %P of `%D' has incomplete type `%T'",
+		       i, fndecl, type);
+	      else
+		error ("parameter %P has incomplete type `%T'", i, type);
+	      parmval = error_mark_node;
 	    }
 	  else
 	    {
@@ -2620,7 +2647,7 @@
     expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
 
   if (processing_template_decl && expr != error_mark_node)
-    return build_min (code, TREE_TYPE (expr), orig_arg1, orig_arg2);
+    return build_min_non_dep (code, expr, orig_arg1, orig_arg2);
   
   return expr;
 }
@@ -2817,7 +2844,6 @@
       break;
 
     case BIT_AND_EXPR:
-    case BIT_ANDTC_EXPR:
     case BIT_IOR_EXPR:
     case BIT_XOR_EXPR:
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
@@ -3521,7 +3547,8 @@
     }
 
   if (processing_template_decl && exp != error_mark_node)
-    return build_min (code, TREE_TYPE (exp), orig_expr, NULL_TREE);
+    return build_min_non_dep (code, exp, orig_expr,
+			      /*For {PRE,POST}{INC,DEC}REMENT_EXPR*/NULL_TREE);
   return exp;
 }
 
@@ -3564,9 +3591,7 @@
   if (error_operand_p (t) || !cxx_mark_addressable (t))
     return error_mark_node;
 
-  addr = build1 (ADDR_EXPR, 
-		 build_pointer_type (TREE_TYPE (t)),
-		 t);
+  addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
   if (staticp (t))
     TREE_CONSTANT (addr) = 1;
 
@@ -3977,7 +4002,7 @@
 	 is an error.  */
       else if (TREE_CODE (argtype) != FUNCTION_TYPE
 	       && TREE_CODE (argtype) != METHOD_TYPE
-	       && !non_cast_lvalue_or_else (arg, "unary `&'"))
+	       && !lvalue_or_else (arg, "unary `&'"))
 	return error_mark_node;
 
       if (argtype != error_mark_node)
@@ -3986,12 +4011,24 @@
       {
 	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)
 	  addr = build_address (arg);
+	else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
+	  {
+	    tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
+
+	    /* We can only get here with a single static member
+	       function.  */
+	    my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL
+				&& DECL_STATIC_FUNCTION_P (fn),
+				20030906);
+	    mark_used (fn);
+	    addr = build_address (fn);
+	    if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
+	      /* Do not lose object's side effects.  */
+	      addr = build (COMPOUND_EXPR, TREE_TYPE (addr),
+			    TREE_OPERAND (arg, 0), addr);
+	  }
 	else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
 	  {
 	    error ("attempt to take address of bit-field structure member `%D'",
@@ -4271,8 +4308,8 @@
 
   expr = build_conditional_expr (ifexp, op1, op2);
   if (processing_template_decl && expr != error_mark_node)
-    return build_min (COND_EXPR, TREE_TYPE (expr), 
-		      orig_ifexp, orig_op1, orig_op2);
+    return build_min_non_dep (COND_EXPR, expr, 
+			      orig_ifexp, orig_op1, orig_op2);
   return expr;
 }
 
@@ -4318,8 +4355,8 @@
     result = build_compound_expr (op1, op2);
 
   if (processing_template_decl && result != error_mark_node)
-    return build_min (COMPOUND_EXPR, TREE_TYPE (result), 
-		      orig_op1, orig_op2);
+    return build_min_non_dep (COMPOUND_EXPR, result, orig_op1, orig_op2);
+  
   return result;
 }
 
@@ -4376,8 +4413,10 @@
 
   if (processing_template_decl)
     {
-      tree t = build_min (STATIC_CAST_EXPR, type, expr); 
-      return t;
+      expr = build_min (STATIC_CAST_EXPR, type, expr);
+      /* We don't know if it will or will not have side effects.  */
+      TREE_SIDE_EFFECTS (expr) = 1;
+      return expr;
     }
 
   /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
@@ -4411,19 +4450,20 @@
   if (TREE_CODE (type) == REFERENCE_TYPE
       && CLASS_TYPE_P (TREE_TYPE (type))
       && CLASS_TYPE_P (intype)
-      && real_non_cast_lvalue_p (expr)
+      && real_lvalue_p (expr)
       && DERIVED_FROM_P (intype, TREE_TYPE (type))
       && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
 		      build_pointer_type (TYPE_MAIN_VARIANT 
 					  (TREE_TYPE (type))))
       && at_least_as_qualified_p (TREE_TYPE (type), intype))
     {
-      /* At this point we have checked all of the conditions except
-	 that B is not a virtual base class of D.  That will be
-	 checked by build_base_path.  */
-      tree base = lookup_base (TREE_TYPE (type), intype, ba_any, NULL);
+      /* There is a standard conversion from "D*" to "B*" even if "B"
+	 is ambiguous or inaccessible.  Therefore, we ask lookup_base
+	 to check these conditions.  */
+      tree base = lookup_base (TREE_TYPE (type), intype, ba_check, NULL);
 
-      /* Convert from B* to D*.  */
+      /* Convert from "B*" to "D*".  This function will check that "B"
+	 is not a virtual base of "D".  */
       expr = build_base_path (MINUS_EXPR, build_address (expr), 
 			      base, /*nonnull=*/false);
       /* Convert the pointer to a reference -- but then remember that
@@ -4467,9 +4507,10 @@
 	 converted to an enumeration type.  */
       || (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
 	  && INTEGRAL_OR_ENUMERATION_TYPE_P (intype)))
-      /* Really, build_c_cast should defer to this function rather
-	 than the other way around.  */
-      return build_c_cast (type, expr);
+    /* Really, build_c_cast should defer to this function rather
+       than the other way around.  */
+    return build_c_cast (type, expr);
+  
   if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
       && CLASS_TYPE_P (TREE_TYPE (type))
       && CLASS_TYPE_P (TREE_TYPE (intype))
@@ -4481,10 +4522,11 @@
       tree base;
 
       check_for_casting_away_constness (intype, type, "static_cast");
-      base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), 
-			  ba_check | ba_quiet, NULL);
+      base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), ba_check, 
+			  NULL);
       return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
     }
+  
   if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
       || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
     {
@@ -4561,6 +4603,11 @@
   if (processing_template_decl)
     {
       tree t = build_min (REINTERPRET_CAST_EXPR, type, expr);
+      
+      if (!TREE_SIDE_EFFECTS (t)
+	  && type_dependent_expression_p (expr))
+	/* There might turn out to be side effects inside expr.  */
+	TREE_SIDE_EFFECTS (t) = 1;
       return t;
     }
 
@@ -4645,6 +4692,11 @@
   if (processing_template_decl)
     {
       tree t = build_min (CONST_CAST_EXPR, type, expr);
+      
+      if (!TREE_SIDE_EFFECTS (t)
+	  && type_dependent_expression_p (expr))
+	/* There might turn out to be side effects inside expr.  */
+	TREE_SIDE_EFFECTS (t) = 1;
       return t;
     }
 
@@ -4714,6 +4766,8 @@
     {
       tree t = build_min (CAST_EXPR, type,
 			  tree_cons (NULL_TREE, value, NULL_TREE));
+      /* We don't know if it will or will not have side effects. */
+      TREE_SIDE_EFFECTS (t) = 1;
       return t;
     }
 
@@ -5677,7 +5731,8 @@
 
       if (fndecl)
 	savew = warningcount, savee = errorcount;
-      rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE);
+      rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE,
+				  /*cleanup=*/NULL);
       if (fndecl)
 	{
 	  if (warningcount > savew)





More information about the llvm-commits mailing list