]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/cp/decl2.c
cvt.c, [...]: Clean up more old overloading code, old RTTI code, and some formatting...
[gcc.git] / gcc / cp / decl2.c
index 85b58761ef7b83610c0a2f9ea64ae6a5b390acdb..e337b18d01f0adeaebe0a0281bc9aa7463b97978 100644 (file)
@@ -36,11 +36,26 @@ Boston, MA 02111-1307, USA.  */
 #include "decl.h"
 #include "lex.h"
 #include "output.h"
+#include "except.h"
+#include "expr.h"
+#include "defaults.h"
 
-extern tree get_file_function_name ();
-extern tree cleanups_this_call;
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+static tree get_sentry PROTO((tree));
+static void mark_vtable_entries PROTO((tree));
+static void import_export_template PROTO((tree));
 static void grok_function_init PROTO((tree, tree));
-void import_export_decl ();
+static int finish_vtable_vardecl PROTO((tree, tree));
+static int prune_vtable_vardecl PROTO((tree, tree));
+static void finish_sigtable_vardecl PROTO((tree, tree));
+
 extern int current_class_depth;
 
 /* A list of virtual function tables we must make sure to write out.  */
@@ -75,6 +90,12 @@ int at_eof;
 /* Functions called along with real static constructors and destructors.  */
 
 tree static_ctors, static_dtors;
+
+/* The current open namespace, and :: */
+
+tree current_namespace;
+tree global_namespace;
+
 \f
 /* C (and C++) language-specific option variables.  */
 
@@ -122,11 +143,6 @@ int flag_no_ident;
 
 int flag_ansi;
 
-/* Nonzero means do argument matching for overloading according to the
-   ANSI rules, rather than what g++ used to believe to be correct.  */
-
-int flag_ansi_overloading = 1;
-
 /* Nonzero means do emit exported implementations of functions even if
    they can be inlined.  */
 
@@ -159,11 +175,10 @@ int warn_ctor_dtor_privacy = 1;
 /* True if we want to implement vtables using "thunks".
    The default is off.  */
 
-#if defined(NEW_OVER) && defined (__i386__)
-int flag_vtable_thunks = 1;
-#else
-int flag_vtable_thunks;
+#ifndef DEFAULT_VTABLE_THUNKS
+#define DEFAULT_VTABLE_THUNKS 0
 #endif
+int flag_vtable_thunks = DEFAULT_VTABLE_THUNKS;
 
 /* True if we want to deal with repository information.  */
 
@@ -245,8 +260,24 @@ int warn_synth;
    into a pointer to (void or function).  */
 int warn_pmf2ptr = 1;
 
-/* Nonzero means `$' can be in an identifier.
-   See cccp.c for reasons why this breaks some obscure ANSI C programs.  */
+/* Nonzero means warn about violation of some Effective C++ style rules.  */
+
+int warn_ecpp;
+
+/* Nonzero means warn where overload resolution chooses a promotion from
+   unsigned to signed over a conversion to an unsigned of the same size.  */
+
+int warn_sign_promo;
+
+/* Nonzero means warn when an old-style cast is used.  */
+
+int warn_old_style_cast;
+
+/* Warn about #pragma directives that are not recognised.  */      
+
+int warn_unknown_pragmas = 0; /* Tri state variable.  */  
+
+/* Nonzero means `$' can be in an identifier.  */
 
 #ifndef DOLLARS_IN_IDENTIFIERS
 #define DOLLARS_IN_IDENTIFIERS 1
@@ -298,7 +329,9 @@ int flag_memoize_lookups; int flag_save_memoized_contexts;
 
 int write_virtuals;
 
-/* Nonzero means we should attempt to elide constructors when possible.  */
+/* Nonzero means we should attempt to elide constructors when possible.
+   FIXME: This flag is obsolete, and should be torn out along with the
+   old overloading code.  */
 
 int flag_elide_constructors;
 
@@ -376,6 +409,25 @@ int flag_new_for_scope = 1;
 
 int flag_weak = 1;
 
+/* Maximum template instantiation depth. Must be at least 17 for ANSI
+   compliance. */
+
+int max_tinst_depth = 17;
+
+/* The name-mangling scheme to use.  Must be 1 or greater to support
+   template functions with identical types, but different template
+   arguments.  */
+int name_mangling_version = 2;
+
+/* Nonzero means that guiding declarations are allowed.  */
+int flag_guiding_decls;
+
+/* Nonzero if squashed mangling is to be performed. 
+   This uses the B and K codes to reference previously seen class types 
+   and class qualifiers.       */
+int flag_do_squangling;
+
+
 /* Table of language-dependent -f options.
    STRING is the option name.  VARIABLE is the address of the variable.
    ON_VALUE is the value to store in VARIABLE
@@ -391,6 +443,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
   {"short-enums", &flag_short_enums, 1},
   {"short-double", &flag_short_double, 1},
   {"cond-mismatch", &flag_cond_mismatch, 1},
+  {"squangle", &flag_do_squangling, 1},
   {"asm", &flag_no_asm, 0},
   {"builtin", &flag_no_builtin, 0},
   {"ident", &flag_no_ident, 0},
@@ -401,6 +454,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
   {"all-virtual", &flag_all_virtual, 1},
   {"memoize-lookups", &flag_memoize_lookups, 1},
   {"elide-constructors", &flag_elide_constructors, 1},
+  {"handle-exceptions", &flag_exceptions, 1},
   {"handle-signatures", &flag_handle_signatures, 1},
   {"default-inline", &flag_default_inline, 1},
   {"dollars-in-identifiers", &dollars_in_ident, 1},
@@ -411,11 +465,9 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
   {"implement-inlines", &flag_implement_inlines, 1},
   {"external-templates", &flag_external_templates, 1},
   {"implicit-templates", &flag_implicit_templates, 1},
-  {"ansi-overloading", &flag_ansi_overloading, 1},
   {"huge-objects", &flag_huge_objects, 1},
   {"conserve-space", &flag_conserve_space, 1},
   {"vtable-thunks", &flag_vtable_thunks, 1},
-  {"short-temps", &flag_short_temps, 1},
   {"access-control", &flag_access_control, 1},
   {"nonansi-builtins", &flag_no_nonansi_builtin, 0},
   {"gnu-keywords", &flag_no_gnu_keywords, 0},
@@ -435,7 +487,7 @@ lang_decode_option (p)
      char *p;
 {
   if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
-    dollars_in_ident = 1, flag_writable_strings = 1,
+    flag_writable_strings = 1,
     flag_this_is_variable = 1, flag_new_for_scope = 0;
   /* The +e options are for cfront compatibility.  They come in as
      `-+eN', to kludge around gcc.c's argument handling.  */
@@ -463,13 +515,17 @@ lang_decode_option (p)
       p += 2;
       /* Try special -f options.  */
 
+      if (!strcmp (p, "handle-exceptions")
+         || !strcmp (p, "no-handle-exceptions"))
+       warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)");
+
       if (!strcmp (p, "save-memoized"))
        {
          flag_memoize_lookups = 1;
          flag_save_memoized_contexts = 1;
          found = 1;
        }
-      if (!strcmp (p, "no-save-memoized"))
+      else if (!strcmp (p, "no-save-memoized"))
        {
          flag_memoize_lookups = 0;
          flag_save_memoized_contexts = 0;
@@ -492,6 +548,56 @@ lang_decode_option (p)
          flag_implicit_templates = 0;
          found = 1;
        }
