OSDN Git Service

* call.c (joust): Don't warn about "confusing" conversions to the
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index b6b2f66..99d8a7f 100644 (file)
@@ -59,6 +59,8 @@ extern int static_labelno;
 extern tree current_namespace;
 extern tree global_namespace;
 
+extern void (*print_error_function) PROTO((char *));
+
 /* Stack of places to restore the search obstack back to.  */
    
 /* Obstack used for remembering local class declarations (like
@@ -144,7 +146,6 @@ static void resume_binding_level PROTO((struct binding_level *));
 static struct binding_level *make_binding_level PROTO((void));
 static int namespace_bindings_p PROTO((void));
 static void declare_namespace_level PROTO((void));
-static tree get_unique_name PROTO((void));
 static void signal_catch PROTO((int));
 static void storedecls PROTO((tree));
 static void storetags PROTO((tree));
@@ -156,7 +157,7 @@ static tree store_bindings PROTO((tree, tree));
 static tree lookup_tag_reverse PROTO((tree, tree));
 static tree obscure_complex_init PROTO((tree, tree));
 static tree maybe_build_cleanup_1 PROTO((tree, tree));
-static tree lookup_name_real PROTO((tree, int, int));
+static tree lookup_name_real PROTO((tree, int, int, int));
 static void warn_extern_redeclared_static PROTO((tree, tree));
 static void grok_reference_init PROTO((tree, tree, tree));
 static tree grokfndecl PROTO((tree, tree, tree, tree, int,
@@ -168,9 +169,11 @@ static tree lookup_tag PROTO((enum tree_code, tree,
 static void set_identifier_type_value_with_scope
        PROTO((tree, tree, struct binding_level *));
 static void record_builtin_type PROTO((enum rid, char *, tree));
+static void record_unknown_type PROTO((tree, char *));
 static int member_function_or_else PROTO((tree, tree, char *));
 static void bad_specifiers PROTO((tree, char *, int, int, int, int,
                                  int));
+static void lang_print_error_function PROTO((char *));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PROTO((void));
@@ -231,6 +234,15 @@ tree unsigned_intSI_type_node;
 tree unsigned_intDI_type_node;
 tree unsigned_intTI_type_node;
 
+tree java_byte_type_node;
+tree java_short_type_node;
+tree java_int_type_node;
+tree java_long_type_node;
+tree java_float_type_node;
+tree java_double_type_node;
+tree java_char_type_node;
+tree java_boolean_type_node;
+
 /* A VOID_TYPE node, and the same, packaged in a TREE_LIST.  */
 
 tree void_type_node, void_list_node;
@@ -319,6 +331,9 @@ tree vtbl_type_node;
 tree std_node;
 int in_std = 0;
 
+/* Expect only namespace names now. */
+static int only_namespace_names;
+
 /* In a destructor, the point at which all derived class destroying
    has been done, just before any base class destroying will be done.  */
 
@@ -598,6 +613,10 @@ struct binding_level
     /* A list of USING_DECL nodes. */
     tree usings;
 
+    /* A list of used namespaces. PURPOSE is the namespace,
+       VALUE the common ancestor with this binding_level's namespace. */
+    tree using_directives;
+
     /* For each level, a list of shadowed outer-level local definitions
        to be restored when this level is popped.
        Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
@@ -1634,6 +1653,9 @@ find_binding (name, scope)
      tree scope;
 {
   tree iter, prev = NULL_TREE;
+
+  scope = ORIGINAL_NAMESPACE (scope);
+  
   for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter;
        iter = TREE_CHAIN (iter))
     {
@@ -1666,6 +1688,9 @@ binding_for_name (name, scope)
 {
   tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
   tree result;
+
+  scope = ORIGINAL_NAMESPACE (scope);
+  
   if (b && TREE_CODE (b) != CPLUS_BINDING)
     {
       /* Get rid of optimization for global scope. */
@@ -1698,6 +1723,8 @@ namespace_binding (name, scope)
   tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
   if (b == NULL_TREE)
     return NULL_TREE;
+  if (scope == NULL_TREE)
+    scope = global_namespace;
   if (TREE_CODE (b) != CPLUS_BINDING)
     return (scope == global_namespace) ? b : NULL_TREE;
   name = find_binding (name,scope);
@@ -1716,6 +1743,10 @@ set_namespace_binding (name, scope, val)
      tree val;
 {
   tree b;
+
+  if (scope == NULL_TREE)
+    scope = global_namespace;
+  
   if (scope == global_namespace)
     {
       b = IDENTIFIER_NAMESPACE_BINDINGS (name);
@@ -1729,50 +1760,6 @@ set_namespace_binding (name, scope, val)
   BINDING_VALUE (b) = val;
 }
 
-extern char * first_global_object_name;
-
-/* Get a unique name for each call to this routine for unnamed namespaces.
-   Mostly copied from get_file_function_name.  */
-
-static tree
-get_unique_name ()
-{
-  static int temp_name_counter = 0;
-  char *buf;
-  register char *p;
-
-  if (first_global_object_name)
-    p = first_global_object_name;
-  else if (main_input_filename)
-    p = main_input_filename;
-  else
-    p = input_filename;
-
-#define UNNAMED_NAMESPACE_FORMAT "__%s_%d"
-
-  buf = (char *) alloca (sizeof (UNNAMED_NAMESPACE_FORMAT) + strlen (p));
-
-  sprintf (buf, UNNAMED_NAMESPACE_FORMAT, p, temp_name_counter++);
-
-  /* Don't need to pull weird characters out of global names.  */
-  if (p != first_global_object_name)
-    {
-      for (p = buf+2; *p; p++)
-       if (! ((*p >= '0' && *p <= '9')
-#ifndef NO_DOLLAR_IN_LABEL     /* this for `$'; unlikely, but... -- kr */
-              || *p == '$'
-#endif
-#ifndef NO_DOT_IN_LABEL                /* this for `.'; unlikely, but...  */
-              || *p == '.'
-#endif
-              || (*p >= 'A' && *p <= 'Z')
-              || (*p >= 'a' && *p <= 'z')))
-         *p = '_';
-    }
-
-  return get_identifier (buf);
-}
-
 /* 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.  */
 
@@ -1792,7 +1779,16 @@ push_namespace (name)
     }
   else if (!name)
     {
-      name = get_unique_name ();
+      /* The name of anonymous namespace is unique for the translation
+         unit.  */
+      static tree anon_name = NULL_TREE;
+      if (!anon_name)
+        anon_name = get_file_function_name ('N');
+      name = anon_name;
+      d = IDENTIFIER_NAMESPACE_VALUE (name);
+      if (d)
+        /* Reopening anonymous namespace.  */
+        need_new = 0;
       implicit_use = 1;
     }
   else if (current_namespace == global_namespace
@@ -1806,13 +1802,21 @@ push_namespace (name)
       /* Check whether this is an extended namespace definition. */
       d = IDENTIFIER_NAMESPACE_VALUE (name);
       if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
-       need_new = 0;
+        {
+          need_new = 0;
+          if (DECL_NAMESPACE_ALIAS (d))
+            {
+              cp_error ("namespace alias `%D' not allowed here, assuming `%D'",
+                        d, DECL_NAMESPACE_ALIAS (d));
+              d = DECL_NAMESPACE_ALIAS (d);
+            }
+        }
     }
   
   if (need_new)
     {
       /* Make a new namespace, binding the name to it. */
-      d = build_lang_decl (NAMESPACE_DECL, name, NULL_TREE);
+      d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
       /* The global namespace is not pushed, and the global binding
         level is set elsewhere.  */
       if (!global)
@@ -1843,7 +1847,7 @@ pop_namespace ()
       in_std--;
       return;
     }
