OSDN Git Service

* cp-tree.def (DECL_STMT): Make it smaller.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 14 Aug 1999 09:23:49 +0000 (09:23 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 14 Aug 1999 09:23:49 +0000 (09:23 +0000)
* cp-tree.h (lang_decl_flags): Move saved_tree to ...
(lang_decl): ... here.  Add next.
(DECL_SAVED_TREE): Adjust accordingly.
(DECL_IMPLICIT_TYPEDEF_P): New macro.
(SET_DECL_IMPLICIT_TYPEDEF_P): Likewise.
(DECL_STMT_DECL): Likewise.
(create_implicit_typedef): New function.
(maybe_push_decl): Likewise.
(tsubst_default_argument): New function.
(at_function_scope_p): Likewise.
(add_decl_stmt): Likewise.
(push_permanent_obstack): Likewise.
* call.c (convert_default_arg): Use tsubst_default_argument.
* class.c (add_method): Use push_permanent_obstack.
(build_self_reference): Create a TEMPLATE_DECL for the
self-reference, if necessary.
* decl.c (pseudo_global_level_p): Only look at the current binding
level.
(push_binding): Use push_permanent_obstack.
(create_implicit_typedef): New function.
(pushtag): Use it.
(duplicate_decls): Use push_permanent_obstack.
(maybe_push_decl): New function.
(start_decl): Use it.  Remove dead code.  Use add_decl_stmt.
(start_decl_1): Remove dead code.
(cp_finish_decl): Remove DECL_STMT handling here.  Don't use
pseudo_global_level_p.
(grokvardecl): Create DECL_LANG_SPECIFIC for a VAR_DECL in a
template.
(grokdeclarator): Likewise, for TYPE_DECLs.  Don't use
pseudo_global_level_p.
* decl2.c (grokfield): Call push_template_decl for a TYPE_DECL in
a template.
(get_sentry): Use push_permanent_obstack.
* dump.c (dequeue_and_dump): Enable DECL_STMT.
* except.c (call_eh_info): Use push_permanent_obstack.
(build_eh_type_ref): Likewise.
(do_pop_exception): Likewise.
(expand_eh_spec): Likewise.
(alloc_eh_object): Likewise.
(expand_throw): Likewise.
* init.c (build_java_class_ref): Likewise.
* lex.c (get_time_identifier): Likewise.
(free_lang_decl_chain): Correct type.
(retrofit_lang_decl): Adjust accordingly.
(build_lang_field_decl): Likewise.
* lex.h (free_lang_decl_chain): Likewise.
* parse.y (lang_extdef): Don't use pseudo_global_level_p.
* parse.c: Regenerated.
* pt.c (tsubst_default_arguments): New function.
(retrieve_local_specialization): Likewise.
(register_local_specialization): Likewise.
(push_template_decl_real): Use DECL_IMPLICIT_TYPEDEF_P.  Just use
pseudo_global_level_p to determine whether or not a template is
primary.
(lookup_template_class): Likewise.  Use create_implicit_typedef.
(instantiate_class_template): Call tsubst_default_arguments for
member functions, if appropriate.
(tsubst_default_argument): New function.
(tsubst_decl): Use it.  Change TYPE_DECL handling to match VAR_DECLs.
* search.c (at_function_scope_p): New function.
* semantics.c (finish_asm_stmt): Use push_permanent_obstack.
(finish_label_stmt): Likewise.
(add_decl_stmt): New function.
(begin_class_definition): Likewise.
(finish_typeof): Likewise.
* tree.c (copy_template_template_parm): Likewise.
(copy_to_permanent): Likewise.
(push_permanent_obstack): Define.
(mark_addressable): Use it.
* typeck.c (mark_addressable): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@28709 138bc75d-0d04-0410-961f-82ee72b054a4

22 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/dump.c
gcc/cp/except.c
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/lex.h
gcc/cp/parse.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/g++.old-deja/g++.pt/crash15.C
gcc/testsuite/g++.old-deja/g++.pt/defarg12.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/defarg13.C [new file with mode: 0644]

index 3782933..4b882a6 100644 (file)
@@ -1,3 +1,78 @@
+1999-08-13  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.def (DECL_STMT): Make it smaller.
+       * cp-tree.h (lang_decl_flags): Move saved_tree to ...
+       (lang_decl): ... here.  Add next.
+       (DECL_SAVED_TREE): Adjust accordingly.
+       (DECL_IMPLICIT_TYPEDEF_P): New macro.
+       (SET_DECL_IMPLICIT_TYPEDEF_P): Likewise.
+       (DECL_STMT_DECL): Likewise.
+       (create_implicit_typedef): New function.
+       (maybe_push_decl): Likewise.
+       (tsubst_default_argument): New function.
+       (at_function_scope_p): Likewise.
+       (add_decl_stmt): Likewise.
+       (push_permanent_obstack): Likewise.
+       * call.c (convert_default_arg): Use tsubst_default_argument.
+       * class.c (add_method): Use push_permanent_obstack.
+       (build_self_reference): Create a TEMPLATE_DECL for the
+       self-reference, if necessary.
+       * decl.c (pseudo_global_level_p): Only look at the current binding
+       level.
+       (push_binding): Use push_permanent_obstack.
+       (create_implicit_typedef): New function.
+       (pushtag): Use it.
+       (duplicate_decls): Use push_permanent_obstack.
+       (maybe_push_decl): New function.
+       (start_decl): Use it.  Remove dead code.  Use add_decl_stmt.
+       (start_decl_1): Remove dead code.
+       (cp_finish_decl): Remove DECL_STMT handling here.  Don't use
+       pseudo_global_level_p.
+       (grokvardecl): Create DECL_LANG_SPECIFIC for a VAR_DECL in a
+       template.
+       (grokdeclarator): Likewise, for TYPE_DECLs.  Don't use
+       pseudo_global_level_p.
+       * decl2.c (grokfield): Call push_template_decl for a TYPE_DECL in
+       a template.
+       (get_sentry): Use push_permanent_obstack.
+       * dump.c (dequeue_and_dump): Enable DECL_STMT.
+       * except.c (call_eh_info): Use push_permanent_obstack.
+       (build_eh_type_ref): Likewise.
+       (do_pop_exception): Likewise.
+       (expand_eh_spec): Likewise.
+       (alloc_eh_object): Likewise.
+       (expand_throw): Likewise.
+       * init.c (build_java_class_ref): Likewise.
+       * lex.c (get_time_identifier): Likewise.
+       (free_lang_decl_chain): Correct type.
+       (retrofit_lang_decl): Adjust accordingly.
+       (build_lang_field_decl): Likewise.
+       * lex.h (free_lang_decl_chain): Likewise.
+       * parse.y (lang_extdef): Don't use pseudo_global_level_p.
+       * parse.c: Regenerated.
+       * pt.c (tsubst_default_arguments): New function.
+       (retrieve_local_specialization): Likewise.
+       (register_local_specialization): Likewise.
+       (push_template_decl_real): Use DECL_IMPLICIT_TYPEDEF_P.  Just use
+       pseudo_global_level_p to determine whether or not a template is
+       primary.
+       (lookup_template_class): Likewise.  Use create_implicit_typedef.
+       (instantiate_class_template): Call tsubst_default_arguments for
+       member functions, if appropriate.
+       (tsubst_default_argument): New function.
+       (tsubst_decl): Use it.  Change TYPE_DECL handling to match VAR_DECLs.
+       * search.c (at_function_scope_p): New function.
+       * semantics.c (finish_asm_stmt): Use push_permanent_obstack.
+       (finish_label_stmt): Likewise.
+       (add_decl_stmt): New function.
+       (begin_class_definition): Likewise.
+       (finish_typeof): Likewise.
+       * tree.c (copy_template_template_parm): Likewise.
+       (copy_to_permanent): Likewise.
+       (push_permanent_obstack): Define.
+       (mark_addressable): Use it.
+       * typeck.c (mark_addressable): Likewise.
+       
 1999-08-13  Gavin Romig-Koch  <gavin@cygnus.com>
 
        cp-tree.h (init_cplus_unsave): New.
index a4ed95b..fda38de 100644 (file)
@@ -3787,30 +3787,7 @@ convert_default_arg (type, arg, fn)
      tree fn;
 {
   if (fn && DECL_TEMPLATE_INFO (fn))
-    {
-      /* This default argument came from a template.  Instantiate the
-        default argument here, not in tsubst.  In the case of
-        something like: 
-
-          template <class T>
-          struct S {
-            static T t();
-            void f(T = t());
-          };
-
-        we must be careful to do name lookup in the scope of S<T>,
-        rather than in the current class.  */
-      if (DECL_CLASS_SCOPE_P (fn))
-       pushclass (DECL_REAL_CONTEXT (fn), 2);
-
-      arg = tsubst_expr (arg, DECL_TI_ARGS (fn), /*complain=*/1, NULL_TREE);
-
-      if (DECL_CLASS_SCOPE_P (fn))
-       popclass ();
-
-      /* Make sure the default argument is reasonable.  */
-      arg = check_default_argument (type, arg);
-    }
+    arg = tsubst_default_argument (fn, type, arg);
 
   arg = break_out_target_exprs (arg);
 
index 47f22a3..3df1390 100644 (file)
@@ -1154,8 +1154,7 @@ void
 add_method (type, fields, method)
      tree type, *fields, method;
 {
-  push_obstacks_nochange ();
-  end_temporary_allocation ();
+  push_permanent_obstack ();
 
   /* Setting the DECL_CONTEXT and DECL_CLASS_CONTEXT here is probably
      redundant.  */
@@ -5379,6 +5378,9 @@ build_self_reference ()
   DECL_CLASS_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
 
+  if (processing_template_decl)
+    value = push_template_decl (value);
+
   saved_cas = current_access_specifier;
   current_access_specifier = access_public_node;
   finish_member_declaration (value);
index 70801fc..fecbbe5 100644 (file)
@@ -217,7 +217,7 @@ DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1)
 
 DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
 DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1)
-DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 3)
+DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 1)
 DEFTREECODE (IF_STMT, "if_stmt", 'e', 3)
 DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4)
 DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2)