+      else if (!strcmp (p, "guiding-decls"))
+       {
+         flag_guiding_decls = 1;
+         name_mangling_version = 0;
+         found = 1;
+       }
+      else if (!strcmp (p, "no-guiding-decls"))
+       {
+         flag_guiding_decls = 0;
+         found = 1;
+       }
+      else if (!strcmp (p, "ansi-overloading"))
+       found = 1;
+      else if (!strcmp (p, "no-ansi-overloading"))
+       {
+         error ("-fno-ansi-overloading is no longer supported");
+         found = 1;
+       }
+      else if (!strncmp (p, "template-depth-", 15))
+       {
+         char *endp = p + 15;
+         while (*endp)
+           {
+             if (*endp >= '0' && *endp <= '9')
+               endp++;
+             else
+               {
+                 error ("Invalid option `%s'", p - 2);
+                 goto template_depth_lose;
+               }
+           }
+         max_tinst_depth = atoi (p + 15);
+       template_depth_lose: ;
+       }
+      else if (!strncmp (p, "name-mangling-version-", 22))
+       {
+         char *endp = p + 22;
+         while (*endp)
+           {
+             if (*endp >= '0' && *endp <= '9')
+               endp++;
+             else
+               {
+                 error ("Invalid option `%s'", p - 2);
+                 goto mangling_version_lose;
+               }
+           }
+         name_mangling_version = atoi (p + 22);
+       mangling_version_lose: ;
+       }
       else for (j = 0;
                !found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]);
                j++)
@@ -560,6 +666,16 @@ lang_decode_option (p)
        warn_synth = setting;
       else if (!strcmp (p, "pmf-conversions"))
        warn_pmf2ptr = setting;
+      else if (!strcmp (p, "effc++"))
+       warn_ecpp = setting;
+      else if (!strcmp (p, "sign-promo"))
+       warn_sign_promo = setting;
+      else if (!strcmp (p, "old-style-cast"))
+       warn_old_style_cast = setting;
+      else if (!strcmp (p, "unknown-pragmas"))
+       /* Set to greater than 1, so that even unknown pragmas in
+          system headers will be warned about.  */  
+       warn_unknown_pragmas = setting * 2;
       else if (!strcmp (p, "comment"))
        ;                       /* cpp handles this one.  */
       else if (!strcmp (p, "comments"))
@@ -588,6 +704,10 @@ lang_decode_option (p)
            warn_uninitialized = (setting ? 2 : 0);
          warn_template_debugging = setting;
          warn_reorder = setting;
+         warn_sign_promo = setting;
+         /* Only warn about unknown pragmas that are not in system
+            headers.  */                                        
+         warn_unknown_pragmas = 1;                  
        }
 
       else if (!strcmp (p, "overloaded-virtual"))
@@ -595,7 +715,7 @@ lang_decode_option (p)
       else return 0;
     }
   else if (!strcmp (p, "-ansi"))
-    dollars_in_ident = 0, flag_no_nonansi_builtin = 1, flag_ansi = 1,
+    flag_no_nonansi_builtin = 1, flag_ansi = 1,
     flag_no_gnu_keywords = 1, flag_operator_names = 1;
 #ifdef SPEW_DEBUG
   /* Undocumented, only ever used when you're invoking cc1plus by hand, since
@@ -661,26 +781,6 @@ grok_method_quals (ctype, function, quals)
   return ctype;
 }
 
-#if 0                          /* Not used.  */
-/* This routine replaces cryptic DECL_NAMEs with readable DECL_NAMEs.
-   It leaves DECL_ASSEMBLER_NAMEs with the correct value.  */
-/* This does not yet work with user defined conversion operators
-   It should.  */
-
-static void
-substitute_nice_name (decl)
-     tree decl;
-{
-  if (DECL_NAME (decl) && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE)
-    {
-      char *n = decl_as_string (DECL_NAME (decl), 1);
-      if (n[strlen (n) - 1] == ' ')
-       n[strlen (n) - 1] = 0;
-      DECL_NAME (decl) = get_identifier (n);
-    }
-}
-#endif
-
 /* Warn when -fexternal-templates is used and #pragma
    interface/implementation is not used all the times it should be,
    inform the user.  */
@@ -810,7 +910,7 @@ grok_x_components (specs, components)
                  break;
            }
          else if (TREE_CODE (t) == ENUMERAL_TYPE)
-           x = grok_enum_decls (t, NULL_TREE);
+           x = grok_enum_decls (NULL_TREE);
          else
            x = NULL_TREE;
          return x;
@@ -823,13 +923,12 @@ grok_x_components (specs, components)
        }
     }
   else
-    {
-      t = TREE_TYPE (components);
-      if (TREE_CODE (t) == ENUMERAL_TYPE && TREE_NONLOCAL_FLAG (t))
-       return grok_enum_decls (t, components);
-      else
-       return components;
-    }
+    /* There may or may not be any enum decls to grok, but
+       grok_enum_decls will just return components, if there aren't
+       any.  We used to try to figure out whether or not there were
+       any enum decls based on the type of components, but that's too
+       hard; it might be something like `enum { a } *p;'.  */
+    return grok_enum_decls (components);
 }
 
 /* Classes overload their constituent function names automatically.
@@ -924,16 +1023,16 @@ grokclassfn (ctype, cname, function, flags, quals)
   if (flags == DTOR_FLAG)
     {
       char *buf, *dbuf;
-      tree const_integer_type = build_type_variant (integer_type_node, 1, 0);
       int len = sizeof (DESTRUCTOR_DECL_PREFIX)-1;
 
-      arg_types = hash_tree_chain (const_integer_type, void_list_node);
+      arg_types = hash_tree_chain (integer_type_node, void_list_node);
       TREE_SIDE_EFFECTS (arg_types) = 1;
       /* Build the overload name.  It will look like `7Example'.  */
       if (IDENTIFIER_TYPE_VALUE (cname))
        dbuf = build_overload_name (IDENTIFIER_TYPE_VALUE (cname), 1, 1);
       else if (IDENTIFIER_LOCAL_VALUE (cname))
-       dbuf = build_overload_name (TREE_TYPE (IDENTIFIER_LOCAL_VALUE (cname)), 1, 1);
+       dbuf = build_overload_name (TREE_TYPE (IDENTIFIER_LOCAL_VALUE (cname)),
+                                   1, 1);
       else
       /* Using ctype fixes the `X::Y::~Y()' crash.  The cname has no type when
         it's defined out of the class definition, since poplevel_class wipes
@@ -990,14 +1089,6 @@ grokclassfn (ctype, cname, function, flags, quals)
       DECL_ASSEMBLER_NAME (function)
        = build_decl_overload (fn_name, these_arg_types,
                               1 + DECL_CONSTRUCTOR_P (function));
-
-#if 0
-      /* This code is going into the compiler, but currently, it makes
-        libg++/src/Integer.cc not compile.  The problem is that the nice name
-        winds up going into the symbol table, and conversion operations look
-        for the manged name.  */
-      substitute_nice_name (function);
-#endif
     }
 
   DECL_ARGUMENTS (function) = last_function_parms;
@@ -1015,6 +1106,9 @@ grok_alignof (expr)
   tree best, t;
   int bestalign;
 
+  if (processing_template_decl)
+    return build_min (ALIGNOF_EXPR, sizetype, expr);
+
   if (TREE_CODE (expr) == COMPONENT_REF
       && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
     error ("`__alignof__' applied to a bit-field");
@@ -1078,8 +1172,7 @@ grok_array_decl (array_expr, index_exp)
     type = TREE_TYPE (type);
 
   /* If they have an `operator[]', use that.  */
-  if (TYPE_LANG_SPECIFIC (type)
-      && TYPE_OVERLOADS_ARRAY_REF (complete_type (type)))
+  if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
     return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
                           array_expr, index_exp, NULL_TREE);
 
@@ -1149,7 +1242,10 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
       return t;
     }
 
-  t = stabilize_reference (convert_from_reference (exp));
+  t = exp;
+  if (TREE_CODE (t) == OFFSET_REF)
+    t = resolve_offset_ref (t);
+  t = stabilize_reference (convert_from_reference (t));
   type = TREE_TYPE (t);
   code = TREE_CODE (type);
 