-  current_namespace = DECL_CONTEXT (current_namespace);
+  current_namespace = CP_DECL_CONTEXT (current_namespace);
   /* The binding level is not popped, as it might be re-opened later.  */
   suspend_binding_level ();
 }
@@ -2024,6 +2028,7 @@ maybe_push_to_top_level (pseudo)
   current_lang_name = lang_name_cplusplus;
   strict_prototype = strict_prototypes_lang_cplusplus;
   named_labels = NULL_TREE;
+  shadowed_labels = NULL_TREE;
   minimal_parse_mode = 0;
   previous_class_type = previous_class_values = NULL_TREE;
   processing_specialization = 0;
@@ -2167,7 +2172,7 @@ identifier_type_value (id)
     return REAL_IDENTIFIER_TYPE_VALUE (id);
   /* Have to search for it. It must be on the global level, now.
      Ask lookup_name not to return non-types. */
-  id = lookup_name_real (id, 2, 1);
+  id = lookup_name_real (id, 2, 1, 0);
   if (id)
     return TREE_TYPE (id);
   return NULL_TREE;
@@ -2258,6 +2263,8 @@ pushtag (name, type, globalize)
            {
              newdecl = 1;
              d = build_decl (TYPE_DECL, name, type);
+             if (current_lang_name == lang_name_java)
+               TYPE_FOR_JAVA (type) = 1;
              SET_DECL_ARTIFICIAL (d);
              if (! in_class)
                set_identifier_type_value_with_scope (name, type, b);
@@ -2266,9 +2273,18 @@ pushtag (name, type, globalize)
            d = TYPE_MAIN_DECL (d);
 
          TYPE_NAME (type) = d;
-         DECL_CONTEXT (d) = context;
+         DECL_CONTEXT (d) = FROB_CONTEXT (context);
+
+         if (processing_template_parmlist)
+           /* You can't declare a new template type in a template
+              parameter list.  But, you can declare a non-template
+              type:
 
-         if (IS_AGGR_TYPE (type)
+                template <class A*> struct S;
+
+              is a forward-declaration of `A'.  */
+           ;
+         else if (IS_AGGR_TYPE (type)
              && (/* If !GLOBALIZE then we are looking at a
                     definition.  It may not be a primary template.
                     (For example, in:
@@ -2302,8 +2318,19 @@ pushtag (name, type, globalize)
                 if appropriate.  */ 
              if (!globalize && b->pseudo_global &&
                  b->level_chain->parm_flag == 2)
-               pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
-                                    b->level_chain);
+               {
+                 pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
+                                      b->level_chain);
+                 /* Put this tag on the list of tags for the class,
+                    since that won't happen below because B is not
+                    the class binding level, but is instead the
+                    pseudo-global level.  */
+                 b->level_chain->tags = 
+                   saveable_tree_cons (name, type, b->level_chain->tags);
+                 TREE_NONLOCAL_FLAG (type) = 1;
+                 if (TYPE_SIZE (current_class_type) == NULL_TREE)
+                   CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
+               }
            }
 
          if (b->parm_flag == 2)
@@ -3224,7 +3251,7 @@ pushdecl (x)
       && ! DECL_CONTEXT (x))
     DECL_CONTEXT (x) = current_function_decl;
   if (!DECL_CONTEXT (x))
-    DECL_CONTEXT (x) = current_namespace;
+    DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
 
   /* Type are looked up using the DECL_NAME, as that is what the rest of the
      compiler wants to use.  */
@@ -3345,6 +3372,20 @@ pushdecl (x)
 
              return t;
            }
+         else if (DECL_MAIN_P (x))
+           {
+             /* A redeclaration of main, but not a duplicate of the
+                previous one. 
+
+                [basic.start.main]
+
+                This function shall not be overloaded.  */
+             cp_error_at ("invalid redeclaration of `%D'", t);
+             cp_error ("as `%D'", x);
+             /* We don't try to push this declaration since that
+                causes a crash.  */
+             return x;
+           }
        }
 
       if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