index 2e58406..410dc7a 100644 (file)
@@ -77,6 +77,7 @@ Boston, MA 02111-1307, USA.  */
    1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
       DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
    2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
+      DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
    3: DECL_IN_AGGR_P.
    4: DECL_MAYBE_TEMPLATE.
    5: DECL_INTERFACE_KNOWN.
@@ -1192,11 +1193,8 @@ struct lang_decl_flags
   tree access;
   tree context;
 
-  /* In a template FUNCTION_DECL, this is DECL_SAVED_TREE.  */
-  tree saved_tree;
-
   union {
-    /* In a FUNCTION_DECL, this is DECL_TEMPLATE_INFO.  */
+    /* In a FUNCTION_DECL or a VAR_DECL, this is DECL_TEMPLATE_INFO.  */
     tree template_info;
 
     /* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL.  */
@@ -1210,10 +1208,17 @@ struct lang_decl
 
   tree main_decl_variant;
   tree befriending_classes;
+
+  /* In a FUNCTION_DECL, this is DECL_SAVED_TREE.  */
+  tree saved_tree;
+
   union
   {
     tree sorted_fields;
     struct pending_inline *pending_inline_info;
+    /* The lang_decls on the free_lang_decl_chain are chained together
+       through this pointer.  */
+    struct lang_decl *next;
   } u;
 };
 
@@ -1502,7 +1507,7 @@ struct lang_decl
 /* In a template FUNCTION_DECL, the tree structure that will be
    substituted into to obtain instantiations.  */
 #define DECL_SAVED_TREE(NODE) \
-  (DECL_LANG_SPECIFIC ((NODE))->decl_flags.saved_tree)
+  (DECL_LANG_SPECIFIC ((NODE))->saved_tree)
 
 #define COMPOUND_STMT_NO_SCOPE(NODE)   TREE_LANG_FLAG_0 (NODE)
 #define NEW_EXPR_USE_GLOBAL(NODE)      TREE_LANG_FLAG_0 (NODE)