@@ -1177,15 +1273,14 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
   if (code == POINTER_TYPE)
     {
 #if 0
-      /* As of Valley Forge, you can delete a pointer to constant.  */
-      /* You can't delete a pointer to constant.  */
+      /* As of Valley Forge, you can delete a pointer to const.  */
       if (TREE_READONLY (TREE_TYPE (type)))
        {
          error ("`const *' cannot be deleted");
          return error_mark_node;
        }
 #endif
-      /* You also can't delete functions.  */
+      /* You can't delete functions.  */
       if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
        {
          error ("cannot delete a function");
@@ -1217,16 +1312,65 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
        {
          /* Only do access checking here; we'll be calling op delete
             from the destructor.  */
-         tree tmp = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, t,
-                                    size_zero_node, NULL_TREE);
+         tree tmp = build_op_delete_call (DELETE_EXPR, t,
+                                          size_zero_node, LOOKUP_NORMAL);
          if (tmp == error_mark_node)
            return error_mark_node;
        }
 
       return build_delete (type, t, integer_three_node,
-                          LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE,
-                          use_global_delete);
+                          LOOKUP_NORMAL, use_global_delete);
+    }
+}
+
+/* Report an error if the indicated template declaration is not the
+   sort of thing that should be a member template.  */
+
+void
+check_member_template (tmpl)
+     tree tmpl;
+{
+  tree decl;
+
+  my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+  decl = DECL_TEMPLATE_RESULT (tmpl);
+
+  if (TREE_CODE (decl) == FUNCTION_DECL) 
+    {
+      if (current_function_decl)
+       /* 14.5.2.2 [temp.mem]
+          
+          A local class shall not have member templates. */
+       cp_error ("declaration of of member template `%#D' in local class",
+                 decl);
+      
+      if (DECL_VIRTUAL_P (decl)) 
+       {
+         /* 14.5.2.3 [temp.mem]
+
+            A member function template shall not be virtual.  */
+         cp_error 
+           ("invalid use of `virtual' in template declaration of `%#D'",
+            decl);
+         DECL_VIRTUAL_P (decl) = 0;
+       }
+
+      /* The debug-information generating code doesn't know what to do
+        with member templates.  */ 
+      DECL_IGNORED_P (tmpl) = 1;
+    } 
+  else if (TREE_CODE (decl) == TYPE_DECL
+          && IS_AGGR_TYPE (TREE_TYPE (decl)))
+    {
+      if (current_function_decl)
+       /* 14.5.2.2 [temp.mem]
+
+          A local class shall not have member templates.  */
+       cp_error ("declaration of of member template `%#D' in local class",
+                 decl);
     }
+  else
+    cp_error ("template declaration of `%#D'", decl);
 }
 
 /* Sanity check: report error if this function FUNCTION is not
@@ -1242,6 +1386,7 @@ check_classfn (ctype, function)
   tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
   tree *methods = 0;
   tree *end = 0;
+  tree templates = NULL_TREE;
 
   if (method_vec != 0)
     {
@@ -1258,22 +1403,26 @@ check_classfn (ctype, function)
 
       while (++methods != end)
        {
+         fndecl = *methods;
          if (fn_name == DECL_NAME (*methods))
            {
            got_it:
-             fndecl = *methods;
-             while (fndecl)
+             for (fndecl = *methods; fndecl != NULL_TREE;
+                  fndecl = DECL_CHAIN (fndecl))
                {
-                 if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl))
-                   return fndecl;
-#if 0
-                 /* This doesn't work for static member functions that are
-                     pretending to be methods.  */
-                 /* We have to do more extensive argument checking here, as
-                    the name may have been changed by asm("new_name").  */
-                 if (decls_match (function, fndecl))
+                 /* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL is
+                    not mangled, so the check below does not work
+                    correctly in that case.  */
+                 if (TREE_CODE (function) != TEMPLATE_DECL
+                     && TREE_CODE (fndecl) != TEMPLATE_DECL
+                     && (DECL_ASSEMBLER_NAME (function) 
+                         == DECL_ASSEMBLER_NAME (fndecl)))
                    return fndecl;
-#else
+
+                 /* We cannot simply call decls_match because this
+                    doesn't work for static member functions that are 
+                     pretending to be methods, and because the name
+                    may have been changed by asm("new_name").  */ 
                  if (DECL_NAME (function) == DECL_NAME (fndecl))
                    {
                      tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
@@ -1287,16 +1436,44 @@ check_classfn (ctype, function)
 
                      if (comptypes (TREE_TYPE (TREE_TYPE (function)),
                                     TREE_TYPE (TREE_TYPE (fndecl)), 1)
-                         && compparms (p1, p2, 3))
+                         && compparms (p1, p2, 3)
+                         && (DECL_TEMPLATE_SPECIALIZATION (function)
+                             == DECL_TEMPLATE_SPECIALIZATION (fndecl))
+                         && (!DECL_TEMPLATE_SPECIALIZATION (function)
+                             || (DECL_TI_TEMPLATE (function) 
+                                 == DECL_TI_TEMPLATE (fndecl))))
                        return fndecl;
+
+                     if (is_member_template (fndecl))
+                       /* This function might be an instantiation
+                          or specialization of fndecl.  */
+                       templates = 
+                         scratch_tree_cons (NULL_TREE, fndecl, templates);
                    }
-#endif
-                 fndecl = DECL_CHAIN (fndecl);
                }
              break;            /* loser */
            }
-       }
-    }
+         else if (TREE_CODE (fndecl) == TEMPLATE_DECL 
+                  && IDENTIFIER_TYPENAME_P (DECL_NAME (fndecl))
+                  && IDENTIFIER_TYPENAME_P (fn_name))
+           /* The method in the class is a member template
+              conversion operator.  We are declaring another
+              conversion operator.  It is possible that even though
+              the names don't match, there is some specialization
+              occurring.  */
+           templates = 
+             scratch_tree_cons (NULL_TREE, fndecl, templates);
+       }
+    }
+
+  if (templates)
+    /* This function might be an instantiation or a specialization.
+       We should verify that this is possible.  If it is, we must
+       somehow add the new declaration to the method vector for the
+       class.  Perhaps we should use add_method?  For now, we simply
+       return NULL_TREE, which lets the caller know that this
+       function is new, but we don't print an error message.  */
+    return NULL_TREE;
 
   if (methods != end)
     {
@@ -1391,7 +1568,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
   if (DECL_NAME (value) != NULL_TREE
       && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_'
       && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr"))
-    cp_error ("member `%D' conflicts with virtual function table field name", value);
+    cp_error ("member `%D' conflicts with virtual function table field name",
+             value);
 
   /* Stash away type declarations.  */
   if (TREE_CODE (value) == TYPE_DECL)
@@ -1485,7 +1663,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
 
   if (processing_template_decl && ! current_function_decl
       && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
-    push_template_decl (value);
+    value = push_template_decl (value);
 
   if (attrlist)
     cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
@@ -1493,38 +1671,37 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
 
   if (TREE_CODE (value) == VAR_DECL)
     {
+      my_friendly_assert (TREE_PUBLIC (value), 0);
+
       /* We cannot call pushdecl here, because that would
         fill in the value of our TREE_CHAIN.  Instead, we
         modify cp_finish_decl to do the right thing, namely, to
         put this decl out straight away.  */
-      if (TREE_PUBLIC (value))
+      /* current_class_type can be NULL_TREE in case of error.  */
+      if (asmspec == 0 && current_class_type)
        {
-         /* current_class_type can be NULL_TREE in case of error.  */
-         if (asmspec == 0 && current_class_type)
-           {
-             TREE_PUBLIC (value) = 1;
-             DECL_INITIAL (value) = error_mark_node;
-             DECL_ASSEMBLER_NAME (value)
-               = build_static_name (current_class_type, DECL_NAME (value));
-           }
-         if (! processing_template_decl)
-           pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics);
-
-         /* Static consts need not be initialized in the class definition.  */
-         if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (value)))
-           {
-             static int explanation = 0;
-
-             error ("initializer invalid for static member with constructor");
-             if (explanation++ == 0)
-               error ("(you really want to initialize it separately)");
-             init = 0;
-           }
-         /* Force the compiler to know when an uninitialized static
-            const member is being used.  */
-         if (TYPE_READONLY (value) && init == 0)
-           TREE_USED (value) = 1;
+         TREE_PUBLIC (value) = 1;
+         DECL_INITIAL (value) = error_mark_node;
+         DECL_ASSEMBLER_NAME (value)
+           = build_static_name (current_class_type, DECL_NAME (value));
        }
+      if (! processing_template_decl)
+       pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics);
+      
+      /* Static consts need not be initialized in the class definition.  */
+      if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (value)))
+       {
+         static int explanation = 0;
+         
+         error ("initializer invalid for static member with constructor");
+         if (explanation++ == 0)
+           error ("(you really want to initialize it separately)");
+         init = 0;
+       }
+      /* Force the compiler to know when an uninitialized static
+        const member is being used.  */
+      if (TYPE_READONLY (value) && init == 0)
+       TREE_USED (value) = 1;
       DECL_INITIAL (value) = init;
       DECL_IN_AGGR_P (value) = 1;
       DECL_CONTEXT (value) = current_class_type;