@@ -3371,43 +3412,6 @@ pushdecl (x)
             {
              push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
 
-             if (!TREE_PERMANENT (x) 
-                 && TYPE_OBSTACK (type) != saveable_obstack)
-               {
-                 /* X should have been allocated on the saveable
-                    obstack.  Since the type was not, the type may
-                    outlive X, unless we make a copy of X.  Here are
-                    some examples:
-                    
-                    template <class T>
-                    void f()
-                    {
-                      typedef S<T> Type_t;
-                      Type_t::foo();
-                    }
-                    
-                    Here, we will create a SCOPE_REF with Type_t as
-                    its first argument, and save the SCOPE_REF for
-                    later, so that we can tsubst into it.  But, that
-                    means we need to save the TYPE_DECL for Type_t.
-                    
-                    But, we must save the TYPE_DECL even when not
-                    processing_template_decl.  For example,
-                    
-                    void f() 
-                    {
-                      typedef int I;
-                      g<I>();
-                    }
-                    
-                    may create a declaration of g with `I' as one of
-                    the arguments.  In the old days, we used to use
-                    the underlying types for things, but now we try
-                    to use the typedef names for readability.  */
-                 x = copy_node (x);
-                 copy_lang_decl (x);
-               }
-
              DECL_ORIGINAL_TYPE (x) = type;
               type = build_type_copy (type);
              TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
@@ -3732,21 +3736,24 @@ pushdecl_class_level (x)
     {
       if (TYPE_BEING_DEFINED (current_class_type))
        {
-         /* Check for inconsistent use of this name in the class body.
+         /* A name N used in a class S shall refer to the same declaration
+            in its context and when re-evaluated in the completed scope of S.
+
             Types, enums, and static vars are checked here; other
             members are checked in finish_struct.  */
          tree icv = IDENTIFIER_CLASS_VALUE (name);
 
          if (icv && icv != x
+             && flag_optional_diags
              /* Don't complain about inherited names.  */
              && id_in_current_class (name)
              /* Or shadowed tags.  */
-             && !(TREE_CODE (icv) == TYPE_DECL
+             && !(DECL_DECLARES_TYPE_P (icv)
                   && DECL_CONTEXT (icv) == current_class_type))
            {
-             cp_error ("declaration of identifier `%D' as `%#D'", name, x);
-             cp_error_at ("conflicts with previous use in class as `%#D'",
-                          icv);
+             cp_pedwarn ("declaration of identifier `%D' as `%#D'", name, x);
+             cp_pedwarn_at ("conflicts with previous use in class as `%#D'",
+                            icv);
            }
        }
 
@@ -3819,12 +3826,6 @@ push_using_decl (scope, name)
 {
   tree decl;
   
-  if (!toplevel_bindings_p ())
-    {
-      sorry ("using declaration inside function");
-      return NULL_TREE;
-    }
-
   my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383);
   my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384);
   for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
@@ -3839,6 +3840,26 @@ push_using_decl (scope, name)
   return decl;
 }
 
+/* Add namespace to using_directives. Return NULL_TREE if nothing was
+   changed (i.e. there was already a directive), or the fresh
+   TREE_LIST otherwise.  */
+
+tree
+push_using_directive (used, ancestor)
+     tree used;
+     tree ancestor;
+{
+  tree ud = current_binding_level->using_directives;
+  
+  /* Check if we already have this. */
+  if (purpose_member (used, ud) != NULL_TREE)
+    return NULL_TREE;
+  ud = perm_tree_cons (used, ancestor, ud);
+  current_binding_level->using_directives = ud;
+  return ud;
+}
+
 /* DECL is a FUNCTION_DECL which may have other definitions already in
    place.  We get around this by making the value of the identifier point
    to a list of all the things that want to be referenced by that name.  It
@@ -4141,7 +4162,6 @@ shadow_label (name)
     {
       shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
       SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE);
-      SET_IDENTIFIER_LABEL_VALUE (decl, NULL_TREE);
     }
 
   return lookup_label (name);
@@ -4413,7 +4433,7 @@ lookup_tag (form, name, binding_level, thislevel_only)
       else if (level->namespace_p)
        /* Do namespace lookup. */
        /* XXX: is this a real lookup, considering using-directives etc. ??? */
-       for (tail = current_namespace; 1; tail = DECL_CONTEXT (tail))
+       for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
          {
            tree old = BINDING_TYPE (binding_for_name (name, tail));
            /* If it has an original type, it is a typedef, and we
@@ -4454,9 +4474,11 @@ lookup_tag (form, name, binding_level, thislevel_only)
        {
          if (level->pseudo_global)
            {
-             tree t = IDENTIFIER_NAMESPACE_VALUE (name);
-             if (t && TREE_CODE (t) == TEMPLATE_DECL
-                 && TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
+             tree t = IDENTIFIER_CLASS_VALUE (name);
+             if (t && DECL_CLASS_TEMPLATE_P (t))
+               return TREE_TYPE (t);
+             t = IDENTIFIER_NAMESPACE_VALUE (name);
+             if (t && DECL_CLASS_TEMPLATE_P (t))
                return TREE_TYPE (t);
            }
          return NULL_TREE;
@@ -4690,10 +4712,10 @@ make_typename_type (context, name)
   if (processing_template_decl)
     pop_obstacks ();
 
-  TYPE_CONTEXT (t) = context;
+  TYPE_CONTEXT (t) = FROB_CONTEXT (context);
   TYPE_NAME (TREE_TYPE (d)) = d;
   TYPE_STUB_DECL (TREE_TYPE (d)) = d;
-  DECL_CONTEXT (d) = context;
+  DECL_CONTEXT (d) = FROB_CONTEXT (context);
   CLASSTYPE_GOT_SEMICOLON (t) = 1;
 
   return t;
@@ -4702,12 +4724,20 @@ make_typename_type (context, name)
 /* Select the right _DECL from multiple choices. */
 
 static tree
-select_decl (binding, prefer_type)
+select_decl (binding, prefer_type, namespaces_only)
      tree binding;
-     int prefer_type;
+     int prefer_type, namespaces_only;
 {
   tree val;
   val = BINDING_VALUE (binding);
+  if (namespaces_only)
+    {
+      /* We are not interested in types. */
+      if (val && TREE_CODE (val) == NAMESPACE_DECL)
+        return val;
+      return NULL_TREE;
+    }
+  
   /* If we could have a type and
      we have nothing or we need a type and have none.  */
   if (BINDING_TYPE (binding)
@@ -4720,6 +4750,62 @@ select_decl (binding, prefer_type)
   return val;
 }
 
+/* Unscoped lookup of a global, iterate over namespaces, considering
+   using namespace statements. */
+
+static tree
+unqualified_namespace_lookup (name, prefer_type, namespaces_only)
+     tree name;
+     int prefer_type;
+     int namespaces_only;
+{
+  struct tree_binding _binding;
+  tree b = binding_init (&_binding);
+  tree initial = current_decl_namespace();
+  tree scope = initial;
+  tree siter;
+  struct binding_level *level;
+  tree val = NULL_TREE;
+
+  while (!val)
+    {
+      val = binding_for_name (name, scope);
+
+      /* Initialize binding for this context. */
+      BINDING_VALUE (b) = BINDING_VALUE (val);
+      BINDING_TYPE (b) = BINDING_TYPE (val);
+
+      /* Add all _DECLs seen through local using-directives. */
+      for (level = current_binding_level; 
+          !level->namespace_p;
+          level = level->level_chain)
+       if (!lookup_using_namespace (name, b, level->using_directives, scope))
+         /* Give up because of error. */
+         return NULL_TREE;
+
+      /* Add all _DECLs seen through global using-directives. */
+      /* XXX local and global using lists should work equally. */
+      siter = initial;
+      while (1)
+       {
+         if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter), 
+                                      scope))
+           /* Give up because of error. */
+           return NULL_TREE;
+         if (siter == scope) break;
+         siter = CP_DECL_CONTEXT (siter);
+       }
+
+      val = select_decl (b, prefer_type, namespaces_only);
+      if (scope == global_namespace)
+       break;
+      scope = DECL_CONTEXT (scope);
+      if (scope == NULL_TREE)
+       scope = global_namespace;
+    }
+  return val;
+}
+
 /* Look up NAME in the current binding level and its superiors in the
    namespace of variables, functions and typedefs.  Return a ..._DECL
    node of some kind representing its definition if there is only one
@@ -4735,15 +4821,19 @@ select_decl (binding, prefer_type)
    using IDENTIFIER_CLASS_VALUE.  */
 
 static tree