@@ -1984,6 +1989,18 @@ extern int flag_new_for_scope;
 #define DECL_DECLARES_TYPE_P(NODE) \
   (TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
 
+/* Nonzero if NODE is the typedef implicitly generated for a type when
+   the type is declared.  (In C++, `struct S {};' is roughly equivalent
+   to `struct S {}; typedef struct S S;' in C.  This macro will hold
+   for the typedef indicated in this example.  Note that in C++, there
+   is a second implicit typedef for each class, in the scope of `S'
+   itself, so that you can `S::S'.  This macro does *not* hold for
+   those typedefs.  */
+#define DECL_IMPLICIT_TYPEDEF_P(NODE) \
+  (TREE_CODE ((NODE)) == TYPE_DECL && DECL_LANG_FLAG_2 ((NODE)))
+#define SET_DECL_IMPLICIT_TYPEDEF_P(NODE) \
+  (DECL_LANG_FLAG_2 ((NODE)) = 1)
+
 /* A `primary' template is one that has its own template header.  A
    member function of a class template is a template, but not primary.
    A member template is primary.  Friend templates are primary, too.  */
@@ -2120,6 +2137,7 @@ extern int flag_new_for_scope;
 #define ASM_OUTPUTS(NODE)       TREE_OPERAND (NODE, 2)
 #define ASM_INPUTS(NODE)        TREE_OPERAND (NODE, 3)
 #define ASM_CLOBBERS(NODE)      TREE_OPERAND (NODE, 4)
+#define DECL_STMT_DECL(NODE)    TREE_OPERAND (NODE, 0)
 
 /* Nonzero for an ASM_STMT if the assembly statement is volatile.  */
 #define ASM_VOLATILE_P(NODE)                   \
@@ -2936,6 +2954,8 @@ extern int walk_namespaces                      PROTO((walk_namespaces_fn,
                                                       void *));
 extern int wrapup_globals_for_namespace         PROTO((tree, void *));
 extern tree cp_namespace_decls                  PROTO((tree));
+extern tree create_implicit_typedef             PROTO((tree, tree));
+extern tree maybe_push_decl                     PROTO((tree));
 
 /* in decl2.c */
 extern int check_java_method                   PROTO((tree));
@@ -3191,7 +3211,6 @@ extern void do_type_instantiation         PROTO((tree, tree));
 extern tree instantiate_decl                   PROTO((tree));
 extern tree do_poplevel                                PROTO((void));
 extern tree get_bindings                       PROTO((tree, tree, tree));
-/* CONT ... */
 extern void add_tree                           PROTO((tree));
 extern void begin_tree                          PROTO((void));
 extern void end_tree                            PROTO((void));
@@ -3210,6 +3229,7 @@ extern void maybe_check_template_type           PROTO((tree));
 extern tree most_specialized_instantiation      PROTO((tree, tree));
 extern void print_candidates                    PROTO((tree));
 extern int instantiate_pending_templates        PROTO((void));
+extern tree tsubst_default_argument             PROTO((tree, tree, tree));
 
 extern int processing_specialization;
 extern int processing_explicit_instantiation;
@@ -3257,6 +3277,7 @@ extern void print_search_statistics               PROTO((void));
 extern void init_search_processing             PROTO((void));
 extern void reinit_search_statistics           PROTO((void));
 extern tree current_scope                      PROTO((void));
+extern int at_function_scope_p                  PROTO((void));
 extern tree lookup_conversions                 PROTO((tree));
 extern tree binfo_for_vtable                   PROTO((tree));
 extern int  binfo_from_vbase                   PROTO((tree));
@@ -3342,6 +3363,7 @@ extern tree finish_base_specifier               PROTO((tree, tree));
 extern void finish_member_declaration           PROTO((tree));
 extern void check_multiple_declarators          PROTO((void));
 extern tree finish_typeof                      PROTO((tree));
+extern void add_decl_stmt                       PROTO((tree));
 
 /* in spew.c */
 extern void init_spew                          PROTO((void));
@@ -3420,6 +3442,7 @@ extern tree mapcar                                PROTO((tree, tree (*) (tree)));
 extern tree no_linkage_check                   PROTO((tree));
 extern void debug_binfo                                PROTO((tree));
 extern void push_expression_obstack            PROTO((void));
+extern void push_permanent_obstack              PROTO((void));
 extern tree build_dummy_object                 PROTO((tree));
 extern tree maybe_dummy_object                 PROTO((tree, tree *));
 extern int is_dummy_object                     PROTO((tree));
index b6e66a9..8c96020 100644 (file)
@@ -923,9 +923,7 @@ declare_namespace_level ()
 int
 pseudo_global_level_p ()
 {
-  struct binding_level *b = innermost_nonclass_level ();
-
-  return b->pseudo_global;
+  return current_binding_level->pseudo_global;
 }
 
 void
@@ -1018,8 +1016,7 @@ push_binding (id, decl, level)
   if (!free_binding_nodes)
     {
       /* There are no free nodes, so we must build one here.  */
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
+      push_permanent_obstack ();
       binding = make_node (CPLUS_BINDING);
       pop_obstacks ();
     }
@@ -2761,6 +2758,29 @@ maybe_process_template_type_declaration (type, globalize, b)
   return decl;
 }
 
+/* In C++, you don't have to write `struct S' to refer to `S'; you
+   can just use `S'.  We accomplish this by creating a TYPE_DECL as
+   if the user had written `typedef struct S S'.  Create and return
+   the TYPE_DECL for TYPE.  */
+
+tree
+create_implicit_typedef (name, type)
+     tree name;
+     tree type;
+{
+  tree decl;
+
+  decl = build_decl (TYPE_DECL, name, type);
+  SET_DECL_ARTIFICIAL (decl);
+  /* There are other implicit type declarations, like the one *within*
+     a class that allows you to write `S::S'.  We must distinguish
+     amongst these.  */
+  SET_DECL_IMPLICIT_TYPEDEF_P (decl);
+  TYPE_NAME (type) = decl;
+
+  return decl;
+}
+
 /* Push a tag name NAME for struct/class/union/enum type TYPE.
    Normally put it into the inner-most non-tag-transparent scope,
    but if GLOBALIZE is true, put it in the inner-most non-class scope.
@@ -2790,9 +2810,8 @@ pushtag (name, type, globalize)
         {
           register tree d = NULL_TREE;
          int in_class = 0;
-         tree context;
+         tree context = TYPE_CONTEXT (type);
 
-         context = type ? TYPE_CONTEXT (type) : NULL_TREE;
          if (! context)
            {
              tree cs = current_scope ();
@@ -2813,15 +2832,13 @@ pushtag (name, type, globalize)
              || b->parm_flag == 2)
            in_class = 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);
 
-         TYPE_NAME (type) = d;
+         d = create_implicit_typedef (name, type);
          DECL_CONTEXT (d) = FROB_CONTEXT (context);
+         if (! in_class)
+           set_identifier_type_value_with_scope (name, type, b);
 
          d = maybe_process_template_type_declaration (type,
                                                       globalize, b);
@@ -3449,10 +3466,7 @@ duplicate_decls (newdecl, olddecl)
       if (oldtype)
        push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
       else
-       {
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
-       }
+       push_permanent_obstack ();
 
       /* Merge the data types specified in the two decls.  */
       newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
@@ -3733,14 +3747,13 @@ duplicate_decls (newdecl, olddecl)
        {
          if (DECL_MAIN_VARIANT (olddecl) == olddecl)
            {
-             /* Save these lang_decls that would otherwise be lost.  */
-             extern tree free_lang_decl_chain;
-             tree free_lang_decl = (tree) ol;
+             struct lang_decl *free_lang_decl = ol;
 
+             /* Save these lang_decls that would otherwise be lost.  */
              if (DECL_LANG_SPECIFIC (olddecl) == ol)
                abort ();
 
-             TREE_CHAIN (free_lang_decl) = free_lang_decl_chain;
+             free_lang_decl->u.next = free_lang_decl_chain;
              free_lang_decl_chain = free_lang_decl;
            }
          else
@@ -4310,6 +4323,35 @@ pushdecl_class_level (x)
     }
 }
 
+/* Enter DECL into the symbol table, if that's appropriate.  Returns
+   DECL, or a modified version thereof.  */
+
+tree
+maybe_push_decl (decl)
+     tree decl;
+{
+  tree type = TREE_TYPE (decl);
+
+  /* Add this decl to the current binding level, but not if it comes
+     from another scope, e.g. a static member variable.  TEM may equal
+     DECL or it may be a previous decl of the same name.  */
+  if ((TREE_CODE (decl) != PARM_DECL 
+       && DECL_CONTEXT (decl) != NULL_TREE 
+       /* Definitions of namespace members outside their namespace are
+         possible. */
+       && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
+      || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
+      || TREE_CODE (type) == UNKNOWN_TYPE
+      /* The declaration of template specializations does not affect
+        the functions available for overload resolution, so we do not
+        call pushdecl.  */
+      || (TREE_CODE (decl) == FUNCTION_DECL
+         && DECL_TEMPLATE_SPECIALIZATION (decl)))
+    return decl;
+  else
+    return pushdecl (decl);
+}
+
 #if 0
 /* This function is used to push the mangled decls for nested types into
    the appropriate scope.  Previously pushdecl_top_level was used, but that
@@ -6987,34 +7029,22 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
                    decl);
     }
 
-  /* Add this decl to the current binding level, but not if it
-     comes from another scope, e.g. a static member variable.
-     TEM may equal DECL or it may be a previous decl of the same name.  */
-  
-  if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE 
-       /* Definitions of namespace members outside their namespace are
-         possible. */
-       && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
-      || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
-      || TREE_CODE (type) == LANG_TYPE
-      /* The declaration of template specializations does not affect
-        the functions available for overload resolution, so we do not
-        call pushdecl.  */
-      || (TREE_CODE (decl) == FUNCTION_DECL
-         && DECL_TEMPLATE_SPECIALIZATION (decl)))
-    tem = decl;
-  else
-    tem = pushdecl (decl);
+  /* Enter this declaration into the symbol table.  */
+  tem = maybe_push_decl (decl);
 
   if (processing_template_decl)
     {
-      if (! current_function_decl)
-       tem = push_template_decl (tem);
-      else
-       DECL_VINDEX (tem)
-           = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
-                           copy_to_permanent (declspecs),
-                           NULL_TREE);
+      if (at_function_scope_p ())
+       push_permanent_obstack ();
+
+      tem = push_template_decl (tem);
+      /* In a a local scope, add a representation of this declaration
+        to the statement tree.  */
+      if (at_function_scope_p ())
+       {
+         add_decl_stmt (decl);
+         pop_obstacks ();
+       }
     }
 
 