@@ -1698,7 +1875,11 @@ copy_assignment_arg_p (parmtype, virtualp)
     parmtype = TREE_TYPE (parmtype);
 
   if ((TYPE_MAIN_VARIANT (parmtype) == current_class_type)
-      || (virtualp && DERIVED_FROM_P (parmtype, current_class_type)))
+#if 0
+      /* Non-standard hack to support old Booch components.  */
+      || (! virtualp && DERIVED_FROM_P (parmtype, current_class_type))
+#endif
+      )
     return 1;
 
   return 0;
@@ -1745,33 +1926,6 @@ grok_function_init (decl, init)
            TYPE_HAS_ABSTRACT_ASSIGN_REF (current_class_type) = 1;
        }
     }
-  else if (TREE_CODE (init) == OFFSET_REF
-          && TREE_OPERAND (init, 0) == NULL_TREE
-          && TREE_CODE (TREE_TYPE (init)) == METHOD_TYPE)
-    {
-      tree basetype = DECL_CLASS_CONTEXT (init);
-      tree basefn = TREE_OPERAND (init, 1);
-      if (TREE_CODE (basefn) != FUNCTION_DECL)
-       cp_error ("non-method initializer invalid for method `%D'", decl);
-      else if (! BINFO_OFFSET_ZEROP (TYPE_BINFO (DECL_CLASS_CONTEXT (basefn))))
-       sorry ("base member function from other than first base class");
-      else
-       {
-         tree binfo = get_binfo (basetype, TYPE_METHOD_BASETYPE (type), 1);
-         if (binfo == error_mark_node)
-           ;
-         else if (binfo == 0)
-           error_not_base_type (TYPE_METHOD_BASETYPE (TREE_TYPE (init)),
-                                TYPE_METHOD_BASETYPE (type));
-         else
-           {
-             /* Mark this function as being defined,
-                and give it new rtl.  */
-             DECL_INITIAL (decl) = error_mark_node;
-             DECL_RTL (decl) = DECL_RTL (basefn);
-           }
-       }
-    }
   else
     cp_error ("invalid initializer for virtual method `%D'", decl);
 }
@@ -1802,7 +1956,8 @@ tree
 constructor_name_full (thing)
      tree thing;
 {
-  if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM)
+  if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM
+      || TREE_CODE (thing) == TEMPLATE_TEMPLATE_PARM)
     thing = TYPE_NAME (thing);
   else if (IS_AGGR_TYPE_CODE (TREE_CODE (thing)))
     {
@@ -1953,35 +2108,22 @@ tree
 get_temp_regvar (type, init)
      tree type, init;
 {
-  static char buf[sizeof (AUTO_TEMP_FORMAT) + 20] = { '_' };
   tree decl;
 
-  sprintf (buf+1, AUTO_TEMP_FORMAT, temp_name_counter++);
-  decl = build_decl (VAR_DECL, get_identifier (buf), type);
+  decl = build_decl (VAR_DECL, NULL_TREE, type);
   TREE_USED (decl) = 1;
   DECL_REGISTER (decl) = 1;
+  DECL_ARTIFICIAL (decl) = 1;
 
-  if (init)
-    store_init_value (decl, init);
-
+  DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
   /* We can expand these without fear, since they cannot need
      constructors or destructors.  */
-  expand_decl (decl);
-  expand_decl_init (decl);
+  expand_expr (build_modify_expr (decl, INIT_EXPR, init),
+              NULL_RTX, VOIDmode, 0);
 
   return decl;
 }
 
-/* Make the macro TEMP_NAME_P available to units which do not
-   include c-tree.h.  */
-
-int
-temp_name_p (decl)
-     tree decl;
-{
-  return TEMP_NAME_P (decl);
-}
-
 /* Finish off the processing of a UNION_TYPE structure.
    If there are static members, then all members are
    static, and must be laid out together.  If the
@@ -2046,7 +2188,7 @@ finish_anon_union (anon_union_decl)
       DECL_INITIAL (decl) = NULL_TREE;
       /* If there's a cleanup to do, it belongs in the
         TREE_PURPOSE of the following TREE_LIST.  */
-      elems = tree_cons (NULL_TREE, decl, elems);
+      elems = scratch_tree_cons (NULL_TREE, decl, elems);
       TREE_TYPE (elems) = type;
     }
   if (static_p)
@@ -2068,82 +2210,6 @@ finish_anon_union (anon_union_decl)
   expand_anon_union_decl (anon_union_decl, NULL_TREE, elems);
 }
 
-/* Finish and output a table which is generated by the compiler.
-   NAME is the name to give the table.
-   TYPE is the type of the table entry.
-   INIT is all the elements in the table.
-   PUBLICP is non-zero if this table should be given external access.  */
-
-tree
-finish_table (name, type, init, publicp)
-     tree name, type, init;
-     int publicp;
-{
-  tree itype, atype, decl;
-  static tree empty_table;
-  int is_empty = 0;
-  tree asmspec;
-
-  itype = build_index_type (size_int (list_length (init) - 1));
-  atype = build_cplus_array_type (type, itype);
-  layout_type (atype);
-
-  if (TREE_VALUE (init) == integer_zero_node
-      && TREE_CHAIN (init) == NULL_TREE)
-    {
-#if 0
-      if (empty_table == NULL_TREE)
-#endif
-       {
-         empty_table = get_temp_name (atype, 1);
-         init = build (CONSTRUCTOR, atype, NULL_TREE, init);
-         TREE_CONSTANT (init) = 1;
-         TREE_STATIC (init) = 1;
-         DECL_INITIAL (empty_table) = init;
-         asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)),
-                                 IDENTIFIER_POINTER (DECL_NAME (empty_table)));
-         cp_finish_decl (empty_table, NULL_TREE, asmspec, 0, 0);
-       }
-      is_empty = 1;
-    }
-
-  if (name == NULL_TREE)
-    {
-      if (is_empty)
-       return empty_table;
-      decl = get_temp_name (atype, 1);
-    }
-  else
-    {
-      decl = build_decl (VAR_DECL, name, atype);
-      decl = pushdecl (decl);
-      TREE_STATIC (decl) = 1;
-    }
-
-  if (is_empty == 0)
-    {
-      TREE_PUBLIC (decl) = publicp;
-      init = build (CONSTRUCTOR, atype, NULL_TREE, init);
-      TREE_CONSTANT (init) = 1;
-      TREE_STATIC (init) = 1;
-      DECL_INITIAL (decl) = init;
-      asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (decl)),
-                             IDENTIFIER_POINTER (DECL_NAME (decl)));
-    }
-  else
-    {
-      /* This will cause DECL to point to EMPTY_TABLE in rtl-land.  */
-      DECL_EXTERNAL (decl) = 1;
-      TREE_STATIC (decl) = 0;
-      init = 0;
-      asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)),
-                             IDENTIFIER_POINTER (DECL_NAME (empty_table)));
-    }
-
-  cp_finish_decl (decl, NULL_TREE, asmspec, 0, 0);
-  return decl;
-}
-
 /* Finish processing a builtin type TYPE.  It's name is NAME,
    its fields are in the array FIELDS.  LEN is the number of elements
    in FIELDS minus one, or put another way, it is the maximum subscript
@@ -2185,8 +2251,6 @@ finish_builtin_type (type, name, fields, len, align_type)
    `operator new' and `operator delete' correspond to
    what compiler will be expecting.  */
 