-lookup_name_real (name, prefer_type, nonclass)
+lookup_name_real (name, prefer_type, nonclass, namespaces_only)
      tree name;
-     int prefer_type, nonclass;
+     int prefer_type, nonclass, namespaces_only;
 {
   register tree val;
   int yylex = 0;
   tree from_obj = NULL_TREE;
   tree locval, classval;
 
+  /* Hack: copy flag set by parser, if set. */
+  if (only_namespace_names)
+    namespaces_only = 1;
+  
   if (prefer_type == -2)
     {
       extern int looking_for_typename;
@@ -4768,7 +4858,8 @@ lookup_name_real (name, prefer_type, nonclass)
          if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
            type = TREE_TYPE (type);
 
-         type = complete_type (type);
+         if (TYPE_P (type))
+           type = complete_type (type);
 
          if (TREE_CODE (type) == VOID_TYPE)
            type = global_namespace;
@@ -4778,7 +4869,7 @@ lookup_name_real (name, prefer_type, nonclass)
              val = binding_init (&b);
              if (!qualified_lookup_using_namespace (name, type, val))
                return NULL_TREE;
-             val = select_decl (val, prefer_type);
+             val = select_decl (val, prefer_type, namespaces_only);
            }
          else if (! IS_AGGR_TYPE (type)
                   || TREE_CODE (type) == TEMPLATE_TYPE_PARM
@@ -4809,7 +4900,7 @@ lookup_name_real (name, prefer_type, nonclass)
          else if (type == current_class_type)
            val = IDENTIFIER_CLASS_VALUE (name);
          else
-           val = lookup_field (type, name, 0, prefer_type);
+           val = lookup_member (type, name, 0, prefer_type);
        }
       else
        val = NULL_TREE;
@@ -4822,7 +4913,7 @@ lookup_name_real (name, prefer_type, nonclass)
 
   locval = classval = NULL_TREE;
 
-  if (!current_binding_level->namespace_p
+  if (!namespaces_only && !current_binding_level->namespace_p
       && IDENTIFIER_LOCAL_VALUE (name)
       /* Kludge to avoid infinite recursion with identifier_type_value.  */
       && (prefer_type <= 0
@@ -4886,33 +4977,7 @@ lookup_name_real (name, prefer_type, nonclass)
   else if (classval)
     val = classval;
   else
-    {
-      /* Unscoped lookup of a global, iterate over namespaces,
-         considering using namespace statements. */
-      struct tree_binding _binding;
-      tree b = binding_init (&_binding);
-      tree initial = current_decl_namespace();
-      tree scope = initial;
-      val = NULL_TREE;
-      while (!val)
-       {
-         val = binding_for_name (name, scope);
-         /* Initialize binding for this context. */
-         BINDING_VALUE (b) = BINDING_VALUE (val);
-         BINDING_TYPE (b) = BINDING_TYPE (val);
-         /* Add all _DECLs seen through using-directives. */
-         if (!lookup_using_namespace (name, b, initial, scope))
-           {
-             /* Give up because of error. */
-             val = NULL_TREE;
-             break;
-           }
-         val = select_decl (b, prefer_type);
-         if (scope == global_namespace)
-           break;
-         scope = DECL_CONTEXT (scope);
-       }
-    }
+    val = unqualified_namespace_lookup (name, prefer_type, namespaces_only);
 
  done:
   if (val)
@@ -4954,7 +5019,7 @@ tree
 lookup_name_nonclass (name)
      tree name;
 {
-  return lookup_name_real (name, 0, 1);
+  return lookup_name_real (name, 0, 1, 0);
 }
 
 tree
@@ -4966,11 +5031,19 @@ lookup_function_nonclass (name, args)
 }
 
 tree
+lookup_name_namespace_only (name)
+     tree name;
+{
+  /* type-or-namespace, nonclass, namespace_only */
+  return lookup_name_real (name, 1, 1, 1);
+}
+
+tree
 lookup_name (name, prefer_type)
      tree name;
      int prefer_type;
 {
-  return lookup_name_real (name, prefer_type, 0);
+  return lookup_name_real (name, prefer_type, 0, 0);
 }
 
 /* Similar to `lookup_name' but look only at current binding level.  */
@@ -5008,6 +5081,18 @@ lookup_name_current_level (name)
 
   return t;
 }
+
+void
+begin_only_namespace_names ()
+{
+  only_namespace_names = 1;
+}
+
+void
+end_only_namespace_names ()
+{
+  only_namespace_names = 0;
+}
 \f
 /* Arrange for the user to get a source line number, even when the
    compiler is going down in flames, so that she at least has a
@@ -5088,6 +5173,53 @@ record_builtin_type (rid_index, name, type)
     }
 }
 
+/* Record one of the standard Java types.
+ * Declare it as having the given NAME.
+ * If SIZE > 0, it is the size of one of the integral types;
+ * otherwise it is the negative of the size of one of the other types.  */
+
+static tree
+record_builtin_java_type (name, size)
+     char *name;
+     int size;
+{
+  tree type, decl;
+  if (size > 0)
+    type = make_signed_type (size);
+  else if (size > -32)
+    { /* "__java_char" or ""__java_boolean". */
+      type = make_unsigned_type (-size);
+      /*if (size == -1)        TREE_SET_CODE (type, BOOLEAN_TYPE);*/
+    }
+  else
+    { /* "__java_float" or ""__java_double". */
+      type = make_node (REAL_TYPE);
+      TYPE_PRECISION (type) = - size;
+      layout_type (type);
+    }
+  record_builtin_type (RID_MAX, name, type);
+  decl = TYPE_NAME (type);
+  DECL_IGNORED_P (decl) = 1;
+  TYPE_FOR_JAVA (type) = 1;
+  return type;
+}
+
+/* Push a type into the namespace so that the back-ends ignore it. */
+
+static void
+record_unknown_type (type, name)
+     tree type;
+     char *name;
+{
+  tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
+  /* Make sure the "unknown type" typedecl gets ignored for debug info.  */
+  DECL_IGNORED_P (decl) = 1;
+  TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
+  TYPE_SIZE (type) = TYPE_SIZE (void_type_node);
+  TYPE_ALIGN (type) = 1;
+  TYPE_MODE (type) = TYPE_MODE (void_type_node);
+} 
+
 /* Push overloaded decl, in global scope, with one argument so it
    can be used as a callback from define_function.  */
 
@@ -5120,7 +5252,6 @@ auto_function (name, type, code)
 void
 init_decl_processing ()
 {
-  tree decl;
   register tree endlink, int_endlink, double_endlink, unsigned_endlink;
   tree fields[20];
   /* Data type of memcpy.  */
@@ -5346,6 +5477,15 @@ init_decl_processing ()
   TREE_TYPE (complex_long_double_type_node) = long_double_type_node;
   layout_type (complex_long_double_type_node);
 
+  java_byte_type_node = record_builtin_java_type ("__java_byte", 8);
+  java_short_type_node = record_builtin_java_type ("__java_short", 16);
+  java_int_type_node = record_builtin_java_type ("__java_int", 32);
+  java_long_type_node = record_builtin_java_type ("__java_long", 64);
+  java_float_type_node = record_builtin_java_type ("__java_float", -32);
+  java_double_type_node = record_builtin_java_type ("__java_double", -64);
+  java_char_type_node = record_builtin_java_type ("__java_char", -16);
+  java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1);
+
   integer_zero_node = build_int_2 (0, 0);
   TREE_TYPE (integer_zero_node) = integer_type_node;
   integer_one_node = build_int_2 (1, 0);
@@ -5683,14 +5823,8 @@ init_decl_processing ()
   /* C++ extensions */
 
   unknown_type_node = make_node (UNKNOWN_TYPE);
-  decl = pushdecl (build_decl (TYPE_DECL, get_identifier ("unknown type"),
-                       unknown_type_node));
-  /* Make sure the "unknown type" typedecl gets ignored for debug info.  */
-  DECL_IGNORED_P (decl) = 1;
-  TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
-  TYPE_SIZE (unknown_type_node) = TYPE_SIZE (void_type_node);
-  TYPE_ALIGN (unknown_type_node) = 1;
-  TYPE_MODE (unknown_type_node) = TYPE_MODE (void_type_node);
+  record_unknown_type (unknown_type_node, "unknown type");
+
   /* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node.  */
   TREE_TYPE (unknown_type_node) = unknown_type_node;
 
@@ -5814,7 +5948,7 @@ init_decl_processing ()
   pushdecl (std_node);
 
   global_type_node = make_node (LANG_TYPE);
-  record_builtin_type (RID_MAX, "global type", global_type_node);
+  record_unknown_type (global_type_node, "global type");
 
   /* Now, C++.  */
   current_lang_name = lang_name_cplusplus;
@@ -5866,6 +6000,19 @@ init_decl_processing ()
 
   /* Show we use EH for cleanups.  */
   using_eh_for_cleanups ();
+
+  print_error_function = lang_print_error_function;
+  lang_get_alias_set = &c_get_alias_set;
+}
+
+/* Function to print any language-specific context for an error message.  */
+
+static void
+lang_print_error_function (file)
+     char *file;
+{
+  default_print_error_function (file);
+  maybe_print_template_context ();
 }
 
 /* Make a definition for a builtin function named NAME and whose data type
@@ -5890,7 +6037,7 @@ define_function (name, type, function_code, pfn, library_name)
   DECL_ARTIFICIAL (decl) = 1;
 
   my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392);
-  DECL_CONTEXT (decl) = current_namespace;
+  DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
 
   /* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
      we cannot change DECL_ASSEMBLER_NAME until we have installed this
@@ -6123,6 +6270,14 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
       ? DECL_CLASS_CONTEXT (decl)
       : DECL_CONTEXT (decl);
 
+  if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL
+      && context != current_namespace && TREE_CODE (decl) == VAR_DECL)
+    {
+      /* When parsing the initializer, lookup should use the object's
+        namespace. */
+      push_decl_namespace (context);
+    }
+
   /* We are only interested in class contexts, later. */
   if (context && TREE_CODE (context) == NAMESPACE_DECL)
     context = NULL_TREE;