@@ -7033,32 +7063,6 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   /* Corresponding pop_obstacks is done in `cp_finish_decl'.  */
   push_obstacks_nochange ();
 
-#if 0
-  /* We have no way of knowing whether the initializer will need to be
-     evaluated at run-time or not until we've parsed it, so let's just put
-     it in the permanent obstack.  (jason) */
-  if (init_written
-      && ! (TREE_CODE (tem) == PARM_DECL
-           || (TREE_READONLY (tem)
-               && (TREE_CODE (tem) == VAR_DECL
-                   || TREE_CODE (tem) == FIELD_DECL))))
-    {
-      /* When parsing and digesting the initializer,
-        use temporary storage.  Do this even if we will ignore the value.  */
-      if (toplevel_bindings_p () && debug_temp_inits)
-       {
-         if (processing_template_decl
-             || TYPE_NEEDS_CONSTRUCTING (type)
-             || TREE_CODE (type) == REFERENCE_TYPE)
-           /* In this case, the initializer must lay down in permanent
-              storage, since it will be saved until `finish_file' is run.   */
-           ;
-         else
-           temporary_allocation ();
-       }
-    }
-#endif
-
   return tem;
 }
 
@@ -7130,23 +7134,6 @@ start_decl_1 (decl)
        }
     }
 
-#if 0
-  /* We don't do this yet for GNU C++.  */
-  /* For a local variable, define the RTL now.  */
-  if (! toplevel_bindings_p ()
-      /* But not if this is a duplicate decl
-        and we preserved the rtl from the previous one
-        (which may or may not happen).  */
-      && DECL_RTL (tem) == NULL_RTX)
-    {
-      if (TYPE_SIZE (TREE_TYPE (tem)) != NULL_TREE)
-       expand_decl (tem);
-      else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
-              && DECL_INITIAL (tem) != NULL_TREE)
-       expand_decl (tem);
-    }
-#endif
-
   if (! initialized)
     DECL_INITIAL (decl) = NULL_TREE;
 }
@@ -7380,22 +7367,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
   if (processing_template_decl)
     {
       if (init && DECL_INITIAL (decl))
-       DECL_INITIAL (decl) = init;
-      if (current_function_decl && ! DECL_ARTIFICIAL (decl))
-       {
-         tree stmt = DECL_VINDEX (decl);
-         /* If the decl is declaring a member of a local class (in a
-            template function), the DECL_VINDEX will either be NULL,
-            or it will be an actual virtual function index, not a
-            DECL_STMT.  */
-         if (stmt != NULL_TREE && TREE_CODE (stmt) == DECL_STMT)
-           {
-             DECL_VINDEX (decl) = NULL_TREE;
-             TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
-             add_tree (stmt);
-           }
-       }
-
+       DECL_INITIAL (decl) = copy_to_permanent (init);
       goto finish_end0;
     }
 
@@ -7466,9 +7438,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
   else if (TREE_CODE (type) == REFERENCE_TYPE)
     {
       if (TREE_STATIC (decl))
-       make_decl_rtl (decl, NULL_PTR,
-                      toplevel_bindings_p ()
-                      || pseudo_global_level_p ());
+       make_decl_rtl (decl, NULL_PTR, toplevel_bindings_p ());
       grok_reference_init (decl, type, init);
       init = NULL_TREE;
     }