-extern tree sizetype;
-
 tree
 coerce_new_type (type)
      tree type;
@@ -2216,7 +2280,10 @@ tree
 coerce_delete_type (type)
      tree type;
 {
-  int e1 = 0, e2 = 0, e3 = 0;
+  int e1 = 0, e2 = 0;
+#if 0
+  e3 = 0;
+#endif
   tree arg_types = TYPE_ARG_TYPES (type);
 
   if (TREE_CODE (type) == METHOD_TYPE)
@@ -2224,12 +2291,15 @@ coerce_delete_type (type)
       type = build_function_type (TREE_TYPE (type), TREE_CHAIN (arg_types));
       arg_types = TREE_CHAIN (arg_types);
     }
+
   if (TREE_TYPE (type) != void_type_node)
     e1 = 1, error ("`operator delete' must return type `void'");
+
   if (arg_types == NULL_TREE
       || TREE_VALUE (arg_types) != ptr_type_node)
     e2 = 1, error ("`operator delete' takes type `void *' as first parameter");
 
+#if 0
   if (arg_types
       && TREE_CHAIN (arg_types)
       && TREE_CHAIN (arg_types) != void_list_node)
@@ -2249,8 +2319,10 @@ coerce_delete_type (type)
            error ("`...' invalid in specification of `operator delete'");
        }
     }
+
   if (e3)
-    arg_types = tree_cons (NULL_TREE, ptr_type_node, build_tree_list (NULL_TREE, sizetype));
+    arg_types = tree_cons (NULL_TREE, ptr_type_node,
+                          build_tree_list (NULL_TREE, sizetype));
   else if (e3 |= e2)
     {
       if (arg_types == NULL_TREE)
@@ -2259,8 +2331,12 @@ coerce_delete_type (type)
        arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types));
     }
   else e3 |= e1;
+#endif
 
-  if (e3)
+  if (e2)
+    arg_types = tree_cons (NULL_TREE, ptr_type_node,
+                          arg_types ? TREE_CHAIN (arg_types): NULL_TREE);
+  if (e2 || e1)
     type = build_function_type (void_type_node, arg_types);
 
   return type;
@@ -2291,7 +2367,11 @@ mark_vtable_entries (decl)
       tree fn = TREE_OPERAND (fnaddr, 0);
       TREE_ADDRESSABLE (fn) = 1;
       if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn))
-       TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl;
+       {
+         TREE_OPERAND (fnaddr, 0) = fn = copy_node (fn);
+         DECL_RTL (fn) = DECL_RTL (abort_fndecl);
+         mark_used (abort_fndecl);
+       }
       if (TREE_CODE (fn) == THUNK_DECL && DECL_EXTERNAL (fn))
        {
          DECL_EXTERNAL (fn) = 0;
@@ -2312,6 +2392,9 @@ comdat_linkage (decl)
     make_decl_one_only (decl);
   else
     TREE_PUBLIC (decl) = 0;
+
+  if (DECL_LANG_SPECIFIC (decl))
+    DECL_COMDAT (decl) = 1;
 }
 
 /* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
@@ -2341,6 +2424,12 @@ import_export_vtable (decl, type, final)
       TREE_PUBLIC (decl) = 1;
       DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type);
       DECL_INTERFACE_KNOWN (decl) = 1;
+
+      /* For WIN32 we also want to put explicit instantiations in
+        linkonce sections.  */
+      if (CLASSTYPE_EXPLICIT_INSTANTIATION (type)
+         && supports_one_only () && ! SUPPORTS_WEAK)
+       make_decl_one_only (decl);
     }
   else
     {
@@ -2349,6 +2438,7 @@ import_export_vtable (decl, type, final)
 
       int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type);
 
+#ifndef MULTIPLE_SYMBOL_SPACES
       if (! found && ! final)
        {
          tree method;
@@ -2362,6 +2452,7 @@ import_export_vtable (decl, type, final)
                break;
              }
        }
+#endif
 
       if (final || ! found)
        {
@@ -2397,7 +2488,7 @@ finish_prevtable_vardecl (prev, vars)
   tree ctype = DECL_CONTEXT (vars);
   import_export_template (ctype);
 
-#ifndef NO_LINKAGE_HEURISTICS
+#ifndef MULTIPLE_SYMBOL_SPACES
   if (CLASSTYPE_INTERFACE_UNKNOWN (ctype) && TYPE_VIRTUAL_P (ctype)
       && ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
     {
@@ -2410,8 +2501,9 @@ finish_prevtable_vardecl (prev, vars)
              && !DECL_ABSTRACT_VIRTUAL_P (method))
            {
              SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
-             CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = ! DECL_EXTERNAL (method);
-             CLASSTYPE_INTERFACE_ONLY (ctype) = DECL_EXTERNAL (method);
+             CLASSTYPE_VTABLE_NEEDS_WRITING (ctype)
+               = ! DECL_REALLY_EXTERN (method);
+             CLASSTYPE_INTERFACE_ONLY (ctype) = DECL_REALLY_EXTERN (method);
              break;
            }
        }
@@ -2429,6 +2521,7 @@ finish_vtable_vardecl (prev, vars)
   if (write_virtuals >= 0
       && ! DECL_EXTERNAL (vars)
       && ((TREE_PUBLIC (vars) && ! DECL_WEAK (vars) && ! DECL_ONE_ONLY (vars))
+         || CLASSTYPE_EXPLICIT_INSTANTIATION (DECL_CONTEXT (vars))
          || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars))
          || (hack_decl_function_context (vars) && TREE_USED (vars)))
       && ! TREE_ASM_WRITTEN (vars))
@@ -2487,8 +2580,8 @@ prune_vtable_vardecl (prev, vars)
 
 int
 walk_vtables (typedecl_fn, vardecl_fn)