@@ -6225,14 +6380,12 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
        }
 
       /* cp_finish_decl sets DECL_EXTERNAL if DECL_IN_AGGR_P is set.  */
-      if (DECL_LANG_SPECIFIC (decl))
-       DECL_IN_AGGR_P (decl) = 0;
-      if (DECL_USE_TEMPLATE (decl) || CLASSTYPE_USE_TEMPLATE (context))
+      DECL_IN_AGGR_P (decl) = 0;
+      if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl)) 
+         || CLASSTYPE_USE_TEMPLATE (context))
        SET_DECL_TEMPLATE_SPECIALIZATION (decl);
 
-      /* Stupid stupid stupid stupid  (jason 7/21/95) */
-      if (pedantic && DECL_EXTERNAL (decl)
-         && ! DECL_TEMPLATE_SPECIALIZATION (decl))
+      if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
        cp_pedwarn ("declaration of `%#D' outside of class is not definition",
                    decl);
 
@@ -6580,6 +6733,16 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       init = NULL_TREE;
     }
 
+  if (TREE_CODE (decl) == VAR_DECL 
+      && DECL_CONTEXT (decl)
+      && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
+      && DECL_CONTEXT (decl) != current_namespace
+      && init)
+    {
+      /* Leave the namespace of the object. */
+      pop_decl_namespace ();
+    }
+
   /* If the type of the thing we are declaring either has
      a constructor, or has a virtual function table pointer,
      AND its initialization was accepted by `start_decl',
@@ -6905,35 +7068,20 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       if (was_temp)
        end_temporary_allocation ();
 
-      /* Extern inline function static data has external linkage.  */
+      /* Extern inline function static data has external linkage.
+         Instead of trying to deal with that, we disable inlining of
+         such functions.  The ASM_WRITTEN check is to avoid hitting this
+         for __FUNCTION__.  */
       if (TREE_CODE (decl) == VAR_DECL
          && TREE_STATIC (decl)
+         && ! TREE_ASM_WRITTEN (decl)
          && current_function_decl
          && DECL_CONTEXT (decl) == current_function_decl
          && DECL_THIS_INLINE (current_function_decl)
          && TREE_PUBLIC (current_function_decl))
        {
-         if (DECL_INTERFACE_KNOWN (current_function_decl))
-           {
-             TREE_PUBLIC (decl) = 1;
-             DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
-           }
-         /* We can only do this if we can use common or weak, and we
-            can't if it has been initialized and we don't support weak.  */
-         else if (DECL_INITIAL (decl) == NULL_TREE
-                  || DECL_INITIAL (decl) == error_mark_node)
-           {
-             TREE_PUBLIC (decl) = 1;
-             DECL_COMMON (decl) = 1;
-           }
-         else if (flag_weak)
-           make_decl_one_only (decl);
-
-         if (TREE_PUBLIC (decl))
-           DECL_ASSEMBLER_NAME (decl)
-             = build_static_name (current_function_decl, DECL_NAME (decl));
-         else if (! DECL_ARTIFICIAL (decl))
-           cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
+         current_function_cannot_inline
+           = "function with static variable cannot be inline";
        }
 
       else if (TREE_CODE (decl) == VAR_DECL
@@ -7545,7 +7693,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
   if (ctype)
     DECL_CLASS_CONTEXT (decl) = ctype;
 
-  if (ctype == NULL_TREE && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
+  if (ctype == NULL_TREE && MAIN_NAME_P (declarator))
     {
       if (inlinep)
        error ("cannot declare `main' to be inline");
@@ -7587,16 +7735,23 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
        break;
       }
 
-  if (friendp && 
-      TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
+  if (friendp
+      && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
     {
-      /* A friend declaration of the form friend void f<>().  Record
-        the information in the TEMPLATE_ID_EXPR.  */
-      SET_DECL_IMPLICIT_INSTANTIATION (decl);
-      DECL_TEMPLATE_INFO (decl) 
-       = perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
-                         TREE_OPERAND (orig_declarator, 1),
-                         NULL_TREE);
+      if (funcdef_flag)
+       cp_error
+         ("defining explicit specialization `%D' in friend declaration",
+          orig_declarator);
+      else
+       {
+         /* A friend declaration of the form friend void f<>().  Record
+            the information in the TEMPLATE_ID_EXPR.  */
+         SET_DECL_IMPLICIT_INSTANTIATION (decl);
+         DECL_TEMPLATE_INFO (decl)
+           = perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
+                             TREE_OPERAND (orig_declarator, 1),
+                             NULL_TREE);
+       }
     }
 
   /* Caller will do the rest of this.  */
@@ -7623,7 +7778,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
                                            2 * (funcdef_flag != 0) + 
                                            4 * (friendp != 0));
 
-      if (check)
+      if ((! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
+         && check)
        {
          tmp = check_classfn (ctype, decl);
 
@@ -7668,8 +7824,9 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
                                            template_count, 
                                            2 * (funcdef_flag != 0) + 
                                            4 * (friendp != 0));
-
-      if (ctype != NULL_TREE && check)
+      if (ctype != NULL_TREE
+         && (! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
+         && check)
        {
          tmp = check_classfn (ctype, decl);
 
@@ -7768,7 +7925,7 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
     {
       tree context = in_namespace ? in_namespace : current_namespace;
       decl = build_decl (VAR_DECL, declarator, complete_type (type));
-      if (context != global_namespace)
+      if (context != global_namespace && namespace_bindings_p ())
        DECL_ASSEMBLER_NAME (decl) =  build_static_name (context,
                                                         declarator);
     }
@@ -7784,8 +7941,7 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
 
   /* In class context, static means one per class,
      public access, and static storage.  */
-  if (DECL_FIELD_CONTEXT (decl) != NULL_TREE
-      && IS_AGGR_TYPE (DECL_FIELD_CONTEXT (decl)))
+  if (DECL_CLASS_SCOPE_P (decl))
     {
       TREE_PUBLIC (decl) = 1;
       TREE_STATIC (decl) = 1;
@@ -8344,7 +8500,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                {
                  if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
                    {
-                     if (pedantic && ! in_system_header)
+                     if (pedantic && ! in_system_header && warn_long_long)
                        pedwarn ("ANSI C++ does not support `long long'");
                      if (longlong)
                        error ("`long long long' is too long for GCC");
@@ -8690,8 +8846,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
   /* Static anonymous unions are dealt with here.  */
   if (staticp && decl_context == TYPENAME
       && TREE_CODE (declspecs) == TREE_LIST
-      && TREE_CODE (TREE_VALUE (declspecs)) == UNION_TYPE
-      && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_VALUE (declspecs))))
+      && ANON_UNION_TYPE_P (TREE_VALUE (declspecs)))
     decl_context = FIELD;
 
   /* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual'
@@ -9387,6 +9542,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            if (TREE_COMPLEXITY (declarator) == 0)
              /* This needs to be here, in case we are called
                 multiple times.  */ ;
+           else if (TREE_COMPLEXITY (declarator) == -1)
+             /* Namespace member. */
+             pop_decl_namespace ();
            else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
              /* Don't fall out into global scope. Hides real bug? --eichin */ ;
            else if (! IS_AGGR_TYPE_CODE
@@ -9579,6 +9737,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
         in typenames, fields or parameters.  */
       if (constp || volatilep)
        type = cp_build_type_variant (type, constp, volatilep);
+      if (current_lang_name == lang_name_java)
+       TYPE_FOR_JAVA (type) = 1;
 
       if (decl_context == FIELD)
        {
@@ -9589,16 +9749,23 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
          if (IS_SIGNATURE (current_class_type) && opaque_typedef)
            SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1;
        }
-      else if (current_lang_name == lang_name_java)
-       decl = build_lang_decl (TYPE_DECL, declarator, type);
       else
-       decl = build_decl (TYPE_DECL, declarator, type);
+       {
+         /* Make sure this typedef lives as long as its type,
+            since it might be used as a template parameter. */
+         if (type != error_mark_node)
+           push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
+         decl = build_decl (TYPE_DECL, declarator, type);
+         if (type != error_mark_node)
+           pop_obstacks ();
+       }
 
       /* If the user declares "struct {...} foo" then `foo' will have
         an anonymous name.  Fill that name in now.  Nothing can
         refer to it, so nothing needs know about the name change.
         The TYPE_NAME field was filled in by build_struct_xref.  */
       if (type != error_mark_node
+         && !TYPE_READONLY (type) && !TYPE_VOLATILE (type)
          && TYPE_NAME (type)
          && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
          && ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
@@ -9617,7 +9784,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
          if (current_class_type)
            DECL_CONTEXT (decl) = current_class_type;
          else
-           DECL_CONTEXT (decl) = current_namespace;
+           DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
 
          DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl);
          DECL_ASSEMBLER_NAME (decl)
@@ -10001,7 +10168,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
                            declarator);
                
-               if (pedantic && ! INTEGRAL_TYPE_P (type))
+               if (pedantic && ! INTEGRAL_TYPE_P (type) 
+                   && !uses_template_parms (type))
                  cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", declarator, type);
              }
 
@@ -10077,9 +10245,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
            if (current_lang_name == lang_name_cplusplus
                && ! processing_template_decl
-               && ! (IDENTIFIER_LENGTH (original_name) == 4
-                     && IDENTIFIER_POINTER (original_name)[0] == 'm'
-                     && strcmp (IDENTIFIER_POINTER (original_name), "main") == 0)
+               && ! MAIN_NAME_P (original_name)
                && ! (IDENTIFIER_LENGTH (original_name) > 10
                      && IDENTIFIER_POINTER (original_name)[0] == '_'
                      && IDENTIFIER_POINTER (original_name)[1] == '_'
@@ -10106,6 +10272,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
        if (decl == NULL_TREE)
          return NULL_TREE;
 
+       /* Among other times, could occur from check_explicit_specialization
+          returning an error_mark_node.  */
+       if (decl == error_mark_node)
+         return error_mark_node;
+
        if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c
            && (! DECL_USE_TEMPLATE (decl) ||
                name_mangling_version < 1)) 
@@ -10498,6 +10669,7 @@ grokparms (first_parm, funcdef_flag)
                      else
                        init = require_instantiated_type (type, init, integer_zero_node);
                      if (! processing_template_decl
+                         && init != error_mark_node
                          && TREE_CODE (init) != DEFAULT_ARG
                          && ! can_convert_arg (type, TREE_TYPE (init), init))
                        cp_pedwarn ("invalid type `%T' for default argument to `%#D'",
@@ -10606,10 +10778,11 @@ grok_ctor_properties (ctype, decl)
      added to any ctor so we can tell if the class has been initialized
      yet.  This could screw things up in this function, so we deliberately
      ignore the leading int if we're in that situation.  */
-  if (parmtypes
-      && TREE_VALUE (parmtypes) == integer_type_node
-      && TYPE_USES_VIRTUAL_BASECLASSES (ctype))
+  if (TYPE_USES_VIRTUAL_BASECLASSES (ctype))
     {
+      my_friendly_assert (parmtypes
+                         && TREE_VALUE (parmtypes) == integer_type_node,
+                         980529);
       parmtypes = TREE_CHAIN (parmtypes);
       parmtype = TREE_VALUE (parmtypes);
     }
@@ -10969,6 +11142,17 @@ xref_tag (code_type_node, name, binfo, globalize)
   register tree ref, t;
   struct binding_level *b = inner_binding_level;
   int got_type = 0;
+  tree attributes = NULL_TREE;
+
+  /* If we are called from the parser, code_type_node will sometimes be a
+     TREE_LIST.  This indicates that the user wrote
+     "class __attribute__ ((foo)) bar".  Extract the attributes so we can
+     use them later.  */
+  if (TREE_CODE (code_type_node) == TREE_LIST)
+    {
+      attributes = TREE_PURPOSE (code_type_node);
+      code_type_node = TREE_VALUE (code_type_node);
+    }
 
   tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
   switch (tag_code)
@@ -11144,6 +11328,8 @@ xref_tag (code_type_node, name, binfo, globalize)
 
   pop_obstacks ();
 
+  TREE_TYPE (ref) = attributes;
+
   return ref;
 }
 
@@ -11210,10 +11396,6 @@ xref_basetypes (code_type_node, name, ref, binfo)
       tree basetype = TREE_VALUE (binfo);
       tree base_binfo;
 
-      GNU_xref_hier (IDENTIFIER_POINTER (name),
-                    IDENTIFIER_POINTER (TREE_VALUE (binfo)),
-                    via_public, via_virtual, 0);
-
       if (basetype && TREE_CODE (basetype) == TYPE_DECL)
        basetype = TREE_TYPE (basetype);
       if (!basetype
@@ -11226,11 +11408,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
                    TREE_VALUE (binfo));
          continue;
        }
+
+      GNU_xref_hier (name, basetype, via_public, via_virtual, 0);
+
 #if 1
       /* This code replaces similar code in layout_basetypes.
          We put the complete_type first for implicit `typename'.  */
-      else if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE
-              && ! (current_template_parms && uses_template_parms (basetype)))
+      if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE
+         && ! (current_template_parms && uses_template_parms (basetype)))
        {
          cp_error ("base class `%T' has incomplete type", basetype);
          continue;
@@ -11247,6 +11432,10 @@ xref_basetypes (code_type_node, name, ref, binfo)
              continue;
            }
 
+         if (TYPE_FOR_JAVA (basetype)
+             && current_lang_stack == current_lang_base)
+           TYPE_FOR_JAVA (ref) = 1;
+
          /* Note that the BINFO records which describe individual
             inheritances are *not* shared in the lattice!  They
             cannot be shared because a given baseclass may be
@@ -11318,8 +11507,13 @@ start_enum (name)
   register tree enumtype = NULL_TREE;
   struct binding_level *b = inner_binding_level;
 
+  /* We are wasting space here and putting these on the permanent_obstack so
+     that typeid(local enum) will work correctly. */
+#if 0
   if (processing_template_decl && current_function_decl)
-    end_temporary_allocation ();
+#endif
+   
+  end_temporary_allocation ();
 
   /* If this is the real definition for a previous forward reference,
      fill in the contents in the same object that used to be the
@@ -11724,9 +11918,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
 
       if (TREE_CODE (fntype) == METHOD_TYPE)
        ctype = TYPE_METHOD_BASETYPE (fntype);
-      else if (IDENTIFIER_LENGTH (DECL_NAME (decl1)) == 4
-              && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (decl1)), "main")
-              && DECL_CONTEXT (decl1) == NULL_TREE)
+      else if (DECL_MAIN_P (decl1))
        {
          /* If this doesn't return integer_type, complain.  */
          if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
@@ -11815,9 +12007,13 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
          && ! DECL_FUNCTION_MEMBER_P (decl1))
        decl1 = pushdecl (decl1);
       else
