]> gcc.gnu.org Git - gcc.git/commitdiff
83rd Cygnus<->FSF merge
authorMike Stump <mrs@gcc.gnu.org>
Wed, 28 Feb 1996 22:01:56 +0000 (22:01 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Wed, 28 Feb 1996 22:01:56 +0000 (22:01 +0000)
From-SVN: r11362

27 files changed:
gcc/cp/ChangeLog
gcc/cp/Makefile.in
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/except.c
gcc/cp/expr.c
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/ptree.c
gcc/cp/repo.c
gcc/cp/rtti.c
gcc/cp/search.c
gcc/cp/sig.c
gcc/cp/spew.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/cp/xref.c

index 217146b76c9b847fd8d5cc39863d9a2e8632161d..49b3e9a83f60538d2fc9e3939273f2a500b46623 100644 (file)
@@ -1,3 +1,433 @@
+Wed Feb 28 09:28:44 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * lex.c (do_identifier): Check for DECL_INITIAL before using it.
+
+Tue Feb 27 16:35:32 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * typeck2.c (build_x_arrow): Call complete_type.
+
+       * pt.c (add_pending_template): Broken out.
+       (lookup_template_class): If -fexternal-templates, call it for all
+       the methods of implemented types.
+       (instantiate_class_template): Instead of instantiating them here.
+       (instantiate_decl): Handle -fexternal-templates earlier.
+
+Tue Feb 27 15:51:32 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * search.c, lex.c, decl.c, class.c, cp-tree.h: Don't wrap the
+       memoized lookup stuff inside GATHER_STATISTICS.
+
+Tue Feb 27 10:38:08 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * decl.c (start_decl): Complain about array of incomplete type
+       here.
+       (grokdeclarator): Not here.
+
+       * parse.y (template_parm): Expand full_parm inline so we can set
+       the rule's precedence.
+
+       * pt.c (tsubst_expr): If we're in a template, just do tsubst_copy.
+       (tsubst): tsubst_expr the DECL_INITIAL of FIELD_DECLs.
+       * decl2.c (grokbitfield): Don't check for integer constant here.
+       * class.c (finish_struct_1): Check here.
+
+       * decl.c (define_label): Make the min decl go on permanent_obstack.
+
+       * pt.c (unify): Don't handle CONST_DECLs.
+       (uses_template_parms): Don't check DECL_INITIAL on a CONST_DECL.
+       (tsubst_copy): Ditto.
+
+       * lex.c (do_identifier): Do pull the DECL_INITIAL out of a
+       CONST_DECL for a template parm.
+
+Mon Feb 26 12:48:18 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * decl.c (grokdeclarator): Complain about array of incomplete type
+       here.
+       (start_decl_1): Not here.
+
+       * pt.c (tsubst): Handle pointer-to-function declarators.
+
+       * method.c (hack_identifier): If pedantic, diagnose local class
+       methods that require a static chain.
+
+       * decl.c (grok_op_properties): No longer static.
+       * cp-tree.h: Declare it.
+       * pt.c (tsubst): Call it for operators.
+       Use tsubst_copy for TREE_VECs.
+
+       * parse.y (template_arg): The expr has precedence like '>'.
+
+Fri Feb 23 14:51:52 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * pt.c (coerce_template_parms): Don't coerce an expression using
+       template parms.
+       (uses_template_parms): Also check DECL_INITIAL in CONST_DECLs.
+       (tsubst): Don't use build_index_2_type if the max_value uses template
+       parms.
+       * method.c (build_overload_int): Emit something arbitrary for an
+       expression using template parms.
+
+       * parse.y (template_close_bracket): New non-terminal to catch use
+       of '>>' instead of '> >' in template class names.
+       (template_type): Use it.
+       * Makefile.in (CONFLICTS): Causes one more r/r conflict.
+
+       * tree.def: Add CAST_EXPR.
+       * typeck2.c (build_functional_cast): Use CAST_EXPR instead of
+       CONVERT_EXPR for minimal_parse_mode.
+       * typeck.c (build_c_cast): Ditto.
+       * pt.c (tsubst_copy): Ditto.
+       * decl2.c (build_expr_from_tree): Ditto.
+       * error.c (dump_expr): Ditto.
+
+Fri Feb 23 10:36:46 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * except.c (SetTerminate, SetUnexpected): Put back global vars.
+       (init_exception_processing): Put back decl/init of
+       set_unexpected_fndecl and set_terminate_fndecl, needed to get the
+       fns from libstdc++.
+
+       * decl.c (struct binding_level): Delete ACCEPT_ANY bitfield.
+       (declare_uninstantiated_type_level, uninstantiated_type_level_p):
+       Delete unused fns.
+       * cp-tree.h (declare_uninstantiated_type_level,
+       uninstantiated_type_level_p): Delete prototypes.
+
+Thu Feb 22 19:36:15 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * pt.c (tsubst_expr): Add default return.
+
+Thu Feb 22 16:47:24 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * error.c (fndecl_as_string): Delete unused arg CNAME.
+       * sig.c (build_signature_table_constructor,
+       build_signature_method_call): Fix calls.
+
+       * class.c (the_null_vtable_entry): Delete var definition.
+       (init_class_processing): Delete tree the_null_vtable_entry init.
+       * decl.c (no_print_{functions, builtins}): Declare as static.
+       (__tp_desc_type_node): #if 0 var definition.
+       (init_type_desc): #if 0 init of __tp_desc_type_node.
+       (vb_off_identifier): Move var decl into init_decl_processing.
+       (current_function_assigns_this): Declare as static.
+       (int_ftype_ptr_ptr_int, void_ftype_ptr_int_int): Delete var decls.
+       (init_decl_processing): Delete init of void_ftype_ptr_ptr_int.
+       Move decls of string_ftype_ptr_ptr and int_ftype_string_string here.
+       * decl2.c (delete_sanity): Delete definition/mod of local var ELT_SIZE.
+       * init.c (BI_header_type, BI_header_size): Declare as static.
+       * pt.c (template_classes): Delete unused var.
+       (add_pending_template): Delete decl for non-existent fn.
+       (lookup_template_class): Delete vars CODE and TAG_CODE.
+       (instantiate_template): Delete unused var TARGS.
+       * cp-tree.h (vb_off_identifier, current_function_assigns_this):
+       Delete decls.
+       (__tp_desc_type_node): #if 0 var decl.
+       (fndecl_as_string): Fix prototype.
+
+Thu Feb 22 15:56:19 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * tree.def: Add GOTO_STMT.
+       * pt.c (tsubst_expr): Support goto and labels.
+       * decl.c (define_label): Support minimal parsing.
+       * parse.y (simple_stmt): Ditto.
+
+Thu Feb 22 15:30:12 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * xref.c (GNU_xref_member): Only define/set var I if
+       XREF_SHORT_MEMBER_NAMES is defined, to match when it's actually
+       used.
+       (GNU_xref_end_scope): Delete unused fifth arg TRNS.
+       (GNU_xref_end): Fix call.
+       * decl.c (poplevel, poplevel_class, finish_method): Fix calls.
+       * cp-tree.h (GNU_xref_end_scope): Fix prototype.
+
+       * tree.c (build_exception_variant): Delete unused vars I, A, T,
+       T2, and CNAME.
+       (layout_vbasetypes): Delete unused var NONVIRTUAL_VAR_SIZE.
+       (mapcar): Delete unused var CODE.
+       (build_cplus_new): Delete unused arg WITH_CLEANUP_P.
+       (break_out_cleanups): Fix call.
+       (bot_manip): Likewise.
+       * call.c (build_method_call): Likewise.
+       * cvt.c (build_up_reference, convert_to_reference, cp_convert):
+       Likewise.
+       * typeck.c (unary_complex_lvalue, build_modify_expr,
+       convert_for_initialization): Likewise.
+       * typeck2.c (build_functional_cast): Likewise.
+       * cp-tree.h (build_cplus_new): Fix prototype.
+
+       * repo.c (open_repo_file): Delete unused var Q.
+       (repo_compile_flags, repo_template_declared,
+       repo_template_defined, repo_class_defined, repo_inline_used,
+       repo_vtable_used, repo_tinfo_used): #if 0 unused fns.
+       (repo_get_id, repo_vtable_used): Declare as static. 
+       * cp-tree.h (mark_{decl,class}_instantiated, finish_repo): Add
+       prototypes.
+
+Thu Feb 22 14:53:35 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * parse.y (pending_inlines): Add function_try_block case.
+
+       * pt.c (unify): Fix for template const parms.
+
+Thu Feb 22 13:24:15 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * lex.c (extract_interface_info): Delete forward decl.
+       (default_copy_constructor_body, default_assign_ref_body): Delete
+       decls for non-existent functions.
+       (synth_firstobj, inline_text_firstobjs): Delete unused vars.
+       (init_lex): Delete setting them.
+       (cons_up_default_function): Delete unused vars FUNC_BUF,
+       FUNC_LEN, and COMPLEX.  Delete code setting COMPLEX.  Delete old
+       #if 0'd synth code.
+       (toplevel, expression_obstack): Delete unused extern decls.
+       (tree_node_kind): Delete unused enum.
+       (tree_node_counts, tree_node_sizes): Wrap with #ifdef
+       GATHER_STATISTICS.
+       (tree_node_kind_names): Delete unused extern decl.
+       (synth_obstack): Delete unused var.
+       (init_lex): Don't set it.
+       (init_parse): Add decl before use.
+       (reduce_count): Only define #ifdef GATHER_STATISTICS && REDUCE_LENGTH.
+       (current_unit_{name, language}): Delete unused vars. 
+       (check_newline): Don't bother setting them, just accept the #pragma.
+       * cp-tree.h (init_repo, peek_yylex): Add prototypes.
+       (current_unit_{name, language}): Delete decls.
+
+       * search.c: Wrap all of the memoized functions, macros, and
+       variables inside #ifdef GATHER_STATISTICS.
+       (lookup_field, lookup_fnfields): Likewise.
+       (init_search_processing): Likewise.
+       (reinit_search_statistics): Wrap whole function.
+       * lex.c (reinit_lang_specific): Wrap call to reinit_search_statistics.
+
+       * decl.c (finish_function): Only call pop_memoized_context if
+       GATHER_STATISTICS is defined.
+       (start_function): Likewise for push_memoized_context.
+       * class.c (pushclass, popclass): Likewise.
+
+       * cp-tree.h (CLASSTYPE_MTABLE_ENTRY): Move definition from here...
+       * search.c (CLASSTYPE_MTABLE_ENTRY): ... to here.
+
+       * cvt.c (cp_convert): Delete unused local var FORM.
+       * cp-tree.h (can_convert, can_convert_arg, real_lvalue_p): Add
+       prototypes.
+
+Thu Feb 22 13:19:44 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * pt.c (do_poplevel): Oops; really return what we get from
+       poplevel this time.
+
+Thu Feb 22 11:41:44 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * cp-tree.h (is_aggr_type): Add prototype.
+
+       * cp-tree.h ({push,pop}_cp_function_context): Add decls.
+       * method.c ({push,pop}_cp_function_context): Delete decls.
+       * except.c (start_eh_unwinder, end_eh_unwinder): Declare as void.
+       (SetUnexpected, SetTerminate): Delete unused vars.
+       (init_exception_processing): Don't set SetUnexpected or
+       SetTerminate.  Don't set SET_UNEXPECTED_FNDECL or SET_TERMINATE_FNDECL.
+       (output_exception_table_entry): Delete unused array LABEL.
+       (expand_internal_throw): Delete unused var PARAMS.
+       (expand_start_catch_block): Delete unused var CLEANUP.
+       (emit_exception_table): Delete unused var EH_NODE_DECL.
+       (expand_builtin_throw): Delete unused vars UNWIND_AND_THROW and
+       GOTO_UNWIND_AND_THROW.  Don't set them.
+       (end_eh_unwinder): Add top decl.
+       (pop_rtl_from_perm): Delete unused decl of PERMANENT_OBSTACK.
+       (exception_section, push_rtl_perm, do_function_call,
+       lang_interim_eh, push_eh_cleanup, eh_outer_context,
+       expand_end_eh_spec, end_eh_unwinder): Declare as static.
+       (saved_pc, saved_throw_type, saved_throw_value, saved_cleanup,
+       throw_used): Likewise.
+       * cp-tree.h (expand_end_eh_spec): Delete prototype.
+
+       * search.c (dfs_mark, dfs_mark_vtable_path,
+       dfs_unmark_vtable_path, dfs_mark_new_vtable,
+       dfs_unmark_new_vtable, dfs_clear_search_slot,
+       dfs_search_slot_nonempty_p, bfs_markedp, bfs_unmarkedp,
+       bfs_marked_vtable_pathp, bfs_unmarked_vtable_pathp,
+       bfs_marked_new_vtablep, bfs_unmarked_new_vtablep): #if 0 unused
+       functions.
+       (n_fields_searched, n_calls_lookup_field, n_calls_lookup_field_1,
+       n_calls_lookup_fnfields, n_calls_lookup_fnfields_1,
+       n_calls_get_base_type, n_outer_fields_searched, n_contexts_saved):
+       Only define #ifdef GATHER_STATISTICS.
+       (reinit_search_statistics): Only init some vars if GATHER_STATISTICS
+       is defined.
+       (vbase_decl): Delete var definition.
+       (init_search): Delete old decl.
+       (init_vbase_pointers): Delete building of VBASE_DECL, since it's
+       never actually used.
+       (expand_indirect_vtbls_init): Delete init of VBASE_DECL.
+       (get_base_distance_recursive): Delete unused fourth arg
+       BASETYPE_PATH.  Fix call .
+       (get_base_distance): Fix call.
+       (push_class_decls): Delete unused var ID.
+       (make_memoized_table_entry): Declare as static.
+       (breadth_first_search): Declare as static.
+       (tree_has_any_destructor_p): Declare as static.
+       (pop_class_decls): Delete unused arg pop_class_decls.
+       * class.c (popclass): Fix call to pop_class_decls.
+       * cp-tree.h (make_memoized_table_entry, breadth_first_search,
+       tree_has_any_destructor_p): Delete prototypes.
+
+       * rtti.c (build_ptmf_desc): Delete unused arg TYPE.
+       (build_t_desc): Fix call.  Delete unused vars ELEMS and TT.
+       (build_dynamic_cast): Delete unused local vars TMP1 and RETVAL.
+       (build_user_desc): Delete unused var T.
+       (build_class_desc): Delete unused vars T and OFF.
+       (build_t_desc): Delete unused var NAME_STRING.
+       (build_headof): Make static.
+       (get_bad_cast_node): Likewise.
+       (get_def_to_follow): Likewise.
+       * cp-tree.h (init_type_desc): Add prototype.
+       (build_headof): Remove prototype.
+
+Thu Feb 22 00:54:22 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * pt.c (tsubst): Only look for matching decls at file scope for
+       non-member functions.
+
+       * call.c (build_scoped_method_call): Handle scoped destructor
+       calls in templates.
+
+       * decl.c (*_top_level): Also save previous_class_values.
+
+       * pt.c (tsubst_expr): Support do {} while loops.
+       * parse.y (simple_stmt): Ditto.
+       * tree.def: Ditto.
+
+       * method.c (build_overload_identifier): For a class nested in a
+       template class, don't mangle in the template parms from our
+       context.
+
+       * lex.c, cp-tree.h: Remove support for template instantiations in
+       the pending_inlines code.
+       * pt.c: Remove dead functions and unused arguments.
+       (uses_template_parms): TYPENAME_TYPEs always use template parms.
+       * parse.y: Stop passing anything to end_template_decl.
+       * tree.c (print_lang_statistics): Only print tinst info #ifdef
+       GATHER_STATISTICS.
+
+Wed Feb 21 16:57:33 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * init.c (expand_recursive_init{,_1}): Delete decls. 
+       (sort_member_init): Delete unused var INIT.
+       (emit_base_init): Delete unused var X.
+       (build_offset_ref): Delete unused var CNAME.
+       (sort_member_init): Delete unused var FIELDS_TO_UNMARK.
+       (emit_base_init): Delete unused local var BASE.  Delete extern
+       decl of IN_CHARGE_IDENTIFIER.
+       (build_delete): Delete unused local var VIRTUAL_SIZE.
+
+       * init.c (build_vec_delete): Delete unused third arg ELT_SIZE.
+       (build_delete): Fix call.
+       * decl2.c (delete_sanity): Likewise.
+       * cp-tree.h (build_vec_delete): Update prototype.
+
+       * typeck.c (common_base_type): Delete unused var TMP.
+       (build_binary_op): Delete local var ARGS_SAVE.
+       (build_array_ref): Delete unused var ITYPE.
+       (c_expand_return): Delete unused var USE_TEMP.
+
+       * typeck.c (compexcepttypes): Delete unused arg STRICT.
+       (comptypes): Fix calls.
+       * decl.c (duplicate_decls): Likewise.
+       * cp-tree.h (compexcepttypes): Delete extra arg.
+
+       * decl2.c (check_classfn): Delete unused second arg CNAME.
+       * decl.c (start_decl, grokfndecl): Fix calls.
+       * init.c (do_friend): Likewise.
+       * cp-tree.h (check_classfn): Update prototype.
+
+       * cp-tree.h (signature_error, import_export_vtable,
+       append_signature_fields, id_in_current_class, mark_used,
+       copy_assignment_arg_p): Add decls.
+       * decl2.c (mark_used): Delete decl.
+
+       * class.c (n_*): Wrap with #ifdef GATHER_STATISTICS.
+
+       * class.c (get_vtable_entry): Diable unused function.
+       (doing_hard_virtuals): Delete unused static global var.
+       (finish_struct_1): Don't init DOING_HARD_VIRTUALS.
+       (prepare_fresh_vtable): Delete unused vars PATH and RESULT.
+       (overrides): Delete unused vars RETTYPE and BASE_RETTYPE.
+       (modify_one_vtable): Delete unused var OLD_RTTI.
+       (finish_struct_anon): Delete unused vars OFFSET and X.
+       (finish_struct_bits): Delete unused var METHOD_VEC.
+       (get_basefndecls): Delete unused var PURPOSE.  Delete unused
+       for-scope local variable METHODS.
+
+       * call.c (user_harshness): Delete unused/unneeded arg PARM.
+       (ideal_candidate): Delete unused args BASETYPE and PARMS.
+       (build_method_call): Delete unused args passed into ideal_candidate.
+       (build_overload_call_real): Likewise.  Delete unused var OVERLOAD_NAME.
+       * cp-tree.h (synthesize_method): Add decl.
+
+       * decl.c (note_level_for_for): Give void return type.
+       (pushdecl_nonclass_level): Likewise.
+       (finish_function): Delete unused vars VFIELDS and ALLOCATED_THIS.
+       (poplevel): Delete unused var IMPLICIT_TRY_BLOCK.
+       (suspend_binding_level): Delete unused var LEVEL.
+       (duplicate_decls): Delete unused var CTYPE.
+       (duplicate_decls): Delete unused var PREVIOUS_C_DECL.
+       (init_decl_processing): Delete unused vars FLOAT_ENDLINK and
+       PTR_ENDLINK.
+       (grokdeclarator): Delete unused var C.
+       (grokdeclarator): Delete unused var SIZE_VARIES.
+       (grokparms): Delete unused var SAW_VOID.
+       (start_function): Delete unused var OLDDECL.
+       (cplus_expand_expr_stmt): Delete unused var
+       REMOVE_IMPLICIT_IMMEDIATELY. 
+
+       * cp-tree.h (pushdecl_nonclass_level): Fix prototype.
+
+       * Makefile.in (CONFLICTS): Update to 12 shift/reduce.
+
+Wed Feb 21 00:06:17 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * tree.c (build_min): Set TREE_COMPLEXITY to lineno.
+       (build_min_nt): Ditto.
+       * pt.c (do_pushlevel): Emit line note.
+       (do_poplevel): Return what we get from poplevel.
+       (tsubst_expr): Set lineno from TREE_COMPLEXITY in stmt nodes.
+       * parse.y: Use do_pushlevel and do_poplevel.
+       * cp-tree.h: Declare do_poplevel.
+       
+       * cp-tree.h: Declare at_eof.
+       * decl.c (cp_finish_decl): Pass it to rest_of_decl_compilation.
+       * decl2.c (import_export_decl): Renamed from import_export_inline.
+       (finish_file): Call it to do interface handling for statics.
+       * pt.c (tsubst_copy): Call mark_used on variables and functions
+       used here.
+
+       * decl2.c (finish_file): Don't emit statics we can't generate.
+       * pt.c (instantiate_decl): Don't set interface on instantiations
+       we can't generate.
+
+       * cp-tree.h (struct tinst_level): Change 'classname' to 'decl'.
+       * tree.c (print_lang_statistics): Print max template depth.
+       * pt.c (push_tinst_level): Dump entire instantiation context.
+       (instantiate_class_template): Use it and pop_tinst_level.
+       (instantiate_decl): Ditto.
+
+       * call.c class.c cp-tree.h decl.c decl2.c error.c lex.c method.c
+       pt.c ptree.c tree.def: Remove all traces of UNINSTANTIATED_P_TYPE.
+
+Tue Feb 20 18:21:51 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * call.c class.c cp-tree.h cvt.c decl.c decl2.c error.c expr.c
+       init.c lex.c method.c parse.y pt.c repo.c search.c spew.c tree.c
+       tree.def typeck.c typeck2.c xref.c: Massive, systemic changes for
+       the new template implementation.
+
+Tue Feb 20 17:14:29 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * decl2.c (check_cp_case_value): Use STRIP_TYPE_NOPS.
+
 Thu Feb 15 18:44:42 1996  Mike Stump  <mrs@cygnus.com>
 
        * decl.c (cp_finish_decl): Delay emitting the debug information for
index 8bfbb125cc38b7220705b583815c65bb3bb2fe88..37ccc18930a7292fbbc6e1908c4712d6ef68274e 100644 (file)
@@ -168,7 +168,6 @@ OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o
 
 compiler: ../cc1plus
 ../cc1plus: $(P) $(CXX_OBJS) $(OBJDEPS) $(LIBDEPS)
-       rm -f ../cc1plus$(exeext)
        $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
              $(CXX_OBJS) $(OBJS) $(LIBS)
 
@@ -196,7 +195,7 @@ parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h
        $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
   `echo $(PARSE_C) | sed 's,^\./,,'`
 
-CONFLICTS = expect 7 shift/reduce conflicts and 38 reduce/reduce conflicts.
+CONFLICTS = expect 12 shift/reduce conflicts and 39 reduce/reduce conflicts.
 $(PARSE_H) : $(PARSE_C)
 $(PARSE_C) : $(srcdir)/parse.y
        @echo $(CONFLICTS)
index cbe5588a3933116b6e8ff9729c89ba34fe3af02f..570c02077e291dfa839ca8dfd02dfbad210e84d6 100644 (file)
@@ -175,8 +175,8 @@ convert_harshness (type, parmtype, parm)
       if (! lvalue && ! (parm && TYPE_READONLY (ttl)))
        return EVIL_RETURN (h);
 
-      if (TYPE_READONLY (ttl) < constp
-         || TYPE_VOLATILE (ttl) < volatilep)
+      if ((TYPE_READONLY (ttl) < constp)
+         || (TYPE_VOLATILE (ttl) < volatilep))
        return EVIL_RETURN (h);
 
       /* When passing a non-const argument into a const reference, dig it a
@@ -646,9 +646,8 @@ convert_harshness (type, parmtype, parm)
    overload resolution.  */
 
 int
-user_harshness (type, parmtype, parm)
+user_harshness (type, parmtype)
      register tree type, parmtype;
-     tree parm;
 {
   tree conv;
   tree winner = NULL_TREE;
@@ -668,7 +667,7 @@ user_harshness (type, parmtype, parm)
        continue;
 
       if (tmp = convert_harshness (type, TREE_VALUE (conv), NULL_TREE),
-         tmp.code < USER_CODE && tmp.distance >= 0)
+         (tmp.code < USER_CODE) && (tmp.distance >= 0))
        {
          if (winner)
            return EVIL_CODE;
@@ -692,7 +691,7 @@ can_convert (to, from)
 {
   struct harshness_code h;
   h = convert_harshness (to, from, NULL_TREE);
-  return h.code < USER_CODE && h.distance >= 0;
+  return (h.code < USER_CODE) && (h.distance >= 0);
 }
 
 int
@@ -701,7 +700,7 @@ can_convert_arg (to, from, arg)
 {
   struct harshness_code h;
   h = convert_harshness (to, from, arg);
-  return h.code < USER_CODE && h.distance >= 0;
+  return (h.code < USER_CODE) && (h.distance >= 0);
 }
 
 #ifdef DEBUG_MATCHING
@@ -1091,11 +1090,9 @@ strictly_better (x, y)
    LEN is the length of the parameter list.  */
 
 static struct candidate *
-ideal_candidate (basetype, candidates, n_candidates, parms, len)
-     tree basetype;
+ideal_candidate (candidates, n_candidates, len)
      struct candidate *candidates;
      int n_candidates;
-     tree parms;
      int len;
 {
   struct candidate *cp = candidates+n_candidates;
@@ -1347,15 +1344,6 @@ find_scoped_type (type, inner_name, inner_types)
       tags = TREE_CHAIN (tags);
     }
 
-#if 0
-  /* XXX This needs to be fixed better.  */
-  if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
-    {
-      sorry ("nested class lookup in template type");
-      return NULL_TREE;
-    }
-#endif
-
   /* Look for a TYPE_DECL.  */
   for (tags = TYPE_FIELDS (type); tags; tags = TREE_CHAIN (tags))
     if (TREE_CODE (tags) == TYPE_DECL && DECL_NAME (tags) == inner_name)
@@ -1477,6 +1465,17 @@ build_scoped_method_call (exp, basetype, name, parms)
       || basetype == error_mark_node)
     return error_mark_node;
 
+  if (current_template_parms)
+    {
+      if (TREE_CODE (name) == BIT_NOT_EXPR)
+       {
+         tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 1);
+         name = build_min_nt (BIT_NOT_EXPR, type);
+       }
+      name = build_min_nt (SCOPE_REF, basetype, name);
+      return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, 0);
+    }
+
   if (TREE_CODE (type) == REFERENCE_TYPE)
     type = TREE_TYPE (type);
 
@@ -1489,7 +1488,7 @@ build_scoped_method_call (exp, basetype, name, parms)
        cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')",
                  exp, basetype, type);
       name = TREE_OPERAND (name, 0);
-      if (basetype != get_type_value (name))
+      if (basetype != name && basetype != get_type_value (name))
        cp_error ("qualified type `%T' does not match destructor name `~%T'",
                  basetype, name);
       return convert (void_type_node, exp);
@@ -1520,7 +1519,8 @@ build_scoped_method_call (exp, basetype, name, parms)
        {
          /* Explicit call to destructor.  */
          name = TREE_OPERAND (name, 0);
-         if (! (name == constructor_name (TREE_TYPE (decl))
+         if (! (name == TYPE_MAIN_VARIANT (TREE_TYPE (decl))
+                || name == constructor_name (TREE_TYPE (decl))
                 || TREE_TYPE (decl) == get_type_value (name)))
            {
              cp_error
@@ -1607,7 +1607,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
 {
   register tree function, fntype, value_type;
   register tree basetype, save_basetype;
-  register tree baselink, result, method_name, parmtypes, parm;
+  register tree baselink, result, parmtypes, parm;
+#if 0
+  register tree method_name;
+#endif
   tree last;
   int pass;
   tree access = access_public_node;
@@ -1636,6 +1639,17 @@ build_method_call (instance, name, parms, basetype_path, flags)
       || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
     return error_mark_node;
 
+  if (current_template_parms)
+    {
+      if (TREE_CODE (name) == BIT_NOT_EXPR)
+       {
+         tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 1);
+         name = build_min_nt (BIT_NOT_EXPR, type);
+       }
+
+      return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, 0);
+    }
+
   /* This is the logic that magically deletes the second argument to
      operator delete, if it is not needed. */
   if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2)
@@ -1668,8 +1682,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
       basetype = TREE_TYPE (instance);
       if (TREE_CODE (basetype) == REFERENCE_TYPE)
        basetype = TREE_TYPE (basetype);
-      if (! ((IS_AGGR_TYPE (basetype)
-             && name == constructor_name (basetype))
+      if (! (name == basetype
+            || (IS_AGGR_TYPE (basetype)
+                && name == constructor_name (basetype))
             || basetype == get_type_value (name)))
        {
          cp_error ("destructor name `~%D' does not match type `%T' of expression",
@@ -1734,7 +1749,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
       else if (IDENTIFIER_HAS_TYPE_VALUE (name))
        {
          basetype = IDENTIFIER_TYPE_VALUE (name);
-         name = constructor_name_full (basetype);
+         name = constructor_name (basetype);
        }
       else
        {
@@ -1884,7 +1899,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
              if (TREE_CODE (instance) != CALL_EXPR)
                my_friendly_abort (125);
              if (TYPE_NEEDS_CONSTRUCTING (basetype))
-               instance = build_cplus_new (basetype, instance, 0);
+               instance = build_cplus_new (basetype, instance);
              else
                {
                  instance = get_temp_name (basetype, 0);
@@ -1942,7 +1957,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
        }
     }
 
-  if (TYPE_SIZE (basetype) == 0)
+  if (TYPE_SIZE (complete_type (basetype)) == 0)
     {
       /* This is worth complaining about, I think.  */
       cp_error ("cannot lookup method in incomplete type `%T'", basetype);
@@ -2033,8 +2048,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
 
   if ((IDENTIFIER_HAS_TYPE_VALUE (name)
        && ! IDENTIFIER_OPNAME_P (name)
-       && IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name))
-       && TREE_CODE (IDENTIFIER_TYPE_VALUE (name)) != UNINSTANTIATED_P_TYPE)
+       && IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name)))
       || name == constructor_name (basetype))
     {
       tree tmp = NULL_TREE;
@@ -2301,8 +2315,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
              int n_candidates = cp - candidates;
              extern int warn_synth;
              TREE_VALUE (parms) = instance_ptr;
-             cp = ideal_candidate (save_basetype, candidates,
-                                   n_candidates, parms, len);
+             cp = ideal_candidate (candidates, n_candidates, len);
              if (cp == (struct candidate *)0)
                {
                  if (flags & LOOKUP_COMPLAIN)
@@ -2529,7 +2542,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
 
   value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
 
-  if (TYPE_SIZE (value_type) == 0)
+  if (TYPE_SIZE (complete_type (value_type)) == 0)
     {
       if (flags & LOOKUP_COMPLAIN)
        incomplete_type_error (0, value_type);
@@ -2710,7 +2723,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
      int buildxxx;
 {
   /* must check for overloading here */
-  tree overload_name, functions, function, parm;
+  tree functions, function, parm;
   tree parmtypes = NULL_TREE, last = NULL_TREE;
   register tree outer;
   int length;
@@ -2831,7 +2844,6 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
       function = outer;
       if (TREE_CODE (function) != FUNCTION_DECL
          && ! (TREE_CODE (function) == TEMPLATE_DECL
-               && ! DECL_TEMPLATE_IS_CLASS (function)
                && TREE_CODE (DECL_TEMPLATE_RESULT (function)) == FUNCTION_DECL))
        {
          enum tree_code code = TREE_CODE (function);
@@ -2869,7 +2881,11 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
                                TYPE_ARG_TYPES (TREE_TYPE (function)),
                                parms, &template_cost, 0);
          if (i == 0)
-           function = instantiate_template (function, targs);
+           {
+             function = instantiate_template (function, targs);
+             if (function == error_mark_node)
+               return function;
+           }
        }
 
       if (TREE_CODE (function) == TEMPLATE_DECL)
@@ -2924,8 +2940,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
       if (cp - candidates > 1)
        {
          struct candidate *best_cp
-           = ideal_candidate (NULL_TREE, candidates,
-                              cp - candidates, parms, parmlength);
+           = ideal_candidate (candidates, cp - candidates, parmlength);
          if (best_cp == (struct candidate *)0)
            {
              if (flags & LOOKUP_COMPLAIN)
index 6b8f88098550aabed9464bdb4973a0b879598b4e..4bceaa16310da8e1c1cb68b8e06c919906ebdb60 100644 (file)
@@ -81,7 +81,6 @@ tree previous_class_type;     /* _TYPE: the previous type that was a class */
 tree previous_class_values;            /* TREE_LIST: copy of the class_shadowed list
                                   when leaving an outermost class scope.  */
 static tree get_vfield_name PROTO((tree));
-tree the_null_vtable_entry;
 
 /* Way of stacking language names.  */
 tree *current_lang_base, *current_lang_stack;
@@ -109,6 +108,7 @@ tree access_private_virtual_node; /* 6 */
 
 /* Variables shared between class.c and call.c.  */
 
+#ifdef GATHER_STATISTICS
 int n_vtables = 0;
 int n_vtable_entries = 0;
 int n_vtable_searches = 0;
@@ -117,6 +117,7 @@ int n_convert_harshness = 0;
 int n_compute_conversion_costs = 0;
 int n_build_method_call = 0;
 int n_inner_fields_searched = 0;
+#endif
 
 /* Virtual baseclass things.  */
 tree
@@ -362,7 +363,6 @@ build_vbase_path (code, type, expr, path, alias_this)
    classes.  We do all overrides after we layout virtual base classes.
    */
 static tree pending_hard_virtuals;
-static int doing_hard_virtuals;
 
 /* Build an entry in the virtual function table.
    DELTA is the offset for the `this' pointer.
@@ -698,8 +698,7 @@ prepare_fresh_vtable (binfo, for_type)
      for_type, and we really want different names.  (mrs) */
   tree name = build_type_pathname (VTABLE_NAME_FORMAT, basetype, for_type);
   tree new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
-  tree path, offset;
-  int result;
+  tree offset;
 
   /* Remember which class this vtable is really for.  */
   DECL_CONTEXT (new_decl) = for_type;
@@ -741,6 +740,7 @@ prepare_fresh_vtable (binfo, for_type)
   SET_BINFO_NEW_VTABLE_MARKED (binfo);
 }
 
+#if 0
 /* Access the virtual function table entry that logically
    contains BASE_FNDECL.  VIRTUALS is the virtual function table's
    initializer.  We can run off the end, when dealing with virtual
@@ -765,6 +765,7 @@ get_vtable_entry (virtuals, base_fndecl)
     }
   return virtuals;
 }
+#endif
 
 /* Put new entry ENTRY into virtual function table initializer
    VIRTUALS.
@@ -913,7 +914,7 @@ add_method (type, fields, method)
     decl = copy_node (method);
     if (DECL_RTL (decl) == 0
         && (!processing_template_decl
-            || !uses_template_parms (decl)))
+           || !uses_template_parms (decl)))
       {
        make_function_rtl (decl);
        DECL_RTL (method) = DECL_RTL (decl);
@@ -1087,8 +1088,16 @@ delete_duplicate_fields_1 (field, fields)
                    cp_error_at ("duplicate nested type `%D'", x);
                  else if (TREE_CODE (field) == TYPE_DECL
                           || TREE_CODE (x) == TYPE_DECL)
-                   cp_error_at ("duplicate field `%D' (as type and non-type)",
-                               x);
+                   {
+                     /* Hide tag decls.  */
+                     if ((TREE_CODE (field) == TYPE_DECL
+                          && DECL_ARTIFICIAL (field))
+                         || (TREE_CODE (x) == TYPE_DECL
+                             && DECL_ARTIFICIAL (x)))
+                       continue;
+                     cp_error_at ("duplicate field `%D' (as type and non-type)",
+                                  x);
+                   }
                  else
                    cp_error_at ("duplicate member `%D'", x);
                  if (prev == 0)
@@ -1658,7 +1667,6 @@ finish_struct_bits (t, max_has_virtual)
      int max_has_virtual;
 {
   int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
-  tree method_vec = CLASSTYPE_METHOD_VEC (t);
 
   /* Fix up variants (if any).  */
   tree variants = TYPE_NEXT_VARIANT (t);
@@ -1677,6 +1685,7 @@ finish_struct_bits (t, max_has_virtual)
       /* Copy whatever these are holding today.  */
       TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t);
       TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t);
+      TYPE_FIELDS (variants) = TYPE_FIELDS (t);
       variants = TYPE_NEXT_VARIANT (variants);
     }
 
@@ -2167,7 +2176,7 @@ overrides (fndecl, base_fndecl)
     return 0;
   if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl))
     {
-      tree rettype, base_rettype, types, base_types;
+      tree types, base_types;
 #if 0
       retypes = TREE_TYPE (TREE_TYPE (fndecl));
       base_retypes = TREE_TYPE (TREE_TYPE (base_fndecl));
@@ -2291,7 +2300,6 @@ modify_one_vtable (binfo, t, fndecl, pfn)
      tree binfo, t, fndecl, pfn;
 {
   tree virtuals = BINFO_VIRTUALS (binfo);
-  tree old_rtti;
   unsigned HOST_WIDE_INT n;
   
   /* update rtti entry */
@@ -2711,8 +2719,6 @@ get_basefndecls (fndecl, t)
 
   while (methods)
     {
-      tree purpose = NULL_TREE;
-
       if (TREE_CODE (methods) == FUNCTION_DECL
          && DECL_VINDEX (methods) != NULL_TREE
          && DECL_NAME (fndecl) == DECL_NAME (methods))
@@ -2728,7 +2734,6 @@ get_basefndecls (fndecl, t)
     {
       tree base_binfo = TREE_VEC_ELT (binfos, i);
       tree basetype = BINFO_TYPE (base_binfo);
-      tree methods = TYPE_METHODS (basetype);
 
       base_fndecls = chainon (get_basefndecls (fndecl, basetype),
                              base_fndecls);
@@ -2913,8 +2918,6 @@ finish_struct_anon (t)
          tree* uelt = &TYPE_FIELDS (TREE_TYPE (field));
          for (; *uelt; uelt = &TREE_CHAIN (*uelt))
            {
-             tree offset, x;
-
              if (TREE_CODE (*uelt) != FIELD_DECL)
                continue;
 
@@ -3190,8 +3193,11 @@ finish_struct_1 (t, attributes, warn_anon)
                                                   &has_virtual, x, t);
          if (DECL_ABSTRACT_VIRTUAL_P (x))
            abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
+#if 0
+         /* XXX Why did I comment this out?  (jason) */
          else
            TREE_USED (x) = 1;
+#endif
        }
     }
 
@@ -3377,9 +3383,26 @@ finish_struct_1 (t, attributes, warn_anon)
          /* Detect and ignore out of range field width.  */
          if (DECL_INITIAL (x))
            {
-             register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
+             tree w = DECL_INITIAL (x);
+             register int width;
 
-             if (width < 0)
+             /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs.  */
+             STRIP_NOPS (w);
+
+             /* detect invalid field size.  */
+             if (TREE_CODE (w) == CONST_DECL)
+               w = DECL_INITIAL (w);
+             else if (TREE_READONLY_DECL_P (w))
+               w = decl_constant_value (w);
+
+             if (TREE_CODE (w) != INTEGER_CST)
+               {
+                 cp_error_at ("bit-field `%D' width not an integer constant",
+                              x);
+                 DECL_INITIAL (x) = NULL_TREE;
+               }
+             else if (width = TREE_INT_CST_LOW (w),
+                      width < 0)
                {
                  DECL_INITIAL (x) = NULL;
                  cp_error_at ("negative width in bit-field `%D'", x);
@@ -3789,6 +3812,8 @@ finish_struct_1 (t, attributes, warn_anon)
        {
          tree name = DECL_NAME (x);
          int i = /*TREE_VEC_ELT (method_vec, 0) ? 0 : */ 1;
+         if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))
+           continue;
          for (; i < n_methods; ++i)
            if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name)
              {
@@ -3842,7 +3867,6 @@ finish_struct_1 (t, attributes, warn_anon)
   /* Now fix up any virtual base class types that we left lying
      around.  We must get these done before we try to lay out the
      virtual function table.  */
-  doing_hard_virtuals = 1;
   pending_hard_virtuals = nreverse (pending_hard_virtuals);
 
   if (TYPE_USES_VIRTUAL_BASECLASSES (t))
@@ -3949,8 +3973,6 @@ finish_struct_1 (t, attributes, warn_anon)
        }
     }
 
-  doing_hard_virtuals = 0;
-
   /* Under our model of GC, every C++ class gets its own virtual
      function table, at least virtually.  */
   if (pending_virtuals || (flag_rtti && TYPE_VIRTUAL_P (t)))
@@ -4090,42 +4112,6 @@ finish_struct_1 (t, attributes, warn_anon)
        }
     }
 
-  /* Now add the tags, if any, to the list of TYPE_DECLs
-     defined for this type.  */
-  if (CLASSTYPE_TAGS (t))
-    {
-      x = CLASSTYPE_TAGS (t);
-      last_x = tree_last (TYPE_FIELDS (t));
-      while (x)
-       {
-         tree tag = TYPE_NAME (TREE_VALUE (x));
-
-         /* Check to see if it is already there.  This will be the case if
-            was do enum { red; } color; */
-         if (chain_member (tag, TYPE_FIELDS (t)))
-             {
-               x = TREE_CHAIN (x);
-               continue;
-             }
-
-#ifdef DWARF_DEBUGGING_INFO
-         if (write_symbols == DWARF_DEBUG)
-           {
-             /* Notify dwarfout.c that this TYPE_DECL node represent a
-                gratuitous typedef.  */
-             DECL_IGNORED_P (tag) = 1;
-           }
-#endif /* DWARF_DEBUGGING_INFO */
-
-         TREE_NONLOCAL_FLAG (TREE_VALUE (x)) = 0;
-         x = TREE_CHAIN (x);
-         last_x = chainon (last_x, tag);
-       }
-      if (TYPE_FIELDS (t) == NULL_TREE)
-       TYPE_FIELDS (t) = last_x;
-      CLASSTYPE_LOCAL_TYPEDECLS (t) = 1;
-    }
-
   if (TYPE_HAS_CONSTRUCTOR (t))
     {
       tree vfields = CLASSTYPE_VFIELDS (t);
@@ -4185,17 +4171,12 @@ finish_struct_1 (t, attributes, warn_anon)
   /* Make the rtl for any new vtables we have created, and unmark
      the base types we marked.  */
   finish_vtbls (TYPE_BINFO (t), 1, t);
-  TYPE_BEING_DEFINED (t) = 0;
   hack_incomplete_structures (t);
 
 #if 0
   if (TYPE_NAME (t) && TYPE_IDENTIFIER (t))
     undo_template_name_overload (TYPE_IDENTIFIER (t), 1);
 #endif
-  if (current_class_type)
-    popclass (0);
-  else
-    error ("trying to finish struct, but kicked out due to previous parse errors.");
 
   resume_momentary (old);
 
@@ -4235,9 +4216,12 @@ finish_struct_1 (t, attributes, warn_anon)
              = (value_member (TYPE_IDENTIFIER (t), pending_vtables) == 0);
          else if (CLASSTYPE_INTERFACE_ONLY (t))
            TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1;
+#if 0
+         /* XXX do something about this.  */
          else if (CLASSTYPE_INTERFACE_UNKNOWN (t))
            /* Only a first approximation!  */
            TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1;
+#endif
        }
       else if (CLASSTYPE_INTERFACE_ONLY (t))
        TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1;
@@ -4336,6 +4320,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
 
          if (TREE_CODE (x) == FUNCTION_DECL)
            {
+             DECL_CLASS_CONTEXT (x) = t;
              if (last_x)
                TREE_CHAIN (last_x) = TREE_CHAIN (x);
              /* Link x onto end of TYPE_METHODS. */
@@ -4354,6 +4339,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
              DECL_RESULT (x) = n;
            }
 #endif
+         if (TREE_CODE (x) != TYPE_DECL)
+           DECL_FIELD_CONTEXT (x) = t;
 
          if (! fields)
            fields = x;
@@ -4372,17 +4359,79 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
        }
     }
 
+  /* Now add the tags, if any, to the list of TYPE_DECLs
+     defined for this type.  */
+  if (CLASSTYPE_TAGS (t))
+    {
+      x = CLASSTYPE_TAGS (t);
+      while (x)
+       {
+         tree tag = TYPE_NAME (TREE_VALUE (x));
+
+         /* Check to see if it is already there.  This will be the case if
+            was do enum { red; } color; */
+         if (chain_member (tag, fields))
+             {
+               x = TREE_CHAIN (x);
+               continue;
+             }
+
+#ifdef DWARF_DEBUGGING_INFO
+         if (write_symbols == DWARF_DEBUG)
+           {
+             /* Notify dwarfout.c that this TYPE_DECL node represent a
+                gratuitous typedef.  */
+             DECL_IGNORED_P (tag) = 1;
+           }
+#endif /* DWARF_DEBUGGING_INFO */
+
+         TREE_NONLOCAL_FLAG (TREE_VALUE (x)) = 0;
+         x = TREE_CHAIN (x);
+         last_x = chainon (last_x, tag);
+       }
+      if (fields == NULL_TREE)
+       fields = last_x;
+      CLASSTYPE_LOCAL_TYPEDECLS (t) = 1;
+    }
+
   *tail = NULL_TREE;
   TYPE_FIELDS (t) = fields;
 
-  if (0 && processing_template_defn)
+  if (processing_template_decl)
     {
+      tree d = getdecls ();
+      for (; d; d = TREE_CHAIN (d))
+       {
+         /* If this is the decl for the class or one of the template
+             parms, we've seen all the injected decls.  */
+         if ((TREE_CODE (d) == TYPE_DECL
+              && (TREE_TYPE (d) == t
+                  || TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TYPE_PARM))
+             || TREE_CODE (d) == CONST_DECL)
+           break;
+         /* Don't inject TYPE_NESTED_NAMEs.  */
+         else if (TREE_MANGLED (DECL_NAME (d))
+                  || IDENTIFIER_TEMPLATE (DECL_NAME (d)))
+           continue;
+         DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t))
+           = tree_cons (NULL_TREE, d,
+                        DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t)));
+       }
       CLASSTYPE_METHOD_VEC (t)
        = finish_struct_methods (t, TYPE_METHODS (t), 1);
-      return t;
-    }
+      TYPE_SIZE (t) = integer_zero_node;
+    }      
   else
-    return finish_struct_1 (t, attributes, warn_anon);
+    t = finish_struct_1 (t, attributes, warn_anon);
+
+  TYPE_BEING_DEFINED (t) = 0;
+
+  if (current_class_type)
+    popclass (0);
+  else
+    error ("trying to finish struct, but kicked out due to previous parse errors.");
+
+  return t;
 }
 \f
 /* Return non-zero if the effective type of INSTANCE is static.
@@ -4516,7 +4565,6 @@ init_class_processing ()
   access_private_virtual_node = build_int_2 (6, 0);
 
   /* Keep these values lying around.  */
-  the_null_vtable_entry = build_vtable_entry (integer_zero_node, integer_zero_node);
   base_layout_decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, error_mark_node);
   TREE_TYPE (base_layout_decl) = make_node (RECORD_TYPE);
 
@@ -4592,6 +4640,9 @@ pushclass (type, modify)
 
   pushlevel_class ();
 
+  if (CLASSTYPE_TEMPLATE_INFO (type))
+    overload_template_name (type);
+
   if (modify)
     {
       tree tags;
@@ -4604,9 +4655,7 @@ pushclass (type, modify)
       else
        current_function_decl = NULL_TREE;
 
-      if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
-       declare_uninstantiated_type_level ();
-      else if (type != previous_class_type || current_class_depth > 1)
+      if (type != previous_class_type || current_class_depth > 1)
        {
          build_mi_matrix (type);
          push_class_decls (type);
@@ -4633,9 +4682,6 @@ pushclass (type, modify)
          unuse_fields (type);
        }
 
-      if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (type)))
-       overload_template_name (current_class_name, 0);
-
       for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags))
        {
          TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 1;
@@ -4686,8 +4732,6 @@ popclass (modify)
          TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
          tags = TREE_CHAIN (tags);
        }
-      if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type)))
-       undo_template_name_overload (current_class_name, 0);
     }
 
   /* Force clearing of IDENTIFIER_CLASS_VALUEs after a class definition,
@@ -4698,7 +4742,7 @@ popclass (modify)
      this really only frees the obstack used for these decls.
      That's why it had to be moved down here.  */
   if (modify)
-    pop_class_decls (current_class_type);
+    pop_class_decls ();
 
   current_class_depth--;
   current_class_type = *--current_class_stack;
@@ -4724,7 +4768,8 @@ push_nested_class (type, modify)
 {
   tree context;
 
-  if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type))
+  if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type)
+      || TREE_CODE (type) == TEMPLATE_TYPE_PARM)
     return;
   
   context = DECL_CONTEXT (TYPE_NAME (type));
@@ -4992,7 +5037,10 @@ instantiate_type (lhstype, rhs, complain)
                      }
                  }
              if (save_elem)
-               return save_elem;
+               {
+                 mark_used (save_elem);
+                 return save_elem;
+               }
            }
 
            /* No match found, look for a compatible function.  */
index 197e9c90e0f278103619984294aa3baab64154c3..51edcb00a07cd2a8962f0e99463ad35097583781 100644 (file)
@@ -90,18 +90,13 @@ DEFTREECODE (TEMPLATE_DECL, "template_decl", "d", 0)
    Use TYPE_FIELDS to find parmlist and index.  */
 DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", "t", 0)
 
+/* A type designated by 'typename T::t'. */
+DEFTREECODE (TYPENAME_TYPE, "typename_type", "t", 0)
+
 /* Index into a template parameter list.  This parameter must not be a
    type.  */
 DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 2)
 
-/* For uninstantiated parameterized types.
-        TYPE_VALUES     tree list:
-                TREE_PURPOSE    template decl
-                TREE_VALUE      parm vector
-                TREE_CHAIN      null
-   Other useful fields to be defined later.  */
-DEFTREECODE (UNINSTANTIATED_P_TYPE, "uninstantiated_p_type", "t", 0)
-
 /* A thunk is a stub function.
 
    Thunks are used to implement multiple inheritance:
@@ -118,3 +113,27 @@ DEFTREECODE (NAMESPACE_DECL, "namespace_decl", "d", 0)
 /* A using declaration.  DECL_INITIAL contains the specified scope.  
    This is not an alias, but is later expanded into multiple aliases.  */
 DEFTREECODE (USING_DECL, "using_decl", "d", 0)
+
+DEFTREECODE (LOOKUP_EXPR, "lookup_expr", "e", 2)
+DEFTREECODE (MODOP_EXPR, "modop_expr", "e", 3)
+DEFTREECODE (CAST_EXPR, "cast_expr", "e", 1)
+DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", "e", 1)
+DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", "e", 1)
+DEFTREECODE (ARROW_EXPR, "arrow_expr", "e", 1)
+DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", "e", 2)
+
+DEFTREECODE (EXPR_STMT, "expr_stmt", "e", 1)
+DEFTREECODE (COMPOUND_STMT, "compound_stmt", "e", 1)
+DEFTREECODE (DECL_STMT, "decl_stmt", "e", 4)
+DEFTREECODE (IF_STMT, "if_stmt", "e", 3)
+DEFTREECODE (FOR_STMT, "for_stmt", "e", 4)
+DEFTREECODE (WHILE_STMT, "while_stmt", "e", 2)
+DEFTREECODE (DO_STMT, "do_stmt", "e", 2)
+DEFTREECODE (RETURN_STMT, "return_stmt", "e", 1)
+DEFTREECODE (BREAK_STMT, "break_stmt", "e", 0)
+DEFTREECODE (CONTINUE_STMT, "continue_stmt", "e", 0)
+DEFTREECODE (SWITCH_STMT, "switch_stmt", "e", 2)
+DEFTREECODE (GOTO_STMT, "goto_stmt", "e", 1)
+
+DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", "e", 2)
+DEFTREECODE (CASE_LABEL, "case_label", "e", 2)
index 67e0de3a82ac91d65f1cb335ff03c127e6d2b5dc..83df18527311a2f035e11b2b22e58debad1135e7 100644 (file)
@@ -330,7 +330,7 @@ enum languages { lang_c, lang_cplusplus };
 #define TYPE_MAIN_DECL(NODE) (TYPE_NAME (NODE))
 
 #define IS_AGGR_TYPE(t)                (TYPE_LANG_FLAG_5 (t))
-#define IS_AGGR_TYPE_CODE(t)   (t == RECORD_TYPE || t == UNION_TYPE || t == UNINSTANTIATED_P_TYPE)
+#define IS_AGGR_TYPE_CODE(t)   (t == RECORD_TYPE || t == UNION_TYPE)
 #define IS_AGGR_TYPE_2(TYPE1,TYPE2) \
   (TREE_CODE (TYPE1) == TREE_CODE (TYPE2)      \
    && IS_AGGR_TYPE (TYPE1)&IS_AGGR_TYPE (TYPE2))
@@ -507,6 +507,8 @@ struct lang_type
   union tree_node *signature_pointer_to;
   union tree_node *signature_reference_to;
 
+  union tree_node *template_info;
+
   int linenum;
 };
 
@@ -834,9 +836,6 @@ struct lang_type
 
 /* Nonzero if a _DECL node requires us to output debug info for this class.  */
 #define CLASSTYPE_DEBUG_REQUESTED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.debug_requested)
-
-#define TYPE_INCOMPLETE(NODE) \
-  (TYPE_SIZE (NODE) == NULL_TREE && TREE_CODE (NODE) != TEMPLATE_TYPE_PARM)
 \f
 /* Additional macros for inheritance information.  */
 
@@ -956,6 +955,7 @@ struct lang_decl_flags
   tree access;
   tree context;
   tree memfunc_pointer_to;
+  tree template_info;
   struct binding_level *level;
 };
 
@@ -963,7 +963,6 @@ struct lang_decl
 {
   struct lang_decl_flags decl_flags;
 
-  struct template_info *template_info;
   tree main_decl_variant;
   struct pending_inline *pending_inline_info;
   tree chain;
@@ -1064,8 +1063,8 @@ struct lang_decl
    ? DECL_CLASS_CONTEXT (NODE) : DECL_CONTEXT (NODE))
 
 /* For a FUNCTION_DECL: the chain through which the next method
-   in the method chain is found.  We now use TREE_CHAIN to
-   link into the FIELD_DECL chain.  */
+   with the same name is found.  We now use TREE_CHAIN to
+   walk through the methods in order of declaration.  */
 #if 1
 #define DECL_CHAIN(NODE) (DECL_LANG_SPECIFIC(NODE)->chain)
 #else
@@ -1097,8 +1096,23 @@ struct lang_decl
    which this signature member function pointer was created.  */
 #define DECL_MEMFUNC_POINTING_TO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.memfunc_pointer_to)
 
-/* For a TEMPLATE_DECL: template-specific information.  */
-#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->template_info)
+/* For a VAR_DECL or FUNCTION_DECL: template-specific information.  */
+#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.template_info)
+#define CLASSTYPE_TEMPLATE_INFO(NODE) (TYPE_LANG_SPECIFIC(NODE)->template_info)
+#define TI_TEMPLATE(NODE) (TREE_PURPOSE (NODE))
+#define TI_ARGS(NODE) (TREE_VALUE (NODE))
+#define TI_USES_TEMPLATE_PARMS(NODE) TREE_LANG_FLAG_0 (NODE)
+#define DECL_TI_TEMPLATE(NODE)      TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE))
+#define DECL_TI_ARGS(NODE)          TI_ARGS (DECL_TEMPLATE_INFO (NODE))
+#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE))
+#define CLASSTYPE_TI_ARGS(NODE)     TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE))
+
+#define DECL_SAVED_TREE(NODE)          DECL_MEMFUNC_POINTER_TO (NODE)
+#define COMPOUND_STMT_NO_SCOPE(NODE)   TREE_LANG_FLAG_0 (NODE)
+#define NEW_EXPR_USE_GLOBAL(NODE)      TREE_LANG_FLAG_0 (NODE)
+#define DELETE_EXPR_USE_GLOBAL(NODE)   TREE_LANG_FLAG_0 (NODE)
+#define DELETE_EXPR_USE_VEC(NODE)      TREE_LANG_FLAG_1 (NODE)
+#define LOOKUP_EXPR_GLOBAL(NODE)       TREE_LANG_FLAG_0 (NODE)
 
 /* Nonzero in INT_CST means that this int is negative by dint of
    using a twos-complement negated operand.  */
@@ -1321,13 +1335,23 @@ extern int flag_new_for_scope;
 #define SET_DECL_REFERENCE_SLOT(NODE,VAL) ((NODE)->decl.arguments=VAL)
 
 /* Accessor macros for C++ template decl nodes.  */
-#define DECL_TEMPLATE_IS_CLASS(NODE)    (DECL_RESULT(NODE) == NULL_TREE)
 #define DECL_TEMPLATE_PARMS(NODE)       DECL_ARGUMENTS(NODE)
 /* For class templates.  */
 #define DECL_TEMPLATE_MEMBERS(NODE)     DECL_SIZE(NODE)
 /* For function, method, class-data templates.  */
 #define DECL_TEMPLATE_RESULT(NODE)      DECL_RESULT(NODE)
 #define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
+#define DECL_TEMPLATE_INJECT(NODE)     DECL_INITIAL(NODE)
+
+#define DECL_FUNCTION_TEMPLATE_P(NODE)  \
+  (TREE_CODE (NODE) == TEMPLATE_DECL \
+   && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
+
+#define PRIMARY_TEMPLATE_P(NODE) \
+  (TREE_TYPE (DECL_TEMPLATE_PARMS (NODE)) == (NODE))
+
+#define CLASSTYPE_TEMPLATE_LEVEL(NODE) \
+  (TREE_INT_CST_HIGH (TREE_PURPOSE (CLASSTYPE_TI_TEMPLATE (NODE))))
 
 /* Indicates whether or not (and how) a template was expanded for this
    FUNCTION_DECL or VAR_DECL.
@@ -1456,7 +1480,9 @@ extern tree default_function_type;
 extern tree vtable_entry_type;
 extern tree sigtable_entry_type;
 extern tree __t_desc_type_node;
+#if 0
 extern tree __tp_desc_type_node;
+#endif
 extern tree __access_mode_type_node;
 extern tree __bltn_desc_type_node, __user_desc_type_node;
 extern tree __class_desc_type_node, __attr_desc_type_node;
@@ -1471,7 +1497,6 @@ extern tree delta_identifier;
 extern tree delta2_identifier;
 extern tree pfn_or_delta2_identifier;
 extern tree tag_identifier;
-extern tree vb_off_identifier;
 extern tree vt_off_identifier;
 
 /* A node that is a list (length 1) of error_mark_nodes.  */
@@ -1497,37 +1522,22 @@ extern tree integer_two_node, integer_three_node;
 extern tree boolean_type_node, boolean_true_node, boolean_false_node;
 
 /* in pt.c  */
-/* PARM_VEC is a vector of template parameters, either IDENTIFIER_NODEs or
-   PARM_DECLs.  BINDINGS, if non-null, is a vector of bindings for those
-   parameters.  */
-struct template_info {
-  /* Vector of template parameters, either PARM_DECLs or IDENTIFIER_NODEs.  */
-  tree parm_vec;
-  /* If non-null, a vector of bindings for the template parms.  */
-  tree bindings;
-
-  /* Text of template, and length.  */
-  char *text;
-  int length;
-  /* Where it came from.  */
-  char *filename;
-  int lineno;
-
-  /* What kind of aggregate -- struct, class, or null.  */
-  tree aggr;
-};
-extern int processing_template_decl, processing_template_defn;
+
+extern tree current_template_parms;
+extern HOST_WIDE_INT processing_template_decl;
 
 /* The template currently being instantiated, and where the instantiation
    was triggered.  */
 struct tinst_level
 {
-  tree classname;
+  tree decl;
   int line;
   char *file;
   struct tinst_level *next;
 };
 
+extern int minimal_parse_mode;
+
 /* in class.c */
 extern tree current_class_name;
 extern tree current_class_type;
@@ -1545,7 +1555,6 @@ extern tree current_class_name, current_class_type, current_class_decl, C_C_D;
 extern tree global_base_init_list;
 extern tree current_base_init_list, current_member_init_list;
 
-extern int current_function_assigns_this;
 extern int current_function_just_assigned_this;
 extern int current_function_parms_stored;
 \f
@@ -1735,9 +1744,6 @@ extern tree access_default_virtual_node; /* 4 */
 extern tree access_public_virtual_node; /* 5 */
 extern tree access_private_virtual_node; /* 6 */
 
-/* in lex.c  */
-extern tree current_unit_name, current_unit_language;
-
 /* Things for handling inline functions.  */
 
 struct pending_inline
@@ -1751,7 +1757,6 @@ struct pending_inline
 
   char *buf;                   /* pointer to character stream */
   int len;                     /* length of stream */
-  tree parm_vec, bindings;     /* in case this is derived from a template */
   unsigned int can_free : 1;   /* free this after we're done with it? */
   unsigned int deja_vu : 1;    /* set iff we don't want to see it again.  */
   unsigned int interface : 2;  /* 0=interface 1=unknown 2=implementation */
@@ -1805,6 +1810,10 @@ extern int flag_implicit_templates;
 
 extern int flag_weak;
 
+/* Nonzero if we're done parsing and into end-of-file activities.  */
+
+extern int at_eof;
+
 enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
 
 extern tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */
@@ -1897,15 +1906,14 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
 #define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
 
 /* These macros are for accessing the fields of TEMPLATE...PARM nodes.  */
-#define TEMPLATE_TYPE_TPARMLIST(NODE) TREE_PURPOSE (TYPE_FIELDS (NODE))
-#define TEMPLATE_TYPE_IDX(NODE) TREE_INT_CST_LOW (TREE_VALUE (TYPE_FIELDS (NODE)))
-#define TEMPLATE_TYPE_SET_INFO(NODE,P,I) \
-  (TYPE_FIELDS (NODE) = build_tree_list (P, build_int_2 (I, 0)))
-#define TEMPLATE_CONST_TPARMLIST(NODE) (*(tree*)&TREE_INT_CST_LOW(NODE))
-#define TEMPLATE_CONST_IDX(NODE) (TREE_INT_CST_HIGH(NODE))
-#define TEMPLATE_CONST_SET_INFO(NODE,P,I) \
-  (TEMPLATE_CONST_TPARMLIST (NODE) = saved_parmlist, \
-   TEMPLATE_CONST_IDX (NODE) = I)
+#define TEMPLATE_TYPE_IDX(NODE) TREE_INT_CST_LOW (TYPE_FIELDS (NODE))
+#define TEMPLATE_TYPE_LEVEL(NODE) TREE_INT_CST_HIGH (TYPE_FIELDS (NODE))
+#define TEMPLATE_TYPE_SET_INFO(NODE,I,L) \
+  (TYPE_FIELDS (NODE) = build_int_2 (I, L))
+#define TEMPLATE_CONST_IDX(NODE) (TREE_INT_CST_LOW(NODE))
+#define TEMPLATE_CONST_LEVEL(NODE) (TREE_INT_CST_HIGH(NODE))
+#define TEMPLATE_CONST_SET_INFO(NODE,I,L) \
+  (TEMPLATE_CONST_IDX (NODE) = I, TEMPLATE_CONST_LEVEL (NODE) = L)
 
 /* in lex.c  */
 /* Indexed by TREE_CODE, these tables give C-looking names to
@@ -1922,6 +1930,8 @@ extern void unsigned_conversion_warning           PROTO((tree, tree));
 extern struct candidate *ansi_c_bullshit;
 
 extern int rank_for_overload                   PROTO((struct candidate *, struct candidate *));
+extern int can_convert                         PROTO((tree, tree));
+extern int can_convert_arg                     PROTO((tree, tree, tree));
 extern void compute_conversion_costs           PROTO((tree, tree, struct candidate *, int));
 extern int get_arglist_len_in_bytes            PROTO((tree));
 extern tree build_vfield_ref                   PROTO((tree, tree));
@@ -1943,6 +1953,8 @@ extern void add_method                            PROTO((tree, tree *, tree));
 extern tree get_vfield_offset                  PROTO((tree));
 extern void duplicate_tag_error                        PROTO((tree));
 extern tree finish_struct                      PROTO((tree, tree, tree, int));
+extern tree finish_struct_1                    PROTO((tree, tree, int));
+extern tree finish_struct_methods              PROTO((tree, tree, int));
 extern int resolves_to_fixed_type_p            PROTO((tree, int *));
 extern void init_class_processing              PROTO((void));
 extern void pushclass                          PROTO((tree, int));
@@ -1980,8 +1992,6 @@ extern int kept_level_p                           PROTO((void));
 extern void declare_parm_level                 PROTO((void));
 extern void declare_implicit_exception         PROTO((void));
 extern int have_exceptions_p                   PROTO((void));
-extern void declare_uninstantiated_type_level  PROTO((void));
-extern int uninstantiated_type_level_p         PROTO((void));
 extern void declare_pseudo_global_level                PROTO((void));
 extern int pseudo_global_level_p               PROTO((void));
 extern void pushlevel                          PROTO((int));
@@ -2008,7 +2018,7 @@ extern tree pushdecl_top_level                    PROTO((tree));
 extern void push_class_level_binding           PROTO((tree, tree));
 extern void push_overloaded_decl_top_level     PROTO((tree, int));
 extern tree pushdecl_class_level               PROTO((tree));
-extern tree pushdecl_nonclass_level            PROTO((tree));
+extern void pushdecl_nonclass_level            PROTO((tree));
 extern int overloaded_globals_p                        PROTO((tree));
 extern tree push_overloaded_decl               PROTO((tree, int));
 extern tree implicitly_declare                 PROTO((tree));
@@ -2024,6 +2034,7 @@ extern tree lookup_name                           PROTO((tree, int));
 extern tree lookup_namespace_name              PROTO((tree, tree));
 extern tree lookup_name_current_level          PROTO((tree));
 extern void init_decl_processing               PROTO((void));
+extern int init_type_desc                      PROTO((void));
 /* skipped define_function */
 extern void shadow_tag                         PROTO((tree));
 extern int grok_ctor_properties                        PROTO((tree, tree));
@@ -2056,6 +2067,10 @@ extern void finish_stmt                          PROTO((void));
 extern void pop_implicit_try_blocks            PROTO((tree));
 extern void push_exception_cleanup             PROTO((tree));
 extern void revert_static_member_fn            PROTO((tree *, tree *, tree *));
+extern int id_in_current_class                 PROTO((tree));
+extern void push_cp_function_context           PROTO((tree));
+extern void pop_cp_function_context            PROTO((tree));
+extern void grok_op_properties                 PROTO((tree, int, int));
 
 /* in decl2.c */
 extern int lang_decode_option                  PROTO((char *));
@@ -2064,11 +2079,12 @@ extern void grokclassfn                         PROTO((tree, tree, tree, enum overload_flags, tree));
 extern tree grok_alignof                       PROTO((tree));
 extern tree grok_array_decl                    PROTO((tree, tree));
 extern tree delete_sanity                      PROTO((tree, tree, int, int));
-extern tree check_classfn                      PROTO((tree, tree, tree));
+extern tree check_classfn                      PROTO((tree, tree));
 extern tree grokfield                          PROTO((tree, tree, tree, tree, tree, tree));
 extern tree grokbitfield                       PROTO((tree, tree, tree));
 extern tree groktypefield                      PROTO((tree, tree));
 extern tree grokoptypename                     PROTO((tree, tree));
+extern int copy_assignment_arg_p               PROTO((tree, int));
 extern void cplus_decl_attributes              PROTO((tree, tree, tree)); 
 extern tree constructor_name_full              PROTO((tree));
 extern tree constructor_name                   PROTO((tree));
@@ -2082,6 +2098,7 @@ extern tree finish_table                  PROTO((tree, tree, tree, int));
 extern void finish_builtin_type                        PROTO((tree, char *, tree *, int, tree));
 extern tree coerce_new_type                    PROTO((tree));
 extern tree coerce_delete_type                 PROTO((tree));
+extern void import_export_vtable               PROTO((tree, tree, int));
 extern void walk_vtables                       PROTO((void (*)(), void (*)()));
 extern void walk_sigtables                     PROTO((void (*)(), void (*)()));
 extern void finish_file                                PROTO((void));
@@ -2089,6 +2106,7 @@ extern void warn_if_unknown_interface             PROTO((tree));
 extern tree grok_x_components                  PROTO((tree, tree));
 extern tree reparse_absdcl_as_expr             PROTO((tree, tree));
 extern tree reparse_absdcl_as_casts            PROTO((tree, tree));
+extern tree build_expr_from_tree               PROTO((tree));
 extern tree reparse_decl_as_expr               PROTO((tree, tree));
 extern tree finish_decl_parsing                        PROTO((tree));
 extern tree lookup_name_nonclass               PROTO((tree));
@@ -2098,6 +2116,7 @@ extern tree do_class_using_decl                   PROTO((tree));
 extern tree current_namespace_id               PROTO((tree));
 extern tree get_namespace_id                   PROTO((void));
 extern void check_default_args                 PROTO((tree));
+extern void mark_used                          PROTO((tree));
 
 /* in except.c */
 extern tree protect_list;
@@ -2118,7 +2137,6 @@ extern tree build_throw                           PROTO((tree));
 extern void init_exception_processing          PROTO((void));
 extern void expand_builtin_throw               PROTO((void));
 extern void expand_start_eh_spec               PROTO((void));
-extern void expand_end_eh_spec                 PROTO((tree));
 extern tree build_cleanup                      PROTO((tree));
 extern tree start_anon_func                    PROTO((void));
 
@@ -2128,8 +2146,11 @@ extern void init_cplus_expand                    PROTO((void));
 extern void fixup_result_decl                  PROTO((tree, struct rtx_def *));
 extern tree unsave_expr_now                    PROTO((tree));
 
+/* in repo.c */
+extern void init_repo                          PROTO((char*));
+extern void finish_repo                                PROTO((void));
+
 /* in rtti.c */
-extern tree build_headof                       PROTO((tree));
 extern tree build_classof                      PROTO((tree));
 extern tree build_t_desc                       PROTO((tree, int));
 extern tree build_i_desc                       PROTO((tree));
@@ -2146,6 +2167,7 @@ extern void do_member_init                        PROTO((tree, tree, tree));
 extern void expand_member_init                 PROTO((tree, tree, tree));
 extern void expand_aggr_init                   PROTO((tree, tree, int, int));
 extern int is_aggr_typedef                     PROTO((tree, int));
+extern int is_aggr_type                                PROTO((tree, int));
 extern tree get_aggr_from_typedef              PROTO((tree, int));
 extern tree get_type_value                     PROTO((tree));
 extern tree build_member_call                  PROTO((tree, tree, tree));
@@ -2156,7 +2178,7 @@ extern tree decl_constant_value                   PROTO((tree));
 extern int is_friend_type                      PROTO((tree, tree));
 extern int is_friend                           PROTO((tree, tree));
 extern void make_friend_class                  PROTO((tree, tree));
-extern tree do_friend                          PROTO((tree, tree, tree, tree, enum overload_flags, tree));
+extern tree do_friend                          PROTO((tree, tree, tree, tree, enum overload_flags, tree, int));
 extern void embrace_waiting_friends            PROTO((tree));
 extern tree build_builtin_call                 PROTO((tree, tree, tree));
 extern tree build_new                          PROTO((tree, tree, tree, int));
@@ -2164,7 +2186,7 @@ extern tree expand_vec_init                       PROTO((tree, tree, tree, tree, int));
 extern tree build_x_delete                     PROTO((tree, tree, int, tree));
 extern tree build_delete                       PROTO((tree, tree, tree, int, int));
 extern tree build_vbase_delete                 PROTO((tree, tree));
-extern tree build_vec_delete                   PROTO((tree, tree, tree, tree, tree, int));
+extern tree build_vec_delete                   PROTO((tree, tree, tree, tree, int));
 
 /* in input.c */
 
@@ -2198,7 +2220,8 @@ extern int check_newline                  PROTO((void));
 extern void dont_see_typename                  PROTO((void));
 extern int identifier_type                     PROTO((tree));
 extern void see_typename                       PROTO((void));
-extern tree do_identifier                      PROTO((tree));
+extern tree do_identifier                      PROTO((tree, int));
+extern tree do_scoped_id                       PROTO((tree, int));
 extern tree identifier_typedecl_value          PROTO((tree));
 extern int real_yylex                          PROTO((void));
 extern tree build_lang_decl                    PROTO((enum tree_code, tree, tree));
@@ -2223,7 +2246,7 @@ extern void cp_sprintf                            ();
 
 /* in error.c */
 extern void init_error                         PROTO((void));
-extern char *fndecl_as_string                  PROTO((tree, tree, int));
+extern char *fndecl_as_string                  PROTO((tree, int));
 extern char *type_as_string                    PROTO((tree, int));
 extern char *args_as_string                    PROTO((tree, int));
 extern char *decl_as_string                    PROTO((tree, int));
@@ -2251,36 +2274,37 @@ extern void declare_overloaded                  PROTO((tree));
 extern int is_overloaded                       PROTO((tree));
 #endif
 extern tree build_opfncall                     PROTO((enum tree_code, int, tree, tree, tree));
-extern tree hack_identifier                    PROTO((tree, tree, int));
+extern tree hack_identifier                    PROTO((tree, tree));
 extern tree build_component_type_expr          PROTO((tree, tree, tree, int));
+extern void synthesize_method                  PROTO((tree));
 
 /* in pt.c */
 extern tree tsubst                             PROTO ((tree, tree*, int, tree));
+extern tree tsubst_expr                                PROTO ((tree, tree*, int, tree));
+extern tree tsubst_copy                                PROTO ((tree, tree*, int, tree));
+extern tree tsubst_chain                       PROTO((tree, tree));
 extern void begin_template_parm_list           PROTO((void));
 extern tree process_template_parm              PROTO((tree, tree));
 extern tree end_template_parm_list             PROTO((tree));
-extern void end_template_decl                  PROTO((tree, tree, tree, int));
+extern void end_template_decl                  PROTO((void));
 extern tree lookup_template_class              PROTO((tree, tree, tree));
-extern void push_template_decls                        PROTO((tree, tree, int));
-extern void pop_template_decls                 PROTO((tree, tree, int));
 extern int uses_template_parms                 PROTO((tree));
-extern void instantiate_member_templates       PROTO((tree));
-extern tree instantiate_class_template         PROTO((tree, int));
+extern tree instantiate_class_template         PROTO((tree));
 extern tree instantiate_template               PROTO((tree, tree *));
-extern void undo_template_name_overload                PROTO((tree, int));
-extern void overload_template_name             PROTO((tree, int));
-extern void end_template_instantiation         PROTO((tree));
-extern void reinit_parse_for_template          PROTO((int, tree, tree));
+extern void overload_template_name             PROTO((tree));
 extern int type_unification                    PROTO((tree, tree *, tree, tree, int *, int));
-extern int do_pending_expansions               PROTO((void));
-extern void do_pending_templates               PROTO((void));
 struct tinst_level *tinst_for_decl             PROTO((void));
+extern void mark_decl_instantiated             PROTO((tree, int));
+extern void mark_class_instantiated            PROTO((tree, int));
 extern void do_function_instantiation          PROTO((tree, tree, tree));
 extern void do_type_instantiation              PROTO((tree, tree));
-extern tree create_nested_upt                  PROTO((tree, tree));
+extern tree make_typename_type                 PROTO((tree, tree));
+extern tree instantiate_decl                   PROTO((tree));
+extern tree classtype_mangled_name             PROTO((tree));
+extern tree lookup_nested_type_by_name         PROTO((tree, tree));
+extern tree do_poplevel                                PROTO((void));
 
 /* in search.c */
-extern tree make_memoized_table_entry          PROTO((tree, tree, int));
 extern void push_memoized_context              PROTO((tree, int));
 extern void pop_memoized_context               PROTO((int));
 extern tree get_binfo                          PROTO((tree, tree, int));
@@ -2290,8 +2314,6 @@ extern tree lookup_field                  PROTO((tree, tree, int, int));
 extern tree lookup_nested_field                        PROTO((tree, int));
 extern tree lookup_fnfields                    PROTO((tree, tree, int));
 extern tree lookup_nested_tag                  PROTO((tree, tree));
-extern HOST_WIDE_INT breadth_first_search      PROTO((tree, int (*)(), int (*)()));
-extern int tree_has_any_destructor_p           PROTO((tree, int));
 extern tree get_matching_virtual               PROTO((tree, tree, int));
 extern tree get_abstract_virtuals              PROTO((tree));
 extern tree get_baselinks                      PROTO((tree, tree, tree));
@@ -2307,7 +2329,7 @@ extern void add_mi_virtuals                       PROTO((int, tree));
 extern void report_ambiguous_mi_virtuals       PROTO((int, tree));
 extern void note_debug_info_needed             PROTO((tree));
 extern void push_class_decls                   PROTO((tree));
-extern void pop_class_decls                    PROTO((tree));
+extern void pop_class_decls                    PROTO(());
 extern void unuse_fields                       PROTO((tree));
 extern void unmark_finished_struct             PROTO((tree));
 extern void print_search_statistics            PROTO((void));
@@ -2323,16 +2345,22 @@ extern tree build_signature_pointer_constructor PROTO((tree, tree));
 extern tree build_signature_method_call                PROTO((tree, tree, tree, tree));
 extern tree build_optr_ref                     PROTO((tree));
 extern tree build_sptr_ref                     PROTO((tree));
+extern void append_signature_fields            PROTO((tree));
 
 /* in spew.c */
 extern void init_spew                          PROTO((void));
+extern int peek_yylex                          PROTO((void));
 extern int yylex                               PROTO((void));
 extern tree arbitrate_lookup                   PROTO((tree, tree, tree));
 
 /* in tree.c */
+extern int real_lvalue_p                       PROTO((tree));
+extern tree build_min                          PVPROTO((enum tree_code, tree, ...));
+extern tree build_min_nt                       PVPROTO((enum tree_code, ...));
+extern tree min_tree_cons                      PROTO((tree, tree, tree));
 extern int lvalue_p                            PROTO((tree));
 extern int lvalue_or_else                      PROTO((tree, char *));
-extern tree build_cplus_new                    PROTO((tree, tree, int));
+extern tree build_cplus_new                    PROTO((tree, tree));
 extern tree break_out_cleanups                 PROTO((tree));
 extern tree break_out_calls                    PROTO((tree));
 extern tree build_cplus_method_type            PROTO((tree, tree, tree));
@@ -2373,17 +2401,19 @@ extern tree break_out_target_exprs              PROTO((tree));
 extern tree build_unsave_expr                  PROTO((tree));
 extern tree unsave_expr                                PROTO((tree));
 extern int cp_expand_decl_cleanup              PROTO((tree, tree));
+extern tree get_type_decl                      PROTO((tree));
 
 /* in typeck.c */
 extern tree condition_conversion               PROTO((tree));
 extern tree target_type                                PROTO((tree));
 extern tree require_complete_type              PROTO((tree));
+extern tree complete_type                      PROTO((tree));
 extern int type_unknown_p                      PROTO((tree));
 extern int fntype_p                            PROTO((tree));
 extern tree require_instantiated_type          PROTO((tree, tree, tree));
 extern tree commonparms                                PROTO((tree, tree));
 extern tree common_type                                PROTO((tree, tree));
-extern int compexcepttypes                     PROTO((tree, tree, int));
+extern int compexcepttypes                     PROTO((tree, tree));
 extern int comptypes                           PROTO((tree, tree, int));
 extern int comp_target_types                   PROTO((tree, tree, int));
 extern tree common_base_types                  PROTO((tree, tree));
@@ -2393,6 +2423,7 @@ extern int self_promoting_args_p          PROTO((tree));
 extern tree unsigned_type                      PROTO((tree));
 extern tree signed_type                                PROTO((tree));
 extern tree signed_or_unsigned_type            PROTO((int, tree));
+extern tree expr_sizeof                                PROTO((tree));
 extern tree c_sizeof                           PROTO((tree));
 extern tree c_sizeof_nowarn                    PROTO((tree));
 extern tree c_alignof                          PROTO((tree));
@@ -2426,6 +2457,7 @@ extern tree build_static_cast                     PROTO((tree, tree));
 extern tree build_reinterpret_cast             PROTO((tree, tree));
 extern tree build_const_cast                   PROTO((tree, tree));
 extern tree build_c_cast                       PROTO((tree, tree, int));
+extern tree build_x_modify_expr                        PROTO((tree, enum tree_code, tree));
 extern tree build_modify_expr                  PROTO((tree, enum tree_code, tree));
 extern int language_lvalue_valid               PROTO((tree));
 extern void warn_for_assignment                        PROTO((char *, char *, char *, tree, int, int));
@@ -2442,6 +2474,7 @@ extern tree binfo_or_else                 PROTO((tree, tree));
 extern void error_with_aggr_type               (); /* PROTO((tree, char *, HOST_WIDE_INT)); */
 extern void readonly_error                     PROTO((tree, char *, int));
 extern void abstract_virtuals_error            PROTO((tree, tree));
+extern void signature_error                    PROTO((tree, tree));
 extern void incomplete_type_error              PROTO((tree, tree));
 extern void my_friendly_abort                  PROTO((int));
 extern void my_friendly_assert                 PROTO((int, int));
@@ -2459,7 +2492,7 @@ extern void GNU_xref_begin                        PROTO((char *));
 extern void GNU_xref_end                       PROTO((int));
 extern void GNU_xref_file                      PROTO((char *));
 extern void GNU_xref_start_scope               PROTO((HOST_WIDE_INT));
-extern void GNU_xref_end_scope                 PROTO((HOST_WIDE_INT, HOST_WIDE_INT, int, int, int));
+extern void GNU_xref_end_scope                 PROTO((HOST_WIDE_INT, HOST_WIDE_INT, int, int));
 extern void GNU_xref_ref                       PROTO((tree, char *));
 extern void GNU_xref_decl                      PROTO((tree, tree));
 extern void GNU_xref_call                      PROTO((tree, char *));
index b45823d0260994f5e87636aaecba1c33390a13f9..b537fdfc1a5bd81e41aaa4abfcefb66ebaa76866 100644 (file)
@@ -356,7 +356,7 @@ build_up_reference (type, arg, flags, checkconst)
         initializing until now: it needs to initialize a temporary.  */
       if (TREE_HAS_CONSTRUCTOR (targ))
        {
-         tree temp = build_cplus_new (argtype, TREE_OPERAND (targ, 0), 1);
+         tree temp = build_cplus_new (argtype, TREE_OPERAND (targ, 0));
          TREE_HAS_CONSTRUCTOR (targ) = 0;
          return build_up_reference (type, temp, flags, 1);
        }
@@ -586,7 +586,7 @@ build_up_reference (type, arg, flags, checkconst)
 
       if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype))
        {
-         temp = build_cplus_new (argtype, targ, 1);
+         temp = build_cplus_new (argtype, targ);
          rval = build1 (ADDR_EXPR, type, temp);
          goto done;
        }
@@ -809,7 +809,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
              if (init == error_mark_node)
                return error_mark_node;
 
-             rval = build_cplus_new (type, init, 1);
+             rval = build_cplus_new (type, init);
              rval = build_up_reference (reftype, rval, flags, 1);
            }
          rval_as_ctor = rval;
@@ -888,7 +888,11 @@ convert_to_aggr (type, expr, msgp, protect)
   tree basetype = type;
   tree name = TYPE_IDENTIFIER (basetype);
   tree function, fndecl, fntype, parmtypes, parmlist, result;
-  tree method_name, access;
+#if 0
+  /* See code below that used this.  */
+  tree method_name;
+#endif
+  tree access;
   int can_be_private, can_be_protected;
 
   if (! TYPE_HAS_CONSTRUCTOR (basetype))
@@ -1229,7 +1233,6 @@ cp_convert (type, expr, convtype, flags)
   if (INTEGRAL_CODE_P (code))
     {
       tree intype = TREE_TYPE (e);
-      enum tree_code form = TREE_CODE (intype);
       /* enum = enum, enum = int, enum = float are all errors. */
       if (flag_int_enum_equivalence == 0
          && TREE_CODE (type) == ENUMERAL_TYPE
@@ -1328,7 +1331,7 @@ cp_convert (type, expr, convtype, flags)
          return conversion;
        }
 
-      if (TYPE_HAS_CONSTRUCTOR (type))
+      if (TYPE_HAS_CONSTRUCTOR (complete_type (type)))
        ctor = build_method_call (NULL_TREE, constructor_name_full (type),
                                  build_tree_list (NULL_TREE, e),
                                  TYPE_BINFO (type),
@@ -1357,7 +1360,7 @@ cp_convert (type, expr, convtype, flags)
        return conversion;
       else if (ctor)
        {
-         ctor = build_cplus_new (type, ctor, 0);
+         ctor = build_cplus_new (type, ctor);
          return ctor;
        }
     }
index ee66250cdb2159bc54473a2fc003476c9bb80755..2dd92e5661091661b7b824b4bdb5f8844bd42f7a 100644 (file)
@@ -58,7 +58,7 @@ extern tree static_ctors, static_dtors;
 /* Obstack used for remembering local class declarations (like
    enums and static (const) members.  */
 #include "stack.h"
-static struct obstack decl_obstack;
+struct obstack decl_obstack;
 static struct stack_level *decl_stack;
 
 #ifndef CHAR_TYPE_SIZE
@@ -126,7 +126,6 @@ static struct stack_level *decl_stack;
 static tree grokparms                          PROTO((tree, int));
 static tree lookup_nested_type                 PROTO((tree, tree));
 static char *redeclaration_error_message       PROTO((tree, tree));
-static void grok_op_properties                 PROTO((tree, int, int));
 extern void* push_eh_context                   PROTO(());
 extern void pop_eh_context                     PROTO((void *));
 
@@ -223,15 +222,8 @@ tree int_ftype_int, long_ftype_long;
 tree float_ftype_float;
 tree ldouble_ftype_ldouble;
 
-/* Function type `void (void *, void *, int)' and similar ones.  */
-
-tree void_ftype_ptr_ptr_int, int_ftype_ptr_ptr_int, void_ftype_ptr_int_int;
-
-/* Function type `char *(char *, char *)' and similar ones */
-tree string_ftype_ptr_ptr, int_ftype_string_string;
-
 /* Function type `int (const void *, const void *, size_t)' */
-tree int_ftype_cptr_cptr_sizet;
+static tree int_ftype_cptr_cptr_sizet;
 
 /* C++ extensions */
 tree vtable_entry_type;
@@ -242,7 +234,10 @@ tree __baselist_desc_type_node;
 tree __i_desc_type_node, __m_desc_type_node;
 tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type;
 #endif
-tree __t_desc_type_node, __tp_desc_type_node;
+tree __t_desc_type_node;
+#if 0
+tree __tp_desc_type_node;
+#endif
 tree __access_mode_type_node;
 tree __bltn_desc_type_node, __user_desc_type_node, __class_desc_type_node;
 tree __ptr_desc_type_node, __attr_desc_type_node, __func_desc_type_node;
@@ -302,7 +297,7 @@ tree this_identifier, in_charge_identifier;
 /* Used in pointer to member functions, in vtables, and in sigtables. */
 tree pfn_identifier, index_identifier, delta_identifier, delta2_identifier;
 tree pfn_or_delta2_identifier, tag_identifier;
-tree vb_off_identifier, vt_off_identifier;
+tree vt_off_identifier;
 
 /* A list (chain of TREE_LIST nodes) of named label uses.
    The TREE_PURPOSE field is the list of variables defined
@@ -444,7 +439,7 @@ extern tree *current_lang_base, *current_lang_stack;
 /* Set to 0 at beginning of a constructor, set to 1
    if that function does an allocation before referencing its
    instance variable.  */
-int current_function_assigns_this;
+static int current_function_assigns_this;
 int current_function_just_assigned_this;
 
 /* Set to 0 at beginning of a function.  Set non-zero when
@@ -565,15 +560,9 @@ struct binding_level
     unsigned more_cleanups_ok : 1;
     unsigned have_cleanups : 1;
 
-    /* Nonzero if we should accept any name as an identifier in
-       this scope.  This happens in some template definitions.  */
-    unsigned accept_any : 1;
-
-    /* Nonzero if this level is for completing a template class definition
-       inside a binding level that temporarily binds the parameters.  This
-       means that definitions here should not be popped off when unwinding
-       this binding level.  (Not actually implemented this way,
-       unfortunately.)  */
+    /* Nonzero if this level is for storing the decls for template
+       parameters and generic decls; these decls will be discarded and
+       replaced with a TEMPLATE_DECL.  */
     unsigned pseudo_global : 1;
 
     /* This is set for a namespace binding level.  */
@@ -583,7 +572,7 @@ struct binding_level
        worry about ambiguous (traditional or ANSI) scope rules. */
     unsigned is_for_scope : 1;
 
-    /* One bit left for this word.  */
+    /* Two bits left for this word.  */
 
 #if defined(DEBUG_CP_BINDING_LEVELS)
     /* Binding depth at which this level began.  */
@@ -742,13 +731,7 @@ suspend_binding_level ()
   is_class_level = 0;
 #endif /* defined(DEBUG_CP_BINDING_LEVELS) */
   {
-    register struct binding_level *level = current_binding_level;
     current_binding_level = current_binding_level->level_chain;
-#if 0 /* defined(DEBUG_CP_BINDING_LEVELS) */
-    if (level->binding_depth != binding_depth)
-      abort ();
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
-
     class_binding_level = current_binding_level;
     if (class_binding_level->parm_flag != 2)
       class_binding_level = 0;
@@ -826,6 +809,8 @@ toplevel_bindings_p ()
     {
       if (b == global_binding_level)
        return 1;
+      if (b->pseudo_global)
+       return 1;
       if (! b->namespace_p)
        return 0;
       b=b->level_chain;
@@ -866,18 +851,6 @@ declare_parm_level ()
   current_binding_level->parm_flag = 1;
 }
 
-void
-declare_uninstantiated_type_level ()
-{
-  current_binding_level->accept_any = 1;
-}
-
-int
-uninstantiated_type_level_p ()
-{
-  return current_binding_level->accept_any;
-}
-
 void
 declare_pseudo_global_level ()
 {
@@ -941,7 +914,7 @@ pushlevel (tag_transparent)
   keep_next_level_flag = 0;
 }
 
-int
+void
 note_level_for_for ()
 {
   current_binding_level->is_for_scope = 1;
@@ -994,7 +967,6 @@ poplevel (keep, reverse, functionbody)
      Put it into forward order, just for cleanliness.  */
   tree decls;
   int tmp = functionbody;
-  int implicit_try_block = current_binding_level->parm_flag == 3;
   int real_functionbody = current_binding_level->keep == 2
     ? ((functionbody = 0), tmp) : functionbody;
   tree tags = functionbody >= 0 ? current_binding_level->tags : 0;
@@ -1006,8 +978,7 @@ poplevel (keep, reverse, functionbody)
   GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
                      (HOST_WIDE_INT) current_binding_level->level_chain,
                      current_binding_level->parm_flag,
-                     current_binding_level->keep,
-                     current_binding_level->tag_transparent);
+                     current_binding_level->keep);
 
   if (current_binding_level->keep == 1)
     keep = 1;
@@ -1437,8 +1408,7 @@ poplevel_class (force)
   GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
                      (HOST_WIDE_INT) class_binding_level->level_chain,
                      class_binding_level->parm_flag,
-                     class_binding_level->keep,
-                     class_binding_level->tag_transparent);
+                     class_binding_level->keep);
 
   if (class_binding_level->parm_flag != 2)
     class_binding_level = (struct binding_level *)0;
@@ -1455,8 +1425,8 @@ poplevel_class (force)
 }
 \f
 /* For debugging.  */
-int no_print_functions = 0;
-int no_print_builtins = 0;
+static int no_print_functions = 0;
+static int no_print_builtins = 0;
 
 void
 print_binding_level (lvl)
@@ -1760,10 +1730,12 @@ struct saved_scope {
   tree class_name, class_type, function_decl;
   tree base_init_list, member_init_list;
   struct binding_level *class_bindings;
-  tree previous_class_type;
+  tree previous_class_type, previous_class_values;
   tree *lang_base, *lang_stack, lang_name;
   int lang_stacksize;
   tree named_labels;
+  int minimal_parse_mode;
+  tree last_function_parms;
 };
 static struct saved_scope *current_saved_scope;
 extern tree prev_class_type;
@@ -1811,12 +1783,13 @@ store_bindings (names, old_bindings)
 }
 
 void
-push_to_top_level ()
+maybe_push_to_top_level (pseudo)
+     int pseudo;
 {
   extern int current_lang_stacksize;
   struct saved_scope *s =
     (struct saved_scope *) xmalloc (sizeof (struct saved_scope));
-  struct binding_level *b = current_binding_level;
+  struct binding_level *b = inner_binding_level;
   tree old_bindings = NULL_TREE;
 
   /* Have to include global_binding_level, because class-level decls
@@ -1825,8 +1798,8 @@ push_to_top_level ()
     {
       tree t;
 
-      if (b == global_binding_level)
-       continue;
+      if (b == global_binding_level || (pseudo && b->pseudo_global))
+       break;
 
       old_bindings = store_bindings (b->names, old_bindings);
       /* We also need to check class_shadowed to save class-level type
@@ -1847,7 +1820,7 @@ push_to_top_level ()
     }
 
   s->old_binding_level = current_binding_level;
-  current_binding_level = global_binding_level;
+  current_binding_level = b;
 
   s->class_name = current_class_name;
   s->class_type = current_class_type;
@@ -1856,11 +1829,14 @@ push_to_top_level ()
   s->member_init_list = current_member_init_list;
   s->class_bindings = class_binding_level;
   s->previous_class_type = previous_class_type;
+  s->previous_class_values = previous_class_values;
   s->lang_stack = current_lang_stack;
   s->lang_base = current_lang_base;
   s->lang_stacksize = current_lang_stacksize;
   s->lang_name = current_lang_name;
   s->named_labels = named_labels;
+  s->minimal_parse_mode = minimal_parse_mode;
+  s->last_function_parms = last_function_parms;
   current_class_name = current_class_type = NULL_TREE;
   current_function_decl = NULL_TREE;
   class_binding_level = (struct binding_level *)0;
@@ -1871,10 +1847,19 @@ push_to_top_level ()
   current_lang_name = lang_name_cplusplus;
   strict_prototype = strict_prototypes_lang_cplusplus;
   named_labels = NULL_TREE;
+  minimal_parse_mode = 0;
 
   s->prev = current_saved_scope;
   s->old_bindings = old_bindings;
   current_saved_scope = s;
+
+  push_obstacks (&permanent_obstack, &permanent_obstack);
+}
+
+void
+push_to_top_level ()
+{
+  maybe_push_to_top_level (0);
 }
 
 void
@@ -1887,6 +1872,8 @@ pop_from_top_level ()
   if (previous_class_type)
     previous_class_type = NULL_TREE;
 
+  pop_obstacks ();
+
   current_binding_level = s->old_binding_level;
   current_saved_scope = s->prev;
   for (t = s->old_bindings; t; t = TREE_CHAIN (t))
@@ -1906,6 +1893,7 @@ pop_from_top_level ()
   current_function_decl = s->function_decl;
   class_binding_level = s->class_bindings;
   previous_class_type = s->previous_class_type;
+  previous_class_values = s->previous_class_values;
   free (current_lang_base);
   current_lang_base = s->lang_base;
   current_lang_stack = s->lang_stack;
@@ -1916,6 +1904,8 @@ pop_from_top_level ()
   else if (current_lang_name == lang_name_c)
     strict_prototype = strict_prototypes_lang_c;
   named_labels = s->named_labels;
+  minimal_parse_mode = s->minimal_parse_mode;
+  last_function_parms = s->last_function_parms;
 
   free (s);
 }
@@ -1962,7 +1952,7 @@ set_identifier_type_value (id, type)
    the type decl in question.  (Argument CLASSNAME can actually be
    a function as well, if that's the smallest containing scope.)  */
 
-static void
+void
 set_nested_typename (decl, classname, name, type)
      tree decl, classname, name, type;
 {
@@ -2077,7 +2067,6 @@ pushtag (name, type, globalize)
                {
                  newdecl = 1;
                  d = build_decl (TYPE_DECL, name, type);
-                 DECL_ASSEMBLER_NAME (d) = current_namespace_id (DECL_ASSEMBLER_NAME (d));
                  SET_DECL_ARTIFICIAL (d);
 #ifdef DWARF_DEBUGGING_INFO
                  if (write_symbols == DWARF_DEBUG)
@@ -2095,6 +2084,9 @@ pushtag (name, type, globalize)
                d = TYPE_NAME (d);
 
              TYPE_NAME (type) = d;
+             DECL_CONTEXT (d) = context;
+             if (! globalize && current_template_parms && IS_AGGR_TYPE (type))
+               push_template_decl (d);
 
              /* If it is anonymous, then we are called from pushdecl,
                 and we don't want to infinitely recurse.  */
@@ -2124,16 +2116,11 @@ pushtag (name, type, globalize)
 #endif /* DWARF_DEBUGGING_INFO */
 
              TYPE_MAIN_DECL (type) = d;
+             DECL_CONTEXT (d) = context;
+             if (! globalize && current_template_parms && IS_AGGR_TYPE (type))
+               push_template_decl (d);
 
-             /* Make sure we're in this type's scope when we push the
-                decl for a template, otherwise class_binding_level will
-                be NULL and we'll end up dying inside of
-                push_class_level_binding.  */
-             if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
-               pushclass (type, 0);
              d = pushdecl_class_level (d);
-             if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
-               popclass (0);
            }
          if (newdecl)
            {
@@ -2143,6 +2130,8 @@ pushtag (name, type, globalize)
                    DECL_IGNORED_P (d) = 1;
                }
 
+             TYPE_CONTEXT (type) = DECL_CONTEXT (d);
+
              if (context == NULL_TREE)
                /* Non-nested class.  */
                set_nested_typename (d, NULL_TREE, name, type);
@@ -2155,8 +2144,6 @@ pushtag (name, type, globalize)
                set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl),
                                     name, type);
 
-             DECL_CONTEXT (d) = context;
-             TYPE_CONTEXT (type) = DECL_CONTEXT (d);
              DECL_ASSEMBLER_NAME (d)
                = get_identifier (build_overload_name (type, 1, 1));
            }
@@ -2317,10 +2304,7 @@ decls_match (newdecl, olddecl)
              return 0;
          }
 
-       if (DECL_TEMPLATE_IS_CLASS (newdecl)
-           != DECL_TEMPLATE_IS_CLASS (olddecl))
-         types_match = 0;
-       else if (DECL_TEMPLATE_IS_CLASS (newdecl))
+       if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
          types_match = 1;
        else
          types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
@@ -2416,7 +2400,9 @@ duplicate_decls (newdecl, olddecl)
   unsigned olddecl_uid = DECL_UID (olddecl);
   int olddecl_friend = 0, types_match = 0;
   int new_defines_function;
-  tree previous_c_decl = NULL_TREE;
+
+  if (newdecl == olddecl)
+    return 1;
 
   if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
     DECL_MACHINE_ATTRIBUTES (newdecl) = DECL_MACHINE_ATTRIBUTES (olddecl);
@@ -2486,11 +2472,9 @@ duplicate_decls (newdecl, olddecl)
   else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
     {
       if ((TREE_CODE (newdecl) == FUNCTION_DECL
-          && TREE_CODE (olddecl) == TEMPLATE_DECL
-          && ! DECL_TEMPLATE_IS_CLASS (olddecl))
+          && DECL_FUNCTION_TEMPLATE_P (olddecl))
          || (TREE_CODE (olddecl) == FUNCTION_DECL
-             && TREE_CODE (newdecl) == TEMPLATE_DECL
-             && ! DECL_TEMPLATE_IS_CLASS (newdecl)))
+             && DECL_FUNCTION_TEMPLATE_P (newdecl)))
        return 0;
       
       cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
@@ -2510,8 +2494,8 @@ duplicate_decls (newdecl, olddecl)
          /* The name of a class template may not be declared to refer to
             any other template, class, function, object, namespace, value,
             or type in the same scope. */
-         if (DECL_TEMPLATE_IS_CLASS (olddecl)
-             || DECL_TEMPLATE_IS_CLASS (newdecl))
+         if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
+             || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
            {
              cp_error ("declaration of template `%#D'", newdecl);
              cp_error_at ("conflicts with previous declaration `%#D'",
@@ -2584,7 +2568,8 @@ duplicate_decls (newdecl, olddecl)
            }
        }
 
-      if (TREE_CODE (olddecl) == FUNCTION_DECL)
+      if (TREE_CODE (olddecl) == FUNCTION_DECL
+         && ! DECL_USE_TEMPLATE (olddecl))
        {
          tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
          tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
@@ -2711,6 +2696,14 @@ duplicate_decls (newdecl, olddecl)
   /* Copy all the DECL_... slots specified in the new decl
      except for any that we copy here from the old type.  */
 
+  if (TREE_CODE (newdecl) == TEMPLATE_DECL)
+    {
+      TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
+      DECL_TEMPLATE_RESULT (olddecl) = DECL_TEMPLATE_RESULT (newdecl);
+      DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
+      return 1;
+    }
+
   if (types_match)
     {
       /* Automatically handles default parameters.  */
@@ -2737,14 +2730,12 @@ duplicate_decls (newdecl, olddecl)
          && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
              != TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
        {
-         tree ctype = NULL_TREE;
-         ctype = DECL_CLASS_CONTEXT (newdecl);
          TREE_TYPE (newdecl) = build_exception_variant (newtype,
                                                         TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
          TREE_TYPE (olddecl) = build_exception_variant (newtype,
                                                         TYPE_RAISES_EXCEPTIONS (oldtype));
 
-         if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
+         if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
            {
              cp_error ("declaration of `%D' throws different exceptions...",
                        newdecl);
@@ -2755,14 +2746,16 @@ duplicate_decls (newdecl, olddecl)
 
       /* Lay the type out, unless already done.  */
       if (oldtype != TREE_TYPE (newdecl)
-         && TREE_TYPE (newdecl) != error_mark_node)
+         && TREE_TYPE (newdecl) != error_mark_node
+         && !(current_template_parms && uses_template_parms (newdecl)))
        layout_type (TREE_TYPE (newdecl));
 
-      if (TREE_CODE (newdecl) == VAR_DECL
-         || TREE_CODE (newdecl) == PARM_DECL
-         || TREE_CODE (newdecl) == RESULT_DECL
-         || TREE_CODE (newdecl) == FIELD_DECL
-         || TREE_CODE (newdecl) == TYPE_DECL)
+      if ((TREE_CODE (newdecl) == VAR_DECL
+          || TREE_CODE (newdecl) == PARM_DECL
+          || TREE_CODE (newdecl) == RESULT_DECL
+          || TREE_CODE (newdecl) == FIELD_DECL
+          || TREE_CODE (newdecl) == TYPE_DECL)
+         && !(current_template_parms && uses_template_parms (newdecl)))
        layout_decl (newdecl, 0);
 
       /* Merge the type qualifiers.  */
@@ -2819,8 +2812,10 @@ duplicate_decls (newdecl, olddecl)
     DECL_EXTERNAL (newdecl) = 0;
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
+    DECL_C_STATIC (newdecl) |= DECL_C_STATIC (olddecl);
+
+  if (DECL_LANG_SPECIFIC (newdecl))
     {
-      DECL_C_STATIC (newdecl) |= DECL_C_STATIC (olddecl);
       DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
       DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
     }
@@ -2839,9 +2834,13 @@ duplicate_decls (newdecl, olddecl)
        {
          DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
          DECL_ASSEMBLER_NAME (olddecl) = DECL_ASSEMBLER_NAME (newdecl);
+         DECL_RTL (olddecl) = DECL_RTL (newdecl);
+       }
+      if (! types_match || new_defines_function)
+       {
+         /* These need to be copied so that the names are available.  */
          DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
          DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
-         DECL_RTL (olddecl) = DECL_RTL (newdecl);
        }
       if (new_defines_function)
        /* If defining a function declared with other language
@@ -2882,15 +2881,13 @@ duplicate_decls (newdecl, olddecl)
 
   if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
-      if (DECL_TEMPLATE_INFO (olddecl)->length)
-       DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
       DECL_TEMPLATE_MEMBERS (newdecl) = DECL_TEMPLATE_MEMBERS (olddecl);
       DECL_TEMPLATE_INSTANTIATIONS (newdecl)
        = DECL_TEMPLATE_INSTANTIATIONS (olddecl);
       if (DECL_CHAIN (newdecl) == NULL_TREE)
        DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl);
     }
-  
+
   /* Now preserve various other info from the definition.  */
   TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl);
   TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
@@ -2904,6 +2901,11 @@ duplicate_decls (newdecl, olddecl)
       DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
       DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
       DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
+      if (DECL_TEMPLATE_INFO (newdecl) == NULL_TREE)
+       {
+         DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
+         DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
+       }
     }
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -2997,8 +2999,11 @@ pushdecl (x)
 
   if (name)
     {
+#if 0
+      /* Not needed...see below.  */
       char *file;
       int line;
+#endif
 
       t = lookup_name_current_level (name);
       if (t == error_mark_node)
@@ -3010,8 +3015,12 @@ pushdecl (x)
 
       else if (t != NULL_TREE)
        {
+#if 0
+         /* This is turned off until I have time to do it right (bpk).  */
+         /* With the code below that uses it... */
          file = DECL_SOURCE_FILE (t);
          line = DECL_SOURCE_LINE (t);
+#endif
          if (TREE_CODE (t) == PARM_DECL)
            {
              if (DECL_CONTEXT (t) == NULL_TREE)
@@ -3022,9 +3031,8 @@ pushdecl (x)
                return t;
            }
          else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c)
-              || (TREE_CODE (x) == TEMPLATE_DECL
-                  && ! DECL_TEMPLATE_IS_CLASS (x)))
-             && is_overloaded_fn (t))
+                   || DECL_FUNCTION_TEMPLATE_P (x))
+                  && is_overloaded_fn (t))
            /* don't do anything just yet */;
          else if (t == wchar_decl_node)
            {
@@ -3096,7 +3104,7 @@ pushdecl (x)
          if (t != x || DECL_LANGUAGE (x) == lang_c)
            return t;
        }
-      else if (TREE_CODE (x) == TEMPLATE_DECL && ! DECL_TEMPLATE_IS_CLASS (x))
+      else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_CONTEXT (x) == NULL_TREE)
        return push_overloaded_decl (x, 0);
 
       /* If declaring a type as a typedef, and the type has no known
@@ -3345,7 +3353,8 @@ pushdecl (x)
   return x;
 }
 
-/* Same as pushdecl, but define X in binding-level LEVEL. */
+/* Same as pushdecl, but define X in binding-level LEVEL.  We rely on the
+   caller to set DECL_CONTEXT properly.  */
 
 static tree
 pushdecl_with_scope (x, level)
@@ -3353,10 +3362,13 @@ pushdecl_with_scope (x, level)
      struct binding_level *level;
 {
   register struct binding_level *b = current_binding_level;
+  tree function_decl = current_function_decl;
 
+  current_function_decl = NULL_TREE;
   current_binding_level = level;
   x = pushdecl (x);
   current_binding_level = b;
+  current_function_decl = function_decl;
   return x;
 }
 
@@ -3435,7 +3447,7 @@ pushdecl_class_level (x)
             members are checked in finish_struct.  */
          tree icv = IDENTIFIER_CLASS_VALUE (name);
 
-         if (icv
+         if (icv && icv != x
              /* Don't complain about inherited names.  */
              && id_in_current_class (name)
              /* Or shadowed tags.  */
@@ -3466,7 +3478,7 @@ pushdecl_class_level (x)
 /* This function is used to push the mangled decls for nested types into
    the appropriate scope.  Previously pushdecl_top_level was used, but that
    is incorrect for members of local classes.  */
-tree
+void
 pushdecl_nonclass_level (x)
      tree x;
 {
@@ -3474,9 +3486,11 @@ pushdecl_nonclass_level (x)
 
   my_friendly_assert (b->parm_flag != 2, 180);
 
+#if 0
   /* Get out of template binding levels */
   while (b->pseudo_global)
     b = b->level_chain;
+#endif
 
   pushdecl_with_scope (x, b);
 }
@@ -3512,11 +3526,11 @@ overloaded_globals_p (list)
   /* Don't commit caller to seeing them as globals.  */
   if (TREE_NONLOCAL_FLAG (list))
     return -1;
-  /* Do commit caller to seeing them as globals.  */
-  if (TREE_CODE (TREE_PURPOSE (list)) == IDENTIFIER_NODE)
-    return 1;
   /* Do commit caller to not seeing them as globals.  */
-  return 0;
+  if (TREE_CODE (TREE_VALUE (list)) == TREE_LIST)
+    return 0;
+  /* Do commit caller to seeing them as globals.  */
+  return 1;
 }
 
 /* DECL is a FUNCTION_DECL which may have other definitions already in
@@ -3538,8 +3552,7 @@ push_overloaded_decl (decl, forgettable)
 {
   tree orig_name = DECL_NAME (decl);
   tree old;
-  int doing_global = (global_bindings_p () || ! forgettable
-                     || flag_traditional || pseudo_global_level_p ());
+  int doing_global = (global_bindings_p () || ! forgettable);
 
   if (doing_global)
     {
@@ -3705,7 +3718,7 @@ redeclaration_error_message (newdecl, olddecl)
        return "redefinition of `%#D'";
       return 0;
     }
-  else if (current_binding_level == global_binding_level)
+  else if (toplevel_bindings_p ())
     {
       /* Objects declared at top level:  */
       /* If at least one is a reference, it's ok.  */
@@ -3820,7 +3833,20 @@ define_label (filename, line, name)
      int line;
      tree name;
 {
-  tree decl = lookup_label (name);
+  tree decl;
+
+  if (minimal_parse_mode)
+    {
+      push_obstacks (&permanent_obstack, &permanent_obstack);
+      decl = build_decl (LABEL_DECL, name, void_type_node);
+      pop_obstacks ();
+      DECL_SOURCE_LINE (decl) = line;
+      DECL_SOURCE_FILE (decl) = filename;
+      add_tree (decl);
+      return decl;
+    }
+
+  decl = lookup_label (name);
 
   /* After labels, make any new cleanups go into their
      own new (temporary) binding contour.  */
@@ -4050,16 +4076,14 @@ lookup_tag (form, name, binding_level, thislevel_only)
       else
        for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
          {
-           if (TREE_PURPOSE (tail) == name)
+           if (TREE_PURPOSE (tail) == name
+               || TYPE_NESTED_NAME (TREE_VALUE (tail)) == name)
              {
                enum tree_code code = TREE_CODE (TREE_VALUE (tail));
                /* Should tighten this up; it'll probably permit
                   UNION_TYPE and a struct template, for example.  */
                if (code != form
-                   && !(form != ENUMERAL_TYPE
-                        && (code == TEMPLATE_DECL
-                            || code == UNINSTANTIATED_P_TYPE)))
-                          
+                   && !(form != ENUMERAL_TYPE && code == TEMPLATE_DECL))
                  {
                    /* Definition isn't the kind we were looking for.  */
                    cp_error ("`%#D' redeclared as %C", TREE_VALUE (tail),
@@ -4070,7 +4094,16 @@ lookup_tag (form, name, binding_level, thislevel_only)
              }
          }
       if (thislevel_only && ! level->tag_transparent)
-       return NULL_TREE;
+       {
+         if (level->pseudo_global)
+           {
+             tree t = IDENTIFIER_GLOBAL_VALUE (name);
+             if (t && TREE_CODE (t) == TEMPLATE_DECL
+                 && TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
+               return TREE_TYPE (t);
+           }
+         return NULL_TREE;
+       }
       if (current_class_type && level->level_chain == global_binding_level)
        {
          /* Try looking in this class's tags before heading into
@@ -4252,6 +4285,42 @@ lookup_namespace_name (namespace, name)
   return x;
 }
 
+tree
+make_typename_type (context, name)
+     tree context, name;
+{
+  tree t, d, i;
+
+  if (! current_template_parms
+      || ! uses_template_parms (context))
+    {
+      t = lookup_field (context, name, 0, 1);
+      if (t == NULL_TREE)
+       {
+         cp_error_at ("no type matching `%#T' in `%#T'", name, context);
+         return error_mark_node;
+       }
+      return TREE_TYPE (t);
+    }
+
+  if (current_template_parms)
+    push_obstacks (&permanent_obstack, &permanent_obstack);
+  t = make_lang_type (TYPENAME_TYPE);
+  d = build_decl (TYPE_DECL, name, t);
+  i = make_anon_name ();
+  if (current_template_parms)
+    pop_obstacks ();
+
+  TYPE_CONTEXT (t) = context;
+  TYPE_MAIN_DECL (TREE_TYPE (d)) = d;
+  DECL_CONTEXT (d) = context;
+  DECL_NESTED_TYPENAME (d) = i;
+  IDENTIFIER_LOCAL_VALUE (i) = d;
+  TREE_TYPE (i) = t;
+
+  return t;
+}
+
 /* Look up NAME in the current binding level and its superiors in the
    namespace of variables, functions and typedefs.  Return a ..._DECL
    node of some kind representing its definition if there is only one
@@ -4288,22 +4357,17 @@ lookup_name_real (name, prefer_type, nonclass)
        {
          if (type == error_mark_node)
            return error_mark_node;
-         else if (type == void_type_node)
+
+         type = complete_type (type);
+
+         if (type == void_type_node)
            val = IDENTIFIER_GLOBAL_VALUE (name);
-         else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
-                  /* TFIXME -- don't do this for UPTs in new model.  */
-                  || TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
-           {
-             if (prefer_type > 0)
-               val = create_nested_upt (type, name);
-             else
-               val = NULL_TREE;
-           }
          else if (TREE_CODE (type) == NAMESPACE_DECL)
            {
              val = lookup_namespace_name (type, name);
            }
-         else if (! IS_AGGR_TYPE (type))
+         else if (! IS_AGGR_TYPE (type)
+                  || TREE_CODE (type) == TEMPLATE_TYPE_PARM)
            /* Someone else will give an error about this if needed. */
            val = NULL_TREE;
          else if (TYPE_BEING_DEFINED (type))
@@ -4323,8 +4387,7 @@ lookup_name_real (name, prefer_type, nonclass)
                        }
                    }
                }
-             if (val == NULL_TREE
-                 && CLASSTYPE_LOCAL_TYPEDECLS (type))
+             if (val == NULL_TREE)
                val = lookup_field (type, name, 0, 1);
            }
          else if (type == current_class_type)
@@ -4351,9 +4414,7 @@ lookup_name_real (name, prefer_type, nonclass)
   else if (current_class_type && ! nonclass)
     {
       val = IDENTIFIER_CLASS_VALUE (name);
-      if (val == NULL_TREE
-         && TYPE_BEING_DEFINED (current_class_type)
-         && CLASSTYPE_LOCAL_TYPEDECLS (current_class_type))
+      if (val == NULL_TREE && TYPE_BEING_DEFINED (current_class_type))
        /* Try to find values from base classes if we are presently
           defining a type.  We are presently only interested in
           TYPE_DECLs.  */
@@ -4375,8 +4436,12 @@ lookup_name_real (name, prefer_type, nonclass)
   if (val)
     {
       if (from_obj && from_obj != val)
-       cp_error ("lookup in the scope of `%#T' does not match lookup in the current scope",
-                 got_object);
+       {
+         cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%D')",
+                     name, got_object, from_obj);
+         cp_pedwarn ("  does not match lookup in the current scope (`%D')",
+                     val);
+       }
 
       if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
          || TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
@@ -4575,7 +4640,7 @@ void
 init_decl_processing ()
 {
   tree decl;
-  register tree endlink, int_endlink, double_endlink, ptr_endlink, float_endlink;
+  register tree endlink, int_endlink, double_endlink;
   tree fields[20];
   /* Either char* or void*.  */
   tree traditional_ptr_type_node;
@@ -4585,6 +4650,9 @@ init_decl_processing ()
   tree temp;
   tree array_domain_type;
   extern int flag_strict_prototype;
+  tree vb_off_identifier;
+  /* Function type `char *(char *, char *)' and similar ones */
+  tree string_ftype_ptr_ptr, int_ftype_string_string;
 
   /* Have to make these distinct before we try using them.  */
   lang_name_cplusplus = get_identifier ("C++");
@@ -4832,8 +4900,6 @@ init_decl_processing ()
   endlink = void_list_node;
   int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
   double_endlink = tree_cons (NULL_TREE, double_type_node, endlink);
-  float_endlink = tree_cons (NULL_TREE, float_type_node, endlink);
-  ptr_endlink = tree_cons (NULL_TREE, ptr_type_node, endlink);
 
   float_ftype_float
     = build_function_type (float_type_node,
@@ -4860,12 +4926,6 @@ init_decl_processing ()
                           tree_cons (NULL_TREE, long_integer_type_node,
                                      endlink));
 
-  void_ftype_ptr_ptr_int
-    = build_function_type (void_type_node,
-                          tree_cons (NULL_TREE, ptr_type_node,
-                                     tree_cons (NULL_TREE, ptr_type_node,
-                                                int_endlink)));
-
   int_ftype_cptr_cptr_sizet
     = build_function_type (integer_type_node,
                           tree_cons (NULL_TREE, const_ptr_type_node,
@@ -4874,12 +4934,6 @@ init_decl_processing ()
                                                            sizetype,
                                                            endlink))));
 
-  void_ftype_ptr_int_int
-    = build_function_type (void_type_node,
-                          tree_cons (NULL_TREE, ptr_type_node,
-                                     tree_cons (NULL_TREE, integer_type_node,
-                                                int_endlink)));
-
   string_ftype_ptr_ptr         /* strcpy prototype */
     = build_function_type (string_type_node,
                           tree_cons (NULL_TREE, string_type_node,
@@ -5416,7 +5470,9 @@ init_type_desc()
   if (tdecl == NULL_TREE)
     return 0;
   __t_desc_type_node = TREE_TYPE(tdecl);
+#if 0
   __tp_desc_type_node = build_pointer_type (__t_desc_type_node);
+#endif
 
 #if 0
   tdecl = lookup_name (get_identifier ("__baselist_type_info"), 0);
@@ -5542,6 +5598,15 @@ shadow_tag (declspecs)
          if (code == ENUMERAL_TYPE && TYPE_SIZE (value) == 0)
            cp_error ("forward declaration of `%#T'", value);
 
+         else if (IS_AGGR_TYPE (value) && CLASSTYPE_USE_TEMPLATE (value))
+           {
+             if (CLASSTYPE_IMPLICIT_INSTANTIATION (value)
+                 && TYPE_SIZE (value) == NULL_TREE)
+               SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (value);
+             else if (CLASSTYPE_TEMPLATE_INSTANTIATION (value))
+               cp_error ("specialization after instantiation of `%T'", value);
+           }
+
          t = value;
          ok_code = code;
          found_tag++;
@@ -5636,6 +5701,8 @@ groktypename (typename)
    to parse initializers.  */
 int debug_temp_inits = 1;
 
+void start_decl_1 ();
+
 tree
 start_decl (declarator, declspecs, initialized, raises)
      tree declarator, declspecs;
@@ -5648,7 +5715,10 @@ start_decl (declarator, declspecs, initialized, raises)
   extern int have_extern_spec;
   extern int used_extern_spec;
 
+#if 0
+  /* See code below that used this.  */
   int init_written = initialized;
+#endif
 
   /* This should only be done once on the top most decl. */
   if (have_extern_spec && !used_extern_spec)
@@ -5666,7 +5736,7 @@ start_decl (declarator, declspecs, initialized, raises)
   type = TREE_TYPE (decl);
 
   /* Don't lose if destructors must be executed at file-level.  */
-  if (TREE_STATIC (decl)
+  if (! current_template_parms && TREE_STATIC (decl)
       && TYPE_NEEDS_DESTRUCTOR (type)
       && !TREE_PERMANENT (decl))
     {
@@ -5685,61 +5755,11 @@ start_decl (declarator, declspecs, initialized, raises)
       pop_obstacks ();
     }
 
-  /* Corresponding pop_obstacks is done in `cp_finish_decl'.  */
-  push_obstacks_nochange ();
-
   context
     = (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
       ? DECL_CLASS_CONTEXT (decl)
       : DECL_CONTEXT (decl);
 
-  if (processing_template_decl)
-    {
-      tree d;
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-        {
-          /* Declarator is a call_expr; extract arguments from it, since
-             grokdeclarator didn't do it.  */
-          tree args;
-          args = copy_to_permanent (last_function_parms);
-          if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
-            {
-             tree t = TREE_TYPE (decl);
-             
-              t = TYPE_METHOD_BASETYPE (t); /* type method belongs to */
-             if (TREE_CODE (t) != UNINSTANTIATED_P_TYPE)
-               {
-                 t = build_pointer_type (t); /* base type of `this' */
-#if 1
-                 /* I suspect this is wrong. */
-                 t = build_type_variant (t, flag_this_is_variable <= 0,
-                                         0); /* type of `this' */
-#else
-                 t = build_type_variant (t, 0, 0); /* type of `this' */
-#endif
-                 t = build (PARM_DECL, t, this_identifier);
-                 TREE_CHAIN (t) = args;
-                 args = t;
-               }
-           }
-          DECL_ARGUMENTS (decl) = args;
-        }
-      d = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), TREE_TYPE (decl));
-      TREE_PUBLIC (d) = TREE_PUBLIC (decl);
-      TREE_STATIC (d) = TREE_STATIC (decl);
-      DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl)
-                          && !(context && !DECL_THIS_EXTERN (decl)));
-      DECL_TEMPLATE_RESULT (d) = decl;
-      decl = d;
-    }
-
-  /* If this type of object needs a cleanup, and control may
-     jump past it, make a new binding level so that it is cleaned
-     up only when it is initialized first.  */
-  if (TYPE_NEEDS_DESTRUCTOR (type)
-      && current_binding_level->more_cleanups_ok == 0)
-    pushlevel_temporary (1);
-
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
        If not, set INITIALIZED to zero, which will indirectly
@@ -5763,51 +5783,14 @@ start_decl (declarator, declspecs, initialized, raises)
        break;
 
       default:
-       /* Don't allow initializations for incomplete types except for
-          arrays which might be completed by the initialization.  */
-       if (type == error_mark_node)
-         ;                     /* Don't complain again.  */
-       else if (TYPE_SIZE (type) != NULL_TREE)
-         ;                     /* A complete type is ok.  */
-       else if (TREE_CODE (type) != ARRAY_TYPE)
-         {
-           cp_error ("variable `%#D' has initializer but incomplete type",
-                     decl);
-           initialized = 0;
-         }
-       else if (TYPE_SIZE (TREE_TYPE (type)) == NULL_TREE)
+       if (TREE_CODE (type) == ARRAY_TYPE && ! current_template_parms
+           && TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
          {
            cp_error ("elements of array `%#D' have incomplete type", decl);
            initialized = 0;
          }
       }
 
-  if (!initialized
-      && TREE_CODE (decl) != TYPE_DECL
-      && TREE_CODE (decl) != TEMPLATE_DECL
-      && IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl))
-    {
-      if (TYPE_SIZE (type) == NULL_TREE)
-       {
-         cp_error ("aggregate `%#D' has incomplete type and cannot be initialized",
-                decl);
-         /* Change the type so that assemble_variable will give
-            DECL an rtl we can live with: (mem (const_int 0)).  */
-         TREE_TYPE (decl) = error_mark_node;
-         type = error_mark_node;
-       }
-      else
-       {
-         /* If any base type in the hierarchy of TYPE needs a constructor,
-            then we set initialized to 1.  This way any nodes which are
-            created for the purposes of initializing this aggregate
-            will live as long as it does.  This is necessary for global
-            aggregates which do not have their initializers processed until
-            the end of the file.  */
-         initialized = TYPE_NEEDS_CONSTRUCTING (type);
-       }
-    }
-
   if (initialized)
     {
       if (! toplevel_bindings_p ()
@@ -5815,7 +5798,7 @@ start_decl (declarator, declspecs, initialized, raises)
        cp_warning ("declaration of `%#D' has `extern' and is initialized",
                    decl);
       DECL_EXTERNAL (decl) = 0;
-      if ( toplevel_bindings_p ())
+      if (toplevel_bindings_p ())
        TREE_STATIC (decl) = 1;
 
       /* Tell `pushdecl' this is an initialized decl
@@ -5824,7 +5807,7 @@ start_decl (declarator, declspecs, initialized, raises)
       DECL_INITIAL (decl) = error_mark_node;
     }
 
-  if (context && TYPE_SIZE (context) != NULL_TREE)
+  if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE)
     {
       if (TREE_CODE (decl) == VAR_DECL)
        {
@@ -5836,7 +5819,7 @@ start_decl (declarator, declspecs, initialized, raises)
        }
       else
        {
-         tree field = check_classfn (context, NULL_TREE, decl);
+         tree field = check_classfn (context, decl);
          if (field && duplicate_decls (decl, field))
            decl = field;
        }
@@ -5867,6 +5850,18 @@ start_decl (declarator, declspecs, initialized, raises)
   else
     tem = pushdecl (decl);
 
+  if (current_template_parms)
+    {
+      if (! current_function_decl)
+       push_template_decl (tem);
+      else if (minimal_parse_mode)
+       DECL_VINDEX (decl)
+           = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
+                           copy_to_permanent (declspecs),
+                           copy_to_permanent (raises), NULL_TREE);
+    }
+
+
 #if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
   /* Tell the back-end to use or not use .common as appropriate.  If we say
      -fconserve-space, we want this to save space, at the expense of wrong
@@ -5878,48 +5873,16 @@ start_decl (declarator, declspecs, initialized, raises)
   DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem);
 #endif
 
-  if (TREE_CODE (decl) == TEMPLATE_DECL)
-    {
-      tree result = DECL_TEMPLATE_RESULT (decl);
-      if (DECL_CONTEXT (result) != NULL_TREE)
-       {
-          tree type;
-          type = DECL_CONTEXT (result);
-
-         if (TREE_CODE (type) != UNINSTANTIATED_P_TYPE)
-           {
-             cp_error ("declaration of `%D' in non-template type `%T'",
-                       decl, type);
-             return NULL_TREE;
-           }
+  if (! current_template_parms)
+    start_decl_1 (tem);
 
-         if (TREE_CODE (result) == FUNCTION_DECL)
-           return tem;
-         else if (TREE_CODE (result) == VAR_DECL)
-           {
-             sorry ("static data member templates");
-             return NULL_TREE;
-           }
-         else
-           my_friendly_abort (13);
-        }
-      else if (TREE_CODE (result) == FUNCTION_DECL)
-        /*tem = push_overloaded_decl (tem, 0)*/;
-      else if (TREE_CODE (result) == VAR_DECL)
-       {
-         cp_error ("data template `%#D' must be member of a class template",
-                   result);
-         return NULL_TREE;
-       }
-      else if (TREE_CODE (result) == TYPE_DECL)
-       {
-         cp_error ("invalid template `%#D'", result);
-         return NULL_TREE;
-       }
-      else
-       my_friendly_abort (14);
-    }
+  /* 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)
@@ -5930,7 +5893,8 @@ start_decl (declarator, declspecs, initialized, raises)
         use temporary storage.  Do this even if we will ignore the value.  */
       if (toplevel_bindings_p () && debug_temp_inits)
        {
-         if (TYPE_NEEDS_CONSTRUCTING (type)
+         if (current_template_parms
+             || 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.   */
@@ -5939,41 +5903,129 @@ start_decl (declarator, declspecs, initialized, raises)
            temporary_allocation ();
        }
     }
+#endif
 
   return tem;
 }
 
-/* Handle initialization of references.
-   These three arguments from from `cp_finish_decl', and have the
-   same meaning here that they do there.  */
-/* quotes on semantics can be found in ARM 8.4.3. */
-static void
-grok_reference_init (decl, type, init, cleanupp)
-     tree decl, type, init;
-     tree *cleanupp;
+void
+start_decl_1 (decl)
+     tree decl;
 {
-  tree tmp;
+  tree type = TREE_TYPE (decl);
+  int initialized = (DECL_INITIAL (decl) != NULL_TREE);
 
-  if (init == NULL_TREE)
+  /* If this type of object needs a cleanup, and control may
+     jump past it, make a new binding level so that it is cleaned
+     up only when it is initialized first.  */
+  if (TYPE_NEEDS_DESTRUCTOR (type)
+      && current_binding_level->more_cleanups_ok == 0)
+    pushlevel_temporary (1);
+
+  if (initialized)
+    /* Is it valid for this decl to have an initializer at all?
+       If not, set INITIALIZED to zero, which will indirectly
+       tell `cp_finish_decl' to ignore the initializer once it is parsed.  */
     {
-      if ((DECL_LANG_SPECIFIC (decl) == 0
-          || DECL_IN_AGGR_P (decl) == 0)
-         && ! DECL_THIS_EXTERN (decl))
+      /* Don't allow initializations for incomplete types except for
+        arrays which might be completed by the initialization.  */
+      if (type == error_mark_node)
+       ;                       /* Don't complain again.  */
+      else if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
+       ;                       /* A complete type is ok.  */
+      else if (TREE_CODE (type) != ARRAY_TYPE)
        {
-         cp_error ("`%D' declared as reference but not initialized", decl);
-         if (TREE_CODE (decl) == VAR_DECL)
-           SET_DECL_REFERENCE_SLOT (decl, error_mark_node);
+         cp_error ("variable `%#D' has initializer but incomplete type",
+                   decl);
+         initialized = 0;
+       }
+      else if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
+       {
+         if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
+           cp_error ("elements of array `%#D' have incomplete type", decl);
+         /* else we already gave an error in start_decl.  */
+         initialized = 0;
        }
-      return;
     }
 
-  if (init == error_mark_node)
-    return;
-
-  if (TREE_CODE (type) == REFERENCE_TYPE
-      && TREE_CODE (init) == CONSTRUCTOR)
+  if (!initialized
+      && TREE_CODE (decl) != TYPE_DECL
+      && TREE_CODE (decl) != TEMPLATE_DECL
+      && IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl))
     {
-      cp_error ("ANSI C++ forbids use of initializer list to initialize reference `%D'", decl);
+      if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
+       {
+         cp_error ("aggregate `%#D' has incomplete type and cannot be initialized",
+                decl);
+         /* Change the type so that assemble_variable will give
+            DECL an rtl we can live with: (mem (const_int 0)).  */
+         TREE_TYPE (decl) = error_mark_node;
+         type = error_mark_node;
+       }
+      else
+       {
+         /* If any base type in the hierarchy of TYPE needs a constructor,
+            then we set initialized to 1.  This way any nodes which are
+            created for the purposes of initializing this aggregate
+            will live as long as it does.  This is necessary for global
+            aggregates which do not have their initializers processed until
+            the end of the file.  */
+         initialized = TYPE_NEEDS_CONSTRUCTING (type);
+       }
+    }
+
+#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;
+}
+
+/* Handle initialization of references.
+   These three arguments from from `cp_finish_decl', and have the
+   same meaning here that they do there.  */
+/* quotes on semantics can be found in ARM 8.4.3. */
+static void
+grok_reference_init (decl, type, init, cleanupp)
+     tree decl, type, init;
+     tree *cleanupp;
+{
+  tree tmp;
+
+  if (init == NULL_TREE)
+    {
+      if ((DECL_LANG_SPECIFIC (decl) == 0
+          || DECL_IN_AGGR_P (decl) == 0)
+         && ! DECL_THIS_EXTERN (decl))
+       {
+         cp_error ("`%D' declared as reference but not initialized", decl);
+         if (TREE_CODE (decl) == VAR_DECL)
+           SET_DECL_REFERENCE_SLOT (decl, error_mark_node);
+       }
+      return;
+    }
+
+  if (init == error_mark_node)
+    return;
+
+  if (TREE_CODE (type) == REFERENCE_TYPE
+      && TREE_CODE (init) == CONSTRUCTOR)
+    {
+      cp_error ("ANSI C++ forbids use of initializer list to initialize reference `%D'", decl);
       return;
     }
 
@@ -6138,8 +6190,20 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       return;
     }
 
-  was_incomplete = (DECL_SIZE (decl) == NULL_TREE);
+  if (current_template_parms)
+    {
+      if (init && DECL_INITIAL (decl))
+       DECL_INITIAL (decl) = init;
+      if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl))
+       {
+         tree stmt = DECL_VINDEX (decl);
+         DECL_VINDEX (decl) = NULL_TREE;
+         TREE_OPERAND (stmt, 3) = copy_to_permanent (init);
+         add_tree (stmt);
+       }
 
+      goto finish_end0;
+    }
   /* Take care of TYPE_DECLs up front.  */
   if (TREE_CODE (decl) == TYPE_DECL)
     {
@@ -6167,7 +6231,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
        TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
 
       rest_of_decl_compilation (decl, NULL_PTR,
-                               DECL_CONTEXT (decl) == NULL_TREE, 0);
+                               DECL_CONTEXT (decl) == NULL_TREE, at_eof);
       goto finish_end;
     }
   if (TREE_CODE (decl) != FUNCTION_DECL)
@@ -6413,6 +6477,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
      unless the type is an undefined structure or union.
      If not, it will get done when the type is completed.  */
 
+  was_incomplete = (DECL_SIZE (decl) == NULL_TREE);
+
   if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL
       || TREE_CODE (decl) == RESULT_DECL)
     {
@@ -6467,7 +6533,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
              make_decl_rtl (decl, asmspec, toplev);
            }
          else
-           rest_of_decl_compilation (decl, asmspec, toplev, 0);
+           rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
        }
       else if (TREE_CODE (decl) == VAR_DECL
               && DECL_LANG_SPECIFIC (decl)
@@ -6488,14 +6554,14 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
                  make_decl_rtl (decl, asmspec, 1);
                }
              else
-               rest_of_decl_compilation (decl, asmspec, toplev, 0);
+               rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
            }
          else
            /* Just a constant field.  Should not need any rtl.  */
            goto finish_end0;
        }
       else
-       rest_of_decl_compilation (decl, asmspec, toplev, 0);
+       rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
 
       if (was_temp)
        resume_temporary_allocation ();
@@ -6521,7 +6587,10 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       if (TREE_CODE (decl) == FUNCTION_DECL)
        ;
       else if (DECL_EXTERNAL (decl))
-       ;
+       {
+         if (init)
+           DECL_INITIAL (decl) = init;
+       }
       else if (TREE_STATIC (decl) && type != error_mark_node)
        {
          /* Cleanups for static variables are handled by `finish_file'.  */
@@ -6667,18 +6736,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
            && (TREE_CODE (decl) == VAR_DECL
                /* We also have a pushclass done that we need to undo here
                   if we're at top level and declare a method.  */
-               || (TREE_CODE (decl) == FUNCTION_DECL
-                   /* If size hasn't been set, we're still defining it,
-                      and therefore inside the class body; don't pop
-                      the binding level..  */
-                   && TYPE_SIZE (context) != NULL_TREE
-                   /* The binding level gets popped elsewhere for a
-                      friend declaration inside another class.  */
-                   /*
-                   && TYPE_IDENTIFIER (context) == current_class_name
-                   */
-                   && context == current_class_type
-                   )))
+               || TREE_CODE (decl) == FUNCTION_DECL)
+           /* If size hasn't been set, we're still defining it,
+              and therefore inside the class body; don't pop
+              the binding level..  */
+           && TYPE_SIZE (context) != NULL_TREE
+           && context == current_class_type)
          popclass (1);
       }
     }
@@ -6688,6 +6751,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
   /* If requested, warn about definitions of large data objects.  */
 
   if (warn_larger_than
+      && ! current_template_parms
       && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
       && !DECL_EXTERNAL (decl))
     {
@@ -6965,13 +7029,13 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
    not look, and -1 if we should not call `grokclassfn' at all.  */
 static tree
 grokfndecl (ctype, type, declarator, virtualp, flags, quals,
-           raises, attrlist, check, publicp, inlinep)
+           raises, attrlist, check, publicp, inlinep, funcdef_flag)
      tree ctype, type;
      tree declarator;
      int virtualp;
      enum overload_flags flags;
      tree quals, raises, attrlist;
-     int check, publicp, inlinep;
+     int check, publicp, inlinep, funcdef_flag;
 {
   tree cname, decl;
   int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
@@ -7035,6 +7099,9 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
   if (check < 0)
     return decl;
 
+  if (check && funcdef_flag)
+    DECL_INITIAL (decl) = error_mark_node;
+
   if (flags == NO_SPECIAL && ctype && constructor_name (cname) == declarator)
     {
       tree tmp;
@@ -7047,7 +7114,11 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
 
       grokclassfn (ctype, declarator, decl, flags, quals);
       if (check)
-       check_classfn (ctype, declarator, decl);
+       {
+         tmp = check_classfn (ctype, decl);
+         if (tmp && duplicate_decls (decl, tmp))
+           return tmp;
+       }
       if (! grok_ctor_properties (ctype, decl))
        return NULL_TREE;
 
@@ -7081,7 +7152,19 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
        grokclassfn (ctype, cname, decl, flags, quals);
 
       if (ctype != NULL_TREE && check)
-       check_classfn (ctype, cname, decl);
+       {
+         tmp = check_classfn (ctype, decl);
+         if (tmp && DECL_STATIC_FUNCTION_P (tmp)
+             && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
+           {
+             /* Remove the `this' parm added by grokclassfn.
+                XXX Isn't this done in start_function, too?  */
+             revert_static_member_fn (&decl, NULL, NULL);
+             last_function_parms = TREE_CHAIN (last_function_parms);
+           }
+         if (tmp && duplicate_decls (decl, tmp))
+           return tmp;
+       }
 
       if (ctype == NULL_TREE || check)
        return decl;
@@ -7317,8 +7400,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
   int funcdef_flag = 0;
   enum tree_code innermost_code = ERROR_MARK;
   int bitfield = 0;
-  int size_varies = 0;
+#if 0
+  /* See the code below that used this.  */
   tree decl_machine_attr = NULL_TREE;
+#endif
   /* Set this to error_mark_node for FIELD_DECLs we could not handle properly.
      All FIELD_DECLs we build here have `init' put into their DECL_INITIAL.  */
   tree init = NULL_TREE;
@@ -7370,6 +7455,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
              my_friendly_assert (flags == NO_SPECIAL, 152);
              flags = DTOR_FLAG;
              return_type = return_dtor;
+             if (TREE_CODE (name) == TYPE_DECL)
+               TREE_OPERAND (decl, 0) = name = constructor_name (name);
              my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
              if (ctype == NULL_TREE)
                {
@@ -7394,9 +7481,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
 
              if (rename)
                {
-                 error ("destructor `%s' must match class name `%s'",
-                        IDENTIFIER_POINTER (name),
-                        IDENTIFIER_POINTER (rename));
+                 cp_error ("destructor `%T' must match class name `%T'",
+                           name, rename);
                  TREE_OPERAND (decl, 0) = rename;
                }
              next = &name;
@@ -7489,6 +7575,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
              else if (TREE_OPERAND (decl, 1)
                       && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)
                ctype = cname;
+             else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM)
+               {
+                 cp_error ("`%T::%D' is not a valid declarator", cname,
+                           TREE_OPERAND (decl, 1));
+                 cp_error ("  perhaps you want `typename %T::%D' to make it a type",
+                           cname, TREE_OPERAND (decl, 1));
+                 return void_type_node;
+               }
              else if (ctype == NULL_TREE)
                ctype = cname;
              else if (TREE_COMPLEXITY (decl) == current_class_depth)
@@ -7593,7 +7687,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
 
      We also want to avoid calling this a PARM if it is in a namespace.  */
 
-  if (decl_context == NORMAL && ! namespace_bindings_p ())
+  if (decl_context == NORMAL && ! namespace_bindings_p ()
+      && ! pseudo_global_level_p ())
     {
       struct binding_level *b = current_binding_level;
       current_binding_level = b->level_chain;
@@ -7692,7 +7787,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
            cp_error ("multiple declarations `%T' and `%T'", type,
                      TREE_TYPE (id));
          else
-           type = TREE_TYPE (id);
+           {
+             type = TREE_TYPE (id);
+             TREE_VALUE (spec) = type;
+           }
          goto found;
        }
       if (type)
@@ -7706,7 +7804,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
          else
            {
              type = TREE_TYPE (t);
+#if 0
+             /* See the code below that used this.  */
              decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
+#endif
              typedef_decl = t;
            }
        }
@@ -7794,13 +7895,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
 
       type = ctor_return_type;
     }
-  /* Catch typedefs that only specify a type, like 'typedef int;'.  */
-  else if (RIDBIT_SETP (RID_TYPEDEF, specbits) && declarator == NULL_TREE)
-    {
-      /* Template "this is a type" syntax; just ignore for now.  */
-      if (processing_template_defn)
-       return void_type_node;
-    }
 
   ctype = NULL_TREE;
 
@@ -8293,10 +8387,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
                    && TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0)))
                  size = TREE_OPERAND (size, 0);
 
-               /* If this is a template parameter, it'll be constant, but
-                  we don't know what the value is yet.  */
-               if (TREE_CODE (size) == TEMPLATE_CONST_PARM)
-                 goto dont_grok_size;
+               /* If this involves a template parameter, it'll be
+                  constant, but we don't know what the value is yet.  */
+               if (current_template_parms)
+                 {
+                   itype = make_node (INTEGER_TYPE);
+                   TYPE_MIN_VALUE (itype) = size_zero_node;
+                   TYPE_MAX_VALUE (itype) = build_min
+                     (MINUS_EXPR, sizetype, size, integer_one_node);
+                   goto dont_grok_size;
+                 }
 
                if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
                    && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE)
@@ -8334,12 +8434,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
                        else
                          cp_pedwarn ("ANSI C++ forbids variable-size array");
                      }
-                   /* Make sure the array size remains visibly nonconstant
-                      even if it is (eg) a const variable with known value. */
-                   size_varies = 1;
                  }
 
-             dont_grok_size:
                itype =
                  fold (build_binary_op (MINUS_EXPR,
                                         convert (index_type, size),
@@ -8348,6 +8444,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
                if (! TREE_CONSTANT (itype))
                  itype = variable_size (itype);
                itype = build_index_type (itype);
+             dont_grok_size:
                resume_momentary (yes);
              }
 
@@ -8713,6 +8810,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
                 multiple times.  */ ;
            else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
              /* don't fall out into global scope. Hides real bug? --eichin */ ;
+           else if (! IS_AGGR_TYPE_CODE
+                    (TREE_CODE (TREE_OPERAND (declarator, 0))))
+             ;
            else if (TREE_COMPLEXITY (declarator) == current_class_depth)
              {
                /* This pop_nested_class corresponds to the
@@ -8769,8 +8869,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
                        return void_type_node;
                      }
                  }
-               else if (TYPE_SIZE (ctype) != NULL_TREE
-                        || (RIDBIT_SETP (RID_TYPEDEF, specbits)))
+               else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
+                        || TYPE_SIZE (complete_type (ctype)) != NULL_TREE)
                  {
                    /* have to move this code elsewhere in this function.
                       this code is used for i.e., typedef int A::M; M *pm;
@@ -8787,14 +8887,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
                  }
                else if (uses_template_parms (ctype))
                  {
-                    enum tree_code c;
                     if (TREE_CODE (type) == FUNCTION_TYPE)
-                     {
-                       type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
-                                                       TREE_TYPE (type),
-                                                       TYPE_ARG_TYPES (type));
-                       c = FUNCTION_DECL;
-                     }
+                     type = 
+                       build_cplus_method_type (build_type_variant (ctype,
+                                                                    constp,
+                                                                    volatilep),
+                                                TREE_TYPE (type),
+                                                TYPE_ARG_TYPES (type));
                  }
                else
                  {
@@ -9170,11 +9269,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
               TREE_PUBLIC, also.  */
            decl = grokfndecl (ctype, type, declarator,
                               virtualp, flags, quals, raises, attrlist,
-                              friendp ? -1 : 0, 1, 0);
+                              friendp ? -1 : 0, 1, 0, funcdef_flag);
            if (decl == NULL_TREE)
              return NULL_TREE;
          }
-       else if (TYPE_SIZE (type) == NULL_TREE && !staticp
+       else if (!staticp && ! processing_template_decl
+                && TYPE_SIZE (complete_type (type)) == NULL_TREE
                 && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
          {
            if (declarator)
@@ -9216,7 +9316,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
                tree t = NULL_TREE;
                if (decl && DECL_NAME (decl))
                  t = do_friend (ctype, declarator, decl,
-                                last_function_parms, flags, quals);
+                                last_function_parms, flags, quals,
+                                funcdef_flag);
                if (t && funcdef_flag)
                  return t;
                
@@ -9308,7 +9409,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
           Storage classes other than `extern' are not allowed
           and `extern' makes no difference.  */
        if (! toplevel_bindings_p ()
-           && ! processing_template_decl
            && (RIDBIT_SETP (RID_STATIC, specbits)
                || RIDBIT_SETP (RID_INLINE, specbits))
            && pedantic)
@@ -9328,6 +9428,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
              }
 
            if (current_lang_name == lang_name_cplusplus
+               && ! current_template_parms
                && ! (IDENTIFIER_LENGTH (original_name) == 4
                      && IDENTIFIER_POINTER (original_name)[0] == 'm'
                      && strcmp (IDENTIFIER_POINTER (original_name), "main") == 0)
@@ -9350,8 +9451,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
 
        decl = grokfndecl (ctype, type, original_name,
                           virtualp, flags, quals, raises, attrlist,
-                          processing_template_decl ? 0 : friendp ? 2 : 1,
-                          publicp, inlinep);
+                          friendp ? 2 : 1,
+                          publicp, inlinep, funcdef_flag);
        if (decl == NULL_TREE)
          return NULL_TREE;
 
@@ -9505,10 +9606,13 @@ static void
 require_complete_types_for_parms (parms)
      tree parms;
 {
+  if (processing_template_decl)
+    return;
+
   while (parms)
     {
       tree type = TREE_TYPE (parms);
-      if (TYPE_SIZE (type) == NULL_TREE)
+      if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
        {
          if (DECL_NAME (parms))
            error ("parameter `%s' has incomplete type",
@@ -9606,7 +9710,7 @@ grokparms (first_parm, funcdef_flag)
       /* Types were specified.  This is a list of declarators
         each represented as a TREE_LIST node.  */
       register tree parm, chain;
-      int any_init = 0, any_error = 0, saw_void = 0;
+      int any_init = 0, any_error = 0;
 
       if (first_parm != NULL_TREE)
        {
@@ -9694,7 +9798,6 @@ grokparms (first_parm, funcdef_flag)
                      TREE_CHAIN (last_result) = void_list_node;
                      last_result = void_list_node;
                    }
-                 saw_void = 1;
                  if (chain
                      && (chain != void_list_node || TREE_CHAIN (chain)))
                    error ("`void' in parameter list must be entire list");
@@ -9716,6 +9819,8 @@ grokparms (first_parm, funcdef_flag)
                      any_init++;
                      if (TREE_CODE (init) == SAVE_EXPR)
                        PARM_DECL_EXPR (init) = 1;
+                     else if (current_template_parms)
+                       ;
                      else if (TREE_CODE (init) == VAR_DECL
                               || TREE_CODE (init) == PARM_DECL)
                        {
@@ -9872,7 +9977,7 @@ unary_op_p (name)
 }
 
 /* Do a little sanity-checking on how they declared their operator.  */
-static void
+void
 grok_op_properties (decl, virtualp, friendp)
      tree decl;
      int virtualp, friendp;
@@ -10124,7 +10229,6 @@ xref_tag (code_type_node, name, binfo, globalize)
   enum tag_types tag_code;
   enum tree_code code;
   int temp = 0;
-  int i;
   register tree ref, t;
   struct binding_level *b = inner_binding_level;
 
@@ -10326,7 +10430,9 @@ xref_basetypes (code_type_node, name, ref, binfo)
 
       if (basetype && TREE_CODE (basetype) == TYPE_DECL)
        basetype = TREE_TYPE (basetype);
-      if (!basetype || TREE_CODE (basetype) != RECORD_TYPE)
+      if (!basetype
+         || (TREE_CODE (basetype) != RECORD_TYPE
+             && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM))
        {
          cp_error ("base type `%T' fails to be a struct or class type",
                    TREE_VALUE (binfo));
@@ -10334,7 +10440,8 @@ xref_basetypes (code_type_node, name, ref, binfo)
        }
 #if 1
       /* This code replaces similar code in layout_basetypes.  */
-      else if (TYPE_INCOMPLETE (basetype))
+      else if (TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
+              && TYPE_SIZE (complete_type (basetype)) == NULL_TREE)
        {
          cp_error ("base class `%T' has incomplete type", basetype);
          continue;
@@ -10467,23 +10574,29 @@ finish_enum (enumtype, values)
     {
       register tree pair;
       register tree value = DECL_INITIAL (TREE_VALUE (values));
-      
-      /* Speed up the main loop by performing some precalculations */
-      TREE_TYPE (TREE_VALUE (values)) = enumtype;
-      TREE_TYPE (value) = enumtype;
+
+      if (! current_template_parms)
+       {
+         /* Speed up the main loop by performing some precalculations */
+         TREE_TYPE (TREE_VALUE (values)) = enumtype;
+         TREE_TYPE (value) = enumtype;
+         minnode = maxnode = value;
+       }
       TREE_VALUE (values) = value;
-      minnode = maxnode = value;
       
       for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
        {
          value = DECL_INITIAL (TREE_VALUE (pair));
-         TREE_TYPE (TREE_VALUE (pair)) = enumtype;
-         TREE_TYPE (value) = enumtype;
+         if (! current_template_parms)
+           {
+             TREE_TYPE (TREE_VALUE (pair)) = enumtype;
+             TREE_TYPE (value) = enumtype;
+             if (tree_int_cst_lt (maxnode, value))
+               maxnode = value;
+             else if (tree_int_cst_lt (value, minnode))
+               minnode = value;
+           }
          TREE_VALUE (pair) = value;
-         if (tree_int_cst_lt (maxnode, value))
-           maxnode = value;
-         else if (tree_int_cst_lt (value, minnode))
-           minnode = value;
        }
     }
   else
@@ -10491,6 +10604,9 @@ finish_enum (enumtype, values)
 
   TYPE_VALUES (enumtype) = values;
 
+  if (current_template_parms)
+    return enumtype;
+
   {
     int unsignedp = tree_int_cst_sgn (minnode) >= 0;
     int lowprec = min_precision (minnode, unsignedp);
@@ -10507,7 +10623,7 @@ finish_enum (enumtype, values)
     else
       fixup_signed_type (enumtype);
 
-    if (flag_short_enums || precision > TYPE_PRECISION (integer_type_node))
+    if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
       /* Use the width of the narrowest normal C type which is wide enough.  */
       TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
                                                  (precision, 1));
@@ -10559,54 +10675,57 @@ build_enumerator (name, value)
   if (value)
     STRIP_TYPE_NOPS (value);
 
-  /* Validate and default VALUE.  */
-  if (value != NULL_TREE)
-    {
-      if (TREE_READONLY_DECL_P (value))
-       {
-         value = decl_constant_value (value);
-         shareable = 0;
-       }
-
-      if (TREE_CODE (value) == INTEGER_CST)
-       {
-         value = default_conversion (value);
-         constant_expression_warning (value);
-       }
-      else
-       {
-         cp_error ("enumerator value for `%D' not integer constant", name);
-         value = NULL_TREE;
-       }
-    }
-
-  /* The order of things is reversed here so that we
-     can check for possible sharing of enum values,
-     to keep that from happening.  */
-  /* Default based on previous value.  */
-  if (value == NULL_TREE)
-    {
-      value = enum_next_value;
-      if (enum_overflow)
-       cp_error ("overflow in enumeration values at `%D'", name);
-    }
-
-  /* Remove no-op casts from the value.  */
-  if (value)
-    STRIP_TYPE_NOPS (value);
-
-  /* Make up for hacks in lex.c.  */
-  if (value == integer_zero_node)
-    value = build_int_2 (0, 0);
-  else if (value == integer_one_node)
-    value = build_int_2 (1, 0);
-  else if (TREE_CODE (value) == INTEGER_CST
-          && (shareable == 0
-              || TREE_CODE (TREE_TYPE (value)) == ENUMERAL_TYPE))
-    {
-      value = copy_node (value);
-      TREE_TYPE (value) = integer_type_node;
-    }
+ if (! current_template_parms)
+   {
+     /* Validate and default VALUE.  */
+     if (value != NULL_TREE)
+       {
+        if (TREE_READONLY_DECL_P (value))
+          {
+            value = decl_constant_value (value);
+            shareable = 0;
+          }
+
+        if (TREE_CODE (value) == INTEGER_CST)
+          {
+            value = default_conversion (value);
+            constant_expression_warning (value);
+          }
+        else
+          {
+            cp_error ("enumerator value for `%D' not integer constant", name);
+            value = NULL_TREE;
+          }
+       }
+
+     /* The order of things is reversed here so that we
+       can check for possible sharing of enum values,
+       to keep that from happening.  */
+     /* Default based on previous value.  */
+     if (value == NULL_TREE && ! current_template_parms)
+       {
+        value = enum_next_value;
+        if (enum_overflow)
+          cp_error ("overflow in enumeration values at `%D'", name);
+       }
+
+     /* Remove no-op casts from the value.  */
+     if (value)
+       STRIP_TYPE_NOPS (value);
+
+     /* Make up for hacks in lex.c.  */
+     if (value == integer_zero_node)
+       value = build_int_2 (0, 0);
+     else if (value == integer_one_node)
+       value = build_int_2 (1, 0);
+     else if (TREE_CODE (value) == INTEGER_CST
+             && (shareable == 0
+                 || TREE_CODE (TREE_TYPE (value)) == ENUMERAL_TYPE))
+       {
+        value = copy_node (value);
+        TREE_TYPE (value) = integer_type_node;
+       }
+   }
 
   /* C++ associates enums with global, function, or class declarations.  */
 
@@ -10633,13 +10752,16 @@ build_enumerator (name, value)
       GNU_xref_decl (current_function_decl, decl);
     }
 
-  /* Set basis for default for next value.  */
-  enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
-                                              integer_one_node, PLUS_EXPR);
-  enum_overflow = tree_int_cst_lt (enum_next_value, value);
-  
-  if (enum_next_value == integer_one_node)
-    enum_next_value = copy_node (enum_next_value);
+ if (! current_template_parms)
+   {
+     /* Set basis for default for next value.  */
+     enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
+                                                 integer_one_node, PLUS_EXPR);
+     enum_overflow = tree_int_cst_lt (enum_next_value, value);
+
+     if (enum_next_value == integer_one_node)
+       enum_next_value = copy_node (enum_next_value);
+   }
 
   result = saveable_tree_cons (name, decl, NULL_TREE);
   return result;
@@ -10671,6 +10793,8 @@ grok_enum_decls (type, decl)
   return decl;
 }
 \f
+static int function_depth;
+
 /* Create the FUNCTION_DECL for a function definition.
    DECLSPECS and DECLARATOR are the parts of the declaration;
    they describe the function's name and the type it returns,
@@ -10697,7 +10821,7 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
      tree declspecs, declarator, raises, attrs;
      int pre_parsed_p;
 {
-  tree decl1, olddecl;
+  tree decl1;
   tree ctype = NULL_TREE;
   tree fntype;
   tree restype;
@@ -10751,18 +10875,6 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
            cp_error_at ("previous declaration here", IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl1)));
        }
 
-      /* This can happen if a template class is instantiated as part of the
-        specialization of a member function which is defined in the class
-        template.  We should just use the specialization, but for now give an
-        error.  */
-      if (DECL_INITIAL (decl1) != NULL_TREE)
-       {
-         cp_error_at ("specialization of `%#D' not supported", decl1);
-         cp_error ("when defined in the class template body", decl1);
-       }
-
-      last_function_parms = DECL_ARGUMENTS (decl1);
-      last_function_parm_tags = NULL_TREE;
       fntype = TREE_TYPE (decl1);
       if (TREE_CODE (fntype) == METHOD_TYPE)
        ctype = TYPE_METHOD_BASETYPE (fntype);
@@ -10786,15 +10898,18 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
       raises = TYPE_RAISES_EXCEPTIONS (fntype);
 
       /* In a fcn definition, arg types must be complete.  */
-      require_complete_types_for_parms (last_function_parms);
+      require_complete_types_for_parms (DECL_ARGUMENTS (decl1));
 
       /* In case some arg types were completed since the declaration was
          parsed, fix up the decls.  */
       {
-       tree t = last_function_parms;
+       tree t = DECL_ARGUMENTS (decl1);
        for (; t; t = TREE_CHAIN (t))
          layout_decl (t, 0);
       }
+
+      last_function_parms = DECL_ARGUMENTS (decl1);
+      last_function_parm_tags = NULL_TREE;
     }
   else
     {
@@ -10833,7 +10948,7 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
          if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
            {
              if (pedantic || warn_return_type)
-               pedwarn ("return type for `main' changed to integer type");
+               pedwarn ("return type for `main' changed to `int'");
              TREE_TYPE (decl1) = fntype = default_function_type;
            }
          warn_about_return_type = 0;
@@ -10847,39 +10962,43 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
     cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
 
   current_function_decl = decl1;
+  /* Save the parm names or decls from this function's declarator
+     where store_parm_decls will find them.  */
+  current_function_parms = last_function_parms;
+  current_function_parm_tags = last_function_parm_tags;
 
   announce_function (decl1);
 
-  if (TYPE_SIZE (TREE_TYPE (fntype)) == NULL_TREE)
+  if (! current_template_parms || ! uses_template_parms (TREE_TYPE (fntype)))
     {
-      if (IS_AGGR_TYPE (TREE_TYPE (fntype)))
-       error_with_aggr_type (TREE_TYPE (fntype),
-                             "return-type `%s' is an incomplete type");
-      else
-       error ("return-type is an incomplete type");
-
-      /* Make it return void instead, but don't change the
-        type of the DECL_RESULT, in case we have a named return value.  */
-      if (ctype)
-       TREE_TYPE (decl1)
-         = build_cplus_method_type (build_type_variant (ctype,
-                                                        TREE_READONLY (decl1),
-                                                        TREE_SIDE_EFFECTS (decl1)),
-                                    void_type_node,
-                                    FUNCTION_ARG_CHAIN (decl1));
-      else
-       TREE_TYPE (decl1)
-         = build_function_type (void_type_node,
-                                TYPE_ARG_TYPES (TREE_TYPE (decl1)));
-      DECL_RESULT (decl1)
-       = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (fntype)));
-      TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (TREE_TYPE (fntype));
-      TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (TREE_TYPE (fntype));
-    }
+      if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE)
+       {
+         cp_error ("return-type `%#T' is an incomplete type",
+                   TREE_TYPE (fntype));
 
-  if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
-      && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype)))
-    abstract_virtuals_error (decl1, TREE_TYPE (fntype));
+         /* Make it return void instead, but don't change the
+            type of the DECL_RESULT, in case we have a named return value.  */
+         if (ctype)
+           TREE_TYPE (decl1)
+             = build_cplus_method_type (build_type_variant (ctype,
+                                                            TREE_READONLY (decl1),
+                                                            TREE_SIDE_EFFECTS (decl1)),
+                                        void_type_node,
+                                        FUNCTION_ARG_CHAIN (decl1));
+         else
+           TREE_TYPE (decl1)
+             = build_function_type (void_type_node,
+                                    TYPE_ARG_TYPES (TREE_TYPE (decl1)));
+         DECL_RESULT (decl1)
+           = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (fntype)));
+         TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (TREE_TYPE (fntype));
+         TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (TREE_TYPE (fntype));
+       }
+
+      if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
+         && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype)))
+       abstract_virtuals_error (decl1, TREE_TYPE (fntype));
+    }
 
   if (warn_about_return_type)
     warning ("return-type defaults to `int'");
@@ -10888,9 +11007,6 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
      error_mark_node is replaced below (in poplevel) with the BLOCK.  */
   DECL_INITIAL (decl1) = error_mark_node;
 
-  /* Didn't get anything from C.  */
-  olddecl = NULL_TREE;
-
   /* This function exists in static storage.
      (This does not mean `static' in the C sense!)  */
   TREE_STATIC (decl1) = 1;
@@ -10899,14 +11015,16 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
      If we already have a decl for this name, and it is a FUNCTION_DECL,
      use the old decl.  */
 
-  if (pre_parsed_p == 0)
+  if (current_template_parms)
+    push_template_decl (decl1);
+  else if (pre_parsed_p == 0)
     {
-      current_function_decl = decl1 = pushdecl (decl1);
+      decl1 = pushdecl (decl1);
       DECL_MAIN_VARIANT (decl1) = decl1;
       fntype = TREE_TYPE (decl1);
     }
-  else
-    current_function_decl = decl1;
+
+  current_function_decl = decl1;
 
   if (DECL_INTERFACE_KNOWN (decl1))
     {
@@ -10916,9 +11034,12 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
   /* If this function belongs to an interface, it is public.
      If it belongs to someone else's interface, it is also external.
      It doesn't matter whether it's inline or not.  */
-  else if (interface_unknown == 0)
+  else if (interface_unknown == 0
+          && (! DECL_TEMPLATE_INSTANTIATION (decl1)
+              || flag_external_templates))
     {
-      if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
+      if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)
+         || current_template_parms)
        DECL_EXTERNAL (decl1)
          = (interface_only
             || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
@@ -10933,7 +11054,10 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
         So clear DECL_EXTERNAL.  */
       DECL_EXTERNAL (decl1) = 0;
 
-      if (DECL_THIS_INLINE (decl1) && ! DECL_INTERFACE_KNOWN (decl1))
+      if ((DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
+         && ! DECL_INTERFACE_KNOWN (decl1)
+         /* Don't try to defer nested functions for now.  */
+         && ! decl_function_context (decl1))
        DECL_DEFER_OUTPUT (decl1) = 1;
       else
        {
@@ -10949,8 +11073,8 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
        TREE_TYPE (decl1) = fntype
          = build_function_type (TREE_TYPE (fntype),
                                 TREE_CHAIN (TYPE_ARG_TYPES (fntype)));
-      last_function_parms = TREE_CHAIN (last_function_parms);
-      DECL_ARGUMENTS (decl1) = last_function_parms;
+      current_function_parms = TREE_CHAIN (current_function_parms);
+      DECL_ARGUMENTS (decl1) = current_function_parms;
       ctype = NULL_TREE;
     }
   restype = TREE_TYPE (fntype);
@@ -10968,7 +11092,7 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
             parse errors may never get us to that point.  Here
             we keep the consistency between `current_class_type'
             and `current_class_decl'.  */
-         tree t = last_function_parms;
+         tree t = current_function_parms;
 
          my_friendly_assert (t != NULL_TREE
                              && TREE_CODE (t) == PARM_DECL, 162);
@@ -11001,34 +11125,21 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
   pushlevel (0);
   current_binding_level->parm_flag = 1;
 
-  /* Save the parm names or decls from this function's declarator
-     where store_parm_decls will find them.  */
-  current_function_parms = last_function_parms;
-  current_function_parm_tags = last_function_parm_tags;
-
   GNU_xref_function (decl1, current_function_parms);
 
   if (attrs)
     cplus_decl_attributes (decl1, NULL_TREE, attrs);
   make_function_rtl (decl1);
 
-  /* Allocate further tree nodes temporarily during compilation
-     of this function only.  Tiemann moved up here from bottom of fn.  */
-  temporary_allocation ();
-
   /* Promote the value to int before returning it.  */
   if (C_PROMOTING_INTEGER_TYPE_P (restype))
-    {
-      /* It retains unsignedness if traditional or if it isn't
-        really getting wider.  */
-      if (TREE_UNSIGNED (restype)
-         && (flag_traditional
-             || TYPE_PRECISION (restype)
-                  == TYPE_PRECISION (integer_type_node)))
-       restype = unsigned_type_node;
-      else
-       restype = integer_type_node;
-    }
+    restype = type_promotes_to (restype);
+
+  /* If this fcn was already referenced via a block-scope `extern' decl
+     (or an implicit decl), propagate certain information about the usage.  */
+  if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl1)))
+    TREE_ADDRESSABLE (decl1) = 1;
+
   if (DECL_RESULT (decl1) == NULL_TREE)
     {
       DECL_RESULT (decl1)
@@ -11037,6 +11148,20 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
       TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (restype);
     }
 
+    /* Allocate further tree nodes temporarily during compilation
+       of this function only.  Tiemann moved up here from bottom of fn.  */
+    temporary_allocation ();
+
+  if (current_template_parms)
+    {
+      extern tree last_tree;
+      ++minimal_parse_mode;
+      last_tree = DECL_SAVED_TREE (decl1)
+       = build_nt (EXPR_STMT, void_zero_node);
+    }
+
+  ++function_depth;
+
   if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1))
       && DECL_LANGUAGE (decl1) == lang_cplusplus)
     {
@@ -11050,11 +11175,6 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
        ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
     }
 
-  /* If this fcn was already referenced via a block-scope `extern' decl
-     (or an implicit decl), propagate certain information about the usage.  */
-  if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl1)))
-    TREE_ADDRESSABLE (decl1) = 1;
-
   return 1;
 }
 \f
@@ -11130,12 +11250,13 @@ store_parm_decls ()
       /* Must clear this because it might contain TYPE_DECLs declared
         at class level.  */
       storedecls (NULL_TREE);
+
       for (parm = nreverse (specparms); parm; parm = next)
        {
          next = TREE_CHAIN (parm);
          if (TREE_CODE (parm) == PARM_DECL)
            {
-             tree cleanup = maybe_build_cleanup (parm);
+             tree cleanup;
              if (DECL_NAME (parm) == NULL_TREE)
                {
                  pushdecl (parm);
@@ -11163,7 +11284,8 @@ store_parm_decls ()
 
                  pushdecl (parm);
                }
-             if (cleanup)
+             if (! current_template_parms
+                 && (cleanup = maybe_build_cleanup (parm), cleanup))
                {
                  expand_decl (parm);
                  if (! cp_expand_decl_cleanup (parm, cleanup))
@@ -11200,7 +11322,8 @@ store_parm_decls ()
 
   /* Initialize the RTL code for the function.  */
   DECL_SAVED_INSNS (fndecl) = NULL_RTX;
-  expand_function_start (fndecl, parms_have_cleanups);
+  if (! current_template_parms)
+    expand_function_start (fndecl, parms_have_cleanups);
 
   /* Create a binding contour which can be used to catch
      cleanup-generated temporaries.  Also, if the return value needs or
@@ -11224,7 +11347,7 @@ store_parm_decls ()
     }
 
   /* Take care of exception handling things. */
-  if (flag_handle_exceptions)
+  if (! current_template_parms && flag_handle_exceptions)
     {
       rtx insns;
       start_sequence ();
@@ -11327,6 +11450,9 @@ finish_function (lineno, call_poplevel, nested)
   if (fndecl == NULL_TREE)
     return;
 
+  if (! nested && decl_function_context (fndecl) != NULL_TREE)
+    nested = 1;
+
   fntype = TREE_TYPE (fndecl);
 
 /*  TREE_READONLY (fndecl) = 1;
@@ -11340,218 +11466,307 @@ finish_function (lineno, call_poplevel, nested)
       store_parm_decls ();
     }
 
-  if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/)
+  if (current_template_parms)
     {
-      tree ttype = target_type (fntype);
-      tree parmdecl;
-
-      if (IS_AGGR_TYPE (ttype))
-       /* Let debugger know it should output info for this type.  */
-       note_debug_info_needed (ttype);
-
-      for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
+      if (DECL_CONSTRUCTOR_P (fndecl) && call_poplevel)
+       {
+         decls = getdecls ();
+         expand_end_bindings (decls, decls != NULL_TREE, 0);
+         poplevel (decls != NULL_TREE, 0, 0);
+       }
+    }
+  else
+    {
+      if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/)
        {
-         ttype = target_type (TREE_TYPE (parmdecl));
+         tree ttype = target_type (fntype);
+         tree parmdecl;
+
          if (IS_AGGR_TYPE (ttype))
            /* Let debugger know it should output info for this type.  */
            note_debug_info_needed (ttype);
+
+         for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
+           {
+             ttype = target_type (TREE_TYPE (parmdecl));
+             if (IS_AGGR_TYPE (ttype))
+               /* Let debugger know it should output info for this type.  */
+               note_debug_info_needed (ttype);
+           }
        }
-    }
 
-  /* Clean house because we will need to reorder insns here.  */
-  do_pending_stack_adjust ();
+      /* Clean house because we will need to reorder insns here.  */
+      do_pending_stack_adjust ();
 
-  if (dtor_label)
-    {
-      tree binfo = TYPE_BINFO (current_class_type);
-      tree cond = integer_one_node;
-      tree exprstmt, vfields;
-      tree in_charge_node = lookup_name (in_charge_identifier, 0);
-      tree virtual_size;
-      int ok_to_optimize_dtor = 0;
-      int empty_dtor = get_last_insn () == last_dtor_insn;
-
-      if (current_function_assigns_this)
-       cond = build (NE_EXPR, boolean_type_node,
-                     current_class_decl, integer_zero_node);
-      else
+      if (dtor_label)
        {
-         int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
+         tree binfo = TYPE_BINFO (current_class_type);
+         tree cond = integer_one_node;
+         tree exprstmt;
+         tree in_charge_node = lookup_name (in_charge_identifier, 0);
+         tree virtual_size;
+         int ok_to_optimize_dtor = 0;
+         int empty_dtor = get_last_insn () == last_dtor_insn;
 
-         /* If this destructor is empty, then we don't need to check
-            whether `this' is NULL in some cases.  */
-         if ((flag_this_is_variable & 1) == 0)
-           ok_to_optimize_dtor = 1;
-         else if (empty_dtor)
-           ok_to_optimize_dtor
-             = (n_baseclasses == 0
-                || (n_baseclasses == 1
-                    && TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0))));
-       }
+         if (current_function_assigns_this)
+           cond = build (NE_EXPR, boolean_type_node,
+                         current_class_decl, integer_zero_node);
+         else
+           {
+             int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
+
+             /* If this destructor is empty, then we don't need to check
+                whether `this' is NULL in some cases.  */
+             if ((flag_this_is_variable & 1) == 0)
+               ok_to_optimize_dtor = 1;
+             else if (empty_dtor)
+               ok_to_optimize_dtor
+                 = (n_baseclasses == 0
+                    || (n_baseclasses == 1
+                        && TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0))));
+           }
 
-      /* These initializations might go inline.  Protect
-        the binding level of the parms.  */
-      pushlevel (0);
-      expand_start_bindings (0);
+         /* These initializations might go inline.  Protect
+            the binding level of the parms.  */
+         pushlevel (0);
+         expand_start_bindings (0);
 
-      if (current_function_assigns_this)
-       {
-         current_function_assigns_this = 0;
-         current_function_just_assigned_this = 0;
-       }
+         if (current_function_assigns_this)
+           {
+             current_function_assigns_this = 0;
+             current_function_just_assigned_this = 0;
+           }
 
-      /* Generate the code to call destructor on base class.
-        If this destructor belongs to a class with virtual
-        functions, then set the virtual function table
-        pointer to represent the type of our base class.  */
+         /* Generate the code to call destructor on base class.
+            If this destructor belongs to a class with virtual
+            functions, then set the virtual function table
+            pointer to represent the type of our base class.  */
 
-      /* This side-effect makes call to `build_delete' generate the
-        code we have to have at the end of this destructor.  */
-      TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
+         /* This side-effect makes call to `build_delete' generate the
+            code we have to have at the end of this destructor.  */
+         TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
 
-      /* These are two cases where we cannot delegate deletion.  */
-      if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
-         || TYPE_GETS_REG_DELETE (current_class_type))
-       exprstmt = build_delete (current_class_type, C_C_D, integer_zero_node,
-                                LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
-      else
-       exprstmt = build_delete (current_class_type, C_C_D, in_charge_node,
-                                LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
-
-      /* If we did not assign to this, then `this' is non-zero at
-        the end of a destructor.  As a special optimization, don't
-        emit test if this is an empty destructor.  If it does nothing,
-        it does nothing.  If it calls a base destructor, the base
-        destructor will perform the test.  */
-
-      if (exprstmt != error_mark_node
-         && (TREE_CODE (exprstmt) != NOP_EXPR
-             || TREE_OPERAND (exprstmt, 0) != integer_zero_node
-             || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)))
-       {
-         expand_label (dtor_label);
-         if (cond != integer_one_node)
-           expand_start_cond (cond, 0);
-         if (exprstmt != void_zero_node)
-           /* Don't call `expand_expr_stmt' if we're not going to do
-              anything, since -Wall will give a diagnostic.  */
-           expand_expr_stmt (exprstmt);
-
-         /* Run destructor on all virtual baseclasses.  */
-         if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+         /* These are two cases where we cannot delegate deletion.  */
+         if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
+             || TYPE_GETS_REG_DELETE (current_class_type))
+           exprstmt = build_delete (current_class_type, C_C_D, integer_zero_node,
+                                    LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
+         else
+           exprstmt = build_delete (current_class_type, C_C_D, in_charge_node,
+                                    LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
+
+         /* If we did not assign to this, then `this' is non-zero at
+            the end of a destructor.  As a special optimization, don't
+            emit test if this is an empty destructor.  If it does nothing,
+            it does nothing.  If it calls a base destructor, the base
+            destructor will perform the test.  */
+
+         if (exprstmt != error_mark_node
+             && (TREE_CODE (exprstmt) != NOP_EXPR
+                 || TREE_OPERAND (exprstmt, 0) != integer_zero_node
+                 || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)))
            {
-             tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
-             expand_start_cond (build (BIT_AND_EXPR, integer_type_node,
-                                       in_charge_node, integer_two_node), 0);
-             while (vbases)
+             expand_label (dtor_label);
+             if (cond != integer_one_node)
+               expand_start_cond (cond, 0);
+             if (exprstmt != void_zero_node)
+               /* Don't call `expand_expr_stmt' if we're not going to do
+                  anything, since -Wall will give a diagnostic.  */
+               expand_expr_stmt (exprstmt);
+
+             /* Run destructor on all virtual baseclasses.  */
+             if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
                {
-                 if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
+                 tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
+                 expand_start_cond (build (BIT_AND_EXPR, integer_type_node,
+                                           in_charge_node, integer_two_node), 0);
+                 while (vbases)
                    {
-                     tree ptr = convert_pointer_to_vbase (BINFO_TYPE (vbases), current_class_decl);
-                     expand_expr_stmt (build_delete (build_pointer_type (BINFO_TYPE (vbases)),
-                                                     ptr, integer_zero_node,
-                                                     LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0));
+                     if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
+                       {
+                         tree ptr = convert_pointer_to_vbase (BINFO_TYPE (vbases), current_class_decl);
+                         expand_expr_stmt (build_delete (build_pointer_type (BINFO_TYPE (vbases)),
+                                                         ptr, integer_zero_node,
+                                                         LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0));
+                       }
+                     vbases = TREE_CHAIN (vbases);
                    }
-                 vbases = TREE_CHAIN (vbases);
+                 expand_end_cond ();
                }
-             expand_end_cond ();
+
+             do_pending_stack_adjust ();
+             if (cond != integer_one_node)
+               expand_end_cond ();
            }
 
-         do_pending_stack_adjust ();
-         if (cond != integer_one_node)
-           expand_end_cond ();
-       }
+         TYPE_HAS_DESTRUCTOR (current_class_type) = 1;
+
+         virtual_size = c_sizeof (current_class_type);
+
+         /* At the end, call delete if that's what's requested.  */
+         if (TYPE_GETS_REG_DELETE (current_class_type))
+           /* This NOP_EXPR means we are in a static call context.  */
+           exprstmt =
+             build_method_call
+               (build_indirect_ref
+                (build1 (NOP_EXPR, build_pointer_type (current_class_type),
+                         error_mark_node),
+                 NULL_PTR),
+                ansi_opname[(int) DELETE_EXPR],
+                tree_cons (NULL_TREE, current_class_decl,
+                           build_tree_list (NULL_TREE, virtual_size)),
+                NULL_TREE, LOOKUP_NORMAL);
+         else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+           exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0,
+                                      virtual_size);
+         else
+           exprstmt = NULL_TREE;
 
-      TYPE_HAS_DESTRUCTOR (current_class_type) = 1;
-
-      virtual_size = c_sizeof (current_class_type);
-
-      /* At the end, call delete if that's what's requested.  */
-      if (TYPE_GETS_REG_DELETE (current_class_type))
-       /* This NOP_EXPR means we are in a static call context.  */
-       exprstmt =
-         build_method_call
-           (build_indirect_ref
-            (build1 (NOP_EXPR, build_pointer_type (current_class_type),
-                     error_mark_node),
-             NULL_PTR),
-            ansi_opname[(int) DELETE_EXPR],
-            tree_cons (NULL_TREE, current_class_decl,
-                       build_tree_list (NULL_TREE, virtual_size)),
-            NULL_TREE, LOOKUP_NORMAL);
-      else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
-       exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0,
-                                  virtual_size);
-      else
-       exprstmt = NULL_TREE;
+         if (exprstmt)
+           {
+             cond = build (BIT_AND_EXPR, integer_type_node,
+                           in_charge_node, integer_one_node);
+             expand_start_cond (cond, 0);
+             expand_expr_stmt (exprstmt);
+             expand_end_cond ();
+           }
 
-      if (exprstmt)
-       {
-         cond = build (BIT_AND_EXPR, integer_type_node,
-                       in_charge_node, integer_one_node);
-         expand_start_cond (cond, 0);
-         expand_expr_stmt (exprstmt);
-         expand_end_cond ();
-       }
+         /* End of destructor.  */
+         expand_end_bindings (NULL_TREE, getdecls() != NULL_TREE, 0);
+         poplevel (2, 0, 0);   /* XXX change to 1 */
+
+         /* Back to the top of destructor.  */
+         /* Dont execute destructor code if `this' is NULL.  */
+
+         start_sequence ();
+
+         /* If the dtor is empty, and we know there is not possible way we
+            could use any vtable entries, before they are possibly set by
+            a base class dtor, we don't have to setup the vtables, as we
+            know that any base class dtoring will set up any vtables it
+            needs.  We avoid MI, because one base class dtor can do a
+            virtual dispatch to an overridden function that would need to
+            have a non-related vtable set up, we cannot avoid setting up
+            vtables in that case.  We could change this to see if there is
+            just one vtable.  */
+         if (! empty_dtor || TYPE_USES_COMPLEX_INHERITANCE (current_class_type))
+           {
+             /* Make all virtual function table pointers in non-virtual base
+                classes point to CURRENT_CLASS_TYPE's virtual function
+                tables.  */
+             expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_decl);
 
-      /* End of destructor.  */
-      expand_end_bindings (NULL_TREE, getdecls() != NULL_TREE, 0);
-      poplevel (2, 0, 0); /* XXX change to 1 */
+             if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+               expand_indirect_vtbls_init (binfo, C_C_D, current_class_decl);
+           }
+         
+         if (! ok_to_optimize_dtor)
+           {
+             cond = build_binary_op (NE_EXPR,
+                                     current_class_decl, integer_zero_node, 1);
+             expand_start_cond (cond, 0);
+           }
 
-      /* Back to the top of destructor.  */
-      /* Dont execute destructor code if `this' is NULL.  */
+         insns = get_insns ();
+         end_sequence ();
 
-      start_sequence ();
+         last_parm_insn = get_first_nonparm_insn ();
+         if (last_parm_insn == NULL_RTX)
+           last_parm_insn = get_last_insn ();
+         else
+           last_parm_insn = previous_insn (last_parm_insn);
 
-      /* If the dtor is empty, and we know there is not possible way we could
-        use any vtable entries, before they are possibly set by a base class
-        dtor, we don't have to setup the vtables, as we know that any base
-        class dtoring will set up any vtables it needs.  We avoid MI,
-        because one base class dtor can do a virtual dispatch to an
-        overridden function that would need to have a non-related vtable set
-        up, we cannot avoid setting up vtables in that case.  We could
-        change this to see if there is just one vtable.  */
-      if (! empty_dtor || TYPE_USES_COMPLEX_INHERITANCE (current_class_type))
-       {
-         /* Make all virtual function table pointers in non-virtual base
-            classes point to CURRENT_CLASS_TYPE's virtual function
-            tables.  */
-         expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_decl);
+         emit_insns_after (insns, last_parm_insn);
 
-         if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
-           expand_indirect_vtbls_init (binfo, C_C_D, current_class_decl);
+         if (! ok_to_optimize_dtor)
+           expand_end_cond ();
        }
-
-      if (! ok_to_optimize_dtor)
+      else if (current_function_assigns_this)
        {
-         cond = build_binary_op (NE_EXPR,
-                                 current_class_decl, integer_zero_node, 1);
-         expand_start_cond (cond, 0);
+         /* Does not need to call emit_base_init, because
+            that is done (if needed) just after assignment to this
+            is seen.  */
+
+         if (DECL_CONSTRUCTOR_P (current_function_decl))
+           {
+             end_protect_partials ();
+             expand_label (ctor_label);
+             ctor_label = NULL_TREE;
+
+             if (call_poplevel)
+               {
+                 decls = getdecls ();
+                 expand_end_bindings (decls, decls != NULL_TREE, 0);
+                 poplevel (decls != NULL_TREE, 0, 0);
+               }
+             c_expand_return (current_class_decl);
+           }
+         else if (TYPE_MAIN_VARIANT (TREE_TYPE (
+                                                DECL_RESULT (current_function_decl))) != void_type_node
+                  && return_label != NULL_RTX)
+           no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+
+         current_function_assigns_this = 0;
+         current_function_just_assigned_this = 0;
+         base_init_expr = NULL_TREE;
        }
+      else if (DECL_CONSTRUCTOR_P (fndecl))
+       {
+         tree cond, thenclause;
+         /* Allow constructor for a type to get a new instance of the object
+            using `build_new'.  */
+         tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type);
+         CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE;
 
-      insns = get_insns ();
-      end_sequence ();
+         DECL_RETURNS_FIRST_ARG (fndecl) = 1;
 
-      last_parm_insn = get_first_nonparm_insn ();
-      if (last_parm_insn == NULL_RTX)
-       last_parm_insn = get_last_insn ();
-      else
-       last_parm_insn = previous_insn (last_parm_insn);
+         if (flag_this_is_variable > 0)
+           {
+             cond = build_binary_op (EQ_EXPR,
+                                     current_class_decl, integer_zero_node, 1);
+             thenclause = build_modify_expr (current_class_decl, NOP_EXPR,
+                                             build_new (NULL_TREE, current_class_type, void_type_node, 0));
+           }
 
-      emit_insns_after (insns, last_parm_insn);
+         CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
 
-      if (! ok_to_optimize_dtor)
-       expand_end_cond ();
-    }
-  else if (current_function_assigns_this)
-    {
-      /* Does not need to call emit_base_init, because
-        that is done (if needed) just after assignment to this
-        is seen.  */
+         start_sequence ();
+
+         if (flag_this_is_variable > 0)
+           {
+             expand_start_cond (cond, 0);
+             expand_expr_stmt (thenclause);
+             expand_end_cond ();
+           }
+
+         /* Emit insns from `emit_base_init' which sets up virtual
+            function table pointer(s).  */
+         if (base_init_expr)
+           {
+             expand_expr_stmt (base_init_expr);
+             base_init_expr = NULL_TREE;
+           }
+
+         insns = get_insns ();
+         end_sequence ();
+
+         /* This is where the body of the constructor begins.
+            If there were no insns in this function body, then the
+            last_parm_insn is also the last insn.
+            
+            If optimization is enabled, last_parm_insn may move, so
+            we don't hold on to it (across emit_base_init).  */
+         last_parm_insn = get_first_nonparm_insn ();
+         if (last_parm_insn == NULL_RTX)
+           last_parm_insn = get_last_insn ();
+         else
+           last_parm_insn = previous_insn (last_parm_insn);
+
+         emit_insns_after (insns, last_parm_insn);
 
-      if (DECL_CONSTRUCTOR_P (current_function_decl))
-       {
          end_protect_partials ();
+
+         /* This is where the body of the constructor ends.  */
          expand_label (ctor_label);
          ctor_label = NULL_TREE;
 
@@ -11559,167 +11774,90 @@ finish_function (lineno, call_poplevel, nested)
            {
              decls = getdecls ();
              expand_end_bindings (decls, decls != NULL_TREE, 0);
-             poplevel (decls != NULL_TREE, 0, 0);
+             poplevel (decls != NULL_TREE, 1, 0);
            }
-         c_expand_return (current_class_decl);
-       }
-      else if (TYPE_MAIN_VARIANT (TREE_TYPE (
-                       DECL_RESULT (current_function_decl))) != void_type_node
-              && return_label != NULL_RTX)
-       no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
-      current_function_assigns_this = 0;
-      current_function_just_assigned_this = 0;
-      base_init_expr = NULL_TREE;
-    }
-  else if (DECL_CONSTRUCTOR_P (fndecl))
-    {
-      tree allocated_this;
-      tree cond, thenclause;
-      /* Allow constructor for a type to get a new instance of the object
-        using `build_new'.  */
-      tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type);
-      CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE;
 
-      DECL_RETURNS_FIRST_ARG (fndecl) = 1;
+         c_expand_return (current_class_decl);
 
-      if (flag_this_is_variable > 0)
+         current_function_assigns_this = 0;
+         current_function_just_assigned_this = 0;
+       }
+      else if (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
+              && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")
+              && DECL_CONTEXT (fndecl) == NULL_TREE)
        {
-         cond = build_binary_op (EQ_EXPR,
-                                 current_class_decl, integer_zero_node, 1);
-         thenclause = build_modify_expr (current_class_decl, NOP_EXPR,
-                                         build_new (NULL_TREE, current_class_type, void_type_node, 0));
+         /* Make it so that `main' always returns 0 by default.  */
+#ifdef VMS
+         c_expand_return (integer_one_node);
+#else
+         c_expand_return (integer_zero_node);
+#endif
        }
+      else if (return_label != NULL_RTX
+              && current_function_return_value == NULL_TREE
+              && ! DECL_NAME (DECL_RESULT (current_function_decl)))
+       no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
 
-      CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
-
-      start_sequence ();
-
-      if (flag_this_is_variable > 0)
+      /* If this function is supposed to return a value, ensure that
+        we do not fall into the cleanups by mistake.  The end of our
+        function will look like this:
+        
+        user code (may have return stmt somewhere)
+        goto no_return_label
+        cleanup_label:
+        cleanups
+        goto return_label
+        no_return_label:
+        NOTE_INSN_FUNCTION_END
+        return_label:
+        things for return
+        
+        If the user omits a return stmt in the USER CODE section, we
+        will have a control path which reaches NOTE_INSN_FUNCTION_END.
+        Otherwise, we won't.  */
+      if (no_return_label)
        {
-         expand_start_cond (cond, 0);
-         expand_expr_stmt (thenclause);
-         expand_end_cond ();
+         DECL_CONTEXT (no_return_label) = fndecl;
+         DECL_INITIAL (no_return_label) = error_mark_node;
+         DECL_SOURCE_FILE (no_return_label) = input_filename;
+         DECL_SOURCE_LINE (no_return_label) = lineno;
+         expand_goto (no_return_label);
        }
 
-      /* Emit insns from `emit_base_init' which sets up virtual
-        function table pointer(s).  */
-      if (base_init_expr)
+      if (cleanup_label)
        {
-         expand_expr_stmt (base_init_expr);
-         base_init_expr = NULL_TREE;
+         /* remove the binding contour which is used
+            to catch cleanup-generated temporaries.  */
+         expand_end_bindings (0, 0, 0);
+         poplevel (0, 0, 0);
        }
 
-      insns = get_insns ();
-      end_sequence ();
-
-      /* This is where the body of the constructor begins.
-        If there were no insns in this function body, then the
-        last_parm_insn is also the last insn.
-
-        If optimization is enabled, last_parm_insn may move, so
-        we don't hold on to it (across emit_base_init).  */
-      last_parm_insn = get_first_nonparm_insn ();
-      if (last_parm_insn == NULL_RTX)
-       last_parm_insn = get_last_insn ();
-      else
-       last_parm_insn = previous_insn (last_parm_insn);
-
-      emit_insns_after (insns, last_parm_insn);
-
-      end_protect_partials ();
+      if (cleanup_label)
+       /* Emit label at beginning of cleanup code for parameters.  */
+       emit_label (cleanup_label);
 
-      /* This is where the body of the constructor ends.  */
-      expand_label (ctor_label);
-      ctor_label = NULL_TREE;
+      /* Get return value into register if that's where it's supposed to be.  */
+      if (original_result_rtx)
+       fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx);
 
-      if (call_poplevel)
+      /* Finish building code that will trigger warnings if users forget
+        to make their functions return values.  */
+      if (no_return_label || cleanup_label)
+       emit_jump (return_label);
+      if (no_return_label)
        {
-         decls = getdecls ();
-         expand_end_bindings (decls, decls != NULL_TREE, 0);
-         poplevel (decls != NULL_TREE, 1, 0);
+         /* We don't need to call `expand_*_return' here because we
+            don't need any cleanups here--this path of code is only
+            for error checking purposes.  */
+         expand_label (no_return_label);
        }
 
-      c_expand_return (current_class_decl);
+      /* Generate rtl for function exit.  */
+      expand_function_end (input_filename, lineno, 1);
 
-      current_function_assigns_this = 0;
-      current_function_just_assigned_this = 0;
+      if (flag_handle_exceptions)
+       expand_exception_blocks ();
     }
-  else if (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
-          && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")
-          && DECL_CONTEXT (fndecl) == NULL_TREE)
-    {
-      /* Make it so that `main' always returns 0 by default.  */
-#ifdef VMS
-      c_expand_return (integer_one_node);
-#else
-      c_expand_return (integer_zero_node);
-#endif
-    }
-  else if (return_label != NULL_RTX
-          && current_function_return_value == NULL_TREE
-          && ! DECL_NAME (DECL_RESULT (current_function_decl)))
-    no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
-  /* If this function is supposed to return a value, ensure that
-     we do not fall into the cleanups by mistake.  The end of our
-     function will look like this:
-
-       user code (may have return stmt somewhere)
-       goto no_return_label
-       cleanup_label:
-       cleanups
-       goto return_label
-       no_return_label:
-       NOTE_INSN_FUNCTION_END
-       return_label:
-       things for return
-
-     If the user omits a return stmt in the USER CODE section, we
-     will have a control path which reaches NOTE_INSN_FUNCTION_END.
-     Otherwise, we won't.  */
-  if (no_return_label)
-    {
-      DECL_CONTEXT (no_return_label) = fndecl;
-      DECL_INITIAL (no_return_label) = error_mark_node;
-      DECL_SOURCE_FILE (no_return_label) = input_filename;
-      DECL_SOURCE_LINE (no_return_label) = lineno;
-      expand_goto (no_return_label);
-    }
-
-  if (cleanup_label)
-    {
-      /* remove the binding contour which is used
-        to catch cleanup-generated temporaries.  */
-      expand_end_bindings (0, 0, 0);
-      poplevel (0, 0, 0);
-    }
-
-  if (cleanup_label)
-    /* Emit label at beginning of cleanup code for parameters.  */
-    emit_label (cleanup_label);
-
-  /* Get return value into register if that's where it's supposed to be.  */
-  if (original_result_rtx)
-    fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx);
-
-  /* Finish building code that will trigger warnings if users forget
-     to make their functions return values.  */
-  if (no_return_label || cleanup_label)
-    emit_jump (return_label);
-  if (no_return_label)
-    {
-      /* We don't need to call `expand_*_return' here because we
-        don't need any cleanups here--this path of code is only
-        for error checking purposes.  */
-      expand_label (no_return_label);
-    }
-
-  /* Generate rtl for function exit.  */
-  expand_function_end (input_filename, lineno, 1);
-
-  if (flag_handle_exceptions)
-    expand_exception_blocks ();
 
   /* This must come after expand_function_end because cleanups might
      have declarations (from inline functions) that need to go into
@@ -11752,54 +11890,65 @@ finish_function (lineno, call_poplevel, nested)
      to the FUNCTION_DECL node itself.  */
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
 
-  /* So we can tell if jump_optimize sets it to 1.  */
-  can_reach_end = 0;
+  if (! current_template_parms)
+    {
+      /* So we can tell if jump_optimize sets it to 1.  */
+      can_reach_end = 0;
 
-  /* Run the optimizers and output the assembler code for this function.  */
-  rest_of_compilation (fndecl);
+      /* Run the optimizers and output the assembler code for this function.  */
+      rest_of_compilation (fndecl);
 
-  if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
-    {
-      /* Set DECL_EXTERNAL so that assemble_external will be called as
-         necessary.  We'll clear it again in finish_file.  */
-      if (! DECL_EXTERNAL (fndecl))
-       DECL_NOT_REALLY_EXTERN (fndecl) = 1;
-      DECL_EXTERNAL (fndecl) = 1;
-      mark_inline_for_output (fndecl);
-    }
+      if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
+       {
+         /* Set DECL_EXTERNAL so that assemble_external will be called as
+            necessary.  We'll clear it again in finish_file.  */
+         if (! DECL_EXTERNAL (fndecl))
+           DECL_NOT_REALLY_EXTERN (fndecl) = 1;
+         DECL_EXTERNAL (fndecl) = 1;
+         mark_inline_for_output (fndecl);
+       }
 
-  if (ctype && TREE_ASM_WRITTEN (fndecl))
-    note_debug_info_needed (ctype);
+      if (ctype && TREE_ASM_WRITTEN (fndecl))
+       note_debug_info_needed (ctype);
 
-  current_function_returns_null |= can_reach_end;
+      current_function_returns_null |= can_reach_end;
 
-  /* Since we don't normally go through c_expand_return for constructors,
-     this normally gets the wrong value.
-     Also, named return values have their return codes emitted after
-     NOTE_INSN_FUNCTION_END, confusing jump.c.  */
-  if (DECL_CONSTRUCTOR_P (fndecl)
-      || DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE)
-    current_function_returns_null = 0;
+      /* Since we don't normally go through c_expand_return for constructors,
+        this normally gets the wrong value.
+        Also, named return values have their return codes emitted after
+        NOTE_INSN_FUNCTION_END, confusing jump.c.  */
+      if (DECL_CONSTRUCTOR_P (fndecl)
+         || DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE)
+       current_function_returns_null = 0;
 
-  if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
-    cp_warning ("`noreturn' function `%D' does return", fndecl);
-  else if ((warn_return_type || pedantic)
-          && current_function_returns_null
-          && TYPE_MAIN_VARIANT (TREE_TYPE (fntype)) != void_type_node)
-    {
-      /* If this function returns non-void and control can drop through,
-        complain.  */
-      cp_pedwarn ("control reaches end of non-void function `%D'", fndecl);
+      if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
+       cp_warning ("`noreturn' function `%D' does return", fndecl);
+      else if ((warn_return_type || pedantic)
+              && current_function_returns_null
+              && TYPE_MAIN_VARIANT (TREE_TYPE (fntype)) != void_type_node)
+       {
+         /* If this function returns non-void and control can drop through,
+            complain.  */
+         cp_pedwarn ("control reaches end of non-void function `%D'", fndecl);
+       }
+      /* With just -W, complain only if function returns both with
+        and without a value.  */
+      else if (extra_warnings
+              && current_function_returns_value && current_function_returns_null)
+       warning ("this function may return with or without a value");
     }
-  /* With just -W, complain only if function returns both with
-     and without a value.  */
-  else if (extra_warnings
-          && current_function_returns_value && current_function_returns_null)
-    warning ("this function may return with or without a value");
+
+  --function_depth;
 
   /* Free all the tree nodes making up this function.  */
   /* Switch back to allocating nodes permanently
      until we start another function.  */
+  if (current_template_parms)
+    {
+      --minimal_parse_mode;
+      DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
+    }
+
   if (! nested)
     permanent_allocation (1);
 
@@ -11809,9 +11958,14 @@ finish_function (lineno, call_poplevel, nested)
       /* But DECL_INITIAL must remain nonzero so we know this
         was an actual function definition.  */
       DECL_INITIAL (fndecl) = error_mark_node;
-      if (! DECL_CONSTRUCTOR_P (fndecl)
-         || !TYPE_USES_VIRTUAL_BASECLASSES (TYPE_METHOD_BASETYPE (fntype)))
-       DECL_ARGUMENTS (fndecl) = NULL_TREE;
+      /* And we need the arguments for template instantiation.  */
+      if (! current_template_parms)
+       {
+         if (! DECL_CONSTRUCTOR_P (fndecl)
+             || !(TYPE_USES_VIRTUAL_BASECLASSES
+                  (TYPE_METHOD_BASETYPE (fntype))))
+           DECL_ARGUMENTS (fndecl) = NULL_TREE;
+       }
     }
 
   if (DECL_STATIC_CONSTRUCTOR (fndecl))
@@ -11895,11 +12049,8 @@ start_method (declspecs, declarator, raises)
   if (flag_default_inline)
     DECL_INLINE (fndecl) = 1;
 
-  if (processing_template_defn)
-    {
-      SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
-      repo_template_used (fndecl);
-    }
+  if (current_template_parms && ! current_function_decl)
+    push_template_decl (fndecl);
 
   /* We read in the parameters on the maybepermanent_obstack,
      but we won't be getting back to them until after we
@@ -12001,8 +12152,7 @@ finish_method (decl)
   GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
                      (HOST_WIDE_INT) current_binding_level->level_chain,
                      current_binding_level->parm_flag,
-                     current_binding_level->keep,
-                     current_binding_level->tag_transparent);
+                     current_binding_level->keep);
 
   poplevel (0, 0, 0);
 
@@ -12139,6 +12289,12 @@ cplus_expand_expr_stmt (exp)
   push_temp_slots ();
   target_temp_slot_level = temp_slot_level;
 
+  if (current_template_parms)
+    {
+      add_tree (build_min_nt (EXPR_STMT, exp));
+      return;
+    }
+
   if (TREE_TYPE (exp) == unknown_type_node)
     {
       if (TREE_CODE (exp) == ADDR_EXPR || TREE_CODE (exp) == TREE_LIST)
@@ -12148,8 +12304,6 @@ cplus_expand_expr_stmt (exp)
     }
   else
     {
-      int remove_implicit_immediately = 0;
-
       if (TREE_CODE (exp) == FUNCTION_DECL)
        {
          cp_warning ("reference, not call, to function `%D'", exp);
@@ -12364,6 +12518,12 @@ pop_cp_function_context (context)
   free (p);
 }
 
+int
+in_function_p ()
+{
+  return function_depth != 0;
+}
+
 /* FSF LOCAL dje prefix attributes */
 /* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
    lists.  SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).
index 38af65277f711ba7e818f6644f8ec17e0230ca09..e137f7e6acbc9835b9e4ee459220d182139c3a97 100644 (file)
@@ -40,6 +40,7 @@ Boston, MA 02111-1307, USA.  */
 extern tree get_file_function_name ();
 extern tree cleanups_this_call;
 static void grok_function_init ();
+void import_export_decl ();
 extern int current_class_depth;
 
 /* A list of virtual function tables we must make sure to write out.  */
@@ -67,6 +68,10 @@ static int global_temp_name_counter;
 
 extern int spew_debug;
 
+/* Nonzero if we're done parsing and into end-of-file activities.  */
+
+int at_eof;
+
 /* Functions called along with real static constructors and destructors.  */
 
 tree static_ctors, static_dtors;
@@ -1043,6 +1048,10 @@ grok_array_decl (array_expr, index_exp)
 
   if (type == error_mark_node || index_exp == error_mark_node)
     return error_mark_node;
+  if (current_template_parms)
+    return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE,
+                     array_expr, index_exp);
+
   if (type == NULL_TREE)
     {
       /* Something has gone very wrong.  Assume we are mistakenly reducing
@@ -1057,7 +1066,7 @@ grok_array_decl (array_expr, index_exp)
 
   /* If they have an `operator[]', use that.  */
   if (TYPE_LANG_SPECIFIC (type)
-      && TYPE_OVERLOADS_ARRAY_REF (type))
+      && TYPE_OVERLOADS_ARRAY_REF (complete_type (type)))
     return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
                           array_expr, index_exp, NULL_TREE);
 
@@ -1108,14 +1117,24 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
      tree exp, size;
      int doing_vec, use_global_delete;
 {
-  tree t = stabilize_reference (convert_from_reference (exp));
-  tree type = TREE_TYPE (t);
-  enum tree_code code = TREE_CODE (type);
+  tree t;
+  tree type;
+  enum tree_code code;
   /* For a regular vector delete (aka, no size argument) we will pass
      this down as a NULL_TREE into build_vec_delete.  */
   tree maxindex = NULL_TREE;
-  /* This is used for deleting arrays.  */
-  tree elt_size;
+
+  if (current_template_parms)
+    {
+      t = build_min (DELETE_EXPR, void_type_node, exp, size);
+      DELETE_EXPR_USE_GLOBAL (t) = use_global_delete;
+      DELETE_EXPR_USE_VEC (t) = doing_vec;
+      return t;
+    }
+
+  t = stabilize_reference (convert_from_reference (exp));
+  type = TREE_TYPE (t);
+  code = TREE_CODE (type);
 
   switch (doing_vec)
     {
@@ -1125,7 +1144,6 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
        pedwarn ("anachronistic use of array size in vector delete");
       /* Fall through.  */
     case 1:
-      elt_size = c_sizeof (type);
       break;
     default:
       if (code != POINTER_TYPE)
@@ -1174,7 +1192,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
 #endif
 
   if (doing_vec)
-    return build_vec_delete (t, maxindex, elt_size, integer_one_node,
+    return build_vec_delete (t, maxindex, integer_one_node,
                             integer_two_node, use_global_delete);
   else
     {
@@ -1200,12 +1218,12 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
    CNAME is the same here as it is for grokclassfn above.  */
 
 tree
-check_classfn (ctype, cname, function)
-     tree ctype, cname, function;
+check_classfn (ctype, function)
+     tree ctype, function;
 {
   tree fn_name = DECL_NAME (function);
   tree fndecl;
-  tree method_vec = CLASSTYPE_METHOD_VEC (ctype);
+  tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
   tree *methods = 0;
   tree *end = 0;
 
@@ -1229,8 +1247,8 @@ check_classfn (ctype, cname, function)
                  if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl))
                    return fndecl;
 #if 0
-                 /* This should work, but causes libg++ to fail
-                    make check-tFix. */
+                 /* 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))
@@ -1250,12 +1268,7 @@ check_classfn (ctype, cname, function)
                      if (comptypes (TREE_TYPE (TREE_TYPE (function)),
                                     TREE_TYPE (TREE_TYPE (fndecl)), 1)
                          && compparms (p1, p2, 3))
-                       {
-                         if (DECL_STATIC_FUNCTION_P (fndecl)
-                             && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
-                           revert_static_member_fn (&function, NULL, NULL);
-                         return fndecl;
-                       }
+                       return fndecl;
                    }
 #endif
                  fndecl = DECL_CHAIN (fndecl);
@@ -1333,7 +1346,9 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
       && TREE_CODE (declarator) == SCOPE_REF)
     {
       /* Access declaration */
-      if (TREE_COMPLEXITY (declarator) == current_class_depth)
+      if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0))))
+       ;
+      else if (TREE_COMPLEXITY (declarator) == current_class_depth)
        pop_nested_class (1);
       return do_class_using_decl (declarator);
     }
@@ -1437,6 +1452,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
               because `decl_const_value' would mis-interpret it
               as only meaning that this VAR_DECL is defined.  */
            init = build1 (NOP_EXPR, TREE_TYPE (value), init);
+         else if (current_template_parms)
+           ;
          else if (! TREE_CONSTANT (init))
            {
              /* We can allow references to things that are effectively
@@ -1456,6 +1473,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
   /* The corresponding pop_obstacks is in cp_finish_decl.  */
   push_obstacks_nochange ();
 
+  if (current_template_parms && ! current_function_decl
+      && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
+    push_template_decl (value);
+
   if (attrlist)
     cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
                           TREE_VALUE (attrlist));
@@ -1476,7 +1497,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
              DECL_ASSEMBLER_NAME (value)
                = build_static_name (current_class_type, DECL_NAME (value));
            }
-         pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics);
+         if (! current_template_parms)
+           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)))
@@ -1495,6 +1517,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
        }
       DECL_INITIAL (value) = init;
       DECL_IN_AGGR_P (value) = 1;
+      DECL_CONTEXT (value) = current_class_type;
+      DECL_CLASS_CONTEXT (value) = current_class_type;
 
       cp_finish_decl (value, init, asmspec_tree, 1, flags);
       pushdecl_class_level (value);
@@ -1600,26 +1624,9 @@ grokbitfield (declarator, declspecs, width)
 
   if (width != error_mark_node)
     {
-      /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs.  */
-      STRIP_NOPS (width);
-
-      /* detect invalid field size.  */
-      if (TREE_CODE (width) == CONST_DECL)
-       width = DECL_INITIAL (width);
-      else if (TREE_READONLY_DECL_P (width))
-       width = decl_constant_value (width);
-      if (TREE_CODE (width) != INTEGER_CST)
-       {
-         cp_error ("structure field `%D' width not an integer constant",
-                     value);
-         DECL_INITIAL (value) = NULL_TREE;
-       }
-      else
-       {
-         constant_expression_warning (width);
-         DECL_INITIAL (value) = width;
-         DECL_BIT_FIELD (value) = 1;
-       }
+      constant_expression_warning (width);
+      DECL_INITIAL (value) = width;
+      DECL_BIT_FIELD (value) = 1;
     }
 
   DECL_IN_AGGR_P (value) = 1;
@@ -1963,9 +1970,7 @@ tree
 constructor_name_full (thing)
      tree thing;
 {
-  if (TREE_CODE (thing) == UNINSTANTIATED_P_TYPE)
-    return DECL_NAME (UPT_TEMPLATE (thing));
-  else if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM)
+  if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM)
     thing = TYPE_NAME (thing);
   else if (IS_AGGR_TYPE_CODE (TREE_CODE (thing)))
     {
@@ -1976,7 +1981,7 @@ constructor_name_full (thing)
     }
   if (TREE_CODE (thing) == TYPE_DECL
       || (TREE_CODE (thing) == TEMPLATE_DECL
-         && DECL_TEMPLATE_IS_CLASS (thing)))
+         && TREE_CODE (DECL_TEMPLATE_RESULT (thing)) == TYPE_DECL))
     thing = DECL_NAME (thing);
   my_friendly_assert (TREE_CODE (thing) == IDENTIFIER_NODE, 197);
   return thing;
@@ -1996,8 +2001,7 @@ constructor_name (thing)
   t = IDENTIFIER_TEMPLATE (thing);
   if (!t)
     return thing;
-  t = TREE_PURPOSE (t);
-  return DECL_NAME (t);
+  return t;
 }
 \f
 /* Cache the value of this class's main virtual function table pointer
@@ -2010,7 +2014,14 @@ setup_vtbl_ptr ()
 
   if (base_init_expr == 0
       && DECL_CONSTRUCTOR_P (current_function_decl))
-    emit_base_init (current_class_type, 0);
+    {
+      if (current_template_parms)
+       add_tree (build_min_nt
+                 (CTOR_INITIALIZER,
+                  current_member_init_list, current_base_init_list));
+      else
+       emit_base_init (current_class_type, 0);
+    }
 }
 
 /* Record the existence of an addressable inline function.  */
@@ -2431,7 +2442,7 @@ mark_vtable_entries (decl)
       TREE_ADDRESSABLE (fn) = 1;
       if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn))
        TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl;
-      assemble_external (fn);
+      mark_used (fn);
     }
 }
 
@@ -2701,10 +2712,10 @@ walk_sigtables (typedecl_fn, vardecl_fn)
 }
 
 /* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an
-   inline function at end-of-file.  */
+   inline function or template instantiation at end-of-file.  */
 
 void
-import_export_inline (decl)
+import_export_decl (decl)
      tree decl;
 {
   if (DECL_INTERFACE_KNOWN (decl))
@@ -2712,12 +2723,17 @@ import_export_inline (decl)
 
   if (DECL_TEMPLATE_INSTANTIATION (decl))
     {
+      DECL_NOT_REALLY_EXTERN (decl) = 1;
       if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
        {
-         if (flag_weak)
-           DECL_WEAK (decl) = 1;
-         else
-           TREE_PUBLIC (decl) = 0;
+         /* For now, leave vars public so multiple defs will break.  */
+         if (TREE_CODE (decl) == FUNCTION_DECL)
+           {
+             if (flag_weak)
+               DECL_WEAK (decl) = 1;
+             else
+               TREE_PUBLIC (decl) = 0;
+           }
        }
       else
        DECL_NOT_REALLY_EXTERN (decl) = 0;
@@ -2767,6 +2783,7 @@ build_cleanup (decl)
 }
 
 extern int parse_time, varconst_time;
+extern tree pending_templates;
 
 #define TIMEVAR(VAR, BODY)    \
 do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0)
@@ -2786,6 +2803,8 @@ finish_file ()
   tree vars;
   int needs_cleaning = 0, needs_messing_up = 0;
 
+  at_eof = 1;
+
   if (flag_detailed_statistics)
     dump_tree_statistics ();
 
@@ -3027,10 +3046,21 @@ finish_file ()
   while (pending_statics)
     {
       tree decl = TREE_VALUE (pending_statics);
+
+      if (DECL_TEMPLATE_INSTANTIATION (decl)
+         && ! DECL_IN_AGGR_P (decl))
+       {
+         import_export_decl (decl);
+         DECL_EXTERNAL (decl) = ! DECL_NOT_REALLY_EXTERN (decl);
+       }
+
       if (TREE_USED (decl) == 1
          || TREE_READONLY (decl) == 0
          || DECL_INITIAL (decl) == 0)
-       rest_of_decl_compilation (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1);
+       {
+         DECL_DEFER_OUTPUT (decl) = 0;
+         rest_of_decl_compilation (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1);
+       }
       pending_statics = TREE_CHAIN (pending_statics);
     }
 
@@ -3043,10 +3073,15 @@ finish_file ()
   if (flag_handle_signatures)
     walk_sigtables ((void (*)())0, finish_sigtable_vardecl);
 
+  for (fnname = pending_templates; fnname; fnname = TREE_CHAIN (fnname))
+    {
+      tree decl = TREE_VALUE (fnname);
+      instantiate_decl (decl);
+    }
   for (fnname = saved_inlines; fnname; fnname = TREE_CHAIN (fnname))
     {
       tree decl = TREE_VALUE (fnname);
-      import_export_inline (decl);
+      import_export_decl (decl);
       if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
          && TREE_PUBLIC (decl) && ! DECL_WEAK (decl)
          && DECL_NOT_REALLY_EXTERN (decl))
@@ -3229,47 +3264,222 @@ reparse_absdcl_as_casts (decl, expr)
   return expr;
 }
 
-/* Recursive helper function for reparse_decl_as_expr.  It may be a good
-   idea to reimplement this using an explicit stack, rather than recursion. */
-static tree
-reparse_decl_as_expr1 (decl)
-     tree decl;
+/* Given plain tree nodes for an expression, build up the full semantics. */
+
+tree
+build_expr_from_tree (t)
+     tree t;
 {
-  switch (TREE_CODE (decl))
+  if (t == NULL_TREE || t == error_mark_node)
+    return t;
+
+  switch (TREE_CODE (t))
     {
     case IDENTIFIER_NODE:
-      return do_identifier (decl);
+      return do_identifier (t, 0);
+
+    case LOOKUP_EXPR:
+      if (LOOKUP_EXPR_GLOBAL (t))
+       return do_scoped_id (TREE_OPERAND (t, 0), 0);
+      else
+       return do_identifier (TREE_OPERAND (t, 0), 0);
+
     case INDIRECT_REF:
       return build_x_indirect_ref
-       (reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)), "unary *");
-    case ADDR_EXPR:
-      return build_x_unary_op (ADDR_EXPR,
-                              reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)));
+       (build_expr_from_tree (TREE_OPERAND (t, 0)), "unary *");
+
+    case CAST_EXPR:
+      return build_functional_cast
+       (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+    case REINTERPRET_CAST_EXPR:
+      return build_reinterpret_cast
+       (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case NEGATE_EXPR:
     case BIT_NOT_EXPR:
-      return build_x_unary_op (BIT_NOT_EXPR,
-                              reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)));
+    case ABS_EXPR:
+    case TRUTH_NOT_EXPR:
+    case ADDR_EXPR:
+    case CONVERT_EXPR:      /* Unary + */
+      return build_x_unary_op (TREE_CODE (t),
+                              build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case BIT_AND_EXPR:
+    case BIT_ANDTC_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case TRUNC_MOD_EXPR:
+    case FLOOR_MOD_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+    case RSHIFT_EXPR:
+    case LSHIFT_EXPR:
+    case RROTATE_EXPR:
+    case LROTATE_EXPR:
+    case EQ_EXPR:
+    case NE_EXPR:
+    case MAX_EXPR:
+    case MIN_EXPR:
+    case LE_EXPR:
+    case GE_EXPR:
+    case LT_EXPR:
+    case GT_EXPR:
+    case MEMBER_REF:
+      return build_x_binary_op
+       (TREE_CODE (t), 
+        build_expr_from_tree (TREE_OPERAND (t, 0)),
+        build_expr_from_tree (TREE_OPERAND (t, 1)));
+
+    case DOTSTAR_EXPR:
+      return build_m_component_ref
+       (build_expr_from_tree (TREE_OPERAND (t, 0)),
+        build_expr_from_tree (TREE_OPERAND (t, 1)));
+
     case SCOPE_REF:
-      return build_offset_ref (TREE_OPERAND (decl, 0), TREE_OPERAND (decl, 1));
+      return build_offset_ref (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
+
     case ARRAY_REF:
-      return grok_array_decl (reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)),
-                             TREE_OPERAND (decl, 1));
+      if (TREE_OPERAND (t, 0) == NULL_TREE)
+       /* new-type-id */
+       return build_parse_node (ARRAY_REF, NULL_TREE,
+                                build_expr_from_tree (TREE_OPERAND (t, 1)));
+      return grok_array_decl (build_expr_from_tree (TREE_OPERAND (t, 0)),
+                             build_expr_from_tree (TREE_OPERAND (t, 1)));
+
+    case SIZEOF_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);
+      }
+
+    case MODOP_EXPR:
+      return build_x_modify_expr
+       (build_expr_from_tree (TREE_OPERAND (t, 0)),
+        TREE_CODE (TREE_OPERAND (t, 1)),
+        build_expr_from_tree (TREE_OPERAND (t, 2)));
+
+    case ARROW_EXPR:
+      return build_x_arrow
+       (build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+    case NEW_EXPR:
+      return build_new
+       (build_expr_from_tree (TREE_OPERAND (t, 0)),
+        build_expr_from_tree (TREE_OPERAND (t, 1)),
+        build_expr_from_tree (TREE_OPERAND (t, 2)),
+        NEW_EXPR_USE_GLOBAL (t));
+
+    case DELETE_EXPR:
+      return delete_sanity
+       (build_expr_from_tree (TREE_OPERAND (t, 0)),
+        build_expr_from_tree (TREE_OPERAND (t, 1)),
+        DELETE_EXPR_USE_VEC (t), DELETE_EXPR_USE_GLOBAL (t));
+
+    case COMPOUND_EXPR:
+      if (TREE_OPERAND (t, 1) == NULL_TREE)
+       return build_x_compound_expr
+         (build_expr_from_tree (TREE_OPERAND (t, 0)));
+      else
+       my_friendly_abort (42);
+
+    case METHOD_CALL_EXPR:
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
+       {
+         tree ref = TREE_OPERAND (t, 0);
+         return build_scoped_method_call
+           (build_expr_from_tree (TREE_OPERAND (t, 1)),
+            build_expr_from_tree (TREE_OPERAND (ref, 0)),
+            TREE_OPERAND (ref, 1),
+            build_expr_from_tree (TREE_OPERAND (t, 2)));
+       }
+      return build_method_call
+       (build_expr_from_tree (TREE_OPERAND (t, 1)),
+        TREE_OPERAND (t, 0),
+        build_expr_from_tree (TREE_OPERAND (t, 2)),
+        NULL_TREE, LOOKUP_NORMAL);
+
+    case CALL_EXPR:
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
+       {
+         tree ref = TREE_OPERAND (t, 0);
+         return build_member_call
+           (build_expr_from_tree (TREE_OPERAND (ref, 0)),
+            TREE_OPERAND (ref, 1),
+            build_expr_from_tree (TREE_OPERAND (t, 1)));
+       }
+      else
+       {
+         tree name = TREE_OPERAND (t, 0);
+         if (! really_overloaded_fn (name))
+           name = build_expr_from_tree (name);
+         return build_x_function_call
+           (name, build_expr_from_tree (TREE_OPERAND (t, 1)),
+            current_class_decl);
+       }
+
+    case COND_EXPR:
+      return build_x_conditional_expr
+       (build_expr_from_tree (TREE_OPERAND (t, 0)),
+        build_expr_from_tree (TREE_OPERAND (t, 1)),
+        build_expr_from_tree (TREE_OPERAND (t, 2)));
+
+    case TREE_LIST:
+      {
+       tree purpose, value, chain;
+
+       if (t == void_list_node)
+         return t;
+
+       purpose = TREE_PURPOSE (t);
+       if (purpose)
+         purpose = build_expr_from_tree (purpose);
+       value = TREE_VALUE (t);
+       if (value)
+         value = build_expr_from_tree (value);
+       chain = TREE_CHAIN (t);
+       if (chain && chain != void_type_node)
+         chain = build_expr_from_tree (chain);
+       return tree_cons (purpose, value, chain);
+      }
+
+    case COMPONENT_REF:
+      return build_component_ref
+       (build_expr_from_tree (TREE_OPERAND (t, 0)),
+        TREE_OPERAND (t, 1), NULL_TREE, 1);
+
     default:
-      my_friendly_abort (5);
-      return NULL_TREE;
+      return t;
     }
 }
 
 /* This is something of the form `int (*a)++' that has turned out to be an
    expr.  It was only converted into parse nodes, so we need to go through
    and build up the semantics.  Most of the work is done by
-   reparse_decl_as_expr1, above.
+   build_expr_from_tree, above.
 
    In the above example, TYPE is `int' and DECL is `*a'.  */
 tree
 reparse_decl_as_expr (type, decl)
      tree type, decl;
 {
-  decl = reparse_decl_as_expr1 (decl);
+  decl = build_expr_from_tree (decl);
   if (type)
     return build_functional_cast (type, build_tree_list (NULL_TREE, decl));
   else
@@ -3319,20 +3529,13 @@ check_cp_case_value (value)
   if (value == NULL_TREE)
     return value;
 
-  /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.
-     Strip such NOP_EXPRs.  */
-  if (TREE_CODE (value) == NOP_EXPR
-      && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
-    value = TREE_OPERAND (value, 0);
+  /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
+  STRIP_TYPE_NOPS (value);
 
   if (TREE_READONLY_DECL_P (value))
     {
       value = decl_constant_value (value);
-      /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.
-        Strip such NOP_EXPRs.  */
-      if (TREE_CODE (value) == NOP_EXPR
-         && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
-       value = TREE_OPERAND (value, 0);
+      STRIP_TYPE_NOPS (value);
     }
   value = fold (value);
 
@@ -3431,7 +3634,7 @@ do_class_using_decl (decl)
       return NULL_TREE;
     }
 
-  value = build_lang_field_decl (USING_DECL, name, unknown_type_node);
+  value = build_lang_field_decl (USING_DECL, name, void_type_node);
   DECL_INITIAL (value) = TREE_OPERAND (decl, 0);
   return value;
 }
@@ -3466,5 +3669,9 @@ mark_used (decl)
      tree decl;
 {
   TREE_USED (decl) = 1;
+  if (current_template_parms)
+    return;
   assemble_external (decl);
+  if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
+    instantiate_decl (decl);
 }
index 6c7a83821341d9e419fe48e6dbb728e1804070aa..3c1d9a2e959bd1c6b85c9260303e326232887666 100644 (file)
@@ -212,11 +212,6 @@ dump_type (t, v)
       OB_PUTID (TYPE_IDENTIFIER (t));
       break;
 
-    case UNINSTANTIATED_P_TYPE:
-      OB_PUTID (DECL_NAME (UPT_TEMPLATE (t)));
-      OB_PUTS ("<...>");
-      break;
-
       /* This is not always necessary for pointers and such, but doing this
         reduces code size.  */
     case ARRAY_TYPE:
@@ -230,6 +225,13 @@ dump_type (t, v)
       dump_type_suffix (t, v);
       break;
 
+    case TYPENAME_TYPE:
+      OB_PUTS ("typename ");
+      dump_type (TYPE_CONTEXT (t), 0);
+      OB_PUTS ("::");
+      OB_PUTID (TYPE_IDENTIFIER (t));
+      break;
+
     default:
       sorry ("`%s' not supported by dump_type",
             tree_code_name[(int) TREE_CODE (t)]);
@@ -422,10 +424,10 @@ dump_type_prefix (t, v)
     case TREE_LIST:
     case TYPE_DECL:
     case TREE_VEC:
-    case UNINSTANTIATED_P_TYPE:
     case UNION_TYPE:
     case UNKNOWN_TYPE:
     case VOID_TYPE:
+    case TYPENAME_TYPE:
       dump_type (t, v);
       break;
       
@@ -494,10 +496,10 @@ dump_type_suffix (t, v)
     case TREE_LIST:
     case TYPE_DECL:
     case TREE_VEC:
-    case UNINSTANTIATED_P_TYPE:
     case UNION_TYPE:
     case UNKNOWN_TYPE:
     case VOID_TYPE:
+    case TYPENAME_TYPE:
       break;
 
     default:
@@ -711,11 +713,8 @@ dump_decl (t, v)
          OB_UNPUT (2);
        OB_PUTC2 ('>', ' ');
 
-       if (DECL_TEMPLATE_IS_CLASS (t))
-         {
-           OB_PUTS ("class ");
-           OB_PUTID (DECL_NAME (t));
-         }
+       if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
+         dump_type (TREE_TYPE (t), v);
        else switch (NEXT_CODE (t))
          {
          case METHOD_TYPE:
@@ -734,7 +733,8 @@ dump_decl (t, v)
       break;
 
     case CONST_DECL:
-      if (NEXT_CODE (t) == ENUMERAL_TYPE)
+      if (NEXT_CODE (t) == ENUMERAL_TYPE
+         || TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_CONST_PARM)
        goto general;
       else
        dump_expr (DECL_INITIAL (t), 0);
@@ -1262,6 +1262,27 @@ dump_expr (t, nop)
        break;
       }
 
+    case TEMPLATE_CONST_PARM:
+      {
+       tree r = TREE_VEC_ELT (TREE_VALUE (current_template_parms),
+                              TEMPLATE_CONST_IDX (t));
+       dump_decl (TREE_VALUE (r), -1);
+       break;
+      }
+
+    case IDENTIFIER_NODE:
+      OB_PUTID (t);
+      break;
+
+    case SCOPE_REF:
+      dump_type (TREE_OPERAND (t, 0), 0);
+      OB_PUTS ("::");
+      dump_expr (TREE_OPERAND (t, 1), 0);
+      break;
+
+    case CAST_EXPR:
+      break;                   /* XXX */
+
     case TREE_LIST:
       if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
        {
@@ -1312,8 +1333,8 @@ dump_unary_op (opstring, t, nop)
 }
 
 char *
-fndecl_as_string (cname, fndecl, print_ret_type_p)
-     tree cname, fndecl;
+fndecl_as_string (fndecl, print_ret_type_p)
+     tree fndecl;
      int print_ret_type_p;
 {
   return decl_as_string (fndecl, print_ret_type_p);
@@ -1389,12 +1410,7 @@ cp_line_of (t)
     t = TREE_TYPE (t);
 
   if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
-    {
-      if (IS_AGGR_TYPE (t))
-       line = CLASSTYPE_SOURCE_LINE (t);
-      else
-       line = DECL_SOURCE_LINE (TYPE_NAME (t));
-    }
+    line = DECL_SOURCE_LINE (TYPE_NAME (t));
   else
     line = DECL_SOURCE_LINE (t);
 
index 2fd5e6e6e99c1f01150b21af427bfdf4a6ddace5..71421ccc8faeb59ba3d153b2eb76878191160ecc 100644 (file)
@@ -37,6 +37,7 @@ tree protect_list;
 
 extern void (*interim_eh_hook) PROTO((tree));
 rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
+static void end_eh_unwinder PROTO((rtx));
 
 /* holds the fndecl for __builtin_return_address () */
 tree builtin_return_address_fndecl;
@@ -90,8 +91,6 @@ output_exception_table_entry (file, start_label, end_label, eh_label)
      FILE *file;
      rtx start_label, end_label, eh_label;
 {
-  char label[100];
-
   assemble_integer (start_label, GET_MODE_SIZE (Pmode), 1);
   assemble_integer (end_label, GET_MODE_SIZE (Pmode), 1);
   assemble_integer (eh_label, GET_MODE_SIZE (Pmode), 1);
@@ -146,7 +145,7 @@ asm (TEXT_SECTION_ASM_OP);
 
 #endif
 
-void
+static void
 exception_section ()
 {
 #ifdef ASM_OUTPUT_SECTION_NAME
@@ -320,15 +319,15 @@ struct ehQueue {
    ========================================================================= */
 
 /* Holds the pc for doing "throw" */
-tree saved_pc;
+static tree saved_pc;
 /* Holds the type of the thing being thrown. */
-tree saved_throw_type;
+static tree saved_throw_type;
 /* Holds the value being thrown.  */
-tree saved_throw_value;
+static tree saved_throw_value;
 /* Holds the cleanup for the value being thrown.  */
-tree saved_cleanup;
+static tree saved_cleanup;
 
-int throw_used;
+static int throw_used;
 
 static rtx catch_clauses;
 
@@ -454,7 +453,8 @@ top_label_entry (labelstack)
 /* Push to permanent obstack for rtl generation.
    One level only!  */
 static struct obstack *saved_rtl_obstack;
-void
+
+static void
 push_rtl_perm ()
 {
   extern struct obstack permanent_obstack;
@@ -468,9 +468,7 @@ push_rtl_perm ()
 static void
 pop_rtl_from_perm ()
 {
-  extern struct obstack permanent_obstack;
   extern struct obstack *rtl_obstack;
-  
   rtl_obstack = saved_rtl_obstack;
 }
 
@@ -587,7 +585,7 @@ new_eh_stack (stack)
 }
 
 /* cheesyness to save some typing. returns the return value rtx */
-rtx
+static rtx
 do_function_call (func, params, return_type)
      tree func, params, return_type;
 {
@@ -603,8 +601,6 @@ static void
 expand_internal_throw (pc)
      rtx pc;
 {
-  tree params;
-
   emit_move_insn (DECL_RTL (saved_pc), pc);
 #ifdef JUMP_TO_THROW
   emit_indirect_jump (gen_rtx (SYMBOL_REF, Pmode, "__throw"));
@@ -616,7 +612,7 @@ expand_internal_throw (pc)
 
 /* ========================================================================= */
 
-void
+static void
 lang_interim_eh (finalization)
      tree finalization;
 {
@@ -946,7 +942,7 @@ build_eh_type (exp)
 }
 
 /* This routine creates the cleanup for the exception handling object.  */
-void
+static void
 push_eh_cleanup ()
 {
   /* All cleanups must last longer than normal.  */
@@ -973,7 +969,6 @@ expand_start_catch_block (declspecs, declarator)
   rtx protect_label_rtx;
   tree decl = NULL_TREE;
   tree init;
-  tree cleanup;
 
   if (! doing_eh (1))
     return;
@@ -1243,7 +1238,7 @@ do_unwind (inner_throw_label)
 /* Given the return address, compute the new pc to throw.  This has to
    work for the current frame of the current function, and the one
    above it in the case of throw.  */
-rtx
+static rtx
 eh_outer_context (addr)
      rtx addr;
 {
@@ -1306,8 +1301,6 @@ expand_builtin_throw ()
   rtx return_val_rtx;
   rtx gotta_rethrow_it;
   rtx gotta_call_terminate;
-  rtx unwind_and_throw;
-  rtx goto_unwind_and_throw;
   rtx top_of_loop;
   rtx unwind_first;
   tree t;
@@ -1331,8 +1324,6 @@ expand_builtin_throw ()
 
   gotta_rethrow_it = gen_label_rtx ();
   gotta_call_terminate = gen_label_rtx ();
-  unwind_and_throw = gen_label_rtx ();
-  goto_unwind_and_throw = gen_label_rtx ();
   top_of_loop = gen_label_rtx ();
   unwind_first = gen_label_rtx ();
 
@@ -1421,7 +1412,7 @@ expand_start_eh_spec ()
   start_protect ();
 }
 
-void
+static void
 expand_end_eh_spec (raises)
      tree raises;
 {
@@ -1771,7 +1762,6 @@ emit_exception_table ()
   int count = 0;
   extern FILE *asm_out_file;
   struct ehEntry *entry;
-  tree eh_node_decl;
 
   if (! doing_eh (0))
     return;
@@ -1826,11 +1816,13 @@ build_throw (e)
   return e;
 }
 
+void
 start_eh_unwinder ()
 {
   start_protect ();
 }
 
+static void
 end_eh_unwinder (end)
      rtx end;
 {
index d0d7b494a4ca7b0e19ea7f5026e2e36cc5204cb0..fc59cb6cfa210b6fb4af25c0f99d9d15bb596aa4 100644 (file)
@@ -359,3 +359,85 @@ extract_init (decl, init)
   return 1;
 #endif
 }
+
+void
+do_case (start, end)
+     tree start, end;
+{
+  tree value1 = NULL_TREE, value2 = NULL_TREE, label;
+
+  if (end && pedantic)
+    pedwarn ("ANSI C++ forbids range expressions in switch statement");
+
+  if (current_template_parms)
+    {
+      add_tree (build_min_nt (CASE_LABEL, start, end));
+      return;
+    }
+
+  if (start)
+    value1 = check_cp_case_value (start);
+  if (end)
+    value2 = check_cp_case_value (end);
+  
+  label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+
+  if (value1 != error_mark_node
+      && value2 != error_mark_node)
+    {
+      tree duplicate;
+      int success;
+
+      if (end)
+       success = pushcase_range (value1, value2, convert_and_check,
+                                 label, &duplicate);
+      else if (start)
+       success = pushcase (value1, convert_and_check, label, &duplicate);
+      else
+       success = pushcase (NULL_TREE, 0, label, &duplicate);
+
+      if (success == 1)
+       {
+         if (end)
+           error ("case label not within a switch statement");
+         else if (start)
+           cp_error ("case label `%E' not within a switch statement", start);
+         else
+           error ("default label not within a switch statement");
+       }
+      else if (success == 2)
+       {
+         if (end)
+           {
+             error ("duplicate (or overlapping) case value");
+             cp_error_at ("this is the first entry overlapping that value",
+                          duplicate);
+           }
+         else if (start)
+           {
+             cp_error ("duplicate case value `%E'", start);
+             cp_error_at ("previously used here", duplicate);
+           }
+         else
+           {
+             error ("multiple default labels in one switch");
+             cp_error_at ("this is the first default label", duplicate);
+           }
+       }
+      else if (success == 3)
+       warning ("case value out of range");
+      else if (success == 4)
+       warning ("empty range specified");
+      else if (success == 5)
+       {
+         if (end)
+           error ("case label within scope of cleanup or variable array");
+         else
+           cp_error ("case label `%E' within scope of cleanup or variable array", start);
+       }
+    }
+  if (start)
+    define_case_label (label);
+  else
+    define_case_label (NULL_TREE);
+}
index 6c2ae1750ec07ea8741cc6f938e73d0d6fd91baa..036fe27fbd4db600ccc4ea68e6f7f0ae81a8737a 100644 (file)
@@ -52,8 +52,6 @@ void expand_member_init ();
 void expand_aggr_init ();
 
 static void expand_aggr_init_1 ();
-static void expand_recursive_init_1 ();
-static void expand_recursive_init ();
 static void expand_virtual_init PROTO((tree, tree));
 tree expand_vec_init ();
 
@@ -70,7 +68,7 @@ static tree minus_one;
 /* Set up local variable for this file.  MUST BE CALLED AFTER
    INIT_DECL_PROCESSING.  */
 
-tree BI_header_type, BI_header_size;
+static tree BI_header_type, BI_header_size;
 
 void init_init_processing ()
 {
@@ -257,9 +255,8 @@ static tree
 sort_member_init (t)
      tree t;
 {
-  tree x, member, name, field, init;
+  tree x, member, name, field;
   tree init_list = NULL_TREE;
-  tree fields_to_unmark = NULL_TREE;
   int last_pos = 0;
   tree last_field;
 
@@ -281,6 +278,8 @@ sort_member_init (t)
          name = TREE_PURPOSE (x);
 
 #if 0
+         /* This happens in templates, since the IDENTIFIER is replaced
+             with the COMPONENT_REF in tsubst_expr.  */
          field = (TREE_CODE (name) == COMPONENT_REF
                   ? TREE_OPERAND (name, 1) : IDENTIFIER_CLASS_VALUE (name));
 #else
@@ -520,9 +519,7 @@ emit_base_init (t, immediately)
      tree t;
      int immediately;
 {
-  extern tree in_charge_identifier;
-
-  tree member, x;
+  tree member;
   tree mem_init_list;
   tree rbase_init_list, vbase_init_list;
   tree t_binfo = TYPE_BINFO (t);
@@ -571,7 +568,6 @@ emit_base_init (t, immediately)
   /* Now, perform initialization of non-virtual base classes.  */
   for (i = 0; i < n_baseclasses; i++)
     {
-      tree base = current_class_decl;
       tree base_binfo = TREE_VEC_ELT (binfos, i);
       tree init = void_list_node;
 
@@ -653,10 +649,15 @@ emit_base_init (t, immediately)
          init = TREE_VALUE (mem_init_list);
          from_init_list = 1;
 
+#if 0
+         if (TREE_CODE (name) == COMPONENT_REF)
+           name = DECL_NAME (TREE_OPERAND (name, 1));
+#else
          /* Also see if it's ever a COMPONENT_REF here.  If it is, we
             need to do `expand_assignment (name, init, 0, 0);' and
             a continue.  */
          my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 349);
+#endif
        }
       else
        {
@@ -993,7 +994,7 @@ expand_member_init (exp, name, init)
          else
            {
              if (basetype != type
-                 && ! binfo_member (basetype, TYPE_BINFO (type))
+                 && ! vec_binfo_member (basetype, TYPE_BINFO_BASETYPES (type))
                  && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
                {
                  if (IDENTIFIER_CLASS_VALUE (name))
@@ -1783,6 +1784,9 @@ build_offset_ref (type, name)
   tree basetypes = NULL_TREE;
   int dtor = 0;
 
+  if (current_template_parms)
+    return build_min_nt (SCOPE_REF, type, name);
+
   /* Handle namespace names fully here.  */
   if (TREE_CODE (type) == IDENTIFIER_NODE
       && get_aggr_from_typedef (type, 0) == 0)
@@ -1813,7 +1817,10 @@ build_offset_ref (type, name)
 
   if (TYPE_SIZE (type) == 0)
     {
-      t = IDENTIFIER_CLASS_VALUE (name);
+      if (type == current_class_type)
+       t = IDENTIFIER_CLASS_VALUE (name);
+      else
+       t = NULL_TREE;
       if (t == 0)
        {
          cp_error ("incomplete type `%T' does not have member `%D'", type,
@@ -2190,12 +2197,12 @@ is_friend (type, supplicant)
          if (name == TREE_PURPOSE (list))
            {
              tree friends = TREE_VALUE (list);
-             name = DECL_ASSEMBLER_NAME (supplicant);
              for (; friends ; friends = TREE_CHAIN (friends))
                {
                  if (ctype == TREE_PURPOSE (friends))
                    return 1;
-                 if (name == DECL_ASSEMBLER_NAME (TREE_VALUE (friends)))
+                 if (comptypes (TREE_TYPE (supplicant),
+                                TREE_TYPE (TREE_VALUE (friends)), 1))
                    return 1;
                }
              break;
@@ -2401,10 +2408,11 @@ make_friend_class (type, friend_type)
    QUALS say what special qualifies should apply to the object
    pointed to by `this'.  */
 tree
-do_friend (ctype, declarator, decl, parmdecls, flags, quals)
+do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
      tree ctype, declarator, decl, parmdecls;
      enum overload_flags flags;
      tree quals;
+     int funcdef_flag;
 {
   /* Every decl that gets here is a friend of something.  */
   DECL_FRIEND_P (decl) = 1;
@@ -2424,7 +2432,7 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
          /* This will set up DECL_ARGUMENTS for us.  */
          grokclassfn (ctype, cname, decl, flags, quals);
          if (TYPE_SIZE (ctype) != 0)
-           check_classfn (ctype, cname, decl);
+           check_classfn (ctype, decl);
 
          if (TREE_TYPE (decl) != error_mark_node)
            {
@@ -2492,7 +2500,8 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
        = build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)),
                               TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
       DECL_ARGUMENTS (decl) = parmdecls;
-      DECL_CLASS_CONTEXT (decl) = current_class_type;
+      if (funcdef_flag)
+       DECL_CLASS_CONTEXT (decl) = current_class_type;
 
       /* We can call pushdecl here, because the TREE_CHAIN of this
         FUNCTION_DECL is not needed for other purposes.  */
@@ -2639,6 +2648,11 @@ build_new (placement, decl, init, use_global_new)
            {
              if (this_nelts == NULL_TREE)
                error ("new of array type fails to specify size");
+             else if (current_template_parms)
+               {
+                 nelts = this_nelts;
+                 absdcl = TREE_OPERAND (absdcl, 0);
+               }
              else
                {
                  this_nelts = save_expr (convert (sizetype, this_nelts));
@@ -2704,6 +2718,21 @@ build_new (placement, decl, init, use_global_new)
       decl = TYPE_NAME (type);
     }
 
+  if (current_template_parms)
+    {
+      tree t;
+      if (has_array)
+       t = min_tree_cons (min_tree_cons (NULL_TREE, type, NULL_TREE),
+                          build_min_nt (ARRAY_REF, NULL_TREE, nelts),
+                          NULL_TREE);
+      else
+       t = type;
+       
+      rval = build_min_nt (NEW_EXPR, placement, t, init);
+      NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
+      return rval;
+    }
+
   /* ``A reference cannot be created by the new operator.  A reference
      is not an object (8.2.2, 8.4.3), so a pointer to it could not be
      returned by new.'' ARM 5.3.3 */
@@ -2740,6 +2769,13 @@ build_new (placement, decl, init, use_global_new)
       nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
       true_type = TREE_TYPE (true_type);
     }
+
+  if (TYPE_SIZE (complete_type (true_type)) == 0)
+    {
+      incomplete_type_error (0, true_type);
+      return error_mark_node;
+    }
+
   if (has_array)
     size = fold (build_binary_op (MULT_EXPR, size_in_bytes (true_type),
                                  nelts, 1));
@@ -2752,12 +2788,6 @@ build_new (placement, decl, init, use_global_new)
       return error_mark_node;
     }
 
-  if (TYPE_SIZE (true_type) == 0)
-    {
-      incomplete_type_error (0, true_type);
-      return error_mark_node;
-    }
-
   if (TYPE_LANG_SPECIFIC (true_type)
       && CLASSTYPE_ABSTRACT_VIRTUALS (true_type))
     {
@@ -3473,7 +3503,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
   if (TREE_CODE (type) == POINTER_TYPE)
     {
       type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-      if (TYPE_SIZE (type) == 0)
+      if (TYPE_SIZE (complete_type (type)) == 0)
        {
          incomplete_type_error (0, type);
          return error_mark_node;
@@ -3505,7 +3535,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
          return error_mark_node;
        }
       return build_vec_delete (addr, array_type_nelts (type),
-                              c_sizeof_nowarn (TREE_TYPE (type)),
                               auto_delete, integer_two_node,
                               use_global_delete);
     }
@@ -3718,12 +3747,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
               || (TREE_VIA_VIRTUAL (base_binfo) == 0
                   && ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))))
        {
-         tree virtual_size;
-
-         /* This is probably wrong. It should be the size of the virtual
-            object being deleted.  */
-         virtual_size = c_sizeof_nowarn (type);
-
          cond = build (COND_EXPR, void_type_node,
                        build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node),
                        build_builtin_call (void_type_node, BID,
@@ -3834,9 +3857,9 @@ build_vbase_delete (type, decl)
    confirm the size, and trap if the numbers differ; not clear that it'd
    be worth bothering.)  */
 tree
-build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
+build_vec_delete (base, maxindex, auto_delete_vec, auto_delete,
                  use_global_delete)
-     tree base, maxindex, elt_size;
+     tree base, maxindex;
      tree auto_delete_vec, auto_delete;
      int use_global_delete;
 {
index 7febe10520d25984e2ae70b9a753bf8b937bffe8..17cdef0abff9e8bba2c1a589d4a14c1de7e5c8ee 100644 (file)
@@ -47,12 +47,11 @@ Boston, MA 02111-1307, USA.  */
 #ifndef errno
 extern int errno;              /* needed for VAX.  */
 #endif
-extern jmp_buf toplevel;
 
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
-extern struct obstack *expression_obstack, permanent_obstack;
+extern struct obstack permanent_obstack;
 extern struct obstack *current_obstack, *saveable_obstack;
 
 extern double atof ();
@@ -68,20 +67,11 @@ extern char *get_directive_line (); /* In c-common.c */
 
 extern char *index ();
 extern char *rindex ();
-
-void extract_interface_info ();
 void yyerror ();
 
 /* This obstack is needed to hold text.  It is not safe to use
    TOKEN_BUFFER because `check_newline' calls `yylex'.  */
 struct obstack inline_text_obstack;
-static char *inline_text_firstobj;
-
-/* This obstack is used to hold information about methods to be
-   synthesized.  It should go away when synthesized methods are handled
-   properly (i.e. only when needed).  */
-struct obstack synth_obstack;
-static char *synth_firstobj;
 
 int end_of_file;
 
@@ -136,16 +126,8 @@ static tree get_time_identifier ();
 static tree filename_times;
 static tree this_filename_time;
 
-/* For implementing #pragma unit.  */
-tree current_unit_name;
-tree current_unit_language;
-
 /* Array for holding counts of the numbers of tokens seen.  */
 extern int *token_count;
-
-/* Textual definition used for default functions.  */
-static void default_copy_constructor_body ();
-static void default_assign_ref_body ();
 \f
 /* Return something to represent absolute declarators containing a *.
    TARGET is the absolute declarator that the * contains.
@@ -399,6 +381,8 @@ reinit_lang_specific ()
   reinit_search_statistics ();
 }
 
+int *init_parse ();
+
 void
 init_lex ()
 {
@@ -571,9 +555,6 @@ init_lex ()
   init_method ();
   init_error ();
   gcc_obstack_init (&inline_text_obstack);
-  inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
-  gcc_obstack_init (&synth_obstack);
-  synth_firstobj = (char *) obstack_alloc (&synth_obstack, 0);
 
   /* Start it at 0, because check_newline is called at the very beginning
      and will increment it to 1.  */
@@ -877,7 +858,10 @@ yyprint (file, yychar, yylval)
     }
 }
 
+#if defined(GATHER_STATISTICS) && defined(REDUCE_LENGTH)
 static int *reduce_count;
+#endif
+
 int *token_count;
 
 #if 0
@@ -1037,8 +1021,7 @@ extract_interface_info ()
     fileinfo = get_time_identifier (input_filename);
   fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
   interface_only = TREE_INT_CST_LOW (fileinfo);
-  if (!processing_template_defn || flag_external_templates)
-    interface_unknown = TREE_INT_CST_HIGH (fileinfo);
+  interface_unknown = TREE_INT_CST_HIGH (fileinfo);
 }
 
 /* Return nonzero if S is not considered part of an
@@ -1118,6 +1101,7 @@ void
 do_pending_inlines ()
 {
   struct pending_inline *t;
+  tree context;
 
   /* Oops, we're still dealing with the last batch.  */
   if (yychar == PRE_PARSED_FUNCTION_DECL)
@@ -1144,10 +1128,9 @@ do_pending_inlines ()
     return;
            
   /* Now start processing the first inline function.  */
-  my_friendly_assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE),
-                     226);
-  if (t->parm_vec)
-    push_template_decls (t->parm_vec, t->bindings, 0);
+  context = decl_function_context (t->fndecl);
+  if (context)
+    push_cp_function_context (context);
   if (t->len > 0)
     {
       feed_input (t->buf, t->len, t->can_free ? &inline_text_obstack : 0);
@@ -1169,13 +1152,6 @@ do_pending_inlines ()
   /* Pass back a handle on the rest of the inline functions, so that they
      can be processed later.  */
   yylval.ttype = build_tree_list ((tree) t, t->fndecl);
-#if 0
-  if (flag_default_inline && t->fndecl
-      /* If we're working from a template, don't change
-        the `inline' state.  */
-      && t->parm_vec == NULL_TREE)
-    DECL_INLINE (t->fndecl) = 1;
-#endif
   DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
 }
 
@@ -1189,11 +1165,11 @@ void
 process_next_inline (t)
      tree t;
 {
+  tree context;
   struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
-  my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
-                     227);
-  if (i->parm_vec)
-    pop_template_decls (i->parm_vec, i->bindings, 0);
+  context = decl_function_context (i->fndecl);
+  if (context)
+    pop_cp_function_context (context);
   i = i->next;
   if (yychar == YYEMPTY)
     yychar = yylex ();
@@ -1215,22 +1191,14 @@ process_next_inline (t)
   to_be_restored = 0;
   if (i && i->fndecl != NULL_TREE)
     {
-      my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
-                         228);
-      if (i->parm_vec)
-       push_template_decls (i->parm_vec, i->bindings, 0);
+      context = decl_function_context (i->fndecl);
+      if (context)
+       push_cp_function_context (context);
       feed_input (i->buf, i->len, i->can_free ? &inline_text_obstack : 0);
       lineno = i->lineno;
       input_filename = i->filename;
       yychar = PRE_PARSED_FUNCTION_DECL;
       yylval.ttype = build_tree_list ((tree) i, i->fndecl);
-#if 0
-      if (flag_default_inline
-         /* If we're working from a template, don't change
-            the `inline' state.  */
-         && i->parm_vec == NULL_TREE)
-       DECL_INLINE (i->fndecl) = 1;
-#endif
       DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
     }
   if (i)
@@ -1388,99 +1356,19 @@ yyungetc (ch, rescan)
 /* This function stores away the text for an inline function that should
    be processed later.  It decides how much later, and may need to move
    the info between obstacks; therefore, the caller should not refer to
-   the T parameter after calling this function.
-
-   This function also stores the list of template-parameter bindings that
-   will be needed for expanding the template, if any.  */
+   the T parameter after calling this function.  */
 
 static void
 store_pending_inline (decl, t)
      tree decl;
      struct pending_inline *t;
 {
-  extern int processing_template_defn;
-  int delay_to_eof = 0;
-  struct pending_inline **inlines;
-
   t->fndecl = decl;
-  /* Default: compile right away, and no extra bindings are needed.  */
-  t->parm_vec = t->bindings = 0;
-  if (processing_template_defn)
-    {
-      tree type = current_class_type;
-      /* Assumption: In this (possibly) nested class sequence, only
-        one name will have template parms.  */
-      while (type && TREE_CODE_CLASS (TREE_CODE (type)) == 't')
-       {
-         tree decl = TYPE_NAME (type);
-         tree tmpl = IDENTIFIER_TEMPLATE (DECL_NAME (decl));
-         if (tmpl)
-           {
-             t->parm_vec = DECL_TEMPLATE_INFO (TREE_PURPOSE (tmpl))->parm_vec;
-             t->bindings = TREE_VALUE (tmpl);
-           }
-         type = DECL_CONTEXT (decl);
-       }
-      if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
-         || TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
-       {
-         if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
-           my_friendly_assert (TYPE_MAX_VALUE (TREE_TYPE (decl)) == current_class_type,
-                               233);
-
-         /* Inline functions can be compiled immediately.  Other functions
-            will be output separately, so if we're in interface-only mode,
-            punt them now, or output them now if we're doing implementations
-            and we know no overrides will exist.  Otherwise, we delay until
-            end-of-file, to see if the definition is really required.  */
-         if (DECL_THIS_INLINE (decl))
-           /* delay_to_eof == 0 */;
-         else if (current_class_type && !interface_unknown)
-           {
-             if (interface_only)
-               {
-#if 0
-                 print_node_brief (stderr, "\ndiscarding text for ", decl, 0);
-#endif
-                 if (t->can_free)
-                   obstack_free (&inline_text_obstack, t->buf);
-                 DECL_PENDING_INLINE_INFO (decl) = 0;
-                 return;
-               }
-           }
-         /* Don't delay the processing of virtual functions.  */
-         else if (DECL_VINDEX (decl) == NULL_TREE)
-           delay_to_eof = 1;
-       }
-      else
-       my_friendly_abort (58);
-    }
-
-  if (delay_to_eof)
-    {
-      extern struct pending_inline *pending_template_expansions;
-
-      if (t->can_free)
-       {
-         char *free_to = t->buf;
-         t->buf = (char *) obstack_copy (&permanent_obstack, t->buf,
-                                         t->len + 1);
-         t = (struct pending_inline *) obstack_copy (&permanent_obstack, 
-                                                     (char *)t, sizeof (*t));
-         obstack_free (&inline_text_obstack, free_to);
-       }
-      inlines = &pending_template_expansions;
-      t->can_free = 0;
-    }
-  else
-    {
-      inlines = &pending_inlines;
-      DECL_PENDING_INLINE_INFO (decl) = t;
-    }
+  DECL_PENDING_INLINE_INFO (decl) = t;
 
   /* Because we use obstacks, we must process these in precise order.  */
-  t->next = *inlines;
-  *inlines = t;
+  t->next = pending_inlines;
+  pending_inlines = t;
 }
 
 void reinit_parse_for_block ();
@@ -1494,7 +1382,7 @@ reinit_parse_for_method (yychar, decl)
   int starting_lineno = lineno;
   char *starting_filename = input_filename;
 
-  reinit_parse_for_block (yychar, &inline_text_obstack, 0);
+  reinit_parse_for_block (yychar, &inline_text_obstack);
 
   len = obstack_object_size (&inline_text_obstack);
   current_base_init_list = NULL_TREE;
@@ -1523,24 +1411,22 @@ reinit_parse_for_method (yychar, decl)
       t->len = len;
       t->can_free = 1;
       t->deja_vu = 0;
+#if 0
       if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
        warn_if_unknown_interface (decl);
+#endif
       t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
       store_pending_inline (decl, t);
     }
 }
 
-/* Consume a block -- actually, a method or template definition beginning
-   with `:' or `{' -- and save it away on the specified obstack.
+/* Consume a block -- actually, a method beginning
+   with `:' or `{' -- and save it away on the specified obstack.  */
 
-   Argument IS_TEMPLATE indicates which set of error messages should be
-   output if something goes wrong.  This should really be cleaned up somehow,
-   without loss of clarity.  */
 void
-reinit_parse_for_block (pyychar, obstackp, is_template)
+reinit_parse_for_block (pyychar, obstackp)
      int pyychar;
      struct obstack *obstackp;
-     int is_template;
 {
   register int c = 0;
   int blev = 1;
@@ -1560,13 +1446,13 @@ reinit_parse_for_block (pyychar, obstackp, is_template)
       look_for_lbrac = 1;
       blev = 0;
     }
-  else if (pyychar == RETURN && !is_template)
+  else if (pyychar == RETURN)
     {
       obstack_grow (obstackp, "return", 6);
       look_for_lbrac = 1;
       blev = 0;
     }
-  else if (pyychar == TRY && !is_template)
+  else if (pyychar == TRY)
     {
       obstack_grow (obstackp, "try", 3);
       look_for_lbrac = 1;
@@ -1574,9 +1460,7 @@ reinit_parse_for_block (pyychar, obstackp, is_template)
     }
   else
     {
-      yyerror (is_template
-              ? "parse error in template specification"
-              : "parse error in method specification");
+      yyerror ("parse error in method specification");
       obstack_1grow (obstackp, '{');
     }
 
@@ -1673,9 +1557,7 @@ reinit_parse_for_block (pyychar, obstackp, is_template)
            {
              if (look_for_lbrac)
                {
-                 error (is_template
-                        ? "template body missing"
-                        : "function body for constructor missing");
+                 error ("function body for constructor missing");
                  obstack_1grow (obstackp, '{');
                  obstack_1grow (obstackp, '}');
                  len += 2;
@@ -1721,13 +1603,10 @@ cons_up_default_function (type, full_name, kind)
      int kind;
 {
   extern tree void_list_node;
-  char *func_buf = NULL;
-  int func_len = 0;
   tree declspecs = NULL_TREE;
   tree fn, args;
   tree argtype;
   int retref = 0;
-  int complex = 0;
   tree name = constructor_name (full_name);
 
   switch (kind)
@@ -1744,7 +1623,6 @@ cons_up_default_function (type, full_name, kind)
     case 2:
       /* Default constructor.  */
       args = void_list_node;
-      complex = TYPE_NEEDS_CONSTRUCTING (type);
       break;
 
     case 3:
@@ -1758,7 +1636,6 @@ cons_up_default_function (type, full_name, kind)
                        build_tree_list (hash_tree_chain (argtype, NULL_TREE),
                                         get_identifier ("_ctor_arg")),
                        void_list_node);
-      complex = TYPE_HAS_COMPLEX_INIT_REF (type);
       break;
 
     case 5:
@@ -1775,7 +1652,6 @@ cons_up_default_function (type, full_name, kind)
                        build_tree_list (hash_tree_chain (argtype, NULL_TREE),
                                         get_identifier ("_ctor_arg")),
                        void_list_node);
-      complex = TYPE_HAS_COMPLEX_ASSIGN_REF (type);
       break;
 
     default:
@@ -1799,11 +1675,13 @@ cons_up_default_function (type, full_name, kind)
   if (fn == void_type_node)
     return fn;
 
+#if 0
   if (processing_template_defn)
     {
       SET_DECL_IMPLICIT_INSTANTIATION (fn);
       repo_template_used (fn);
     }
+#endif
 
   if (CLASSTYPE_INTERFACE_KNOWN (type))
     {
@@ -1814,27 +1692,7 @@ cons_up_default_function (type, full_name, kind)
   else
     DECL_NOT_REALLY_EXTERN (fn) = 1;
 
-#if 0
-  /* When on-the-fly synthesis works properly, remove the second and third
-     conditions here.  */
-  if (flag_keep_inline_functions
-#if 0
-      || ! flag_no_inline
-      || complex
-#endif
-      || ! DECL_EXTERNAL (fn))
-    {
-      struct pending_inline *t;
-      t = (struct pending_inline *)
-       obstack_alloc (&synth_obstack, sizeof (struct pending_inline));
-      t->lineno = -kind;
-      t->can_free = 0;
-      t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
-      store_pending_inline (fn, t);
-    }
-  else
-#endif
-    mark_inline_for_output (fn);
+  mark_inline_for_output (fn);
 
 #ifdef DEBUG_DEFAULT_FUNCTIONS
   { char *fn_type = NULL;
@@ -2090,8 +1948,6 @@ check_newline ()
                      error ("invalid #pragma unit");
                      goto skipline;
                    }
-                 current_unit_name = get_identifier (TREE_STRING_POINTER (yylval.ttype));
-                 current_unit_language = current_lang_name;
                  if (nextchar < 0)
                    nextchar = getch ();
                  c = nextchar;
@@ -2810,9 +2666,11 @@ int
 identifier_type (decl)
      tree decl;
 {
-  if (TREE_CODE (decl) == TEMPLATE_DECL
-      && DECL_TEMPLATE_IS_CLASS (decl))
-    return PTYPENAME;
+  if (TREE_CODE (decl) == TEMPLATE_DECL)
+    {
+      if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
+       return PTYPENAME;
+    }
   if (TREE_CODE (decl) == NAMESPACE_DECL)
     return NSNAME;
   if (TREE_CODE (decl) != TYPE_DECL)
@@ -2841,22 +2699,24 @@ see_typename ()
 }
 
 tree
-do_identifier (token)
+do_identifier (token, parsing)
      register tree token;
+     int parsing;
 {
-  register tree id = lastiddecl;
+  register tree id;
 
-  if (IDENTIFIER_OPNAME_P (token))
+  if (! parsing || IDENTIFIER_OPNAME_P (token))
     id = lookup_name (token, 0);
+  else
+    id = lastiddecl;
 
-  if (yychar == YYEMPTY)
+  if (parsing && yychar == YYEMPTY)
     yychar = yylex ();
   /* Scope class declarations before global
      declarations.  */
   if (id == IDENTIFIER_GLOBAL_VALUE (token)
       && current_class_type != 0
-      && TYPE_SIZE (current_class_type) == 0
-      && TREE_CODE (current_class_type) != UNINSTANTIATED_P_TYPE)
+      && TYPE_SIZE (current_class_type) == 0)
     {
       /* Could be from one of the base classes.  */
       tree field = lookup_field (current_class_type, token, 1, 0);
@@ -2898,13 +2758,15 @@ do_identifier (token)
            return id;
        }
 
-      if (IDENTIFIER_OPNAME_P (token))
+      if (current_template_parms)
+       return build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
+      else if (IDENTIFIER_OPNAME_P (token))
        {
          if (token != ansi_opname[ERROR_MARK])
            cp_error ("operator %O not defined", token);
          id = error_mark_node;
        }
-      else if (yychar == '(' || yychar == LEFT_RIGHT)
+      else if (parsing && (yychar == '(' || yychar == LEFT_RIGHT))
        {
          id = implicitly_declare (token);
        }
@@ -2986,10 +2848,88 @@ do_identifier (token)
            cp_error ("enum `%D' is private", id);
          /* protected is OK, since it's an enum of `this'.  */
        }
-      id = DECL_INITIAL (id);
+      if (! current_template_parms
+         || (DECL_INITIAL (id)
+             && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_CONST_PARM))
+       id = DECL_INITIAL (id);
     }
   else
-    id = hack_identifier (id, token, yychar);
+    id = hack_identifier (id, token);
+
+  if (current_template_parms)
+    {
+      if (is_overloaded_fn (id))
+       {
+         tree t = build_min (LOOKUP_EXPR, unknown_type_node,
+                             token, get_first_fn (id));
+         if (id != IDENTIFIER_GLOBAL_VALUE (token))
+           TREE_OPERAND (t, 1) = error_mark_node;
+         id = t;
+       }
+      else if (! TREE_PERMANENT (id) || TREE_CODE (id) == PARM_DECL
+              || TREE_CODE (id) == USING_DECL)
+       id = build_min (LOOKUP_EXPR, TREE_TYPE (id), token, error_mark_node);
+      /* else just use the decl */
+    }
+      
+  return id;
+}
+
+tree
+do_scoped_id (token, parsing)
+     tree token;
+     int parsing;
+{
+  tree id = IDENTIFIER_GLOBAL_VALUE (token);
+  if (parsing && yychar == YYEMPTY)
+    yychar = yylex ();
+  if (! id)
+    {
+      if (current_template_parms)
+       {
+         id = build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
+         LOOKUP_EXPR_GLOBAL (id) = 1;
+         return id;
+       }
+      if (parsing && yychar == '(' || yychar == LEFT_RIGHT)
+       id = implicitly_declare (token);
+      else
+       {
+         if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node)
+           error ("undeclared variable `%s' (first use here)",
+                  IDENTIFIER_POINTER (token));
+         id = error_mark_node;
+         /* Prevent repeated error messages.  */
+         IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node;
+       }
+    }
+  else
+    {
+      if (TREE_CODE (id) == ADDR_EXPR)
+       mark_used (TREE_OPERAND (id, 0));
+      else if (TREE_CODE (id) != TREE_LIST)
+       mark_used (id);
+    }
+  if (TREE_CODE (id) == CONST_DECL && ! current_template_parms)
+    {
+      /* XXX CHS - should we set TREE_USED of the constant? */
+      id = DECL_INITIAL (id);
+      /* This is to prevent an enum whose value is 0
+        from being considered a null pointer constant.  */
+      id = build1 (NOP_EXPR, TREE_TYPE (id), id);
+      TREE_CONSTANT (id) = 1;
+    }
+
+  if (current_template_parms)
+    {
+      if (is_overloaded_fn (id))
+       {
+         id = build_min (LOOKUP_EXPR, unknown_type_node,
+                         token, get_first_fn (id));
+         LOOKUP_EXPR_GLOBAL (id) = 1;
+       }
+      /* else just use the decl */
+    }
   return id;
 }
 
@@ -3091,9 +3031,6 @@ real_yylex ()
        value = END_OF_SAVED_INPUT;
       else if (linemode)
        value = END_OF_LINE;
-      else if (do_pending_expansions ())
-       /* this will set yychar for us */
-       return yychar;
       else
        value = ENDFILE;
       break;
@@ -4141,12 +4078,20 @@ real_yylex ()
              len = p - token_buffer - 1;
            }
 #endif
+           if (current_template_parms)
+             push_obstacks (&permanent_obstack, &permanent_obstack);
            yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep);
+           if (current_template_parms)
+             pop_obstacks ();
            TREE_TYPE (yylval.ttype) = wchar_array_type_node;
          }
        else
          {
+           if (current_template_parms)
+             push_obstacks (&permanent_obstack, &permanent_obstack);
            yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
+           if (current_template_parms)
+             pop_obstacks ();
            TREE_TYPE (yylval.ttype) = char_array_type_node;
          }
 
@@ -4363,15 +4308,10 @@ is_rid (t)
   return !!is_reserved_word (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t));
 }
 
-typedef enum
-{
-  d_kind, t_kind, s_kind, r_kind, e_kind, c_kind,
-  id_kind, op_id_kind, perm_list_kind, temp_list_kind,
-  vec_kind, x_kind, lang_decl, lang_type, all_kinds
-} tree_node_kind;
+#ifdef GATHER_STATISTICS
 extern int tree_node_counts[];
 extern int tree_node_sizes[];
-extern char *tree_node_kind_names[];
+#endif
 
 /* Place to save freed lang_decls which were allocated on the
    permanent_obstack.  @@ Not currently used.  */
@@ -4490,6 +4430,9 @@ copy_lang_decl (node)
   int size;
   int *pi;
 
+  if (! DECL_LANG_SPECIFIC (node))
+    return;
+
   if (TREE_CODE (node) == FIELD_DECL)
     size = sizeof (struct lang_decl_flags);
   else
index 7d9497257280dd7fe8e1f500bed8c9bb26c4123c..5156121ffb74534b67b18fb2bf1d68d91f4312ca 100644 (file)
@@ -346,10 +346,7 @@ build_overload_nested_name (decl)
       OB_PUTCP (label);
     }
   else                         /* TYPE_DECL */
-    {
-      tree name = DECL_NAME (decl);
-      build_overload_identifier (name);
-    }
+    build_overload_identifier (decl);
 }
 
 /* Encoding for an INTEGER_CST value. */
@@ -357,6 +354,27 @@ static void
 build_overload_int (value)
      tree value;
 {
+  if (TREE_CODE (value) == TEMPLATE_CONST_PARM)
+    {
+      OB_PUTC ('Y');
+      if (TEMPLATE_CONST_IDX (value) > 9)
+       OB_PUTC ('_');
+      icat (TEMPLATE_CONST_IDX (value)); 
+      if (TEMPLATE_CONST_IDX (value) > 9)
+       OB_PUTC ('_');
+      return;
+    }
+  else if (uses_template_parms (value))
+    /* We don't ever want this output, but it's inconvenient not to
+       be able to build the string.  This should cause assembler
+       errors we'll notice.  */
+    {
+      static int n;
+      sprintf (digit_buffer, " *%d", n++);
+      OB_PUTCP (digit_buffer);
+      return;
+    }
+
   my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243);
   if (TYPE_PRECISION (value) == 2 * HOST_BITS_PER_WIDE_INT)
     {
@@ -544,11 +562,14 @@ static void
 build_overload_identifier (name)
      tree name;
 {
-  if (IDENTIFIER_TEMPLATE (name))
+  if (TREE_CODE (name) == TYPE_DECL
+      && IS_AGGR_TYPE (TREE_TYPE (name))
+      && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name))
+      && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name))))
     {
       tree template, parmlist, arglist, tname;
       int i, nparms;
-      template = IDENTIFIER_TEMPLATE (name);
+      template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
       arglist = TREE_VALUE (template);
       template = TREE_PURPOSE (template);
       tname = DECL_NAME (template);
@@ -580,6 +601,8 @@ build_overload_identifier (name)
     }
   else
     {
+      if (TREE_CODE (name) == TYPE_DECL)
+       name = DECL_NAME (name);
       if (numeric_output_need_bar)
        {
          OB_PUTC ('_');
@@ -873,8 +896,8 @@ build_overload_name (parmtypes, begin, end)
                numeric_output_need_bar = 0;
                build_overload_nested_name (TYPE_MAIN_DECL (parmtype));
              }
-           else
-             build_overload_identifier (name);
+           else              
+             build_overload_identifier (TYPE_MAIN_DECL (parmtype));
            break;
          }
 
@@ -884,8 +907,15 @@ build_overload_name (parmtypes, begin, end)
          break;
 
        case TEMPLATE_TYPE_PARM:
-       case TEMPLATE_CONST_PARM:
-        case UNINSTANTIATED_P_TYPE:
+         OB_PUTC ('X');
+         if (TEMPLATE_TYPE_IDX (parmtype) > 9)
+           OB_PUTC ('_');
+         icat (TEMPLATE_TYPE_IDX (parmtype)); 
+         if (TEMPLATE_TYPE_IDX (parmtype) > 9)
+           OB_PUTC ('_');
+         break;
+           
+       case TYPENAME_TYPE:
          /* We don't ever want this output, but it's inconvenient not to
             be able to build the string.  This should cause assembler
             errors we'll notice.  */
@@ -1468,7 +1498,6 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
 
    NAME is $1 from the bison rule. It is an IDENTIFIER_NODE.
    VALUE is $$ from the bison rule. It is the value returned by lookup_name ($1)
-   yychar is the pending input character (suitably encoded :-).
 
    As a last ditch, try to look up the name as a label and return that
    address.
@@ -1478,11 +1507,10 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
    compiler faster).  */
 
 tree
-hack_identifier (value, name, yychar)
+hack_identifier (value, name)
      tree value, name;
-     int yychar;
 {
-  tree type;
+  tree type, context;
 
   if (TREE_CODE (value) == ERROR_MARK)
     {
@@ -1562,6 +1590,20 @@ hack_identifier (value, name, yychar)
   else
     mark_used (value);
 
+  if (pedantic
+      && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL))
+    {
+      tree context = decl_function_context (value);
+      if (context != NULL_TREE && context != current_function_decl
+         && ! TREE_STATIC (value))
+       {
+         cp_pedwarn ("use of %s from containing function",
+                     (TREE_CODE (value) == VAR_DECL
+                      ? "`auto' variable" : "parameter"));
+         cp_pedwarn_at ("  `%#D' declared here", value);
+       }
+    }
+
   if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value))
     {
       if (DECL_LANG_SPECIFIC (value)
@@ -1605,7 +1647,7 @@ hack_identifier (value, name, yychar)
       return value;
     }
 
-  if (TREE_CODE (type) == REFERENCE_TYPE)
+  if (TREE_CODE (type) == REFERENCE_TYPE && ! current_template_parms)
     {
       my_friendly_assert (TREE_CODE (value) == VAR_DECL
                          || TREE_CODE (value) == PARM_DECL
@@ -2217,9 +2259,6 @@ do_build_assign_ref (fndecl)
   pop_momentary ();
 }
 
-void push_cp_function_context ();
-void pop_cp_function_context ();
-
 void
 synthesize_method (fndecl)
      tree fndecl;
index a75344bbea1cb41c8c5ec92ccb20ae4a908ffa8d..be782b7eb9e9e29ca384859315f1c7f1672750e0 100644 (file)
@@ -55,6 +55,7 @@ extern int errno;
 
 extern int end_of_file;
 extern int current_class_depth;
+extern tree last_tree;
 
 /* FSF LOCAL dje prefix attributes */
 extern tree strip_attrs                PROTO((tree));
@@ -230,7 +231,7 @@ empty_parms ()
 %token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
 %token <ttype> PRE_PARSED_CLASS_DECL
 %type <ttype> fn.def1 /* Not really! */
-%type <ttype> fn.def2 return_id
+%type <ttype> fn.def2 return_id fn.defpen
 %type <itype> ctor_initializer_opt
 %type <ttype> named_class_head named_class_head_sans_basetype
 %type <ttype> named_complex_class_head_sans_basetype
@@ -247,22 +248,20 @@ empty_parms ()
 %type <itype> initdcl0 notype_initdcl0 member_init_list
 %type <ttype> template_header template_parm_list template_parm
 %type <ttype> template_type_parm
+%type <code>  template_close_bracket
 %type <ttype> template_type template_arg_list template_arg
-%type <ttype> template_instantiation template_type_name tmpl.2
-%type <ttype> template_instantiate_once template_instantiate_some
-%type <itype> fn_tmpl_end
 /* %type <itype> try_for_typename */
 %type <ttype> condition xcond paren_cond_or_null
 %type <ttype> type_name nested_name_specifier nested_type ptr_to_mem
 %type <ttype> complete_type_name notype_identifier
 %type <ttype> complex_type_name nested_name_specifier_1
 %type <itype> nomods_initdecls nomods_initdcl0
-%type <ttype> new_initializer new_placement specialization type_specifier_seq
+%type <ttype> new_initializer new_placement type_specifier_seq
 %type <ttype> using_decl .poplevel
 
 /* in order to recognize aggr tags as defining and thus shadowing. */
 %token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
-%type <ttype> named_class_head_sans_basetype_defn 
+%type <ttype> named_class_head_sans_basetype_defn
 %type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
 
 %token NSNAME
@@ -271,7 +270,7 @@ empty_parms ()
 /* Used in lex.c for parsing pragmas.  */
 %token END_OF_LINE
 
-/* lex.c and pt.c depends on this being the last token.  Define
+/* lex.c and pt.c depend on this being the last token.  Define
    any new tokens before this one!  */
 %token END_OF_SAVED_INPUT
 \f
@@ -447,10 +446,13 @@ template_parm:
           their match before considering them nameless parameter
           declarations.  */
          template_type_parm
-               { $$ = build_tree_list (NULL_TREE, $$); }
-       | template_type_parm '=' typespec
-               { $$ = build_tree_list ($3, $$); }
-       | full_parm
+               { $$ = build_tree_list (NULL_TREE, $1); }
+       | template_type_parm '=' type_id
+               { $$ = build_tree_list (groktypename ($3), $1); }
+       | parm
+               { $$ = build_tree_list (NULL_TREE, $1); }
+       | parm '=' expr_no_commas %prec ARITHCOMPARE
+               { $$ = build_tree_list ($3, $1); }
        ;
 
 overloaddef:
@@ -463,102 +465,14 @@ ov_identifiers: IDENTIFIER
        | ov_identifiers ',' IDENTIFIER
                { declare_overloaded ($3); }
        ;
-         
-template_def:
-       /* Class template declarations go here; they aren't normal class
-          declarations, because we can't process the bodies yet.  */
-         template_header named_class_head_sans_basetype '{'
-               { yychar = '{'; goto template1; }
-        ';'
-       | template_header named_class_head_sans_basetype_defn '{'
-               { yychar = '{'; goto template1; }
-        ';'
-       | template_header named_class_head_sans_basetype ':'
-               { yychar = ':'; goto template1; }
-        ';'
-       | template_header named_class_head_sans_basetype_defn ':'
-               {
-                 yychar = ':';
-               template1:
-                 if (current_aggr == signature_type_node)
-                   sorry ("template type defining a signature");
-                 /* Maybe pedantic warning for union?
-                    How about an enum? :-)  */
-                 end_template_decl ($1, $2, current_aggr, 1);
-                 reinit_parse_for_template (yychar, $1, $2);
-                 yychar = YYEMPTY;
-               }
-         ';'
-       | template_header named_class_head_sans_basetype ';'
-               {
-                 end_template_decl ($1, $2, current_aggr, 0);
-                 /* declare $2 as template name with $1 parm list */
-               }
-       | template_header named_class_head_sans_basetype_defn ';'
-               {
-                 end_template_decl ($1, $2, current_aggr, 0);
-                 /* declare $2 as template name with $1 parm list */
-               }
-       | template_header /* notype_initdcl0 ';' */
-         notype_declarator exception_specification_opt maybeasm maybe_attribute
-         fn_tmpl_end
-               {
-                 tree d;
-                 int momentary;
-                 int def = ($6 != ';');
-                 momentary = suspend_momentary ();
-                 d = start_decl ($<ttype>2, /*current_declspecs*/NULL_TREE, 0,
-                                 $3);
-                 cplus_decl_attributes (d, $5, /*prefix_attributes*/NULL_TREE);
-                 cp_finish_decl (d, NULL_TREE, $4, 1, 0);
-                 end_template_decl ($1, d, 0, def);
-                 if (def)
-                   reinit_parse_for_template ((int) $6, $1, d);
-                 resume_momentary (momentary);
-               }
-       | template_header typed_declspecs /*initdcl0*/
-         declarator exception_specification_opt maybeasm maybe_attribute
-         fn_tmpl_end
-               {
-                 tree d, specs, attrs;
-                 int momentary;
-                 int def = ($7 != ';');
-                 split_specs_attrs ($2, &specs, &attrs);
-                 momentary = suspend_momentary ();
-                 d = start_decl ($<ttype>3, specs, 0, $<ttype>4);
-                 cplus_decl_attributes (d, $6, attrs);
-                 cp_finish_decl (d, NULL_TREE, $5, 1, 0);
-                 end_template_decl ($1, d, 0, def);
-                 if (def)
-                   {
-                     reinit_parse_for_template ((int) $7, $1, d);
-                     yychar = YYEMPTY;
-                   }
-                 note_list_got_semicolon ($<ttype>2);
-                 resume_momentary (momentary);
-               }
-       | template_header declmods notype_declarator fn_tmpl_end
-               {
-                 tree d, specs, attrs;
-                 int def = ($4 != ';');
-                 split_specs_attrs ($2, &specs, &attrs);
-                 d = start_decl ($<ttype>3, specs, 0, NULL_TREE);
-                 cplus_decl_attributes (d, NULL_TREE, attrs);
-                 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
-                 end_template_decl ($1, d, 0, def);
-                 if (def)
-                   reinit_parse_for_template ((int) $4, $1, d);
-               }
-       /* Try to recover from syntax errors in templates.  */
-       | template_header error '}'     { end_template_decl ($1, 0, 0, 0); }
-       | template_header error ';'     { end_template_decl ($1, 0, 0, 0); }
-       ;
 
-fn_tmpl_end: '{'               { $$ = '{'; }
-       | ':'                   { $$ = ':'; }
-       | ';'                   { $$ = ';'; }
-       | '='                   { $$ = '='; }
-       | RETURN                { $$ = RETURN; }
+template_def:
+         template_header
+         extdef
+               { end_template_decl (); }
+       | template_header
+         error %prec EMPTY
+               { end_template_decl (); }
        ;
 
 datadef:
@@ -595,19 +509,6 @@ datadef:
            tree t, attrs;
            split_specs_attrs ($1, &t, &attrs);
            shadow_tag (t);
-           if (TREE_CODE (t) == TREE_LIST
-               && TREE_PURPOSE (t) == NULL_TREE)
-             {
-               t = TREE_VALUE (t);
-               if (IS_AGGR_TYPE (t)
-                   && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (t)))
-                 {
-                   if (CLASSTYPE_USE_TEMPLATE (t) == 0)
-                     SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
-                   else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
-                     error ("override declaration for already-expanded template");
-                 }
-             }
            note_list_got_semicolon ($<ttype>$);
          }
        | error ';'
@@ -635,14 +536,9 @@ eat_saved_input:
 
 fndef:
          fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
-               {
-                 finish_function (lineno, (int)$3, 0);
-                 if ($<ttype>$) process_next_inline ($<ttype>$);
-               }
+               { finish_function (lineno, (int)$3, 0); }
        | fn.def1 maybe_return_init function_try_block
-               {
-                 if ($<ttype>$) process_next_inline ($<ttype>$);
-               }
+               { if ($<ttype>$) process_next_inline ($<ttype>$); }
          eat_saved_input
        | typed_declspecs declarator error
                {}
@@ -672,10 +568,6 @@ fn.def1:
                    YYERROR1;
                  reinit_parse_for_function ();
                  $$ = NULL_TREE; }
-       | PRE_PARSED_FUNCTION_DECL
-               { start_function (NULL_TREE, TREE_VALUE ($$),
-                                 NULL_TREE, NULL_TREE, 1);
-                 reinit_parse_for_function (); }
        ;
 
 /* more C++ complexity.  See component_decl for a comment on the
@@ -683,6 +575,13 @@ fn.def1:
 fn.def2:
          typed_declspecs '(' parmlist ')' type_quals exception_specification_opt
                { tree specs = strip_attrs ($1);
+                 if (TREE_VALUE (specs) == current_class_type)
+                   {
+                     if (TREE_CHAIN (specs) == NULL_TREE)
+                       specs = get_decl_list (current_class_name);
+                     else
+                       TREE_VALUE (specs) = current_class_name;
+                   } 
                  $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), $3, $5);
                  $$ = start_method (TREE_CHAIN (specs), $$, $6);
                 rest_of_mdef:
@@ -817,15 +716,15 @@ identifier_defn:
        ;
 
 explicit_instantiation:
-         TEMPLATE specialization template_instantiation
-               { do_type_instantiation ($3 ? $3 : $2, NULL_TREE); }
+         TEMPLATE aggr template_type
+               { do_type_instantiation ($3, NULL_TREE); }
        | TEMPLATE typed_declspecs declarator
                { tree specs = strip_attrs ($2);
                  do_function_instantiation (specs, $3, NULL_TREE); }
        | TEMPLATE notype_declarator
                { do_function_instantiation (NULL_TREE, $2, NULL_TREE); }
-       | SCSPEC TEMPLATE specialization template_instantiation
-               { do_type_instantiation ($4 ? $4 : $3, $1); }
+       | SCSPEC TEMPLATE aggr template_type
+               { do_type_instantiation ($4, $1); }
        | SCSPEC TEMPLATE typed_declspecs declarator
                { tree specs = strip_attrs ($3);
                  do_function_instantiation (specs, $4, $1); }
@@ -833,23 +732,45 @@ explicit_instantiation:
                { do_function_instantiation (NULL_TREE, $3, $1); }
        ;
 
-template_type:
-         template_type_name tmpl.2 template_instantiation
-               { if ($3) $$ = $3; }
-       ;
+/* The TYPENAME expansions are to deal with use of a template class name as
+  a template within the class itself, where the template decl is hidden by
+  a type decl.  Got all that?  */
 
-template_type_name:
-         PTYPENAME '<' template_arg_list '>'
-               { $$ = lookup_template_class ($$, $3, NULL_TREE); }
-       | PTYPENAME '<' '>'
-               { $$ = lookup_template_class ($$, NULL_TREE, NULL_TREE); }
-       | TYPENAME  '<' template_arg_list '>'
-               { $$ = lookup_template_class ($$, $3, NULL_TREE); }
+template_type:
+         PTYPENAME '<' template_arg_list template_close_bracket
+               {
+                 $$ = lookup_template_class ($1, $3, NULL_TREE);
+                 if ($$ != error_mark_node)
+                   $$ = TYPE_STUB_DECL ($$);
+               }
+       | PTYPENAME '<' template_close_bracket
+               {
+                 $$ = lookup_template_class ($1, NULL_TREE, NULL_TREE);
+                 if ($$ != error_mark_node)
+                   $$ = TYPE_STUB_DECL ($$);
+               }
+       | TYPENAME  '<' template_arg_list template_close_bracket
+               {
+                 $$ = lookup_template_class ($1, $3, NULL_TREE);
+                 if ($$ != error_mark_node)
+                   $$ = TYPE_STUB_DECL ($$);
+               }
+       | TYPENAME '<' template_close_bracket
+               {
+                 $$ = lookup_template_class ($1, NULL_TREE, NULL_TREE);
+                 if ($$ != error_mark_node)
+                   $$ = TYPE_STUB_DECL ($$);
+               }
        ;
 
-tmpl.2: 
-         /* empty */ %prec EMPTY
-               { $$ = instantiate_class_template ($<ttype>0, 1); }
+template_close_bracket:
+         '>'
+       | RSHIFT 
+               {
+                 /* Handle `Class<Class<Type>>' without space in the `>>' */
+                 pedwarn ("`>>' should be `> >' in template class name");
+                 yyungetc ('>', 1);
+               }
        ;
 
 template_arg_list:
@@ -862,75 +783,9 @@ template_arg_list:
 template_arg:
          type_id
                { $$ = groktypename ($$); }
-       | expr_no_commas  %prec UNARY
+       | expr_no_commas  %prec ARITHCOMPARE
        ;
 
-template_instantiate_once:
-         PRE_PARSED_CLASS_DECL maybe_base_class_list
-               {
-                 tree t, decl, tmpl;
-
-                 tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE ($1));
-                 t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, $1, $2, 0);
-                 set_current_level_tags_transparency (1);
-                 my_friendly_assert (TREE_CODE (t) == RECORD_TYPE
-                                     || TREE_CODE (t) == UNION_TYPE, 257);
-                 $<ttype>$ = t;
-
-                 /* Now, put a copy of the decl in global scope, to avoid
-                    recursive expansion.  */
-                 decl = IDENTIFIER_LOCAL_VALUE ($1);
-                 if (!decl)
-                   decl = IDENTIFIER_CLASS_VALUE ($1);
-                 /* Now, put a copy of the decl in global scope, to avoid
-                    recursive expansion.  */
-                  if (decl)
-                    {
-                     /* Need to copy it to clear the chain pointer,
-                        and need to get it into permanent storage.  */
-                      my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 258);
-                     push_obstacks (&permanent_obstack, &permanent_obstack);
-                      decl = copy_node (decl);
-                     if (DECL_LANG_SPECIFIC (decl))
-                       copy_lang_decl (decl);
-                     pop_obstacks ();
-                     pushdecl_top_level (decl);
-                   }
-                 /* Kludge; see instantiate_class_template.  */
-                 TYPE_BEING_DEFINED (t) = 0;
-               }
-         left_curly opt.component_decl_list '}'
-               {
-                 tree t = finish_struct ($<ttype>3, $5, NULL_TREE, 0);
-
-                 pop_obstacks ();
-                 end_template_instantiation ($1);
-
-                 repo_template_used (t);
-
-                  /* Now go after the methods & class data.  */
-                  instantiate_member_templates ($1);
-
-                 pop_tinst_level();
-
-                 CLASSTYPE_GOT_SEMICOLON (t) = 1;
-               }
-       ;
-
-template_instantiation:
-          /* empty */
-                { $$ = NULL_TREE; }
-        | template_instantiate_once
-                { $$ = $1; }
-        ;
-
-template_instantiate_some:
-          /* empty */
-                { $$ = NULL_TREE; /* never used from here... */}
-        | template_instantiate_once template_instantiate_some
-                { $$ = $1; /*???*/ }
-        ;
-
 unop:     '-'
                { $$ = NEGATE_EXPR; }
        | '+'
@@ -1013,8 +868,25 @@ compstmtend:
        ;
 
 already_scoped_stmt:
-         '{' compstmtend
-               { finish_stmt (); }
+         '{'
+               {
+                 if (current_template_parms)
+                   {
+                     $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE);
+                     COMPOUND_STMT_NO_SCOPE ($<ttype>$) = 1;
+                     add_tree ($<ttype>$);
+                   }
+               }
+         compstmtend
+               { 
+                 if (current_template_parms)
+                   {
+                     TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
+                     TREE_CHAIN ($<ttype>2) = NULL_TREE;
+                     last_tree = $<ttype>2;
+                   }
+                 finish_stmt (); 
+               }
        | simple_stmt
        ;
 
@@ -1078,27 +950,7 @@ unary_expr:
                    }
                }
        | SIZEOF unary_expr  %prec UNARY
-               { if (TREE_CODE ($2) == COMPONENT_REF
-                     && DECL_BIT_FIELD (TREE_OPERAND ($2, 1)))
-                   error ("sizeof applied to a bit-field");
-                 /* ANSI says arrays and functions are converted inside comma.
-                    But we can't really convert them in build_compound_expr
-                    because that would break commas in lvalues.
-                    So do the conversion here if operand was a comma.  */
-                 if (TREE_CODE ($2) == COMPOUND_EXPR
-                     && (TREE_CODE (TREE_TYPE ($2)) == ARRAY_TYPE
-                         || TREE_CODE (TREE_TYPE ($2)) == FUNCTION_TYPE))
-                   $2 = default_conversion ($2);
-                 else if (TREE_CODE ($2) == TREE_LIST)
-                   {
-                     tree t = TREE_VALUE ($2);
-                     if (t != NULL_TREE
-                         && ((TREE_TYPE (t)
-                             && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
-                             || is_overloaded_fn (t)))
-                       pedwarn ("ANSI C++ forbids taking the sizeof a function type");
-                   }
-                 $$ = c_sizeof (TREE_TYPE ($2)); }
+               { $$ = expr_sizeof ($2); }
        | SIZEOF '(' type_id ')'  %prec HYPERUNARY
                { $$ = c_sizeof (groktypename ($3)); }
        | ALIGNOF unary_expr  %prec UNARY
@@ -1243,15 +1095,10 @@ expr_no_commas:
        | expr_no_commas '?' xexpr ':' expr_no_commas
                { $$ = build_x_conditional_expr ($$, $3, $5); }
        | expr_no_commas '=' expr_no_commas
-               { $$ = build_modify_expr ($$, NOP_EXPR, $3);
+               { $$ = build_x_modify_expr ($$, NOP_EXPR, $3);
                   C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
        | expr_no_commas ASSIGN expr_no_commas
-               { register tree rval;
-                 if ((rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3,
-                                            make_node ($2))))
-                   $$ = rval;
-                 else
-                   $$ = build_modify_expr ($$, $2, $3); }
+               { $$ = build_x_modify_expr ($$, $2, $3); }
        | THROW
                { $$ = build_throw (NULL_TREE); }
        | THROW expr_no_commas
@@ -1308,12 +1155,18 @@ primary:
                  if (TREE_CODE ($$) == BIT_NOT_EXPR)
                    $$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($$, 0));
                  else
-                   $$ = do_identifier ($$);
+                   $$ = do_identifier ($$, 1);
                }               
        | CONSTANT
        | boolean.literal
        | string
-               { $$ = combine_strings ($$); }
+               {
+                 if (current_template_parms)
+                   push_obstacks (&permanent_obstack, &permanent_obstack);
+                 $$ = combine_strings ($$);
+                 if (current_template_parms)
+                   pop_obstacks ();
+               }
        | '(' expr ')'
                { char class;
                  $$ = $2;
@@ -1362,16 +1215,11 @@ primary:
                    $$ = $3;
                }
        | primary '(' nonnull_exprlist ')'
-                { /* [eichin:19911016.1902EST] */
-                  $<ttype>$ = build_x_function_call ($1, $3, current_class_decl); 
-                  /* here we instantiate_class_template as needed... */
-                  do_pending_templates ();
-                } template_instantiate_some {
-                  if (TREE_CODE ($<ttype>5) == CALL_EXPR
-                      && TREE_TYPE ($<ttype>5) != void_type_node)
-                   $$ = require_complete_type ($<ttype>5);
-                  else
-                    $$ = $<ttype>5;
+                {
+                  $$ = build_x_function_call ($1, $3, current_class_decl); 
+                  if (TREE_CODE ($$) == CALL_EXPR
+                      && TREE_TYPE ($$) != void_type_node)
+                   $$ = require_complete_type ($$);
                 }
        | primary LEFT_RIGHT
                 {
@@ -1498,65 +1346,37 @@ primary:
                { tree type = groktypename ($3);
                  $$ = get_typeid (TYPE_MAIN_VARIANT (type)); }
        | global_scope IDENTIFIER
-               {
-               do_scoped_id:
-                 $$ = IDENTIFIER_GLOBAL_VALUE ($2);
-                 if (yychar == YYEMPTY)
-                   yychar = YYLEX;
-                 if (! $$)
-                   {
-                     if (yychar == '(' || yychar == LEFT_RIGHT)
-                       $$ = implicitly_declare ($2);
-                     else
-                       {
-                         if (IDENTIFIER_GLOBAL_VALUE ($2) != error_mark_node)
-                           error ("undeclared variable `%s' (first use here)",
-                                  IDENTIFIER_POINTER ($2));
-                         $$ = error_mark_node;
-                         /* Prevent repeated error messages.  */
-                         IDENTIFIER_GLOBAL_VALUE ($2) = error_mark_node;
-                       }
-                   }
-                 else
-                   {
-                     if (TREE_CODE ($$) == ADDR_EXPR)
-                       mark_used (TREE_OPERAND ($$, 0));
-                     else
-                       mark_used ($$);
-                   }
-                 if (TREE_CODE ($$) == CONST_DECL)
-                   {
-                     /* XXX CHS - should we set TREE_USED of the constant? */
-                     $$ = DECL_INITIAL ($$);
-                     /* This is to prevent an enum whose value is 0
-                        from being considered a null pointer constant.  */
-                     $$ = build1 (NOP_EXPR, TREE_TYPE ($$), $$);
-                     TREE_CONSTANT ($$) = 1;
-                   }
-
-               }
+               { $$ = do_scoped_id ($2, 1); }
        | global_scope operator_name
                {
                  got_scope = NULL_TREE;
                  if (TREE_CODE ($2) == IDENTIFIER_NODE)
-                   goto do_scoped_id;
-                 $$ = $2;
+                   $$ = do_scoped_id ($2, 1);
+                 else
+                   $$ = $2;
                }
        | overqualified_id %prec HYPERUNARY
                { $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
        | overqualified_id '(' nonnull_exprlist ')'
-               { $$ = build_member_call (OP0 ($$), OP1 ($$), $3); }
+               { if (current_template_parms)
+                   $$ = build_min_nt (CALL_EXPR, copy_to_permanent ($1), $3, 0);
+                 else
+                   $$ = build_member_call (OP0 ($$), OP1 ($$), $3); }
        | overqualified_id LEFT_RIGHT
-               { $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
+               { if (current_template_parms)
+                   $$ = build_min_nt (CALL_EXPR, copy_to_permanent ($1), 
+                                      NULL_TREE, 0);
+                 else
+                   $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
        | object unqualified_id  %prec UNARY
-               { got_object = NULL_TREE;
-                 $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
+               { $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
        | object overqualified_id %prec UNARY
-               { got_object = NULL_TREE;
-                 $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
+               { if (current_template_parms)
+                   $$ = build_min_nt (COMPONENT_REF, $1, copy_to_permanent ($2));
+                 else
+                   $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
        | object unqualified_id '(' nonnull_exprlist ')'
                {
-                 got_object = NULL_TREE;
 #if 0
                  /* This is a future direction of this code, but because
                     build_x_function_call cannot always undo what is done
@@ -1572,7 +1392,6 @@ primary:
                }
        | object unqualified_id LEFT_RIGHT
                {
-                 got_object = NULL_TREE;
 #if 0
                  /* This is a future direction of this code, but because
                     build_x_function_call cannot always undo what is done
@@ -1588,7 +1407,6 @@ primary:
                }
        | object overqualified_id '(' nonnull_exprlist ')'
                {
-                 got_object = NULL_TREE;
                  if (IS_SIGNATURE (OP0 ($2)))
                    {
                      warning ("signature name in scope resolution ignored");
@@ -1600,7 +1418,6 @@ primary:
                }
        | object overqualified_id LEFT_RIGHT
                {
-                 got_object = NULL_TREE;
                  if (IS_SIGNATURE (OP0 ($2)))
                    {
                      warning ("signature name in scope resolution ignored");
@@ -1613,7 +1430,6 @@ primary:
        /* p->int::~int() is valid -- 12.4 */
        | object '~' TYPESPEC LEFT_RIGHT
                {
-                 got_object = NULL_TREE;
                  if (IDENTIFIER_GLOBAL_VALUE ($3)
                      && (TREE_CODE (TREE_TYPE ($1)) 
                          != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3)))))
@@ -1622,7 +1438,6 @@ primary:
                }
        | object TYPESPEC SCOPE '~' TYPESPEC LEFT_RIGHT
                {
-                 got_object = NULL_TREE;
                  if ($2 != $5)
                    cp_error ("destructor specifier `%T::~%T()' must have matching names", $2, $5);
                  if (TREE_CODE (TREE_TYPE ($1))
@@ -1632,7 +1447,6 @@ primary:
                }
        | object error
                {
-                 got_object = NULL_TREE;
                  $$ = error_mark_node;
                }
        ;
@@ -2126,6 +1940,9 @@ maybe_init:
        | '=' init
                { $$ = $2; }
 
+/* If we are processing a template, we don't want to expand this
+   initializer yet.  */
+
 init:
          expr_no_commas %prec '='
        | '{' '}'
@@ -2159,6 +1976,25 @@ initlist:
                { $$ = tree_cons ($3, $5, $$); }
        ;
 
+fn.defpen:
+       PRE_PARSED_FUNCTION_DECL
+               { start_function (NULL_TREE, TREE_VALUE ($1),
+                                 NULL_TREE, NULL_TREE, 1);
+                 reinit_parse_for_function (); }
+
+pending_inlines:
+       /* empty */
+       | pending_inlines fn.defpen maybe_return_init ctor_initializer_opt
+         compstmt_or_error
+               {
+                 finish_function (lineno, (int)$4, 0);
+                 process_next_inline ($2);
+               }
+       | pending_inlines fn.defpen maybe_return_init function_try_block
+               { process_next_inline ($2); }
+         eat_saved_input
+       ;
+
 structsp:
          ENUM identifier '{'
                { $<itype>3 = suspend_momentary ();
@@ -2184,8 +2020,10 @@ structsp:
                { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); }
        | ENUM complex_type_name
                { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); }
-       | TYPENAME_KEYWORD complex_type_name
-               { $$ = $2; }
+       | TYPENAME_KEYWORD nested_name_specifier identifier
+               { $$ = make_typename_type ($2, $3); }
+       | TYPENAME_KEYWORD global_scope nested_name_specifier identifier
+               { $$ = make_typename_type ($3, $4); }
        /* C++ extensions, merged with C to avoid shift/reduce conflicts */
        | class_head left_curly opt.component_decl_list '}' maybe_attribute
                {
@@ -2195,7 +2033,7 @@ structsp:
 #if 0
                  /* Need to rework class nesting in the
                     presence of nested classes, etc.  */
-                 shadow_tag (CLASSTYPE_AS_LIST ($$)); */
+                 shadow_tag (CLASSTYPE_AS_LIST ($1)); */
 #endif
                  if (yychar == YYEMPTY)
                    yychar = YYLEX;
@@ -2203,38 +2041,26 @@ structsp:
                  /* finish_struct nukes this anyway; if
                     finish_exception does too, then it can go. */
                  if (semi)
-                   note_got_semicolon ($$);
+                   note_got_semicolon ($1);
 
-                 if (TREE_CODE ($$) == ENUMERAL_TYPE)
-                   /* $$ = $1 from default rule.  */;
+                 if (TREE_CODE ($1) == ENUMERAL_TYPE)
+                   ;
                  else
                    {
-                     $$ = finish_struct ($$, $3, $5, semi);
-                     if (semi) note_got_semicolon ($$);
+                     $<ttype>$ = finish_struct ($1, $3, $5, semi);
+                     if (semi) note_got_semicolon ($<ttype>$);
                    }
 
                  pop_obstacks ();
 
-                 id = TYPE_IDENTIFIER ($$);
-                 if (id && IDENTIFIER_TEMPLATE (id))
-                   {
-                     tree decl;
-
-                     /* I don't know if the copying of this TYPE_DECL is
-                      * really needed.  However, it's such a small per-
-                      * formance penalty that the extra safety is a bargain.
-                      * - niklas@appli.se
-                      */
-                     push_obstacks (&permanent_obstack, &permanent_obstack);
-                     decl = copy_node (lookup_name (id, 0));
-                     if (DECL_LANG_SPECIFIC (decl))
-                       copy_lang_decl (decl);
-                     pop_obstacks ();
-                     undo_template_name_overload (id, 0);
-                     pushdecl_top_level (decl);
-                   }
                  if (! semi)
-                   check_for_missing_semicolon ($$); }
+                   check_for_missing_semicolon ($1); 
+                 if (pending_inlines 
+                     && current_scope () == current_function_decl)
+                   do_pending_inlines ();
+               }
+         pending_inlines
+               { $$ = $<ttype>6; }
        | class_head  %prec EMPTY
                {
                  /* struct B: public A; is not accepted by the WP grammar.  */
@@ -2267,39 +2093,23 @@ aggr:     AGGR
                { error ("no body nor ';' separates two class, struct or union declarations"); }
        ;
 
-specialization:
-         aggr template_type_name ';'
-               { 
-                 yyungetc (';', 1); current_aggr = $$; $$ = $2; 
-                 if ($<ttype>0 == ridpointers[(int) RID_TEMPLATE])
-                   instantiate_class_template ($$, 2);
-               }
-       ;
-
 named_class_head_sans_basetype:
          aggr identifier
                { current_aggr = $$; $$ = $2; }
-       | specialization
        ;
 
 named_class_head_sans_basetype_defn:
          aggr identifier_defn %prec EMPTY
                { current_aggr = $$; $$ = $2; }
-       | aggr template_type_name '{'
-               { yyungetc ('{', 1);
-               aggr2:
-                 current_aggr = $$;
-                 $$ = $2;
-                 overload_template_name ($$, 0); }
-       | aggr template_type_name ':'
-               { yyungetc (':', 1); goto aggr2; }
        ;
 
 named_complex_class_head_sans_basetype:
          aggr nested_name_specifier identifier
                { current_aggr = $$; $$ = $3; }
-       | aggr template_type %prec EMPTY
+       | aggr template_type
                { current_aggr = $$; $$ = $2; }
+       | aggr nested_name_specifier template_type
+               { current_aggr = $$; $$ = $3; }
        ;
 
 do_xref_defn: /* empty */ %prec EMPTY
@@ -2320,7 +2130,7 @@ named_class_head:
                { 
                  $$ = TREE_TYPE ($1);
                  if ($2)
-                   xref_basetypes (current_aggr, $1, TREE_TYPE ($1), $2); 
+                   xref_basetypes (current_aggr, $1, $$, $2); 
                }
        ;
 
@@ -2506,8 +2316,19 @@ left_curly: '{'
                       pushtag (TYPE_IDENTIFIER ($<ttype>0), t, 0);
                       $<ttype>0 = t;
                     }
+                 if (current_template_parms && TYPE_CONTEXT (t)
+                     && ! current_class_type)
+                   push_template_decl (TYPE_STUB_DECL (t));
                  pushclass (t, 0);
                  TYPE_BEING_DEFINED (t) = 1;
+                 if (IS_AGGR_TYPE (t) && CLASSTYPE_USE_TEMPLATE (t))
+                   {
+                     if (CLASSTYPE_IMPLICIT_INSTANTIATION (t)
+                         && TYPE_SIZE (t) == NULL_TREE)
+                       SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
+                     else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
+                       cp_error ("specialization after instantiation of `%T'", t);
+                   }
                  /* Reset the interface data, at the earliest possible
                     moment, as it might have been set via a class foo;
                     before.  */
@@ -2650,6 +2471,13 @@ component_decl_1:
        | typed_declspecs '(' parmlist ')' type_quals exception_specification_opt maybeasm maybe_attribute maybe_init
                { tree specs, attrs;
                  split_specs_attrs ($1, &specs, &attrs);
+                 if (TREE_VALUE (specs) == current_class_type)
+                   {
+                     if (TREE_CHAIN (specs) == NULL_TREE)
+                       specs = get_decl_list (current_class_name);
+                     else
+                       TREE_VALUE (specs) = current_class_name;
+                   } 
                  $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
                                         $3, $5);
                  $$ = grokfield ($$, TREE_CHAIN (specs), $6, $9, $7,
@@ -2657,6 +2485,13 @@ component_decl_1:
        | typed_declspecs LEFT_RIGHT type_quals exception_specification_opt maybeasm maybe_attribute maybe_init
                { tree specs, attrs;
                  split_specs_attrs ($1, &specs, &attrs);
+                 if (TREE_VALUE (specs) == current_class_type)
+                   {
+                     if (TREE_CHAIN (specs) == NULL_TREE)
+                       specs = get_decl_list (current_class_name);
+                     else
+                       TREE_VALUE (specs) = current_class_name;
+                   } 
                  $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
                                         empty_parms (), $3);
                  $$ = grokfield ($$, TREE_CHAIN (specs), $4, $7, $5,
@@ -2900,7 +2735,7 @@ complete_type_name:
 
 nested_type:
        nested_name_specifier type_name %prec EMPTY
-               { $$ = identifier_typedecl_value ($2); }
+               { $$ = get_type_decl ($2); }
        ;
 
 direct_after_type_declarator:
@@ -3028,7 +2863,7 @@ nested_name_specifier_1:
        | NSNAME SCOPE
                { got_scope = $$ = $1; }
        | template_type SCOPE
-               { got_scope = $$ = TREE_TYPE ($1); }
+               { got_scope = $$ = complete_type (TREE_TYPE ($1)); }
 /*     These break 'const i;'
        | IDENTIFIER SCOPE
                {
@@ -3181,17 +3016,11 @@ errstmt:  error ';'
   set up to point at this one.  */
 
 .pushlevel:  /* empty */
-               { emit_line_note (input_filename, lineno);
-                 pushlevel (0);
-                 clear_last_expr ();
-                 push_momentary ();
-                 expand_start_bindings (0); }
+               { do_pushlevel (); }
        ;
 
 .poplevel:   /* empty */
-               { expand_end_bindings (getdecls (), kept_level_p (), 1);
-                 $$ = poplevel (kept_level_p (), 1, 0);
-                 pop_momentary (); }
+               { $$ = do_poplevel (); }
        ;
 
 /* Read zero or more forward-declarations for labels
@@ -3228,24 +3057,88 @@ compstmt_or_error:
        | error compstmt
        ;
 
-compstmt: '{' .pushlevel compstmtend .poplevel
-               { $$ = $4; }
+compstmt: '{'
+               {
+                 if (current_template_parms)
+                   {
+                     $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE);
+                     add_tree ($<ttype>$);
+                   }
+               }
+         .pushlevel compstmtend .poplevel
+               {
+                 if (current_template_parms)
+                   {
+                     TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
+                     TREE_CHAIN ($<ttype>2) = NULL_TREE;
+                     last_tree = $<ttype>2;
+                   }
+                 $$ = $5;
+               }
        ;
 
 simple_if:
          IF
-               { cond_stmt_keyword = "if"; }
+               {
+                 if (current_template_parms)
+                   {
+                     $<ttype>$ = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE,
+                                               NULL_TREE);
+                     add_tree ($<ttype>$);
+                   }
+                  cond_stmt_keyword = "if";
+               }
          .pushlevel paren_cond_or_null
-               { emit_line_note (input_filename, lineno);
-                 expand_start_cond ($4, 0); }
+               {
+                 if (current_template_parms)
+                   {
+                     if (last_tree != $<ttype>2)
+                       {
+                         TREE_OPERAND ($<ttype>2, 0) = last_tree;
+                         TREE_CHAIN ($<ttype>2) = NULL_TREE;
+                         last_tree = $<ttype>2;
+                       }
+                     else
+                       TREE_OPERAND ($<ttype>2, 0) = $4;
+                   }
+                 else
+                   {
+                     emit_line_note (input_filename, lineno);
+                     expand_start_cond ($4, 0);
+                   }
+               }
          implicitly_scoped_stmt
+               {
+                 if (current_template_parms)
+                   {
+                     TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2);
+                     TREE_CHAIN ($<ttype>2) = NULL_TREE;
+                     $<ttype>$ = last_tree = $<ttype>2;
+                   }
+               }
        ;
 
 implicitly_scoped_stmt:
          compstmt
                { finish_stmt (); }
-       | .pushlevel simple_stmt .poplevel
-               { $$ = $3; }
+       | .pushlevel
+               {
+                 if (current_template_parms)
+                   {
+                     $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE);
+                     add_tree ($<ttype>$);
+                   }
+               }
+         simple_stmt .poplevel
+               {
+                 if (current_template_parms)
+                   {
+                     TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
+                     TREE_CHAIN ($<ttype>2) = NULL_TREE;
+                     last_tree = $<ttype>2;
+                   }
+                 $$ = $4;
+               }
        ;
 
 stmt:
@@ -3260,53 +3153,136 @@ simple_stmt:
        | expr ';'
                {
                  tree expr = $1;
-                 emit_line_note (input_filename, lineno);
-                 /* Do default conversion if safe and possibly important,
-                    in case within ({...}).  */
-                 if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
-                      && lvalue_p (expr))
-                     || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
-                   expr = default_conversion (expr);
+                 if (! current_template_parms)
+                   {
+                     emit_line_note (input_filename, lineno);
+                     /* Do default conversion if safe and possibly important,
+                        in case within ({...}).  */
+                     if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
+                          && lvalue_p (expr))
+                         || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
+                       expr = default_conversion (expr);
+                   }
                  cplus_expand_expr_stmt (expr);
                  clear_momentary ();
                  finish_stmt (); }
        | simple_if ELSE
-               { expand_start_else (); }
+               { if (! current_template_parms) expand_start_else (); }
          implicitly_scoped_stmt
-               { expand_end_cond (); }
+               {
+                 if (current_template_parms)
+                   {
+                     TREE_OPERAND ($<ttype>1, 2) = TREE_CHAIN ($<ttype>1);
+                     TREE_CHAIN ($<ttype>1) = NULL_TREE;
+                     last_tree = $<ttype>1;
+                   }
+                 else
+                   expand_end_cond ();
+               }
          .poplevel
                { finish_stmt (); }
        | simple_if %prec IF
-               { expand_end_cond ();
+               { if (! current_template_parms) expand_end_cond ();
                  expand_end_bindings (getdecls (), kept_level_p (), 1);
                  poplevel (kept_level_p (), 1, 0);
                  pop_momentary ();
                  finish_stmt (); }
        | WHILE
-               { emit_nop ();
-                 emit_line_note (input_filename, lineno);
-                 expand_start_loop (1);
-                 cond_stmt_keyword = "while"; }
+               {
+                 if (current_template_parms)
+                   {
+                     $<ttype>$ = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
+                     add_tree ($<ttype>$);
+                   }
+                 else
+                   {
+                     emit_nop ();
+                     emit_line_note (input_filename, lineno);
+                     expand_start_loop (1); 
+                   }
+                 cond_stmt_keyword = "while";
+               }
          .pushlevel paren_cond_or_null
-               { expand_exit_loop_if_false (0, $4); }
+               {
+                 if (current_template_parms)
+                   {
+                     if (last_tree != $<ttype>2)
+                       {
+                         TREE_OPERAND ($<ttype>2, 0) = last_tree;
+                         TREE_CHAIN ($<ttype>2) = NULL_TREE;
+                         last_tree = $<ttype>2;
+                       }
+                     else
+                       TREE_OPERAND ($<ttype>2, 0) = $4;
+                   }
+                 else
+                   {
+                     emit_line_note (input_filename, lineno);
+                     expand_exit_loop_if_false (0, $4);
+                   }
+               }
          already_scoped_stmt .poplevel
-               { expand_end_loop ();
-                 finish_stmt (); }
+               {
+                 if (current_template_parms)
+                   {
+                     TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2);
+                     TREE_CHAIN ($<ttype>2) = NULL_TREE;
+                     last_tree = $<ttype>2;
+                   }
+                 else
+                   expand_end_loop ();
+                 finish_stmt ();
+               }
        | DO
-               { emit_nop ();
-                 emit_line_note (input_filename, lineno);
-                 expand_start_loop_continue_elsewhere (1); }
+               {
+                 if (current_template_parms)
+                   {
+                     $<ttype>$ = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
+                     add_tree ($<ttype>$);
+                   }
+                 else
+                   {
+                     emit_nop ();
+                     emit_line_note (input_filename, lineno);
+                     expand_start_loop_continue_elsewhere (1);
+                   }
+               }
          implicitly_scoped_stmt WHILE
-               { expand_loop_continue_here ();
-                 cond_stmt_keyword = "do"; }
+               {
+                 if (current_template_parms)
+                   {
+                     TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
+                     TREE_CHAIN ($<ttype>2) = NULL_TREE;
+                     last_tree = $<ttype>2;
+                   }
+                 else
+                   {
+                     expand_loop_continue_here ();
+                     cond_stmt_keyword = "do";
+                   }
+               }
          paren_expr_or_null ';'
-               { emit_line_note (input_filename, lineno);
-                 expand_exit_loop_if_false (0, $6);
-                 expand_end_loop ();
+               {
+                 if (current_template_parms)
+                   TREE_OPERAND ($<ttype>2, 1) = $6;
+                 else
+                   {
+                     emit_line_note (input_filename, lineno);
+                     expand_exit_loop_if_false (0, $6);
+                     expand_end_loop ();
+                   }
                  clear_momentary ();
-                 finish_stmt (); }
+                 finish_stmt ();
+               }
        | FOR
-               { emit_line_note (input_filename, lineno);
+               { if (current_template_parms)
+                   {
+                     $<ttype>$ = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE, 
+                                               NULL_TREE, NULL_TREE);
+                     add_tree ($<ttype>$);
+                   }
+                  else
+                   emit_line_note (input_filename, lineno);
                  if (flag_new_for_scope > 0)
                    {
                      /* Conditionalize .pushlevel */
@@ -3318,22 +3294,66 @@ simple_stmt:
                    }
                }
          '(' for.init.statement
-               { emit_nop ();
-                 emit_line_note (input_filename, lineno);
-                 expand_start_loop_continue_elsewhere (1); }
+               {
+                 if (current_template_parms)
+                   {
+                     if (last_tree != $<ttype>2)
+                       {
+                         TREE_OPERAND ($<ttype>2, 0) = last_tree;
+                         TREE_CHAIN ($<ttype>2) = NULL_TREE;
+                         last_tree = $<ttype>2;
+                       }
+                   }
+                 else
+                   {
+                     emit_nop ();
+                     emit_line_note (input_filename, lineno);
+                     expand_start_loop_continue_elsewhere (1); 
+                   }
+               }
          .pushlevel xcond ';'
-               { emit_line_note (input_filename, lineno);
-                 if ($7) expand_exit_loop_if_false (0, $7); }
+               {
+                 if (current_template_parms)
+                   {
+                     if (last_tree != $<ttype>2)
+                       {
+                         TREE_OPERAND ($<ttype>2, 1) = last_tree;
+                         TREE_CHAIN ($<ttype>2) = NULL_TREE;
+                         last_tree = $<ttype>2;
+                       }
+                     else
+                       TREE_OPERAND ($<ttype>2, 1) = $7;
+                   }
+                 else
+                   {
+                     emit_line_note (input_filename, lineno);
+                     if ($7) expand_exit_loop_if_false (0, $7);
+                   }
+               }
          xexpr ')'
                /* Don't let the tree nodes for $10 be discarded
                   by clear_momentary during the parsing of the next stmt.  */
-               { push_momentary (); }
+               {
+                 if (current_template_parms)
+                   TREE_OPERAND ($<ttype>2, 2) = $10;
+                 push_momentary ();
+               }
          already_scoped_stmt .poplevel
-               { emit_line_note (input_filename, lineno);
-                 expand_loop_continue_here ();
-                 if ($10) cplus_expand_expr_stmt ($10);
+               {
+                 if (current_template_parms)
+                   {
+                     TREE_OPERAND ($<ttype>2, 3) = TREE_CHAIN ($<ttype>2);
+                     TREE_CHAIN ($<ttype>2) = NULL_TREE;
+                     last_tree = $<ttype>2;
+                   }
+                 else
+                   {
+                     emit_line_note (input_filename, lineno);
+                     expand_loop_continue_here ();
+                     if ($10) cplus_expand_expr_stmt ($10);
+                     expand_end_loop ();
+                   }
                  pop_momentary ();
-                 expand_end_loop ();
                  if (flag_new_for_scope > 0)
                    {
                      expand_end_bindings (getdecls (), kept_level_p (), 1);
@@ -3342,98 +3362,57 @@ simple_stmt:
                    }
                  finish_stmt (); }
        | SWITCH .pushlevel '(' condition ')'
-               { emit_line_note (input_filename, lineno);
-                 c_expand_start_case ($4);
+               {
+                 if (current_template_parms)
+                   {
+                     $<ttype>$ = build_min_nt (SWITCH_STMT, $4, NULL_TREE);
+                     add_tree ($<ttype>$);
+                   }
+                 else
+                   {
+                     emit_line_note (input_filename, lineno);
+                     c_expand_start_case ($4);
+                   }
                  push_switch ();
                  /* Don't let the tree nodes for $4 be discarded by
                     clear_momentary during the parsing of the next stmt.  */
-                 push_momentary (); }
+                 push_momentary ();
+               }
          implicitly_scoped_stmt
-               { expand_end_case ($4);
+               {
+                 if (current_template_parms)
+                   {
+                     TREE_OPERAND ($<ttype>6, 1) = TREE_CHAIN ($<ttype>6);
+                     TREE_CHAIN ($<ttype>6) = NULL_TREE;
+                     last_tree = $<ttype>6;
+                   }
+                 else
+                   expand_end_case ($4);
                  pop_momentary ();
-                 pop_switch (); }
+                 pop_switch (); 
+               }
          .poplevel
                { finish_stmt (); }
        | CASE expr_no_commas ':'
-               { register tree value = check_cp_case_value ($2);
-                 register tree label
-                   = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
-                 if (value != error_mark_node)
-                   {
-                     tree duplicate;
-                     int success = pushcase (value, convert_and_check,
-                                             label, &duplicate);
-                     if (success == 1)
-                       cp_error ("case label `%E' not within a switch statement", $2);
-                     else if (success == 2)
-                       {
-                         cp_error ("duplicate case value `%E'", $2);
-                         cp_error_at ("previously used here", duplicate);
-                       }
-                     else if (success == 3)
-                       warning ("case value out of range");
-                     else if (success == 5)
-                       cp_error ("case label `%E' within scope of cleanup or variable array", $2);
-                   }
-                 define_case_label (label);
-               }
+               { do_case ($2, NULL_TREE); }
          stmt
        | CASE expr_no_commas ELLIPSIS expr_no_commas ':'
-               { register tree value1 = check_cp_case_value ($2);
-                 register tree value2 = check_cp_case_value ($4);
-                 register tree label
-                   = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
-                 if (pedantic)
-                   pedwarn ("ANSI C++ forbids range expressions in switch statement");
-                 if (value1 != error_mark_node
-                     && value2 != error_mark_node)
-                   {
-                     tree duplicate;
-                     int success = pushcase_range (value1, value2,
-                                                   convert_and_check, label,
-                                                   &duplicate);
-                     if (success == 1)
-                       error ("case label not within a switch statement");
-                     else if (success == 2)
-                       {
-                         error ("duplicate (or overlapping) case value");
-                         error_with_decl (duplicate, "this is the first entry overlapping that value");
-                       }
-                     else if (success == 3)
-                       warning ("case value out of range");
-                     else if (success == 4)
-                       warning ("empty range specified");
-                     else if (success == 5)
-                       error ("case label within scope of cleanup or variable array");
-                   }
-                 define_case_label (label);
-               }
+               { do_case ($2, $4); }
          stmt
        | DEFAULT ':'
-               {
-                 tree duplicate;
-                 register tree label
-                   = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-                 int success = pushcase (NULL_TREE, 0, label, &duplicate);
-                 if (success == 1)
-                   error ("default label not within a switch statement");
-                 else if (success == 2)
-                   {
-                     error ("multiple default labels in one switch");
-                     error_with_decl (duplicate, "this is the first default label");
-                   }
-                 define_case_label (NULL_TREE);
-               }
+               { do_case (NULL_TREE, NULL_TREE); }
          stmt
        | BREAK ';'
                { emit_line_note (input_filename, lineno);
-                 if ( ! expand_exit_something ())
+                 if (current_template_parms)
+                   add_tree (build_min_nt (BREAK_STMT));
+                 else if ( ! expand_exit_something ())
                    error ("break statement not within loop or switch"); }
        | CONTINUE ';'
                { emit_line_note (input_filename, lineno);
-                 if (! expand_continue_loop (0))
+                 if (current_template_parms)
+                   add_tree (build_min_nt (CONTINUE_STMT));
+                 else if (! expand_continue_loop (0))
                    error ("continue statement not within a loop"); }
        | RETURN ';'
                { emit_line_note (input_filename, lineno);
@@ -3478,14 +3457,26 @@ simple_stmt:
                  finish_stmt ();
                }
        | GOTO '*' expr ';'
-               { emit_line_note (input_filename, lineno);
-                 expand_computed_goto ($3); }
+               {
+                 if (current_template_parms)
+                   add_tree (build_min_nt (GOTO_STMT, $3));
+                 else
+                   { emit_line_note (input_filename, lineno);
+                     expand_computed_goto ($3); }
+               }
        | GOTO identifier ';'
-               { tree decl;
-                 emit_line_note (input_filename, lineno);
-                 decl = lookup_label ($2);
-                 TREE_USED (decl) = 1;
-                 expand_goto (decl); }
+               {
+                 if (current_template_parms)
+                   add_tree (build_min_nt (GOTO_STMT, $2));
+                 else
+                   {
+                     tree decl;
+                     emit_line_note (input_filename, lineno);
+                     decl = lookup_label ($2);
+                     TREE_USED (decl) = 1;
+                     expand_goto (decl); 
+                   }
+               }
        | label_colon stmt
                { finish_stmt (); }
        | label_colon '}'
@@ -3563,7 +3554,7 @@ label_colon:
                { tree label;
                do_label:
                  label = define_label (input_filename, lineno, $1);
-                 if (label)
+                 if (label && ! minimal_parse_mode)
                    expand_label (label);
                }
        | PTYPENAME ':'
index ffc7f33f1ba1444437d72b7c478856040f5a5b8e..5a30c9a2301a5c1dc0d54b08a96fe14d294c6262 100644 (file)
@@ -25,8 +25,6 @@ Boston, MA 02111-1307, USA.  */
    * interface/impl data is taken from file defining the template
    * all methods must be provided in header files; can't use a source
      file that contains only the method templates and "just win"
-   * method templates must be seen before the expansion of the
-     class template is done
  */
 
 #include "config.h"
@@ -48,40 +46,37 @@ extern int lineno;
 extern char *input_filename;
 struct pending_inline *pending_template_expansions;
 
-int processing_template_decl;
-int processing_template_defn;
+tree current_template_parms;
+HOST_WIDE_INT processing_template_decl;
 
-/* This is a kludge to handle instantiation of template methods that are
-   used before their definition.  It should not be necessary after the
-   template rewrite.  */
-static tree template_classes;
+tree pending_templates;
+static tree *template_tail = &pending_templates;
+
+int minimal_parse_mode;
 
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
 static int unify ();
-static void add_pending_template ();
 
-void overload_template_name (), pop_template_decls ();
+void pop_template_decls ();
+
+tree classtype_mangled_name ();
+static char * mangle_class_name_for_template ();
+tree tsubst_expr_values ();
+
+/* We've got a template header coming up; push to a new level for storing
+   the parms.  */
 
-/* We've got a template header coming up; set obstacks up to save the
-   nodes created permanently.  (There might be cases with nested templates
-   where we don't have to do this, but they aren't implemented, and it
-   probably wouldn't be worth the effort.)  */
 void
 begin_template_parm_list ()
 {
   pushlevel (0);
-  push_obstacks (&permanent_obstack, &permanent_obstack);
-  pushlevel (0);
+  declare_pseudo_global_level ();
 }
 
 /* Process information from new template parameter NEXT and append it to the
-   LIST being built.  The rules for use of a template parameter type name
-   by later parameters are not well-defined for us just yet.  However, the
-   only way to avoid having to parse expressions of unknown complexity (and
-   with tokens of unknown types) is to disallow it completely. So for now,
-   that is what is assumed.  */
+   LIST being built.  */
 tree
 process_template_parm (list, next)
      tree list, next;
@@ -89,12 +84,26 @@ process_template_parm (list, next)
   tree parm;
   tree decl = 0;
   tree defval;
-  int is_type;
+  int is_type, idx;
   parm = next;
   my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
   defval = TREE_PURPOSE (parm);
   parm = TREE_VALUE (parm);
   is_type = TREE_PURPOSE (parm) == class_type_node;
+
+  if (list)
+    {
+      tree p = TREE_VALUE (tree_last (list));
+
+      if (TREE_CODE (p) == TYPE_DECL)
+       idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
+      else
+       idx = TEMPLATE_CONST_IDX (DECL_INITIAL (p));
+      ++idx;
+    }
+  else
+    idx = 0;
+
   if (!is_type)
     {
       tree tinfo = 0;
@@ -120,13 +129,16 @@ process_template_parm (list, next)
       decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
       DECL_INITIAL (decl) = tinfo;
       DECL_INITIAL (parm) = tinfo;
+      TEMPLATE_CONST_SET_INFO (tinfo, idx, processing_template_decl + 1);
     }
   else
     {
-      tree t = make_node (TEMPLATE_TYPE_PARM);
+      tree t = make_lang_type (TEMPLATE_TYPE_PARM);
+      CLASSTYPE_GOT_SEMICOLON (t) = 1;
       decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t);
       TYPE_MAIN_DECL (t) = decl;
       parm = decl;
+      TEMPLATE_TYPE_SET_INFO (t, idx, processing_template_decl + 1);
     }
   SET_DECL_ARTIFICIAL (decl);
   pushdecl (decl);
@@ -143,182 +155,106 @@ tree
 end_template_parm_list (parms)
      tree parms;
 {
-  int nparms = 0;
-  int saw_default = 0;
-  tree saved_parmlist;
+  int nparms;
   tree parm;
-  for (parm = parms; parm; parm = TREE_CHAIN (parm))
-    nparms++;
-  saved_parmlist = make_tree_vec (nparms);
+  tree saved_parmlist = make_tree_vec (list_length (parms));
+
+  ++processing_template_decl;
+  current_template_parms
+    = tree_cons (build_int_2 (0, processing_template_decl),
+                saved_parmlist, current_template_parms);
 
   for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
-    {
-      tree p = TREE_VALUE (parm);
-      if (TREE_PURPOSE (parm))
-       saw_default = 1;
-      else if (saw_default)
-       {
-         error ("if a default argument is given for one template parameter");
-         error ("default arguments must be given for all subsequent");
-         error ("parameters as well");
-       }
+    TREE_VEC_ELT (saved_parmlist, nparms) = parm;
 
-      if (TREE_CODE (p) == TYPE_DECL)
-       {
-         tree t = TREE_TYPE (p);
-         TEMPLATE_TYPE_SET_INFO (t, saved_parmlist, nparms);
-       }
-      else
-       {
-         tree tinfo = DECL_INITIAL (p);
-         DECL_INITIAL (p) = NULL_TREE;
-         TEMPLATE_CONST_SET_INFO (tinfo, saved_parmlist, nparms);
-       }
-      TREE_VEC_ELT (saved_parmlist, nparms) = parm;
-    }
-  set_current_level_tags_transparency (1);
-  processing_template_decl++;
   return saved_parmlist;
 }
 
-/* end_template_decl is called after a template declaration is seen.
-   D1 is template header; D2 is class_head_sans_basetype or a
-   TEMPLATE_DECL with its DECL_RESULT field set.  */
+/* end_template_decl is called after a template declaration is seen.  */
+
 void
-end_template_decl (d1, d2, is_class, defn)
-     tree d1, d2, is_class;
-     int defn;
+end_template_decl ()
 {
-  tree decl;
-  struct template_info *tmpl;
+  /* This matches the pushlevel in begin_template_parm_list.  */
+  poplevel (0, 0, 0);
 
-  tmpl = (struct template_info *) obstack_alloc (&permanent_obstack,
-                                           sizeof (struct template_info));
-  tmpl->text = 0;
-  tmpl->length = 0;
-  tmpl->aggr = is_class;
+  --processing_template_decl;
+  current_template_parms = TREE_CHAIN (current_template_parms);
+  (void) get_pending_sizes (); /* Why? */
+}
 
-  /* cloned from reinit_parse_for_template */
-  tmpl->filename = input_filename;
-  tmpl->lineno = lineno;
-  tmpl->parm_vec = d1;          /* [eichin:19911015.2306EST] */
+void
+push_template_decl (decl)
+     tree decl;
+{
+  tree header = current_template_parms;
+  tree tmpl;
+  tree args = NULL_TREE;
+  tree info;
+  tree ctx = DECL_CONTEXT (decl) ? DECL_CONTEXT (decl) : current_class_type;
+  int primary = 0;
+
+  /* Kludge! */
+  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl)
+      && DECL_CLASS_CONTEXT (decl))
+    ;
+  /* Note that this template is a "primary template" */
+  else if (! ctx || ! CLASSTYPE_TEMPLATE_INFO (ctx)
+      /* || (processing_template_decl > CLASSTYPE_TEMPLATE_LEVEL (ctx)) */)
+    primary = 1;
 
-  if (d2 == NULL_TREE || d2 == error_mark_node)
+  while (header)
     {
-      decl = 0;
-      goto lose;
+      tree a = copy_node (TREE_VALUE (header));
+      int i = TREE_VEC_LENGTH (a);
+      TREE_TYPE (a) = NULL_TREE;
+      while (i--)
+       {
+         tree t = TREE_VALUE (TREE_VEC_ELT (a, i));
+         if (TREE_CODE (t) == TYPE_DECL)
+           t = TREE_TYPE (t);
+         else
+           t = DECL_INITIAL (t);
+         TREE_VEC_ELT (a, i) = t;
+       }
+      args = tree_cons (TREE_PURPOSE (header), a, args);
+      header = TREE_CHAIN (header);
     }
+  args = nreverse (args);
+  args = TREE_VALUE (args);
 
-  if (is_class)
+  if (! ctx || TYPE_BEING_DEFINED (ctx))
     {
-      decl = build_lang_decl (TEMPLATE_DECL, d2, NULL_TREE);
-      GNU_xref_decl (current_function_decl, decl);
+      tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
+      DECL_TEMPLATE_PARMS (tmpl) = TREE_VALUE (current_template_parms);
+      DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
     }
   else
     {
-      if (TREE_CODE (d2) == TEMPLATE_DECL)
-       decl = d2;
+      if (TREE_CODE (decl) == TYPE_DECL)
+       tmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
       else
-       {
-         /* Class destructor templates and operator templates are
-            slipping past as non-template nodes.  Process them here, since
-            I haven't figured out where to catch them earlier.  I could
-            go do that, but it's a choice between getting that done and
-            staying only N months behind schedule.  Sorry....  */
-         enum tree_code code;
-         my_friendly_assert (TREE_CODE (d2) == CALL_EXPR, 263);
-         code = TREE_CODE (TREE_OPERAND (d2, 0));
-         my_friendly_assert (code == BIT_NOT_EXPR
-                 || code == OP_IDENTIFIER
-                 || code == SCOPE_REF, 264);
-         d2 = grokdeclarator (d2, NULL_TREE, MEMFUNCDEF, 0, NULL_TREE, NULL_TREE);
-         decl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (d2),
-                                 TREE_TYPE (d2));
-         DECL_TEMPLATE_RESULT (decl) = d2;
-         DECL_CONTEXT (decl) = DECL_CONTEXT (d2);
-         DECL_CLASS_CONTEXT (decl) = DECL_CLASS_CONTEXT (d2);
-         DECL_NAME (decl) = DECL_NAME (d2);
-         TREE_TYPE (decl) = TREE_TYPE (d2);
-         if (interface_unknown && flag_external_templates
-             && ! flag_alt_external_templates
-             && ! DECL_IN_SYSTEM_HEADER (decl))
-           warn_if_unknown_interface (decl);
-         TREE_PUBLIC (decl) = TREE_PUBLIC (d2) = flag_external_templates && !interface_unknown;
-         DECL_EXTERNAL (decl) = (DECL_EXTERNAL (d2)
-                                 && !(DECL_CLASS_CONTEXT (d2)
-                                      && !DECL_THIS_EXTERN (d2)));
-       }
+       tmpl = DECL_TI_TEMPLATE (decl);
+    }
 
-      /* All routines creating TEMPLATE_DECL nodes should now be using
-        build_lang_decl, which will have set this up already.  */
-      my_friendly_assert (DECL_LANG_SPECIFIC (decl) != 0, 265);
+  DECL_TEMPLATE_RESULT (tmpl) = decl;
+  TREE_TYPE (tmpl) = TREE_TYPE (decl);
 
-      /* @@ Somewhere, permanent allocation isn't being used.  */
-      if (! DECL_TEMPLATE_IS_CLASS (decl)
-         && TREE_CODE (DECL_TEMPLATE_RESULT (decl)) == FUNCTION_DECL)
-       {
-         tree result = DECL_TEMPLATE_RESULT (decl);
-         /* Will do nothing if allocation was already permanent.  */
-         DECL_ARGUMENTS (result) = copy_to_permanent (DECL_ARGUMENTS (result));
-       }
+  if (! ctx)
+    tmpl = pushdecl_top_level (tmpl);
 
-      /* If this is for a method, there's an extra binding level here. */
-      if (DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
-       {
-         /* @@ Find out where this should be getting set!  */
-         tree r = DECL_TEMPLATE_RESULT (decl);
-         if (DECL_LANG_SPECIFIC (r) && DECL_CLASS_CONTEXT (r) == NULL_TREE)
-           DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
-       }
-    }
-  DECL_TEMPLATE_INFO (decl) = tmpl;
-  DECL_TEMPLATE_PARMS (decl) = d1;
-
-  /* So that duplicate_decls can do the right thing.  */
-  if (defn)
-    DECL_INITIAL (decl) = error_mark_node;
-  
-  /* If context of decl is non-null (i.e., method template), add it
-     to the appropriate class template, and pop the binding levels.  */
-  if (! is_class && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
+  if (primary)
+    TREE_TYPE (DECL_TEMPLATE_PARMS (tmpl)) = tmpl;
+
+  info = perm_tree_cons (tmpl, args, NULL_TREE);
+
+  if (TREE_CODE (decl) == TYPE_DECL)
     {
-      tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl));
-      tree tmpl, t;
-      my_friendly_assert (TREE_CODE (ctx) == UNINSTANTIATED_P_TYPE, 266);
-      tmpl = UPT_TEMPLATE (ctx);
-      for (t = DECL_TEMPLATE_MEMBERS (tmpl); t; t = TREE_CHAIN (t))
-       if (TREE_PURPOSE (t) == DECL_NAME (decl)
-           && duplicate_decls (decl, TREE_VALUE (t)))
-         goto already_there;
-      DECL_TEMPLATE_MEMBERS (tmpl) =
-       perm_tree_cons (DECL_NAME (decl), decl, DECL_TEMPLATE_MEMBERS (tmpl));
-    already_there:
-      poplevel (0, 0, 0);
-      poplevel (0, 0, 0);
+      CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info;
+      DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
     }
-  /* Otherwise, go back to top level first, and push the template decl
-     again there.  */
   else
-    {
-      poplevel (0, 0, 0);
-      poplevel (0, 0, 0);
-      pushdecl (decl);
-    }
- lose:
-#if 0 /* It happens sometimes, with syntactic or semantic errors.
-
-        One specific case:
-        template <class A, int X, int Y> class Foo { ... };
-        template <class A, int X, int y> Foo<X,Y>::method (Foo& x) { ... }
-        Note the missing "A" in the class containing "method".  */
-  my_friendly_assert (global_bindings_p (), 267);
-#else
-  while (! global_bindings_p ())
-    poplevel (0, 0, 0);
-#endif
-  pop_obstacks ();
-  processing_template_decl--;
-  (void) get_pending_sizes ();
+    DECL_TEMPLATE_INFO (decl) = info;
 }
 
 tree tsubst            PROTO ((tree, tree*, int, tree));
@@ -374,7 +310,8 @@ coerce_template_parms (parms, arglist, in_decl)
                arg = TREE_VALUE (arg);
            }
          else
-           arg = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
+           arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
+                         &TREE_VEC_ELT (vec, 0), i, in_decl);
 
          TREE_VEC_ELT (vec, i) = arg;
        }
@@ -388,11 +325,28 @@ coerce_template_parms (parms, arglist, in_decl)
 
       is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
       requires_type = TREE_CODE (parm) == TYPE_DECL;
+
+      if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
+         && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
+       {
+         cp_pedwarn ("to refer to a type member of a template parameter,");
+         cp_pedwarn ("  use `typename %E'", arg);
+         arg = make_typename_type (TREE_OPERAND (arg, 0),
+                                   TREE_OPERAND (arg, 1));
+         is_type = 1;
+       }
       if (is_type != requires_type)
        {
          if (in_decl)
-           cp_error ("type/value mismatch in template parameter list for `%D'",
-                     in_decl);
+           {
+             cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+                       i, in_decl);
+             if (is_type)
+               cp_error ("  expected a constant of type `%T', got `%T'",
+                         TREE_TYPE (parm), arg);
+             else
+               cp_error ("  expected a type, got `%E'", arg);
+           }
          lost++;
          TREE_VEC_ELT (vec, i) = error_mark_node;
          continue;
@@ -403,9 +357,12 @@ coerce_template_parms (parms, arglist, in_decl)
        {
          tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0),
                           TREE_VEC_LENGTH (vec), in_decl);
-         val = digest_init (t, arg, (tree *) 0);
+         if (current_template_parms && uses_template_parms (arg))
+           val = arg;
+         else
+           val = digest_init (t, arg, (tree *) 0);
 
-         if (val == error_mark_node)
+         if (val == error_mark_node || current_template_parms)
            ;
 
          /* 14.2: Other template-arguments must be constant-expressions,
@@ -467,6 +424,32 @@ coerce_template_parms (parms, arglist, in_decl)
   return vec;
 }
 
+int
+comp_template_args (oldargs, newargs)
+     tree oldargs, newargs;
+{
+  int i;
+
+  for (i = 0; i < TREE_VEC_LENGTH (oldargs); ++i)
+    {
+      tree nt = TREE_VEC_ELT (newargs, i);
+      tree ot = TREE_VEC_ELT (oldargs, i);
+
+      if (nt == ot)
+       continue;
+      if (TREE_CODE (nt) != TREE_CODE (ot))
+       return 0;
+      if (TREE_CODE (ot) == TEMPLATE_TYPE_PARM
+         && comptypes (ot, nt, 1))
+       continue;
+      if (TREE_CODE (ot) == TEMPLATE_CONST_PARM
+         && TEMPLATE_CONST_IDX (nt) == TEMPLATE_CONST_IDX (ot))
+       continue;
+      return 0;
+    }
+  return 1;
+}
+
 /* Given class template name and parameter list, produce a user-friendly name
    for the instantiation.  */
 static char *
@@ -553,6 +536,39 @@ mangle_class_name_for_template (name, parms, arglist)
   return NULL;
 }
 
+tree
+classtype_mangled_name (t)
+     tree t;
+{
+  if (CLASSTYPE_TEMPLATE_INFO (t)
+      && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
+    {
+      tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
+      char *mangled_name = mangle_class_name_for_template
+       (IDENTIFIER_POINTER (name),
+        DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
+        CLASSTYPE_TI_ARGS (t));
+      tree id = get_identifier (mangled_name);
+      IDENTIFIER_TEMPLATE (id) = name;
+      return id;
+    }
+  else
+    return TYPE_IDENTIFIER (t);
+}
+
+static void
+add_pending_template (d)
+     tree d;
+{
+  if (TREE_LANG_FLAG_0 (DECL_TEMPLATE_INFO (d)))
+    return;
+
+  *template_tail = perm_tree_cons
+    (current_function_decl, d, NULL_TREE);
+  template_tail = &TREE_CHAIN (*template_tail);
+  TREE_LANG_FLAG_0 (DECL_TEMPLATE_INFO (d)) = 1;
+}
+
 /* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of
    parameters, find the desired type.
 
@@ -569,12 +585,23 @@ lookup_template_class (d1, arglist, in_decl)
 {
   tree template, parmlist;
   char *mangled_name;
-  tree id;
+  tree id, t;
+  tree code_type_node;
+
+  if (TREE_CODE (d1) == IDENTIFIER_NODE)
+    {
+      template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */
+      if (! template)
+       template = IDENTIFIER_CLASS_VALUE (d1);
+    }
+  else if (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' && IS_AGGR_TYPE (d1))
+    {
+      template = CLASSTYPE_TI_TEMPLATE (d1);
+      d1 = DECL_NAME (template);
+    }
+  else
+    my_friendly_abort (272);
 
-  my_friendly_assert (TREE_CODE (d1) == IDENTIFIER_NODE, 272);
-  template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */
-  if (! template)
-    template = IDENTIFIER_CLASS_VALUE (d1);
   /* With something like `template <class T> class X class X { ... };'
      we could end up with D1 having nothing but an IDENTIFIER_LOCAL_VALUE.
      We don't want to do that, but we have to deal with the situation, so
@@ -588,112 +615,112 @@ lookup_template_class (d1, arglist, in_decl)
        cp_error_at ("for template declaration `%D'", in_decl);
       return error_mark_node;
     }
-  parmlist = DECL_TEMPLATE_PARMS (template);
 
-  arglist = coerce_template_parms (parmlist, arglist, template);
-  if (arglist == error_mark_node)
-    return error_mark_node;
-  if (uses_template_parms (arglist))
-    {
-      tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
-      tree d;
-      id = make_anon_name ();
-      d = build_decl (TYPE_DECL, id, t);
-      TYPE_NAME (t) = d;
-      TYPE_VALUES (t) = build_tree_list (template, arglist);
-      pushdecl_top_level (d);
-    }
+  if (TREE_CODE (TREE_TYPE (template)) == RECORD_TYPE)
+    code_type_node = (CLASSTYPE_DECLARED_CLASS (TREE_TYPE (template))
+                     ? class_type_node : record_type_node);
   else
+    code_type_node = union_type_node;
+
+  if (PRIMARY_TEMPLATE_P (template))
     {
+      parmlist = DECL_TEMPLATE_PARMS (template);
+
+      arglist = coerce_template_parms (parmlist, arglist, template);
+      if (arglist == error_mark_node)
+       return error_mark_node;
+      if (uses_template_parms (arglist))
+       {
+         tree found;
+         if (comp_template_args
+             (CLASSTYPE_TI_ARGS (TREE_TYPE (template)), arglist))
+           found = TREE_TYPE (template);
+         else
+           {
+             for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+                  found; found = TREE_CHAIN (found))
+               {
+                 if (TI_USES_TEMPLATE_PARMS (found)
+                     && comp_template_args (TREE_PURPOSE (found), arglist))
+                   break;
+               }
+             if (found)
+               found = TREE_VALUE (found);
+           }
+
+         if (found)
+           {
+             if (can_free (&permanent_obstack, arglist))
+               obstack_free (&permanent_obstack, arglist);
+             return found;
+           }
+       }
+
       mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
                                                     parmlist, arglist);
       id = get_identifier (mangled_name);
-    }
-  if (!IDENTIFIER_TEMPLATE (id))
-    {
-      arglist = copy_to_permanent (arglist);
-      IDENTIFIER_TEMPLATE (id) = perm_tree_cons (template, arglist, NULL_TREE);
-    }
-  return id;
-}
-\f
-void
-push_template_decls (parmlist, arglist, class_level)
-     tree parmlist, arglist;
-     int class_level;
-{
-  int i, nparms;
+      IDENTIFIER_TEMPLATE (id) = d1;
 
-  /* Don't want to push values into global context.  */
-  if (!class_level)
-    {
-      pushlevel (1);
-      declare_pseudo_global_level ();
+      maybe_push_to_top_level (uses_template_parms (arglist));
+      t = xref_tag (code_type_node, id, NULL_TREE, 1);
+      pop_from_top_level ();
     }
-
-  nparms = TREE_VEC_LENGTH (parmlist);
-
-  for (i = 0; i < nparms; i++)
+  else
     {
-      int requires_type, is_type;
-      tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
-      tree arg = TREE_VEC_ELT (arglist, i);
-      tree decl = 0;
+      tree ctx = lookup_template_class (TYPE_CONTEXT (TREE_TYPE (template)),
+                                       arglist, in_decl);
+      id = d1;
+      arglist = CLASSTYPE_TI_ARGS (ctx);
 
-      requires_type = TREE_CODE (parm) == TYPE_DECL;
-      is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
-      if (is_type)
+      if (TYPE_BEING_DEFINED (ctx) && ctx == current_class_type)
        {
-         /* add typename to namespace */
-         if (!requires_type)
-           {
-             error ("template use error: type provided where value needed");
-             continue;
-           }
-         decl = arg;
-         my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273);
-         decl = build_decl (TYPE_DECL, DECL_NAME (parm), decl);
+         tree save_parms = current_template_parms;
+         current_template_parms = NULL_TREE;
+         t = xref_tag (code_type_node, id, NULL_TREE, 0);
+         current_template_parms = save_parms;
        }
       else
        {
-         /* add const decl to namespace */
-         tree val;
-         tree parmtype;
-         if (requires_type)
-           {
-             error ("template use error: value provided where type needed");
-             continue;
-           }
-         parmtype = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (arglist, 0),
-                            TREE_VEC_LENGTH (arglist), NULL_TREE);
-         val = digest_init (parmtype, arg, (tree *) 0);
-         if (val != error_mark_node)
-           {
-             decl = build_decl (CONST_DECL, DECL_NAME (parm),
-                                parmtype);
-             DECL_INITIAL (decl) = val;
-             TREE_READONLY (decl) = 1;
-           }
+         t = lookup_nested_type_by_name (ctx, id);
+         my_friendly_assert (t != NULL_TREE, 42);
        }
-      if (decl != 0)
+    }
+
+  /* Seems to be wanted. */
+  CLASSTYPE_GOT_SEMICOLON (t) = 1;
+
+  if (! CLASSTYPE_TEMPLATE_INFO (t))
+    {
+      arglist = copy_to_permanent (arglist);
+      CLASSTYPE_TEMPLATE_INFO (t)
+       = perm_tree_cons (template, arglist, NULL_TREE);
+      DECL_TEMPLATE_INSTANTIATIONS (template) = perm_tree_cons
+       (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (template));
+      TI_USES_TEMPLATE_PARMS (DECL_TEMPLATE_INSTANTIATIONS (template))
+       = uses_template_parms (arglist);
+
+      SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
+
+      /* We need to set this again after CLASSTYPE_TEMPLATE_INFO is set up. */
+      DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t)) = id;
+      if (! uses_template_parms (arglist))
+       DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t)) 
+         = get_identifier (build_overload_name (t, 1, 1));
+
+      if (flag_external_templates && ! uses_template_parms (arglist)
+         && CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template))
+         && ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template)))
        {
-         SET_DECL_ARTIFICIAL (decl);
-         layout_decl (decl, 0);
-         if (class_level)
-           pushdecl_class_level (decl);
-         else
-           pushdecl (decl);
+         tree d;
+
+         instantiate_class_template (t);
+
+         for (d = TYPE_METHODS (t); d; d = TREE_CHAIN (d))
+           add_pending_template (d);
        }
     }
-}
 
-void
-pop_template_decls (parmlist, arglist, class_level)
-     tree parmlist, arglist;
-     int class_level;
-{
-  if (!class_level)
-    poplevel (0, 0, 0);
+  return t;
 }
 \f
 /* Should be defined in parse.h.  */
@@ -717,7 +744,7 @@ uses_template_parms (t)
     case IDENTIFIER_NODE:
       if (!IDENTIFIER_TEMPLATE (t))
        return 0;
-      return uses_template_parms (TREE_VALUE (IDENTIFIER_TEMPLATE (t)));
+      my_friendly_abort (42);
 
       /* aggregates of tree nodes */
     case TREE_VEC:
@@ -742,11 +769,9 @@ uses_template_parms (t)
       if (TYPE_PTRMEMFUNC_FLAG (t))
        return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (t));
     case UNION_TYPE:
-      if (!TYPE_NAME (t))
+      if (! CLASSTYPE_TEMPLATE_INFO (t))
        return 0;
-      if (!TYPE_IDENTIFIER (t))
-       return 0;
-      return uses_template_parms (TYPE_IDENTIFIER (t));
+      return uses_template_parms (TREE_VALUE (CLASSTYPE_TEMPLATE_INFO (t)));
     case FUNCTION_TYPE:
       if (uses_template_parms (TYPE_ARG_TYPES (t)))
        return 1;
@@ -768,23 +793,21 @@ uses_template_parms (t)
 
       /* decl nodes */
     case TYPE_DECL:
-      return uses_template_parms (DECL_NAME (t));
+      return uses_template_parms (TREE_TYPE (t));
+
     case FUNCTION_DECL:
-      if (uses_template_parms (TREE_TYPE (t)))
+    case VAR_DECL:
+      /* ??? What about FIELD_DECLs?  */
+      if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
+         && uses_template_parms (DECL_TI_ARGS (t)))
        return 1;
       /* fall through */
-    case VAR_DECL:
+    case CONST_DECL:
     case PARM_DECL:
-      /* ??? What about FIELD_DECLs?  */
-      /* The type of a decl can't use template parms if the name of the
-        variable doesn't, because it's impossible to resolve them.  So
-        ignore the type field for now.  */
+      if (uses_template_parms (TREE_TYPE (t)))
+       return 1;
       if (DECL_CONTEXT (t) && uses_template_parms (DECL_CONTEXT (t)))
        return 1;
-      if (uses_template_parms (TREE_TYPE (t)))
-       {
-         error ("template parms used where they can't be resolved");
-       }
       return 0;
 
     case CALL_EXPR:
@@ -821,7 +844,7 @@ uses_template_parms (t)
       /* NOTREACHED */
       return 0;
 
-    case UNINSTANTIATED_P_TYPE:
+    case TYPENAME_TYPE:
       return 1;
 
     case CONSTRUCTOR:
@@ -854,77 +877,41 @@ uses_template_parms (t)
     }
 }
 
-void
-instantiate_member_templates (classname)
-     tree classname;
-{
-  tree t;
-  tree id = classname;
-  tree members = DECL_TEMPLATE_MEMBERS (TREE_PURPOSE (IDENTIFIER_TEMPLATE (id)));
-
-  for (t = members; t; t = TREE_CHAIN (t))
-    {
-      tree parmvec, type, classparms, tdecl, t2;
-      int nparms, xxx = 0, i;
-
-      my_friendly_assert (TREE_VALUE (t) != NULL_TREE, 275);
-      my_friendly_assert (TREE_CODE (TREE_VALUE (t)) == TEMPLATE_DECL, 276);
-      /* @@ Should verify that class parm list is a list of
-        distinct template parameters, and covers all the template
-        parameters.  */
-      tdecl = TREE_VALUE (t);
-      type = DECL_CONTEXT (DECL_TEMPLATE_RESULT (tdecl));
-      classparms = UPT_PARMS (type);
-      nparms = TREE_VEC_LENGTH (classparms);
-      parmvec = make_tree_vec (nparms);
-      for (i = 0; i < nparms; i++)
-       TREE_VEC_ELT (parmvec, i) = NULL_TREE;
-      switch (unify (DECL_TEMPLATE_PARMS (tdecl),
-                    &TREE_VEC_ELT (parmvec, 0), nparms,
-                    type, IDENTIFIER_TYPE_VALUE (classname),
-                    &xxx))
-       {
-       case 0:
-         /* Success -- well, no inconsistency, at least.  */
-         for (i = 0; i < nparms; i++)
-           if (TREE_VEC_ELT (parmvec, i) == NULL_TREE)
-             goto failure;
-         t2 = instantiate_template (tdecl,
-                                    &TREE_VEC_ELT (parmvec, 0));
-         type = IDENTIFIER_TYPE_VALUE (id);
-         my_friendly_assert (type != 0, 277);
-         break;
-       case 1:
-         /* Failure.  */
-       failure:
-         cp_error_at ("type unification error instantiating `%D'", tdecl);
-         cp_error ("while instantiating members of `%T'", classname);
-
-         continue /* loop of members */;
-       default:
-         /* Eek, a bug.  */
-         my_friendly_abort (83);
-       }
-    }
-}
-
 static struct tinst_level *current_tinst_level = 0;
 static struct tinst_level *free_tinst_level = 0;
 static int tinst_depth = 0;
 int max_tinst_depth = 17;
+#ifdef GATHER_STATISTICS
+int depth_reached = 0;
+#endif
 
 int
-push_tinst_level (name)
-     tree name;
+push_tinst_level (d)
+     tree d;
 {
   struct tinst_level *new;
-  tree global = IDENTIFIER_GLOBAL_VALUE (name);
 
   if (tinst_depth >= max_tinst_depth)
     {
+      struct tinst_level *p = current_tinst_level;
+      int line = lineno;
+      char *file = input_filename;
+
       error ("template instantiation depth exceeds maximum of %d",
             max_tinst_depth);
-      cp_error ("  instantiating `%D'", name);
+      cp_error ("  instantiating `%D'", d);
+
+      for (; p; p = p->next)
+       {
+         cp_error ("  instantiated from `%D'", p->decl);
+         lineno = p->line;
+         input_filename = p->file;
+       }
+      error ("  instantiated from here");
+
+      lineno = line;
+      input_filename = file;
+
       return 0;
     }
 
@@ -936,20 +923,18 @@ push_tinst_level (name)
   else
     new = (struct tinst_level *) xmalloc (sizeof (struct tinst_level));
 
-  new->classname = name;
-  if (global)
-    {
-      new->line = DECL_SOURCE_LINE (global);
-      new->file = DECL_SOURCE_FILE (global);
-    }
-  else
-    {
-      new->line = lineno;
-      new->file = input_filename;
-    }
+  new->decl = d;
+  new->line = lineno;
+  new->file = input_filename;
   new->next = current_tinst_level;
   current_tinst_level = new;
+
   ++tinst_depth;
+#ifdef GATHER_STATISTICS
+  if (tinst_depth > depth_reached)
+    depth_reached = tinst_depth;
+#endif
+
   return 1;
 }
 
@@ -976,118 +961,218 @@ tinst_for_decl ()
 }
 
 tree
-instantiate_class_template (classname, setup_parse)
-     tree classname;
-     int setup_parse;
+instantiate_class_template (type)
+     tree type;
 {
-  struct template_info *template_info;
-  tree template, t1;
+  tree template, template_info, args, pattern, t, *field_chain, *tag_chain;
 
-  if (classname == error_mark_node)
+  if (type == error_mark_node)
     return error_mark_node;
 
-  my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 278);
-  template = IDENTIFIER_TEMPLATE (classname);
+  template_info = CLASSTYPE_TEMPLATE_INFO (type);
+
+  if (TYPE_BEING_DEFINED (type) || TYPE_SIZE (type))
+    return type;
+
+  template = TI_TEMPLATE (template_info);
+  my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
+  args = TI_ARGS (template_info);
+  pattern = TREE_TYPE (template);
+
+  if (TYPE_SIZE (pattern) == NULL_TREE)
+    {
+      cp_error_at ("no definition available for `%#D'", template);
+      cp_error ("  trying to instantiate `%#T'", type);
+      return error_mark_node;
+    }
+
+  TYPE_BEING_DEFINED (type) = 1;
+
+  if (! push_tinst_level (type))
+    return type;
 
-  if (IDENTIFIER_HAS_TYPE_VALUE (classname))
+  maybe_push_to_top_level (uses_template_parms (type));
+  pushclass (type, 0);
+
+  if (flag_external_templates)
+    {
+      if (flag_alt_external_templates)
+       {
+         CLASSTYPE_INTERFACE_ONLY (type) = interface_only;
+         SET_CLASSTYPE_INTERFACE_UNKNOWN_X (type, interface_unknown);
+         CLASSTYPE_VTABLE_NEEDS_WRITING (type)
+           = ! CLASSTYPE_INTERFACE_ONLY (type)
+             && CLASSTYPE_INTERFACE_KNOWN (type);
+       }
+      else
+       {
+         CLASSTYPE_INTERFACE_ONLY (type) = CLASSTYPE_INTERFACE_ONLY (pattern);
+         SET_CLASSTYPE_INTERFACE_UNKNOWN_X
+           (type, CLASSTYPE_INTERFACE_UNKNOWN (pattern));
+         CLASSTYPE_VTABLE_NEEDS_WRITING (type)
+           = ! CLASSTYPE_INTERFACE_ONLY (type)
+             && CLASSTYPE_INTERFACE_KNOWN (type);
+       }
+    }
+  else
     {
-      tree type = IDENTIFIER_TYPE_VALUE (classname);
-      if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
-       return type;
-      if (TYPE_BEING_DEFINED (type)
-         || TYPE_SIZE (type)
-         || CLASSTYPE_USE_TEMPLATE (type) != 0)
-       return type;
+      SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
+      CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
     }
 
-  /* If IDENTIFIER_LOCAL_VALUE is already set on this template classname
-     (it's something like `foo<int>'), that means we're already working on
-     the instantiation for it.  Normally, a classname comes in with nothing
-     but its IDENTIFIER_TEMPLATE slot set.  If we were to try to instantiate
-     this again, we'd get a redeclaration error.  Since we're already working
-     on it, we'll pass back this classname's TYPE_DECL (it's the value of
-     the classname's IDENTIFIER_LOCAL_VALUE).  Only do this if we're setting
-     things up for the parser, though---if we're just trying to instantiate
-     it (e.g., via tsubst) we can trip up cuz it may not have an
-     IDENTIFIER_TYPE_VALUE when it will need one.  */
-  if (setup_parse && IDENTIFIER_LOCAL_VALUE (classname))
-    return IDENTIFIER_LOCAL_VALUE (classname);
-
-  if (uses_template_parms (classname))
+  {
+    tree binfo = TYPE_BINFO (type);
+    tree pbases = TYPE_BINFO_BASETYPES (pattern);
+
+    if (pbases)
+      {
+       tree bases;
+       int i;
+       int len = TREE_VEC_LENGTH (pbases);
+       BINFO_BASETYPES (binfo) = bases = make_tree_vec (len);
+       for (i = 0; i < len; ++i)
+         {
+           tree elt;
+
+           TREE_VEC_ELT (bases, i) = elt
+             = tsubst (TREE_VEC_ELT (pbases, i), &TREE_VEC_ELT (args, 0),
+                       TREE_VEC_LENGTH (args), NULL_TREE);
+           BINFO_INHERITANCE_CHAIN (elt) = binfo;
+
+           if (! uses_template_parms (type) &&
+               TYPE_SIZE (complete_type (TREE_TYPE (elt))) == NULL_TREE)
+             cp_error ("base class `%T' of `%T' has incomplete type",
+                       TREE_TYPE (elt), type);
+         }
+      }
+  }
+
+  CLASSTYPE_LOCAL_TYPEDECLS (type) = CLASSTYPE_LOCAL_TYPEDECLS (pattern);
+
+  field_chain = &TYPE_FIELDS (type);
+  tag_chain = &CLASSTYPE_TAGS (type);
+
+  for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
     {
-      if (!TREE_TYPE (classname))
+      tree name = TREE_PURPOSE (t);
+      tree tag = TREE_VALUE (t);
+      tree newtag;
+
+      if (TREE_CODE (tag) == ENUMERAL_TYPE)
+       newtag = start_enum (name);
+      else
+       newtag = tsubst (tag, &TREE_VEC_ELT (args, 0),
+                        TREE_VEC_LENGTH (args), NULL_TREE);
+
+      *tag_chain = build_tree_list (name, newtag);
+      tag_chain = &TREE_CHAIN (*tag_chain);
+
+      if (TREE_CODE (tag) == ENUMERAL_TYPE)
        {
-         tree t = make_lang_type (RECORD_TYPE);
-         tree d = build_decl (TYPE_DECL, classname, t);
-         DECL_NAME (d) = classname;
-         TYPE_NAME (t) = d;
-         pushdecl (d);
+         tree e, values = NULL_TREE, *last = &values;
+
+         for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
+           {
+             tree elt = build_enumerator
+               (TREE_PURPOSE (e),
+                tsubst_expr (TREE_VALUE (e), &TREE_VEC_ELT (args, 0),
+                             TREE_VEC_LENGTH (args), NULL_TREE));
+             DECL_FIELD_CONTEXT (TREE_VALUE (elt)) = type;
+             *last = elt;
+             last = &TREE_CHAIN (elt);
+           }
+
+         finish_enum (newtag, values);
+
+         *field_chain = grok_enum_decls (newtag, NULL_TREE);
+         while (*field_chain)
+           field_chain = &TREE_CHAIN (*field_chain);
        }
-      return NULL_TREE;
     }
 
-  t1 = TREE_PURPOSE (template);
-  my_friendly_assert (TREE_CODE (t1) == TEMPLATE_DECL, 279);
+  /* Don't replace enum constants here.  */
+  for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
+    if (TREE_CODE (t) != CONST_DECL)
+      {
+       tree r = tsubst (t, &TREE_VEC_ELT (args, 0),
+                        TREE_VEC_LENGTH (args), NULL_TREE);
+       if (TREE_CODE (r) == VAR_DECL)
+         {
+           if (! uses_template_parms (r))
+             pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics);
+           /* Perhaps I should do more of grokfield here. */
+           start_decl_1 (r);
+           DECL_IN_AGGR_P (r) = 1;
+           DECL_EXTERNAL (r) = 1;
+           cp_finish_decl (r, DECL_INITIAL (r), NULL_TREE, 0, 0);
+         }
+
+       *field_chain = r;
+       field_chain = &TREE_CHAIN (r);
+      }
 
-  /* If a template is declared but not defined, accept it; don't crash.
-     Later uses requiring the definition will be flagged as errors by
-     other code.  Thanks to niklas@appli.se for this bug fix.  */
-  if (DECL_TEMPLATE_INFO (t1)->text == 0)
-    setup_parse = 0;
+  TYPE_METHODS (type) = tsubst_chain (TYPE_METHODS (pattern), args);
 
-  push_to_top_level ();
-  template_info = DECL_TEMPLATE_INFO (t1);
-  if (setup_parse && push_tinst_level (classname))
+  DECL_FRIENDLIST (TYPE_MAIN_DECL (type))
+    = tsubst_chain (DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern)), args);
+  CLASSTYPE_FRIEND_CLASSES (type)
+    = tsubst_chain (CLASSTYPE_FRIEND_CLASSES (pattern), args);
+
+  {
+    tree d = tsubst (DECL_TEMPLATE_INJECT (template), &TREE_VEC_ELT (args, 0),
+                    TREE_VEC_LENGTH (args), NULL_TREE);
+
+    for (; d; d = TREE_CHAIN (d))
+      pushdecl (TREE_VALUE (d));
+  }
+
+  TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
+  TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (pattern);
+  TYPE_HAS_ASSIGNMENT (type) = TYPE_HAS_ASSIGNMENT (pattern);
+  TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
+  TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
+  TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern);
+  TYPE_GETS_NEW (type) = TYPE_GETS_NEW (pattern);
+  TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
+  TYPE_VEC_DELETE_TAKES_SIZE (type) = TYPE_VEC_DELETE_TAKES_SIZE (pattern);
+  TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
+  TYPE_HAS_CONST_ASSIGN_REF (type) = TYPE_HAS_CONST_ASSIGN_REF (pattern);
+  TYPE_HAS_ABSTRACT_ASSIGN_REF (type) = TYPE_HAS_ABSTRACT_ASSIGN_REF (pattern);
+  TYPE_HAS_INIT_REF (type) = TYPE_HAS_INIT_REF (pattern);
+  TYPE_HAS_CONST_INIT_REF (type) = TYPE_HAS_CONST_INIT_REF (pattern);
+  TYPE_GETS_INIT_AGGR (type) = TYPE_GETS_INIT_AGGR (pattern);
+  TYPE_HAS_DEFAULT_CONSTRUCTOR (type) = TYPE_HAS_DEFAULT_CONSTRUCTOR (pattern);
+  TYPE_HAS_CONVERSION (type) = TYPE_HAS_CONVERSION (pattern);
+  TYPE_USES_COMPLEX_INHERITANCE (type)
+    = TYPE_USES_COMPLEX_INHERITANCE (pattern);
+  TYPE_USES_VIRTUAL_BASECLASSES (type)
+    = TYPE_USES_VIRTUAL_BASECLASSES (pattern);
+
+  if (! uses_template_parms (type))
     {
-      push_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (template)),
-                          TREE_VALUE (template), 0);
-      set_current_level_tags_transparency (1);
-      feed_input (template_info->text, template_info->length, (struct obstack *)0);
-      lineno = template_info->lineno;
-      input_filename = template_info->filename;
-      /* Get interface/implementation back in sync.  */
-      extract_interface_info ();
-      overload_template_name (classname, 0);
-      /* Kludge so that we don't get screwed by our own base classes.  */
-      TYPE_BEING_DEFINED (TREE_TYPE (classname)) = 1;
-      yychar = PRE_PARSED_CLASS_DECL;
-      yylval.ttype = classname;
-      processing_template_defn++;
-      if (!flag_external_templates)
-       interface_unknown++;
-      template_classes
-       = perm_tree_cons (classname, NULL_TREE, template_classes);
+      tree tmp;
+      for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
+       if (TREE_CODE (tmp) == FIELD_DECL
+           && TREE_CODE (DECL_NAME (tmp)) != SCOPE_REF)
+         require_complete_type (tmp);
+
+      /* XXX handle attributes */
+      type = finish_struct_1 (type, 0, 0);
     }
   else
     {
-      tree t, decl, id, tmpl;
-
-      id = classname;
-      tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE (id));
-      t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, id, NULL_TREE, 0);
-      my_friendly_assert (TREE_CODE (t) == RECORD_TYPE
-                         || TREE_CODE (t) == UNION_TYPE, 280);
-
-      /* Now, put a copy of the decl in global scope, to avoid
-       * recursive expansion.  */
-      decl = IDENTIFIER_LOCAL_VALUE (id);
-      if (!decl)
-       decl = IDENTIFIER_CLASS_VALUE (id);
-      if (decl)
-       {
-         my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 281);
-         /* We'd better make sure we're on the permanent obstack or else
-          * we'll get a "friendly" abort 124 in pushdecl.  Perhaps a
-          * copy_to_permanent would be sufficient here, but then a
-          * sharing problem might occur.  I don't know -- niklas@appli.se */
-         push_obstacks (&permanent_obstack, &permanent_obstack);
-         pushdecl_top_level (copy_node (decl));
-         pop_obstacks ();
-       }
-      pop_from_top_level ();
+      TYPE_SIZE (type) = integer_zero_node;
+      CLASSTYPE_METHOD_VEC (type)
+       = finish_struct_methods (type, TYPE_METHODS (type), 1);
     }
 
-  return NULL_TREE;
+  TYPE_BEING_DEFINED (type) = 0;
+  popclass (0);
+
+  pop_from_top_level ();
+  pop_tinst_level ();
+
+  return type;
 }
 
 static int
@@ -1106,12 +1191,14 @@ list_eq (t1, t2)
   return list_eq (TREE_CHAIN (t1), TREE_CHAIN (t2));
 }
 
-static tree 
+tree 
 lookup_nested_type_by_name (ctype, name)
         tree ctype, name;
 {
   tree t;
 
+  complete_type (ctype);
+
   for (t = CLASSTYPE_TAGS (ctype); t; t = TREE_CHAIN (t))
     {
       if (name == TREE_PURPOSE (t))
@@ -1120,20 +1207,6 @@ lookup_nested_type_by_name (ctype, name)
   return NULL_TREE;
 }
 
-static tree
-search_nested_type_in_tmpl (tmpl, type)
-        tree tmpl, type;
-{
-  tree t;
-
-  if (tmpl == NULL || TYPE_CONTEXT(type) == NULL)
-    return tmpl;
-  t = search_nested_type_in_tmpl (tmpl, TYPE_CONTEXT(type));
-  if (t == NULL) return t;
-  t = lookup_nested_type_by_name(t, DECL_NAME(TYPE_NAME(type)));
-  return t;
-}
-
 tree
 tsubst (t, args, nargs, in_decl)
      tree t, *args;
@@ -1142,41 +1215,60 @@ tsubst (t, args, nargs, in_decl)
 {
   tree type;
 
-  if (t == NULL_TREE || t == error_mark_node)
+  if (t == NULL_TREE || t == error_mark_node
+      || t == integer_type_node
+      || t == void_type_node
+      || t == char_type_node)
     return t;
 
   type = TREE_TYPE (t);
-  if (type
-      /* Minor optimization.
-        ?? Are these really the most frequent cases?  Is the savings
-        significant?  */
-      && type != integer_type_node
-      && type != void_type_node
-      && type != char_type_node)
+  if (type == unknown_type_node)
+    my_friendly_abort (42);
+  if (type && TREE_CODE (t) != FUNCTION_DECL)
     type = tsubst (type, args, nargs, in_decl);
 
   switch (TREE_CODE (t))
     {
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (t))
-       return build_ptrmemfunc_type
-         (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, nargs, in_decl));
-         
+       {
+         tree r = build_ptrmemfunc_type
+           (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, nargs, in_decl));
+         return cp_build_type_variant (r, TYPE_READONLY (t),
+                                       TYPE_VOLATILE (t));
+       }
+
       /* else fall through */
+    case UNION_TYPE:
+      if (uses_template_parms (t))
+       {
+         tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, nargs, in_decl);
+         tree r = lookup_template_class (t, argvec, in_decl);
+         return cp_build_type_variant (r, TYPE_READONLY (t),
+                                       TYPE_VOLATILE (t));
+       }
 
+      /* else fall through */
     case ERROR_MARK:
     case IDENTIFIER_NODE:
     case OP_IDENTIFIER:
     case VOID_TYPE:
     case REAL_TYPE:
-    case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
     case INTEGER_CST:
     case REAL_CST:
     case STRING_CST:
-    case UNION_TYPE:
       return t;
 
+    case ENUMERAL_TYPE:
+      {
+       tree ctx = tsubst (TYPE_CONTEXT (t), args, nargs, in_decl);
+       if (ctx == NULL_TREE)
+         return t;
+       else
+         return lookup_nested_type_by_name (ctx, TYPE_IDENTIFIER (t));
+      }
+
     case INTEGER_TYPE:
       if (t == integer_type_node)
        return t;
@@ -1184,9 +1276,18 @@ tsubst (t, args, nargs, in_decl)
       if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
          && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
        return t;
-      return build_index_2_type
-       (tsubst (TYPE_MIN_VALUE (t), args, nargs, in_decl),
-        tsubst (TYPE_MAX_VALUE (t), args, nargs, in_decl));
+
+      {
+       tree max = tsubst_expr (TYPE_MAX_VALUE (t), args, nargs, in_decl);
+       if (current_template_parms)
+         {
+           tree itype = make_node (INTEGER_TYPE);
+           TYPE_MIN_VALUE (itype) = size_zero_node;
+           TYPE_MAX_VALUE (itype) = max;
+           return itype;
+         }
+       return build_index_2_type (size_zero_node, max);
+      }
 
     case TEMPLATE_TYPE_PARM:
       {
@@ -1201,279 +1302,167 @@ tsubst (t, args, nargs, in_decl)
 
     case FUNCTION_DECL:
       {
-       tree r;
-       tree fnargs, result;
-       
-       if (type == TREE_TYPE (t)
-           && (DECL_CONTEXT (t) == NULL_TREE
-               || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't'))
-         return t;
-       fnargs = tsubst (DECL_ARGUMENTS (t), args, nargs, t);
-       result = tsubst (DECL_RESULT (t), args, nargs, t);
+       tree r = NULL_TREE;
+       tree arg_types, ctx;
+
+       int member;
+
        if (DECL_CONTEXT (t) != NULL_TREE
            && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't')
          {
-           /* Look it up in that class, and return the decl node there,
-              instead of creating a new one.  */
-           tree ctx, methods, name, method;
-           int n_methods;
-           int i, found = 0;
-
-           name = DECL_NAME (t);
-           ctx = tsubst (DECL_CONTEXT (t), args, nargs, t);
-           methods = CLASSTYPE_METHOD_VEC (ctx);
-           if (methods == NULL_TREE)
-             /* No methods at all -- no way this one can match.  */
-             goto no_match;
-           n_methods = TREE_VEC_LENGTH (methods);
-
-           r = NULL_TREE;
-
-           if (!strncmp (OPERATOR_TYPENAME_FORMAT,
-                         IDENTIFIER_POINTER (name),
-                         sizeof (OPERATOR_TYPENAME_FORMAT) - 1))
-             {
-               /* Type-conversion operator.  Reconstruct the name, in
-                  case it's the name of one of the template's parameters.  */
-               name = build_typename_overload (TREE_TYPE (type));
-             }
+           if (DECL_NAME (t) == constructor_name (DECL_CONTEXT (t)))
+             member = 2;
+           else
+             member = 1;
+           ctx = tsubst (DECL_CLASS_CONTEXT (t), args, nargs, t);
+           type = tsubst (type, args, nargs, in_decl);
+         }
+       else
+         {
+           member = 0;
+           ctx = NULL_TREE;
+           type = tsubst (type, args, nargs, in_decl);
+         }
 
-           if (DECL_CONTEXT (t) != NULL_TREE
-               && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'
-               && constructor_name (DECL_CONTEXT (t)) == DECL_NAME (t))
-             name = constructor_name (ctx);
+       if (type == TREE_TYPE (t)
+           && (! member || ctx == DECL_CLASS_CONTEXT (t)))
+         return t;
 
-           if (DECL_CONSTRUCTOR_P (t) && TYPE_USES_VIRTUAL_BASECLASSES (ctx))
-             {
-               /* Since we didn't know that this class had virtual bases until after
-                  we instantiated it, we have to recreate the arguments to this
-                  constructor, as otherwise it would miss the __in_chrg parameter.  */
-               tree newtype, parm;
-               tree parms = TREE_CHAIN (TYPE_ARG_TYPES (type));
-               parms = hash_tree_chain (integer_type_node, parms);
-               newtype = build_cplus_method_type (ctx,
-                                                  TREE_TYPE (type),
-                                                  parms);
-               newtype = build_type_variant (newtype,
-                                             TYPE_READONLY (type),
-                                             TYPE_VOLATILE (type));
-               type = newtype;
-
-               fnargs = copy_node (DECL_ARGUMENTS (t));
-               TREE_CHAIN (fnargs) = TREE_CHAIN (DECL_ARGUMENTS (t));
-
-               /* In this case we need "in-charge" flag saying whether
-                  this constructor is responsible for initialization
-                  of virtual baseclasses or not.  */
-               parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
-               /* Mark the artificial `__in_chrg' parameter as "artificial".  */
-               SET_DECL_ARTIFICIAL (parm);
-               DECL_ARG_TYPE (parm) = integer_type_node;
-               DECL_REGISTER (parm) = 1;
-               TREE_CHAIN (parm) = TREE_CHAIN (fnargs);
-               TREE_CHAIN (fnargs) = parm;
-
-               fnargs = tsubst (fnargs, args, nargs, t);
-             }
-#if 0
-           fprintf (stderr, "\nfor function %s in class %s:\n",
-                    IDENTIFIER_POINTER (name),
-                    IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));
-#endif
-           for (i = 0; i < n_methods; i++)
-             {
-               int pass;
-
-               method = TREE_VEC_ELT (methods, i);
-               if (method == NULL_TREE || DECL_NAME (method) != name)
-                 continue;
-
-               pass = 0;
-             maybe_error:
-               for (; method; method = DECL_CHAIN (method))
-                 {
-                   my_friendly_assert (TREE_CODE (method) == FUNCTION_DECL,
-                                       282);
-                   if (! comptypes (type, TREE_TYPE (method), 1))
-                     {
-                       tree mtype = TREE_TYPE (method);
-                       tree t1, t2;
-
-                       /* Keep looking for a method that matches
-                          perfectly.  This takes care of the problem
-                          where destructors (which have implicit int args)
-                          look like constructors which have an int arg.  */
-                       if (pass == 0)
-                         continue;
-
-                       t1 = TYPE_ARG_TYPES (mtype);
-                       t2 = TYPE_ARG_TYPES (type);
-                       if (TREE_CODE (mtype) == FUNCTION_TYPE)
-                         t2 = TREE_CHAIN (t2);
-
-                       if (list_eq (t1, t2))
-                         {
-                           if (TREE_CODE (mtype) == FUNCTION_TYPE)
-                             {
-                               tree newtype;
-                               newtype = build_function_type (TREE_TYPE (type),
-                                                              TYPE_ARG_TYPES (type));
-                               newtype = build_type_variant (newtype,
-                                                             TYPE_READONLY (type),
-                                                             TYPE_VOLATILE (type));
-                               type = newtype;
-                               if (TREE_TYPE (type) != TREE_TYPE (mtype))
-                                 goto maybe_bad_return_type;
-                             }
-                           else if (TYPE_METHOD_BASETYPE (mtype)
-                                    == TYPE_METHOD_BASETYPE (type))
-                             {
-                               /* Types didn't match, but arg types and
-                                  `this' do match, so the return type is
-                                  all that should be messing it up.  */
-                             maybe_bad_return_type:
-                               if (TREE_TYPE (type) != TREE_TYPE (mtype))
-                                 error ("inconsistent return types for method `%s' in class `%s'",
-                                        IDENTIFIER_POINTER (name),
-                                        IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));
-                             }
-                           r = method;
-                           break;
-                         }
-                       found = 1;
-                       continue;
-                     }
-#if 0
-                   fprintf (stderr, "\tfound %s\n\n",
-                            IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method)));
-#endif
-                   if (DECL_ARTIFICIAL (method))
-                     {
-                       cp_error ("template for method `%D' which has default implementation in class `%T'", name, ctx);
-                       if (in_decl)
-                         cp_error_at ("in attempt to instantiate `%D' declared at this point in file", in_decl);
-                       return error_mark_node;
-                     }
-
-                   if (DECL_ARGUMENTS (method)
-                       && ! TREE_PERMANENT (DECL_ARGUMENTS (method)))
-                     /* @@ Is this early enough?  Might we want to do
-                        this instead while processing the expansion?    */
-                     DECL_ARGUMENTS (method)
-                       = tsubst (DECL_ARGUMENTS (t), args, nargs, t);
-                   r = method;
-                   break;
-                 }
-               if (r == NULL_TREE && pass == 0)
-                 {
-                   pass = 1;
-                   method = TREE_VEC_ELT (methods, i);
-                   goto maybe_error;
-                 }
-             }
-           if (r == NULL_TREE)
-             {
-             no_match:
-               cp_error
-                 (found
-                  ? "template for method `%D' doesn't match any in class `%T'"
-                  : "method `%D' not found in class `%T'", name, ctx);
-               if (in_decl)
-                 cp_error_at ("in attempt to instantiate `%D' declared at this point in file", in_decl);
-               return error_mark_node;
-             }
+       /* Do we already have this instantiation?  */
+       if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
+         {
+           tree tmpl = TREE_PURPOSE (DECL_TEMPLATE_INFO (t));
+           tree decls = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+
+           for (; decls; decls = TREE_CHAIN (decls))
+             if (TREE_TYPE (TREE_VALUE (decls)) == type
+                 && DECL_CLASS_CONTEXT (TREE_VALUE (decls)) == ctx)
+               return TREE_VALUE (decls);
+         }
+
+       /* We do NOT check for matching decls pushed separately at this
+           point, as they may not represent instantiations of this
+           template, and in any case are considered separate under the
+           discrete model.  */
+
+       r = copy_node (t);
+       copy_lang_decl (r);
+       TREE_TYPE (r) = type;
+
+       DECL_CONTEXT (r)
+         = tsubst (DECL_CONTEXT (t), args, nargs, t);
+       DECL_CLASS_CONTEXT (r) = ctx;
+
+       if (member && !strncmp (OPERATOR_TYPENAME_FORMAT,
+                               IDENTIFIER_POINTER (DECL_NAME (r)),
+                               sizeof (OPERATOR_TYPENAME_FORMAT) - 1))
+         {
+           /* Type-conversion operator.  Reconstruct the name, in
+              case it's the name of one of the template's parameters.  */
+           DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
+         }
+
+       arg_types = TYPE_VALUES (type);
+
+       if (member && TREE_CODE (type) == FUNCTION_TYPE)
+         arg_types = hash_tree_chain
+           (build_pointer_type (DECL_CONTEXT (r)), arg_types);
+
+       if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t)))
+         {
+           char *buf, *dbuf = build_overload_name (ctx, 1, 1);
+           int len = sizeof (DESTRUCTOR_DECL_PREFIX) - 1;
+           buf = (char *) alloca (strlen (dbuf)
+                                  + sizeof (DESTRUCTOR_DECL_PREFIX));
+           bcopy (DESTRUCTOR_DECL_PREFIX, buf, len);
+           buf[len] = '\0';
+           strcat (buf, dbuf);
+           DECL_ASSEMBLER_NAME (r) = get_identifier (buf);
          }
        else
+         DECL_ASSEMBLER_NAME (r)
+           = build_decl_overload (DECL_NAME (r), arg_types, member);
+       DECL_RTL (r) = 0;
+       make_decl_rtl (r, NULL_PTR, 1);
+
+       DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, nargs, t);
+       DECL_MAIN_VARIANT (r) = r;
+       DECL_RESULT (r) = NULL_TREE;
+       DECL_INITIAL (r) = NULL_TREE;
+
+       TREE_STATIC (r) = 0;
+       TREE_PUBLIC (r) = 1;
+       DECL_EXTERNAL (r) = 1;
+       DECL_INTERFACE_KNOWN (r) = 0;
+       DECL_DEFER_OUTPUT (r) = 0;
+       TREE_CHAIN (r) = NULL_TREE;
+       DECL_CHAIN (r) = NULL_TREE;
+
+       if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
+         grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
+
+       /* Look for matching decls for the moment.  */
+       if (! member)
          {
-           r = DECL_NAME (t);
-           {
-             tree decls;
-             int got_it = 0;
-
-             decls = lookup_name_nonclass (r);
-             if (decls == NULL_TREE)
-               /* no match */;
-             else if (TREE_CODE (decls) == TREE_LIST)
-               for (decls = TREE_VALUE (decls); decls ;
-                    decls = DECL_CHAIN (decls))
-                 {
-                   if (TREE_CODE (decls) == FUNCTION_DECL
-                       && TREE_TYPE (decls) == type)
-                     {
-                       got_it = 1;
-                       r = decls;
-                       break;
-                     }
-                 }
-             else
+           tree decls = lookup_name_nonclass (DECL_NAME (t));
+           tree d = NULL_TREE;
+    
+           if (decls == NULL_TREE)
+             /* no match */;
+           else if (is_overloaded_fn (decls))
+             for (decls = get_first_fn (decls); decls;
+                  decls = DECL_CHAIN (decls))
                {
-                 tree val = decls;
-                 decls = NULL_TREE;
-                 if (TREE_CODE (val) == FUNCTION_DECL
-                     && TREE_TYPE (val) == type)
+                 if (TREE_CODE (decls) == FUNCTION_DECL
+                     && TREE_TYPE (decls) == type)
                    {
-                     got_it = 1;
-                     r = val;
+                     d = decls;
+                     break;
                    }
                }
 
-             if (!got_it)
-               {
-                 tree a = build_decl_overload (r, TYPE_VALUES (type),
-                                               DECL_CONTEXT (t) != NULL_TREE);
-                 r = build_lang_decl (FUNCTION_DECL, r, type);
-                 DECL_ASSEMBLER_NAME (r) = a;
-               }
-             else if (TREE_STATIC (r))
-               {
-                 /* This overrides the template version, use it. */
-                 return r;
-               }
-           }
+           if (d)
+             {
+               int dcl_only = ! DECL_INITIAL (d);
+               if (dcl_only)
+                 DECL_INITIAL (r) = error_mark_node;
+               duplicate_decls (r, d);
+               r = d;
+               if (dcl_only)
+                 DECL_INITIAL (r) = 0;
+             }
+         }
+
+       if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
+         {
+           tree tmpl = DECL_TI_TEMPLATE (t);
+           tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+           tree argvec = tsubst (TREE_VALUE (DECL_TEMPLATE_INFO (t)),
+                                 args, nargs, in_decl);
+
+           DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
+           *declsp = perm_tree_cons (argvec, r, *declsp);
+
+           /* If we have a preexisting version of this function, don't expand
+              the template version, use the other instead.  */
+           if (TREE_STATIC (r) || DECL_TEMPLATE_SPECIALIZATION (r))
+             SET_DECL_TEMPLATE_SPECIALIZATION (r);
+           else
+             SET_DECL_IMPLICIT_INSTANTIATION (r);
+
+           DECL_TEMPLATE_INSTANTIATIONS (tmpl) =
+             tree_cons (argvec, r, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
          }
-       TREE_PUBLIC (r) = 1;
-       DECL_EXTERNAL (r) = 1;
-       TREE_STATIC (r) = 0;
-       DECL_INTERFACE_KNOWN (r) = 0;
-       DECL_INLINE (r) = DECL_INLINE (t);
-       DECL_THIS_INLINE (r) = DECL_THIS_INLINE (t);
-       TREE_READONLY (r) = TREE_READONLY (t);
-       TREE_THIS_VOLATILE (r) = TREE_THIS_VOLATILE (t);
-       {
-#if 0                          /* Maybe later.  -jason  */
-         struct tinst_level *til = tinst_for_decl();
 
-         /* should always be true under new approach */
-         if (til)
-           {
-             DECL_SOURCE_FILE (r) = til->file;
-             DECL_SOURCE_LINE (r) = til->line;
-           }
-         else
-#endif
-           {
-             DECL_SOURCE_FILE (r) = DECL_SOURCE_FILE (t);
-             DECL_SOURCE_LINE (r) = DECL_SOURCE_LINE (t);
-           }
-       }
-       DECL_CLASS_CONTEXT (r) = tsubst (DECL_CLASS_CONTEXT (t), args, nargs, t);
-       make_decl_rtl (r, NULL_PTR, 1);
-       DECL_ARGUMENTS (r) = fnargs;
-       DECL_RESULT (r) = result;
-#if 0
-       if (DECL_CONTEXT (t) == NULL_TREE
-           || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't')
-         push_overloaded_decl_top_level (r, 0);
-#endif
        return r;
       }
 
     case PARM_DECL:
       {
-       tree r;
-       r = build_decl (PARM_DECL, DECL_NAME (t), type);
+       tree r = copy_node (t);
+       TREE_TYPE (r) = type;
        DECL_INITIAL (r) = TREE_TYPE (r);
-       DECL_ARTIFICIAL (r) = DECL_ARTIFICIAL (t);
+       DECL_CONTEXT (r) = NULL_TREE;
 #ifdef PROMOTE_PROTOTYPES
        if ((TREE_CODE (type) == INTEGER_TYPE
             || TREE_CODE (type) == ENUMERAL_TYPE)
@@ -1485,6 +1474,86 @@ tsubst (t, args, nargs, in_decl)
        return r;
       }
 
+    case FIELD_DECL:
+      {
+       tree r = copy_node (t);
+       TREE_TYPE (r) = type;
+       copy_lang_decl (r);
+#if 0
+       DECL_FIELD_CONTEXT (r) = tsubst (DECL_FIELD_CONTEXT (t), args, nargs, in_decl);
+#endif
+       DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args, nargs, in_decl);
+       TREE_CHAIN (r) = NULL_TREE;
+       return r;
+      }
+
+    case USING_DECL:
+      {
+       tree r = copy_node (t);
+       DECL_INITIAL (r)
+         = tsubst_copy (DECL_INITIAL (t), args, nargs, in_decl);
+       TREE_CHAIN (r) = NULL_TREE;
+       return r;
+      }
+
+    case VAR_DECL:
+      {
+       tree r;
+       tree ctx = tsubst_copy (DECL_CONTEXT (t), args, nargs, in_decl);
+
+       /* Do we already have this instantiation?  */
+       if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
+         {
+           tree tmpl = DECL_TI_TEMPLATE (t);
+           tree decls = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+
+           for (; decls; decls = TREE_CHAIN (decls))
+             if (DECL_CONTEXT (TREE_VALUE (decls)) == ctx)
+               return TREE_VALUE (decls);
+         }
+
+       r = copy_node (t);
+       TREE_TYPE (r) = type;
+       DECL_CONTEXT (r) = ctx;
+       if (TREE_STATIC (r))
+         DECL_ASSEMBLER_NAME (r)
+           = build_static_name (DECL_CONTEXT (r), DECL_NAME (r));
+       DECL_INITIAL (r) = tsubst_expr
+         (DECL_INITIAL (t), args, nargs, in_decl);
+
+       DECL_RTL (r) = 0;
+       DECL_SIZE (r) = 0;
+
+       if (DECL_LANG_SPECIFIC (r))
+         {
+           copy_lang_decl (r);
+           DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
+         }
+
+       if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
+         {
+           tree tmpl = DECL_TI_TEMPLATE (t);
+           tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+           tree argvec = tsubst (TREE_VALUE (DECL_TEMPLATE_INFO (t)),
+                                 args, nargs, in_decl);
+
+           DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
+           *declsp = perm_tree_cons (argvec, r, *declsp);
+           SET_DECL_IMPLICIT_INSTANTIATION (r);
+         }
+       TREE_CHAIN (r) = NULL_TREE;
+       return r;
+      }
+
+    case TYPE_DECL:
+      {
+       tree r = copy_node (t);
+       TREE_TYPE (r) = type;
+       set_nested_typename (r, current_class_name, DECL_NAME (r), type);
+       TREE_CHAIN (r) = NULL_TREE;
+       return r;
+      }          
+
     case TREE_LIST:
       {
        tree purpose, value, chain, result;
@@ -1516,14 +1585,30 @@ tsubst (t, args, nargs, in_decl)
        return result;
       }
     case TREE_VEC:
+      if (type != NULL_TREE)
+       {
+         t = copy_node (t);
+
+         if (type == TREE_TYPE (t))
+           return t;
+
+         TREE_TYPE (t) = complete_type (type);
+         BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (type);
+         BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (type);
+         if (TYPE_BINFO_BASETYPES (type) != NULL_TREE)
+           BINFO_BASETYPES (t) = copy_node (TYPE_BINFO_BASETYPES (type));
+
+         return t;
+       }
       {
        int len = TREE_VEC_LENGTH (t), need_new = 0, i;
        tree *elts = (tree *) alloca (len * sizeof (tree));
+
        bzero ((char *) elts, len * sizeof (tree));
 
        for (i = 0; i < len; i++)
          {
-           elts[i] = tsubst (TREE_VEC_ELT (t, i), args, nargs, in_decl);
+           elts[i] = tsubst_copy (TREE_VEC_ELT (t, i), args, nargs, in_decl);
            if (elts[i] != TREE_VEC_ELT (t, i))
              need_new = 1;
          }
@@ -1534,6 +1619,7 @@ tsubst (t, args, nargs, in_decl)
        t = make_tree_vec (len);
        for (i = 0; i < len; i++)
          TREE_VEC_ELT (t, i) = elts[i];
+       
        return t;
       }
     case POINTER_TYPE:
@@ -1566,7 +1652,33 @@ tsubst (t, args, nargs, in_decl)
 
        /* Don't bother recursing if we know it won't change anything.  */
        if (values != void_list_node)
-         values = tsubst (values, args, nargs, in_decl);
+         {
+           /* This should probably be rewritten to use hash_tree_cons for
+               the memory savings.  */
+           tree first = NULL_TREE;
+           tree last;
+
+           for (; values && values != void_list_node;
+                values = TREE_CHAIN (values))
+             {
+               tree value
+                 = tsubst (TREE_VALUE (values), args, nargs, in_decl);
+               tree purpose = tsubst_expr (TREE_PURPOSE (values),
+                                      args, nargs, in_decl);
+               tree x = build_tree_list (purpose, value);
+
+               if (first)
+                 TREE_CHAIN (last) = x;
+               else
+                 first = x;
+               last = x;
+             }
+
+           if (values == void_list_node)
+             TREE_CHAIN (last) = void_list_node;
+
+           values = first;
+         }
        if (context)
          context = tsubst (context, args, nargs, in_decl);
        /* Could also optimize cases where return value and
@@ -1621,39 +1733,8 @@ tsubst (t, args, nargs, in_decl)
        return r;
       }
 
-    case UNINSTANTIATED_P_TYPE:
-      {
-       int nparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (UPT_TEMPLATE (t)));
-       tree argvec = make_tree_vec (nparms);
-       tree parmvec = UPT_PARMS (t);
-       int i;
-       tree id, rt;
-       for (i = 0; i < nparms; i++)
-         TREE_VEC_ELT (argvec, i) = tsubst (TREE_VEC_ELT (parmvec, i),
-                                            args, nargs, in_decl);
-       id = lookup_template_class (DECL_NAME (UPT_TEMPLATE (t)), argvec, NULL_TREE);
-       if (! IDENTIFIER_HAS_TYPE_VALUE (id)) {
-         instantiate_class_template(id, 0);
-         /* set up pending_classes */
-         add_pending_template (id);
-
-         TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (id)) =
-           IDENTIFIER_TYPE_VALUE (id);
-       }
-        rt = IDENTIFIER_TYPE_VALUE (id);
-
-       /* kung: this part handles nested type in template definition */
-        
-       if ( !ANON_AGGRNAME_P (DECL_NAME(TYPE_NAME(t))))
-          {
-           rt = search_nested_type_in_tmpl (rt, t);
-          }
-
-       return build_type_variant (rt, TYPE_READONLY (t), TYPE_VOLATILE (t));
-      }
-
-    case MINUS_EXPR:
     case PLUS_EXPR:
+    case MINUS_EXPR:
       return fold (build (TREE_CODE (t), TREE_TYPE (t),
                          tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl),
                          tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl)));
@@ -1663,338 +1744,586 @@ tsubst (t, args, nargs, in_decl)
       return fold (build1 (TREE_CODE (t), TREE_TYPE (t),
                           tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl)));
 
+    case TYPENAME_TYPE:
+      {
+       tree ctx = tsubst (TYPE_CONTEXT (t), args, nargs, in_decl);
+       tree f = make_typename_type (ctx, TYPE_IDENTIFIER (t));
+       return cp_build_type_variant
+         (f, TYPE_READONLY (f) || TYPE_READONLY (t),
+          TYPE_VOLATILE (f) || TYPE_VOLATILE (t));
+      }
+
+    case INDIRECT_REF:
+      return make_pointer_declarator
+       (type, tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl));
+      
+    case ADDR_EXPR:
+      return make_reference_declarator
+       (type, tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl));
+
+    case ARRAY_REF:
+      return build_parse_node
+       (ARRAY_REF, tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl),
+        tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl));
+
+    case CALL_EXPR:
+      return build_parse_node
+       (CALL_EXPR, tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl),
+        tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl), 0);
+
     default:
-      sorry ("use of `%s' in function template",
+      sorry ("use of `%s' in template",
             tree_code_name [(int) TREE_CODE (t)]);
       return error_mark_node;
     }
 }
 
+void
+do_pushlevel ()
+{
+  emit_line_note (input_filename, lineno);
+  pushlevel (0);
+  clear_last_expr ();
+  push_momentary ();
+  expand_start_bindings (0);
+}  
+
 tree
-instantiate_template (tmpl, targ_ptr)
-     tree tmpl, *targ_ptr;
+do_poplevel ()
 {
-  tree targs, fndecl;
-  int i, len;
-  struct pending_inline *p;
-  struct template_info *t;
-  struct obstack *old_fmp_obstack;
-  extern struct obstack *function_maybepermanent_obstack;
+  tree t;
 
-  push_obstacks (&permanent_obstack, &permanent_obstack);
-  old_fmp_obstack = function_maybepermanent_obstack;
-  function_maybepermanent_obstack = &permanent_obstack;
+  expand_end_bindings (getdecls (), kept_level_p (), 1);
+  t = poplevel (kept_level_p (), 1, 0);
+  pop_momentary ();
+  return t;
+}
 
-  my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
-  len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
+tree
+tsubst_copy (t, args, nargs, in_decl)
+     tree t, *args;
+     int nargs;
+     tree in_decl;
+{
+  enum tree_code code;
 
-  i = len;
-  while (i--)
-    targ_ptr[i] = copy_to_permanent (targ_ptr[i]);
+  if (t == NULL_TREE || t == error_mark_node)
+    return t;
+
+  code = TREE_CODE (t);
 
-  for (fndecl = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
-       fndecl; fndecl = TREE_CHAIN (fndecl))
+  switch (code)
+    {
+    case PARM_DECL:
+      return do_identifier (DECL_NAME (t), 0);
+
+    case CONST_DECL:
+    case FIELD_DECL:
+      if (DECL_CONTEXT (t))
+       {
+         tree ctx = tsubst (DECL_CONTEXT (t), args, nargs, in_decl);
+         if (ctx != DECL_CONTEXT (t))
+           return lookup_field (ctx, DECL_NAME (t), 0, 0);
+       }
+      return t;
+
+    case VAR_DECL:
+    case FUNCTION_DECL:
+      if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
+       t = tsubst (t, args, nargs, in_decl);
+      mark_used (t);
+      return t;
+
+#if 0
+    case IDENTIFIER_NODE:
+      return do_identifier (t, 0);
+#endif
+      
+    case CAST_EXPR:
+    case REINTERPRET_CAST_EXPR:
+      return build1
+       (code, tsubst (TREE_TYPE (t), args, nargs, in_decl),
+        tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl));
+
+    case INDIRECT_REF:
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case NEGATE_EXPR:
+    case TRUTH_NOT_EXPR:
+    case ADDR_EXPR:
+    case CONVERT_EXPR:      /* Unary + */
+    case SIZEOF_EXPR:
+    case ARROW_EXPR:
+      return build1
+       (code, NULL_TREE,
+        tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl));
+
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case BIT_AND_EXPR:
+    case BIT_ANDTC_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case TRUNC_MOD_EXPR:
+    case FLOOR_MOD_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+    case RSHIFT_EXPR:
+    case LSHIFT_EXPR:
+    case RROTATE_EXPR:
+    case LROTATE_EXPR:
+    case EQ_EXPR:
+    case NE_EXPR:
+    case MAX_EXPR:
+    case MIN_EXPR:
+    case LE_EXPR:
+    case GE_EXPR:
+    case LT_EXPR:
+    case GT_EXPR:
+    case COMPONENT_REF:
+    case ARRAY_REF:
+    case COMPOUND_EXPR:
+    case SCOPE_REF:
+    case DOTSTAR_EXPR:
+    case MEMBER_REF:
+      return build_nt
+       (code, tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
+        tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl));
+
+    case CALL_EXPR:
+      {
+       tree fn = TREE_OPERAND (t, 0);
+       if (really_overloaded_fn (fn))
+         fn = tsubst_copy (TREE_VALUE (fn), args, nargs, in_decl);
+       else
+         fn = tsubst_copy (fn, args, nargs, in_decl);
+       return build_nt
+         (code, fn, tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl),
+          NULL_TREE);
+      }
+
+    case METHOD_CALL_EXPR:
+      {
+       tree name = TREE_OPERAND (t, 0);
+       if (TREE_CODE (name) == BIT_NOT_EXPR)
+         {
+           name = tsubst_copy (TREE_OPERAND (name, 0), args, nargs, in_decl);
+           name = build1 (BIT_NOT_EXPR, NULL_TREE, name);
+         }
+       else if (TREE_CODE (name) == SCOPE_REF
+                && TREE_CODE (TREE_OPERAND (name, 1)) == BIT_NOT_EXPR)
+         {
+           tree base = tsubst_copy (TREE_OPERAND (name, 0), args, nargs, in_decl);
+           name = TREE_OPERAND (name, 1);
+           name = tsubst_copy (TREE_OPERAND (name, 0), args, nargs, in_decl);
+           name = build1 (BIT_NOT_EXPR, NULL_TREE, name);
+           name = build_nt (SCOPE_REF, base, name);
+         }
+       else
+         name = tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl);
+       return build_nt
+         (code, name, tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl),
+          tsubst_copy (TREE_OPERAND (t, 2), args, nargs, in_decl),
+          NULL_TREE);
+      }
+
+    case COND_EXPR:
+    case MODOP_EXPR:
+      return build_nt
+       (code, tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
+        tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl),
+        tsubst_copy (TREE_OPERAND (t, 2), args, nargs, in_decl));
+
+    case NEW_EXPR:
+      {
+       tree r = build_nt
+       (code, tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
+        tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl),
+        tsubst_copy (TREE_OPERAND (t, 2), args, nargs, in_decl));
+       NEW_EXPR_USE_GLOBAL (r) = NEW_EXPR_USE_GLOBAL (t);
+       return r;
+      }
+
+    case DELETE_EXPR:
+      {
+       tree r = build_nt
+       (code, tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
+        tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl));
+       DELETE_EXPR_USE_GLOBAL (r) = DELETE_EXPR_USE_GLOBAL (t);
+       DELETE_EXPR_USE_VEC (r) = DELETE_EXPR_USE_VEC (t);
+       return r;
+      }
+
+    case TREE_LIST:
+      {
+       tree purpose, value, chain;
+
+       if (t == void_list_node)
+         return t;
+
+       purpose = TREE_PURPOSE (t);
+       if (purpose)
+         purpose = tsubst_copy (purpose, args, nargs, in_decl);
+       value = TREE_VALUE (t);
+       if (value)
+         value = tsubst_copy (value, args, nargs, in_decl);
+       chain = TREE_CHAIN (t);
+       if (chain && chain != void_type_node)
+         chain = tsubst_copy (chain, args, nargs, in_decl);
+       if (purpose == TREE_PURPOSE (t)
+           && value == TREE_VALUE (t)
+           && chain == TREE_CHAIN (t))
+         return t;
+       return tree_cons (purpose, value, chain);
+      }
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case ENUMERAL_TYPE:
+    case INTEGER_TYPE:
+    case TEMPLATE_TYPE_PARM:
+    case TEMPLATE_CONST_PARM:
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+    case OFFSET_TYPE:
+    case FUNCTION_TYPE:
+    case METHOD_TYPE:
+    case ARRAY_TYPE:
+    case TYPENAME_TYPE:
+      return tsubst (t, args, nargs, in_decl);
+
+    default:
+      return t;
+    }
+}
+
+tree
+tsubst_expr (t, args, nargs, in_decl)
+     tree t, *args;
+     int nargs;
+     tree in_decl;
+{
+  if (t == NULL_TREE || t == error_mark_node)
+    return t;
+
+  if (current_template_parms)
+    return tsubst_copy (t, args, nargs, in_decl);
+
+  switch (TREE_CODE (t))
     {
-      tree *t1 = &TREE_VEC_ELT (TREE_PURPOSE (fndecl), 0);
-      for (i = len - 1; i >= 0; i--)
-       if (simple_cst_equal (t1[i], targ_ptr[i]) <= 0)
-         goto no_match;
+    case RETURN_STMT:
+      lineno = TREE_COMPLEXITY (t);
+      emit_line_note (input_filename, lineno);
+      c_expand_return
+       (tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl));
+      finish_stmt ();
+      break;
+
+    case EXPR_STMT:
+      lineno = TREE_COMPLEXITY (t);
+      emit_line_note (input_filename, lineno);
+      t = tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl);
+      /* Do default conversion if safe and possibly important,
+        in case within ({...}).  */
+      if ((TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE && lvalue_p (t))
+         || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
+       t = default_conversion (t);
+      cplus_expand_expr_stmt (t);
+      clear_momentary ();
+      finish_stmt ();
+      break;
+
+    case DECL_STMT:
+      {
+       int i = suspend_momentary ();
+       tree dcl;
+
+       lineno = TREE_COMPLEXITY (t);
+       emit_line_note (input_filename, lineno);
+       dcl = start_decl
+         (tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl),
+          tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl),
+          TREE_OPERAND (t, 3) != 0,
+          tsubst (TREE_OPERAND (t, 2), args, nargs, in_decl));
+       cp_finish_decl
+         (dcl, tsubst_expr (TREE_OPERAND (t, 3), args, nargs, in_decl),
+          NULL_TREE, 1, LOOKUP_ONLYCONVERTING);
+       resume_momentary (i);
+       return dcl;
+      }
 
-      /* Here, we have a match.  */
-      fndecl = TREE_VALUE (fndecl);
-      goto exit;
+    case FOR_STMT:
+      {
+       tree tmp;
+       int init_scope = (flag_new_for_scope > 0 && TREE_OPERAND (t, 0)
+                         && TREE_CODE (TREE_OPERAND (t, 0)) == DECL_STMT);
+       int cond_scope = (TREE_OPERAND (t, 1)
+                         && TREE_CODE (TREE_OPERAND (t, 1)) == DECL_STMT);
+
+       lineno = TREE_COMPLEXITY (t);
+       emit_line_note (input_filename, lineno);
+       if (init_scope)
+         do_pushlevel ();
+       tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl);
+       emit_nop ();
+       emit_line_note (input_filename, lineno);
+       expand_start_loop_continue_elsewhere (1); 
+
+       if (cond_scope)
+         do_pushlevel ();
+       tmp = tsubst_expr (TREE_OPERAND (t, 1), args, nargs, in_decl);
+       emit_line_note (input_filename, lineno);
+       if (tmp)
+         expand_exit_loop_if_false (0, condition_conversion (tmp));
+
+       if (! cond_scope)
+         do_pushlevel ();
+       tsubst_expr (TREE_OPERAND (t, 3), args, nargs, in_decl);
+       do_poplevel ();
+
+       emit_line_note (input_filename, lineno);
+       expand_loop_continue_here ();
+       tmp = tsubst_expr (TREE_OPERAND (t, 2), args, nargs, in_decl);
+       if (tmp)
+         cplus_expand_expr_stmt (tmp);
+
+       expand_end_loop ();
+       if (init_scope)
+         do_poplevel ();
+       finish_stmt ();
+      }
+      break;
 
-    no_match:
-      ;
-    }
+    case WHILE_STMT:
+      {
+       tree cond;
+
+       lineno = TREE_COMPLEXITY (t);
+       emit_nop ();
+       emit_line_note (input_filename, lineno);
+       expand_start_loop (1); 
+
+       cond = TREE_OPERAND (t, 0);
+       if (TREE_CODE (cond) == DECL_STMT)
+         do_pushlevel ();
+       cond = tsubst_expr (cond, args, nargs, in_decl);
+       emit_line_note (input_filename, lineno);
+       expand_exit_loop_if_false (0, condition_conversion (cond));
+
+       if (TREE_CODE (TREE_OPERAND (t, 0)) != DECL_STMT)
+         do_pushlevel ();
+       tsubst_expr (TREE_OPERAND (t, 1), args, nargs, in_decl);
+       do_poplevel ();
+
+       expand_end_loop ();
+       finish_stmt ();
+      }
+      break;
 
-  targs = make_tree_vec (len);
-  i = len;
-  while (i--)
-    TREE_VEC_ELT (targs, i) = targ_ptr[i];
+    case DO_STMT:
+      {
+       tree cond;
 
-  /* substitute template parameters */
-  fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr,
-                  TREE_VEC_LENGTH (targs), tmpl);
+       lineno = TREE_COMPLEXITY (t);
+       emit_nop ();
+       emit_line_note (input_filename, lineno);
+       expand_start_loop_continue_elsewhere (1); 
 
-  if (fndecl == error_mark_node)
-    goto exit;
+       tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl);
+       expand_loop_continue_here ();
 
-  assemble_external (fndecl);
+       cond = tsubst_expr (TREE_OPERAND (t, 1), args, nargs, in_decl);
+       emit_line_note (input_filename, lineno);
+       expand_exit_loop_if_false (0, condition_conversion (cond));
+       expand_end_loop ();
 
-  /* If it's a static member fn in the template, we need to change it
-     into a FUNCTION_TYPE and chop off its this pointer.  */
-  if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE
-      && DECL_STATIC_FUNCTION_P (fndecl))
-    {
-      revert_static_member_fn (&DECL_RESULT (tmpl), NULL, NULL);
-      /* Chop off the this pointer that grokclassfn so kindly added
-        for us (it didn't know yet if the fn was static or not).  */
-      DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
-    }
-     
-  t = DECL_TEMPLATE_INFO (tmpl);
+       clear_momentary ();
+       finish_stmt ();
+      }
+      break;
 
-  /* If we have a preexisting version of this function, don't expand
-     the template version, use the other instead.  */
-  if (TREE_STATIC (fndecl) || DECL_TEMPLATE_SPECIALIZATION (fndecl))
-    {
-      SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
-      p = (struct pending_inline *)0;
-    }
-  else if (t->text)
-    {
-      SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
-      repo_template_used (fndecl);
-      p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));
-      p->parm_vec = t->parm_vec;
-      p->bindings = targs;
-      p->can_free = 0;
-      p->deja_vu = 0;
-      p->buf = t->text;
-      p->len = t->length;
-      p->fndecl = fndecl;
+    case IF_STMT:
       {
-       int l = lineno;
-       char * f = input_filename;
-
-       lineno = p->lineno = t->lineno;
-       input_filename = p->filename = t->filename;
-
-       extract_interface_info ();
+       tree tmp;
+       int cond_scope = (TREE_CODE (TREE_OPERAND (t, 0)) == DECL_STMT);
+
+       lineno = TREE_COMPLEXITY (t);
+       if (cond_scope)
+         do_pushlevel ();
+       tmp = tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl);
+       emit_line_note (input_filename, lineno);
+       expand_start_cond (condition_conversion (tmp), 0);
+       
+       if (tmp = TREE_OPERAND (t, 1), tmp)
+         tsubst_expr (tmp, args, nargs, in_decl);
 
-       if (interface_unknown && flag_external_templates)
+       if (tmp = TREE_OPERAND (t, 2), tmp)
          {
-           if (DECL_CLASS_CONTEXT (fndecl)
-               && CLASSTYPE_INTERFACE_KNOWN (DECL_CLASS_CONTEXT (fndecl)))
-             {
-               interface_unknown = 0;
-               interface_only
-                 = CLASSTYPE_INTERFACE_ONLY (DECL_CLASS_CONTEXT (fndecl));
-             }
-           else if (! DECL_IN_SYSTEM_HEADER (tmpl))
-             warn_if_unknown_interface (tmpl);
+           expand_start_else ();
+           tsubst_expr (tmp, args, nargs, in_decl);
          }
 
-       if (interface_unknown || ! flag_external_templates)
-         p->interface = 1;             /* unknown */
-       else
-         p->interface = interface_only ? 0 : 2;
+       expand_end_cond ();
 
-       lineno = l;
-       input_filename = f;
+       if (cond_scope)
+         do_poplevel ();
 
-       extract_interface_info ();
+       finish_stmt ();
       }
-    }
-  else
-    p = (struct pending_inline *)0;
-
-  DECL_TEMPLATE_INSTANTIATIONS (tmpl) =
-    tree_cons (targs, fndecl, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
-
-  if (p == (struct pending_inline *)0)
-    {
-      /* do nothing */
-    }
-  else if (DECL_INLINE (fndecl))
-    {
-      DECL_PENDING_INLINE_INFO (fndecl) = p;
-      p->next = pending_inlines;
-      pending_inlines = p;
-    }
-  else
-    {
-      p->next = pending_template_expansions;
-      pending_template_expansions = p;
-    }
- exit:
-  function_maybepermanent_obstack = old_fmp_obstack;
-  pop_obstacks ();
-
-  return fndecl;
-}
+      break;
 
-/* classlevel should now never be true.  jason 4/12/94 */
-void
-undo_template_name_overload (id, classlevel)
-     tree id;
-     int classlevel;
-{
-  tree template;
-
-  template = IDENTIFIER_TEMPLATE (id);
-  if (!template)
-    return;
+    case COMPOUND_STMT:
+      {
+       tree substmt = TREE_OPERAND (t, 0);
 
-#if 0 /* not yet, should get fixed properly later */
-  poplevel (0, 0, 0);
-#endif
-#if 1 /* XXX */
-  /* This was a botch... See `overload_template_name' just below.  */
-  if (!classlevel)
-    poplevel (0, 0, 0);
-#endif
-}
+       lineno = TREE_COMPLEXITY (t);
 
-/* classlevel should now never be true.  jason 4/12/94 */
-void
-overload_template_name (id, classlevel)
-     tree id;
-     int classlevel;
-{
-  tree template, t, decl;
-  struct template_info *tinfo;
+       if (COMPOUND_STMT_NO_SCOPE (t) == 0)
+         do_pushlevel ();
 
-  my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 284);
-  template = IDENTIFIER_TEMPLATE (id);
-  if (!template)
-    return;
+       for (; substmt; substmt = TREE_CHAIN (substmt))
+         tsubst_expr (substmt, args, nargs, in_decl);
 
-  template = TREE_PURPOSE (template);
-  tinfo = DECL_TEMPLATE_INFO (template);
-  template = DECL_NAME (template);
-  my_friendly_assert (template != NULL_TREE, 285);
-
-#if 1 /* XXX */
-  /* This was a botch... names of templates do not get their own private
-     scopes.  Rather, they should go into the binding level already created
-     by push_template_decls.  Except that there isn't one of those for
-     specializations.  */
-  if (!classlevel)
-    {
-      pushlevel (1);
-      declare_pseudo_global_level ();
-    }
-#endif
+       if (COMPOUND_STMT_NO_SCOPE (t) == 0)
+         do_poplevel ();
+      }
+      break;
 
-  t = xref_tag (tinfo->aggr, id, NULL_TREE, 1);
-  my_friendly_assert (TREE_CODE (t) == RECORD_TYPE
-                     || TREE_CODE (t) == UNION_TYPE
-                     || TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286);
+    case BREAK_STMT:
+      lineno = TREE_COMPLEXITY (t);
+      emit_line_note (input_filename, lineno);
+      if (! expand_exit_something ())
+       error ("break statement not within loop or switch");
+      break;
 
-  decl = build_decl (TYPE_DECL, template, t);
-  SET_DECL_ARTIFICIAL (decl);
+    case SWITCH_STMT:
+      {
+       tree val, tmp;
+       int cond_scope = (TREE_CODE (TREE_OPERAND (t, 0)) == DECL_STMT);
+
+       lineno = TREE_COMPLEXITY (t);
+       if (cond_scope)
+         do_pushlevel ();
+       val = tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl);
+       emit_line_note (input_filename, lineno);
+       c_expand_start_case (val);
+       push_switch ();
+       
+       if (tmp = TREE_OPERAND (t, 1), tmp)
+         tsubst_expr (tmp, args, nargs, in_decl);
 
-#if 0 /* fix this later */
-  /* We don't want to call here if the work has already been done.  */
-  t = (classlevel
-       ? IDENTIFIER_CLASS_VALUE (template)
-       : IDENTIFIER_LOCAL_VALUE (template));
-  if (t
-      && TREE_CODE (t) == TYPE_DECL
-      && TREE_TYPE (t) == t)
-    my_friendly_abort (85);
-#endif
+       expand_end_case (val);
+       pop_switch ();
 
-  if (classlevel)
-    pushdecl_class_level (decl);
-  else
-    pushdecl (decl);
+       if (cond_scope)
+         do_poplevel ();
 
-#if 0 /* This seems bogus to me; if it isn't, explain why.  (jason) */
-  /* Fake this for now, just to make dwarfout.c happy.  It will have to
-     be done in a proper way later on.  */
-  DECL_CONTEXT (decl) = t;
-#endif
+       finish_stmt ();
+      }
+      break;
+
+    case CASE_LABEL:
+      do_case (tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl),
+              tsubst_expr (TREE_OPERAND (t, 1), args, nargs, in_decl));
+      break;
+
+    case LABEL_DECL:
+      t = define_label (DECL_SOURCE_FILE (t), DECL_SOURCE_LINE (t),
+                       DECL_NAME (t));
+      if (t)
+       expand_label (t);
+      break;
+
+    case GOTO_STMT:
+      lineno = TREE_COMPLEXITY (t);
+      emit_line_note (input_filename, lineno);
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == IDENTIFIER_NODE)
+       {
+         tree decl = lookup_label (TREE_OPERAND (t, 0));
+         TREE_USED (decl) = 1;
+         expand_goto (decl);
+       }
+      else
+       expand_computed_goto
+         (tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl));
+      break;
+         
+    default:
+      return build_expr_from_tree (tsubst_copy (t, args, nargs, in_decl));
+    }
+  return NULL_TREE;
 }
 
-extern struct pending_input *to_be_restored;
-
-/* NAME is the IDENTIFIER value of a PRE_PARSED_CLASS_DECL. */
-void
-end_template_instantiation (name)
-     tree name;
+tree
+instantiate_template (tmpl, targ_ptr)
+     tree tmpl, *targ_ptr;
 {
-  tree t, decl;
+  tree fndecl;
+  int i, len;
+  struct obstack *old_fmp_obstack;
+  extern struct obstack *function_maybepermanent_obstack;
+
+  push_obstacks (&permanent_obstack, &permanent_obstack);
+  old_fmp_obstack = function_maybepermanent_obstack;
+  function_maybepermanent_obstack = &permanent_obstack;
 
-  processing_template_defn--;
-  if (!flag_external_templates)
-    interface_unknown--;
+  my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
+  len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
 
-  /* Restore the old parser input state.  */
-  if (yychar == YYEMPTY)
-    yychar = yylex ();
-  if (yychar != END_OF_SAVED_INPUT)
-    error ("parse error at end of class template");
-  else
+  i = len;
+  while (i--)
     {
-      restore_pending_input (to_be_restored);
-      to_be_restored = 0;
+      tree t = targ_ptr [i];
+      if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+       {
+         tree nt = target_type (t);
+         if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_STUB_DECL (nt)))
+           {
+             cp_error ("type `%T' composed from a local class is not a valid template-argument", t);
+             cp_error ("  trying to instantiate `%D'", tmpl);
+             fndecl = error_mark_node;
+             goto out;
+           }
+       }
+      targ_ptr[i] = copy_to_permanent (t);
     }
 
-  /* Our declarations didn't get stored in the global slot, since
-     there was a (supposedly tags-transparent) scope in between.  */
-  t = IDENTIFIER_TYPE_VALUE (name);
-  my_friendly_assert (t != NULL_TREE
-                     && TREE_CODE_CLASS (TREE_CODE (t)) == 't',
-                     287);
-  SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
-  /* Make methods of template classes static, unless
-     -fexternal-templates is given.  */
-  if (!flag_external_templates)
-    SET_CLASSTYPE_INTERFACE_UNKNOWN (t);
-  decl = IDENTIFIER_GLOBAL_VALUE (name);
-  my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 288);
-
-  undo_template_name_overload (name, 0);
-  t = IDENTIFIER_TEMPLATE (name);
-  pop_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (t)), TREE_VALUE (t),
-                     0);
-  /* This will fix up the type-value field.  */
-  pushdecl (decl);
-  pop_from_top_level ();
+  /* substitute template parameters */
+  fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, len, tmpl);
 
-#ifdef DWARF_DEBUGGING_INFO
-  if (write_symbols == DWARF_DEBUG && TREE_CODE (decl) == TYPE_DECL)
-    {
-      /* We just completed the definition of a new file-scope type,
-        so we can go ahead and output debug-info for it now.  */
-      TYPE_STUB_DECL (TREE_TYPE (decl)) = decl;
-      rest_of_type_compilation (TREE_TYPE (decl), 1);
-    }
-#endif /* DWARF_DEBUGGING_INFO */
+ out:
+  function_maybepermanent_obstack = old_fmp_obstack;
+  pop_obstacks ();
 
-  /* Restore interface/implementation settings.         */
-  extract_interface_info ();
+  return fndecl;
 }
-\f
-/* Store away the text of an template.  */
+
+/* Push the name of the class template into the scope of the instantiation.  */
 
 void
-reinit_parse_for_template (yychar, d1, d2)
-     int yychar;
-     tree d1, d2;
+overload_template_name (type)
+     tree type;
 {
-  struct template_info *template_info;
-  extern struct obstack inline_text_obstack; /* see comment in lex.c */
+  tree id = DECL_NAME (CLASSTYPE_TI_TEMPLATE (type));
+  tree decl;
 
-  if (d2 == NULL_TREE || d2 == error_mark_node)
-    {
-    lose:
-      /* @@ Should use temp obstack, and discard results.  */
-      reinit_parse_for_block (yychar, &inline_text_obstack, 1);
-      return;
-    }
+  if (IDENTIFIER_CLASS_VALUE (id)
+      && TREE_TYPE (IDENTIFIER_CLASS_VALUE (id)) == type)
+    return;
 
-  if (TREE_CODE (d2) == IDENTIFIER_NODE)
-    d2 = IDENTIFIER_GLOBAL_VALUE (d2);
-  if (!d2)
-    goto lose;
-  template_info = DECL_TEMPLATE_INFO (d2);
-  if (!template_info)
-    {
-      template_info = (struct template_info *) permalloc (sizeof (struct template_info));
-      bzero ((char *) template_info, sizeof (struct template_info));
-      DECL_TEMPLATE_INFO (d2) = template_info;
-    }
-  template_info->filename = input_filename;
-  template_info->lineno = lineno;
-  reinit_parse_for_block (yychar, &inline_text_obstack, 1);
-  template_info->text = obstack_base (&inline_text_obstack);
-  template_info->length = obstack_object_size (&inline_text_obstack);
-  obstack_finish (&inline_text_obstack);
-  template_info->parm_vec = d1;
+  decl = build_decl (TYPE_DECL, id, type);
+  SET_DECL_ARTIFICIAL (decl);
+  pushdecl_class_level (decl);
 }
 
 /* Type unification.
@@ -2156,12 +2485,6 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
     {
     case TEMPLATE_TYPE_PARM:
       (*nsubsts)++;
-      if (TEMPLATE_TYPE_TPARMLIST (parm) != tparms)
-       {
-         error ("mixed template headers?!");
-         my_friendly_abort (86);
-         return 1;
-       }
       idx = TEMPLATE_TYPE_IDX (parm);
 #if 0
       /* Template type parameters cannot contain cv-quals; i.e.
@@ -2291,30 +2614,27 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
        return 0;
       }
 
-    case UNINSTANTIATED_P_TYPE:
-      {
-       tree a;
-       /* Unification of something that is not a class fails.  */
-       if (! IS_AGGR_TYPE (arg))
-         return 1;
-       a = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (arg));
-       if (a && UPT_TEMPLATE (parm) == TREE_PURPOSE (a))
-         return unify (tparms, targs, ntparms, UPT_PARMS (parm),
-                       TREE_VALUE (a), nsubsts);
-       /* FIXME: Should check base conversions here.  */
-       return 1;
-      }
-
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_FLAG (parm))
        return unify (tparms, targs, ntparms, TYPE_PTRMEMFUNC_FN_TYPE (parm),
                      arg, nsubsts);
 
       /* Allow trivial conversions.  */
-      if (TYPE_MAIN_VARIANT (parm) != TYPE_MAIN_VARIANT (arg)
+      if (TREE_CODE (arg) != RECORD_TYPE
          || TYPE_READONLY (parm) < TYPE_READONLY (arg)
          || TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg))
        return 1;
+
+      if (CLASSTYPE_TEMPLATE_INFO (parm) && CLASSTYPE_TEMPLATE_INFO (arg)
+         && uses_template_parms (parm))
+       {
+         if (CLASSTYPE_TI_TEMPLATE (parm) != CLASSTYPE_TI_TEMPLATE (arg))
+           return 1;
+         return unify (tparms, targs, ntparms, CLASSTYPE_TI_ARGS (parm),
+                       CLASSTYPE_TI_ARGS (arg), nsubsts);
+       }
+      else if (TYPE_MAIN_VARIANT (parm) != TYPE_MAIN_VARIANT (arg))
+       return 1;
       return 0;
 
     case METHOD_TYPE:
@@ -2347,154 +2667,9 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
       return 1;
     }
 }
-
-\f
-#undef DEBUG
-
-int
-do_pending_expansions ()
-{
-  struct pending_inline *i, *new_list = 0;
-
-  {
-    tree t;
-    for (t = template_classes; t; t = TREE_CHAIN (t))
-      instantiate_member_templates (TREE_PURPOSE (t));
-  }
-  
-  if (!pending_template_expansions)
-    return 0;
-
-#ifdef DEBUG
-  fprintf (stderr, "\n\n\t\t IN DO_PENDING_EXPANSIONS\n\n");
-#endif
-
-  i = pending_template_expansions;
-  while (i)
-    {
-      tree context;
-
-      struct pending_inline *next = i->next;
-      tree t = i->fndecl;
-
-      int decision = 0;
-#define DECIDE(N) do {decision=(N); goto decided;} while(0)
-
-      my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL
-                         || TREE_CODE (t) == VAR_DECL, 294);
-      if (TREE_ASM_WRITTEN (t))
-       DECIDE (0);
-
-      if (DECL_EXPLICIT_INSTANTIATION (t))
-       DECIDE (DECL_NOT_REALLY_EXTERN (t));
-      else if (! flag_implicit_templates)
-       DECIDE (0);
-
-      if (i->interface == 1)
-       /* OK, it was an implicit instantiation.  */
-       {
-         if (flag_weak)
-           DECL_WEAK (t) = 1;
-         else
-           TREE_PUBLIC (t) = 0;
-       }
-
-      /* If it's a method, let the class type decide it.
-        @@ What if the method template is in a separate file?
-        Maybe both file contexts should be taken into account?
-        Maybe only do this if i->interface == 1 (unknown)?  */
-      context = DECL_CONTEXT (t);
-      if (context != NULL_TREE
-         && TREE_CODE_CLASS (TREE_CODE (context)) == 't')
-       {
-         /* I'm interested in the context of this version of the function,
-            not the original virtual declaration.  */
-         context = DECL_CLASS_CONTEXT (t);
-
-         /* If `unknown', we might want a static copy.
-            If `implementation', we want a global one.
-            If `interface', ext ref.  */
-         if (CLASSTYPE_INTERFACE_KNOWN (context))
-           DECIDE (!CLASSTYPE_INTERFACE_ONLY (context));
-#if 1 /* This doesn't get us stuff needed only by the file initializer.  */
-         DECIDE (TREE_USED (t));
-#else /* This compiles too much stuff, but that's probably better in
-        most cases than never compiling the stuff we need.  */
-         DECIDE (1);
-#endif
-       }
-
-      if (i->interface == 1)
-       DECIDE (TREE_USED (t));
-      else
-       DECIDE (i->interface);
-
-    decided:
-#ifdef DEBUG
-      print_node_brief (stderr, decision ? "yes: " : "no: ", t, 0);
-      fprintf (stderr, "\t%s\n",
-              (DECL_ASSEMBLER_NAME (t)
-               ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t))
-               : ""));
-#endif
-      if (decision)
-       {
-         i->next = pending_inlines;
-         pending_inlines = i;
-       }
-      else
-       {
-         i->next = new_list;
-         new_list = i;
-       }
-      i = next;
-    }
-  pending_template_expansions = new_list;
-  if (!pending_inlines)
-    return 0;
-  do_pending_inlines ();
-  return 1;
-}
-
 \f
-struct pending_template {
-  struct pending_template *next;
-  tree id;
-};
-
-static struct pending_template* pending_templates;
-
-void
-do_pending_templates ()
-{
-  struct pending_template* t;
-  
-  for ( t = pending_templates; t; t = t->next)
-    {
-      instantiate_class_template (t->id, 1);
-    }
-
-  for ( t = pending_templates; t; t = pending_templates)
-    {
-      pending_templates = t->next;
-      free(t);
-    }
-}
-
-static void
-add_pending_template (pt)
-     tree pt;
-{
-  struct pending_template *p;
-  
-  p = (struct pending_template *) malloc (sizeof (struct pending_template));
-  p->next = pending_templates;
-  pending_templates = p;
-  p->id = pt;
-}
-
 void
-mark_function_instantiated (result, extern_p)
+mark_decl_instantiated (result, extern_p)
      tree result;
      int extern_p;
 {
@@ -2572,7 +2747,10 @@ do_function_instantiation (declspecs, declarator, storage)
   else
     cp_error ("storage class `%D' applied to template instantiation",
              storage);
-  mark_function_instantiated (result, extern_p);
+
+  if (! extern_p)
+    instantiate_decl (result);
+  mark_decl_instantiated (result, extern_p);
   repo_template_instantiated (result, extern_p);
 }
 
@@ -2600,6 +2778,9 @@ do_type_instantiation (name, storage)
   tree t = TREE_TYPE (name);
   int extern_p = 0;
   int nomem_p = 0;
+  int static_p = 0;
+
+  complete_type (t);
 
   /* With -fexternal-templates, explicit instantiations are treated the same
      as implicit ones.  */
@@ -2619,6 +2800,8 @@ do_type_instantiation (name, storage)
     nomem_p = 1;
   else if (storage == ridpointers[(int) RID_EXTERN])
     extern_p = 1;
+  else if (storage == ridpointers[(int) RID_STATIC])
+    static_p = 1;
   else
     {
       cp_error ("storage class `%D' applied to template instantiation",
@@ -2642,31 +2825,26 @@ do_type_instantiation (name, storage)
 
   {
     tree tmp;
-    /* Classes nested in template classes currently don't have an
-       IDENTIFIER_TEMPLATE--their out-of-line members are handled
-       by the enclosing template class.  Note that there are name
-       conflict bugs with this approach. */
-    tmp = TYPE_IDENTIFIER (t);
-    if (IDENTIFIER_TEMPLATE (tmp))
-      instantiate_member_templates (tmp);
-
-    /* this should really be done by instantiate_member_templates */
-    tmp = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
-    for (; tmp; tmp = TREE_CHAIN (tmp))
-      if (DECL_TEMPLATE_INSTANTIATION (tmp))
+
+    if (! static_p)
+      for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
+       if (DECL_TEMPLATE_INSTANTIATION (tmp))
+         {
+           mark_decl_instantiated (tmp, extern_p);
+           repo_template_instantiated (tmp, extern_p);
+           if (! extern_p)
+             instantiate_decl (tmp);
+         }
+
+    for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
+      if (TREE_CODE (tmp) == VAR_DECL && DECL_TEMPLATE_INSTANTIATION (tmp))
        {
-         mark_function_instantiated (tmp, extern_p);
+         mark_decl_instantiated (tmp, extern_p);
          repo_template_instantiated (tmp, extern_p);
+         if (! extern_p)
+           instantiate_decl (tmp);
        }
 
-#if 0
-    for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
-      {
-       if (TREE_CODE (tmp) == VAR_DECL)
-         /* eventually do something */;
-      }
-#endif
-
     for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
       if (IS_AGGR_TYPE (TREE_VALUE (tmp)))
        do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage);
@@ -2674,16 +2852,189 @@ do_type_instantiation (name, storage)
 }
 
 tree
-create_nested_upt (scope, name)
-     tree scope, name;
+instantiate_decl (d)
+     tree d;
 {
-  tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
-  tree d = build_decl (TYPE_DECL, name, t);
+  tree ti = DECL_TEMPLATE_INFO (d);
+  tree tmpl = TI_TEMPLATE (ti);
+  tree args = TI_ARGS (ti);
+  tree td;
+  tree pattern = DECL_TEMPLATE_RESULT (tmpl);
+  tree save_ti;
+  int nested = in_function_p ();
+  int d_defined;
+  int pattern_defined;
+
+  if (TREE_CODE (d) == FUNCTION_DECL)
+    {
+      d_defined = (DECL_INITIAL (d) != NULL_TREE);
+      pattern_defined = (DECL_INITIAL (pattern) != NULL_TREE);
+    }
+  else
+    {
+      d_defined = ! DECL_IN_AGGR_P (d);
+      pattern_defined = ! DECL_IN_AGGR_P (pattern);
+    }
+
+  if (d_defined)
+    return d;
+  else if (pattern_defined)
+    {
+      repo_template_used (d);
+
+      if (flag_external_templates && ! DECL_INTERFACE_KNOWN (d))
+       {
+         if (flag_alt_external_templates)
+           {
+             if (interface_unknown)
+               warn_if_unknown_interface (d);
+           }
+         else if (DECL_INTERFACE_KNOWN (pattern))
+           {
+             DECL_INTERFACE_KNOWN (d) = 1;
+             DECL_NOT_REALLY_EXTERN (d) = ! DECL_EXTERNAL (pattern);
+           }
+         else
+           warn_if_unknown_interface (pattern);
+       }
+
+      if (at_eof)
+       import_export_decl (d);
+    }
+
+  if (! pattern_defined
+      || (TREE_CODE (d) == FUNCTION_DECL && ! DECL_INLINE (d)
+         && (! DECL_INTERFACE_KNOWN (d)
+             || ! DECL_NOT_REALLY_EXTERN (d))))
+    {
+      add_pending_template (d);
+      return d;
+    }
+
+  if (! push_tinst_level (d))
+    return d;
+
+  if (TREE_CODE (d) == FUNCTION_DECL && nested)
+    push_cp_function_context (NULL_TREE);
+  push_to_top_level ();
+
+  /* Trick tsubst into giving us a new decl in case the template changed.  */
+  save_ti = DECL_TEMPLATE_INFO (pattern);
+  DECL_TEMPLATE_INFO (pattern) = NULL_TREE;
+  td = tsubst (pattern, &TREE_VEC_ELT (args, 0), TREE_VEC_LENGTH (args), tmpl);
+  DECL_TEMPLATE_INFO (pattern) = save_ti;
+
+  /* Convince duplicate_decls to use the DECL_ARGUMENTS from the new decl.  */
+  if (TREE_CODE (d) == FUNCTION_DECL)
+    DECL_INITIAL (td) = error_mark_node;
+  duplicate_decls (td, d);
+  if (TREE_CODE (d) == FUNCTION_DECL)
+    DECL_INITIAL (td) = 0;
+
+  if (TREE_CODE (d) == VAR_DECL)
+    {
+      DECL_IN_AGGR_P (d) = 0;
+      if (DECL_INTERFACE_KNOWN (d))
+       DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
+      else
+       {
+         DECL_EXTERNAL (d) = 1;
+         DECL_NOT_REALLY_EXTERN (d) = 1;
+       }
+      cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0, 0);
+    }
+  else if (TREE_CODE (d) == FUNCTION_DECL)
+    {
+      tree t = DECL_SAVED_TREE (pattern);
+      int line = lineno;
+      char *file = input_filename;
+
+      lineno = DECL_SOURCE_LINE (d);
+      input_filename = DECL_SOURCE_FILE (d);
+
+      start_function (NULL_TREE, d, NULL_TREE, NULL_TREE, 1);
+      store_parm_decls ();
+
+      if (t && TREE_CODE (t) == CTOR_INITIALIZER)
+       {
+         current_member_init_list
+           = tsubst_expr_values (TREE_OPERAND (t, 0), args);
+         current_base_init_list
+           = tsubst_expr_values (TREE_OPERAND (t, 1), args);
+         t = TREE_CHAIN (t);
+       }
+
+      setup_vtbl_ptr ();
+      /* Always keep the BLOCK node associated with the outermost
+        pair of curley braces of a function.  These are needed
+        for correct operation of dwarfout.c.  */
+      keep_next_level ();
+
+      my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
+      tsubst_expr (t, &TREE_VEC_ELT (args, 0),
+                  TREE_VEC_LENGTH (args), tmpl);
 
-  TYPE_NAME (t) = d;
-  TYPE_VALUES (t) = TYPE_VALUES (scope);
-  TYPE_CONTEXT (t) = scope;
+      finish_function (lineno, 0, nested);
+
+      lineno = line;
+      input_filename = file;
+    }
+
+  pop_from_top_level ();
+  if (TREE_CODE (d) == FUNCTION_DECL && nested)
+    pop_cp_function_context (NULL_TREE);
+  pop_tinst_level ();
 
-  pushdecl (d);
   return d;
 }
+
+tree
+tsubst_chain (t, argvec)
+     tree t, argvec;
+{
+  if (t)
+    {
+      tree first = tsubst (t, &TREE_VEC_ELT (argvec, 0),
+                          TREE_VEC_LENGTH (argvec), NULL_TREE);
+      tree last = first;
+
+      for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t))
+       {
+         tree x = tsubst (t, &TREE_VEC_ELT (argvec, 0),
+                          TREE_VEC_LENGTH (argvec), NULL_TREE);
+         TREE_CHAIN (last) = x;
+         last = x;
+       }
+
+      return first;
+    }
+  return NULL_TREE;
+}
+
+tree
+tsubst_expr_values (t, argvec)
+     tree t, argvec;
+{
+  tree first = NULL_TREE;
+  tree *p = &first;
+
+  for (; t; t = TREE_CHAIN (t))
+    {
+      tree pur = tsubst_copy (TREE_PURPOSE (t), &TREE_VEC_ELT (argvec, 0),
+                             TREE_VEC_LENGTH (argvec), NULL_TREE);
+      tree val = tsubst_expr (TREE_VALUE (t), &TREE_VEC_ELT (argvec, 0),
+                             TREE_VEC_LENGTH (argvec), NULL_TREE);
+      *p = build_tree_list (pur, val);
+      p = &TREE_CHAIN (*p);
+    }
+  return first;
+}
+
+tree last_tree;
+
+void
+add_tree (t)
+     tree t;
+{
+  last_tree = TREE_CHAIN (last_tree) = t;
+}
index ad1480a1ed9d65ad2922e2b6e12666e79b346aa8..5a859561512b079b5e38b1364735aba0bbd057c8 100644 (file)
@@ -72,13 +72,6 @@ print_lang_type (file, node, indent)
       return;
     }
 
-  if (TREE_CODE (node) == UNINSTANTIATED_P_TYPE)
-    {
-      print_node (file, "template", UPT_TEMPLATE (node), indent + 4);
-      print_node (file, "parameters", UPT_PARMS (node), indent + 4);
-      return;
-    }
-
   if (! (TREE_CODE (node) == RECORD_TYPE
         || TREE_CODE (node) == UNION_TYPE))
     return;
index 50fc9f8b727f8a10da6df7997d0ad919203f3cb9..6800512825b648c0f5bfe1da395574fa4be051ea 100644 (file)
@@ -49,6 +49,7 @@ extern struct obstack permanent_obstack;
 #define IDENTIFIER_REPO_USED(NODE)   (TREE_LANG_FLAG_3 (NODE))
 #define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
 
+#if 0
 /* Record the flags used to compile this translation unit.  */
 
 void
@@ -82,8 +83,9 @@ void
 repo_class_defined (t)
      tree t;
 {}
+#endif
 
-tree
+static tree
 repo_get_id (t)
      tree t;
 {
@@ -120,7 +122,7 @@ repo_template_used (t)
   else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
     {
       if (IDENTIFIER_REPO_CHOSEN (id))
-       mark_function_instantiated (t, 0);
+       mark_decl_instantiated (t, 0);
     }
   else
     my_friendly_abort (1);
@@ -132,9 +134,10 @@ repo_template_used (t)
     }
 }
 
+#if 0
 /* Note that the vtable for a class has been used, and offer to emit it.  */
 
-void
+static void
 repo_vtable_used (t)
      tree t;
 {
@@ -172,6 +175,7 @@ repo_tinfo_used (ti)
      tree ti;
 {
 }
+#endif
 
 void
 repo_template_instantiated (t, extern_p)
@@ -246,7 +250,7 @@ static void
 open_repo_file (filename)
      char *filename;
 {
-  register char *p, *q;
+  register char *p;
   char *s = get_base_filename (filename);
 
   if (s == NULL)
index 64b96bfcd8e907754ac647d02a912245b6c57887..4a762eb58b543ee769e446bdd734eb52c4144e6f 100644 (file)
@@ -37,7 +37,7 @@ extern tree combine_strings PROTO((tree));
 \f
 /* Given the expression EXP of type `class *', return the head
    of the object pointed to by EXP.  */
-tree
+static tree
 build_headof (exp)
      tree exp;
 {
@@ -156,7 +156,7 @@ get_typeid (type)
 /* Get a bad_cast node for the program to throw...
 
    See libstdc++::exception{,.cc} for __bad_cast_object */
-tree
+static tree
 get_bad_cast_node ()
 {
   static tree t;
@@ -179,7 +179,6 @@ build_dynamic_cast (type, expr)
   enum tree_code tc = TREE_CODE (type);
   tree exprtype = TREE_TYPE (expr);
   enum tree_code ec = TREE_CODE (exprtype);
-  tree retval;
 
   if (type == error_mark_node || expr == error_mark_node)
     return error_mark_node;
@@ -268,7 +267,7 @@ build_dynamic_cast (type, expr)
       else
        {
          tree retval;
-          tree result, td1, td2, elems, tmp1, expr1;
+          tree result, td1, td2, elems, expr1;
 
          /* If we got here, we can't convert statically.  Therefore,
             dynamic_cast<D&>(b) (b an object) cannot succeed.  */
@@ -462,7 +461,7 @@ static tree
 build_user_desc (tdecl)
      tree tdecl;
 {
-  tree elems, name_string, t;
+  tree elems, name_string;
   tree tname = DECL_NAME (tdecl);
 
   name_string = combine_strings (build_string 
@@ -481,13 +480,15 @@ build_class_desc (tdecl, type)
   tree name_string;
 
   int i = CLASSTYPE_N_BASECLASSES (type);
-  int n_base = i;
   int base_cnt = 0;
   tree binfos = TYPE_BINFO_BASETYPES (type);
+#if 0
+  /* See code below that used these.  */
   tree vb = CLASSTYPE_VBASECLASSES (type);
+  int n_base = i;
+#endif
   tree base, elems, access, offset, isvir;
   tree base_list, off_list, acc_list, isvir_list;
-  tree t;
   static tree acc_pub = NULL_TREE;
   static tree acc_pro = NULL_TREE;
   static tree acc_pri = NULL_TREE;
@@ -516,7 +517,6 @@ build_class_desc (tdecl, type)
          tree t = BINFO_TYPE (binfo);
          char *name;
          tree field;
-         int off;
 
          name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
          sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
@@ -659,9 +659,8 @@ build_func_desc (tdecl)
 
 /* Build an initializer for a __ptmf_type_info node.  */
 static tree
-build_ptmf_desc (tdecl, type)
+build_ptmf_desc (tdecl)
      tree tdecl;
-     tree type;
 { 
   tree elems, name_string;
   tree tname = DECL_NAME (tdecl);
@@ -711,7 +710,7 @@ add_uninstantiated_desc (type)
    objects, we do that here.  Return the type to link against if such a
    link exists, otherwise just return TYPE.  */
 
-tree
+static tree
 get_def_to_follow (type)
      tree type;
 {
@@ -735,10 +734,8 @@ build_t_desc (type, definition)
      tree type;
      int definition;
 {
-  tree tdecl;
-  tree tname, name_string;
-  tree elems;
-  tree t, tt, taggr;
+  tree tdecl, tname;
+  tree t, taggr;
 
   if (__ptmd_desc_type_node == NULL_TREE)
     {
@@ -841,13 +838,9 @@ build_t_desc (type, definition)
   else if (IS_AGGR_TYPE (type))
     {
       if (TYPE_PTRMEMFUNC_P (type))
-       {
-         t = build_ptmf_desc (tdecl, type);
-       }
+       t = build_ptmf_desc (tdecl);
       else
-       {
-         t = build_class_desc (tdecl, type);
-       }
+       t = build_class_desc (tdecl, type);
     }
   else if (TREE_CODE (type) == FUNCTION_TYPE)
     t = build_func_desc (tdecl);
index 2f1b0c307efa2649ffb22e7f5ac9e209764c4949..bd46eb79c25d20c21f4a40b700821c2aa1142b4c 100644 (file)
@@ -34,7 +34,6 @@ Boston, MA 02111-1307, USA.  */
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
-void init_search ();
 extern struct obstack *current_obstack;
 extern tree abort_fndecl;
 
@@ -82,8 +81,7 @@ static void dfs_unmark ();
 static void dfs_init_vbase_pointers ();
 
 static tree vbase_types;
-static tree vbase_decl, vbase_decl_ptr;
-static tree vbase_decl_ptr_intermediate;
+static tree vbase_decl_ptr_intermediate, vbase_decl_ptr;
 static tree vbase_init_result;
 
 /* Allocate a level of searching.  */
@@ -141,12 +139,14 @@ extern int flag_memoize_lookups, flag_save_memoized_contexts;
 static int my_memoized_entry_counter;
 static int memoized_fast_finds[2], memoized_adds[2], memoized_fast_rejects[2];
 static int memoized_fields_searched[2];
+#ifdef GATHER_STATISTICS
 static int n_fields_searched;
 static int n_calls_lookup_field, n_calls_lookup_field_1;
 static int n_calls_lookup_fnfields, n_calls_lookup_fnfields_1;
 static int n_calls_get_base_type;
 static int n_outer_fields_searched;
 static int n_contexts_saved;
+#endif
 
 /* Local variables to help save memoization contexts.  */
 static tree prev_type_memoized;
@@ -249,7 +249,7 @@ my_new_memoized_entry (chain)
 /* Make an entry in the memoized table for type TYPE
    that the entry for NAME is FIELD.  */
 
-tree
+static tree
 make_memoized_table_entry (type, name, function_p)
      tree type, name;
      int function_p;
@@ -492,10 +492,10 @@ get_binfo (parent, binfo, protect)
 
 /* This is the newer depth first get_base_distance routine.  */
 static int
-get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
+get_base_distance_recursive (binfo, depth, is_private, rval,
                             rval_private_ptr, new_binfo_ptr, parent, path_ptr,
                             protect, via_virtual_ptr, via_virtual)
-     tree binfo, basetype_path, *new_binfo_ptr, parent, *path_ptr;
+     tree binfo, *new_binfo_ptr, parent, *path_ptr;
      int *rval_private_ptr, depth, is_private, rval, protect, *via_virtual_ptr,
        via_virtual;
 {
@@ -569,7 +569,7 @@ get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
 
          was = WATCH_VALUES (rval, *via_virtual_ptr);
          rval = get_base_distance_recursive (base_binfo, depth, via_private,
-                                             binfo, rval, rval_private_ptr,
+                                             rval, rval_private_ptr,
                                              new_binfo_ptr, parent, path_ptr,
                                              protect, via_virtual_ptr,
                                              this_virtual);
@@ -619,8 +619,11 @@ get_base_distance (parent, binfo, protect, path_ptr)
   int via_virtual;
   int watch_access = protect;
 
+  /* Should we be completing types here?  */
   if (TREE_CODE (parent) != TREE_VEC)
-    parent = TYPE_MAIN_VARIANT (parent);
+    parent = complete_type (TYPE_MAIN_VARIANT (parent));
+  else
+    complete_type (TREE_TYPE (parent));
 
   if (TREE_CODE (binfo) == TREE_VEC)
     type = BINFO_TYPE (binfo);
@@ -647,7 +650,7 @@ get_base_distance (parent, binfo, protect, path_ptr)
   if (path_ptr)
     watch_access = 1;
 
-  rval = get_base_distance_recursive (binfo, 0, 0, NULL_TREE, -1,
+  rval = get_base_distance_recursive (binfo, 0, 0, -1,
                                      &rval_private, &new_binfo, parent,
                                      path_ptr, watch_access, &via_virtual, 0);
 
@@ -721,6 +724,8 @@ lookup_field_1 (type, name)
       if (TYPE_VIRTUAL_P (type))
        return CLASSTYPE_VFIELD (type);
     }
+  if (name == constructor_name (type))
+    return TYPE_STUB_DECL (type);
   return NULL_TREE;
 }
 
@@ -1081,8 +1086,8 @@ lookup_field (xbasetype, name, protect, want_type)
     }
   else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
     {
-      type = xbasetype;
-      basetype_path = TYPE_BINFO (xbasetype);
+      type = complete_type (xbasetype);
+      basetype_path = TYPE_BINFO (type);
       BINFO_VIA_PUBLIC (basetype_path) = 1;
       BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
     }
@@ -1132,7 +1137,10 @@ lookup_field (xbasetype, name, protect, want_type)
            {
              if (TREE_CODE (rval) != TYPE_DECL)
                {
-                 rval = purpose_member (name, CLASSTYPE_TAGS (type));
+                 if (name == constructor_name (type))
+                   rval = type;
+                 else
+                   rval = purpose_member (name, CLASSTYPE_TAGS (type));
                  if (rval)
                    rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
                }
@@ -1314,7 +1322,10 @@ lookup_field (xbasetype, name, protect, want_type)
              {
                if (TREE_CODE (rval) != TYPE_DECL)
                  {
-                   rval = purpose_member (name, CLASSTYPE_TAGS (type));
+                   if (name == constructor_name (type))
+                     rval = type;
+                   else
+                     rval = purpose_member (name, CLASSTYPE_TAGS (type));
                    if (rval)
                      rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
                  }
@@ -1577,7 +1588,7 @@ lookup_fnfields (basetype_path, name, complain)
 
   binfo = basetype_path;
   binfo_h = binfo;
-  type = BINFO_TYPE (basetype_path);
+  type = complete_type (BINFO_TYPE (basetype_path));
 
   /* The memoization code is in need of maintenance. */
   if (!find_all && CLASSTYPE_MTABLE_ENTRY (type))
@@ -1826,7 +1837,7 @@ lookup_fnfields (basetype_path, name, complain)
    QFN, if non-NULL, is a predicate dictating whether the type should
    even be queued.  */
 
-HOST_WIDE_INT
+static HOST_WIDE_INT
 breadth_first_search (binfo, testfn, qfn)
      tree binfo;
      int (*testfn)();
@@ -1932,7 +1943,8 @@ static tree get_virtual_destructor (binfo, i)
   return 0;
 }
 
-int tree_has_any_destructor_p (binfo, i)
+static int
+tree_has_any_destructor_p (binfo, i)
      tree binfo;
      int i;
 {
@@ -2297,7 +2309,9 @@ dfs_walk (binfo, fn, qfn)
 
       if (qfn == 0 || (*qfn)(base_binfo))
        {
-         if (fn == dfs_init_vbase_pointers)
+         if (TREE_CODE (BINFO_TYPE (base_binfo)) == TEMPLATE_TYPE_PARM)
+           /* Pass */;
+         else if (fn == dfs_init_vbase_pointers)
            {
              /* When traversing an arbitrary MI hierarchy, we need to keep
                 a record of the path we took to get down to the final base
@@ -2334,8 +2348,9 @@ dfs_walk (binfo, fn, qfn)
              dfs_walk (base_binfo, fn, qfn);
 
              vbase_decl_ptr_intermediate = saved_vbase_decl_ptr_intermediate;
-           } else
-             dfs_walk (base_binfo, fn, qfn);
+           }
+         else
+           dfs_walk (base_binfo, fn, qfn);
        }
     }
 
@@ -2350,31 +2365,37 @@ static int unnumberedp (binfo) tree binfo;
 
 static int markedp (binfo) tree binfo;
 { return BINFO_MARKED (binfo); }
-static int bfs_markedp (binfo, i) tree binfo; int i;
-{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)); }
 static int unmarkedp (binfo) tree binfo;
 { return BINFO_MARKED (binfo) == 0; }
+
+#if 0
+static int bfs_markedp (binfo, i) tree binfo; int i;
+{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)); }
 static int bfs_unmarkedp (binfo, i) tree binfo; int i;
 { return BINFO_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-static int marked_vtable_pathp (binfo) tree binfo;
-{ return BINFO_VTABLE_PATH_MARKED (binfo); }
 static int bfs_marked_vtable_pathp (binfo, i) tree binfo; int i;
 { return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int unmarked_vtable_pathp (binfo) tree binfo;
-{ return BINFO_VTABLE_PATH_MARKED (binfo) == 0; }
 static int bfs_unmarked_vtable_pathp (binfo, i) tree binfo; int i;
 { return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-static int marked_new_vtablep (binfo) tree binfo;
-{ return BINFO_NEW_VTABLE_MARKED (binfo); }
 static int bfs_marked_new_vtablep (binfo, i) tree binfo; int i;
 { return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int unmarked_new_vtablep (binfo) tree binfo;
-{ return BINFO_NEW_VTABLE_MARKED (binfo) == 0; }
 static int bfs_unmarked_new_vtablep (binfo, i) tree binfo; int i;
 { return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
+#endif
+
+static int marked_vtable_pathp (binfo) tree binfo;
+{ return BINFO_VTABLE_PATH_MARKED (binfo); }
+static int unmarked_vtable_pathp (binfo) tree binfo;
+{ return BINFO_VTABLE_PATH_MARKED (binfo) == 0; }
+static int marked_new_vtablep (binfo) tree binfo;
+{ return BINFO_NEW_VTABLE_MARKED (binfo); }
+static int unmarked_new_vtablep (binfo) tree binfo;
+{ return BINFO_NEW_VTABLE_MARKED (binfo) == 0; }
 
+#if 0
 static int dfs_search_slot_nonempty_p (binfo) tree binfo;
 { return CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) != 0; }
+#endif
 
 static int dfs_debug_unmarkedp (binfo) tree binfo;
 { return CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) == 0; }
@@ -2400,14 +2421,17 @@ dfs_unnumber (binfo)
   BINFO_CID (binfo) = 0;
 }
 
+#if 0
 static void
 dfs_mark (binfo) tree binfo;
 { SET_BINFO_MARKED (binfo); }
+#endif
 
 static void
 dfs_unmark (binfo) tree binfo;
 { CLEAR_BINFO_MARKED (binfo); }
 
+#if 0
 static void
 dfs_mark_vtable_path (binfo) tree binfo;
 { SET_BINFO_VTABLE_PATH_MARKED (binfo); }
@@ -2427,6 +2451,7 @@ dfs_unmark_new_vtable (binfo) tree binfo;
 static void
 dfs_clear_search_slot (binfo) tree binfo;
 { CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
+#endif
 
 static void
 dfs_debug_mark (binfo)
@@ -2571,9 +2596,7 @@ init_vbase_pointers (type, decl_ptr)
       tree binfo = TYPE_BINFO (type);
       flag_this_is_variable = -2;
       vbase_types = CLASSTYPE_VBASECLASSES (type);
-      vbase_decl_ptr = decl_ptr;
-      vbase_decl = build_indirect_ref (decl_ptr, NULL_PTR);
-      vbase_decl_ptr_intermediate = vbase_decl_ptr;
+      vbase_decl_ptr = vbase_decl_ptr_intermediate = decl_ptr;
       vbase_init_result = NULL_TREE;
       dfs_walk (binfo, dfs_find_vbases, unmarked_vtable_pathp);
       dfs_walk (binfo, dfs_init_vbase_pointers, marked_vtable_pathp);
@@ -2800,7 +2823,7 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
    offsets are valid to store vtables.  When zero, we must store new
    vtables through virtual baseclass pointers.
 
-   We setup and use the globals: vbase_decl, vbase_decl_ptr, vbase_types
+   We setup and use the globals: vbase_decl_ptr, vbase_types
    ICK!  */
 
 void
@@ -2816,7 +2839,6 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
       tree vbases = CLASSTYPE_VBASECLASSES (type);
       vbase_types = vbases;
       vbase_decl_ptr = true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) : decl_ptr;
-      vbase_decl = true_exp ? true_exp : build_indirect_ref (decl_ptr, NULL_PTR);
 
       dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep);
 
@@ -2840,7 +2862,8 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
 
          if (flag_vtable_thunks)
            {
-             /* We don't have dynamic thunks yet!  So for now, just fail silently. */
+             /* We don't have dynamic thunks yet!
+                So for now, just fail silently. */
            }
          else
            {
@@ -3270,13 +3293,9 @@ void
 push_class_decls (type)
      tree type;
 {
-  tree id;
   struct obstack *ambient_obstack = current_obstack;
-
   search_stack = push_search_level (search_stack, &search_obstack);
 
-  id = TYPE_IDENTIFIER (type);
-
   /* Push class fields into CLASS_VALUE scope, and mark.  */
   dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp);
 
@@ -3351,8 +3370,7 @@ unuse_fields (type)
 }
 
 void
-pop_class_decls (type)
-     tree type;
+pop_class_decls ()
 {
   /* We haven't pushed a search level when dealing with cached classes,
      so we'd better not try to pop it.  */
@@ -3400,7 +3418,7 @@ init_search_processing ()
 
   /* This gives us room to build our chains of basetypes,
      whether or not we decide to memoize them.  */
-  type_stack = push_type_level (0, &type_obstack);
+  type_stack = push_type_level ((struct stack_level *)0, &type_obstack);
   _vptr_name = get_identifier ("_vptr");
 }
 
@@ -3416,12 +3434,14 @@ reinit_search_statistics ()
   memoized_fast_rejects[1] = 0;
   memoized_fields_searched[0] = 0;
   memoized_fields_searched[1] = 0;
+#ifdef GATHER_STATISTICS
   n_fields_searched = 0;
   n_calls_lookup_field = 0, n_calls_lookup_field_1 = 0;
   n_calls_lookup_fnfields = 0, n_calls_lookup_fnfields_1 = 0;
   n_calls_get_base_type = 0;
   n_outer_fields_searched = 0;
   n_contexts_saved = 0;
+#endif
 }
 
 static tree conversions;
index 27d4e2ec71a00677aee4e90f4b0cc7758343b231..de687e02a58b2116032e308299a82815ca43b0cb 100644 (file)
@@ -534,7 +534,7 @@ build_signature_table_constructor (sig_ty, rhs)
            {
              error ("class `%s' does not contain a method conforming to `%s'",
                     TYPE_NAME_STRING (rhstype),
-                    fndecl_as_string (NULL, sig_method, 1));
+                    fndecl_as_string (sig_method, 1));
              undo_casts (sig_ty);
              return error_mark_node;
            }
@@ -1000,7 +1000,7 @@ build_signature_method_call (basetype, instance, function, parms)
          && (!deflt_call || deflt_call == error_mark_node)))
     {
       compiler_error ("cannot build call of signature member function `%s'",
-                     fndecl_as_string (NULL, function, 1));
+                     fndecl_as_string (function, 1));
       return error_mark_node;
     }
 
index a0250e575863cfadf2f1e4d27777dc869b2cd315..6564cab2e6331fd78e64659df35fd0b2fda6e690 100644 (file)
@@ -295,8 +295,8 @@ yylex()
              if (lastiddecl != trrr)
                {
                  lastiddecl = trrr;
-                 if (got_scope || got_object)
-                   tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
+                 if (got_scope)
+                   tmp_token.yylval.ttype = trrr;
                }
              break;
            case IDENTIFIER:
@@ -307,7 +307,7 @@ yylex()
              break;
            case NSNAME:
              lastiddecl = trrr;
-             if (got_scope || got_object)
+             if (got_scope)
                tmp_token.yylval.ttype = trrr;
              break;
            default:
@@ -352,6 +352,7 @@ yylex()
       consume_token();
     }
 
+  got_object = NULL_TREE;
   yylval = tmp_token.yylval;
   yychar = tmp_token.yychar;
   end_of_file = tmp_token.end_of_file;
index e34cf5bab94dffaed182d56fa05af573a1538671..e5eb64749e5e6294c1eabf73cd42a824be63a247 100644 (file)
@@ -26,6 +26,11 @@ Boston, MA 02111-1307, USA.  */
 #include "cp-tree.h"
 #include "flags.h"
 #include "rtl.h"
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
 
 #define CEIL(x,y) (((x) + (y) - 1) / (y))
 
@@ -202,10 +207,9 @@ lvalue_or_else (ref, string)
    and return it so that it can be processed by language-independent
    and language-specific expression expanders.  */
 tree
-build_cplus_new (type, init, with_cleanup_p)
+build_cplus_new (type, init)
      tree type;
      tree init;
-     int with_cleanup_p;
 {
   tree slot;
   tree rval;
@@ -234,7 +238,7 @@ break_out_cleanups (exp)
 
   if (TREE_CODE (tmp) == CALL_EXPR
       && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (tmp)))
-    return build_cplus_new (TREE_TYPE (tmp), tmp, 1);
+    return build_cplus_new (TREE_TYPE (tmp), tmp);
 
   while (TREE_CODE (tmp) == NOP_EXPR
         || TREE_CODE (tmp) == CONVERT_EXPR
@@ -245,7 +249,7 @@ break_out_cleanups (exp)
        {
          TREE_OPERAND (tmp, 0)
            = build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)),
-                              TREE_OPERAND (tmp, 0), 1);
+                              TREE_OPERAND (tmp, 0));
          break;
        }
       else
@@ -412,7 +416,14 @@ build_cplus_array_type (elt_type, index_type)
       saveable_obstack = &permanent_obstack;
     }
 
-  t = build_array_type (elt_type, index_type);
+  if (current_template_parms)
+    {
+      t = make_node (ARRAY_TYPE);
+      TREE_TYPE (t) = elt_type;
+      TYPE_DOMAIN (t) = index_type;
+    }
+  else
+    t = build_array_type (elt_type, index_type);
 
   /* Push these needs up so that initialization takes place
      more easily.  */
@@ -568,7 +579,6 @@ layout_vbasetypes (rec, max)
   register unsigned const_size = 0;
   register tree var_size = 0;
   int nonvirtual_const_size;
-  tree nonvirtual_var_size;
 
   CLASSTYPE_VBASECLASSES (rec) = vbase_types;
 
@@ -578,7 +588,6 @@ layout_vbasetypes (rec, max)
     var_size = TYPE_SIZE (rec);
 
   nonvirtual_const_size = const_size;
-  nonvirtual_var_size = var_size;
 
   while (vbase_types)
     {
@@ -1403,10 +1412,7 @@ build_exception_variant (type, raises)
      tree type;
      tree raises;
 {
-  int i;
   tree v = TYPE_MAIN_VARIANT (type);
-  tree t, t2, cname;
-  tree *a = (tree *)alloca ((list_length (raises)+1) * sizeof (tree));
   int constp = TYPE_READONLY (type);
   int volatilep = TYPE_VOLATILE (type);
 
@@ -1435,6 +1441,7 @@ build_exception_variant (type, raises)
       raises = copy_list (raises);
       pop_obstacks ();
     }
+
   TYPE_RAISES_EXCEPTIONS (v) = raises;
   return v;
 }
@@ -1449,7 +1456,6 @@ mapcar (t, func)
      tree t;
      tree (*func)();
 {
-  enum tree_code code;
   tree tmp;
 
   if (t == NULL_TREE)
@@ -1458,7 +1464,7 @@ mapcar (t, func)
   if (tmp = func (t), tmp != NULL_TREE)
     return tmp;
 
-  switch (code = TREE_CODE (t))
+  switch (TREE_CODE (t))
     {
     case ERROR_MARK:
       return error_mark_node;
@@ -1552,6 +1558,8 @@ mapcar (t, func)
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
     case CALL_EXPR:
+    case ARRAY_REF:
+    case SCOPE_REF:
       t = copy_node (t);
       TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
       TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
@@ -1646,15 +1654,24 @@ copy_to_permanent (t)
   return t;
 }
 
+#ifdef GATHER_STATISTICS
+extern int depth_reached;
+#endif
+
 void
 print_lang_statistics ()
 {
-  extern struct obstack maybepermanent_obstack;
+  extern struct obstack maybepermanent_obstack, decl_obstack;
   print_obstack_statistics ("class_obstack", &class_obstack);
+  print_obstack_statistics ("decl_obstack", &decl_obstack);
   print_obstack_statistics ("permanent_obstack", &permanent_obstack);
   print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack);
   print_search_statistics ();
   print_class_statistics ();
+#ifdef GATHER_STATISTICS
+  fprintf (stderr, "maximum template instantiation depth reached: %d\n",
+          depth_reached);
+#endif
 }
 
 /* This is used by the `assert' macro.  It is provided in libgcc.a,
@@ -1720,7 +1737,7 @@ bot_manip (t)
     return t;
   else if (TREE_CODE (t) == TARGET_EXPR)
     return build_cplus_new (TREE_TYPE (t),
-                           break_out_target_exprs (TREE_OPERAND (t, 1)), 0);
+                           break_out_target_exprs (TREE_OPERAND (t, 1)));
   return NULL_TREE;
 }
   
@@ -1819,3 +1836,151 @@ cp_expand_decl_cleanup (decl, cleanup)
 {
   return expand_decl_cleanup (decl, unsave_expr (cleanup));
 }
+
+/* Obstack used for allocating nodes in template function and variable
+   definitions.  */
+
+extern struct obstack *expression_obstack;
+
+/* Similar to `build_nt', except we build
+   on the permanent_obstack, regardless.  */
+
+tree
+build_min_nt VPROTO((enum tree_code code, ...))
+{
+#ifndef __STDC__
+  enum tree_code code;
+#endif
+  register struct obstack *ambient_obstack = expression_obstack;
+  va_list p;
+  register tree t;
+  register int length;
+  register int i;
+
+  VA_START (p, code);
+
+#ifndef __STDC__
+  code = va_arg (p, enum tree_code);
+#endif
+
+  expression_obstack = &permanent_obstack;
+
+  t = make_node (code);
+  length = tree_code_length[(int) code];
+  TREE_COMPLEXITY (t) = lineno;
+
+  for (i = 0; i < length; i++)
+    {
+      tree x = va_arg (p, tree);
+      TREE_OPERAND (t, i) = copy_to_permanent (x);
+    }
+
+  va_end (p);
+  expression_obstack = ambient_obstack;
+  return t;
+}
+
+/* Similar to `build', except we build
+   on the permanent_obstack, regardless.  */
+
+tree
+build_min VPROTO((enum tree_code code, tree tt, ...))
+{
+#ifndef __STDC__
+  enum tree_code code;
+  tree tt;
+#endif
+  register struct obstack *ambient_obstack = expression_obstack;
+  va_list p;
+  register tree t;
+  register int length;
+  register int i;
+
+  VA_START (p, tt);
+
+#ifndef __STDC__
+  code = va_arg (p, enum tree_code);
+  tt = va_arg (p, tree);
+#endif
+
+  expression_obstack = &permanent_obstack;
+
+  t = make_node (code);
+  length = tree_code_length[(int) code];
+  TREE_TYPE (t) = tt;
+  TREE_COMPLEXITY (t) = lineno;
+
+  for (i = 0; i < length; i++)
+    {
+      tree x = va_arg (p, tree);
+      TREE_OPERAND (t, i) = copy_to_permanent (x);
+    }
+
+  va_end (p);
+  expression_obstack = ambient_obstack;
+  return t;
+}
+
+/* Same as `tree_cons' but make a permanent object.  */
+
+tree
+min_tree_cons (purpose, value, chain)
+     tree purpose, value, chain;
+{
+  register tree node;
+  register struct obstack *ambient_obstack = current_obstack;
+  current_obstack = &permanent_obstack;
+
+  node = tree_cons (purpose, value, chain);
+  current_obstack = ambient_obstack;
+  return node;
+}
+
+tree
+get_type_decl (t)
+     tree t;
+{
+  if (TREE_CODE (t) == IDENTIFIER_NODE)
+    return identifier_typedecl_value (t);
+  if (TREE_CODE (t) == TYPE_DECL)
+    return t;
+  if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+    return TYPE_STUB_DECL (t);
+  
+  my_friendly_abort (42);
+}
+
+int
+can_free (obstack, t)
+     struct obstack *obstack;
+     tree t;
+{
+  int size;
+
+  if (TREE_CODE (t) == TREE_VEC)
+    size = (TREE_VEC_LENGTH (t)-1) * sizeof (tree) + sizeof (struct tree_vec);
+  else
+    my_friendly_abort (42);
+
+#define ROUND(x) ((x + obstack_alignment_mask (obstack)) \
+                 & ~ obstack_alignment_mask (obstack))
+  if ((char *)t + ROUND (size) == obstack_next_free (obstack))
+    return 1;
+#undef ROUND
+
+  return 0;
+}
+
+/* Return first vector element whose BINFO_TYPE is ELEM.
+   Return 0 if ELEM is not in VEC.  */
+
+tree
+vec_binfo_member (elem, vec)
+     tree elem, vec;
+{
+  int i;
+  for (i = 0; i < TREE_VEC_LENGTH (vec); ++i)
+    if (elem == BINFO_TYPE (TREE_VEC_ELT (vec, i)))
+      return TREE_VEC_ELT (vec, i);
+  return NULL_TREE;
+}
index 5a3d2fb672409ea476113823cc4f9ddaf629cceb..e4b944b4784ad92578b86cdb93703eaa461a15c0 100644 (file)
@@ -79,7 +79,12 @@ tree
 require_complete_type (value)
      tree value;
 {
-  tree type = TREE_TYPE (value);
+  tree type;
+
+  if (current_template_parms)
+    return value;
+
+  type = TREE_TYPE (value);
 
   /* First, detect a valid value with a complete type.  */
   if (TYPE_SIZE (type) != 0
@@ -105,10 +110,35 @@ require_complete_type (value)
       return require_complete_type (value);
     }
 
+  if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+    {
+      instantiate_class_template (type);
+      if (TYPE_SIZE (type) != 0)
+       return value;
+    }
+
   incomplete_type_error (value, type);
   return error_mark_node;
 }
 
+tree
+complete_type (type)
+     tree type;
+{
+  if (TYPE_SIZE (type) != NULL_TREE)
+    ;
+  else if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      tree t = complete_type (TREE_TYPE (type));
+      if (TYPE_SIZE (t) != NULL_TREE)
+       type = build_cplus_array_type (t, TYPE_DOMAIN (type));
+    }
+  else if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+    instantiate_class_template (type);
+
+  return type;
+}
+
 /* Return truthvalue of whether type of EXP is instantiated.  */
 int
 type_unknown_p (exp)
@@ -309,6 +339,11 @@ common_type (t1, t2)
   if (TREE_CODE (t2) == ENUMERAL_TYPE)
     t2 = type_for_size (TYPE_PRECISION (t2), 1);
 
+  if (TYPE_PTRMEMFUNC_P (t1))
+    t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
+  if (TYPE_PTRMEMFUNC_P (t2))
+    t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
+
   code1 = TREE_CODE (t1);
   code2 = TREE_CODE (t2);
 
@@ -471,7 +506,8 @@ common_type (t1, t2)
          tree b1 = TYPE_OFFSET_BASETYPE (t1);
          tree b2 = TYPE_OFFSET_BASETYPE (t2);
 
-         if (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2))
+         if (comptypes (b1, b2, 1)
+             || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
            basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));
          else
            {
@@ -516,9 +552,8 @@ common_type (t1, t2)
 \f
 /* Return 1 if TYPE1 and TYPE2 raise the same exceptions.  */
 int
-compexcepttypes (t1, t2, strict)
+compexcepttypes (t1, t2)
      tree t1, t2;
-     int strict;
 {
   return TYPE_RAISES_EXCEPTIONS (t1) == TYPE_RAISES_EXCEPTIONS (t2);
 }
@@ -611,6 +646,11 @@ comptypes (type1, type2, strict)
        return 1;
     }
 
+  if (TYPE_PTRMEMFUNC_P (t1))
+    t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
+  if (TYPE_PTRMEMFUNC_P (t2))
+    t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
+
   /* Different classes of types can't be compatible.  */
 
   if (TREE_CODE (t1) != TREE_CODE (t2))
@@ -660,6 +700,28 @@ comptypes (type1, type2, strict)
     {
     case RECORD_TYPE:
     case UNION_TYPE:
+      if (CLASSTYPE_TEMPLATE_INFO (t1) && CLASSTYPE_TEMPLATE_INFO (t2)
+         && CLASSTYPE_TI_TEMPLATE (t1) == CLASSTYPE_TI_TEMPLATE (t2))
+       {
+         int i = TREE_VEC_LENGTH (CLASSTYPE_TI_ARGS (t1));
+         tree *p1 = &TREE_VEC_ELT (CLASSTYPE_TI_ARGS (t1), 0);
+         tree *p2 = &TREE_VEC_ELT (CLASSTYPE_TI_ARGS (t2), 0);
+       
+         while (i--)
+           {
+             if (TREE_CODE_CLASS (TREE_CODE (p1[i])) == 't')
+               {
+                 if (! comptypes (p1[i], p2[i], 1))
+                   return 0;
+               }
+             else
+               {
+                 if (simple_cst_equal (p1[i], p2[i]) <= 0)
+                   return 0;
+               }
+           }
+         return 1;
+       }
       if (strict <= 0)
        goto look_hard;
       return 0;
@@ -671,7 +733,7 @@ comptypes (type1, type2, strict)
       break;
 
     case METHOD_TYPE:
-      if (! compexcepttypes (t1, t2, strict))
+      if (! compexcepttypes (t1, t2))
        return 0;
 
       /* This case is anti-symmetrical!
@@ -719,7 +781,7 @@ comptypes (type1, type2, strict)
       break;
 
     case FUNCTION_TYPE:
-      if (! compexcepttypes (t1, t2, strict))
+      if (! compexcepttypes (t1, t2))
        return 0;
 
       val = ((TREE_TYPE (t1) == TREE_TYPE (t2)
@@ -734,30 +796,6 @@ comptypes (type1, type2, strict)
 
     case TEMPLATE_TYPE_PARM:
       return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2);
-
-    case UNINSTANTIATED_P_TYPE:
-      if (UPT_TEMPLATE (t1) != UPT_TEMPLATE (t2))
-       return 0;
-      {
-       int i = TREE_VEC_LENGTH (UPT_PARMS (t1));
-       tree *p1 = &TREE_VEC_ELT (UPT_PARMS (t1), 0);
-       tree *p2 = &TREE_VEC_ELT (UPT_PARMS (t2), 0);
-       
-       while (i--)
-         {
-           if (TREE_CODE_CLASS (TREE_CODE (p1[i])) == 't')
-             {
-               if (! comptypes (p1[i], p2[i], 1))
-                 return 0;
-             }
-           else
-             {
-               if (simple_cst_equal (p1[i], p2[i]) <= 0)
-                 return 0;
-             }
-         }
-      }
-      return 1;
     }
   return attrval == 2 && val == 1 ? 2 : val;
 }
@@ -889,7 +927,7 @@ tree
 common_base_type (tt1, tt2)
      tree tt1, tt2;
 {
-  tree best = NULL_TREE, tmp;
+  tree best = NULL_TREE;
   int i;
 
   /* If one is a baseclass of another, that's good enough.  */
@@ -1215,6 +1253,9 @@ c_sizeof (type)
   enum tree_code code = TREE_CODE (type);
   tree t;
 
+  if (current_template_parms)
+    return build_min (SIZEOF_EXPR, sizetype, type);
+
   if (code == FUNCTION_TYPE)
     {
       if (pedantic || warn_pointer_arith)
@@ -1259,9 +1300,9 @@ c_sizeof (type)
       return size_int (0);
     }
 
-  if (TYPE_SIZE (type) == 0)
+  if (TYPE_SIZE (complete_type (type)) == 0)
     {
-      error ("`sizeof' applied to an incomplete type");
+      cp_error ("`sizeof' applied to incomplete type `%T'", type);
       return size_int (0);
     }
 
@@ -1274,6 +1315,36 @@ c_sizeof (type)
   return t;
 }
 
+tree
+expr_sizeof (e)
+     tree e;
+{
+  if (current_template_parms)
+    return build_min (SIZEOF_EXPR, sizetype, e);
+
+  if (TREE_CODE (e) == COMPONENT_REF
+      && DECL_BIT_FIELD (TREE_OPERAND (e, 1)))
+    error ("sizeof applied to a bit-field");
+  /* ANSI says arrays and functions are converted inside comma.
+     But we can't really convert them in build_compound_expr
+     because that would break commas in lvalues.
+     So do the conversion here if operand was a comma.  */
+  if (TREE_CODE (e) == COMPOUND_EXPR
+      && (TREE_CODE (TREE_TYPE (e)) == ARRAY_TYPE
+         || TREE_CODE (TREE_TYPE (e)) == FUNCTION_TYPE))
+    e = default_conversion (e);
+  else if (TREE_CODE (e) == TREE_LIST)
+    {
+      tree t = TREE_VALUE (e);
+      if (t != NULL_TREE
+         && ((TREE_TYPE (t)
+              && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
+             || is_overloaded_fn (t)))
+       pedwarn ("ANSI C++ forbids taking the sizeof a function type");
+    }
+  return c_sizeof (TREE_TYPE (e));
+}
+  
 tree
 c_sizeof_nowarn (type)
      tree type;
@@ -1657,10 +1728,13 @@ build_component_ref (datum, component, basetype_path, protect)
      int protect;
 {
   register tree basetype = TREE_TYPE (datum);
-  register enum tree_code code = TREE_CODE (basetype);
+  register enum tree_code code;
   register tree field = NULL;
   register tree ref;
 
+  if (current_template_parms)
+    return build_min_nt (COMPONENT_REF, datum, component);
+
   /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it. */
   switch (TREE_CODE (datum))
     {
@@ -1680,6 +1754,8 @@ build_component_ref (datum, component, basetype_path, protect)
                              basetype_path, protect));
     }
 
+  code = TREE_CODE (basetype);
+
   if (code == REFERENCE_TYPE)
     {
       datum = convert_from_reference (datum);
@@ -1703,7 +1779,7 @@ build_component_ref (datum, component, basetype_path, protect)
       return error_mark_node;
     }
 
-  if (TYPE_SIZE (basetype) == 0)
+  if (TYPE_SIZE (complete_type (basetype)) == 0)
     {
       incomplete_type_error (0, basetype);
       return error_mark_node;
@@ -1888,7 +1964,12 @@ build_x_indirect_ref (ptr, errorstring)
      tree ptr;
      char *errorstring;
 {
-  tree rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, NULL_TREE);
+  tree rval;
+
+  if (current_template_parms)
+    return build_min_nt (INDIRECT_REF, ptr);
+
+  rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, NULL_TREE);
   if (rval)
     return rval;
   return build_indirect_ref (ptr, errorstring);
@@ -1984,8 +2065,6 @@ tree
 build_array_ref (array, idx)
      tree array, idx;
 {
-  tree itype;
-
   if (idx == 0)
     {
       error ("subscript missing in array reference");
@@ -1996,8 +2075,6 @@ build_array_ref (array, idx)
       || TREE_TYPE (idx) == error_mark_node)
     return error_mark_node;
 
-  itype = TREE_TYPE (idx);
-
   if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
       && TREE_CODE (array) != INDIRECT_REF)
     {
@@ -2145,6 +2222,9 @@ build_x_function_call (function, params, decl)
   if (function == error_mark_node)
     return error_mark_node;
 
+  if (current_template_parms)
+    return build_min_nt (CALL_EXPR, function, params, 0);
+
   type = TREE_TYPE (function);
   is_method = ((TREE_CODE (function) == TREE_LIST
                && current_class_type != NULL_TREE
@@ -2818,8 +2898,13 @@ build_x_binary_op (code, arg1, arg2)
      enum tree_code code;
      tree arg1, arg2;
 {
-  tree rval = build_opfncall (code, LOOKUP_SPECULATIVELY,
-                             arg1, arg2, NULL_TREE);
+  tree rval;
+
+  if (current_template_parms)
+    return build_min_nt (code, arg1, arg2);
+
+  rval = build_opfncall (code, LOOKUP_SPECULATIVELY,
+                        arg1, arg2, NULL_TREE);
   if (rval)
     return build_opfncall (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
   if (code == MEMBER_REF)
@@ -2841,7 +2926,6 @@ build_binary_op (code, arg1, arg2, convert_p)
 
   if (convert_p)
     {
-      tree args_save [2];
       tree type0, type1;
       args[0] = decay_conversion (args[0]);
       args[1] = decay_conversion (args[1]);
@@ -3483,7 +3567,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
                 it never happens because available widths are 2**N.  */
              && (!TREE_UNSIGNED (final_type)
                  || unsigned_arg
-                 || ((unsigned) 2 * TYPE_PRECISION (TREE_TYPE (arg0))
+                 || (((unsigned) 2 * TYPE_PRECISION (TREE_TYPE (arg0)))
                      <= TYPE_PRECISION (result_type))))
            {
              /* Do an unsigned shift if the operand was zero-extended.  */
@@ -3578,8 +3662,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
             have all bits set that are set in the ~ operand when it is
             extended.  */
 
-         if (TREE_CODE (primop0) == BIT_NOT_EXPR
-             ^ TREE_CODE (primop1) == BIT_NOT_EXPR)
+         if ((TREE_CODE (primop0) == BIT_NOT_EXPR)
+             ^ (TREE_CODE (primop1) == BIT_NOT_EXPR))
            {
              if (TREE_CODE (primop0) == BIT_NOT_EXPR)
                primop0 = get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
@@ -3705,7 +3789,7 @@ pointer_int_sum (resultcode, ptrop, intop)
       size_exp = integer_one_node;
     }
   else
-    size_exp = size_in_bytes (TREE_TYPE (result_type));
+    size_exp = size_in_bytes (complete_type (TREE_TYPE (result_type)));
 
   /* Needed to make OOPS V2R3 work.  */
   intop = folded;
@@ -3863,6 +3947,9 @@ build_x_unary_op (code, xarg)
      enum tree_code code;
      tree xarg;
 {
+  if (current_template_parms)
+    return build_min_nt (code, xarg, NULL_TREE);
+
   /* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
      error message. */
   if (code == ADDR_EXPR
@@ -3887,7 +3974,10 @@ tree
 condition_conversion (expr)
      tree expr;
 {
-  tree t = convert (boolean_type_node, expr);
+  tree t;
+  if (current_template_parms)
+    return expr;
+  t = convert (boolean_type_node, expr);
   t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
   return t;
 }
@@ -4018,7 +4108,7 @@ build_unary_op (code, xarg, noconvert)
        if (TREE_CODE (argtype) == POINTER_TYPE)
          {
            enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype));
-           if (TYPE_SIZE (TREE_TYPE (argtype)) == 0)
+           if (TYPE_SIZE (complete_type (TREE_TYPE (argtype))) == 0)
              cp_error ("cannot %s a pointer to incomplete type `%T'",
                        ((code == PREINCREMENT_EXPR
                          || code == POSTINCREMENT_EXPR)
@@ -4420,7 +4510,7 @@ unary_complex_lvalue (code, arg)
        if (TREE_CODE (arg) == SAVE_EXPR)
          targ = arg;
        else
-         targ = build_cplus_new (TREE_TYPE (arg), arg, 1);
+         targ = build_cplus_new (TREE_TYPE (arg), arg);
        return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), targ);
       }
 
@@ -4531,6 +4621,9 @@ build_x_conditional_expr (ifexp, op1, op2)
 {
   tree rval = NULL_TREE;
 
+  if (current_template_parms)
+    return build_min_nt (COND_EXPR, ifexp, op1, op2);
+
   /* See comments in `build_x_binary_op'.  */
   if (op1 != 0)
     rval = build_opfncall (COND_EXPR, LOOKUP_SPECULATIVELY, ifexp, op1, op2);
@@ -4838,6 +4931,9 @@ build_x_compound_expr (list)
   tree rest = TREE_CHAIN (list);
   tree result;
 
+  if (current_template_parms)
+    return build_min_nt (COMPOUND_EXPR, list, NULL_TREE);
+
   if (rest == NULL_TREE)
     return build_compound_expr (list);
 
@@ -4915,6 +5011,13 @@ tree build_reinterpret_cast (type, expr)
 
   if (TYPE_PTRMEMFUNC_P (type))
     type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+
+  if (current_template_parms)
+    {
+      tree t = build_min (REINTERPRET_CAST_EXPR, type, expr);
+      return t;
+    }
+
   if (TYPE_PTRMEMFUNC_P (intype))
     intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
 
@@ -5080,6 +5183,13 @@ build_c_cast (type, expr, allow_nonconverting)
       && TREE_CHAIN (value) == NULL_TREE)
     value = TREE_VALUE (value);
 
+  if (current_template_parms)
+    {
+      tree t = build_min (CAST_EXPR, type,
+                         min_tree_cons (NULL_TREE, value, NULL_TREE));
+      return t;
+    }
+
   if (TREE_CODE (type) == VOID_TYPE)
     value = build1 (CONVERT_EXPR, type, value);
   else if (TREE_TYPE (value) == NULL_TREE
@@ -5625,7 +5735,7 @@ build_modify_expr (lhs, modifycode, rhs)
                                         NULL_TREE, 0);
       if (TREE_CODE (newrhs) == CALL_EXPR
          && TYPE_NEEDS_CONSTRUCTING (lhstype))
-       newrhs = build_cplus_new (lhstype, newrhs, 0);
+       newrhs = build_cplus_new (lhstype, newrhs);
 
       /* Can't initialize directly from a TARGET_EXPR, since that would
         cause the lhs to be constructed twice, and possibly result in
@@ -5700,6 +5810,25 @@ build_modify_expr (lhs, modifycode, rhs)
                                 NULL_TREE, 0);
 }
 
+tree
+build_x_modify_expr (lhs, modifycode, rhs)
+     tree lhs;
+     enum tree_code modifycode;
+     tree rhs;
+{
+  if (current_template_parms)
+    return build_min_nt (MODOP_EXPR, lhs,
+                        build_min_nt (modifycode, 0, 0), rhs);
+
+  if (modifycode != NOP_EXPR)
+    {
+      tree rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
+                                 make_node (modifycode));
+      if (rval)
+       return rval;
+    }
+  return build_modify_expr (lhs, modifycode, rhs);
+}
 
 /* Return 0 if EXP is not a valid lvalue in this language
    even though `lvalue_or_else' would accept it.  */
@@ -6216,8 +6345,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
          for (; ; ttl = TREE_TYPE (ttl), ttr = TREE_TYPE (ttr))
            {
              nptrs -= 1;
-             const_parity |= TYPE_READONLY (ttl) < TYPE_READONLY (ttr);
-             volatile_parity |= TYPE_VOLATILE (ttl) < TYPE_VOLATILE (ttr);
+             const_parity |= (TYPE_READONLY (ttl) < TYPE_READONLY (ttr));
+             volatile_parity |= (TYPE_VOLATILE (ttl) < TYPE_VOLATILE (ttr));
 
              if (! left_const
                  && (TYPE_READONLY (ttl) > TYPE_READONLY (ttr)
@@ -6525,7 +6654,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
             cleanups if it is used.  */
          if (TREE_CODE (rhs) == CALL_EXPR)
            {
-             rhs = build_cplus_new (type, rhs, 0);
+             rhs = build_cplus_new (type, rhs);
              return rhs;
            }
          /* Handle the case of default parameter initialization and
@@ -6542,7 +6671,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
                    = build_unary_op (ADDR_EXPR, exp, 0);
                }
              else
-               rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0), 0);
+               rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0));
              return rhs;
            }
          else if (TYPE_HAS_TRIVIAL_INIT_REF (type))
@@ -6562,7 +6691,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
 
              if (exp == 0)
                {
-                 exp = build_cplus_new (type, init, 0);
+                 exp = build_cplus_new (type, init);
                  return exp;
                }
 
@@ -6675,7 +6804,6 @@ c_expand_return (retval)
   extern tree dtor_label, ctor_label;
   tree result = DECL_RESULT (current_function_decl);
   tree valtype = TREE_TYPE (result);
-  register int use_temp = 0;
   int returns_value = 1;
 
   if (TREE_THIS_VOLATILE (current_function_decl))
@@ -6687,6 +6815,12 @@ c_expand_return (retval)
       return;
     }
 
+  if (current_template_parms)
+    {
+      add_tree (build_min_nt (RETURN_STMT, retval));
+      return;
+    }
+
   if (retval == NULL_TREE)
     {
       /* A non-named return value does not count.  */
@@ -6827,10 +6961,7 @@ c_expand_return (retval)
 
       if (TYPE_MODE (valtype) != BLKmode
          && any_pending_cleanups (1))
-       {
-         retval = get_temp_regvar (valtype, retval);
-         use_temp = obey_regdecls;
-       }
+       retval = get_temp_regvar (valtype, retval);
     }
   else if (IS_AGGR_TYPE (valtype) && current_function_returns_struct)
     {
@@ -6855,7 +6986,6 @@ c_expand_return (retval)
        {
          retval = get_temp_regvar (valtype, retval);
          expand_cleanups_to (NULL_TREE);
-         use_temp = obey_regdecls;
          result = 0;
        }
       else
index 69d003d916c080fc89f6c338a71e3d7bf3d72c2b..891a9f70a497a42c97454ee603c53da9323a02dc 100644 (file)
@@ -468,8 +468,8 @@ initializer_constant_valid_p (value, endtype)
       return 0;
 
     case PLUS_EXPR:
-      if (TREE_CODE (endtype) == INTEGER_TYPE
-         && TYPE_PRECISION (endtype) < POINTER_SIZE)
+      if ((TREE_CODE (endtype) == INTEGER_TYPE)
+         && (TYPE_PRECISION (endtype) < POINTER_SIZE))
        return 0;
       {
        tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
@@ -485,8 +485,8 @@ initializer_constant_valid_p (value, endtype)
       }
 
     case MINUS_EXPR:
-      if (TREE_CODE (endtype) == INTEGER_TYPE
-         && TYPE_PRECISION (endtype) < POINTER_SIZE)
+      if ((TREE_CODE (endtype) == INTEGER_TYPE)
+         && (TYPE_PRECISION (endtype) < POINTER_SIZE))
        return 0;
       {
        tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
@@ -1287,6 +1287,9 @@ build_x_arrow (datum)
   if (type == error_mark_node)
     return error_mark_node;
 
+  if (current_template_parms)
+    return build_min_nt (ARROW_EXPR, rval);
+
   if (TREE_CODE (rval) == OFFSET_REF)
     {
       rval = resolve_offset_ref (datum);
@@ -1299,7 +1302,7 @@ build_x_arrow (datum)
       type = TREE_TYPE (rval);
     }
 
-  if (IS_AGGR_TYPE (type) && TYPE_OVERLOADS_ARROW (type))
+  if (IS_AGGR_TYPE (type) && TYPE_OVERLOADS_ARROW (complete_type (type)))
     {
       while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval, NULL_TREE, NULL_TREE)))
        {
@@ -1359,6 +1362,9 @@ build_m_component_ref (datum, component)
   tree rettype;
   tree binfo;
 
+  if (current_template_parms)
+    return build_min_nt (DOTSTAR_EXPR, datum, component);
+
   if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component)))
     {
       type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (component)));
@@ -1445,6 +1451,9 @@ build_functional_cast (exp, parms)
   else
     type = exp;
 
+  if (current_template_parms)
+    return build_min (CAST_EXPR, type, parms);
+
   if (IS_SIGNATURE (type))
     {
       error ("signature type not allowed in cast or constructor expression");
@@ -1480,7 +1489,7 @@ build_functional_cast (exp, parms)
        name = DECL_NESTED_TYPENAME (name);
     }
 
-  if (TYPE_SIZE (type) == NULL_TREE)
+  if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
     {
       cp_error ("type `%T' is not yet defined", type);
       return error_mark_node;
@@ -1495,7 +1504,7 @@ build_functional_cast (exp, parms)
   if (expr_as_ctor == error_mark_node)
     return error_mark_node;
 
-  return build_cplus_new (type, expr_as_ctor, 1);
+  return build_cplus_new (type, expr_as_ctor);
 }
 \f
 /* Return the character string for the name that encodes the
index ec4b174b52ca820ff6d9deb2adc30681f47c1c71..2645848b7a781de3e660879deae739eb55eb62c2 100644 (file)
@@ -183,7 +183,7 @@ GNU_xref_end (ect)
   if (xf == NULL) return;
 
   while (cur_scope != NULL)
-    GNU_xref_end_scope(cur_scope->gid,0,0,0,0);
+    GNU_xref_end_scope(cur_scope->gid,0,0,0);
 
   doing_xref = 0;
 
@@ -275,10 +275,10 @@ GNU_xref_start_scope (id)
    TRNS is ???  */
 
 void
-GNU_xref_end_scope (id,inid,prm,keep,trns)
+GNU_xref_end_scope (id,inid,prm,keep)
    HOST_WIDE_INT id;
    HOST_WIDE_INT inid;
-   int prm,keep,trns;
+   int prm,keep;
 {
   XREF_FILE xf;
   XREF_SCOPE xs,lxs,oxs;
@@ -400,7 +400,7 @@ GNU_xref_decl (fndecl,decl)
     }
   else if (TREE_CODE (decl) == TEMPLATE_DECL)
     {
-      if (DECL_TEMPLATE_IS_CLASS (decl))
+      if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
        cls = "CLASSTEMP";
       else if (TREE_CODE (DECL_RESULT (decl)) == FUNCTION_DECL)
        cls = "FUNCTEMP";
@@ -599,7 +599,9 @@ GNU_xref_member(cls, fld)
   char *prot;
   int confg, pure;
   char *d;
+#ifdef XREF_SHORT_MEMBER_NAMES
   int i;
+#endif
   char buf[1024], bufa[1024];
 
   if (!doing_xref) return;
@@ -622,7 +624,9 @@ GNU_xref_member(cls, fld)
 
   d = IDENTIFIER_POINTER(cls);
   sprintf(buf, "%d%s", strlen(d), d);
+#ifdef XREF_SHORT_MEMBER_NAMES
   i = strlen(buf);
+#endif
   strcpy(bufa, declname(fld));
 
 #ifdef XREF_SHORT_MEMBER_NAMES
This page took 0.43678 seconds and 5 git commands to generate.