-     register void (*typedecl_fn)();
-     register int (*vardecl_fn)();
+     register void (*typedecl_fn) PROTO ((tree, tree));
+     register int (*vardecl_fn) PROTO ((tree, tree));
 {
   tree prev, vars;
   int flag = 0;
@@ -2535,8 +2628,8 @@ finish_sigtable_vardecl (prev, vars)
 
 void
 walk_sigtables (typedecl_fn, vardecl_fn)
-     register void (*typedecl_fn)();
-     register void (*vardecl_fn)();
+     register void (*typedecl_fn) PROTO((tree, tree));
+     register void (*vardecl_fn) PROTO((tree, tree));
 {
   tree prev, vars;
 
@@ -2577,25 +2670,14 @@ import_export_decl (decl)
       if (DECL_IMPLICIT_INSTANTIATION (decl)
          && (flag_implicit_templates || DECL_THIS_INLINE (decl)))
        {
-         if (TREE_CODE (decl) == FUNCTION_DECL)
+         if (!TREE_PUBLIC (decl))
+           /* Templates are allowed to have internal linkage.  See 
+              [basic.link].  */
+           ;
+         else if (TREE_CODE (decl) == FUNCTION_DECL)
            comdat_linkage (decl);
-         /* Dynamically initialized vars go into common.  */
-         else if (DECL_INITIAL (decl) == NULL_TREE
-                  || DECL_INITIAL (decl) == error_mark_node)
-           DECL_COMMON (decl) = 1;
-         else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
-           {
-             DECL_COMMON (decl) = 1;
-             DECL_INITIAL (decl) = error_mark_node;
-           }
          else
-           {
-             /* Statically initialized vars are weak or comdat, if
-                 supported.  */
-             if (flag_weak)
-               make_decl_one_only (decl);
-             /* else leave vars public so multiple defs will break.  */
-           }
+           DECL_COMDAT (decl) = 1;
        }
       else
        DECL_NOT_REALLY_EXTERN (decl) = 0;
@@ -2603,7 +2685,8 @@ import_export_decl (decl)
   else if (DECL_FUNCTION_MEMBER_P (decl))
     {
       tree ctype = DECL_CLASS_CONTEXT (decl);
-      if (CLASSTYPE_INTERFACE_KNOWN (ctype) && ! DECL_ARTIFICIAL (decl))
+      if (CLASSTYPE_INTERFACE_KNOWN (ctype)
+         && (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl)))
        {
          DECL_NOT_REALLY_EXTERN (decl)
            = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
@@ -2622,14 +2705,18 @@ import_export_decl (decl)
          DECL_NOT_REALLY_EXTERN (decl)
            = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
                 || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
+
+         /* For WIN32 we also want to put explicit instantiations in
+            linkonce sections.  */
+         if (CLASSTYPE_EXPLICIT_INSTANTIATION (ctype)
+             && supports_one_only () && ! SUPPORTS_WEAK)
+           make_decl_one_only (decl);
        }
       else if (TYPE_BUILT_IN (ctype) && ctype == TYPE_MAIN_VARIANT (ctype))
        DECL_NOT_REALLY_EXTERN (decl) = 0;
       else
        comdat_linkage (decl);
     } 
-  else if (DECL_C_STATIC (decl))
-    TREE_PUBLIC (decl) = 0;
   else
     comdat_linkage (decl);
 
@@ -2661,13 +2748,15 @@ extern tree pending_templates;
 extern tree maybe_templates;
 
 extern struct obstack permanent_obstack;
-extern tree get_id_2 ();
 
-tree
+static tree
 get_sentry (base)
      tree base;
 {
   tree sname = get_id_2 ("__sn", base);
+  /* for struct X foo __attribute__((weak)), there is a counter
+     __snfoo. Since base is already an assembler name, sname should
+     be globally unique */
   tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
   if (! sentry)
     {
@@ -2702,9 +2791,6 @@ finish_file ()
 
   at_eof = 1;
 
-  if (flag_detailed_statistics)
-    dump_tree_statistics ();
-
   /* Bad parse errors.  Just forget about it.  */
   if (! global_bindings_p () || current_class_type)
     return;
@@ -2735,15 +2821,14 @@ finish_file ()
 
   for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
     {
-      tree *args, fn, decl = TREE_VALUE (fnname);
+      tree args, fn, decl = TREE_VALUE (fnname);
 
       if (DECL_INITIAL (decl))
        continue;
 
       fn = TREE_PURPOSE (fnname);
-      args = get_bindings (fn, decl);
+      args = get_bindings (fn, decl, NULL_TREE);
       fn = instantiate_template (fn, args);
-      free (args);
       instantiate_decl (fn);
     }
 
@@ -2778,26 +2863,15 @@ finish_file ()
 
   /* Walk to mark the inline functions we need, then output them so
      that we can pick up any other tdecls that those routines need.  */
-  walk_vtables ((void (*)())0, finish_prevtable_vardecl);
-
-  for (vars = pending_statics; vars; vars = TREE_CHAIN (vars))
-    {
-      tree decl = TREE_VALUE (vars);
-
-      if (DECL_TEMPLATE_INSTANTIATION (decl)
-         && ! DECL_IN_AGGR_P (decl))
-       {
-         import_export_decl (decl);
-         DECL_EXTERNAL (decl) = ! DECL_NOT_REALLY_EXTERN (decl);
-       }
-    }
+  walk_vtables ((void (*) PROTO ((tree, tree))) 0,
+               finish_prevtable_vardecl);
 
   for (vars = static_aggregates; vars; vars = TREE_CHAIN (vars))
     if (! TREE_ASM_WRITTEN (TREE_VALUE (vars)))
       rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1);
   vars = static_aggregates;
 
-  if (static_ctors || vars || exception_table_p ())
+  if (static_ctors || vars)
     needs_messing_up = 1;
   if (static_dtors)
     needs_cleaning = 1;
@@ -2896,20 +2970,10 @@ finish_file ()
       push_momentary ();
       expand_start_bindings (0);
 
-      if (exception_table_p ())
-       register_exception_table ();
-
       while (vars)
        {
-         extern int temp_slot_level;
-         extern int target_temp_slot_level; 
          tree decl = TREE_VALUE (vars);
          tree init = TREE_PURPOSE (vars);
-         tree old_cleanups = cleanups_this_call;
-         int old_temp_level = target_temp_slot_level;
-         push_temp_slots ();
-         push_temp_slots ();
-         target_temp_slot_level = temp_slot_level;
 
          /* If this was a static attribute within some function's scope,
             then don't initialize it here.  Also, don't bother
@@ -2922,9 +2986,9 @@ finish_file ()
 
          if (TREE_CODE (decl) == VAR_DECL)
            {
-         int protect = (TREE_PUBLIC (decl) && (DECL_COMMON (decl)
-                                               || DECL_ONE_ONLY (decl)
-                                               || DECL_WEAK (decl)));
+             int protect = (TREE_PUBLIC (decl) && (DECL_COMMON (decl)
+                                                   || DECL_ONE_ONLY (decl)
+                                                   || DECL_WEAK (decl)));
 
              /* Set these global variables so that GDB at least puts
                 us near the declaration which required the initialization.  */
@@ -2946,6 +3010,8 @@ finish_file ()
                  expand_start_cond (sentry, 0);
                }
 
+             expand_start_target_temps ();
+
              if (IS_AGGR_TYPE (TREE_TYPE (decl))
                  || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
                expand_aggr_init (decl, init, 0, 0);
@@ -2954,10 +3020,17 @@ finish_file ()
                  expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
                                                TREE_VEC_ELT (init, 1),
                                                TREE_VEC_ELT (init, 2), 0),
-                              const0_rtx, VOIDmode, 0);
+                              const0_rtx, VOIDmode, EXPAND_NORMAL);
                }
              else
                expand_assignment (decl, init, 0, 0);
+             
+             /* The expression might have involved increments and
+                decrements.  */
+             emit_queue ();
+
+             /* Cleanup any temporaries needed for the initial value.  */
+             expand_end_target_temps ();
 
              if (protect)
                expand_end_cond ();
@@ -2969,13 +3042,7 @@ finish_file ()
            ;
          else my_friendly_abort (22);
 
-         /* Cleanup any temporaries needed for the initial value.  */
-         expand_cleanups_to (old_cleanups);
        next_mess:
-         pop_temp_slots ();
-         pop_temp_slots ();
-         target_temp_slot_level = old_temp_level;
-
          vars = TREE_CHAIN (vars);
        }
 
@@ -2991,8 +3058,6 @@ finish_file ()
       assemble_constructor (IDENTIFIER_POINTER (fnname));
     }
 
-  expand_builtin_throw ();
-
   permanent_allocation (1);
 
   /* Done with C language context needs.  */