-       /* We need to set the DECL_CONTEXT. */
-       if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
-         DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
+       {
+         /* We need to set the DECL_CONTEXT. */
+         if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
+           DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
+         /* And make sure we have enough default args.  */
+         check_default_args (decl1);
+       }
       DECL_MAIN_VARIANT (decl1) = decl1;
       fntype = TREE_TYPE (decl1);
     }
@@ -12121,13 +12317,8 @@ store_parm_decls ()
 
   /* If this function is `main', emit a call to `__main'
      to run global initializers, etc.  */
-  if (DECL_NAME (fndecl)
-      && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
-      && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0
-      && DECL_CONTEXT (fndecl) == global_namespace)
-    {
-      expand_main_function ();
-    }
+  if (DECL_MAIN_P (fndecl))
+    expand_main_function ();
 
   /* Now that we have initialized the parms, we can start their
      cleanups.  We cannot do this before, since expand_decl_cleanup
@@ -12410,20 +12601,22 @@ finish_function (lineno, call_poplevel, nested)
          virtual_size = c_sizeof (current_class_type);
 
          /* At the end, call delete if that's what's requested.  */
-         if (TYPE_GETS_REG_DELETE (current_class_type))
-           /* This NOP_EXPR means we are in a static call context.  */
-           exprstmt
-             = build_method_call (build_indirect_ref (build1 (NOP_EXPR,
-                                                              build_pointer_type (current_class_type),
-                                                              error_mark_node),
-                                                      NULL_PTR),
-                                  ansi_opname[(int) DELETE_EXPR],
-                                  expr_tree_cons (NULL_TREE, current_class_ptr,
-                                             build_expr_list (NULL_TREE, virtual_size)),
-                                  NULL_TREE, LOOKUP_NORMAL);
-         else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
-           exprstmt = build_x_delete (ptr_type_node, current_class_ptr, 0,
-                                      virtual_size);
+
+         /* FDIS sez: At the point of definition of a virtual destructor
+              (including an implicit definition), non-placement operator
+              delete shall be looked up in the scope of the destructor's
+              class and if found shall be accessible and unambiguous.
+
+            This is somewhat unclear, but I take it to mean that if the
+            class only defines placement deletes we don't do anything here.
+            So we pass LOOKUP_SPECULATIVELY; delete_sanity will complain
+            for us if they ever try to delete one of these.  */
+
+         if (TYPE_GETS_REG_DELETE (current_class_type)
+             || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+           exprstmt = build_op_delete_call
+             (DELETE_EXPR, current_class_ptr, virtual_size,
+              LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
          else
            exprstmt = NULL_TREE;
 
@@ -12504,7 +12697,8 @@ finish_function (lineno, call_poplevel, nested)
                  expand_end_bindings (decls, decls != NULL_TREE, 0);
                  poplevel (decls != NULL_TREE, 0, 0);
                }
-             c_expand_return (current_class_ptr);
+             /* c_expand_return knows to return 'this' from a constructor.  */
+             c_expand_return (NULL_TREE);
            }
          else if (TREE_CODE (TREE_TYPE (DECL_RESULT (current_function_decl))) != VOID_TYPE
                   && return_label != NULL_RTX)
@@ -12571,14 +12765,13 @@ finish_function (lineno, call_poplevel, nested)
              poplevel (decls != NULL_TREE, 1, 0);
            }
 
-         c_expand_return (current_class_ptr);
+         /* c_expand_return knows to return 'this' from a constructor.  */
+         c_expand_return (NULL_TREE);
 
          current_function_assigns_this = 0;
          current_function_just_assigned_this = 0;
        }
-      else if (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
-              && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")
-              && DECL_CONTEXT (fndecl) == global_namespace)
+      else if (DECL_MAIN_P (fndecl))
        {
          /* Make it so that `main' always returns 0 by default.  */
 #ifdef VMS