@@ -7678,7 +7648,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       || TREE_CODE (decl) == RESULT_DECL)
     {
       /* ??? FIXME: What about nested classes?  */
-      int toplev = toplevel_bindings_p () || pseudo_global_level_p ();
+      int toplev = toplevel_bindings_p ();
       int was_temp
        = (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
           && allocation_temporary_p ());
@@ -8647,7 +8617,17 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
       else
        context = NULL_TREE;
 
-      decl = build_decl (VAR_DECL, declarator, complete_type (type));
+      if (processing_template_decl) 
+       {
+         /* If we're in a template, we need DECL_LANG_SPECIFIC so that
+            we can call push_template_decl.  */
+         push_permanent_obstack ();
+         decl = build_lang_field_decl (VAR_DECL, declarator,
+                                       complete_type (type));
+         pop_obstacks ();
+       }
+      else
+       decl = build_decl (VAR_DECL, declarator, complete_type (type));
 
       if (context)
        set_decl_namespace (decl, context, 0);
@@ -9259,8 +9239,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
      We also want to avoid calling this a PARM if it is in a namespace.  */
 
-  if (decl_context == NORMAL && ! namespace_bindings_p ()
-      && ! pseudo_global_level_p ())
+  if (decl_context == NORMAL && !toplevel_bindings_p ())
     {
       struct binding_level *b = current_binding_level;
       current_binding_level = b->level_chain;
@@ -10568,15 +10547,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
             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 (processing_template_decl)
+           decl = build_lang_field_decl (TYPE_DECL, declarator, type);
+         else
+           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 the user declares "typedef struct {...} foo" then the
+        struct will have an anonymous name.  Fill that name in now.
+        Nothing can refer to it, so nothing needs know about the name
+        change.  */
       if (type != error_mark_node
          && TYPE_NAME (type)
          && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
@@ -11039,7 +11021,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
              {
                /* C++ allows static class members.
                   All other work for this is done by grokfield.
-                  This VAR_DCL is built by build_lang_field_decl.
+                  This VAR_DECL is built by build_lang_field_decl.
                   All other VAR_DECLs are built by build_decl.  */
                decl = build_lang_field_decl (VAR_DECL, declarator, type);
                TREE_STATIC (decl) = 1;
@@ -12913,6 +12895,31 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
   if (pre_parsed_p == 2)
     maybe_begin_member_template_processing (decl1);
 
+  /* Effective C++ rule 15.  See also c_expand_return.  */
+  if (warn_ecpp
+      && DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
+      && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
+    cp_warning ("`operator=' should return a reference to `*this'");
+
+  /* Make the init_value nonzero so pushdecl knows this is not tentative.
+     error_mark_node is replaced below (in poplevel) with the BLOCK.  */
+  DECL_INITIAL (decl1) = error_mark_node;
+
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+  SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
+#endif
+  
+  /* This function exists in static storage.
+     (This does not mean `static' in the C sense!)  */
+  TREE_STATIC (decl1) = 1;
+
+  /* We must call push_template_decl after current_class_type is set
+     up.  (If we are processing inline definitions after exiting a
+     class scope, current_class_type will be NULL_TREE until set above
+     by push_nested_class.)  */
+  if (processing_template_decl)
+    decl1 = push_template_decl (decl1);
+
   /* We are now in the scope of the function being defined.  */
   current_function_decl = decl1;
 
@@ -12955,31 +12962,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
       abstract_virtuals_error (decl1, TREE_TYPE (fntype));
     }
 
-  /* Effective C++ rule 15.  See also c_expand_return.  */
-  if (warn_ecpp
-      && DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
-      && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
-    cp_warning ("`operator=' should return a reference to `*this'");
-
-  /* Make the init_value nonzero so pushdecl knows this is not tentative.
-     error_mark_node is replaced below (in poplevel) with the BLOCK.  */
-  DECL_INITIAL (decl1) = error_mark_node;
-
-#ifdef SET_DEFAULT_DECL_ATTRIBUTES
-  SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
-#endif
-  
-  /* This function exists in static storage.
-     (This does not mean `static' in the C sense!)  */
-  TREE_STATIC (decl1) = 1;
-
-  /* We must call push_template_decl after current_class_type is set
-     up.  (If we are processing inline definitions after exiting a
-     class scope, current_class_type will be NULL_TREE until set above
-     by push_nested_class.)  */
-  if (processing_template_decl)
-    decl1 = push_template_decl (decl1);
-
   /* Record the decl so that the function name is defined.
      If we already have a decl for this name, and it is a FUNCTION_DECL,
      use the old decl.  */
index 217b783..3cebe81 100644 (file)
@@ -1644,6 +1644,9 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
        DECL_ASSEMBLER_NAME (value) =
          get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
 
+      if (processing_template_decl)
+       value = push_template_decl (value);
+
       return value;
     }
 
@@ -2823,8 +2826,7 @@ get_sentry (base)
   tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
   if (! sentry)
     {
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
+      push_permanent_obstack ();
       sentry = build_decl (VAR_DECL, sname, integer_type_node);
       TREE_PUBLIC (sentry) = 1;
       DECL_ARTIFICIAL (sentry) = 1;
index 0ae83ef..e046552 100644 (file)
@@ -662,12 +662,8 @@ dequeue_and_dump (di)
 
     case DECL_STMT:
       dump_stmt (di, t);
-#if 0
-      /* We do not yet have DECL_STMT_DECL; there are declarators and
-        such hanging about in DECL_STMTs.  */
       if (dump_children_p)
        dump_child ("decl", DECL_STMT_DECL (t));
-#endif
       break;
       
     case DO_STMT:
index dd70855..0ef6e82 100644 (file)
@@ -240,8 +240,7 @@ call_eh_info ()
 
       /* Declare cp_eh_info * __start_cp_handler (void),
         as defined in exception.cc. */
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
+      push_permanent_obstack ();
 
       /* struct cp_eh_info.  This must match exception.cc.  Note that this
         type is not pushed anywhere.  */
@@ -422,8 +421,7 @@ build_eh_type_type_ref (type)
   /* Peel off cv qualifiers.  */
   type = TYPE_MAIN_VARIANT (type);
 
-  push_obstacks_nochange ();
-  end_temporary_allocation ();
+  push_permanent_obstack ();
 
   if (flag_rtti)
     {
@@ -502,8 +500,7 @@ do_pop_exception ()
     {
       /* Declare void __cp_pop_exception (void *),
         as defined in exception.cc. */
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
+      push_permanent_obstack ();
       fn = build_lang_decl
        (FUNCTION_DECL, fn,
         build_function_type (void_type_node, tree_cons
@@ -773,8 +770,7 @@ expand_end_eh_spec (raises)
     fn = IDENTIFIER_GLOBAL_VALUE (fn);
   else
     {
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
+      push_permanent_obstack ();
 
       tmp = tree_cons
        (NULL_TREE, integer_type_node, tree_cons
@@ -920,8 +916,7 @@ alloc_eh_object (type)
     {
       /* Declare __eh_alloc (size_t), as defined in exception.cc.  */
       tree tmp;
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
+      push_permanent_obstack ();
       tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
       fn = build_lang_decl (FUNCTION_DECL, fn,
                            build_function_type (ptr_type_node, tmp));
@@ -973,8 +968,7 @@ expand_throw (exp)
         the internal type of a destructor. */
       if (cleanup_type == NULL_TREE)
        {
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
+         push_permanent_obstack ();
          cleanup_type = build_pointer_type
            (build_function_type
             (void_type_node, tree_cons
@@ -1074,8 +1068,7 @@ expand_throw (exp)
          /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
             as defined in exception.cc.  */
          tree tmp;
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
+         push_permanent_obstack ();
          tmp = tree_cons
            (NULL_TREE, ptr_type_node, tree_cons
             (NULL_TREE, ptr_type_node, tree_cons
@@ -1108,8 +1101,7 @@ expand_throw (exp)
        {
          /* Declare void __uncatch_exception (void)
             as defined in exception.cc. */
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
+         push_permanent_obstack ();
          fn = build_lang_decl (FUNCTION_DECL, fn,
                                build_function_type (void_type_node,
                                                     void_list_node));
index 98b67ee..69758a6 100644 (file)
@@ -2141,8 +2141,7 @@ build_java_class_ref (type)
   class_decl = IDENTIFIER_GLOBAL_VALUE (name);
   if (class_decl == NULL_TREE)
     {
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
+      push_permanent_obstack ();
       class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
       TREE_STATIC (class_decl) = 1;
       DECL_EXTERNAL (class_decl) = 1;
index a92a4f3..f36da53 100644 (file)
@@ -330,8 +330,7 @@ get_time_identifier (name)
   time_identifier = get_identifier (buf);
   if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
     {
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
+      push_permanent_obstack ();
       TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
       TIME_IDENTIFIER_FILEINFO (time_identifier) 
        = build_int_2 (0, 1);
@@ -4716,8 +4715,8 @@ extern int tree_node_sizes[];
 #endif
 
 /* Place to save freed lang_decls which were allocated on the
-   permanent_obstack.  @@ Not currently used.  */
-tree free_lang_decl_chain;
+   permanent_obstack.  */
+struct lang_decl *free_lang_decl_chain;
 
 tree
 build_lang_decl (code, name, type)
@@ -4738,8 +4737,7 @@ retrofit_lang_decl (t)
      tree t;
 {
   struct obstack *obstack = current_obstack;
-  register int i = sizeof (struct lang_decl) / sizeof (int);
-  register int *pi;
+  struct lang_decl *ld;
 
   if (! TREE_PERMANENT (t))
     obstack = saveable_obstack;
@@ -4749,20 +4747,18 @@ retrofit_lang_decl (t)
 
   if (free_lang_decl_chain && obstack == &permanent_obstack)
     {
-      pi = (int *)free_lang_decl_chain;
-      free_lang_decl_chain = TREE_CHAIN (free_lang_decl_chain);
+      ld = free_lang_decl_chain;
+      free_lang_decl_chain = free_lang_decl_chain->u.next;
     }
   else
-    pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
+    ld = ((struct lang_decl *) 
+         obstack_alloc (obstack, sizeof (struct lang_decl)));
 
-  while (i > 0)
-    pi[--i] = 0;
+  bzero (ld, sizeof (struct lang_decl));
 
-  DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
-  LANG_DECL_PERMANENT ((struct lang_decl *) pi)
-    = obstack == &permanent_obstack;
-  my_friendly_assert (LANG_DECL_PERMANENT ((struct lang_decl *) pi)
-         == TREE_PERMANENT  (t), 234);
+  DECL_LANG_SPECIFIC (t) = ld;
+  LANG_DECL_PERMANENT (ld) = obstack == &permanent_obstack;
+  my_friendly_assert (LANG_DECL_PERMANENT (ld) == TREE_PERMANENT  (t), 234);
   DECL_MAIN_VARIANT (t) = t;
   if (current_lang_name == lang_name_cplusplus)
     DECL_LANGUAGE (t) = lang_cplusplus;
@@ -4772,21 +4768,15 @@ retrofit_lang_decl (t)
     DECL_LANGUAGE (t) = lang_java;
   else my_friendly_abort (64);
 
-#if 0 /* not yet, should get fixed properly later */
-  if (code == TYPE_DECL)
-    {
-      tree id;
-      id = get_identifier (build_overload_name (type, 1, 1));
-      DECL_ASSEMBLER_NAME (t) = id;
-    }
-
-#endif
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)lang_decl] += 1;
   tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
 #endif
 }
 
+/* Like build_decl, except that a new lang_decl_flags structure is
+   placed in DECL_LANG_SPECIFIC.  */
+
 tree
 build_lang_field_decl (code, name, type)
      enum tree_code code;
@@ -4796,28 +4786,16 @@ build_lang_field_decl (code, name, type)
   extern struct obstack *current_obstack, *saveable_obstack;
   register tree t = build_decl (code, name, type);
   struct obstack *obstack = current_obstack;
-  register int i = sizeof (struct lang_decl_flags) / sizeof (int);
-  register int *pi;
-#if 0 /* not yet, should get fixed properly later */
-
-  if (code == TYPE_DECL)
-    {
-      tree id;
-      id = get_identifier (build_overload_name (type, 1, 1));
-      DECL_ASSEMBLER_NAME (t) = id;
-    }
-#endif
 
   if (! TREE_PERMANENT (t))
     obstack = saveable_obstack;
   else
     my_friendly_assert (obstack == &permanent_obstack, 235);
 
-  pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags));
-  while (i > 0)
-    pi[--i] = 0;
-
-  DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
+  DECL_LANG_SPECIFIC (t) 
+    = ((struct lang_decl *) 
+       obstack_alloc (obstack, sizeof (struct lang_decl_flags)));
+  bzero (DECL_LANG_SPECIFIC (t), sizeof (struct lang_decl_flags));
   return t;
 }
 
index 8f997ad..337e55a 100644 (file)
@@ -131,3 +131,5 @@ extern tree got_object;
 extern int pending_lang_change;
 
 extern int yylex PROTO((void));
+
+extern struct lang_decl *free_lang_decl_chain;
index 809a7eb..b2b85c9 100644 (file)
@@ -4444,7 +4444,7 @@ case 12:
     break;}
 case 13:
 #line 386 "parse.y"
-{ if (! toplevel_bindings_p () && ! pseudo_global_level_p())
+{ if (! toplevel_bindings_p ())
                  pop_everything (); ;
     break;}
 case 14:
index 94acf0a..5698789 100644 (file)
@@ -383,7 +383,7 @@ asm_keyword:
 lang_extdef:
                { if (pending_lang_change) do_pending_lang_change(); }
          extdef
-               { if (! toplevel_bindings_p () && ! pseudo_global_level_p())
+               { if (! toplevel_bindings_p ())
                  pop_everything (); }
        ;
 
index 6e491e1..e00afbd 100644 (file)
@@ -123,7 +123,9 @@ static tree build_template_parm_index PROTO((int, int, int, tree, tree));
 static int inline_needs_template_parms PROTO((tree));
 static void push_inline_template_parms_recursive PROTO((tree, int));
 static tree retrieve_specialization PROTO((tree, tree));
+static tree retrieve_local_specialization PROTO((tree, tree));
 static tree register_specialization PROTO((tree, tree, tree));
+static tree register_local_specialization PROTO((tree, tree, tree));
 static int unregister_specialization PROTO((tree, tree));
 static tree reduce_template_parm_level PROTO((tree, tree, int));
 static tree build_template_decl PROTO((tree, tree));
@@ -160,6 +162,7 @@ static int coerce_template_template_parms PROTO((tree, tree, int,
 static tree determine_specialization PROTO((tree, tree, tree *, int));
 static int template_args_equal PROTO((tree, tree));
 static void print_template_context PROTO((int));
+static void tsubst_default_arguments PROTO((tree));
 
 /* We use TREE_VECs to hold template arguments.  If there is only one
    level of template arguments, then the TREE_VEC contains the
@@ -756,6 +759,18 @@ retrieve_specialization (tmpl, args)
   return NULL_TREE;
 }
 
+/* Like retrieve_speciailization, but for local declarations.  FN is
+   the function in which we are looking for an instantiation.  */
+
+static tree
+retrieve_local_specialization (tmpl, fn)
+     tree tmpl;
+     tree fn;
+{
+  tree s = purpose_member (fn, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+  return s ? TREE_VALUE (s) : NULL_TREE;
+}
+
 /* Returns non-zero iff DECL is a specialization of TMPL.  */
 
 int
@@ -911,6 +926,22 @@ unregister_specialization (spec, tmpl)
   return 0;
 }
 
+/* Like register_specialization, but for local declarations.  FN is
+   the function in which we are registering SPEC, an instantiation of
+   TMPL.  */
+
+static tree
+register_local_specialization (spec, tmpl, fn)
+     tree spec;
+     tree tmpl;
+     tree fn;
+{
+  DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
+     = perm_tree_cons (fn, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+
+  return spec;
+}
+
 /* Print the list of candidate FNS in an error message.  */
 
 void
@@ -2350,7 +2381,7 @@ push_template_decl_real (decl, is_friend)
   int is_partial;
 
   /* See if this is a partial specialization.  */
-  is_partial = (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
+  is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl)
                && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
                && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));
 
@@ -2368,7 +2399,7 @@ push_template_decl_real (decl, is_friend)
   else
     /* Otherwise, if we're currently definining some class, the DECL
        is assumed to be a member of the class.  */
-    ctx = current_class_type;
+    ctx = current_scope ();
 
   if (ctx && TREE_CODE (ctx) == NAMESPACE_DECL)
     ctx = NULL_TREE;
@@ -2376,22 +2407,8 @@ push_template_decl_real (decl, is_friend)
   if (!DECL_CONTEXT (decl))
     DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
 
-  /* For determining whether this is a primary template or not, we're really
-     interested in the lexical context, not the true context.  */
-  if (is_friend)
-    info = current_class_type;
-  else
-    info = ctx;
-
   /* See if this is a primary template.  */
-  if (info && TREE_CODE (info) == FUNCTION_DECL)
-    primary = 0;
-  /* Note that template_class_depth returns 0 if given NULL_TREE, so
-     this next line works even when we are at global scope.  */
-  else if (processing_template_decl > template_class_depth (info))
-    primary = 1;
-  else
-    primary = 0;
+  primary = pseudo_global_level_p ();
 
   if (primary)
     {
@@ -2546,7 +2563,7 @@ push_template_decl_real (decl, is_friend)
 
   info = perm_tree_cons (tmpl, args, NULL_TREE);
 
-  if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+  if (DECL_IMPLICIT_TYPEDEF_P (decl))
     {
       SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
       if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
@@ -3932,16 +3949,13 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
        {
          TYPE_CONTEXT (t) = FROB_CONTEXT (context);
          
-         /* Create a stub TYPE_DECL for it.  */
-         type_decl = build_decl (TYPE_DECL, DECL_NAME (template), t);
-         SET_DECL_ARTIFICIAL (type_decl);
+         type_decl = create_implicit_typedef (DECL_NAME (template), t);
          DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
-         
+         TYPE_STUB_DECL (t) = type_decl;
          DECL_SOURCE_FILE (type_decl) 
            = DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
          DECL_SOURCE_LINE (type_decl) 
            = DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
-         TYPE_STUB_DECL (t) = TYPE_NAME (t) = type_decl;
        }
       else
        type_decl = TYPE_NAME (t);
@@ -5193,6 +5207,18 @@ instantiate_class_template (type)
   TYPE_BEING_DEFINED (type) = 0;
   repo_template_used (type);
 
+  /* Now that the class is complete, instantiate default arguments for
+     any member functions.  We don't do this earlier because the
+     default arguments may reference members of the class.  */
+  if (!PRIMARY_TEMPLATE_P (template))
+    for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
+      if (TREE_CODE (t) == FUNCTION_DECL 
+         /* Implicitly generated member functions will not have tmplate
+            information; they are not instantiations, but instead are
+            created "fresh" for each instantiation.  */
+         && DECL_TEMPLATE_INFO (t))
+       tsubst_default_arguments (t);
+
   popclass ();
   pop_from_top_level ();
   pop_tinst_level ();
@@ -5417,6 +5443,66 @@ tsubst_aggr_type (t, args, complain, in_decl, entering_scope)
     }
 }
 
+/* Substitute into the default argument ARG (a default argument for
+   FN), which has the indicated TYPE.  */
+
+tree
+tsubst_default_argument (fn, type, arg)
+     tree fn;
+     tree type;
+     tree arg;
+{
+  /* This default argument came from a template.  Instantiate the
+     default argument here, not in tsubst.  In the case of
+     something like: 
+     
+       template <class T>
+       struct S {
+        static T t();
+        void f(T = t());
+       };
+     
+     we must be careful to do name lookup in the scope of S<T>,
+     rather than in the current class.  */
+  if (DECL_CLASS_SCOPE_P (fn))
+    pushclass (DECL_REAL_CONTEXT (fn), 2);
+
+  arg = tsubst_expr (arg, DECL_TI_ARGS (fn), /*complain=*/1, NULL_TREE);
+  
+  if (DECL_CLASS_SCOPE_P (fn))
+    popclass ();
+
+  /* Make sure the default argument is reasonable.  */
+  arg = check_default_argument (type, arg);
+
+  return arg;
+}
+
+/* Substitute into all the default arguments for FN.  */
+
+static void
+tsubst_default_arguments (fn)
+     tree fn;
+{
+  tree arg;
+  tree tmpl_args;
+
+  tmpl_args = DECL_TI_ARGS (fn);
+
+  /* If this function is not yet instantiated, we certainly don't need
+     its default arguments.  */
+  if (uses_template_parms (tmpl_args))
+    return;
+
+  for (arg = TYPE_ARG_TYPES (TREE_TYPE (fn)); 
+       arg; 
+       arg = TREE_CHAIN (arg))
+    if (TREE_PURPOSE (arg))
+      TREE_PURPOSE (arg) = tsubst_default_argument (fn, 
+                                                   TREE_VALUE (arg),
+                                                   TREE_PURPOSE (arg));
+}
+
 /* Substitute the ARGS into the T, which is a _DECL.  TYPE is the
    (already computed) substitution of ARGS into TREE_TYPE (T), if
    appropriate.  Return the result of the substitution.  IN_DECL is as
@@ -5804,6 +5890,22 @@ tsubst_decl (t, args, type, in_decl)
                && (IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r)) 
                    == NULL_TREE))
              SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
+
+           /* We're not supposed to instantiate default arguments
+              until they are called, for a template.  But, for a
+              declaration like:
+
+                template <class T> void f () 
+                 { extern void g(int i = T()); }
+                
+              we should do the substitution when the template is
+              instantiated.  We handle the member function case in
+              instantiate_class_template since the default arguments
+              might refer to other members of the class.  */
+           if (!member
+               && !PRIMARY_TEMPLATE_P (gen_tmpl)
+               && !uses_template_parms (argvec))
+             tsubst_default_arguments (r);
          }
 
        /* Copy the list of befriending classes.  */
@@ -5877,26 +5979,56 @@ tsubst_decl (t, args, type, in_decl)
       }
       break;
 
+    case TYPE_DECL:
+      if (DECL_IMPLICIT_TYPEDEF_P (t))
+       {
+         /* For an implicit typedef, we just want the implicit
+            typedef for the tsubst'd type.  We've already got the
+            tsubst'd type, as TYPE, so we just need it's associated
+            declaration.  */
+         r = TYPE_NAME (type);
+         break;
+       }
+      else if (!DECL_LANG_SPECIFIC (t))
+       {
+         /* For a template type parameter, we don't have to do
+            anything special.  */
+         r= TYPE_NAME (type);
+         break;
+       }
+
+      /* Fall through.  */
+
     case VAR_DECL:
       {
        tree argvec;
        tree gen_tmpl;
        tree spec;
        tree tmpl;
-       tree ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, 
-                                    /*complain=*/1,
-                                    in_decl, /*entering_scope=*/1);
-       
+       tree ctx;
+
        /* Nobody should be tsubst'ing into non-template variables.  */
        my_friendly_assert (DECL_LANG_SPECIFIC (t) 
                            && DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
 
+       if (TYPE_P (DECL_CONTEXT (t)))
+         ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, 
+                                 /*complain=*/1,
+                                 in_decl, /*entering_scope=*/1);
+       else
+         /* Subsequent calls to pushdecl will fill this in.  */
+         ctx = NULL_TREE;
+
        /* Check to see if we already have this specialization.  */
        tmpl = DECL_TI_TEMPLATE (t);
        gen_tmpl = most_general_template (tmpl);
        argvec = tsubst (DECL_TI_ARGS (t), args, /*complain=*/1, in_decl);
-       spec = retrieve_specialization (gen_tmpl, argvec);
-       
+       if (ctx)
+         spec = retrieve_specialization (gen_tmpl, argvec);
+       else
+         spec = retrieve_local_specialization (gen_tmpl,
+                                               current_function_decl);
+
        if (spec)
          {
            r = spec;
@@ -5923,26 +6055,18 @@ tsubst_decl (t, args, type, in_decl)
 
        DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
        SET_DECL_IMPLICIT_INSTANTIATION (r);
-       register_specialization (r, gen_tmpl, argvec);
+       if (ctx)
+         register_specialization (r, gen_tmpl, argvec);
+       else
+         register_local_specialization (r, gen_tmpl,
+                                        current_function_decl);
 
        TREE_CHAIN (r) = NULL_TREE;
-       if (TREE_CODE (type) == VOID_TYPE)
+       if (TREE_CODE (r) == VAR_DECL && TREE_CODE (type) == VOID_TYPE)
          cp_error_at ("instantiation of `%D' as type void", r);
       }
       break;
 
-    case TYPE_DECL:
-      if (t == TYPE_NAME (TREE_TYPE (t)))
-       r = TYPE_NAME (type);
-      else
-       {
-         r = copy_node (t);
-         TREE_TYPE (r) = type;
-         DECL_CONTEXT (r) = current_class_type;
-         TREE_CHAIN (r) = NULL_TREE;
-       }
-      break;
-
     default:
       my_friendly_abort (0);
     } 
@@ -6759,15 +6883,15 @@ tsubst_copy (t, args, complain, in_decl)
          return t;
 
        /* Unfortunately, we cannot just call lookup_name here.
-        Consider:
-
-        template <int I> int f() {
-          enum E { a = I };
-          struct S { void g() { E e = a; } };
-        };
-
-        When we instantiate f<7>::S::g(), say, lookup_name is not
-        clever enough to find f<7>::a.  */
+          Consider:
+          
+            template <int I> int f() {
+            enum E { a = I };
+            struct S { void g() { E e = a; } };
+            };
+          
+          When we instantiate f<7>::S::g(), say, lookup_name is not
+          clever enough to find f<7>::a.  */
        enum_type 
          = tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl, 
                              /*entering_scope=*/0);
index f68edd6..300d710 100644 (file)
@@ -622,6 +622,17 @@ current_scope ()
   return current_class_type;
 }
 
+/* Returns non-zero if we are currently in a function scope.  Note
+   that this function returns zero if we are within a local class, but
+   not within a member function body of the local class.  */
+
+int
+at_function_scope_p ()
+{
+  tree cs = current_scope ();
+  return cs && TREE_CODE (cs) == FUNCTION_DECL;
+}
+
 /* Return the scope of DECL, as appropriate when doing name-lookup.  */
 
 static tree
@@ -1212,9 +1223,9 @@ lookup_field_queue_p (binfo, data)
     return binfo;
 }
 
-/* Within the scope of a template class, you can refer to the
-   particular to the current specialization with the name of the
-   template itself.  For example:
+/* Within the scope of a template class, you can refer to the to the
+   current specialization with the name of the template itself.  For
+   example:
    
      template <typename T> struct S { S* sp; }
 
index f464c33..0711da3 100644 (file)
@@ -780,12 +780,9 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
   if (TREE_CHAIN (string))
     {
       if (processing_template_decl)
-       {
-         /* We need to build the combined string on the permanent
-            obstack so that we can use it during instantiations.  */
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
-       }
+       /* We need to build the combined string on the permanent
+          obstack so that we can use it during instantiations.  */
+       push_permanent_obstack ();
 
       string = combine_strings (string);
 
@@ -842,8 +839,7 @@ finish_label_stmt (name)
 
   if (processing_template_decl)
     {
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
+      push_permanent_obstack ();
       decl = build_decl (LABEL_DECL, name, void_type_node);
       pop_obstacks ();
       DECL_SOURCE_LINE (decl) = lineno;
@@ -858,6 +854,21 @@ finish_label_stmt (name)
     }
 }
 
+/* Create a declaration statement for the declaration given by the
+   DECL.  */
+
+void
+add_decl_stmt (decl)
+     tree decl;
+{
+  tree decl_stmt;
+
+  /* We need the type to last until instantiation time.  */
+  TREE_TYPE (decl) = copy_to_permanent (TREE_TYPE (decl));
+  decl_stmt = build_min_nt (DECL_STMT, decl);
+  add_tree (decl_stmt);
+}
+
 /* Finish a parenthesized expression EXPR.  */
 
 tree
@@ -1302,9 +1313,8 @@ tree
 begin_class_definition (t)
      tree t;
 {
-  push_obstacks_nochange ();
-  end_temporary_allocation ();
-  
+  push_permanent_obstack ();
+
   if (t == error_mark_node
       || ! IS_AGGR_TYPE (t))
     {
@@ -1726,12 +1736,9 @@ finish_typeof (expr)
     {
       tree t;
 
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
-
+      push_permanent_obstack ();
       t = make_lang_type (TYPEOF_TYPE);
       TYPE_FIELDS (t) = expr;
-
       pop_obstacks ();
 
       return t;
index a6bbbe0..7a35b47 100644 (file)
@@ -442,7 +442,7 @@ build_cplus_array_type_1 (elt_type, index_type)
 
   push_obstacks_nochange ();
 
-  /* We need a new one.  If both ELT_TYPE and INDEX_TYPE are permanent,
+  /* If both ELT_TYPE and INDEX_TYPE are permanent,
      make this permanent too.  */
   if (TREE_PERMANENT (elt_type)
       && (index_type == 0 || TREE_PERMANENT (index_type)))
@@ -1533,8 +1533,7 @@ copy_template_template_parm (t)
   tree t2;
 
   /* Make sure these end up on the permanent_obstack.  */
-  push_obstacks_nochange ();
-  end_temporary_allocation ();
+  push_permanent_obstack ();
   
   t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
   template = copy_node (template);
@@ -2086,11 +2085,8 @@ copy_to_permanent (t)
   if (t == NULL_TREE || TREE_PERMANENT (t))
     return t;
 
-  push_obstacks_nochange ();
-  end_temporary_allocation ();
-
+  push_permanent_obstack ();
   t = mapcar (t, perm_manip);
-
   pop_obstacks ();
 
   return t;
@@ -2622,6 +2618,17 @@ push_expression_obstack ()
   current_obstack = expression_obstack;
 }
 
+/* Begin allocating on the permanent obstack.  When you're done
+   allocating there, call pop_obstacks to return to the previous set
+   of obstacks.  */
+
+void
+push_permanent_obstack ()
+{
+  push_obstacks_nochange ();
+  end_temporary_allocation ();
+}
+
 /* The type of ARG when used as an lvalue.  */
 
 tree
index 3723936..044f48f 100644 (file)
@@ -5090,8 +5090,7 @@ mark_addressable (exp)
          {
            /* We thought this would make a good constant variable,
               but we were wrong.  */
-           push_obstacks_nochange ();
-           end_temporary_allocation ();
+           push_permanent_obstack ();
 
            TREE_ASM_WRITTEN (x) = 0;
            DECL_RTL (x) = 0;
index 75b1054..d0af82f 100644 (file)
@@ -6,5 +6,5 @@ struct A { // ERROR - too many template parameter lists
 public:
   A() {}
 
-  A(const A<T>& b) {} // ERROR - invalid use of template
+  A(const A<T>& b) {}
 };
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/defarg12.C b/gcc/testsuite/g++.old-deja/g++.pt/defarg12.C
new file mode 100644 (file)
index 0000000..3c53e8e
--- /dev/null
@@ -0,0 +1,12 @@
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+template <class T = int>
+struct S 
+{
+  void f ()
+    {
+      struct U {
+      };
+    }
+};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/defarg13.C b/gcc/testsuite/g++.old-deja/g++.pt/defarg13.C
new file mode 100644 (file)
index 0000000..1082bf5
--- /dev/null
@@ -0,0 +1,13 @@
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+template <class T>
+void f (int i)
+{
+  struct S { void g (int j = i) {} }; // ERROR - default argument uses local
+
+  S s; // ERROR - instantiated here
+}
+
+template void f<double>(int); // ERROR - instantiated here
+