@@ -3028,7 +3093,8 @@ finish_file ()
   start_time = get_run_time ();
 
   if (flag_handle_signatures)
-    walk_sigtables ((void (*)())0, finish_sigtable_vardecl);
+    walk_sigtables ((void (*) PROTO ((tree, tree))) 0,
+                   finish_sigtable_vardecl);
 
   for (fnname = saved_inlines; fnname; fnname = TREE_CHAIN (fnname))
     {
@@ -3054,7 +3120,8 @@ finish_file ()
        SET_DECL_ARTIFICIAL (vars);
        pushdecl (vars);
 
-       reconsider |= walk_vtables ((void (*)())0, finish_vtable_vardecl);
+       reconsider |= walk_vtables ((void (*) PROTO((tree, tree))) 0, 
+                                   finish_vtable_vardecl);
 
        while (*p)
          {
@@ -3080,8 +3147,7 @@ finish_file ()
              *p = TREE_CHAIN (*p);
            else if (DECL_INITIAL (decl) == 0)
              p = &TREE_CHAIN (*p);
-           else if ((TREE_PUBLIC (decl) && ! DECL_WEAK (decl)
-                     && ! DECL_ONE_ONLY (decl))
+           else if ((TREE_PUBLIC (decl) && ! DECL_COMDAT (decl))
                     || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
                     || flag_keep_inline_functions)
              {
@@ -3090,11 +3156,10 @@ finish_file ()
                    DECL_EXTERNAL (decl) = 0;
                    reconsider = 1;
                    /* We can't inline this function after it's been
-                       emitted, so just disable inlining.  We want a
-                       variant of output_inline_function that doesn't
-                       prevent subsequent integration...  */
-                   flag_no_inline = 1;
-                   temporary_allocation ();
+                       emitted.  We want a variant of
+                       output_inline_function that doesn't prevent
+                       subsequent integration...  */
+                   DECL_INLINE (decl) = 0;
                    output_inline_function (decl);
                    permanent_allocation (1);
                  }
@@ -3105,20 +3170,32 @@ finish_file ()
              p = &TREE_CHAIN (*p);
          }
       }
+
+    /* It's possible that some of the remaining inlines will still be
+       needed.  For example, a static inline whose address is used in
+       the initializer for a file-scope static variable will be
+       needed.  Code in compile_file will handle this, but we mustn't
+       pretend that there are no definitions for the inlines, or it
+       won't be able to.
+
+       FIXME: This won't catch member functions.  We should really
+       unify this stuff with the compile_file stuff.  */
+    for (vars = saved_inlines; vars != NULL_TREE; vars = TREE_CHAIN (vars))
+      {
+       tree decl = TREE_VALUE (vars);
+
+       if (DECL_NOT_REALLY_EXTERN (decl)
+           && !DECL_COMDAT (decl)
+           && DECL_INITIAL (decl) != NULL_TREE)
+         DECL_EXTERNAL (decl) = 0;
+      }
   }
 
   /* Now delete from the chain of variables all virtual function tables.
      We output them all ourselves, because each will be treated specially.  */
 
-  walk_vtables ((void (*)())0, prune_vtable_vardecl);
-
-  for (vars = getdecls (); vars; vars = TREE_CHAIN (vars))
-    {
-      if (TREE_CODE (vars) == FUNCTION_DECL
-         && ! DECL_INTERFACE_KNOWN (vars)
-         && DECL_C_STATIC (vars))
-       TREE_PUBLIC (vars) = 0;
-    }
+  walk_vtables ((void (*) PROTO((tree, tree))) 0,
+               prune_vtable_vardecl);
 
   if (write_virtuals == 2)
     {
@@ -3140,7 +3217,10 @@ finish_file ()
   varconst_time += this_time - start_time;
 
   if (flag_detailed_statistics)
-    dump_time_statistics ();
+    {
+      dump_tree_statistics ();
+      dump_time_statistics ();
+    }
 }
 
 /* This is something of the form 'A()()()()()+1' that has turned out to be an
@@ -3213,6 +3293,9 @@ reparse_absdcl_as_casts (decl, expr)
       expr = build_c_cast (type, expr);
     }
 
+  if (warn_old_style_cast)
+    warning ("use of old-style cast");
+
   return expr;
 }
 
@@ -3236,6 +3319,11 @@ build_expr_from_tree (t)
       else
        return do_identifier (TREE_OPERAND (t, 0), 0);
 
+    case TEMPLATE_ID_EXPR:
+      return (lookup_template_function
+             (build_expr_from_tree (TREE_OPERAND (t, 0)),
+              build_expr_from_tree (TREE_OPERAND (t, 1))));
+
     case INDIRECT_REF:
       return build_x_indirect_ref
        (build_expr_from_tree (TREE_OPERAND (t, 0)), "unary *");
@@ -3328,11 +3416,12 @@ build_expr_from_tree (t)
                              build_expr_from_tree (TREE_OPERAND (t, 1)));
 
     case SIZEOF_EXPR:
+    case ALIGNOF_EXPR:
       {
        tree r = build_expr_from_tree (TREE_OPERAND (t, 0));
        if (TREE_CODE_CLASS (TREE_CODE (r)) != 't')
          r = TREE_TYPE (r);
-       return c_sizeof (r);
+       return TREE_CODE (t) == SIZEOF_EXPR ? c_sizeof (r) : c_alignof (r);
       }
 
     case MODOP_EXPR:
@@ -3393,7 +3482,8 @@ build_expr_from_tree (t)
       else
        {
          tree name = TREE_OPERAND (t, 0);
-         if (! really_overloaded_fn (name))
+         if (TREE_CODE (name) == TEMPLATE_ID_EXPR
+             || ! really_overloaded_fn (name))
            name = build_expr_from_tree (name);
          return build_x_function_call
            (name, build_expr_from_tree (TREE_OPERAND (t, 1)),
@@ -3422,14 +3512,14 @@ build_expr_from_tree (t)
        chain = TREE_CHAIN (t);
        if (chain && chain != void_type_node)
          chain = build_expr_from_tree (chain);
-       return tree_cons (purpose, value, chain);
+       return expr_tree_cons (purpose, value, chain);
       }
 
     case COMPONENT_REF:
       return build_x_component_ref
        (build_expr_from_tree (TREE_OPERAND (t, 0)),
         TREE_OPERAND (t, 1), NULL_TREE, 1);
-
+      
     case THROW_EXPR:
       return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0)));
 
@@ -3444,6 +3534,8 @@ build_expr_from_tree (t)
       }
 
     case TYPEID_EXPR:
+      if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't')
+       return get_typeid (TREE_OPERAND (t, 0));
       return build_x_typeid (build_expr_from_tree (TREE_OPERAND (t, 0)));
 
     case VAR_DECL:
@@ -3467,7 +3559,7 @@ reparse_decl_as_expr (type, decl)
 {
   decl = build_expr_from_tree (decl);
   if (type)
-    return build_functional_cast (type, build_tree_list (NULL_TREE, decl));
+    return build_functional_cast (type, build_expr_list (NULL_TREE, decl));
   else
     return decl;
 }
@@ -3541,8 +3633,179 @@ check_cp_case_value (value)
   return value;
 }
 
-tree current_namespace;
+/* return 1 if root encloses child */
+static int
+is_namespace_ancestor (root, child)
+     tree root, child;
+{
+  if (root == child)
+    return 1;
+  if (root == global_namespace)
+    return 1;
+  if (child == global_namespace)
+    return 0;
+  return is_namespace_ancestor (root, DECL_NAMESPACE (child));
+}
+  
+
+/* return the namespace that is the common ancestor 
+   of two given namespaces */
+static tree
+namespace_ancestor (ns1, ns2)
+     tree ns1, ns2;
+{
+  if (is_namespace_ancestor (ns1, ns2))
+    return ns1;
+  return namespace_ancestor (DECL_NAMESPACE (ns1), ns2);
+}
+
+/* Insert used into the using list of user. Set indirect_flag if this
+   directive is not directly from the source. Also find the common
+   ancestor and let our users know about the new namespace */
+static void 
+add_using_namespace (user, used, indirect)
+     tree user;
+     tree used;
+     int indirect;
+{
+  tree iter;
+  /* using oneself is a no-op */
+  if (user == used)
+    return;
+  my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
+  my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
+  /* check if we already have this */
+  if (purpose_member (used, DECL_NAMESPACE_USING (user)) != NULL_TREE)
+    return;
+
+  /* add used to the user's using list */
+  DECL_NAMESPACE_USING (user) 
+    = perm_tree_cons (used, namespace_ancestor (user, used), 
+                     DECL_NAMESPACE_USING (user));
+
+  TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
+
+  /* add user to the used's users list */
+  DECL_NAMESPACE_USERS (used)
+    = perm_tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
+                     
+  for (iter = DECL_NAMESPACE_USERS (user); iter; iter = TREE_CHAIN (iter))
+    /* indirect usage */
+    add_using_namespace (TREE_PURPOSE (iter), used, 1);
+}
+
+/* This should return an error not all definitions define functions.
+   It is not an error if we find two functions with exactly the
+   same signature, only if these are selected in overload resolution.
+   XXX Do we want to give *all* candidates in case of ambiguity?
+   XXX In what way should I treat extern declarations?
+   XXX I don't want to repeat the entire duplicate_decls here */
+static tree
+ambiguous_decl (name, val1, val2)
+     tree val1, val2;
+{
+  my_friendly_assert (val1 != val2, 376);
+  if (is_overloaded_fn (val1) && is_overloaded_fn (val1))
+    {
+      /* now built a joint list of all overloaded declarations */
+      /* XXX if I chain'em together, they will be always considered
+        as overloaded */
+      sorry ("overloaded functions used from different namespaces");
+    }
+  cp_error ("ambiguous definition `%D' used", name);
+  cp_error_at ("first definition here", val1);
+  cp_error_at ("other definition here", val2);
+  return error_mark_node;
+}
+
+/* add the bindings of name in used namespaces to val 
+   the using list is defined by current, and the lookup goes to scope */
+tree
+lookup_using_namespace (name, val, current, scope)
+     tree name, val, current, scope;
+{
+  tree iter;
+  tree val1;
+  /* iterate over all namespaces from current to scope */
+  while (1)
+    {
+      /* iterate over all used namespaces in current, searching for
+        using directives of scope */
+      for (iter = DECL_NAMESPACE_USING (current); 
+          iter; iter = TREE_CHAIN (iter))
+       if (TREE_VALUE (iter) == scope)
+         {
+           val1 = NAMESPACE_BINDING (name, TREE_PURPOSE (iter));
+           /* name not found in this space */
+           if (!val1) 
+             continue;
+           /* first definition ever */
+           if (!val)
+             {
+               val = val1;
+               continue;
+             }
+           /* Hmmm. Ambiguity. As long as both are overloaded functions,
+              this is fine */
+           val = ambiguous_decl (name, val, val1);
+           if (val == error_mark_node)
+             break;
+         }
+      if (current == scope)
+       break;
+      current = DECL_NAMESPACE (current);
+    }
+  return val;
+}
+
+/* [namespace.qual] */
+tree
+qualified_lookup_using_namespace (name, scope)
+     tree name;
+     tree scope;
+{
+  tree val = NULL_TREE;
+  tree val1;
+  /* maintain a list of namespaces visited */
+  tree seen = NULL_TREE;
+  /* and a list of namespace yet to see */
+  tree todo = NULL_TREE;
+  tree usings;
+  while (scope)
+    {
+      seen = temp_tree_cons (scope, NULL_TREE, seen);
+      val1 = NAMESPACE_BINDING (name, scope);
+      if (val1)
+       {
+         if (val)
+           {
+             val = ambiguous_decl (name, val, val1);
+             break;
+           }
+         else
+           val = val1;
+       }
+      else
+       /* consider using directives */
+       for (usings = DECL_NAMESPACE_USING (scope); usings;
+            usings = TREE_CHAIN (usings))
+         /* if this was a real directive, and we have not seen it */
+         if (!TREE_INDIRECT_USING (usings)
+             && !purpose_member (seen, TREE_PURPOSE (usings)))
+           todo = temp_tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
+      if (todo)
+       {
+         scope = TREE_PURPOSE (todo);
+         todo = TREE_CHAIN (todo);
+       }
+      else
+       scope = NULL_TREE; /* if there never was a todo list */
+    }
+  return val;
+}
 
+#if 0
+/* this is broken and should not be called anymore */
 /* Get the inner part of a namespace id.  It doesn't have any prefix, nor
    postfix.  Returns 0 if in global namespace.  */
 
@@ -3574,18 +3837,47 @@ current_namespace_id (name)
           IDENTIFIER_POINTER (name));
   return get_identifier (buf);
 }
+#endif
 
 void
 do_namespace_alias (alias, namespace)
      tree alias, namespace;
 {
-  sorry ("namespace alias");
+  tree binding;
+  tree ns;
+  if (TREE_CODE (namespace) == IDENTIFIER_NODE)
+    ns = lookup_name (namespace, 1);
+  else
+    ns = namespace;
+  if (TREE_CODE (ns) != NAMESPACE_DECL)
+    {
+      cp_error ("`%D' is not a namespace", namespace);
+      return;
+    }
+  binding = binding_for_name (alias, current_namespace);
+  if (BINDING_VALUE (binding) && BINDING_VALUE (binding) != namespace)
+    {
+      cp_error ("invalid namespace alias `%D'", alias);
+      cp_error_at ("`%D' previously declared here", alias);
+    }
+  else
+    {
+      /* XXX the alias is not exactly identical to the name space,
+        it must not be used in a using directive or namespace alias */
+      BINDING_VALUE (binding) = ns;
+    }
 }
 
 void
 do_toplevel_using_decl (decl)
      tree decl;
 {
+#if 1
+  if (TREE_CODE (decl) == SCOPE_REF
+      && TREE_OPERAND (decl, 0) == std_node)
+    return;
+  sorry ("using-declaration");
+#else
   if (decl == NULL_TREE || decl == error_mark_node)
     return;
 
@@ -3603,6 +3895,7 @@ do_toplevel_using_decl (decl)
        pushdecl (TREE_VALUE (decl));
        decl = TREE_CHAIN (decl);
       }
+#endif
 }
 
 tree
@@ -3632,7 +3925,13 @@ void
 do_using_directive (namespace)
      tree namespace;
 {
-  sorry ("using directive");
+  if (namespace == std_node)
+    return;
+  /* using A::B::C; */
+  if (TREE_CODE (namespace) == SCOPE_REF)
+      namespace = TREE_OPERAND (namespace, 1);
+  /* direct usage */
+  add_using_namespace (current_namespace, namespace, 0);
 }
 
 void
@@ -3671,3 +3970,22 @@ mark_used (decl)
   if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
     instantiate_decl (decl);
 }
+
+/* Helper function for named_class_head_sans_basetype nonterminal.  */
+
+tree
+handle_class_head (aggr, scope, id)
+     tree aggr, scope, id;
+{
+  if (TREE_CODE (id) == TYPE_DECL)
+    return id;
+
+  if (scope)
+    cp_error ("`%T' does not have a nested type named `%D'", scope, id);
+  else
+    cp_error ("no file-scope type named `%D'", id);
+
+  id = xref_tag
+    (aggr, make_anon_name (), NULL_TREE, 1);
+  return TYPE_MAIN_DECL (id);
+}
This page took 0.072847 seconds and 5 git commands to generate.