OSDN Git Service

75th Cygnus<->FSF merge
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 12 Oct 1995 02:33:51 +0000 (02:33 +0000)
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 12 Oct 1995 02:33:51 +0000 (02:33 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@10438 138bc75d-0d04-0410-961f-82ee72b054a4

28 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl.h
gcc/cp/decl2.c
gcc/cp/errfn.c
gcc/cp/error.c
gcc/cp/except.c
gcc/cp/expr.c
gcc/cp/g++.1
gcc/cp/gxx.gperf
gcc/cp/gxxint.texi
gcc/cp/hash.h
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/parse.y
gcc/cp/pt.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

index 79f8312..c00f293 100644 (file)
+Wed Oct 11 12:20:56 1995  Mike Stump  <mrs@cygnus.com>
+
+       * search.c (envelope_add_decl): New routine.  Fix so that
+       methods are hidden in the same way that other members are.
+       (dfs_pushdecls): Cleanup and move functionality out of line,
+       into envelope_add_decl. 
+
+Tue Oct 10 15:46:01 1995  Mike Stump  <mrs@cygnus.com>
+
+       * typeck.c (mark_addressable): Only call assemble_external if we
+       have started the output file.
+
+Tue Oct 10 11:27:18 1995  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * decl.c (start_function): Fix earlier cv-quals change.
+
+Mon Oct  9 23:53:05 1995  Mike Stump  <mrs@cygnus.com>
+
+       * parse.y (complex_direct_notype_declarator): Only push the class if
+       we are not already in the class.
+
+Mon Oct  9 11:22:03 1995  Doug Evans  <dje@canuck.cygnus.com>
+
+       * decl.c (duplicate_decls): Call merge_machine_decl_attributes.
+       Update olddecl's attributes too.
+       (grokdeclarator): #if 0 out call to build_decl_attribute_variant.
+       * typeck.c (common_type): Call merge_machine_type_attributes.
+
+Fri Oct  6 14:44:27 1995  Mike Stump  <mrs@cygnus.com>
+
+       * typeck.c (mark_addressable): Add missing call to
+       assemble_external.
+
+Wed Oct  4 22:05:23 1995  Jeff Law  (law@hurl.cygnus.com
+
+       * cp/decl.c (deplicate_decls): Merge in deferred output
+       status for variables.
+       * cp/tree.c (tree_copy_lang_decl_for_deferred_output): New
+       function to copy the g++ specific parts of a DECL node.
+       (tree_copy_lang_type_for_deferred_output): Similarly for
+       TYPE nodes.
+
+Wed Oct  4 15:06:39 1995  Mike Stump  <mrs@cygnus.com>
+
+       * decl.c (store_parm_decls): Make sure the unwinder start comes
+       before the exception specification start.
+       * except.c (expand_exception_blocks): Make sure the unwinder end
+       comes after the terminate protected catch clause region and after
+       the end of the exception specification region.
+
+Wed Oct  4 12:47:02 1995  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * lex.c (real_yylex): Fix identifier case for linemode.
+       (handle_sysv_pragma): Don't abort when we see a pragma we don't
+       recognize.
+
+Tue Oct  3 14:09:46 1995  Mike Stump  <mrs@cygnus.com>
+
+       * decl.c (store_parm_decls): Add a call to start_eh_unwinder.
+       * except.c (init_exception_processing): __throw doesn't take any
+       arguments.
+       (expand_builtin_throw): Ditto.  Always use Pmode, instead of SImode
+       for all pointers.  Use expand_builtin_return_addr to unwind the
+       first level off the stack.
+       (do_unwind): Always use Pmode, instead of SImode for all pointers.
+       (expand_exception_blocks): Add a call to end_eh_unwinder.
+       (start_eh_unwinder, end_eh_unwinder): New routines to build machine
+       independent stack unwinders for function/method calls.
+       
+Mon Oct  2 17:20:42 1995  Mike Stump  <mrs@cygnus.com>
+
+       * tree.c (unsave_expr_now): Make sure we process the argument list
+       of any called functions.  Fixes incorrect code generation for
+       cleanups.
+
+Mon Oct  2 13:04:16 1995  Mike Stump  <mrs@cygnus.com>
+
+       * typeck.c (get_member_function_from_ptrfunc): Save function if it
+       needs it.  Cures core dump on things like (this->*(f()))().
+
+Sat Sep 23 22:51:25 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (start_function): Conform to gcc cv-quals convention (no
+       expression has a cv-qualified type) in RESULT_DECLs.
+       * method.c (make_thunk): Ditto.
+
+Fri Sep 22 10:21:13 1995  Mike Stump  <mrs@cygnus.com>
+
+       * decl.c (pushtag): Add in the namespace name for the tag.
+
+Thu Sep 21 13:11:13 1995  Mike Stump  <mrs@cygnus.com>
+
+       * parse.y (maybe_base_class_list, base_class_list, base_class,
+       base_class_access_list): Make sure we see the typenames for base
+       classes.
+       * lex.c (see_typename): Instead of failing to see a typename when
+       there is no next token, perfer a typename, and get the next token.
+
+Wed Sep 20 12:35:27 1995  Michael Meissner  <meissner@cygnus.com>
+
+       * decl.c (init_decl_processing): Add __builtin_expect.
+
+Tue Sep 19 16:48:11 1995  Mike Stump  <mrs@cygnus.com>
+
+       * cvt.c (cp_convert_to_pointer): Don't allow leftover conversions to
+       or from pointer to member functions, they must all be handled before
+       this point.
+
+Fri Sep 15 17:14:47 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * init.c (resolve_offset_ref): Fix wording of non-static member
+       being referenced as a static.
+
+Fri Sep 15 12:39:11 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (build_indirect_ref): Only bash pointer if we actually
+       call build_expr_type_conversion.
+
+Thu Sep 14 18:24:56 1995  Jason Merrill  <jason@deneb.cygnus.com>
+
+       * cvt.c (build_expr_type_conversion): Handle conversion from
+       reference.
+       * typeck.c (build_indirect_ref): Avoid infinite recursion.
+
+Thu Sep 14 17:23:28 1995  Mike Stump  <mrs@cygnus.com>
+
+       * decl.c (expand_start_early_try_stmts): New routine to start a try
+       block at the start of the function, for function-try-blocks.
+       * cp-tree.h (expand_start_early_try_stmts): Declare it.
+       * parse.y (function_try_block): Use it, instead of doing it here, as
+       we don't want to include rtl.h here, as that conflicts with RETURN
+       in the parser.
+
+Wed Sep 13 18:32:24 1995  Mike Stump  <mrs@cygnus.com>
+
+       * lex.c (reinit_parse_for_block): Support saving inline
+       function-try-blocks, uses peekyylex.
+       * parse.y (eat_saved_input): New rule, permit the parser to see that
+       END_OF_SAVED_INPUT is ok, as it can see this when parsing the
+       handlers of a function-try-block.
+       (fndef): Use it.
+       (component_decl): Make sure TRY and RETURN can come after fn.def2.
+       * spew.c (peekyylex): New routine to peek at what will come next.
+
 Wed Sep 13 16:52:06 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
+       * typeck.c (comptypes): Tighten up comparisons of template type
+       parms.
+
        * decl.c (duplicate_decls): Turn off whining about virtual functions
        redeclared inline for now.
 
+Wed Sep 13 11:13:40 1995  Mike Stump  <mrs@cygnus.com>
+
+       * decl.c (store_in_parms): New routine to put things before we
+       put base inits.
+       * cp-tree.h (store_in_parms): Declare it.
+       * decl.c (store_parm_decls): Use it to makr sure the starting of the
+       eh spec comes before base inits.
+       (finish_function): Use sequences instead of the obsolete
+       reorder_insns.
+       * parse.y (fndef): Enhance readability and maintainability.  Update
+       to include function_try_block syntax.
+       (function_try_block): Add.
+
+Tue Sep 12 17:43:07 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * call.c (convert_harshness): Use comptypes, not ==, to check if
+       TYPE and PARMTYPE are equivalent on a function type.
+
 Tue Sep 12 17:31:33 1995  Douglas Rupp  (drupp@cs.washington.edu)
 
        * Make-lang.in (cc1plus) : Removed unnecessary $(exeext).
 
+Mon Sep 11 23:24:07 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_throw): Never allocate storage for thrown pointer
+       to objects.
+
+Mon Sep 11 19:36:45 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_start_catch_block): Pointers to objects come
+       back from catch matching already dereferenced, don't dereference
+       again.
+
+Mon Sep 11 15:46:28 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_throw): Only decay the throw expression, don't do
+       any default conversions.  This is so that one can throw and catch
+       characters, and not have them match integers.
+
+Mon Sep 11 13:46:45 1995  Mike Stump  <mrs@cygnus.com>
+
+       * error.c (dump_aggr_type): Deal with anonymous unions that don't
+       have a TYPE_NAME.
+
 Fri Sep  8 20:40:27 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
 
        * lex.c (handle_sysv_pragma): Deal with getting a comma from yylex.
 
+Fri Sep  8 15:51:41 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_end_eh_spec): Handle empty EH specifications.
+
+Fri Sep  8 15:27:22 1995  Mike Stump  <mrs@cygnus.com>
+
+       * cp-tree.h (expand_start_eh_spec): Declare new routine.
+       (expand_end_eh_spec): Ditto.
+       * decl.c (store_parm_decls): Call expand_start_eh_spec to process
+       exception specifications.
+       * except.c (expand_leftover_cleanups): Remove unused parameter.
+       (expand_end_catch_block): Ditto.
+       (expand_exception_blocks): Ditto.
+       (expand_start_eh_spec): New routine to mark the start of an
+       exception specification region.
+       (expand_end_eh_spec): New routine to mark the end of an exception
+       specification region.
+       (expand_exception_blocks): Call expand_end_eh_spec to process
+       exception specifications.
+
 Fri Sep  8 14:40:48 1995  Per Bothner  <bothner@kalessin.cygnus.com>
 
        * lex.c (do_identifier):  Use global binding in preference of
        dead for local variable.
 
+Wed Sep  6 19:32:59 1995  Mike Stump  <mrs@cygnus.com>
+
+       * cp-tree.h (build_exception_variant): Remove used first argument.
+       * decl.c (duplicate_decls): Ditto.
+       (grokfndecl): Ditto.
+       (revert_static_member_fn): Ditto.
+       * decl2.c (grok_method_quals): Ditto.
+       * tree.c (build_exception_variant): Ditto.
+       * typeck.c (common_type): Ditto.
+       * decl2.c (grokclassfn): After changing the type, call
+       build_exception_variant, if necessary.
+
+Tue Sep  5 15:56:27 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_throw): Run cleanups for the throw expression.
+
+Wed Aug 30 15:24:38 1995  Stephen L. Favor  (sfavor@tigger.intecom.com)
+
+       * except.c (expand_builtin_throw): Moved gen_label_rtx calls beyond
+       the store_parm_decls call which does initialization in the emit_*
+       code concerning label numbering.
+       
+Thu Aug 31 09:01:07 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_internal_throw): Let the frontend be responsible
+       for managing all frontend EH parameters, the backend routine only
+       needs to deal with backend values.  type and value are no longer
+       passed to __throw.
+       (init_exception_processing): Ditto.
+       (expand_start_all_catch): Ditto.
+       (expand_end_all_catch): Ditto.
+       (expand_leftover_cleanups): Ditto.
+       (expand_end_catch_block): Ditto.
+       (expand_builtin_throw): Ditto.
+       (expand_throw): Ditto.
+       
+Tue Aug 29 15:04:36 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * cp-tree.h (DECL_REAL_CONTEXT): Give the real declaration context
+       for a decl.
+       * decl.c (cp_finish_decl): Use it.
+
+Tue Aug 29 10:30:27 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_internal_throw): Oops, almost forgot type and
+       value are now trees.
+
+Mon Aug 28 17:57:45 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       Fix the attribute handling to make sure they get noted before we
+       create the function's RTL, in case they can affect that.
+       * decl.c (grokfndecl): New arg ATTRLIST.  Run
+       cplus_decl_attributes before creating the decl's rtl.
+       (grokdeclarator): New arg ATTRLIST, passed down into grokfndecl.
+       (shadow_tag, groktypename, start_decl, start_method): Pass a
+       NULL_TREE to grokdeclarator's new last arg.
+       * decl2.c (grokfield): New arg ATTRLIST, passed into grokdeclarator.
+       (grokbitfield, grokoptypename): Pass a NULL_TREE to
+       grokdeclarator's new last arg.
+       * except.c (expand_start_catch_block): Likewise.
+       * pt.c (process_template_parm, end_template_decl,
+       do_function_instantiation): Likewise.
+       * cp-tree.h (grokfield): Add arg.
+       (grokdeclarator): Move the prototype from here...
+       * decl.h: ...to here.
+       * lex.c (cons_up_default_function): Pass NULL_TREE to grokfield
+       ATTRLIST argument.
+       * parse.y: Create a list for the grokfield arg where appropriate,
+       and pass it down instead of calling cplus_decl_attributes.
+
+Mon Aug 28 15:07:24 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c: Always allow turning on exception handling.  Allow cross
+       compilations to use EH.
+
+Thu Aug 24 17:39:24 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (saved_pc, saved_throw_type, saved_throw_value): Use
+       trees, instead of rtxs, and don't depend on using special machine
+       dependent registers.
+       (expand_internal_throw): Ditto.
+       (init_exception_processing): Ditto.
+       (expand_start_all_catch): Ditto.
+       (expand_end_all_catch): Ditto.
+       (expand_start_catch_block): Ditto.
+       (expand_leftover_cleanups): Ditto.
+       (expand_end_catch_block): Ditto.
+       (expand_builtin_throw): Ditto.
+       (expand_throw): Ditto.
+
+Wed Aug 23 17:25:51 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * cvt.c (build_expr_type_conversion): Handle conversions to
+       reference types.
+
+Wed Aug 23 15:33:59 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (do_unwind): Work around backend bug with -fpic.
+
 Tue Aug 22 17:20:07 1995  Per Bothner  <bothner@kalessin.cygnus.com>
 
        * decl2.c (flag_new_for_scope):  Add a new mode that follows ANSI
@@ -33,7 +339,379 @@ Tue Aug 22 17:20:07 1995  Per Bothner  <bothner@kalessin.cygnus.com>
        and warn if conflicts.
        * parse.y (FOR):  Call note_level_for_for.
 
-Wed Jul 19 11:49:57 1995  Gerald Baumgartner  <gb@alexander.cs.purdue.edu>
+Mon Aug 21 10:28:31 1995  Jason Merrill  <jason@deneb.cygnus.com>
+
+       * decl2.c (import_export_inline): Class interface hackery does not
+       apply to synthesized methods.
+
+Sun Aug 20 16:29:00 1995  Mike Stump  <mrs@cygnus.com>
+
+       * search.c (virtual_context): Find the right context more often.
+       Solves a `recoverable compiler error, fixups for virtual function'
+       problem.
+
+Sun Aug 20 13:53:24 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_start_all_catch): Ensure that we always transfer
+       control to the right EH handler, by rethrowing the end label on the
+       region, instead of hoping we are nested and falling through.
+       (expand_leftover_cleanups): Ditto.
+       (end_protect): Since we now rethrow the end label, put a
+       nop after it, so that outer regions are recognized.
+       * init.c (build_vec_delete_1): New routine to handle most of vector
+       deleting, all code moved here from build_vec_delete.
+       (build_array_eh_cleanup): Use build_vec_delete_1 to do all the real
+       work.
+       (expand_vec_init): If the array needs partial destructing, setup an
+       EH region to handle it.
+       (build_vec_delete): Move lots of code to build_vec_delete_1, use
+       build_vec_delete_1 to do the grunt work.
+       
+Sat Aug 19 14:25:33 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       Handle decl attributes properly for function definitions without
+       previous attribute-loaded declarations.
+       * decl.c (start_function): New arg ATTRS.  Add a call to
+       cplus_decl_attributes with it before we create the RTL.
+       * cp-tree.h (start_function): Update prototype.
+       * parse.y (fn.def1): Pass ATTRS into start_function instead of
+       trying to call cplus_decl_attributes too late.  Pass a NULL_TREE
+       for other use.
+       * decl2.c (finish_file): Pass NULL_TREE as fourth arg to
+       start_function.
+       * method.c (synthesize_method): Likewise.
+       * except.c (expand_builtin_throw): Likewise for start on __throw.
+
+Sat Aug 19 13:36:08 1995  Mike Stump  <mrs@cygnus.com>
+
+       * class.c (set_rtti_entry): Turn on -fvtable-thunk -frtti support.
+       This changes -fvtable-thunks vtable layout, so a recompile will be
+       necessary, if you use -fvtable-thunks.
+       (get_vtable_entry): Use n, instead of i to be consistent with the
+       rest of the compiler.
+       (get_vtable_entry_n): Ditto.
+       (add_virtual_function): Add a slot for the tdesc, if -fvtable-thunks
+       are being used.
+       (finish_struct_1): Ditto.
+       (skip_rtti_stuff): New routine to collapse similar code from many
+       different parts of the compiler.  I think I got them all.
+       (modify_one_vtable): Use it.
+       (fixup_vtable_deltas1): Ditto.
+       (override_one_vtable): Ditto.
+       * decl2.c (mark_vtable_entries): Ditto.
+       * tree.c (debug_binfo): Ditto.
+       * search.c (expand_upcast_fixups): Ditto.
+       (get_abstract_virtuals_1): Ditto.  Use virtuals, instead of tmp to
+       consistent with the rest of the compiler.
+       (get_abstract_virtuals): Ditto.
+       * cp-tree.h (skip_rtti_stuff): New routine, declare it.
+       * gc.c (build_headof): Support -fvtable-thunk and -frtti together.
+       (build_typeid): Ditto.
+       (build_classof): Remove old style way of doing rtti.  Remove support
+       for `classof' and `headof'.
+       * gxx.gperf: Ditto.
+       * hash.h: Ditto.
+       * parse.y: Ditto.
+
+Fri Aug 18 17:31:58 1995  Jason Merrill  <jason@deneb.cygnus.com>
+
+       * decl.c (start_function): Clear ctor_label and dtor_label.
+
+       * class.c (finish_struct_1): Fix handling of access decls.
+
+Tue Aug 15 19:21:54 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * class.c (finish_struct): Only do minimal processing here, so it
+       can be used for class template definitions, as well.
+       (finish_struct_1): New function with the rest of the code.
+
+Tue Aug 15 09:46:16 1995  Mike Stump  <mrs@cygnus.com>
+
+       * class.c (prepare_fresh_vtable): On second though, always build the
+       offset (see Aug 10 change), unless -fvtable-thunks is given.  It
+       does this by calling the new routine set_rtti_entry.
+       (finish_struct): Ditto.
+       (set_rtti_entry): New routine to update the rtti information at the
+       start of the vtable.
+
+Mon Aug 14 12:21:22 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * error.c (dump_decl, case IDENTIFIER_NODE): Only work on a dtor
+       if it's declared in the C++ language spec.
+       (dump_function_decl): Likewise.
+       (dump_function_name): Likewise.
+       (ident_fndecl): Make sure we got something back from lookup_name.
+       * decl.c (start_function): Likewise.
+
+Fri Aug 11 16:52:15 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * call.c (build_method_call): Don't call build_new when calling a
+       constructor without an instance.
+
+Thu Aug 10 20:00:17 1995  Mike Stump  <mrs@cygnus.com>
+
+       * class.c (prepare_fresh_vtable): Always build the offset to the
+       complete object, as it doesn't cost much.  This allows dynamic_cast
+       to void * to work when -frtti isn't given.
+       (finish_struct): Ditto.
+
+Thu Aug 10 16:31:28 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (build_eh_type): Split out some functionality to new
+       routine named build_eh_type_type.
+       (build_eh_type_type): New routine.
+       (expand_start_catch_block): Use build_eh_type_type, as we never want
+       the dynamic type of the catch parameter, just the static type.
+       Fixes core dumps when -frtti is used and one catchs pointers to
+       classes.
+
+Thu Aug 10 14:55:29 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_builtin_throw): Since we now use normal calling
+       conventions for __throw, we have to remove the first layer off the
+       stack, so that the next context we search for handlers is the outer
+       context instead of the context that had the call to __throw, if we
+       don't immediately find the desired context.
+
+Tue Aug  8 17:44:23 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * tree.c (cp_expand_decl_cleanup): Returns int, not tree.
+       * cp-tree.h: Update.
+
+       * parse.y (template_type_parm): Add support for `typename'.
+
+Tue Aug  8 12:06:31 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_internal_throw): New internal routine to throw a
+       value.
+       (expand_end_all_catch, expand_leftover_cleanups): All throwers
+       changed to use `expand_internal_throw' instead of jumping to throw
+       label.
+       (expand_end_catch_block, expand_throw): Ditto.
+       (throw_label): Removed.
+       (expand_builtin_throw): Changed so that EH parameters are passed by
+       normal function call conventions.  Completes Aug 4th work.
+
+Fri Aug  4 17:17:08 1995  Mike Stump  <mrs@cygnus.com>
+
+       * cp-tree.h (expand_builtin_throw): Declare it.
+       * decl2.c (finish_file): Call expand_builtin_throw.
+       * except.c (make_first_label): Remove.
+       (init_exception_processing): Don't use a LABEL_REF for throw_label,
+       instead use a SYMBOL_REF, this is so that we don't use LABEL_REFs in
+       other functions that don't really appear in those functions.  This
+       solves a problem where cc1plus consumed exponential amounts of
+       memory when -Wall was used.
+       (expand_end_all_catch, expand_leftover_cleanups,
+       expand_end_catch_block, expand_throw): Change all uses of
+       throw_label to match new style.
+       (do_unwind): Rename parameter to inner_throw_label, as it is now
+       different from throw_label.  Also, assume that our caller will wrap
+       the passed label with a LABEL_REF, if needed.
+       (expand_builtin_throw): Make external, change so that the generated
+       throw is now a real function.
+       (expand_exception_blocks): Never generate throw code inside another
+       function.
+
+Fri Aug  4 12:20:02 1995  Mike Stump  <mrs@cygnus.com>
+
+       * decl.c (grokdeclarator): Move checking of mutable const objects
+       and mutable static objects down, as we might decide during parsing
+       to unset staticp or constp (for example, when const is part of the
+       object being pointed to).
+
+Thu Aug  3 17:13:43 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (output_exception_table_entry): Enhance portability to
+       weird machines.
+       (emit_exception_table): Ditto.
+
+Thu Aug  3 16:41:38 1995  Mike Stump  <mrs@cygnus.com>
+
+       * typeck.c (build_ptrmemfunc): Handle casting of pointer to
+       non-virtual member functions.
+
+Wed Aug  2 11:58:25 1995  Mike Stump  <mrs@cygnus.com>
+
+       * gc.c (build_typeid): Strip cv qualifiers so that const T&, T&, T
+       and const T all match.
+
+Wed Aug  2 11:25:33 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (build_eh_type): Strip cv qualifiers so that const T&,
+       T&, T and const T all match.
+
+Tue Aug  1 14:20:16 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c: Fix up comments, cleanup code and eliminate exceptNode,
+       exceptStack, exceptstack, push_except_stmts, pop_except_stmts,
+       new_except_stack, push_last_insn, pop_last_insn, insn_save_node and
+       InsnSave.  Also, numerous speed improvements, and correctness
+       improvements.  Double faulting in all situations should now be
+       handled correctly.
+       (expand_start_all_catch): Instead of having many terminate protected
+       regions, just have one.
+       (expand_start_catch_block): No longer have to protect
+       false_label_rtx, as it isn't used for EH region marking.
+       (expand_end_catch_block): Expand out EH cleanups here by using
+       expand_leftover_cleanups.
+       (expand_end_all_catch): Use sequences instead of playing with insn
+       links directly.
+       (expand_exception_blocks): Ditto.  Also protect all catch clauses
+       with one terminate region.
+
+Mon Jul 31 13:24:30 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * method.c (report_type_mismatch): Don't talk about an object
+       parameter for non-methods.
+
+Sun Jul 30 13:13:02 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * class.c (finish_struct): Catch private and protected members of
+       anonymous unions here.
+       * decl2.c (finish_anon_union): And here.
+       * parse.y: Instead of here.
+
+       * errfn.c (ARGSLIST): Support passing four args.
+       * error.c (cv_as_string): New function.
+       (cp_printers): Add it.
+       * call.c (build_method_call): Report 'const' at end of pseudo-decl.
+
+       * method.c (report_type_mismatch): Deal with a bad_arg of 0.
+
+       * init.c (expand_aggr_init): Handle volatile objects, too.
+
+Sat Jul 29 13:42:03 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (struct binding_level): Keep list of incomplete decls.
+       (print_binding_level): Use list_length to count them.
+       (pushdecl): Build up the list.
+       (hack_incomplete_structures): Walk it and prune completed decls.
+
+Fri Jul 28 15:26:44 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (comp_target_types): Don't check const and volatile for
+       function types.
+       (comp_ptr_ttypes_real): Ditto.
+
+Thu Jul 27 15:40:48 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (comp_target_types): Fix.
+
+Thu Jul 27 15:10:48 1995  Mike Stump  <mrs@cygnus.com>
+
+       * cp-tree.h (unsave_expr_now, build_unsave_expr,
+       cp_expand_decl_cleanup): Declare new routines.
+       * decl.c (cp_finish_decl, store_parm_decls,
+       hack_incomplete_structures): Change all cals from
+       expand_decl_cleanup to cp_expand_decl_cleanup.
+       * gc.c (protect_value_from_gc): Ditto.
+       * expr.c (cplus_expand_expr): Handle UNSAVE_EXPRs.
+       * tree.c (unsave_expr): New routine to build an UNSAVE_EXPR.
+       (unsave_expr_now): Backend routine used by tree expander.
+       (cp_expand_decl_cleanup): Wrap second argument in an UNSAVE_EXPR to
+       work around a limitation in the backend.  The backend uses the
+       cleanups multiple times, on disjoint control flows, so we cannot
+       pass unsaved SAVE_EXPRs to the backend.
+       * tree.def (UNSAVE_EXPR): New tree code.
+       * typeck.c (c_expand_return): Move goto/return code up inside
+       conditional, as we don't always want to do this, we only want to do
+       this when we don't otherwise finish with this control flow.
+
+Thu Jul 27 10:38:43 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * parse.y (typespec): Only complain about typeof if we're not
+       getting it from a system header.
+
+Thu Jul 27 10:26:23 1995  Doug Evans  <dje@canuck.cygnus.com>
+
+       Clean up prefix attribute handling.
+       * parse.y (reserved_declspecs): Link prefix attributes with declspecs.
+       (declmods): Likewise.
+       (all rules that reference typed_declspecs and declmods): Call
+       split_specs_attrs or strip_attrs to separate declspecs and attrs.
+       (lang_extdef): Delete resetting of prefix_attributes.
+       (template_def, notype_declarator rule): Use NULL_TREE for
+       prefix_attributes.
+       (condition): Use NULL_TREE for prefix_attributes.
+       (setattrs): Deleted.
+       (nomods_initdcl0): Set prefix_attributes to NULL_TREE.
+       (component_decl): Delete resetting of prefix_attributes.
+       (component_decl_1, notype_components rule): Use NULL_TREE for
+       prefix_attributes.
+       (simple_stmt): Delete resetting of prefix_attributes.
+
+Mon Jul 24 13:37:53 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * call.c (convert_harshness): Deal with reference conversions before
+       others.  Actually do array->pointer decay.  Call comp_target_types
+       with pointer types rather than their targets.
+
+       * typeck.c (comp_target_types): Avoid assigning D const * to B *.
+
+Mon Jul 24 08:54:46 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * pt.c (to_be_restored): Move decl to global scope.
+
+Sat Jul 22 12:22:11 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (start_decl): Put back clearing of DECL_IN_AGGR_P.
+
+Fri Jul 21 17:09:02 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (grokdeclarator): Downgrade error about 'extern int A::i'
+       to pedwarn.
+
+       * pt.c (instantiate_template): Also avoid instantiation if the
+       function has already been declared to be a specialization.
+
+       * decl2.c (check_classfn): Ignore cname argument, and return the
+       matching function.
+
+       * decl.c (start_decl): Handle declarations of member functions
+       outside of the class (i.e. specialization declarations).
+
+Thu Jul 20 10:34:48 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * class.c (finish_struct): Don't mess with the type of bitfields.
+
+       * various.c: s/TYPE_POINTER_TO/build_pointer_type/.
+
+Thu Jul 20 01:43:10 1995  Mike Stump  <mrs@cygnus.com>
+
+       * init.c (expand_aggr_init): Assume LOOKUP_ONLYCONVERTING if init
+       is not a parameter list (TREE_LIST).
+       (expand_default_init): If LOOKUP_ONLYCONVERTING is set, then set
+       LOOKUP_NO_CONVERSION so that we don't allow two-level conversions,
+       but don't set it otherwise.
+
+Wed Jul 19 20:32:01 1995  Mike Stump  <mrs@cygnus.com>
+
+       * init.c (expand_default_init): Don't allow two-level conversions
+       during construction.
+
+Wed Jul 19 18:06:37 1995  Mike Stump  <mrs@cygnus.com>
+
+       * gc.c (build_headof): The type of dyncasting to a pointer to cv
+       void, should be pointer to cv void.
+
+Wed Jul 19 17:25:43 1995  Mike Stump  <mrs@cygnus.com>
+
+       * gc.c (build_dynamic_cast): Allow casting in const.
+
+Wed Jul 19 16:34:27 1995  Mike Stump  <mrs@cygnus.com>
+
+       * typeck.c (build_const_cast): If we are passed error_mark_node,
+       return it.
+
+Wed Jul 19 15:24:48 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * class.c (push_nested_class): Make sure TYPE is non-nil.
+
+       * cvt.c (type_promotes_to): Watch for error_mark_node on the
+       incoming TYPE.
+
+Wed Jul 19 13:23:12 1995  Gerald Baumgartner  <gb@alexander.cs.purdue.edu>
 
        * cp-tree.h (SIGTABLE_VT_OFF_NAME): Renamed from SIGTABLE_OFFSET_NAME.
        (SIGTABLE_VB_OFF_NAME): New macro.
@@ -58,34 +736,192 @@ Wed Jul 19 11:49:57 1995  Gerald Baumgartner  <gb@alexander.cs.purdue.edu>
        * decl.c (init_decl_processing): Align sigtable_entry_type on word
        boundaries instead of double word boundaries to save space.
 
+Tue Jul 18 16:58:37 1995  Mike Stump  <mrs@cygnus.com>
+
+       * cvt.c (cp_convert): Always call build_cplus_new for a ctor.
+
+Tue Jul 18 14:24:53 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * parse.y (opt.component_decl_list): Only forbid private/protected
+       in anonymous unions.  We need to make this know when the type is
+       defined for an object, to not give the error.
+
+Mon Jul 17 14:22:44 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * parse.y (opt.component_decl_list): Don't allow access control
+       as private or protected for union members.
+
+Sun Jul 16 14:01:00 1995  Jim Wilson  <wilson@chestnut.cygnus.com>
+
+       * lex.c (check_newline): For 'p' case, move goto skipline line to
+       before end brace for 'pragma'.
+
+Fri Jul  7 13:55:58 1995  Mike Stump  <mrs@cygnus.com>
+
+       * g++.1: Tiny updates.
+
+Fri Jul  7 13:05:20 1995  Mike Stump  <mrs@cygnus.com>
+
+       * decl.c (cp_finish_decl): Only destruct local static variables if
+       they are constructed, and only construct the first time control
+       passes completely through its declaration (if not initialized with a
+       constant-expression).
+       (expand_static_init): Ditto.
+
+Wed Jul  5 14:05:04 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * typeck.c (comptypes, case OFFSET_REF): If either offset basetype
+       is a TEMPLATE_TYPE_PARM, give a match.
+
+Mon Jul  3 15:17:20 1995  Steve Chamberlain  <sac@slash.cygnus.com>
+
+       * g++.c (sys/file.h): Remove change of Jun 28.
+
+Fri Jun 30 15:42:57 1995  Mike Stump  <mrs@cygnus.com>
+
+       * method.c (build_overload_value): Handle encoding of null pointer
+       constants (or any pointer with a constant numeric value) for
+       templates.
+
 Fri Jun 30 13:45:51 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
 
        * call.c (convert_harshness): Add QUAL_CODE when we're faced with
        const vs non-const for void conversions.
 
+Fri Jun 30 10:19:52 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_start_all_catch): Fix problem with finding an
+       outer nested try block when there is no code to separate it from an
+       inner try block.
+
+Fri Jun 30 02:22:26 1995  Mike Stump  <mrs@cygnus.com>
+
+       * search.c (dfs_pushdecls): Consume 2 or 3 orders of magnitude less
+       memory please when virtual bases are used.
+
+Thu Jun 29 19:03:47 1995  Mike Stump  <mrs@cygnus.com>
+
+       * class.c (build_vbase_path): Avoid testing things that cannot be
+       null to see if they are null.
+       * cvt.c (convert_pointer_to_vbase): Remove code that doesn't work.
+       * decl.c (finish_function): Pass a type into the new
+       convert_pointer_to_vbase instead of a binfo.
+       * search.c (convert_pointer_to_vbase): Rewritten to use get_vbase
+       and convert_pointer_to_real.
+       (expand_indirect_vtbls_init): Use convert_pointer_to_vbase instead
+       of the more cryptic call to get_vbase.
+
 Thu Jun 29 09:35:05 1995  Mike Stump  <mrs@cygnus.com>
 
        * decl.c (BOOL_TYPE_SIZE): Fix broken SLOW_BYTE_ACCESS check.
 
+Thu Jun 29 03:43:55 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * pt.c (instantiate_template): Don't strip 'this' twice.
+
+       * pt.c (coerce_template_parms): Allow null pointer constants.
+
+       * decl.c (revert_static_member_fn): But only if DECL_ARGUMENTS is
+       set.
+
+Wed Jun 28 23:34:58 1995  Steve Chamberlain  <sac@slash.cygnus.com>
+
+       * g++.c (pfatal_with_name):  Use my_strerror to get error
+       string.
+       (sys/file.h): Include if HAVE_FILE_H defined.
+
+Wed Jun 28 18:39:03 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (revert_static_member_fn): Also remove 'this' from
+       DECL_ARGUMENTS.
+       * decl2.c (check_classfn): Don't revert this function until we get a
+       match.
+
+Wed Jun 28 14:07:27 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * parse.y (component_decl): Clear PREFIX_ATTRIBUTES here.
+
+Wed Jun 28 11:05:13 1995  Mike Stump  <mrs@cygnus.com>
+
+       * decl2.c (finish_file): Handle global vector news.
+       * init.c (build_new): Encode vector news so that later we will know
+       how many elements there are.
+
 Mon Jun 26 13:38:06 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
        * expr.c (cplus_expand_expr): Don't mess with temp slots.
 
+       * decl2.c (warn_if_unknown_interface): Don't crash if tinst_for_decl
+       returns null.
+
+       * decl2.c (check_classfn): Use revert_static_member_fn.
+       * decl.c (revert_static_member_fn): Diagnose static member functions
+       declared const or volatile.
+
+       * decl2.c (grokfield): Check for missing default args here, too.
+       (check_default_args): Function to do the checking.
+       * decl.c (pushdecl): Use it.
+
+       * decl.c (pushdecl): Don't warn about shadowing a member of `this'
+       if there is no `this'.
+
+Sun Jun 25 11:34:25 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * call.c (build_method_call): Downgrade 'called before definition'
+       to a warning, as it ought to go away after Monterey.
+
+Sat Jun 24 14:18:42 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * pt.c (coerce_template_parms): Don't do extra checking on pointer
+       to member arguments.
+
+       * class.c (finish_struct): const and reference members don't prevent
+       a class from being an aggregate.
+
+       * class.c (finish_struct): Signatures are always aggregates.
+
 Fri Jun 23 17:20:29 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
-        * pt.c (tsubst): Handle PROMOTE_PROTOTYPES.
+       * decl2.c (check_classfn): Improve error message.
+
+       * pt.c (tsubst): Handle PROMOTE_PROTOTYPES.
 
 Thu Jun 22 01:50:42 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
-       * pt.c (tsubst, PARM_TYPE): Propagate DECL_ARTIFICIAL.
+       * typeck.c (comptypes): Don't ignore method quals.
 
-Thu Jun 22 01:50:42 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+       * class.c (finish_struct): Non-abstract virtuals are always USED.
+
+       * decl.c (build_ptrmemfunc_type): The underlying union type isn't
+       IS_AGGR_TYPE, either.
+       * class.c (finish_struct): Use CLASSTYPE_NON_AGGREGATE instead.
+       * cp-tree.h: Ditto.
+
+       * cp-tree.h (lang_type): Add aggregate.
+       (CLASSTYPE_AGGREGATE): New macro.
+       (TYPE_NON_AGGREGATE_CLASS): Ditto.
+       * class.c (finish_struct): Determine whether a class is an
+       aggregate.
+       * decl.c (cp_finish_decl): Check TYPE_NON_AGGREGATE_CLASS instead of
+       TYPE_NEEDS_CONSTRUCTING.
+       * typeck2.c (digest_init): Check TYPE_NON_AGGREGATE_CLASS for
+       subobjects, too.
+
+       * pt.c (tsubst, PARM_TYPE): Propagate DECL_ARTIFICIAL.
 
        * decl.c (start_function): For pre-parsed functions, layout all of
        the parm decls again.
        (grokvardecl): TREE_PUBLIC depends on DECL_THIS_EXTERN, not
        DECL_EXTERNAL.
 
+       * pt.c (coerce_template_parms): Improve checking for invalid
+       template parms.
+
+Wed Jun 21 12:01:16 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * decl.c (grokdeclarator): Forbid declaration of a static member
+       with the same name as its enclosing class.
+
 Mon Jun 19 10:28:14 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
        * decl.c (finish_function): Clear current_class_decl.
@@ -120,7 +956,7 @@ Thu Jun 15 15:00:41 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        * decl.c (define_function): Don't set DECL_INTERFACE_KNOWN.
 
        * parse.y: Call cplus_decl_attributes with prefix_attributes where
-        appropriate.
+       appropriate.
 
 Wed Jun 14 19:24:49 1995  Mike Stump  <mrs@cygnus.com>
 
@@ -132,7 +968,7 @@ Wed Jun 14 19:24:49 1995  Mike Stump  <mrs@cygnus.com>
 Mon Jun 12 17:50:30 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
        * pt.c (instantiate_class_template): Add the new instantiation to
-        template_classes.
+       template_classes.
        (do_pending_expansions): Call instantiate_member_templates on all of
        the classes in template_classes.
 
@@ -300,7 +1136,7 @@ Fri Jun  2 11:05:58 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        * class.c (popclass): Don't mess with current_class_decl,
        current_vtable_decl, or C_C_D.
 
-on May 29 12:45:10 1995  Paul Eggert  <eggert@twinsun.com>
+Mon May 29 12:45:10 1995  Paul Eggert  <eggert@twinsun.com>
 
        * Make-lang.in (c++.mostlyclean): Remove $(DEMANGLER_PROG).
 
@@ -491,7 +1327,7 @@ Mon May 15 12:47:56 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        affects reference conversion.
 
        * init.c (emit_base_init): Build up an RTL_EXPR and add it to
-        rtl_expr_chain.
+       rtl_expr_chain.
        * decl.c, decl2.c: s/base_init_insns/base_init_expr/.
 
 Tue May 16 07:06:28 1995  Paul Eggert  <eggert@twinsun.com>
@@ -597,7 +1433,7 @@ Thu Apr 27 16:56:24 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        folding.
 
        * decl.c (grokdeclarator): Prohibit pointers to void or reference
-        members.
+       members.
 
 Thu Apr 27 09:49:07 1995  Mike Stump  <mrs@cygnus.com>
 
@@ -1093,7 +1929,7 @@ Tue Mar 28 14:16:35 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        if the types are the same.
 
        * decl.c (start_function): Handle extern inlines more like C++ says
-        we should.
+       we should.
 
        * init.c (build_member_call): Hand constructor calls off to
        build_functional_cast.
@@ -1331,7 +2167,7 @@ Wed Mar 15 13:56:16 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        (mark_vtable_entries): Call assemble_external on the vtable entries.
 
        * class.c (finish_struct): Set the vtable's size to NULL_TREE before
-        calling layout_decl, so that it gets updated properly.
+       calling layout_decl, so that it gets updated properly.
 
        Finally re-enable dynamic synthesis.  This time it works.
        * method.c (synthesize_method): Pass decl_function_context (fndecl)
@@ -1779,7 +2615,7 @@ Thu Feb 16 03:28:49 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 Wed Feb 15 15:38:12 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
        * class.c (grow_method): Update method_vec after growing the class
-        obstack.
+       obstack.
 
 Wed Feb 15 13:42:59 1995  Mike Stump  <mrs@cygnus.com>
 
@@ -1858,7 +2694,7 @@ Sun Feb 12 03:57:06 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 Fri Feb 10 16:18:52 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
        * typeck.c (build_c_cast): Use non_lvalue to tack something on
-        where necessary.
+       where necessary.
 
        * decl.c (auto_function): Now a function.
        * except.c (init_exception_processing): terminate, unexpected,
@@ -1894,7 +2730,7 @@ Fri Feb 10 00:52:04 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        * tree.c (real_lvalue_p): Like lvalue_p, but class temps aren't
        considered lvalues.
        * cvt.c (convert_to_reference): Use real_lvalue_p instead of
-        lvalue_p.
+       lvalue_p.
 
        * cvt.c (build_type_conversion_1): Don't call convert on aggregate
        types.
@@ -2040,7 +2876,7 @@ Sun Feb  5 02:50:45 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 Fri Feb  3 14:58:58 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
        * decl.c (grok_reference_init): Convert initializer from
-        reference.
+       reference.
        * typeck.c (convert_for_initialization): Ditto.
 
        * decl.c (duplicate_decls): Propagate DECL_NESTED_TYPENAME.
@@ -2228,12 +3064,12 @@ Fri Jan 20 01:17:59 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 Thu Jan 19 15:43:11 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
        * call.c (build_method_call): Don't mess with 'this' before calling
-        compute_conversion_costs.
+       compute_conversion_costs.
 
 Wed Jan 18 15:40:55 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
        * search.c (get_matching_virtual): Give line number for previous
-        declaration.
+       declaration.
 
        * call.c (convert_harshness): Handle conversions to references
        better.
@@ -2262,8 +3098,8 @@ Tue Jan 17 19:56:15 1995  Mike Stump  <mrs@cygnus.com>
 
 Wed Jan 17 18:20:57 1994  Fergus Henderson <fjh@munta.cs.mu.oz.au>
 
-        * cp-tree.h : Make if (x=0) warn with wall
-        * parse.y : Make if (x=0) warn with wall
+       * cp-tree.h : Make if (x=0) warn with wall
+       * parse.y : Make if (x=0) warn with wall
 
 Tue Jan 17 14:12:00 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
@@ -2274,7 +3110,7 @@ Tue Jan 17 14:12:00 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        types are the same.
 
        * cvt.c (cp_convert): Just call truthvalue_conversion to convert to
-        bool.
+       bool.
 
 Mon Jan 16 13:28:48 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
@@ -2437,7 +3273,7 @@ Tue Jan 10 18:07:51 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        * spew.c (yylex): Also use DECL_NESTED_TYPENAME if got_object is set.
 
        * parse.y (primary): Unset got_object after all rules that use the
-        'object' nonterminal.
+       'object' nonterminal.
        (object): Set got_object.
 
        * lex.h: Declare got_object.
@@ -2509,7 +3345,7 @@ Mon Jan  9 03:44:33 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        _DEFN.
 
        * decl.c (pushdecl): Don't install an artificial TYPE_DECL in
-        IDENTIFIER_LOCAL_VALUE if we already have a decl with that name.
+       IDENTIFIER_LOCAL_VALUE if we already have a decl with that name.
 
        * typeck.c (convert_for_assignment): Converting pointers to bool
        does not need a cast.
@@ -2539,7 +3375,7 @@ Fri Jan  6 14:10:57 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        (convert_harshness): Non-lvalues do not convert to reference types.
 
        * class.c (finish_struct_methods): Still set
-        TYPE_HAS_{INT,REAL}_CONVERSION.
+       TYPE_HAS_{INT,REAL}_CONVERSION.
 
        * call.c (can_convert): Don't use aggregate initialization.
 
@@ -2574,7 +3410,7 @@ Wed Jan  4 16:44:19 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        method vector.
        (finish_struct_methods): Use it.  Put all type conversion operators
        right after the constructors.  Perhaps we should sort the methods
-        alphabetically?
+       alphabetically?
 
 Mon Jan  2 14:42:58 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
@@ -2844,7 +3680,7 @@ Fri Dec  2 18:32:41 1994  Mike Stump  <mrs@cygnus.com>
 Fri Dec  2 17:04:27 1994  Mike Stump  <mrs@cygnus.com>
 
        * gc.c (build_dynamic_cast): Change interface to libg++, ensure that
-        the return type is the right type, and make references work.
+       the return type is the right type, and make references work.
 
 Fri Dec  2 16:36:43 1994  Jason Merrill  <jason@phydeaux.cygnus.com>
 
index 765e8fe..2dd6cff 100644 (file)
@@ -156,6 +156,55 @@ convert_harshness (type, parmtype, parm)
   if (coder == ERROR_MARK)
     return EVIL_RETURN (h);
 
+  if (codel == REFERENCE_TYPE)
+    {
+      tree ttl, ttr;
+      int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype);
+      int volatilep = (parm ? TREE_THIS_VOLATILE (parm)
+                      : TYPE_VOLATILE (parmtype));
+      register tree intype = TYPE_MAIN_VARIANT (parmtype);
+      register enum tree_code form = TREE_CODE (intype);
+      int penalty = 0;
+
+      ttl = TREE_TYPE (type);
+
+      /* Only allow const reference binding if we were given a parm to deal
+         with, since it isn't really a conversion.  This is a hack to
+         prevent build_type_conversion from finding this conversion, but
+         still allow overloading to find it.  */
+      if (! lvalue && ! (parm && TYPE_READONLY (ttl)))
+       return EVIL_RETURN (h);
+
+      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
+        little, so a non-const reference is preferred over this one.  */
+      penalty = ((TYPE_READONLY (ttl) > constp)
+                + (TYPE_VOLATILE (ttl) > volatilep));
+
+      ttl = TYPE_MAIN_VARIANT (ttl);
+
+      if (form == OFFSET_TYPE)
+       {
+         intype = TREE_TYPE (intype);
+         form = TREE_CODE (intype);
+       }
+
+      ttr = intype;
+
+      /* Maybe handle conversion to base here?  */
+
+      h = convert_harshness (ttl, ttr, NULL_TREE);
+      if (penalty && h.code == 0)
+       {
+         h.code = QUAL_CODE;
+         h.int_penalty = penalty;
+       }
+      return h;
+    }
+
   if (codel == POINTER_TYPE && fntype_p (parmtype))
     {
       tree p1, p2;
@@ -198,7 +247,7 @@ convert_harshness (type, parmtype, parm)
 
       /* We allow the default conversion between function type
         and pointer-to-function type for free.  */
-      if (type == parmtype)
+      if (comptypes (type, parmtype, 1))
        return h;
 
       if (pedantic)
@@ -421,10 +470,21 @@ convert_harshness (type, parmtype, parm)
     }
 
   /* Convert arrays which have not previously been converted.  */
+#if 0
   if (codel == ARRAY_TYPE)
     codel = POINTER_TYPE;
+#endif
   if (coder == ARRAY_TYPE)
-    coder = POINTER_TYPE;
+    {
+      coder = POINTER_TYPE;
+      if (parm)
+       {
+         parm = decay_conversion (parm);
+         parmtype = TREE_TYPE (parm);
+       }
+      else
+       parmtype = build_pointer_type (TREE_TYPE (parmtype));
+    }
 
   /* Conversions among pointers */
   if (codel == POINTER_TYPE && coder == POINTER_TYPE)
@@ -462,7 +522,7 @@ convert_harshness (type, parmtype, parm)
              ttr = unsigned_type (ttr);
              penalty = 10;
            }
-         if (comp_target_types (ttl, ttr, 0) <= 0)
+         if (comp_target_types (type, parmtype, 1) <= 0)
            return EVIL_RETURN (h);
        }
 #else
@@ -559,54 +619,6 @@ convert_harshness (type, parmtype, parm)
       && IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype)))
     return ZERO_RETURN (h);
 
-  if (codel == REFERENCE_TYPE)
-    {
-      tree ttl, ttr;
-      int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype);
-      int volatilep = (parm ? TREE_THIS_VOLATILE (parm)
-                      : TYPE_VOLATILE (parmtype));
-      register tree intype = TYPE_MAIN_VARIANT (parmtype);
-      register enum tree_code form = TREE_CODE (intype);
-      int penalty = 0;
-
-      ttl = TREE_TYPE (type);
-
-      /* Only allow const reference binding if we were given a parm to deal
-         with, since it isn't really a conversion.  This is a hack to
-         prevent build_type_conversion from finding this conversion, but
-         still allow overloading to find it.  */
-      if (! lvalue && ! (parm && TYPE_READONLY (ttl)))
-       return EVIL_RETURN (h);
-
-      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
-        little, so a non-const reference is preferred over this one.  */
-      penalty = ((TYPE_READONLY (ttl) > constp)
-                + (TYPE_VOLATILE (ttl) > volatilep));
-
-      ttl = TYPE_MAIN_VARIANT (ttl);
-
-      if (form == OFFSET_TYPE)
-       {
-         intype = TREE_TYPE (intype);
-         form = TREE_CODE (intype);
-       }
-
-      ttr = intype;
-
-      /* Maybe handle conversion to base here?  */
-
-      h = convert_harshness (ttl, ttr, NULL_TREE);
-      if (penalty && h.code == 0)
-       {
-         h.code = QUAL_CODE;
-         h.int_penalty = penalty;
-       }
-      return h;
-    }
   if (codel == RECORD_TYPE && coder == RECORD_TYPE)
     {
       int b_or_d = get_base_distance (type, parmtype, 0, 0);
@@ -625,6 +637,9 @@ convert_harshness (type, parmtype, parm)
   return EVIL_RETURN (h);
 }
 
+/* A clone of build_type_conversion for checking user-defined conversions in
+   overload resolution.  */
+
 int
 user_harshness (type, parmtype, parm)
      register tree type, parmtype;
@@ -1766,7 +1781,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
        {
          basetype = SIGNATURE_TYPE (basetype);
          instance_ptr = build_optr_ref (instance);
-         instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr);
+         instance_ptr = convert (build_pointer_type (basetype), instance_ptr);
          basetype_path = TYPE_BINFO (basetype);
        }
       else
@@ -1788,7 +1803,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
         within the scope of this function.  */
       if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))
        need_vtbl = maybe_needed;
-      instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (basetype), instance);
+      instance_ptr = build1 (ADDR_EXPR, build_pointer_type (basetype), instance);
     }
   else
     {
@@ -1883,7 +1898,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
            basetype = inst_ptr_basetype;
          else
            {
-             instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr);
+             instance_ptr = convert (build_pointer_type (basetype), instance_ptr);
              if (instance_ptr == error_mark_node)
                return error_mark_node;
            }
@@ -1999,40 +2014,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
          parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);
        }
 
-      if (flag_this_is_variable > 0)
-       {
-         constp = 0;
-         volatilep = 0;
-         instance_ptr = build_int_2 (0, 0);
-         TREE_TYPE (instance_ptr) = TYPE_POINTER_TO (basetype);
-         parms = tree_cons (NULL_TREE, instance_ptr, parms);
-       }
-      else
-       {
-         constp = 0;
-         volatilep = 0;
-         instance_ptr = build_new (NULL_TREE, basetype, void_type_node, 0);
-         if (instance_ptr == error_mark_node)
-           return error_mark_node;
-         instance_ptr = save_expr (instance_ptr);
-         TREE_CALLS_NEW (instance_ptr) = 1;
-         instance = build_indirect_ref (instance_ptr, NULL_PTR);
-
-#if 0
-         /* This breaks initialization of a reference from a new
-             expression of a different type.  And it doesn't appear to
-             serve its original purpose any more, either.  jason 10/12/94 */
-         /* If it's a default argument initialized from a ctor, what we get
-            from instance_ptr will match the arglist for the FUNCTION_DECL
-            of the constructor.  */
-         if (parms && TREE_CODE (TREE_VALUE (parms)) == CALL_EXPR
-             && TREE_OPERAND (TREE_VALUE (parms), 1)
-             && TREE_CALLS_NEW (TREE_VALUE (TREE_OPERAND (TREE_VALUE (parms), 1))))
-           parms = build_tree_list (NULL_TREE, instance_ptr);
-         else
-#endif
-           parms = tree_cons (NULL_TREE, instance_ptr, parms);
-       }
+      constp = 0;
+      volatilep = 0;
+      instance_ptr = build_int_2 (0, 0);
+      TREE_TYPE (instance_ptr) = build_pointer_type (basetype);
+      parms = tree_cons (NULL_TREE, instance_ptr, parms);
     }
 
   parmtypes = tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes);
@@ -2385,9 +2371,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
              else if (ever_seen > 1)
                {
                  TREE_CHAIN (last) = void_list_node;
-                 cp_error ("no matching function for call to `%T::%D (%A)'",
-                           TREE_TYPE (TREE_TYPE (instance_ptr)),
-                           name, TREE_CHAIN (parmtypes));
+                 cp_error ("no matching function for call to `%T::%D (%A)%V'",
+                           TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (instance_ptr))),
+                           name, TREE_CHAIN (parmtypes),
+                           TREE_TYPE (TREE_TYPE (instance_ptr)));
                  TREE_CHAIN (last) = NULL_TREE;
                  print_candidates (found_fns);
                }
@@ -2486,7 +2473,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
 
   if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function)
        && ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function))
-    cp_pedwarn ("inline function `%#D' called before definition", function);
+    cp_warning ("inline function `%#D' called before definition", function);
 
   fntype = TREE_TYPE (function);
   if (TREE_CODE (fntype) == POINTER_TYPE)
index 9a373c3..e289304 100644 (file)
@@ -188,6 +188,9 @@ build_vbase_path (code, type, expr, path, alias_this)
   tree basetype;
   tree offset = integer_zero_node;
 
+  if (nonnull == 0 && (alias_this && flag_this_is_variable <= 0))
+    nonnull = 1;
+
   /* We need additional logic to convert back to the unconverted type
      (the static type of the complete object), and then convert back
      to the type we want.  Until that is done, or until we can
@@ -244,8 +247,8 @@ build_vbase_path (code, type, expr, path, alias_this)
                          || !flag_assume_nonnull_objects)
                      && null_expr == NULL_TREE)
                    {
-                     null_expr = build1 (NOP_EXPR, TYPE_POINTER_TO (last_virtual), integer_zero_node);
-                     expr = build (COND_EXPR, TYPE_POINTER_TO (last_virtual),
+                     null_expr = build1 (NOP_EXPR, build_pointer_type (last_virtual), integer_zero_node);
+                     expr = build (COND_EXPR, build_pointer_type (last_virtual),
                                    build (EQ_EXPR, boolean_type_node, expr,
                                           integer_zero_node),
                                    null_expr, nonnull_expr);
@@ -286,12 +289,9 @@ build_vbase_path (code, type, expr, path, alias_this)
   if (changed)
     {
       tree intype = TREE_TYPE (TREE_TYPE (expr));
-      if (TYPE_MAIN_VARIANT (intype) == BINFO_TYPE (last))
-       basetype = intype;
-      else
+      if (TYPE_MAIN_VARIANT (intype) != BINFO_TYPE (last))
        {
          tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (intype), 0);
-         basetype = last;
          offset = BINFO_OFFSET (binfo);
        }
     }
@@ -319,7 +319,7 @@ build_vbase_path (code, type, expr, path, alias_this)
         case of constructors need we worry, and in those cases,
         it will be zero, or initialized to some valid value to
         which we may add.  */
-      if (nonnull == 0 && (alias_this == 0 || flag_this_is_variable > 0))
+      if (nonnull == 0)
        {
          if (null_expr)
            TREE_TYPE (null_expr) = type;
@@ -641,6 +641,36 @@ build_type_pathname (format, parent, type)
   return id;
 }
 
+/* Update the rtti info for this class.  */
+static void
+set_rtti_entry (virtuals, offset, type)
+     tree virtuals, offset, type;
+{
+  if (! flag_vtable_thunks)
+    TREE_VALUE (virtuals)
+      = build_vtable_entry (offset,
+                           (flag_rtti
+                            ? build_t_desc (type, 0)
+                            : integer_zero_node));
+  else
+    {
+      tree vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
+      TREE_CONSTANT (vfn) = 1;
+
+      TREE_VALUE (virtuals)
+       = build_vtable_entry (integer_zero_node, vfn);
+      /* The second slot is for the tdesc pointer when thunks are used.  */
+      vfn = flag_rtti
+            ? build_t_desc (type, 0)
+            : integer_zero_node;
+      vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, vfn);
+      TREE_CONSTANT (vfn) = 1;
+
+      TREE_VALUE (TREE_CHAIN (virtuals))
+       = build_vtable_entry (integer_zero_node, vfn);
+    }
+}
+
 /* Give TYPE a new virtual function table which is initialized
    with a skeleton-copy of its original initialization.  The only
    entry that changes is the `delta' entry, so we can really
@@ -684,11 +714,9 @@ prepare_fresh_vtable (binfo, for_type)
   else
     offset = BINFO_OFFSET (binfo);
 
-  /* Install the value for `headof' if that's what we're doing.  */
-  if (flag_rtti)
-    TREE_VALUE (BINFO_VIRTUALS (binfo))
-      = build_vtable_entry (size_binop (MINUS_EXPR, integer_zero_node, offset),
-                           build_t_desc (for_type, 0));
+  set_rtti_entry (BINFO_VIRTUALS (binfo),
+                 size_binop (MINUS_EXPR, integer_zero_node, offset),
+                 for_type);
 
 #ifdef GATHER_STATISTICS
   n_vtables += 1;
@@ -713,19 +741,19 @@ static tree
 get_vtable_entry (virtuals, base_fndecl)
      tree virtuals, base_fndecl;
 {
-  unsigned HOST_WIDE_INT i = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD
+  unsigned HOST_WIDE_INT n = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD
           ? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))
              & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1))
           : TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)));
 
 #ifdef GATHER_STATISTICS
-  n_vtable_searches += i;
+  n_vtable_searches += n;
 #endif
 
-  while (i > 0 && virtuals)
+  while (n > 0 && virtuals)
     {
+      --n;
       virtuals = TREE_CHAIN (virtuals);
-      i -= 1;
     }
   return virtuals;
 }
@@ -759,14 +787,14 @@ modify_vtable_entry (old_entry_in_list, new_entry, fndecl)
 /* Access the virtual function table entry i.  VIRTUALS is the virtual
    function table's initializer.  */
 static tree
-get_vtable_entry_n (virtuals, i)
+get_vtable_entry_n (virtuals, n)
      tree virtuals;
-     unsigned HOST_WIDE_INT i;
+     unsigned HOST_WIDE_INT n;
 {
-  while (i > 0)
+  while (n > 0)
     {
+      --n;
       virtuals = TREE_CHAIN (virtuals);
-      i -= 1;
     }
   return virtuals;
 }
@@ -811,15 +839,20 @@ add_virtual_function (pending_virtuals, has_virtual, fndecl, t)
        {
          /* CLASSTYPE_RTTI is only used as a Boolean (NULL or not). */
          CLASSTYPE_RTTI (t) = integer_one_node;
-#if 0
-         *has_virtual = 1;
-#endif
         }
 
+      /* If we are using thunks, use two slots at the front, one
+        for the offset pointer, one for the tdesc pointer.  */
+      if (*has_virtual == 0 && flag_vtable_thunks)
+       {
+         *has_virtual = 1;
+       }
+
       /* Build a new INT_CST for this DECL_VINDEX.  */
       {
        static tree index_table[256];
        tree index;
+       /* We skip a slot for the offset/tdesc entry.  */
        int i = ++(*has_virtual);
 
        if (i >= 256 || index_table[i] == 0)
@@ -2225,6 +2258,30 @@ get_class_offset (context, t, binfo, fndecl)
   return offset;
 }
 
+/* Skip RTTI information at the front of the virtual list.  */
+unsigned HOST_WIDE_INT
+skip_rtti_stuff (virtuals)
+     tree *virtuals;
+{
+  int n;
+
+  n = 0;
+  if (*virtuals)
+    {
+      /* We always reserve a slot for the offset/tdesc entry.  */
+      ++n;
+      *virtuals = TREE_CHAIN (*virtuals);
+    }
+  if (flag_vtable_thunks && *virtuals)
+    {
+      /* The second slot is reserved for the tdesc pointer when thunks
+         are used.  */
+      ++n;
+      *virtuals = TREE_CHAIN (*virtuals);
+    }
+  return n;
+}
+
 static void
 modify_one_vtable (binfo, t, fndecl, pfn)
      tree binfo, t, fndecl, pfn;
@@ -2247,12 +2304,11 @@ modify_one_vtable (binfo, t, fndecl, pfn)
            prepare_fresh_vtable (binfo, t);
        }
     }
-  if (fndecl == NULL_TREE) return;
+  if (fndecl == NULL_TREE)
+    return;
+
+  n = skip_rtti_stuff (&virtuals);
 
-  /* Skip RTTI fake object. */
-  n = 1;
-  if (virtuals)
-    virtuals = TREE_CHAIN (virtuals);
   while (virtuals)
     {
       tree current_fndecl = TREE_VALUE (virtuals);
@@ -2346,10 +2402,8 @@ fixup_vtable_deltas1 (binfo, t)
   tree virtuals = BINFO_VIRTUALS (binfo);
   unsigned HOST_WIDE_INT n;
   
-  /* Skip RTTI fake object. */
-  n = 1;
-  if (virtuals)
-    virtuals = TREE_CHAIN (virtuals);
+  n = skip_rtti_stuff (&virtuals);
+
   while (virtuals)
     {
       tree fndecl = TREE_VALUE (virtuals);
@@ -2517,9 +2571,8 @@ override_one_vtable (binfo, old, t)
   if (BINFO_NEW_VTABLE_MARKED (binfo))
     choose = NEITHER;
 
-  /* Skip RTTI fake object. */
-  virtuals = TREE_CHAIN (virtuals);
-  old_virtuals = TREE_CHAIN (old_virtuals);
+  skip_rtti_stuff (&virtuals);
+  skip_rtti_stuff (&old_virtuals);
 
   while (virtuals)
     {
@@ -2640,6 +2693,8 @@ merge_overrides (binfo, old, do_self, t)
     }
 }
 
+extern int interface_only, interface_unknown;
+
 /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
    (or C++ class declaration).
 
@@ -2700,22 +2755,19 @@ merge_overrides (binfo, old, do_self, t)
    or otherwise in a type-consistent manner.  */
 
 tree
-finish_struct (t, list_of_fieldlists, warn_anon)
+finish_struct_1 (t, warn_anon)
      tree t;
-     tree list_of_fieldlists;
      int warn_anon;
 {
-  extern int interface_only, interface_unknown;
-
   int old;
   int round_up_size = 1;
 
+  tree name = TYPE_IDENTIFIER (t);
   enum tree_code code = TREE_CODE (t);
-  register tree x, last_x, method_vec;
+  tree fields = TYPE_FIELDS (t);
+  tree fn_fields = CLASSTYPE_METHODS (t);
+  tree x, last_x, method_vec;
   int needs_virtual_dtor;
-  tree name = TYPE_NAME (t), fields, fn_fields, *tail;
-  tree *tail_user_methods = &CLASSTYPE_METHODS (t);
-  enum access_type access;
   int all_virtual;
   int has_virtual;
   int max_has_virtual;
@@ -2740,37 +2792,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
   int nonprivate_method = 0;
   tree t_binfo = TYPE_BINFO (t);
   tree access_decls = NULL_TREE;
+  int aggregate = 1;
 
-  if (TREE_CODE (name) == TYPE_DECL)
-    {
-#if 0                          /* Maybe later.  -jason  */
-      struct tinst_level *til = tinst_for_decl();
-
-      if (til)
-       {
-         DECL_SOURCE_FILE (name) = til->file;
-         if (DECL_SOURCE_LINE (name))
-           DECL_SOURCE_LINE (name) = til->line;
-       }
-      else
-#endif
-       {
-         extern int lineno;
-         
-         DECL_SOURCE_FILE (name) = input_filename;
-         /* For TYPE_DECL that are not typedefs (those marked with a line
-            number of zero, we don't want to mark them as real typedefs.
-            If this fails one needs to make sure real typedefs have a
-            previous line number, even if it is wrong, that way the below
-            will fill in the right line number.  (mrs) */
-         if (DECL_SOURCE_LINE (name))
-           DECL_SOURCE_LINE (name) = lineno;
-         CLASSTYPE_SOURCE_LINE (t) = lineno;
-       }
-      name = DECL_NAME (name);
-    }
-
-  if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (name))
+  if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
     pedwarn ("anonymous class type not used to declare any objects");
 
   if (TYPE_SIZE (t))
@@ -2789,10 +2813,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
               dont_allow_type_definitions);
     }
 
-  /* Append the fields we need for constructing signature tables.  */
-  if (IS_SIGNATURE (t))
-    append_signature_fields (list_of_fieldlists);
-
   GNU_xref_decl (current_function_decl, t);
 
   /* If this type was previously laid out as a forward reference,
@@ -2838,8 +2858,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
 
       /* If using multiple inheritance, this may cause variants of our
         basetypes to be used (instead of their canonical forms).  */
-      fields = layout_basetypes (t, BINFO_BASETYPES (t_binfo));
-      last_x = tree_last (fields);
+      tree vf = layout_basetypes (t, BINFO_BASETYPES (t_binfo));
+      last_x = tree_last (vf);
+      fields = chainon (vf, fields);
 
       first_vfn_base_index = finish_base_struct (t, &base_info, t_binfo);
       /* Remember where we got our vfield from */
@@ -2856,6 +2877,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
       no_const_asn_ref = base_info.no_const_asn_ref;
       needs_virtual_dtor = base_info.needs_virtual_dtor;
       n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo));
+      aggregate = 0;
     }
   else
     {
@@ -2864,7 +2886,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
       max_has_virtual = has_virtual;
       vfield = NULL_TREE;
       vfields = NULL_TREE;
-      fields = NULL_TREE;
       last_x = NULL_TREE;
       cant_have_default_ctor = 0;
       cant_have_const_ctor = 0;
@@ -2892,10 +2913,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
   CLASSTYPE_VFIELDS (t) = vfields;
   CLASSTYPE_VFIELD (t) = vfield;
 
-  tail = &fn_fields;
-  if (last_x && list_of_fieldlists)
-    TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
-
   if (IS_SIGNATURE (t))
     all_virtual = 0;
   else if (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (t))
@@ -2903,426 +2920,359 @@ finish_struct (t, list_of_fieldlists, warn_anon)
   else
     all_virtual = 0;
 
-  /* For signatures, we made all methods `public' in the parser and
-     reported an error if a access specifier was used.  */
-  if (CLASSTYPE_DECLARED_CLASS (t) == 0)
+  for (x = CLASSTYPE_METHODS (t); x; x = TREE_CHAIN (x))
     {
-      nonprivate_method = 1;
-      if (list_of_fieldlists
-         && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default)
-       TREE_PURPOSE (list_of_fieldlists) = (tree)access_public;
-    }
-  else if (list_of_fieldlists
-          && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default)
-    TREE_PURPOSE (list_of_fieldlists) = (tree)access_private;
+      GNU_xref_member (current_class_name, x);
 
-  while (list_of_fieldlists)
-    {
-      access = (enum access_type)TREE_PURPOSE (list_of_fieldlists);
+      nonprivate_method |= ! TREE_PRIVATE (x);
 
-      for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x))
-       {
-         TREE_PRIVATE (x) = access == access_private;
-         TREE_PROTECTED (x) = access == access_protected;
-         GNU_xref_member (current_class_name, x);
-
-          if (TREE_CODE (x) == TYPE_DECL)
-            {
-             /* Make sure we set this up.  In find_scoped_type, it explicitly
-                looks for a TYPE_DECL in the TYPE_FIELDS list.  If we don't
-                do this here, we'll miss including this TYPE_DECL in the
-                list.  */
-             if (! fields)
-               fields = x;
-             last_x = x;
-             continue;
-           }
+      /* If this was an evil function, don't keep it in class.  */
+      if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
+       continue;
 
-         /* Check for inconsistent use of this name in the class body.
-             Enums, types and static vars have already been checked.  */
-         if (TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL)
-           {
-             tree name = DECL_NAME (x);
-             tree icv;
+      DECL_CLASS_CONTEXT (x) = t;
 
-             /* Don't get confused by access decls.  */
-             if (name && TREE_CODE (name) == IDENTIFIER_NODE)
-               icv = IDENTIFIER_CLASS_VALUE (name);
-             else
-               icv = NULL_TREE;
+      /* Do both of these, even though they're in the same union;
+        if the insn `r' member and the size `i' member are
+        different sizes, as on the alpha, the larger of the two
+        will end up with garbage in it.  */
+      DECL_SAVED_INSNS (x) = NULL_RTX;
+      DECL_FIELD_SIZE (x) = 0;
 
-             if (icv
-                 /* Don't complain about constructors.  */
-                 && name != constructor_name (current_class_type)
-                 /* Or inherited names.  */
-                 && id_in_current_class (name)
-                 /* Or shadowed tags.  */
-                 && !(TREE_CODE (icv) == TYPE_DECL
-                      && DECL_CONTEXT (icv) == t))
-               {
-                 cp_error_at ("declaration of identifier `%D' as `%+#D'",
-                              name, x);
-                 cp_error_at ("conflicts with other use in class as `%#D'",
-                              icv);
-               }
-           }
-
-         if (TREE_CODE (x) == FUNCTION_DECL)
-           {
-             nonprivate_method |= ! TREE_PRIVATE (x);
-
-             /* If this was an evil function, don't keep it in class.  */
-             if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
-               continue;
+      /* The name of the field is the original field name
+        Save this in auxiliary field for later overloading.  */
+      if (DECL_VINDEX (x)
+         || (all_virtual == 1 && ! DECL_CONSTRUCTOR_P (x)))
+       {
+         pending_virtuals = add_virtual_function (pending_virtuals,
+                                                  &has_virtual, x, t);
+         if (DECL_ABSTRACT_VIRTUAL_P (x))
+           abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
+         else
+           TREE_USED (x) = 1;
+       }
+    }
 
-             if (last_x)
-               TREE_CHAIN (last_x) = TREE_CHAIN (x);
-             /* Link x onto end of fn_fields and CLASSTYPE_METHODS. */
-             *tail = x;
-             tail = &TREE_CHAIN (x);
-             *tail_user_methods = x;
-             tail_user_methods = &DECL_NEXT_METHOD (x);
+  for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x))
+    {
+      GNU_xref_member (current_class_name, x);
 
-             DECL_CLASS_CONTEXT (x) = t;
+      /* Handle access declarations.  */
+      if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF)
+       {
+         tree fdecl = TREE_OPERAND (DECL_NAME (x), 1);
+         enum access_type access
+           = TREE_PRIVATE (x) ? access_private :
+             TREE_PROTECTED (x) ? access_protected : access_public;
 
-             /* Do both of these, even though they're in the same union;
-                if the insn `r' member and the size `i' member are
-                different sizes, as on the alpha, the larger of the two
-                will end up with garbage in it.  */
-             DECL_SAVED_INSNS (x) = NULL_RTX;
-             DECL_FIELD_SIZE (x) = 0;
+         if (last_x)
+           TREE_CHAIN (last_x) = TREE_CHAIN (x);
+         else
+           fields = TREE_CHAIN (x);
 
-             /* The name of the field is the original field name
-                Save this in auxiliary field for later overloading.  */
-             if (DECL_VINDEX (x)
-                 || (all_virtual == 1 && ! DECL_CONSTRUCTOR_P (x)))
-               {
-                  pending_virtuals = add_virtual_function (pending_virtuals,
-                                                           &has_virtual, x, t);
-                  if (DECL_ABSTRACT_VIRTUAL_P (x))
-                    abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
-               }
-             continue;
-           }
+         access_decls = tree_cons ((tree) access, fdecl, access_decls);
+         continue;
+       }
 
-         /* Handle access declarations.  */
-         if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF)
-           {
-             tree fdecl = TREE_OPERAND (DECL_NAME (x), 1);
+      last_x = x;
 
-             if (last_x)
-               TREE_CHAIN (last_x) = TREE_CHAIN (x);
-             access_decls = tree_cons ((tree) access, fdecl, access_decls);
-             continue;
-           }
+      if (TREE_CODE (x) == TYPE_DECL)
+       continue;
 
-         /* If we've gotten this far, it's a data member, possibly static,
-            or an enumerator. */
+      /* If we've gotten this far, it's a data member, possibly static,
+        or an enumerator. */
 
-         DECL_FIELD_CONTEXT (x) = t;
+      DECL_FIELD_CONTEXT (x) = t;
 
-         /* ``A local class cannot have static data members.'' ARM 9.4 */
-         if (current_function_decl && TREE_STATIC (x))
-           cp_error_at ("field `%D' in local class cannot be static", x);
+      /* ``A local class cannot have static data members.'' ARM 9.4 */
+      if (current_function_decl && TREE_STATIC (x))
+       cp_error_at ("field `%D' in local class cannot be static", x);
 
-         /* Perform error checking that did not get done in
-             grokdeclarator.  */
-         if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE)
-           {
-             cp_error_at ("field `%D' invalidly declared function type",
-                       x);
-             TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
-           }
-         else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE)
-           {
-             cp_error_at ("field `%D' invalidly declared method type", x);
-                 TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
-           }
-         else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE)
-           {
-             cp_error_at ("field `%D' invalidly declared offset type", x);
-             TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
-           }
+      /* Perform error checking that did not get done in
+        grokdeclarator.  */
+      if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE)
+       {
+         cp_error_at ("field `%D' invalidly declared function type",
+                      x);
+         TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
+       }
+      else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE)
+       {
+         cp_error_at ("field `%D' invalidly declared method type", x);
+         TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
+       }
+      else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE)
+       {
+         cp_error_at ("field `%D' invalidly declared offset type", x);
+         TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
+       }
 
 #if 0
-         if (DECL_NAME (x) == constructor_name (t))
-           cant_have_default_ctor = cant_synth_copy_ctor = 1;
+      if (DECL_NAME (x) == constructor_name (t))
+       cant_have_default_ctor = cant_synth_copy_ctor = 1;
 #endif
 
-         if (TREE_TYPE (x) == error_mark_node)
-           continue;
+      if (TREE_TYPE (x) == error_mark_node)
+       continue;
          
-         if (! fields)
-           fields = x;
-         last_x = x;
-
-         DECL_SAVED_INSNS (x) = NULL_RTX;
-         DECL_FIELD_SIZE (x) = 0;
+      DECL_SAVED_INSNS (x) = NULL_RTX;
+      DECL_FIELD_SIZE (x) = 0;
 
-         /* When this goes into scope, it will be a non-local reference.  */
-         DECL_NONLOCAL (x) = 1;
+      /* When this goes into scope, it will be a non-local reference.  */
+      DECL_NONLOCAL (x) = 1;
 
-         if (TREE_CODE (x) == CONST_DECL)
-           continue;
+      if (TREE_CODE (x) == CONST_DECL)
+       continue;
 
-         if (TREE_CODE (x) == VAR_DECL)
-           {
-             if (TREE_CODE (t) == UNION_TYPE)
-               /* Unions cannot have static members.  */
-               cp_error_at ("field `%D' declared static in union", x);
+      if (TREE_CODE (x) == VAR_DECL)
+       {
+         if (TREE_CODE (t) == UNION_TYPE)
+           /* Unions cannot have static members.  */
+           cp_error_at ("field `%D' declared static in union", x);
              
-             continue;
-           }
+         continue;
+       }
 
-         /* Now it can only be a FIELD_DECL.  */
+      /* Now it can only be a FIELD_DECL.  */
 
-         /* If this is of reference type, check if it needs an init.
-            Also do a little ANSI jig if necessary.  */
-         if (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE)
-           {
-             if (DECL_INITIAL (x) == NULL_TREE)
-               ref_sans_init = 1;
+      if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
+       aggregate = 0;
 
-             /* ARM $12.6.2: [A member initializer list] (or, for an
-                aggregate, initialization by a brace-enclosed list) is the
-                only way to initialize nonstatic const and reference
-                members.  */
-             cant_synth_asn_ref = 1;
-             cant_have_default_ctor = 1;
+      /* If this is of reference type, check if it needs an init.
+        Also do a little ANSI jig if necessary.  */
+      if (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE)
+       {
+         if (DECL_INITIAL (x) == NULL_TREE)
+           ref_sans_init = 1;
 
-             if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
-               {
-                 if (DECL_NAME (x))
-                   cp_warning_at ("non-static reference `%#D' in class without a constructor", x);
-                 else
-                   cp_warning_at ("non-static reference in class without a constructor", x);
-               }
+         /* ARM $12.6.2: [A member initializer list] (or, for an
+            aggregate, initialization by a brace-enclosed list) is the
+            only way to initialize nonstatic const and reference
+            members.  */
+         cant_synth_asn_ref = 1;
+         cant_have_default_ctor = 1;
+
+         if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
+           {
+             if (DECL_NAME (x))
+               cp_warning_at ("non-static reference `%#D' in class without a constructor", x);
+             else
+               cp_warning_at ("non-static reference in class without a constructor", x);
            }
+       }
 
-         /* If any field is const, the structure type is pseudo-const.  */
-         if (TREE_READONLY (x))
+      /* If any field is const, the structure type is pseudo-const.  */
+      if (TREE_READONLY (x))
+       {
+         C_TYPE_FIELDS_READONLY (t) = 1;
+         if (DECL_INITIAL (x) == NULL_TREE)
+           const_sans_init = 1;
+
+         /* ARM $12.6.2: [A member initializer list] (or, for an
+            aggregate, initialization by a brace-enclosed list) is the
+            only way to initialize nonstatic const and reference
+            members.  */
+         cant_synth_asn_ref = 1;
+         cant_have_default_ctor = 1;
+
+         if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t)
+             && extra_warnings)
+           {
+             if (DECL_NAME (x))
+               cp_warning_at ("non-static const member `%#D' in class without a constructor", x);
+             else
+               cp_warning_at ("non-static const member in class without a constructor", x);
+           }
+       }
+      else
+       {
+         /* A field that is pseudo-const makes the structure
+            likewise.  */
+         tree t1 = TREE_TYPE (x);
+         while (TREE_CODE (t1) == ARRAY_TYPE)
+           t1 = TREE_TYPE (t1);
+         if (IS_AGGR_TYPE (t1))
            {
-             C_TYPE_FIELDS_READONLY (t) = 1;
-             if (DECL_INITIAL (x) == NULL_TREE)
+             if (C_TYPE_FIELDS_READONLY (t1))
+               C_TYPE_FIELDS_READONLY (t) = 1;
+             if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (t1))
                const_sans_init = 1;
+           }
+       }
 
-             /* ARM $12.6.2: [A member initializer list] (or, for an
-                aggregate, initialization by a brace-enclosed list) is the
-                only way to initialize nonstatic const and reference
-                members.  */
-             cant_synth_asn_ref = 1;
-             cant_have_default_ctor = 1;
+      /* We set DECL_BIT_FIELD tentatively in grokbitfield.
+        If the type and width are valid, we'll keep it set.
+        Otherwise, the flag is cleared.  */
+      if (DECL_BIT_FIELD (x))
+       {
+         DECL_BIT_FIELD (x) = 0;
+         /* Invalid bit-field size done by grokfield.  */
+         /* Detect invalid bit-field type.  */
+         if (DECL_INITIAL (x)
+             && ! INTEGRAL_TYPE_P (TREE_TYPE (x)))
+           {
+             cp_error_at ("bit-field `%#D' with non-integral type", x);
+             DECL_INITIAL (x) = NULL;
+           }
 
-             if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t)
-                 && extra_warnings)
+         /* Detect and ignore out of range field width.  */
+         if (DECL_INITIAL (x))
+           {
+             register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
+
+             if (width < 0)
                {
-                 if (DECL_NAME (x))
-                   cp_warning_at ("non-static const member `%#D' in class without a constructor", x);
-                 else
-                   cp_warning_at ("non-static const member in class without a constructor", x);
+                 DECL_INITIAL (x) = NULL;
+                 cp_error_at ("negative width in bit-field `%D'", x);
                }
-           }
-         else
-           {
-             /* A field that is pseudo-const makes the structure
-                likewise.  */
-             tree t1 = TREE_TYPE (x);
-             while (TREE_CODE (t1) == ARRAY_TYPE)
-               t1 = TREE_TYPE (t1);
-             if (IS_AGGR_TYPE (t1))
+             else if (width == 0 && DECL_NAME (x) != 0)
                {
-                 if (C_TYPE_FIELDS_READONLY (t1))
-                   C_TYPE_FIELDS_READONLY (t) = 1;
-                 if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (t1))
-                   const_sans_init = 1;
+                 DECL_INITIAL (x) = NULL;
+                 cp_error_at ("zero width for bit-field `%D'", x);
                }
-           }
-
-         /* We set DECL_BIT_FIELD tentatively in grokbitfield.
-            If the type and width are valid, we'll keep it set.
-            Otherwise, the flag is cleared.  */
-         if (DECL_BIT_FIELD (x))
-           {
-             DECL_BIT_FIELD (x) = 0;
-             /* Invalid bit-field size done by grokfield.  */
-             /* Detect invalid bit-field type.  */
-             if (DECL_INITIAL (x)
-                 && ! INTEGRAL_TYPE_P (TREE_TYPE (x)))
+             else if (width
+                      > TYPE_PRECISION (long_long_unsigned_type_node))
                {
-                 cp_error_at ("bit-field `%#D' with non-integral type", x);
+                 /* The backend will dump if you try to use something
+                    too big; avoid that.  */
                  DECL_INITIAL (x) = NULL;
+                 sorry ("bit-fields larger than %d bits",
+                        TYPE_PRECISION (long_long_unsigned_type_node));
+                 cp_error_at ("  in declaration of `%D'", x);
                }
-
-             /* Detect and ignore out of range field width.  */
-             if (DECL_INITIAL (x))
+             else if (width > TYPE_PRECISION (TREE_TYPE (x))
+                      && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
                {
-                 register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
-                 if (width < 0)
-                   {
-                     DECL_INITIAL (x) = NULL;
-                     cp_error_at ("negative width in bit-field `%D'", x);
-                   }
-                 else if (width == 0 && DECL_NAME (x) != 0)
-                   {
-                     DECL_INITIAL (x) = NULL;
-                     cp_error_at ("zero width for bit-field `%D'", x);
-                   }
-                 else if (width
-                          > TYPE_PRECISION (long_long_unsigned_type_node))
-                   {
-                     /* The backend will dump if you try to use something
-                        too big; avoid that.  */
-                     DECL_INITIAL (x) = NULL;
-                     sorry ("bit-fields larger than %d bits",
-                            TYPE_PRECISION (long_long_unsigned_type_node));
-                     cp_error_at ("  in declaration of `%D'", x);
-                   }
-                 else if (width > TYPE_PRECISION (TREE_TYPE (x))
-                          && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
-                   {
-                     cp_warning_at ("width of `%D' exceeds its type", x);
-                   }
-                 else if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
-              && ((min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
-                                  TREE_UNSIGNED (TREE_TYPE (x))) > width)
-                  || (min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
-                                     TREE_UNSIGNED (TREE_TYPE (x))) > width)))
-                   {
-                     cp_warning_at ("`%D' is too small to hold all values of `%#T'",
-                                    x, TREE_TYPE (x));
-                   }
+                 cp_warning_at ("width of `%D' exceeds its type", x);
                }
-
-             /* Process valid field width.  */
-             if (DECL_INITIAL (x))
+             else if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
+                      && ((min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
+                                          TREE_UNSIGNED (TREE_TYPE (x))) > width)
+                          || (min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
+                                             TREE_UNSIGNED (TREE_TYPE (x))) > width)))
                {
-                 register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
+                 cp_warning_at ("`%D' is too small to hold all values of `%#T'",
+                                x, TREE_TYPE (x));
+               }
+           }
 
-                 if (width == 0)
-                   {
+         /* Process valid field width.  */
+         if (DECL_INITIAL (x))
+           {
+             register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
+
+             if (width == 0)
+               {
 #ifdef EMPTY_FIELD_BOUNDARY
-                     /* field size 0 => mark following field as "aligned" */
-                     if (TREE_CHAIN (x))
-                       DECL_ALIGN (TREE_CHAIN (x))
-                         = MAX (DECL_ALIGN (TREE_CHAIN (x)), EMPTY_FIELD_BOUNDARY);
-                     /* field of size 0 at the end => round up the size.  */
-                     else
-                       round_up_size = EMPTY_FIELD_BOUNDARY;
+                 /* field size 0 => mark following field as "aligned" */
+                 if (TREE_CHAIN (x))
+                   DECL_ALIGN (TREE_CHAIN (x))
+                     = MAX (DECL_ALIGN (TREE_CHAIN (x)), EMPTY_FIELD_BOUNDARY);
+                 /* field of size 0 at the end => round up the size.  */
+                 else
+                   round_up_size = EMPTY_FIELD_BOUNDARY;
 #endif
 #ifdef PCC_BITFIELD_TYPE_MATTERS
-                     DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
-                                           TYPE_ALIGN (TREE_TYPE (x)));
+                 DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
+                                       TYPE_ALIGN (TREE_TYPE (x)));
 #endif
-                   }
-                 else
-                   {
-                     DECL_INITIAL (x) = NULL_TREE;
-                     DECL_FIELD_SIZE (x) = width;
-                     DECL_BIT_FIELD (x) = 1;
-                     /* Traditionally a bit field is unsigned
-                        even if declared signed.  */
-                     if (flag_traditional
-                         && TREE_CODE (TREE_TYPE (x)) == INTEGER_TYPE)
-                       TREE_TYPE (x) = unsigned_type_node;
-                   }
                }
              else
-               /* Non-bit-fields are aligned for their type.  */
-               DECL_ALIGN (x) = MAX (DECL_ALIGN (x), TYPE_ALIGN (TREE_TYPE (x)));
+               {
+                 DECL_INITIAL (x) = NULL_TREE;
+                 DECL_FIELD_SIZE (x) = width;
+                 DECL_BIT_FIELD (x) = 1;
+                 /* Traditionally a bit field is unsigned
+                    even if declared signed.  */
+                 if (flag_traditional
+                     && TREE_CODE (TREE_TYPE (x)) == INTEGER_TYPE)
+                   TREE_TYPE (x) = unsigned_type_node;
+               }
            }
          else
-           {
-             tree type = TREE_TYPE (x);
+           /* Non-bit-fields are aligned for their type.  */
+           DECL_ALIGN (x) = MAX (DECL_ALIGN (x), TYPE_ALIGN (TREE_TYPE (x)));
+       }
+      else
+       {
+         tree type = TREE_TYPE (x);
 
-             if (TREE_CODE (type) == ARRAY_TYPE)
-               type = TREE_TYPE (type);
+         if (TREE_CODE (type) == ARRAY_TYPE)
+           type = TREE_TYPE (type);
 
-             if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x)
-                 && ! TYPE_PTRMEMFUNC_P (type))
-               {
-                 /* Never let anything with uninheritable virtuals
-                    make it through without complaint.  */
-                 if (CLASSTYPE_ABSTRACT_VIRTUALS (type))
-                   abstract_virtuals_error (x, type);
+         if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x)
+             && ! TYPE_PTRMEMFUNC_P (type))
+           {
+             /* Never let anything with uninheritable virtuals
+                make it through without complaint.  */
+             if (CLASSTYPE_ABSTRACT_VIRTUALS (type))
+               abstract_virtuals_error (x, type);
                      
-                 /* Don't let signatures make it through either.  */
-                 if (IS_SIGNATURE (type))
-                   signature_error (x, type);
+             /* Don't let signatures make it through either.  */
+             if (IS_SIGNATURE (type))
+               signature_error (x, type);
                      
-                 if (code == UNION_TYPE)
-                   {
-                     char *fie = NULL;
-                     if (TYPE_NEEDS_CONSTRUCTING (type))
-                       fie = "constructor";
-                     else if (TYPE_NEEDS_DESTRUCTOR (type))
-                       fie = "destructor";
-                     else if (TYPE_HAS_REAL_ASSIGNMENT (type))
-                       fie = "assignment operator";
-                     if (fie)
-                       cp_error_at ("member `%#D' with %s not allowed in union", x,
-                                    fie);
-                   }
-                 else
-                   {
-                     TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
-                     TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type);
-                     TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
-                     TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
-                   }
+             if (code == UNION_TYPE)
+               {
+                 char *fie = NULL;
+                 if (TYPE_NEEDS_CONSTRUCTING (type))
+                   fie = "constructor";
+                 else if (TYPE_NEEDS_DESTRUCTOR (type))
+                   fie = "destructor";
+                 else if (TYPE_HAS_REAL_ASSIGNMENT (type))
+                   fie = "assignment operator";
+                 if (fie)
+                   cp_error_at ("member `%#D' with %s not allowed in union", x,
+                                fie);
+               }
+             else
+               {
+                 TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
+                 TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type);
+                 TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
+                 TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
+               }
 
-                 if (! TYPE_HAS_INIT_REF (type)
-                     || (TYPE_HAS_NONPUBLIC_CTOR (type)
-                         && ! is_friend (t, type)))
-                   cant_synth_copy_ctor = 1;
-                 else if (!TYPE_HAS_CONST_INIT_REF (type))
-                   cant_have_const_ctor = 1;
-
-                 if (! TYPE_HAS_ASSIGN_REF (type)
-                     || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (type)
-                         && ! is_friend (t, type)))
-                   cant_synth_asn_ref = 1;
-                 else if (!TYPE_HAS_CONST_ASSIGN_REF (type))
-                   no_const_asn_ref = 1;
-
-                 if (TYPE_HAS_CONSTRUCTOR (type)
-                     && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
-                   {
-                     cant_have_default_ctor = 1;
+             if (! TYPE_HAS_INIT_REF (type)
+                 || (TYPE_HAS_NONPUBLIC_CTOR (type)
+                     && ! is_friend (t, type)))
+               cant_synth_copy_ctor = 1;
+             else if (!TYPE_HAS_CONST_INIT_REF (type))
+               cant_have_const_ctor = 1;
+
+             if (! TYPE_HAS_ASSIGN_REF (type)
+                 || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (type)
+                     && ! is_friend (t, type)))
+               cant_synth_asn_ref = 1;
+             else if (!TYPE_HAS_CONST_ASSIGN_REF (type))
+               no_const_asn_ref = 1;
+
+             if (TYPE_HAS_CONSTRUCTOR (type)
+                 && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+               {
+                 cant_have_default_ctor = 1;
 #if 0
-                     /* This is wrong for aggregates.  */
-                     if (! TYPE_HAS_CONSTRUCTOR (t))
-                       {
-                         if (DECL_NAME (x))
-                           cp_pedwarn_at ("member `%#D' with only non-default constructor", x);
-                         else
-                           cp_pedwarn_at ("member with only non-default constructor", x);
-                         cp_pedwarn_at ("in class without a constructor",
-                                        x);
-                       }
-#endif
+                 /* This is wrong for aggregates.  */
+                 if (! TYPE_HAS_CONSTRUCTOR (t))
+                   {
+                     if (DECL_NAME (x))
+                       cp_pedwarn_at ("member `%#D' with only non-default constructor", x);
+                     else
+                       cp_pedwarn_at ("member with only non-default constructor", x);
+                     cp_pedwarn_at ("in class without a constructor",
+                                    x);
                    }
-               }
-             if (DECL_INITIAL (x) != NULL_TREE)
-               {
-                 /* `build_class_init_list' does not recognize
-                     non-FIELD_DECLs.  */
-                 if (code == UNION_TYPE && any_default_members != 0)
-                   cp_error_at ("multiple fields in union `%T' initialized");
-                 any_default_members = 1;
+#endif
                }
            }
-       }
-      list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
-      /* link the tail while we have it! */
-      if (last_x)
-       {
-         TREE_CHAIN (last_x) = NULL_TREE;
-
-         if (list_of_fieldlists
-             && TREE_VALUE (list_of_fieldlists)
-             && TREE_CODE (TREE_VALUE (list_of_fieldlists)) != FUNCTION_DECL)
-           TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
+         if (DECL_INITIAL (x) != NULL_TREE)
+           {
+             /* `build_class_init_list' does not recognize
+                non-FIELD_DECLs.  */
+             if (code == UNION_TYPE && any_default_members != 0)
+               cp_error_at ("multiple fields in union `%T' initialized");
+             any_default_members = 1;
+           }
        }
     }
 
@@ -3337,6 +3287,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
   /* Synthesize any needed methods.  Note that methods will be synthesized
      for anonymous unions; grok_x_components undoes that.  */
 
+  if (! fn_fields)
+    nonprivate_method = 1;
+
   if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t)
       && !IS_SIGNATURE (t))
     {
@@ -3349,8 +3302,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
       else
        {
          /* Link dtor onto end of fn_fields. */
-         *tail = dtor;
-         tail = &TREE_CHAIN (dtor);
+
+         TREE_CHAIN (dtor) = fn_fields;
+         fn_fields = dtor;
 
          if (DECL_VINDEX (dtor) == NULL_TREE
              && (needs_virtual_dtor
@@ -3364,23 +3318,20 @@ finish_struct (t, list_of_fieldlists, warn_anon)
        }
     }
 
-  *tail = NULL_TREE;
-  *tail_user_methods = NULL_TREE;
-
   TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
   if (flag_rtti && (max_has_virtual > 0 || needs_virtual_dtor) && 
        has_virtual == 0)
     has_virtual = 1;
 
-  if (! fn_fields)
-    nonprivate_method = 1;
-
   TYPE_HAS_COMPLEX_INIT_REF (t)
     |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
        || any_default_members);
   TYPE_NEEDS_CONSTRUCTING (t)
     |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
        || has_virtual || any_default_members || first_vfn_base_index >= 0);
+  if (! IS_SIGNATURE (t))
+    CLASSTYPE_NON_AGGREGATE (t)
+      = ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t);
 
   /* ARM $12.1: A default constructor will be generated for a class X
      only if no constructor has been declared for class X.  So we
@@ -3653,6 +3604,13 @@ finish_struct (t, list_of_fieldlists, warn_anon)
                if (TREE_CODE (uelt) != FIELD_DECL)
                  continue;
 
+               if (TREE_PRIVATE (uelt))
+                 cp_pedwarn_at ("private member `%#D' in anonymous union",
+                                uelt);
+               else if (TREE_PROTECTED (uelt))
+                 cp_pedwarn_at ("protected member `%#D' in anonymous union",
+                                uelt);
+
                DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field);
                DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field);
              }
@@ -3788,39 +3746,28 @@ finish_struct (t, list_of_fieldlists, warn_anon)
       /* We must enter these virtuals into the table.  */
       if (first_vfn_base_index < 0)
        {
-         if (flag_rtti)
-           pending_virtuals = tree_cons (NULL_TREE,
-               build_vtable_entry (integer_zero_node, build_t_desc (t, 0)),
-               pending_virtuals);
-         else 
-            pending_virtuals = tree_cons (NULL_TREE,
-                build_vtable_entry (integer_zero_node, integer_zero_node),
-                pending_virtuals);
+         /* The first slot is for the rtti offset.  */
+         pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
 
-#if 0
-         /* The size is no longer used. */
-         /* now we put the size of the vtable as first entry */
-         pending_virtuals = tree_cons (NULL_TREE, the_null_vtable_entry,
-                                       pending_virtuals);
-#endif
+         /* The second slot is for the tdesc pointer when thunks are used.  */
+         if (flag_vtable_thunks)
+           pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
+
+         set_rtti_entry (pending_virtuals, integer_zero_node, t);
          build_vtable (NULL_TREE, t);
        }
       else
        {
+         tree offset;
          /* Here we know enough to change the type of our virtual
             function table, but we will wait until later this function.  */
 
          if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t)))
            build_vtable (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index), t);
 
-         /* Update the rtti pointer for this class.  */
-         if (flag_rtti)
-           {
-             tree offset = get_derived_offset (TYPE_BINFO (t), NULL_TREE);
-             offset = size_binop (MINUS_EXPR, integer_zero_node, offset);
-             TREE_VALUE (TYPE_BINFO_VIRTUALS (t))
-               = build_vtable_entry (offset, build_t_desc (t, 0));
-           }
+         offset = get_derived_offset (TYPE_BINFO (t), NULL_TREE);
+         offset = size_binop (MINUS_EXPR, integer_zero_node, offset);
+         set_rtti_entry (TYPE_BINFO_VIRTUALS (t), offset, t);
        }
 
       /* If this type has basetypes with constructors, then those
@@ -3918,29 +3865,10 @@ finish_struct (t, list_of_fieldlists, warn_anon)
 
   finish_struct_bits (t, max_has_virtual);
 
-  /* Promote each bit-field's type to int if it is narrower than that.
-     There's more: complete the rtl for any static member objects which
-     is of the same type we're working on.  */
+  /* Complete the rtl for any static member objects of the type we're
+     working on.  */
   for (x = fields; x; x = TREE_CHAIN (x))
     {
-      if (DECL_BIT_FIELD (x)
-         && (C_PROMOTING_INTEGER_TYPE_P (TREE_TYPE (x))
-             || DECL_FIELD_SIZE (x) < TYPE_PRECISION (integer_type_node)))
-       {
-         tree type = TREE_TYPE (x);
-
-         /* Preserve unsignedness if traditional or if not really getting
-            any wider.  */
-         if (TREE_UNSIGNED (type)
-             && (flag_traditional
-                 ||
-                 (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)
-                  && DECL_FIELD_SIZE (x) == TYPE_PRECISION (integer_type_node))))
-           TREE_TYPE (x) = unsigned_type_node;
-         else
-           TREE_TYPE (x) = integer_type_node;
-       }
-
       if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
          && TREE_TYPE (x) == t)
        {
@@ -4110,6 +4038,146 @@ finish_struct (t, list_of_fieldlists, warn_anon)
 
   return t;
 }
+
+tree
+finish_struct (t, list_of_fieldlists, warn_anon)
+     tree t;
+     tree list_of_fieldlists;
+     int warn_anon;
+{
+  tree fields = NULL_TREE, fn_fields, *tail;
+  tree *tail_user_methods = &CLASSTYPE_METHODS (t);
+  tree name = TYPE_NAME (t);
+  tree x, last_x = NULL_TREE;
+  enum access_type access;
+
+  if (TREE_CODE (name) == TYPE_DECL)
+    {
+      extern int lineno;
+         
+      DECL_SOURCE_FILE (name) = input_filename;
+      /* For TYPE_DECL that are not typedefs (those marked with a line
+        number of zero, we don't want to mark them as real typedefs.
+        If this fails one needs to make sure real typedefs have a
+        previous line number, even if it is wrong, that way the below
+        will fill in the right line number.  (mrs) */
+      if (DECL_SOURCE_LINE (name))
+       DECL_SOURCE_LINE (name) = lineno;
+      CLASSTYPE_SOURCE_LINE (t) = lineno;
+      name = DECL_NAME (name);
+    }
+
+  /* Append the fields we need for constructing signature tables.  */
+  if (IS_SIGNATURE (t))
+    append_signature_fields (list_of_fieldlists);
+
+  tail = &fn_fields;
+  if (last_x && list_of_fieldlists)
+    TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
+
+  /* For signatures, we made all methods `public' in the parser and
+     reported an error if a access specifier was used.  */
+  if (CLASSTYPE_DECLARED_CLASS (t) == 0)
+    {
+      if (list_of_fieldlists
+         && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default)
+       TREE_PURPOSE (list_of_fieldlists) = (tree)access_public;
+    }
+  else if (list_of_fieldlists
+          && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default)
+    TREE_PURPOSE (list_of_fieldlists) = (tree)access_private;
+
+  while (list_of_fieldlists)
+    {
+      access = (enum access_type)TREE_PURPOSE (list_of_fieldlists);
+
+      for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x))
+       {
+         TREE_PRIVATE (x) = access == access_private;
+         TREE_PROTECTED (x) = access == access_protected;
+
+         /* Check for inconsistent use of this name in the class body.
+             Enums, types and static vars have already been checked.  */
+         if (TREE_CODE (x) != TYPE_DECL
+             && TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL)
+           {
+             tree name = DECL_NAME (x);
+             tree icv;
+
+             /* Don't get confused by access decls.  */
+             if (name && TREE_CODE (name) == IDENTIFIER_NODE)
+               icv = IDENTIFIER_CLASS_VALUE (name);
+             else
+               icv = NULL_TREE;
+
+             if (icv
+                 /* Don't complain about constructors.  */
+                 && name != constructor_name (current_class_type)
+                 /* Or inherited names.  */
+                 && id_in_current_class (name)
+                 /* Or shadowed tags.  */
+                 && !(TREE_CODE (icv) == TYPE_DECL
+                      && DECL_CONTEXT (icv) == t))
+               {
+                 cp_error_at ("declaration of identifier `%D' as `%+#D'",
+                              name, x);
+                 cp_error_at ("conflicts with other use in class as `%#D'",
+                              icv);
+               }
+           }
+
+         if (TREE_CODE (x) == FUNCTION_DECL)
+           {
+             if (last_x)
+               TREE_CHAIN (last_x) = TREE_CHAIN (x);
+             /* Link x onto end of fn_fields and CLASSTYPE_METHODS. */
+             *tail = x;
+             tail = &TREE_CHAIN (x);
+             *tail_user_methods = x;
+             tail_user_methods = &DECL_NEXT_METHOD (x);
+             continue;
+           }
+
+#if 0
+         /* Handle access declarations.  */
+         if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF)
+           {
+             tree n = DECL_NAME (x);
+             x = build_decl
+               (USING_DECL, DECL_NAME (TREE_OPERAND (n, 1)), TREE_TYPE (x));
+             DECL_RESULT (x) = n;
+           }
+#endif
+
+         if (! fields)
+           fields = x;
+         last_x = x;
+       }
+      list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
+      /* link the tail while we have it! */
+      if (last_x)
+       {
+         TREE_CHAIN (last_x) = NULL_TREE;
+
+         if (list_of_fieldlists
+             && TREE_VALUE (list_of_fieldlists)
+             && TREE_CODE (TREE_VALUE (list_of_fieldlists)) != FUNCTION_DECL)
+           TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
+       }
+    }
+
+  *tail = NULL_TREE;
+  *tail_user_methods = NULL_TREE;
+  TYPE_FIELDS (t) = fields;
+
+  if (0 && processing_template_defn)
+    {
+      CLASSTYPE_METHOD_VEC (t) = finish_struct_methods (t, fn_fields, 1);
+      return t;
+    }
+  else
+    return finish_struct_1 (t, warn_anon);
+}
 \f
 /* Return non-zero if the effective type of INSTANCE is static.
    Used to determine whether the virtual function table is needed
@@ -4452,7 +4520,7 @@ push_nested_class (type, modify)
 {
   tree context;
 
-  if (type == error_mark_node || ! IS_AGGR_TYPE (type))
+  if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type))
     return;
   
   context = DECL_CONTEXT (TYPE_NAME (type));
index 2cab395..82b7954 100644 (file)
@@ -35,6 +35,15 @@ DEFTREECODE (CP_OFFSET_REF, "cp_offset_ref", "r", 2)
 DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2)
 DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", "e", 2)
 
+/* For a UNSAVE_EXPR, operand 0 is the value to unsave.  By unsave, we
+   mean that all _EXPRs such as TARGET_EXPRs, SAVE_EXPRs,
+   WITH_CLEANUP_EXPRs, CALL_EXPRs and RTL_EXPRs, that are protected
+   from being evaluated more than once should be reset so that a new
+   expand_expr call of this expr will cause those to be re-evaluated.
+   This is useful when we want to reuse a tree in different places,
+   but where we must re-expand.  */
+DEFTREECODE (UNSAVE_EXPR, "unsave_expr", "e", 1)
+
 /* Value is reference to particular overloaded class method.
    Operand 0 is the class name (an IDENTIFIER_NODE);
    operand 1 is the field (also an IDENTIFIER_NODE).
index 2ee2310..fe9855d 100644 (file)
@@ -450,11 +450,12 @@ struct lang_type
       unsigned has_complex_init_ref : 1;
       unsigned has_complex_assign_ref : 1;
       unsigned has_abstract_assign_ref : 1;
+      unsigned non_aggregate : 1;
 
       /* The MIPS compiler gets it wrong if this struct also
         does not fill out to a multiple of 4 bytes.  Add a
         member `dummy' with new bits if you go over the edge.  */
-      unsigned dummy : 20;
+      unsigned dummy : 19;
 
       unsigned n_vancestors : 16;
     } type_flags;
@@ -1054,6 +1055,9 @@ struct lang_decl
    class where a virtual function instance is actually defined, and the
    lexical scope of a friend function defined in a class body.  */
 #define DECL_CLASS_CONTEXT(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.context)
+#define DECL_REAL_CONTEXT(NODE) \
+  ((TREE_CODE (NODE) == FUNCTION_DECL && DECL_FUNCTION_MEMBER_P (NODE)) \
+   ? 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
@@ -1068,7 +1072,7 @@ struct lang_decl
 #define DECL_NEXT_METHOD(NODE) (DECL_LANG_SPECIFIC(NODE)->next_method)
 
 /* In a VAR_DECL for a variable declared in a for statement,
-   this is the shadowed (local) variable. */
+   this is the shadowed variable. */
 #define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT(NODE)
 
 /* Points back to the decl which caused this lang_decl to be allocated.  */
@@ -1218,6 +1222,13 @@ extern int flag_new_for_scope;
 #define TYPE_NEEDS_CONSTRUCTING(NODE) (TYPE_LANG_FLAG_3(NODE))
 #endif
 
+/* Nonzero means that an object of this type can not be initialized using
+   an initializer list.  */
+#define CLASSTYPE_NON_AGGREGATE(NODE) \
+  (TYPE_LANG_SPECIFIC (NODE)->type_flags.non_aggregate)
+#define TYPE_NON_AGGREGATE_CLASS(NODE) \
+  (IS_AGGR_TYPE (NODE) && CLASSTYPE_NON_AGGREGATE (NODE))
+
 /* Nonzero if there is a user-defined X::op=(x&) for this class.  */
 #define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assign_ref)
 #define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_complex_assign_ref)
@@ -1953,6 +1964,7 @@ extern int root_lang_context_p                    PROTO((void));
 extern tree instantiate_type                   PROTO((tree, tree, int));
 extern void print_class_statistics             PROTO((void));
 extern void maybe_push_cache_obstack           PROTO((void));
+extern unsigned HOST_WIDE_INT skip_rtti_stuff  PROTO((tree *));
 
 /* in cvt.c */
 extern tree convert_to_reference               PROTO((tree, tree, int, int, tree));
@@ -2030,7 +2042,7 @@ extern void cp_finish_decl                        PROTO((tree, tree, tree, int, int));
 extern void expand_static_init                 PROTO((tree, tree));
 extern int complete_array_type                 PROTO((tree, tree, int));
 extern tree build_ptrmemfunc_type              PROTO((tree));
-extern tree grokdeclarator                     (); /* PROTO((tree, tree, enum decl_context, int, tree)); */
+/* the grokdeclarator prototype is in decl.h */
 extern int parmlist_is_exprlist                        PROTO((tree));
 extern tree xref_tag                           PROTO((tree, tree, tree, int));
 extern void xref_basetypes                     PROTO((tree, tree, tree, tree));
@@ -2038,8 +2050,10 @@ extern tree start_enum                           PROTO((tree));
 extern tree finish_enum                                PROTO((tree, tree));
 extern tree build_enumerator                   PROTO((tree, tree));
 extern tree grok_enum_decls                    PROTO((tree, tree));
-extern int start_function                      PROTO((tree, tree, tree, int));
+extern int start_function                      PROTO((tree, tree, tree, tree, int));
 extern void store_parm_decls                   PROTO((void));
+extern void expand_start_early_try_stmts       PROTO((void));
+extern void store_in_parms                     PROTO((struct rtx_def *));
 extern void store_return_init                  PROTO((tree, tree));
 extern void finish_function                    PROTO((int, int, int));
 extern tree start_method                       PROTO((tree, tree, tree));
@@ -2059,8 +2073,8 @@ 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 void check_classfn                      PROTO((tree, tree, tree));
-extern tree grokfield                          PROTO((tree, tree, tree, tree, tree));
+extern tree check_classfn                      PROTO((tree, 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));
@@ -2093,6 +2107,7 @@ extern tree do_toplevel_using_decl                PROTO((tree));
 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));
 
 /* in edsel.c */
 
@@ -2113,12 +2128,16 @@ extern int might_have_exceptions_p              PROTO((void));
 extern void emit_exception_table               PROTO((void));
 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));
 
 /* in expr.c */
 /* skip cplus_expand_expr */
 extern void init_cplus_expand                  PROTO((void));
 extern void fixup_result_decl                  PROTO((tree, struct rtx_def *));
 extern int decl_in_memory_p                    PROTO((tree));
+extern tree unsave_expr_now                    PROTO((tree));
 
 /* in gc.c */
 extern int type_needs_gc_entry                 PROTO((tree));
@@ -2232,6 +2251,7 @@ extern char *code_as_string                       PROTO((enum tree_code, int));
 extern char *language_as_string                        PROTO((enum languages, int));
 extern char *parm_as_string                    PROTO((int, int));
 extern char *op_as_string                      PROTO((enum tree_code, int));
+extern char *cv_as_string                      PROTO((tree, int));
 
 /* in method.c */
 extern void init_method                                PROTO((void));
@@ -2367,13 +2387,15 @@ extern int promotes_to_aggr_type                PROTO((tree, enum tree_code));
 extern int is_aggr_type_2                      PROTO((tree, tree));
 extern void message_2_types                    PROTO((void (*)(), char *, tree, tree));
 extern char *lang_printable_name               PROTO((tree));
-extern tree build_exception_variant            PROTO((tree, tree, tree));
+extern tree build_exception_variant            PROTO((tree, tree));
 extern tree copy_to_permanent                  PROTO((tree));
 extern void print_lang_statistics              PROTO((void));
 /* skip __eprintf */
 extern tree array_type_nelts_total             PROTO((tree));
 extern tree array_type_nelts_top               PROTO((tree));
 extern tree break_out_target_exprs             PROTO((tree));
+extern tree build_unsave_expr                  PROTO((tree));
+extern int cp_expand_decl_cleanup              PROTO((tree, tree));
 
 /* in typeck.c */
 extern tree condition_conversion               PROTO((tree));
@@ -2397,6 +2419,7 @@ extern tree signed_or_unsigned_type               PROTO((int, tree));
 extern tree c_sizeof                           PROTO((tree));
 extern tree c_sizeof_nowarn                    PROTO((tree));
 extern tree c_alignof                          PROTO((tree));
+extern tree decay_conversion                   PROTO((tree));
 extern tree default_conversion                 PROTO((tree));
 extern tree build_object_ref                   PROTO((tree, tree, tree));
 extern tree build_component_ref_1              PROTO((tree, tree, int));
index c1d8165..56508c1 100644 (file)
@@ -180,6 +180,15 @@ cp_convert_to_pointer (type, expr)
            return error_mark_node;
        }
 
+      if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
+         || (TREE_CODE (type) == POINTER_TYPE
+             && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
+       {
+         cp_error ("cannot convert `%E' from type `%T' to type `%T'",
+                   expr, intype, type);
+         return error_mark_node;
+       }
+
       return build1 (NOP_EXPR, type, expr);
     }
 
@@ -904,7 +913,7 @@ convert_to_aggr (type, expr, msgp, protect)
 
   /* The type of the first argument will be filled in inside the loop.  */
   parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist);
-  parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes);
+  parmtypes = tree_cons (NULL_TREE, build_pointer_type (basetype), parmtypes);
 
 #if 0
   method_name = build_decl_overload (name, parmtypes, 1);
@@ -1164,32 +1173,6 @@ convert_pointer_to (binfo, expr)
       type = binfo;
   return convert_pointer_to_real (type, expr);
 }
-
-/* Same as above, but don't abort if we get an "ambiguous" baseclass.
-   There's only one virtual baseclass we are looking for, and once
-   we find one such virtual baseclass, we have found them all.  */
-
-tree
-convert_pointer_to_vbase (binfo, expr)
-     tree binfo;
-     tree expr;
-{
-  tree intype = TREE_TYPE (TREE_TYPE (expr));
-  tree binfos = TYPE_BINFO_BASETYPES (intype);
-  int i;
-
-  for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
-    {
-      tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
-      if (BINFO_TYPE (binfo) == basetype)
-       return convert_pointer_to (binfo, expr);
-      if (binfo_member (BINFO_TYPE (binfo), CLASSTYPE_VBASECLASSES (basetype)))
-       return convert_pointer_to_vbase (binfo, convert_pointer_to (basetype, expr));
-    }
-  my_friendly_abort (6);
-  /* NOTREACHED */
-  return NULL_TREE;
-}
 \f
 /* Conversion...
 
@@ -1374,44 +1357,7 @@ cp_convert (type, expr, convtype, flags)
        return conversion;
       else if (ctor)
        {
-         if (current_function_decl)
-           /* We can't pass 1 to the with_cleanup_p arg here, because that
-              screws up passing classes by value.  */
-           ctor = build_cplus_new (type, ctor, 0);
-         else
-           {
-             register tree parm = TREE_OPERAND (ctor, 1);
-
-             /* Initializers for static variables and parameters
-                have to handle doing the initialization and
-                cleanup themselves.  */
-             my_friendly_assert (TREE_CODE (ctor) == CALL_EXPR, 322);
-#if 0
-             /* The following assertion fails in cases where we
-                are initializing a static member variable of a
-                particular instance of a template class with a
-                call to a constructor of the given instance, as
-                in:
-                
-                TMPL<int> object = TMPL<int>();
-                
-                Curiously, the assertion does not fail if we do
-                the same thing for a static member of a
-                non-template class, as in:
-                
-                T object = T();
-                
-                I can't see why we should care here whether or not
-                the initializer expression involves a call to
-                `new', so for the time being, it seems best to
-                just avoid doing this assertion.  */
-             my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)),
-                                 323);
-#endif
-             TREE_VALUE (parm) = NULL_TREE;
-             ctor = build_indirect_ref (ctor, NULL_PTR);
-             TREE_HAS_CONSTRUCTOR (ctor) = 1;
-           }
+         ctor = build_cplus_new (type, ctor, 0);
          return ctor;
        }
     }
@@ -1524,7 +1470,14 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
 
    If (FOR_SURE & 1) is non-zero, then we allow this type conversion
    to take place immediately.  Otherwise, we build a SAVE_EXPR
-   which can be evaluated if the results are ever needed.  */
+   which can be evaluated if the results are ever needed.
+
+   Changes to this functions should be mirrored in user_harshness.
+
+   FIXME: Ambiguity checking is wrong.  Should choose one by the implicit
+   object parameter, or by the second standard conversion sequence if
+   that doesn't do it.  This will probably wait for an overloading rewrite.
+   (jason 8/9/95)  */
 
 tree
 build_type_conversion (code, xtype, expr, for_sure)
@@ -1604,10 +1557,9 @@ build_expr_type_conversion (desires, expr, complain)
   tree winner = NULL_TREE;
 
   if (TREE_CODE (basetype) == OFFSET_TYPE)
-    {
-      expr = resolve_offset_ref (expr);
-      basetype = TREE_TYPE (expr);
-    }
+    expr = resolve_offset_ref (expr);
+  expr = convert_from_reference (expr);
+  basetype = TREE_TYPE (expr);
 
   if (! IS_AGGR_TYPE (basetype))
     switch (TREE_CODE (basetype))
@@ -1641,11 +1593,16 @@ build_expr_type_conversion (desires, expr, complain)
   for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
     {
       int win = 0;
+      tree candidate;
 
       if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
        continue;
 
-      switch (TREE_CODE (TREE_VALUE (conv)))
+      candidate = TREE_VALUE (conv);
+      if (TREE_CODE (candidate) == REFERENCE_TYPE)
+       candidate = TREE_TYPE (candidate);
+
+      switch (TREE_CODE (candidate))
        {
        case BOOLEAN_TYPE:
        case INTEGER_TYPE:
@@ -1817,8 +1774,13 @@ tree
 type_promotes_to (type)
      tree type;
 {
-  int constp = TYPE_READONLY (type);
-  int volatilep = TYPE_VOLATILE (type);
+  int constp, volatilep;
+
+  if (type == error_mark_node)
+    return error_mark_node;
+
+  constp = TYPE_READONLY (type);
+  volatilep = TYPE_VOLATILE (type);
   type = TYPE_MAIN_VARIANT (type);
 
   /* bool always promotes to int (not unsigned), even if it's the same
index d5b149f..b0453b6 100644 (file)
@@ -548,9 +548,9 @@ struct binding_level
     /* The binding level which this one is contained in (inherits from).  */
     struct binding_level *level_chain;
 
-    /* Number of decls in `names' that have incomplete 
+    /* List of decls in `names' that have incomplete
        structure or union types.  */
-    unsigned int n_incomplete;
+    tree incomplete;
 
     /* List of VAR_DECLS saved from a previous for statement.
        These would be dead in ANSI-conforming code, but might
@@ -1488,7 +1488,7 @@ print_binding_level (lvl)
   fprintf (stderr, " blocks=");
   fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks);
   fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d",
-          lvl->n_incomplete, lvl->parm_flag, lvl->keep);
+          list_length (lvl->incomplete), lvl->parm_flag, lvl->keep);
   if (lvl->tag_transparent)
     fprintf (stderr, " tag-transparent");
   if (lvl->more_cleanups_ok)
@@ -2138,6 +2138,7 @@ pushtag (name, type, globalize)
                  d = make_type_decl (name, type);
 #else
                  d = build_decl (TYPE_DECL, name, type);
+                 DECL_ASSEMBLER_NAME (d) = current_namespace_id (DECL_ASSEMBLER_NAME (d));
 #endif
                  SET_DECL_ARTIFICIAL (d);
 #ifdef DWARF_DEBUGGING_INFO
@@ -2806,9 +2807,9 @@ duplicate_decls (newdecl, olddecl)
        {
          tree ctype = NULL_TREE;
          ctype = DECL_CLASS_CONTEXT (newdecl);
-         TREE_TYPE (newdecl) = build_exception_variant (ctype, newtype,
+         TREE_TYPE (newdecl) = build_exception_variant (newtype,
                                                         TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
-         TREE_TYPE (olddecl) = build_exception_variant (ctype, newtype,
+         TREE_TYPE (olddecl) = build_exception_variant (newtype,
                                                         TYPE_RAISES_EXCEPTIONS (oldtype));
 
          if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
@@ -3172,6 +3173,8 @@ pushdecl (x)
 #endif
              if (TREE_CODE (t) == TYPE_DECL)
                SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
+             else if (TREE_CODE (t) == FUNCTION_DECL)
+               check_default_args (t);
 
              return t;
            }
@@ -3395,6 +3398,7 @@ pushdecl (x)
              if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
                warnstring = "declaration of `%s' shadows a parameter";
              else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE
+                      && current_class_decl
                       && !TREE_STATIC (name))
                warnstring = "declaration of `%s' shadows a member of `this'";
              else if (oldlocal != NULL_TREE)
@@ -3408,43 +3412,17 @@ pushdecl (x)
        }
 
       if (TREE_CODE (x) == FUNCTION_DECL)
-       {
-         /* This is probably the wrong place to check this, but it has to
-             come after the call to duplicate_decls.  */
-         tree arg = TYPE_ARG_TYPES (TREE_TYPE (x));
-         int saw_def = 0, i = 1;
-         for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i)
-           {
-             if (TREE_PURPOSE (arg))
-               saw_def = 1;
-             else if (saw_def)
-               {
-                 cp_error ("default argument missing for parameter %d of `%#D'",
-                           i, x);
-                 break;
-               }
-           }
-       }
-
-      /* Keep count of variables in this level with incomplete type.  */
-      if (TREE_CODE (x) != TEMPLATE_DECL
-         && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
-         && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
-       {
-         if (++b->n_incomplete == 0)
-           error ("too many incomplete variables at this point");
-       }
+       check_default_args (x);
 
       /* Keep count of variables in this level with incomplete type.  */
-      /* RTTI TD entries are created while defining the type_info.  */
       if (TREE_CODE (x) == VAR_DECL
          && TREE_TYPE (x) != error_mark_node
-         && TYPE_LANG_SPECIFIC (TREE_TYPE (x))
-         && TYPE_BEING_DEFINED (TREE_TYPE (x)))
-       {
-         if (++b->n_incomplete == 0)
-           error ("too many incomplete variables at this point");
-       }
+         && ((TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
+              && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
+             /* RTTI TD entries are created while defining the type_info.  */
+             || (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
+                 && TYPE_BEING_DEFINED (TREE_TYPE (x)))))
+       b->incomplete = tree_cons (NULL_TREE, x, b->incomplete);
     }
 
   /* Put decls on list in reverse order.
@@ -5428,11 +5406,11 @@ init_decl_processing ()
       __i_desc_type_node = make_lang_type (RECORD_TYPE);
       __m_desc_type_node = make_lang_type (RECORD_TYPE);
       __t_desc_array_type =
-       build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE);
+       build_array_type (build_pointer_type (__t_desc_type_node), NULL_TREE);
       __i_desc_array_type =
-       build_array_type (TYPE_POINTER_TO (__i_desc_type_node), NULL_TREE);
+       build_array_type (build_pointer_type (__i_desc_type_node), NULL_TREE);
       __m_desc_array_type =
-       build_array_type (TYPE_POINTER_TO (__m_desc_type_node), NULL_TREE);
+       build_array_type (build_pointer_type (__m_desc_type_node), NULL_TREE);
 
       fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
                                         string_type_node);
@@ -5442,7 +5420,7 @@ init_decl_processing ()
                                         unsigned_type_node);
       fields[3] = build_lang_field_decl (FIELD_DECL,
                                         get_identifier ("points_to"),
-                                        TYPE_POINTER_TO (__t_desc_type_node));
+                                        build_pointer_type (__t_desc_type_node));
       fields[4] = build_lang_field_decl (FIELD_DECL,
                                         get_identifier ("ivars_count"),
                                         integer_type_node);
@@ -5476,7 +5454,7 @@ init_decl_processing ()
       fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("offset"),
                                         integer_type_node);
       fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
-                                        TYPE_POINTER_TO (__t_desc_type_node));
+                                        build_pointer_type (__t_desc_type_node));
       finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2,
                           integer_type_node);
 
@@ -5500,9 +5478,9 @@ init_decl_processing ()
       fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("vindex"),
                                         integer_type_node);
       fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("vcontext"),
-                                        TYPE_POINTER_TO (__t_desc_type_node));
+                                        build_pointer_type (__t_desc_type_node));
       fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("return_type"),
-                                        TYPE_POINTER_TO (__t_desc_type_node));
+                                        build_pointer_type (__t_desc_type_node));
       fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("address"),
                                         build_pointer_type (default_function_type));
       fields[5] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_count"),
@@ -5510,7 +5488,7 @@ init_decl_processing ()
       fields[6] = build_lang_field_decl (FIELD_DECL, get_identifier ("required_parms"),
                                         short_integer_type_node);
       fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_types"),
-                                        build_pointer_type (build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE)));
+                                        build_pointer_type (build_array_type (build_pointer_type (__t_desc_type_node), NULL_TREE)));
       finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7,
                           integer_type_node);
     }
@@ -5751,7 +5729,7 @@ shadow_tag (declspecs)
       if (TYPE_FIELDS (t))
        {
          tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
-                                     NULL_TREE);
+                                     NULL_TREE, NULL_TREE);
          finish_anon_union (decl);
        }
       else
@@ -5792,7 +5770,7 @@ groktypename (typename)
     return typename;
   return grokdeclarator (TREE_VALUE (typename),
                         TREE_PURPOSE (typename),
-                        TYPENAME, 0, NULL_TREE);
+                        TYPENAME, 0, NULL_TREE, NULL_TREE);
 }
 
 /* Decode a declarator in an ordinary declaration or data definition.
@@ -5836,7 +5814,8 @@ start_decl (declarator, declspecs, initialized, raises)
       used_extern_spec = 1;
     }
 
-  decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, raises);
+  decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, raises,
+                        NULL_TREE);
   if (decl == NULL_TREE || decl == void_type_node)
     return NULL_TREE;
 
@@ -6011,13 +5990,25 @@ start_decl (declarator, declspecs, initialized, raises)
          else if (duplicate_decls (decl, field))
            decl = field;
        }
-      
-      /* If it was not explicitly declared `extern',
-        revoke any previous claims of DECL_EXTERNAL.  */
-      if (DECL_THIS_EXTERN (decl) == 0)
-       DECL_EXTERNAL (decl) = 0;
+      else
+       {
+         tree field = check_classfn (context, NULL_TREE, decl);
+         if (field && duplicate_decls (decl, field))
+           decl = field;
+       }
+
+      /* cp_finish_decl sets DECL_EXTERNAL if DECL_IN_AGGR_P is set.  */
       if (DECL_LANG_SPECIFIC (decl))
        DECL_IN_AGGR_P (decl) = 0;
+      if (DECL_USE_TEMPLATE (decl) || CLASSTYPE_USE_TEMPLATE (context))
+       SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+
+      /* Stupid stupid stupid stupid  (jason 7/21/95) */
+      if (pedantic && DECL_EXTERNAL (decl)
+         && ! DECL_TEMPLATE_SPECIALIZATION (decl))
+       cp_pedwarn ("declaration of `%#D' outside of class is not definition",
+                   decl);
+
       pushclass (context, 2);
     }
 
@@ -6164,7 +6155,7 @@ make_temporary_for_reference (decl, ctor_call, init, cleanupp)
     }
 
   TREE_TYPE (tmp_addr) = build_pointer_type (target_type);
-  DECL_INITIAL (decl) = convert (TYPE_POINTER_TO (target_type), tmp_addr);
+  DECL_INITIAL (decl) = convert (build_pointer_type (target_type), tmp_addr);
   TREE_TYPE (DECL_INITIAL (decl)) = type;
   if (TYPE_NEEDS_CONSTRUCTING (target_type))
     {
@@ -6272,7 +6263,7 @@ grok_reference_init (decl, type, init, cleanupp)
              if (TREE_CODE (tmp) == TARGET_EXPR)
                {
                  *cleanupp = build_delete
-                   (TYPE_POINTER_TO (subtype),
+                   (build_pointer_type (subtype),
                     build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0),
                     integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
                  TREE_OPERAND (tmp, 2) = error_mark_node;
@@ -6515,7 +6506,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
            init = digest_init (type, init, (tree *) 0);
          else if (TREE_CODE (init) == CONSTRUCTOR)
            {
-             if (TYPE_NEEDS_CONSTRUCTING (type))
+             if (TYPE_NON_AGGREGATE_CLASS (type))
                {
                  cp_error ("`%D' must be initialized by constructor, not by `{...}'",
                            decl);
@@ -6524,47 +6515,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
              else
                goto dont_use_constructor;
            }
-#if 0
-         /* fix this in `build_functional_cast' instead.
-            Here's the trigger code:
-
-               struct ostream
-               {
-                 ostream ();
-                 ostream (int, char *);
-                 ostream (char *);
-                 operator char *();
-                 ostream (void *);
-                 operator void *();
-                 operator << (int);
-               };
-               int buf_size = 1024;
-               static char buf[buf_size];
-               const char *debug(int i) {
-                 char *b = &buf[0];
-                 ostream o = ostream(buf_size, b);
-                 o << i;
-                 return buf;
-               }
-               */
-
-         else if (TREE_CODE (init) == TARGET_EXPR
-                  && TREE_CODE (TREE_OPERAND (init, 1) == NEW_EXPR))
-           {
-             /* User wrote something like `foo x = foo (args)'  */
-             my_friendly_assert (TREE_CODE (TREE_OPERAND (init, 0)) == VAR_DECL, 150);
-             my_friendly_assert (DECL_NAME (TREE_OPERAND (init, 0)) == NULL_TREE, 151);
-
-             /* User wrote exactly `foo x = foo (args)'  */
-             if (TYPE_MAIN_VARIANT (type) == TREE_TYPE (init))
-               {
-                 init = build (CALL_EXPR, TREE_TYPE (init),
-                               TREE_OPERAND (TREE_OPERAND (init, 1), 0),
-                               TREE_OPERAND (TREE_OPERAND (init, 1), 1), 0);
-                 TREE_SIDE_EFFECTS (init) = 1;
-               }
-           }
-#endif
        }
       else
        {
@@ -6859,11 +6809,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       else if (TREE_STATIC (decl) && type != error_mark_node)
        {
          /* Cleanups for static variables are handled by `finish_file'.  */
-         if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE)
+         if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
+             || TYPE_NEEDS_DESTRUCTOR (type))
            expand_static_init (decl, init);
-         else if (TYPE_NEEDS_DESTRUCTOR (type))
-           static_aggregates = perm_tree_cons (NULL_TREE, decl,
-                                               static_aggregates);
 
          /* Make entry in appropriate vector.  */
          if (flag_gc && type_needs_gc_entry (type))
@@ -6898,7 +6846,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
                {
                  /* XXX: Why don't we use decl here?  */
                  /* Ans: Because it was already expanded? */
-                 if (! expand_decl_cleanup (NULL_TREE, cleanup))
+                 if (! cp_expand_decl_cleanup (NULL_TREE, cleanup))
                    cp_error ("parser lost in parsing declaration of `%D'",
                              decl);
                  /* Cleanup used up here.  */
@@ -6928,7 +6876,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
              /* Store the cleanup, if there was one.  */
              if (cleanup)
                {
-                 if (! expand_decl_cleanup (decl, cleanup))
+                 if (! cp_expand_decl_cleanup (decl, cleanup))
                    cp_error ("parser lost in parsing declaration of `%D'",
                              decl);
                }
@@ -6942,7 +6890,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
         due to initialization of qualified member variable.
         I.e., Foo::x = 10;  */
       {
-       tree context = DECL_CONTEXT (decl);
+       tree context = DECL_REAL_CONTEXT (decl);
        if (context
            && TREE_CODE_CLASS (TREE_CODE (context)) == 't'
            && (TREE_CODE (decl) == VAR_DECL
@@ -7036,13 +6984,14 @@ expand_static_init (decl, init)
       old_cleanups = cleanups_this_call;
       expand_assignment (temp, integer_one_node, 0, 0);
       if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
-         || TREE_CODE (init) == TREE_LIST)
+         || (init && TREE_CODE (init) == TREE_LIST))
        {
          expand_aggr_init (decl, init, 0, 0);
          do_pending_stack_adjust ();
        }
-      else
+      else if (init)
        expand_assignment (decl, init, 0, 0);
+
       /* Cleanup any temporaries needed for the initial value.  */
       expand_cleanups_to (old_cleanups);
       expand_end_cond ();
@@ -7200,12 +7149,12 @@ 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, check, publicp, inlinep)
+           raises, attrlist, check, publicp, inlinep)
      tree ctype, type;
      tree declarator;
      int virtualp;
      enum overload_flags flags;
-     tree quals, raises;
+     tree quals, raises, attrlist;
      int check, publicp, inlinep;
 {
   tree cname, decl;
@@ -7219,7 +7168,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
 
   if (raises)
     {
-      type = build_exception_variant (ctype, type, raises);
+      type = build_exception_variant (type, raises);
       raises = TYPE_RAISES_EXCEPTIONS (type);
     }
   decl = build_lang_decl (FUNCTION_DECL, declarator, type);
@@ -7340,6 +7289,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
              /* avoid creating circularities.  */
              DECL_CHAIN (decl) = NULL_TREE;
            }
+
+         if (attrlist)
+           cplus_decl_attributes (decl, TREE_PURPOSE (attrlist),
+                                  TREE_VALUE (attrlist));
          make_decl_rtl (decl, NULL_PTR, 1);
        }
 
@@ -7390,7 +7343,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
                      type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
                      if (raises)
                        {
-                         type = build_exception_variant (ctype, type, raises);
+                         type = build_exception_variant (type, raises);
                          raises = TYPE_RAISES_EXCEPTIONS (type);
                        }
                      TREE_TYPE (decl) = type;
@@ -7500,6 +7453,7 @@ build_ptrmemfunc_type (type)
   push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
 
   u = make_lang_type (UNION_TYPE);
+  IS_AGGR_TYPE (u) = 0;
   fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type);
   fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier,
                                     delta_type_node);
@@ -7592,12 +7546,12 @@ build_ptrmemfunc_type (type)
 enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
 
 tree
-grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
+grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrlist)
      tree declspecs;
      tree declarator;
      enum decl_context decl_context;
      int initialized;
-     tree raises;
+     tree raises, attrlist;
 {
   RID_BIT_TYPE specbits;
   int nclasses = 0;
@@ -8034,7 +7988,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
       if (return_type == return_dtor)
        type = void_type_node;
       else if (return_type == return_ctor)
-       type = TYPE_POINTER_TO (ctor_return_type);
+       type = build_pointer_type (ctor_return_type);
       else if (return_type == return_conversion)
        type = ctor_return_type;
       else if (current_class_type
@@ -8077,7 +8031,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
   else if (return_type == return_ctor)
     {
       error ("return type specification for constructor invalid");
-      type = TYPE_POINTER_TO (ctor_return_type);
+      type = build_pointer_type (ctor_return_type);
     }
   else if (return_type == return_conversion)
     {
@@ -8244,16 +8198,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
          error ("non-object member `%s' cannot be declared `mutable'", name);
          RIDBIT_RESET (RID_MUTABLE, specbits);
        }
-      else if (constp)
-       {
-         error ("const `%s' cannot be declared `mutable'", name);
-         RIDBIT_RESET (RID_MUTABLE, specbits);
-       }
-      else if (staticp)
-       {
-         error ("static `%s' cannot be declared `mutable'", name);
-         RIDBIT_RESET (RID_MUTABLE, specbits);
-       }
 #if 0
       if (RIDBIT_SETP (RID_TYPEDEF, specbits))
        {
@@ -8400,7 +8344,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
            SIGNATURE_GROKKING_TYPEDEF (current_class_type) = 1;
   
          loc_typedecl =
-           grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE);
+           grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE, NULL_TREE);
 
          if (previous_declspec)
            TREE_CHAIN (previous_declspec) = scanner;
@@ -8819,7 +8763,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                      if (RIDBIT_ANY_SET (tmp_bits))
                        error ("return value type specifier for constructor ignored");
                    }
-                   type = TYPE_POINTER_TO (ctype);
+                   type = build_pointer_type (ctype);
                    if (decl_context == FIELD &&
                        IS_SIGNATURE (current_class_type))
                      {
@@ -9234,6 +9178,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
 
   /* If this is declaring a typedef name, return a TYPE_DECL.  */
 
+  if (RIDBIT_SETP (RID_MUTABLE, specbits))
+    {
+      if (constp)
+       {
+         error ("const `%s' cannot be declared `mutable'", name);
+         RIDBIT_RESET (RID_MUTABLE, specbits);
+       }
+      else if (staticp)
+       {
+         error ("static `%s' cannot be declared `mutable'", name);
+         RIDBIT_RESET (RID_MUTABLE, specbits);
+       }
+    }
+
   if (RIDBIT_SETP (RID_TYPEDEF, specbits))
     {
       tree decl;
@@ -9524,8 +9482,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                       || RIDBIT_SETP (RID_EXTERN, specbits)
                       || ! (funcdef_flag < 0 || inlinep));
            decl = grokfndecl (ctype, type, declarator,
-                              virtualp, flags, quals,
-                              raises, friendp ? -1 : 0, publicp, inlinep);
+                              virtualp, flags, quals, raises, attrlist,
+                              friendp ? -1 : 0, publicp, inlinep);
            if (decl == NULL_TREE)
              return NULL_TREE;
            decl = build_decl_attribute_variant (decl, decl_machine_attr);
@@ -9540,8 +9498,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
            /* All method decls are public, so tell grokfndecl to set
               TREE_PUBLIC, also.  */
            decl = grokfndecl (ctype, type, declarator,
-                              virtualp, flags, quals,
-                              raises, friendp ? -1 : 0, 1, 0);
+                              virtualp, flags, quals, raises, attrlist,
+                              friendp ? -1 : 0, 1, 0);
            if (decl == NULL_TREE)
              return NULL_TREE;
          }
@@ -9634,6 +9592,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
 
            if (staticp || (constp && initialized))
              {
+               /* ANSI C++ Apr '95 wp 9.2 */
+               if (staticp && declarator == current_class_name)
+                 cp_pedwarn ("ANSI C++ forbids static member `%D' with same name as enclosing class",
+                             declarator);
+
                /* C++ allows static class members.
                   All other work for this is done by grokfield.
                   This VAR_DECL is built by build_lang_field_decl.
@@ -9715,8 +9678,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                       && !RIDBIT_SETP (RID_INLINE, specbits)));
 
        decl = grokfndecl (ctype, type, original_name,
-                          virtualp, flags, quals,
-                          raises,
+                          virtualp, flags, quals, raises, attrlist,
                           processing_template_decl ? 0 : friendp ? 2 : 1,
                           publicp, inlinep);
        if (decl == NULL_TREE)
@@ -9789,8 +9751,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
            DECL_CONTEXT (decl) = ctype;
            if (staticp == 1)
              {
-               cp_error ("static member `%D' re-declared as static",
-                         decl);
+               cp_pedwarn ("static member `%D' re-declared as static", decl);
                staticp = 0;
                RIDBIT_RESET (RID_STATIC, specbits);
              }
@@ -9799,10 +9760,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                cp_error ("static member `%D' declared `register'", decl);
                RIDBIT_RESET (RID_REGISTER, specbits);
              }
-           if (RIDBIT_SETP (RID_EXTERN, specbits))
+           if (RIDBIT_SETP (RID_EXTERN, specbits) && pedantic)
              {
-               cp_error ("cannot explicitly declare member `%#D' to have extern linkage",
-                         decl);
+               cp_pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
+                           decl);
                RIDBIT_RESET (RID_EXTERN, specbits);
              }
          }
@@ -10005,7 +9966,8 @@ grokparms (first_parm, funcdef_flag)
                  /* @@ May need to fetch out a `raises' here.  */
                  decl = grokdeclarator (TREE_VALUE (decl),
                                         TREE_PURPOSE (decl),
-                                        PARM, init != NULL_TREE, NULL_TREE);
+                                        PARM, init != NULL_TREE,
+                                        NULL_TREE, NULL_TREE);
                  if (! decl)
                    continue;
                  type = TREE_TYPE (decl);
@@ -11130,8 +11092,8 @@ grok_enum_decls (type, decl)
    @@ something we had previously.  */
 
 int
-start_function (declspecs, declarator, raises, pre_parsed_p)
-     tree declarator, declspecs, raises;
+start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
+     tree declspecs, declarator, raises, attrs;
      int pre_parsed_p;
 {
   tree decl1, olddecl;
@@ -11162,6 +11124,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
   protect_list = NULL_TREE;
   current_base_init_list = NULL_TREE;
   current_member_init_list = NULL_TREE;
+  ctor_label = dtor_label = NULL_TREE;
 
   clear_temp_name ();
 
@@ -11236,7 +11199,8 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
     }
   else
     {
-      decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, raises);
+      decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, raises,
+                             NULL_TREE);
       /* If the declarator is not suitable for a function definition,
         cause a syntax error.  */
       if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0;
@@ -11311,7 +11275,10 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
        TREE_TYPE (decl1)
          = build_function_type (void_type_node,
                                 TYPE_ARG_TYPES (TREE_TYPE (decl1)));
-      DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, TREE_TYPE (fntype));
+      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))
@@ -11445,6 +11412,8 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
 
   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
@@ -11465,9 +11434,15 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
        restype = integer_type_node;
     }
   if (DECL_RESULT (decl1) == NULL_TREE)
-    DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, restype);
+    {
+      DECL_RESULT (decl1)
+       = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
+      TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (restype);
+      TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (restype);
+    }
 
-  if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1)))
+  if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1))
+      && DECL_LANGUAGE (decl1) == lang_cplusplus)
     {
       dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
       ctor_label = NULL_TREE;
@@ -11487,6 +11462,30 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
   return 1;
 }
 \f
+void
+expand_start_early_try_stmts ()
+{
+  rtx insns;
+  start_sequence ();
+  expand_start_try_stmts ();
+  insns = get_insns ();
+  end_sequence ();
+  store_in_parms (insns);
+}
+
+void
+store_in_parms (insns)
+     rtx insns;
+{
+  rtx last_parm_insn;
+
+  last_parm_insn = get_first_nonparm_insn ();
+  if (last_parm_insn == NULL_RTX)
+    emit_insns (insns);
+  else
+    emit_insns_before (insns, previous_insn (last_parm_insn));
+}
+
 /* Store the parameter declarations into the current function declaration.
    This is called after parsing the parameter declarations, before
    digesting the body of the function.
@@ -11576,7 +11575,7 @@ store_parm_decls ()
              if (cleanup)
                {
                  expand_decl (parm);
-                 if (! expand_decl_cleanup (parm, cleanup))
+                 if (! cp_expand_decl_cleanup (parm, cleanup))
                    cp_error ("parser lost in parsing declaration of `%D'",
                              parm);
                  parms_have_cleanups = 1;
@@ -11626,7 +11625,7 @@ store_parm_decls ()
   if (flag_gc)
     {
       maybe_gc_cleanup = build_tree_list (NULL_TREE, error_mark_node);
-      if (! expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup))
+      if (! cp_expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup))
        cp_error ("parser lost in parsing declaration of `%D'", fndecl);
     }
 
@@ -11648,6 +11647,26 @@ store_parm_decls ()
        output_builtin_tdesc_entries ();
 #endif
     }
+
+  /* Take care of exception handling things. */
+  if (flag_handle_exceptions)
+    {
+      rtx insns;
+      start_sequence ();
+
+      /* Mark the start of a stack unwinder if we need one.  */
+      start_eh_unwinder ();
+
+      /* Do the starting of the exception specifications, if we have any.  */
+      if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
+       expand_start_eh_spec ();
+
+      insns = get_insns ();
+      end_sequence ();
+
+      if (insns)
+       store_in_parms (insns);
+    }
 }
 
 /* Bind a name and initialization to the return value of
@@ -11722,7 +11741,7 @@ finish_function (lineno, call_poplevel, nested)
 {
   register tree fndecl = current_function_decl;
   tree fntype, ctype = NULL_TREE;
-  rtx head, last_parm_insn, mark;
+  rtx last_parm_insn, insns;
   /* Label to use if this function is supposed to return a value.  */
   tree no_return_label = NULL_TREE;
   tree decls = NULL_TREE;
@@ -11784,12 +11803,9 @@ finish_function (lineno, call_poplevel, nested)
 
          /* If this destructor is empty, then we don't need to check
             whether `this' is NULL in some cases.  */
-         mark = get_last_insn ();
-         last_parm_insn = get_first_nonparm_insn ();
-
          if ((flag_this_is_variable & 1) == 0)
            ok_to_optimize_dtor = 1;
-         else if (mark == last_parm_insn)
+         else if (get_last_insn () == get_first_nonparm_insn ())
            ok_to_optimize_dtor
              = (n_baseclasses == 0
                 || (n_baseclasses == 1
@@ -11854,8 +11870,8 @@ finish_function (lineno, call_poplevel, nested)
                {
                  if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
                    {
-                     tree ptr = convert_pointer_to_vbase (vbases, current_class_decl);
-                     expand_expr_stmt (build_delete (TYPE_POINTER_TO (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));
                    }
@@ -11879,7 +11895,7 @@ finish_function (lineno, call_poplevel, nested)
        exprstmt =
          build_method_call
            (build_indirect_ref
-            (build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type),
+            (build1 (NOP_EXPR, build_pointer_type (current_class_type),
                      error_mark_node),
              NULL_PTR),
             ansi_opname[(int) DELETE_EXPR],
@@ -11907,12 +11923,8 @@ finish_function (lineno, call_poplevel, nested)
 
       /* Back to the top of destructor.  */
       /* Dont execute destructor code if `this' is NULL.  */
-      mark = get_last_insn ();
-      last_parm_insn = get_first_nonparm_insn ();
-      if (last_parm_insn == NULL_RTX)
-       last_parm_insn = mark;
-      else
-       last_parm_insn = previous_insn (last_parm_insn);
+
+      start_sequence ();
 
       /* Make all virtual function table pointers in non-virtual base
         classes point to CURRENT_CLASS_TYPE's virtual function
@@ -11926,8 +11938,18 @@ finish_function (lineno, call_poplevel, nested)
                                  current_class_decl, integer_zero_node, 1);
          expand_start_cond (cond, 0);
        }
-      if (mark != get_last_insn ())
-       reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
+
+      insns = get_insns ();
+      end_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);
+
+      emit_insns_after (insns, last_parm_insn);
+
       if (! ok_to_optimize_dtor)
        expand_end_cond ();
     }
@@ -11981,11 +12003,7 @@ finish_function (lineno, call_poplevel, nested)
 
       CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
 
-      /* must keep the first insn safe.  */
-      head = get_insns ();
-
-      /* this note will come up to the top with us.  */
-      mark = get_last_insn ();
+      start_sequence ();
 
       if (flag_this_is_variable > 0)
        {
@@ -12008,6 +12026,9 @@ finish_function (lineno, call_poplevel, nested)
          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.
@@ -12016,12 +12037,11 @@ finish_function (lineno, call_poplevel, nested)
         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 = mark;
+       last_parm_insn = get_last_insn ();
       else
        last_parm_insn = previous_insn (last_parm_insn);
 
-      if (mark != get_last_insn ())
-       reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
+      emit_insns_after (insns, last_parm_insn);
 
       end_protect_partials ();
 
@@ -12118,7 +12138,7 @@ finish_function (lineno, call_poplevel, nested)
   expand_function_end (input_filename, lineno, 1);
 
   if (flag_handle_exceptions)
-    expand_exception_blocks();
+    expand_exception_blocks ();
 
   /* This must come after expand_function_end because cleanups might
      have declarations (from inline functions) that need to go into
@@ -12259,7 +12279,8 @@ tree
 start_method (declspecs, declarator, raises)
      tree declarator, declspecs, raises;
 {
-  tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, raises);
+  tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, raises,
+                               NULL_TREE);
 
   /* Something too ugly to handle.  */
   if (fndecl == NULL_TREE)
@@ -12430,46 +12451,43 @@ void
 hack_incomplete_structures (type)
      tree type;
 {
-  tree decl;
+  tree *list;
 
-  if (current_binding_level->n_incomplete == 0)
+  if (current_binding_level->incomplete == NULL_TREE)
     return;
 
   if (!type) /* Don't do this for class templates.  */
     return;
 
-  for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl))
-    if (TREE_TYPE (decl) == type
-       || (TREE_TYPE (decl)
-           && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
-           && TREE_TYPE (TREE_TYPE (decl)) == type))
-      {
-       if (TREE_CODE (decl) == TYPE_DECL)
-         layout_type (TREE_TYPE (decl));
-       else
-         {
-           int toplevel = toplevel_bindings_p ();
-           if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
-               && TREE_TYPE (TREE_TYPE (decl)) == type)
-             layout_type (TREE_TYPE (decl));
-           layout_decl (decl, 0);
-           rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
-           if (! toplevel)
-             {
-               tree cleanup;
-               expand_decl (decl);
-               cleanup = maybe_build_cleanup (decl);
-               expand_decl_init (decl);
-               if (! expand_decl_cleanup (decl, cleanup))
-                 cp_error ("parser lost in parsing declaration of `%D'",
-                           decl);
-             }
-         }
-       /*
-       my_friendly_assert (current_binding_level->n_incomplete > 0, 164);
-       */
-       --current_binding_level->n_incomplete;
-      }
+  for (list = &current_binding_level->incomplete; *list; )
+    {
+      tree decl = TREE_VALUE (*list);
+      if (decl && TREE_TYPE (decl) == type
+         || (TREE_TYPE (decl)
+             && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+             && TREE_TYPE (TREE_TYPE (decl)) == type))
+       {
+         int toplevel = toplevel_bindings_p ();
+         if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+             && TREE_TYPE (TREE_TYPE (decl)) == type)
+           layout_type (TREE_TYPE (decl));
+         layout_decl (decl, 0);
+         rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
+         if (! toplevel)
+           {
+             tree cleanup;
+             expand_decl (decl);
+             cleanup = maybe_build_cleanup (decl);
+             expand_decl_init (decl);
+             if (! cp_expand_decl_cleanup (decl, cleanup))
+               cp_error ("parser lost in parsing declaration of `%D'",
+                         decl);
+           }
+         *list = TREE_CHAIN (*list);
+       }
+      else
+       list = &TREE_CHAIN (*list);
+    }
 }
 
 /* Nonzero if presently building a cleanup.  Needed because
@@ -12620,13 +12638,20 @@ revert_static_member_fn (decl, fn, argtypes)
   tree function = fn ? *fn : TREE_TYPE (*decl);
   tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function);
 
+  if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (args))))
+    cp_error ("static member function `%#D' declared const", *decl);
+  if (TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (args))))
+    cp_error ("static member function `%#D' declared volatile", *decl);
+
   args = TREE_CHAIN (args);
   tmp = build_function_type (TREE_TYPE (function), args);
   tmp = build_type_variant (tmp, TYPE_READONLY (function),
                            TYPE_VOLATILE (function));
-  tmp = build_exception_variant (TYPE_METHOD_BASETYPE (function), tmp,
+  tmp = build_exception_variant (tmp,
                                 TYPE_RAISES_EXCEPTIONS (function));
   TREE_TYPE (*decl) = tmp;
+  if (DECL_ARGUMENTS (*decl))
+    DECL_ARGUMENTS (*decl) = TREE_CHAIN (DECL_ARGUMENTS (*decl));
   DECL_STATIC_FUNCTION_P (*decl) = 1;
   if (fn)
     *fn = tmp;
index 349a162..0824c13 100644 (file)
@@ -30,6 +30,9 @@ enum decl_context
   MEMFUNCDEF                   /* Member function definition */
 };
 
+/* We need this in here to get the decl_context definition.  */
+extern tree grokdeclarator                     PROTO((tree, tree, enum decl_context, int, tree, tree));
+
 /* C++: Keep these around to reduce calls to `get_identifier'.
    Identifiers for `this' in member functions and the auto-delete
    parameter for destructors.  */
index c95bb59..7a3f7d5 100644 (file)
@@ -38,7 +38,6 @@ Boston, MA 02111-1307, USA.  */
 #include "output.h"
 #include "defaults.h"
 
-extern tree grokdeclarator ();
 extern tree get_file_function_name ();
 extern tree cleanups_this_call;
 static void grok_function_init ();
@@ -677,7 +676,7 @@ grok_method_quals (ctype, function, quals)
                                     ? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
                                     : TYPE_ARG_TYPES (fntype)));
   if (raises)
-    fntype = build_exception_variant (ctype, fntype, raises);
+    fntype = build_exception_variant (fntype, raises);
 
   TREE_TYPE (function) = fntype;
   return ctype;
@@ -719,8 +718,11 @@ warn_if_unknown_interface (decl)
       int sl = lineno;
       char *sf = input_filename;
 
-      lineno = til->line;
-      input_filename = til->file;
+      if (til)
+       {
+         lineno = til->line;
+         input_filename = til->file;
+       }
       cp_warning ("template `%#D' instantiated in file without #pragma interface",
                  decl);
       lineno = sl;
@@ -864,6 +866,8 @@ grokclassfn (ctype, cname, function, flags, quals)
   tree arg_types;
   tree parm;
   tree qualtype;
+  tree fntype = TREE_TYPE (function);
+  tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
 
   if (fn_name == NULL_TREE)
     {
@@ -959,8 +963,13 @@ grokclassfn (ctype, cname, function, flags, quals)
       /* This is the same chain as DECL_ARGUMENTS (...).  */
       TREE_CHAIN (last_function_parms) = parm;
 
-      TREE_TYPE (function) = build_cplus_method_type (qualtype, void_type_node,
-                                                     arg_types);
+      fntype = build_cplus_method_type (qualtype, void_type_node,
+                                       arg_types);
+      if (raises)
+       {
+         fntype = build_exception_variant (fntype, raises);
+       }
+      TREE_TYPE (function) = fntype;
       TYPE_HAS_DESTRUCTOR (ctype) = 1;
     }
   else
@@ -971,10 +980,14 @@ grokclassfn (ctype, cname, function, flags, quals)
        {
          arg_types = hash_tree_chain (integer_type_node,
                                       TREE_CHAIN (arg_types));
-         TREE_TYPE (function)
-           = build_cplus_method_type (qualtype,
-                                      TREE_TYPE (TREE_TYPE (function)),
-                                      arg_types);
+         fntype = build_cplus_method_type (qualtype,
+                                           TREE_TYPE (TREE_TYPE (function)),
+                                           arg_types);
+         if (raises)
+           {
+             fntype = build_exception_variant (fntype, raises);
+           }
+         TREE_TYPE (function) = fntype;
          arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
        }
 
@@ -982,7 +995,7 @@ grokclassfn (ctype, cname, function, flags, quals)
 
       if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
        /* Only true for static member functions.  */
-       these_arg_types = hash_tree_chain (TYPE_POINTER_TO (qualtype),
+       these_arg_types = hash_tree_chain (build_pointer_type (qualtype),
                                           arg_types);
 
       DECL_ASSEMBLER_NAME (function)
@@ -1213,7 +1226,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
    really a member of the class (CTYPE) it is supposed to belong to.
    CNAME is the same here as it is for grokclassfn above.  */
 
-void
+tree
 check_classfn (ctype, cname, function)
      tree ctype, cname, function;
 {
@@ -1229,8 +1242,7 @@ check_classfn (ctype, cname, function)
       end = TREE_VEC_END (method_vec);
 
       /* First suss out ctors and dtors.  */
-      if (*methods
-         && (fn_name == cname || fn_name == DECL_NAME (*methods)))
+      if (*methods && fn_name == DECL_NAME (*methods))
        goto got_it;
 
       while (++methods != end)
@@ -1242,14 +1254,14 @@ check_classfn (ctype, cname, function)
              while (fndecl)
                {
                  if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl))
-                   return;
+                   return fndecl;
 #if 0
                  /* This should work, but causes libg++ to fail
                     make check-tFix. */
                  /* 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))
-                   return;
+                   return fndecl;
 #else
                  if (DECL_NAME (function) == DECL_NAME (fndecl))
                    {
@@ -1265,7 +1277,12 @@ check_classfn (ctype, cname, function)
                      if (comptypes (TREE_TYPE (TREE_TYPE (function)),
                                     TREE_TYPE (TREE_TYPE (fndecl)), 1)
                          && compparms (p1, p2, 3))
-                       return;
+                       {
+                         if (DECL_STATIC_FUNCTION_P (fndecl)
+                             && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
+                           revert_static_member_fn (&function, NULL, NULL);
+                         return fndecl;
+                       }
                    }
 #endif
                  fndecl = DECL_CHAIN (fndecl);
@@ -1276,8 +1293,15 @@ check_classfn (ctype, cname, function)
     }
 
   if (methods != end)
-    cp_error ("argument list for `%#D' does not match any in class `%T'",
-             function, ctype);
+    {
+      tree fndecl = *methods;
+      cp_error ("prototype for `%#D' does not match any in class `%T'",
+               function, ctype);
+      cp_error_at ("candidate%s: %+#D", DECL_CHAIN (fndecl) ? "s are" : " is",
+                  fndecl);
+      while (fndecl = DECL_CHAIN (fndecl), fndecl)
+       cp_error_at ("                %#D", fndecl);
+    }
   else
     {
       methods = 0;
@@ -1288,6 +1312,7 @@ check_classfn (ctype, cname, function)
   /* If we did not find the method in the class, add it to
      avoid spurious errors.  */
   add_method (ctype, methods, function);
+  return NULL_TREE;
 }
 
 /* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
@@ -1311,8 +1336,8 @@ check_classfn (ctype, cname, function)
    CHANGES TO CODE IN `start_method'.  */
 
 tree
-grokfield (declarator, declspecs, raises, init, asmspec_tree)
-     tree declarator, declspecs, raises, init, asmspec_tree;
+grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
+     tree declarator, declspecs, raises, init, asmspec_tree, attrlist;
 {
   register tree value;
   char *asmspec = 0;
@@ -1337,7 +1362,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
       && TREE_CHAIN (init) == NULL_TREE)
        init = NULL_TREE;
 
-  value = grokdeclarator (declarator, declspecs, FIELD, init != 0, raises);
+  value = grokdeclarator (declarator, declspecs, FIELD, init != 0,
+                         raises, attrlist);
   if (! value)
     return value; /* friend or constructor went bad.  */
 
@@ -1509,6 +1535,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
     }
   if (TREE_CODE (value) == FUNCTION_DECL)
     {
+      check_default_args (value);
       if (DECL_CHAIN (value) != NULL_TREE)
        {
          /* Need a fresh node here so that we don't get circularity
@@ -1551,7 +1578,8 @@ tree
 grokbitfield (declarator, declspecs, width)
      tree declarator, declspecs, width;
 {
-  register tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL_TREE);
+  register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
+                                       0, NULL_TREE, NULL_TREE);
 
   if (! value) return NULL_TREE; /* friends went bad.  */
 
@@ -1754,7 +1782,7 @@ groktypefield (declspecs, parmlist)
 
  found:
   decl = grokdeclarator (build_parse_node (CALL_EXPR, type_id, parmlist, NULL_TREE),
-                        declspecs, FIELD, 0, NULL_TREE);
+                        declspecs, FIELD, 0, NULL_TREE, NULL_TREE);
   if (decl == NULL_TREE)
     return NULL_TREE;
 
@@ -1797,7 +1825,8 @@ tree
 grokoptypename (declspecs, declarator)
      tree declspecs, declarator;
 {
-  tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE);
+  tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0,
+                          NULL_TREE, NULL_TREE);
   return build_typename_overload (t);
 }
 
@@ -2037,7 +2066,7 @@ constructor_name (thing)
 void
 setup_vtbl_ptr ()
 {
-  extern rtx base_init_expr;
+  extern tree base_init_expr;
 
   if (base_init_expr == 0
       && DECL_CONSTRUCTOR_P (current_function_decl))
@@ -2199,6 +2228,11 @@ finish_anon_union (anon_union_decl)
       if (TREE_CODE (field) != FIELD_DECL)
        continue;
 
+      if (TREE_PRIVATE (field))
+       cp_pedwarn_at ("private member `%#D' in anonymous union", field);
+      else if (TREE_PROTECTED (field))
+       cp_pedwarn_at ("protected member `%#D' in anonymous union", field);
+
       decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
       /* tell `pushdecl' that this is not tentative.  */
       DECL_INITIAL (decl) = error_mark_node;
@@ -2449,7 +2483,9 @@ static void
 mark_vtable_entries (decl)
      tree decl;
 {
-  tree entries = TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)));
+  tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl));
+
+  skip_rtti_stuff (&entries);
 
   for (; entries; entries = TREE_CHAIN (entries))
     {
@@ -2757,7 +2793,7 @@ import_export_inline (decl)
   else if (DECL_FUNCTION_MEMBER_P (decl))
     {
       tree ctype = DECL_CLASS_CONTEXT (decl);
-      if (CLASSTYPE_INTERFACE_KNOWN (ctype))
+      if (CLASSTYPE_INTERFACE_KNOWN (ctype) && ! DECL_ARTIFICIAL (decl))
        {
          DECL_NOT_REALLY_EXTERN (decl)
            = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
@@ -2874,7 +2910,10 @@ finish_file ()
     goto mess_up;
 
   fnname = get_file_function_name ('D');
-  start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0);
+  start_function (void_list_node,
+                 build_parse_node (CALL_EXPR, fnname, void_list_node,
+                                   NULL_TREE),
+                 NULL_TREE, NULL_TREE, 0);
   fnname = DECL_ASSEMBLER_NAME (current_function_decl);
   store_parm_decls ();
 
@@ -2900,7 +2939,7 @@ finish_file ()
          else
            {
              mark_addressable (decl);
-             temp = build1 (ADDR_EXPR, TYPE_POINTER_TO (type), decl);
+             temp = build1 (ADDR_EXPR, build_pointer_type (type), decl);
            }
          temp = build_delete (TREE_TYPE (temp), temp,
                               integer_two_node, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
@@ -2931,7 +2970,10 @@ finish_file ()
   if (needs_messing_up)
     {
       fnname = get_file_function_name ('I');
-      start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0);
+      start_function (void_list_node,
+                     build_parse_node (CALL_EXPR, fnname,
+                                       void_list_node, NULL_TREE),
+                     NULL_TREE, NULL_TREE, 0);
       fnname = DECL_ASSEMBLER_NAME (current_function_decl);
       store_parm_decls ();
 
@@ -2973,40 +3015,6 @@ finish_file ()
              DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
              DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
 
-#if 0
-             if (init)
-               {
-                 if (TREE_CODE (init) == VAR_DECL)
-                   {
-                     /* This behavior results when there are
-                        multiple declarations of an aggregate,
-                        the last of which defines it.  */
-                     if (DECL_RTL (init) == DECL_RTL (decl))
-                       {
-                         my_friendly_assert (DECL_INITIAL (decl) == error_mark_node
-                                 || (TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
-                                     && CONSTRUCTOR_ELTS (DECL_INITIAL (decl)) == NULL_TREE),
-                                             199);
-                         init = DECL_INITIAL (init);
-                         if (TREE_CODE (init) == CONSTRUCTOR
-                             && CONSTRUCTOR_ELTS (init) == NULL_TREE)
-                           init = NULL_TREE;
-                       }
-                     else if (TREE_TYPE (decl) == TREE_TYPE (init))
-                       {
-#if 1
-                         my_friendly_abort (200);
-#else
-                         /* point to real decl's rtl anyway.  */
-                         DECL_RTL (init) = DECL_RTL (decl);
-                         my_friendly_assert (DECL_INITIAL (decl) == error_mark_node,
-                                             201);
-                         init = DECL_INITIAL (init);
-#endif                         /* 1 */
-                       }
-                   }
-               }
-#endif                         /* 0 */
              if (IS_AGGR_TYPE (TREE_TYPE (decl))
                  || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
                expand_aggr_init (decl, init, 0, 0);
@@ -3030,7 +3038,16 @@ finish_file ()
                  /* a `new' expression at top level.  */
                  expand_expr (decl, const0_rtx, VOIDmode, 0);
                  free_temp_slots ();
-                 expand_aggr_init (build_indirect_ref (decl, NULL_PTR), init, 0, 0);
+                 if (TREE_CODE (init) == TREE_VEC)
+                   {
+                     expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
+                                                   TREE_VEC_ELT (init, 1),
+                                                   TREE_VEC_ELT (init, 2), 0),
+                                  const0_rtx, VOIDmode, 0);
+                     free_temp_slots ();
+                   }
+                 else
+                   expand_aggr_init (build_indirect_ref (decl, NULL_PTR), init, 0, 0);
                }
            }
          else if (decl == error_mark_node)
@@ -3053,6 +3070,8 @@ finish_file ()
       assemble_constructor (IDENTIFIER_POINTER (fnname));
     }
 
+  expand_builtin_throw ();
+
   permanent_allocation (1);
 
   /* Done with C language context needs.  */
@@ -3460,7 +3479,10 @@ tree
 do_class_using_decl (decl)
      tree decl;
 {
-  return error_mark_node;
+  tree type;
+
+  /* Ignore for now, unimplemented. */
+  return NULL_TREE;
 }
 
 void
@@ -3468,3 +3490,22 @@ do_using_directive (namespace)
      tree namespace;
 {
 }
+
+void
+check_default_args (x)
+     tree x;
+{
+  tree arg = TYPE_ARG_TYPES (TREE_TYPE (x));
+  int saw_def = 0, i = 0 - (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE);
+  for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i)
+    {
+      if (TREE_PURPOSE (arg))
+       saw_def = 1;
+      else if (saw_def)
+       {
+         cp_error ("default argument missing for parameter %P of `%#D'",
+                   i, x);
+         break;
+       }
+    }
+}
index 6e84e43..f36b0e1 100644 (file)
@@ -43,11 +43,11 @@ extern int   cp_line_of PROTO((tree));
 
 #define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
 
-#define NARGS 3
-#define arglist a1, a2, a3
-#define arglist_dcl HOST_WIDE_INT a1, a2, a3;
-#define ARGSINIT args[0] = a1; args[1] = a2; args[2] = a3;
-#define ARGSLIST args[0], args[1], args[2]
+#define NARGS 4
+#define arglist a1, a2, a3, a4
+#define arglist_dcl HOST_WIDE_INT a1, a2, a3, a4;
+#define ARGSINIT args[0] = a1; args[1] = a2; args[2] = a3; args[3] = a4;
+#define ARGSLIST args[0], args[1], args[2], args[3]
 
 static void
 cp_thing (errfn, atarg1, format, arglist)
index db93c63..4eb196e 100644 (file)
@@ -35,6 +35,7 @@ typedef char* cp_printer ();
 #define O op_as_string
 #define P parm_as_string
 #define T type_as_string
+#define V cv_as_string
 
 #define _ (cp_printer *) 0
 cp_printer * cp_printers[256] =
@@ -45,7 +46,7 @@ cp_printer * cp_printers[256] =
   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */
   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */
   _, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */
-  P, _, _, _, T, _, _, _, _, _, _, _, _, _, _, _, /* 0x50 */
+  P, _, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */
   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */
 };
@@ -56,6 +57,7 @@ cp_printer * cp_printers[256] =
 #undef O
 #undef P
 #undef T
+#undef V
 #undef _
 
 #define obstack_chunk_alloc xmalloc
@@ -269,7 +271,7 @@ dump_aggr_type (t, v)
   
   name = TYPE_NAME (t);
 
-  if (DECL_CONTEXT (name))
+  if (name && DECL_CONTEXT (name))
     {
       /* FUNCTION_DECL or RECORD_TYPE */
       dump_decl (DECL_CONTEXT (name), 0);
@@ -277,10 +279,10 @@ dump_aggr_type (t, v)
     }
 
   /* kludge around weird behavior on g++.brendan/line1.C */
-  if (TREE_CODE (name) != IDENTIFIER_NODE)
+  if (name && TREE_CODE (name) != IDENTIFIER_NODE)
     name = DECL_NAME (name);
 
-  if (ANON_AGGRNAME_P (name))
+  if (name == 0 || ANON_AGGRNAME_P (name))
     {
       OB_PUTS ("{anonymous");
       if (!v)
@@ -512,6 +514,9 @@ ident_fndecl (t)
 {
   tree n = lookup_name (t, 0);
 
+  if (n == NULL_TREE)
+    return NULL_TREE;
+
   if (TREE_CODE (n) == FUNCTION_DECL)
     return n;
   else if (TREE_CODE (n) == TREE_LIST
@@ -643,26 +648,30 @@ dump_decl (t, v)
       /* These special cases are duplicated here so that other functions
         can feed identifiers to cp_error and get them demangled properly. */
     case IDENTIFIER_NODE:
-      if (DESTRUCTOR_NAME_P (t))
-       {
-         OB_PUTC ('~');
-         dump_decl (DECL_NAME (ident_fndecl (t)), 0);
-       }
-      else if (IDENTIFIER_TYPENAME_P (t))
-       {
-         OB_PUTS ("operator ");
-         /* Not exactly IDENTIFIER_TYPE_VALUE.  */
-         dump_type (TREE_TYPE (t), 0);
-         break;
-       }
-      else if (IDENTIFIER_OPNAME_P (t))
-       {
-         char *name_string = operator_name_string (t);
-         OB_PUTS ("operator ");
-         OB_PUTCP (name_string);
-       }
-      else
-       OB_PUTID (t);
+      { tree f;
+       if (DESTRUCTOR_NAME_P (t)
+           && (f = ident_fndecl (t))
+           && DECL_LANGUAGE (f) == lang_cplusplus)
+         {
+           OB_PUTC ('~');
+           dump_decl (DECL_NAME (f), 0);
+         }
+       else if (IDENTIFIER_TYPENAME_P (t))
+         {
+           OB_PUTS ("operator ");
+           /* Not exactly IDENTIFIER_TYPE_VALUE.  */
+           dump_type (TREE_TYPE (t), 0);
+           break;
+         }
+       else if (IDENTIFIER_OPNAME_P (t))
+         {
+           char *name_string = operator_name_string (t);
+           OB_PUTS ("operator ");
+           OB_PUTCP (name_string);
+         }
+       else
+         OB_PUTID (t);
+      }
       break;
 
     case FUNCTION_DECL:
@@ -785,7 +794,7 @@ dump_function_decl (t, v)
        parmtypes = TREE_CHAIN (parmtypes);
     }
 
-  if (DESTRUCTOR_NAME_P (name))
+  if (DESTRUCTOR_NAME_P (name) && DECL_LANGUAGE (t) == lang_cplusplus)
     parmtypes = TREE_CHAIN (parmtypes);
   
   dump_function_name (t);
@@ -824,7 +833,8 @@ dump_function_name (t)
 
   /* There ought to be a better way to find out whether or not something is
      a destructor.  */
-  if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t)))
+  if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t))
+      && DECL_LANGUAGE (t) == lang_cplusplus)
     {
       OB_PUTC ('~');
       dump_decl (name, 0);
@@ -1456,3 +1466,17 @@ args_as_string (p, v)
 
   return type_as_string (p, v);
 }
+
+char *
+cv_as_string (p, v)
+     tree p;
+     int v;
+{
+  OB_INIT ();
+
+  dump_readonly_or_volatile (p, before);
+
+  OB_FINISH ();
+
+  return (char *)obstack_base (&scratch_obstack);
+}
index 261bf57..51577f8 100644 (file)
@@ -35,121 +35,11 @@ Boston, MA 02111-1307, USA.  */
 tree protect_list;
 
 extern void (*interim_eh_hook) PROTO((tree));
+rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
 
 /* holds the fndecl for __builtin_return_address () */
 tree builtin_return_address_fndecl;
-
-/* Define at your own risk!  */
-#ifndef CROSS_COMPILE
-#ifdef sun
-#ifdef sparc
-#define TRY_NEW_EH
-#endif
-#endif
-#ifdef _IBMR2
-#ifndef __rs6000
-#define __rs6000
-#endif
-#endif
-#ifdef mips
-#ifndef __mips
-#define __mips
-#endif
-#endif
-#ifdef __i386__
-#ifndef __i386
-#define __i386
-#endif
-#endif
-#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm) || defined (__alpha)
-#define TRY_NEW_EH
-#endif
-#endif
-
-#ifndef TRY_NEW_EH
-
-static void
-sorry_no_eh ()
-{
-  static int warned = 0;
-  if (! warned)
-    {
-      sorry ("exception handling not supported");
-      warned = 1;
-    }
-}
-
-void
-expand_exception_blocks ()
-{
-}
-
-void
-start_protect ()
-{
-}
-
-void
-end_protect (finalization)
-     tree finalization;
-{
-}
-
-void
-expand_start_try_stmts ()
-{
-  sorry_no_eh ();
-}
-
-void
-expand_end_try_stmts ()
-{
-}
-
-void
-expand_start_all_catch ()
-{
-}
-
-void
-expand_end_all_catch ()
-{
-}
-
-void
-expand_start_catch_block (declspecs, declarator)
-     tree declspecs, declarator;
-{
-}
-
-void
-expand_end_catch_block ()
-{
-}
-
-void
-init_exception_processing ()
-{
-}
-
-void
-expand_throw (exp)
-     tree exp;
-{
-  sorry_no_eh ();
-}
-
-#else
-
-/* Make 'label' the first numbered label of the current function */
-void
-make_first_label(label)
-     rtx label;
-{
-  if (CODE_LABEL_NUMBER(label) < get_first_label_num())
-    set_new_first_and_last_label_num (CODE_LABEL_NUMBER(label),
-                                     max_label_num());
-}
+tree throw_fndecl;
 
 static int
 doing_eh (do_warn)
@@ -171,16 +61,14 @@ doing_eh (do_warn)
 
 /*
 NO GNEWS IS GOOD GNEWS WITH GARRY GNUS: This version is much closer
-to supporting exception handling as per Stroustrup's 2nd edition.
+to supporting exception handling as per ANSI C++ working draft.
 It is a complete rewrite of all the EH stuff that was here before
        Shortcomings:
-               1. The type of the throw and catch must still match
-                  exactly (no support yet for matching base classes)
-               2. Throw specifications of functions still don't work.
+               1. Throw specifications of functions still don't work.
        Cool Things:
                1. Destructors are called properly :-)
                2. No overhead for the non-exception thrown case.
-               3. Fixing shortcomings 1 and 2 is simple.
+               3. Fixing shortcoming 1 is simple.
                        -Tad Hunt       (tad@mail.csh.rit.edu)
 
 */
@@ -189,10 +77,7 @@ It is a complete rewrite of all the EH stuff that was here before
 
 /* used to cache a call to __builtin_return_address () */
 static tree BuiltinReturnAddress;
-
-
-
-
+     
 
 #include <stdio.h>
 
@@ -206,9 +91,9 @@ output_exception_table_entry (file, start_label, end_label, eh_label)
 {
   char label[100];
 
-  assemble_integer (start_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
-  assemble_integer (end_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
-  assemble_integer (eh_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
+  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);
   putc ('\n', file);           /* blank line */
 }
    
@@ -269,7 +154,7 @@ exception_section ()
   if (flag_pic)
     data_section ();
   else
-#if defined(__rs6000)
+#if defined(TARGET_POWERPC) /* are we on a __rs6000? */
     data_section ();
 #else
     readonly_data_section ();
@@ -336,24 +221,11 @@ exception_section ()
 
      Since we don't want to generate the catch block inline with the
      regular flow of the function, we need to have some way of doing
-     so.  Luckily, we have a couple of routines "get_last_insn ()" and
-     "set_last_insn ()" provided.  When the start of a catch block is
-     encountered, we save a pointer to the last insn generated.  After
-     the catch block is generated, we save a pointer to the first
-     catch block insn and the last catch block insn with the routines
-     "NEXT_INSN ()" and "get_last_insn ()".  We then set the last insn
-     to be the last insn generated before the catch block, and set the
-     NEXT_INSN (last_insn) to zero.
-
-     Since catch blocks might be nested inside other catch blocks, and
-     we munge the chain of generated insns after the catch block is
-     generated, we need to store the pointers to the last insn
-     generated in a stack, so that when the end of a catch block is
-     encountered, the last insn before the current catch block can be
-     popped and set to be the last insn, and the first and last insns
-     of the catch block just generated can be enqueue'd for output at
-     a later time.
-               
+     so.  Luckily, we can use sequences to defer the catch sections.
+     When the start of a catch block is encountered, we start the
+     sequence.  After the catch block is generated, we end the
+     sequence.
+
      Next we must insure that when the catch block is executed, all
      finalizations for the matching try block have been completed.  If
      any of those finalizations throw an exception, we must call
@@ -379,17 +251,17 @@ extern rtx gen_nop                PROTO(());
    ====================================================================== */
 
 /* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and
-   "set_unexpected ()" after default_conversion. (lib-except.c) */
-static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch;
+   "set_unexpected ()" after default_conversion. (lib-except.c)  */
+static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch, Throw;
 
 /* used to cache __find_first_exception_table_match ()
    for throw (lib-except.c)  */
 static tree FirstExceptionMatch;
 
-/* used to cache a call to __unwind_function () (lib-except.c) */
+/* used to cache a call to __unwind_function () (lib-except.c)  */
 static tree Unwind;
 
-/* holds a ready to emit call to "terminate ()". */
+/* holds a ready to emit call to "terminate ()".  */
 static tree TerminateFunctionCall;
 
 /* ====================================================================== */
@@ -398,7 +270,7 @@ static tree TerminateFunctionCall;
 
 /* data structures for my various quick and dirty stacks and queues
    Eventually, most of this should go away, because I think it can be
-   integrated with stuff already built into the compiler. */
+   integrated with stuff already built into the compiler.  */
 
 /* =================================================================== */
 
@@ -432,17 +304,6 @@ struct ehQueue {
   struct ehNode *head;
   struct ehNode *tail;
 };
-
-struct exceptNode {
-  rtx catchstart;
-  rtx catchend;
-
-  struct exceptNode *chain;
-};
-
-struct exceptStack {
-  struct exceptNode *top;
- };
 /* ========================================================================= */
 
 
@@ -453,18 +314,20 @@ struct exceptStack {
    ========================================================================= */
 
 /* Holds the pc for doing "throw" */
-rtx saved_pc;
+tree saved_pc;
 /* Holds the type of the thing being thrown. */
-rtx saved_throw_type;
+tree saved_throw_type;
 /* Holds the value being thrown.  */
-rtx saved_throw_value;
+tree saved_throw_value;
+
+int throw_used;
 
-rtx throw_label;
+static rtx catch_clauses;
+static first_catch_label;
 
 static struct ehStack ehstack;
 static struct ehQueue ehqueue;
 static struct ehQueue eh_table_output_queue;
-static struct exceptStack exceptstack;
 static struct labelNode *false_label_stack = NULL;
 static struct labelNode *caught_return_label_stack = NULL;
 /* ========================================================================= */
@@ -472,17 +335,10 @@ static struct labelNode *caught_return_label_stack = NULL;
 /* function prototypes */
 static struct ehEntry *pop_eh_entry    PROTO((struct ehStack *stack));
 static void enqueue_eh_entry           PROTO((struct ehQueue *queue, struct ehEntry *entry));
-static void push_except_stmts          PROTO((struct exceptStack *exceptstack,
-                                        rtx catchstart, rtx catchend));
-static int pop_except_stmts            PROTO((struct exceptStack *exceptstack,
-                                        rtx *catchstart, rtx *catchend));
 static rtx push_eh_entry               PROTO((struct ehStack *stack));
 static struct ehEntry *dequeue_eh_entry        PROTO((struct ehQueue *queue));
 static void new_eh_queue               PROTO((struct ehQueue *queue));
 static void new_eh_stack               PROTO((struct ehStack *stack));
-static void new_except_stack           PROTO((struct exceptStack *queue));
-static void push_last_insn             PROTO(());
-static rtx pop_last_insn               PROTO(());
 static void push_label_entry           PROTO((struct labelNode **labelstack, rtx label));
 static rtx pop_label_entry             PROTO((struct labelNode **labelstack));
 static rtx top_label_entry             PROTO((struct labelNode **labelstack));
@@ -532,43 +388,6 @@ top_label_entry (labelstack)
   return (*labelstack)->label;
 }
 
-static void
-push_except_stmts (exceptstack, catchstart, catchend)
-     struct exceptStack *exceptstack;
-     rtx catchstart, catchend;
-{
-  struct exceptNode *newnode = (struct exceptNode*)
-    xmalloc (sizeof (struct exceptNode));
-
-  newnode->catchstart = catchstart;
-  newnode->catchend = catchend;
-  newnode->chain = exceptstack->top;
-
-  exceptstack->top = newnode;
-}
-
-static int
-pop_except_stmts (exceptstack, catchstart, catchend)
-     struct exceptStack *exceptstack;
-     rtx *catchstart, *catchend;
-{
-  struct exceptNode *tempnode;
-
-  if (!exceptstack->top) {
-    *catchstart = *catchend = NULL_RTX;
-    return 0;
-  }
-
-  tempnode = exceptstack->top;
-  exceptstack->top = exceptstack->top->chain;
-
-  *catchstart = tempnode->catchstart;
-  *catchend = tempnode->catchend;
-  free (tempnode);
-
-  return 1;
-}
-
 /* Push to permanent obstack for rtl generation.
    One level only!  */
 static struct obstack *saved_rtl_obstack;
@@ -712,12 +531,34 @@ new_eh_stack (stack)
   stack->top = NULL;
 }
 
+/* cheesyness to save some typing. returns the return value rtx */
+rtx
+do_function_call (func, params, return_type)
+     tree func, params, return_type;
+{
+  tree func_call;
+  func_call = build_function_call (func, params);
+  expand_call (func_call, NULL_RTX, 0);
+  if (return_type != NULL_TREE)
+    return hard_function_value (return_type, func_call);
+  return NULL_RTX;
+}
+
 static void
-new_except_stack (stack)
-     struct exceptStack *stack;
+expand_internal_throw (pc)
+     rtx pc;
 {
-  stack->top = NULL;
+  tree params;
+
+  emit_move_insn (DECL_RTL (saved_pc), pc);
+#ifdef JUMP_TO_THROW
+  emit_indirect_jump (gen_rtx (SYMBOL_REF, Pmode, "__throw"));
+#else
+  do_function_call (Throw, NULL_TREE, NULL_TREE);
+#endif
+  throw_used = 1;
 }
+
 /* ========================================================================= */
 
 void
@@ -740,7 +581,6 @@ extern tree auto_function PROTO((tree, tree, enum built_in_function));
                - Initializing the ehqueue
                - Initializing the eh_table_output_queue
                - Initializing the ehstack
-               - Initializing the exceptstack
 */
 
 void
@@ -752,6 +592,8 @@ init_exception_processing ()
   tree catch_match_fndecl;
   tree find_first_exception_match_fndecl;
   tree unwind_fndecl;
+  tree declspecs;
+  tree d;
 
   /* void (*)() */
   tree PFV = build_pointer_type (build_function_type
@@ -803,10 +645,19 @@ init_exception_processing ()
   unwind_fndecl =
     define_function ("__unwind_function",
                     build_function_type (void_type_node,
-                                         tree_cons (NULL_TREE, ptr_type_node, void_list_node)),
+                                         tree_cons (NULL_TREE, ptr_type_node,
+                                                    void_list_node)),
+                    NOT_BUILT_IN,
+                    pushdecl,
+                    0);
+  throw_fndecl =
+    define_function ("__throw",
+                    build_function_type (void_type_node, void_list_node),
                     NOT_BUILT_IN,
                     pushdecl,
                     0);
+  DECL_EXTERNAL (throw_fndecl) = 0;
+  TREE_PUBLIC (throw_fndecl) = 0;
 
   Unexpected = default_conversion (unexpected_fndecl);
   Terminate = default_conversion (terminate_fndecl);
@@ -815,56 +666,37 @@ init_exception_processing ()
   CatchMatch = default_conversion (catch_match_fndecl);
   FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl);
   Unwind = default_conversion (unwind_fndecl);
+  Throw = default_conversion (throw_fndecl);
   BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl);
 
   TerminateFunctionCall = build_function_call (Terminate, NULL_TREE);
 
   pop_lang_context ();
-  throw_label = gen_label_rtx ();
-#ifdef sparc
-  saved_pc = gen_rtx (REG, Pmode, 16);
-  saved_throw_type = gen_rtx (REG, Pmode, 17);
-  saved_throw_value = gen_rtx (REG, Pmode, 18);
-#endif
-#ifdef __i386
-  saved_pc = gen_rtx (REG, Pmode, 3);
-  saved_throw_type = gen_rtx (REG, Pmode, 4);
-  saved_throw_value = gen_rtx (REG, Pmode, 5);
-#endif
-#ifdef __rs6000
-  saved_pc = gen_rtx (REG, Pmode, 13);
-  saved_throw_type = gen_rtx (REG, Pmode, 14);
-  saved_throw_value = gen_rtx (REG, Pmode, 15);
-#endif
-#ifdef __hppa
-  saved_pc = gen_rtx (REG, Pmode, 5);
-  saved_throw_type = gen_rtx (REG, Pmode, 6);
-  saved_throw_value = gen_rtx (REG, Pmode, 7);
-#endif
-#ifdef __mc68000
-  saved_pc = gen_rtx (REG, Pmode, 10);
-  saved_throw_type = gen_rtx (REG, Pmode, 11);
-  saved_throw_value = gen_rtx (REG, Pmode, 12);
-#endif
-#ifdef __mips
-  saved_pc = gen_rtx (REG, Pmode, 16);
-  saved_throw_type = gen_rtx (REG, Pmode, 17);
-  saved_throw_value = gen_rtx (REG, Pmode, 18);
-#endif
-#ifdef __arm
-  saved_pc = gen_rtx (REG, Pmode, 7);
-  saved_throw_type = gen_rtx (REG, Pmode, 8);
-  saved_throw_value = gen_rtx (REG, Pmode, 9);
-#endif
-#ifdef __alpha
-  saved_pc = gen_rtx (REG, Pmode, 9);
-  saved_throw_type = gen_rtx (REG, Pmode, 10);
-  saved_throw_value = gen_rtx (REG, Pmode, 11);
-#endif
+
   new_eh_queue (&ehqueue);
   new_eh_queue (&eh_table_output_queue);
   new_eh_stack (&ehstack);
-  new_except_stack (&exceptstack);
+
+  declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
+  d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_pc"));
+  d = start_decl (d, declspecs, 0, NULL_TREE);
+  DECL_COMMON (d) = 1;
+  cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
+  saved_pc = lookup_name (get_identifier ("__eh_pc"), 0);
+
+  declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
+  d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_type"));
+  d = start_decl (d, declspecs, 0, NULL_TREE);
+  DECL_COMMON (d) = 1;
+  cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
+  saved_throw_type = lookup_name (get_identifier ("__eh_type"), 0);
+
+  declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
+  d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_value"));
+  d = start_decl (d, declspecs, 0, NULL_TREE);
+  DECL_COMMON (d) = 1;
+  cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
+  saved_throw_value = lookup_name (get_identifier ("__eh_value"), 0);
 }
 
 /* call this to begin a block of unwind protection (ie: when an object is
@@ -872,10 +704,10 @@ init_exception_processing ()
 void
 start_protect ()
 {
-  if (doing_eh (0))
-    {
-      emit_label (push_eh_entry (&ehstack));
-    }
+  if (doing_eh (0))
+    return;
+
+  emit_label (push_eh_entry (&ehstack));
 }
    
 /* call this to end a block of unwind protection.  the finalization tree is
@@ -893,6 +725,12 @@ end_protect (finalization)
   entry = pop_eh_entry (&ehstack);
 
   emit_label (entry->end_label);
+  /* Put in something that takes up space, as otherwise the end
+     address for the EH region could have the exact same address as
+     the outer region, causing us to miss the fact that resuming
+     exception handling with this PC value would be inside the outer
+     region.  */
+  emit_insn (gen_nop ());
 
   entry->finalization = finalization;
 
@@ -903,10 +741,10 @@ end_protect (finalization)
 void
 expand_start_try_stmts ()
 {
-  if (doing_eh (1))
-    {
-      start_protect ();
-    }
+  if (doing_eh (1))
+    return;
+
+  start_protect ();
 }
 
 void
@@ -915,43 +753,6 @@ expand_end_try_stmts ()
   end_protect (integer_zero_node);
 }
 
-struct insn_save_node {
-       rtx last;
-       struct insn_save_node *chain;
- };
-
-static struct insn_save_node *InsnSave = NULL;
-
-
-/* Used to keep track of where the catch blocks start.  */
-static void
-push_last_insn ()
-{
-  struct insn_save_node *newnode = (struct insn_save_node*)
-    xmalloc (sizeof (struct insn_save_node));
-
-  newnode->last = get_last_insn ();
-  newnode->chain = InsnSave;
-  InsnSave = newnode;
-}
-
-/* Use to keep track of where the catch blocks start.  */
-static rtx
-pop_last_insn ()
-{
-  struct insn_save_node *tempnode;
-  rtx temprtx;
-
-  if (!InsnSave) return NULL_RTX;
-
-  tempnode = InsnSave;
-  temprtx = tempnode->last;
-  InsnSave = InsnSave->chain;
-
-  free (tempnode);
-
-  return temprtx;
-}
 
 /* call this to start processing of all the catch blocks. */
 void
@@ -965,19 +766,24 @@ expand_start_all_catch ()
 
   emit_line_note (input_filename, lineno);
   label = gen_label_rtx ();
-  /* The label for the exception handling block we will save.  */
+
+  /* The label for the exception handling block we will save.  This is
+     Lresume, in the documention.  */
   emit_label (label);
   
-  push_label_entry (&caught_return_label_stack, label);
-
-  /* Remember where we started. */
-  push_last_insn ();
-
+  /* Put in something that takes up space, as otherwise the end
+     address for the EH region could have the exact same address as
+     the outer region, causing us to miss the fact that resuming
+     exception handling with this PC value would be inside the outer
+     region.  */
   emit_insn (gen_nop ());
 
-  /* Will this help us not stomp on it? */
-  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
-  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
+  push_label_entry (&caught_return_label_stack, label);
+
+  /* Start a new sequence for all the catch blocks.  We will add this
+     to the gloabl sequence catch_clauses, when we have completed all
+     the handlers in this handler-seq.  */
+  start_sequence ();
 
   while (1)
     {
@@ -990,151 +796,78 @@ expand_start_all_catch ()
       if (entry->finalization == integer_zero_node)
        break;
 
+      /* The below can be optimized away, and we could just fall into the
+        next EH handler, if we are certain they are nested.  */
+      /* Code to throw out to outer context, if we fall off end of the
+        handler.  */
+      expand_internal_throw (gen_rtx (LABEL_REF,
+                                     Pmode,
+                                     entry->end_label));
       free (entry);
     }
-
-  /* This goes when the below moves out of our way.  */
-#if 1
-  label = gen_label_rtx ();
-  emit_jump (label);
-#endif
-  
-  /* All this should be out of line, and saved back in the exception handler
-     block area.  */
-#if 1
-  entry->start_label = entry->exception_handler_label;
-  /* These are saved for the exception table.  */
-  push_rtl_perm ();
-  entry->end_label = gen_label_rtx ();
-  entry->exception_handler_label = gen_label_rtx ();
-  entry->finalization = TerminateFunctionCall;
-  entry->context = current_function_decl;
-  assemble_external (TREE_OPERAND (Terminate, 0));
-  pop_rtl_from_perm ();
-
-  LABEL_PRESERVE_P (entry->start_label) = 1;
-  LABEL_PRESERVE_P (entry->end_label) = 1;
-  LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
-
-  emit_label (entry->end_label);
-
-  enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
-
-  /* After running the finalization, continue on out to the next
-     cleanup, if we have nothing better to do.  */
-  emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, entry->end_label));
-  /* Will this help us not stomp on it? */
-  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
-  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
-  make_first_label(throw_label);
-  emit_jump (throw_label);
-  emit_label (entry->exception_handler_label);
-  expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
-  emit_barrier ();
-#endif
-  emit_label (label);
 }
 
 /* call this to end processing of all the catch blocks. */
 void
 expand_end_all_catch ()
 {
-  rtx catchstart, catchend, last;
-  rtx label;
+  rtx new_catch_clause;
 
   if (! doing_eh (1))
     return;
 
   /* Code to throw out to outer context, if we fall off end of catch
-     handlers.  */
-  emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
-                                    Pmode,
-                                    top_label_entry (&caught_return_label_stack)));
-  make_first_label(throw_label);
-  emit_jump (throw_label);
-
-  /* Find the start of the catch block.  */
-  last = pop_last_insn ();
-  catchstart = NEXT_INSN (last);
-  catchend = get_last_insn ();
-
-  NEXT_INSN (last) = 0;
-  set_last_insn (last);
-
+     handlers.  This is rethrow (Lresume, same id, same obj); in the
+     documentation.  */
+  expand_internal_throw (gen_rtx (LABEL_REF,
+                                 Pmode,
+                                 top_label_entry (&caught_return_label_stack)));
+
+  /* Now we have the complete catch sequence.  */
+  new_catch_clause = get_insns ();
+  end_sequence ();
+  
   /* this level of catch blocks is done, so set up the successful catch jump
      label for the next layer of catch blocks. */
   pop_label_entry (&caught_return_label_stack);
 
-  push_except_stmts (&exceptstack, catchstart, catchend);
+  /* Add the new sequence of catchs to the main one for this
+     function.  */
+  push_to_sequence (catch_clauses);
+  emit_insns (new_catch_clause);
+  catch_clauses = get_insns ();
+  end_sequence ();
   
   /* Here we fall through into the continuation code.  */
 }
 
-
-/* this is called from expand_exception_blocks () to expand the toplevel
-   finalizations for a function. */
-void
-expand_leftover_cleanups ()
+/* Build a type value for use at runtime for a type that is matched
+   against by the exception handling system.  */
+static tree
+build_eh_type_type (type)
+     tree type;
 {
-  struct ehEntry *entry;
-  rtx first_label = NULL_RTX;
-
-  if (! doing_eh (0))
-    return;
-
-  /* Will this help us not stomp on it? */
-  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
-  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
+  char *typestring;
+  tree exp;
 
-  while ((entry = dequeue_eh_entry (&ehqueue)) != 0)
-    {
-      if (! first_label)
-       first_label = entry->exception_handler_label;
-      emit_label (entry->exception_handler_label);
+  if (type == error_mark_node)
+    return error_mark_node;
 
-      expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
+  /* peel back references, so they match. */
+  if (TREE_CODE (type) == REFERENCE_TYPE)
+    type = TREE_TYPE (type);
 
-      /* leftover try block, opps.  */
-      if (entry->finalization == integer_zero_node)
-       abort ();
+  /* Peel off cv qualifiers. */
+  type = TYPE_MAIN_VARIANT (type);
 
-      free (entry);
-    }
-  if (first_label)
+  if (flag_rtti)
     {
-      rtx label;
-      struct ehEntry entry;
-      /* These are saved for the exception table.  */
-      push_rtl_perm ();
-      label = gen_label_rtx ();
-      entry.start_label = first_label;
-      entry.end_label = label;
-      entry.exception_handler_label = gen_label_rtx ();
-      entry.finalization = TerminateFunctionCall;
-      entry.context = current_function_decl;
-      assemble_external (TREE_OPERAND (Terminate, 0));
-      pop_rtl_from_perm ();
-
-      LABEL_PRESERVE_P (entry.start_label) = 1;
-      LABEL_PRESERVE_P (entry.end_label) = 1;
-      LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
-
-      emit_label (label);
-
-      enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
-
-      /* After running the finalization, continue on out to the next
-        cleanup, if we have nothing better to do.  */
-      emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, entry.end_label));
-      /* Will this help us not stomp on it? */
-      emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
-      emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
-      make_first_label(throw_label);
-      emit_jump (throw_label);
-      emit_label (entry.exception_handler_label);
-      expand_expr (entry.finalization, const0_rtx, VOIDmode, 0);
-      emit_barrier ();
+      return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
     }
+
+  typestring = build_overload_name (type, 1, 1);
+  exp = combine_strings (build_string (strlen (typestring)+1, typestring));
+  return build1 (ADDR_EXPR, ptr_type_node, exp);
 }
 
 /* Build a type value for use at runtime for a exp that is thrown or
@@ -1143,23 +876,12 @@ static tree
 build_eh_type (exp)
      tree exp;
 {
-  char *typestring;
-  tree type;
-
   if (flag_rtti)
     {
       exp = build_typeid (exp);
       return build1 (ADDR_EXPR, ptr_type_node, exp);
     }
-  type = TREE_TYPE (exp);
-
-  /* peel back references, so they match. */
-  if (TREE_CODE (type) == REFERENCE_TYPE)
-    type = TREE_TYPE (type);
-
-  typestring = build_overload_name (type, 1, 1);
-  exp = combine_strings (build_string (strlen (typestring)+1, typestring));
-  return build1 (ADDR_EXPR, ptr_type_node, exp);
+  return build_eh_type_type (TREE_TYPE (exp));
 }
 
 /* call this to start a catch block. Typename is the typename, and identifier
@@ -1182,9 +904,9 @@ expand_start_catch_block (declspecs, declarator)
   /* Create a binding level for the parm.  */
   expand_start_bindings (0);
 
-  /* These are saved for the exception table.  */
-  push_rtl_perm ();
   false_label_rtx = gen_label_rtx ();
+  /* This is saved for the exception table.  */
+  push_rtl_perm ();
   protect_label_rtx = gen_label_rtx ();
   pop_rtl_from_perm ();
   push_label_entry (&false_label_stack, false_label_rtx);
@@ -1196,7 +918,8 @@ expand_start_catch_block (declspecs, declarator)
       rtx call_rtx, return_value_rtx;
       tree init_type;
 
-      decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
+      decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1,
+                            NULL_TREE, NULL_TREE);
 
       if (decl == NULL_TREE)
        {
@@ -1206,14 +929,15 @@ expand_start_catch_block (declspecs, declarator)
 
       /* Figure out the type that the initializer is. */
       init_type = TREE_TYPE (decl);
-      if (TREE_CODE (init_type) != REFERENCE_TYPE)
+      if (TREE_CODE (init_type) != REFERENCE_TYPE
+         && TREE_CODE (init_type) != POINTER_TYPE)
        init_type = build_reference_type (init_type);
 
-      exp = make_tree (ptr_type_node, saved_throw_value);
+      exp = saved_throw_value;
       exp = tree_cons (NULL_TREE,
-                      build_eh_type (decl),
+                      build_eh_type_type (TREE_TYPE (decl)),
                       tree_cons (NULL_TREE,
-                                 make_tree (ptr_type_node, saved_throw_type),
+                                 saved_throw_type,
                                  tree_cons (NULL_TREE, exp, NULL_TREE)));
       exp = build_function_call (CatchMatch, exp);
       call_rtx = expand_call (exp, NULL_RTX, 0);
@@ -1248,129 +972,141 @@ expand_start_catch_block (declspecs, declarator)
 }
 
 
+/* this is called from expand_exception_blocks and
+   expand_end_catch_block to expand the toplevel finalizations for a
+   function.  We return the first label emitted, if any, otherwise
+   return NULL_RTX.  */
+static rtx
+expand_leftover_cleanups ()
+{
+  struct ehEntry *entry;
+  rtx first_label = NULL_RTX;
+
+  while ((entry = dequeue_eh_entry (&ehqueue)) != 0)
+    {
+      if (! first_label)
+       first_label = entry->exception_handler_label;
+      emit_label (entry->exception_handler_label);
+
+      expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
+
+      /* The below can be optimized away, and we could just fall into the
+        next EH handler, if we are certain they are nested.  */
+      /* Code to throw out to outer context, if we fall off end of the
+        handler.  */
+      expand_internal_throw (gen_rtx (LABEL_REF,
+                                     Pmode,
+                                     entry->end_label));
+
+      /* leftover try block, opps.  */
+      if (entry->finalization == integer_zero_node)
+       abort ();
+
+      free (entry);
+    }
+
+  return first_label;
+}
+
 /* Call this to end a catch block.  Its responsible for emitting the
    code to handle jumping back to the correct place, and for emitting
    the label to jump to if this catch block didn't match.  */
 void expand_end_catch_block ()
 {
-  if (doing_eh (1))
-    {
-      rtx start_protect_label_rtx;
-      rtx end_protect_label_rtx;
-      tree decls;
-      struct ehEntry entry;
+  rtx start_protect_label_rtx;
+  rtx end_protect_label_rtx;
+  tree decls;
+  struct ehEntry entry;
 
-      /* label we jump to if we caught the exception */
-      emit_jump (top_label_entry (&caught_return_label_stack));
+  if (! doing_eh (1))
+    return;
 
-      /* Code to throw out to outer context, if we get a throw from within
-        our catch handler. */
-      /* These are saved for the exception table.  */
-      push_rtl_perm ();
-      entry.exception_handler_label = gen_label_rtx ();
-      pop_rtl_from_perm ();
-      emit_label (entry.exception_handler_label);
-      emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
-                                        Pmode,
-                                        top_label_entry (&caught_return_label_stack)));
-      make_first_label(throw_label);
-      emit_jump (throw_label);
-      /* No associated finalization.  */
-      entry.finalization = NULL_TREE;
-      entry.context = current_function_decl;
+  /* fall to outside the try statement when done executing handler and
+     we fall off end of handler.  This is jump Lresume in the
+     documentation.  */
+  emit_jump (top_label_entry (&caught_return_label_stack));
 
-      /* Because we are reordered out of line, we have to protect this. */
-      /* label for the start of the protection region.  */
-      start_protect_label_rtx = pop_label_entry (&false_label_stack);
+  /* We end the rethrow protection region as soon as we hit a label. */
+  end_protect_label_rtx = expand_leftover_cleanups ();
 
-      /* Cleanup the EH parameter.  */
-      decls = getdecls ();
-      expand_end_bindings (decls, decls != NULL_TREE, 0);
+  /* Code to throw out to outer context, if we get a throw from within
+     our catch handler. */
+  /* These are saved for the exception table.  */
+  push_rtl_perm ();
+  entry.exception_handler_label = gen_label_rtx ();
+  pop_rtl_from_perm ();
+  /* This label is Lhandler in the documentation.  */
+  emit_label (entry.exception_handler_label);
+  expand_internal_throw (gen_rtx (LABEL_REF,
+                                 Pmode,
+                                 top_label_entry (&caught_return_label_stack)));
+
+  /* No associated finalization.  */
+  entry.finalization = NULL_TREE;
+  entry.context = current_function_decl;
+
+  if (end_protect_label_rtx == NULL_RTX)
+    end_protect_label_rtx = entry.exception_handler_label;
+
+  /* Because we are emitted out of line, we have to protect this. */
+  /* label for the start of the protection region.  */
+  start_protect_label_rtx = pop_label_entry (&false_label_stack);
+
+  /* Cleanup the EH parameter.  */
+  decls = getdecls ();
+  expand_end_bindings (decls, decls != NULL_TREE, 0);
       
-      /* label we emit to jump to if this catch block didn't match. */
-      emit_label (end_protect_label_rtx = pop_label_entry (&false_label_stack));
+  /* label we emit to jump to if this catch block didn't match. */
+  /* This the closing } in the `if (eq) {' of the documentation.  */
+  emit_label (pop_label_entry (&false_label_stack));
 
-      /* Because we are reordered out of line, we have to protect this. */
-      entry.start_label = start_protect_label_rtx;
-      entry.end_label = end_protect_label_rtx;
+  /* Because we are reordered out of line, we have to protect this. */
+  entry.start_label = start_protect_label_rtx;
+  entry.end_label = end_protect_label_rtx;
 
-      LABEL_PRESERVE_P (entry.start_label) = 1;
-      LABEL_PRESERVE_P (entry.end_label) = 1;
-      LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
-
-      /* These set up a call to throw the caught exception into the outer
-       context.  */
-      enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
-    }
-}
+  LABEL_PRESERVE_P (entry.start_label) = 1;
+  LABEL_PRESERVE_P (entry.end_label) = 1;
+  LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
 
-/* cheesyness to save some typing. returns the return value rtx */
-rtx
-do_function_call (func, params, return_type)
-     tree func, params, return_type;
-{
-  tree func_call;
-  func_call = build_function_call (func, params);
-  expand_call (func_call, NULL_RTX, 0);
-  if (return_type != NULL_TREE)
-    return hard_function_value (return_type, func_call);
-  return NULL_RTX;
+  /* These set up a call to throw the caught exception into the outer
+     context.  */
+  enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
 }
 
 /* unwind the stack. */
 static void
-do_unwind (throw_label)
-     rtx throw_label;
+do_unwind (inner_throw_label)
+     rtx inner_throw_label;
 {
-#ifdef sparc
-  extern FILE *asm_out_file;
+#if defined(SPARC_STACK_ALIGN) /* was sparc */
   tree fcall;
   tree params;
   rtx return_val_rtx;
+  rtx temp;
 
   /* call to  __builtin_return_address () */
-  params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
+  params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
   fcall = build_function_call (BuiltinReturnAddress, params);
-  return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
+  return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
   /* In the return, the new pc is pc+8, as the value coming in is
      really the address of the call insn, not the next insn.  */
-  emit_move_insn (return_val_rtx, plus_constant(gen_rtx (LABEL_REF,
-                                                        Pmode,
-                                                        throw_label), -8));
-  /* We use three values, PC, type, and value */
-  easy_expand_asm ("st %l0,[%fp]");
-  easy_expand_asm ("st %l1,[%fp+4]");
-  easy_expand_asm ("st %l2,[%fp+8]");
+  temp = gen_reg_rtx (Pmode);
+  emit_move_insn (temp, inner_throw_label);
+  emit_move_insn (return_val_rtx, plus_constant (temp, -8));
   easy_expand_asm ("ret");
   easy_expand_asm ("restore");
   emit_barrier ();
 #endif
-#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined(__alpha)
-  extern FILE *asm_out_file;
-  tree fcall;
-  tree params;
-  rtx return_val_rtx;
+#if defined(ARM_FRAME_RTX)  /* was __arm */
+  if (flag_omit_frame_pointer)
+    sorry ("this implementation of exception handling requires a frame pointer");
 
-  /* call to  __builtin_return_address () */
-  params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
-  fcall = build_function_call (BuiltinReturnAddress, params);
-  return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
-#if 0
-  /* I would like to do this here, but doesn't seem to work. */
-  emit_move_insn (return_val_rtx, gen_rtx (LABEL_REF,
-                                          Pmode,
-                                          throw_label));
-  /* So, for now, just pass throw label to stack unwinder. */
-#endif
-  /* We use three values, PC, type, and value */
-  params = tree_cons (NULL_TREE, make_tree (ptr_type_node,
-                                           gen_rtx (LABEL_REF, Pmode, throw_label)), NULL_TREE);
-  
-  do_function_call (Unwind, params, NULL_TREE);
-  assemble_external (TREE_OPERAND (Unwind, 0));
-  emit_barrier ();
+  emit_move_insn (stack_pointer_rtx,
+                 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -8)));
+  emit_move_insn (hard_frame_pointer_rtx,
+                 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12)));
 #endif
-#if m88k
+#if defined(TARGET_88000) /* was m88k */
   rtx temp_frame = frame_pointer_rtx;
 
   temp_frame = memory_address (Pmode, temp_frame);
@@ -1393,17 +1129,30 @@ do_unwind (throw_label)
                                                     (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
 #endif
 #endif
-#ifdef __arm
-  if (flag_omit_frame_pointer)
-    sorry ("this implementation of exception handling requires a frame pointer");
+#if !defined(TARGET_88000) && !defined(ARM_FRAME_RTX) && !defined(SPARC_STACK_ALIGN)
+  tree fcall;
+  tree params;
+  rtx return_val_rtx;
 
-  emit_move_insn (stack_pointer_rtx,
-                 gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -8)));
-  emit_move_insn (hard_frame_pointer_rtx,
-                 gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -12)));
+  /* call to  __builtin_return_address () */
+  params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
+  fcall = build_function_call (BuiltinReturnAddress, params);
+  return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
+#if 0
+  /* I would like to do this here, but doesn't seem to work. */
+  emit_move_insn (return_val_rtx, inner_throw_label);
+  /* So, for now, just pass throw label to stack unwinder. */
+#endif
+  params = tree_cons (NULL_TREE, make_tree (ptr_type_node,
+                                           inner_throw_label), NULL_TREE);
+  
+  do_function_call (Unwind, params, NULL_TREE);
+  assemble_external (TREE_OPERAND (Unwind, 0));
+  emit_barrier ();
 #endif
 }
 
+
 /* is called from expand_exception_blocks () to generate the code in a function
    to "throw" if anything in the function needs to perform a throw.
 
@@ -1420,23 +1169,51 @@ do_unwind (throw_label)
                goto throw;
 
  */
-static void
+void
 expand_builtin_throw ()
 {
   tree fcall;
   tree params;
   rtx return_val_rtx;
-  rtx gotta_rethrow_it = gen_label_rtx ();
-  rtx gotta_call_terminate = gen_label_rtx ();
-  rtx unwind_and_throw = gen_label_rtx ();
-  rtx goto_unwind_and_throw = gen_label_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;
+
+  if (! doing_eh (0))
+    return;
+
+  if (! throw_used)
+    return;
 
-  make_first_label(throw_label);
-  emit_label (throw_label);
+  params = void_list_node;
+  t = build_parse_node (CALL_EXPR, get_identifier ("__throw"), params, NULL_TREE);
+  start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
+                                 void_list_node),
+                 t, NULL_TREE, NULL_TREE, 0);
+  store_parm_decls ();
+  pushlevel (0);
+  clear_last_expr ();
+  push_momentary ();
+  expand_start_bindings (0);
+
+  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 ();
+
+  emit_jump (unwind_first);
+
+  emit_label (top_of_loop);
 
   /* search for an exception handler for the saved_pc */
   return_val_rtx = do_function_call (FirstExceptionMatch,
-                                    tree_cons (NULL_TREE, make_tree (ptr_type_node, saved_pc), NULL_TREE),
+                                    tree_cons (NULL_TREE, saved_pc, NULL_TREE),
                                     ptr_type_node);
   assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
 
@@ -1454,14 +1231,14 @@ expand_builtin_throw ()
   emit_label (gotta_rethrow_it);
 
   /* call to  __builtin_return_address () */
-#ifdef __arm
+#if defined(ARM_FRAME_RTX)  /* was __arm */
 /* This replaces a 'call' to __builtin_return_address */
   return_val_rtx = gen_reg_rtx (Pmode);
-  emit_move_insn (return_val_rtx, gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -4)));
+  emit_move_insn (return_val_rtx, gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
 #else
-  params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
+  params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
   fcall = build_function_call (BuiltinReturnAddress, params);
-  return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
+  return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
 #endif
 
   /* did __builtin_return_address () return a valid address? */
@@ -1470,7 +1247,7 @@ expand_builtin_throw ()
 
   emit_jump_insn (gen_beq (gotta_call_terminate));
 
-#ifdef __arm
+#if defined(ARM_FRAME_RTX)  /* was __arm */
   /* On the ARM, '__builtin_return_address',  must have 4
      subtracted from it. */
   emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-4)));
@@ -1480,9 +1257,9 @@ expand_builtin_throw ()
      they will confuse BuiltinReturnAddress.  This does not apply to ARM6 and
      later processors when running in 32 bit mode. */
   if (!TARGET_6)
-    emit_insn (gen_rtx (SET, SImode, return_val_rtx, gen_rtx (AND, SImode, return_val_rtx, GEN_INT (0x03fffffc))));
+    emit_insn (gen_rtx (SET, Pmode, return_val_rtx, gen_rtx (AND, Pmode, return_val_rtx, GEN_INT (0x03fffffc))));
 #else
-#ifndef sparc
+#if !defined(SPARC_STACK_ALIGN) /* was sparc */
   /* On the SPARC, __builtin_return_address is already -8, no need to
      subtract any more from it. */
   return_val_rtx = plus_constant (return_val_rtx, -1);
@@ -1490,53 +1267,224 @@ expand_builtin_throw ()
 #endif
 
   /* yes it did */
-  emit_move_insn (saved_pc, return_val_rtx);
-  do_unwind (throw_label);
-  make_first_label(throw_label);
-  emit_jump (throw_label);
+  t = build_modify_expr (saved_pc, NOP_EXPR, make_tree (ptr_type_node, return_val_rtx));
+  expand_expr (t, const0_rtx, VOIDmode, 0);
+
+  do_unwind (gen_rtx (LABEL_REF, Pmode, top_of_loop));
+  emit_jump (top_of_loop);
 
   /* no it didn't --> therefore we need to call terminate */
   emit_label (gotta_call_terminate);
   do_function_call (Terminate, NULL_TREE, NULL_TREE);
   assemble_external (TREE_OPERAND (Terminate, 0));
+
+  {
+    rtx ret_val, return_val_rtx;
+    emit_label (unwind_first);
+    ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
+                                         0, hard_frame_pointer_rtx);
+
+    /* Set it up so that we continue inside, at the top of the loop.  */
+    emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop));
+#ifdef NORMAL_RETURN_ADDR_OFFSET
+  return_val_rtx = plus_constant (ret_val, -NORMAL_RETURN_ADDR_OFFSET);
+    if (return_val_rtx != ret_val)
+      emit_move_insn (ret_val, return_val_rtx);
+#endif
+
+    /* Fall into epilogue to unwind prologue. */
+  }
+
+  expand_end_bindings (getdecls(), 1, 0);
+  poplevel (1, 0, 0);
+  pop_momentary ();
+
+  finish_function (lineno, 0, 0);
 }
 
 
+void
+expand_start_eh_spec ()
+{
+  start_protect ();
+}
+
+void
+expand_end_eh_spec (raises)
+     tree raises;
+{
+  tree expr, second_try;
+  rtx check = gen_label_rtx ();
+  rtx cont;
+  rtx ret = gen_reg_rtx (Pmode);
+  rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node));
+  rtx end = gen_label_rtx ();
+
+  expr = make_node (RTL_EXPR);
+  TREE_TYPE (expr) = void_type_node;
+  RTL_EXPR_RTL (expr) = const0_rtx;
+  TREE_SIDE_EFFECTS (expr) = 1;
+  start_sequence_for_rtl_expr (expr);
+  cont = gen_label_rtx ();
+  emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
+  emit_jump (check);
+  emit_label (cont);
+  jumpif (make_tree (integer_type_node, flag), end);
+  do_function_call (Terminate, NULL_TREE, NULL_TREE);
+  assemble_external (TREE_OPERAND (Terminate, 0));
+  emit_barrier ();
+  RTL_EXPR_SEQUENCE (expr) = get_insns ();
+  end_sequence ();
+  
+  second_try = expr;
+
+  expr = make_node (RTL_EXPR);
+  TREE_TYPE (expr) = void_type_node;
+  RTL_EXPR_RTL (expr) = const0_rtx;
+  TREE_SIDE_EFFECTS (expr) = 1;
+  start_sequence_for_rtl_expr (expr);
+
+  cont = gen_label_rtx ();
+  emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
+  emit_jump (check);
+  emit_label (cont);
+  jumpif (make_tree (integer_type_node, flag), end);
+  start_protect ();
+  do_function_call (Unexpected, NULL_TREE, NULL_TREE);
+  assemble_external (TREE_OPERAND (Unexpected, 0));
+  emit_barrier ();
+  end_protect (second_try);
+  
+  emit_label (check);
+  emit_move_insn (flag, const1_rtx);
+  cont = gen_label_rtx ();
+  while (raises)
+    {
+      tree exp;
+      tree match_type = TREE_VALUE (raises);
+      
+      if (match_type)
+       {
+         /* check TREE_VALUE (raises) here */
+         exp = saved_throw_value;
+         exp = tree_cons (NULL_TREE,
+                          build_eh_type_type (match_type),
+                          tree_cons (NULL_TREE,
+                                     saved_throw_type,
+                                     tree_cons (NULL_TREE, exp, NULL_TREE)));
+         exp = build_function_call (CatchMatch, exp);
+         assemble_external (TREE_OPERAND (CatchMatch, 0));
+
+         jumpif (exp, cont);
+       }
+
+      raises = TREE_CHAIN (raises);
+    }
+  emit_move_insn (flag, const0_rtx);
+  emit_label (cont);
+  emit_indirect_jump (ret);
+  emit_label (end);
+  
+  RTL_EXPR_SEQUENCE (expr) = get_insns ();
+  end_sequence ();
+  
+  end_protect (expr);
+}
+
 /* This is called to expand all the toplevel exception handling
    finalization for a function.  It should only be called once per
    function.  */
 void
 expand_exception_blocks ()
 {
-  rtx catchstart, catchend;
-  rtx last;
   static rtx funcend;
+  rtx insns;
+
+  start_sequence ();
 
   funcend = gen_label_rtx ();
   emit_jump (funcend);
   /* expand_null_return (); */
 
-  while (pop_except_stmts (&exceptstack, &catchstart, &catchend)) {
-    last = get_last_insn ();
-    NEXT_INSN (last) = catchstart;
-    PREV_INSN (catchstart) = last;
-    NEXT_INSN (catchend) = 0;
-    set_last_insn (catchend);
-  }
+  start_sequence ();
+
+  /* Add all the catch clauses here.  */
+  emit_insns (catch_clauses);
+  catch_clauses = NULL_RTX;
 
   expand_leftover_cleanups ();
 
+  insns = get_insns ();
+  end_sequence ();
+  
+  /* Do this after we expand leftover cleanups, so that the end_protect
+     that expand_end_eh_spec does will match the right start_protect,
+     and make sure it comes out before the terminate protected region.  */
+  if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
+    {
+      expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
+      push_to_sequence (insns);
+
+      /* Now expand any new ones.  */
+      expand_leftover_cleanups ();
+
+      insns = get_insns ();
+      end_sequence ();
+    }
+
+  if (insns)
+    {
+      struct ehEntry entry;
+
+      /* These are saved for the exception table.  */
+      push_rtl_perm ();
+      entry.start_label = gen_label_rtx ();
+      entry.end_label = gen_label_rtx ();
+      entry.exception_handler_label = gen_label_rtx ();
+      entry.finalization = TerminateFunctionCall;
+      entry.context = current_function_decl;
+      assemble_external (TREE_OPERAND (Terminate, 0));
+      pop_rtl_from_perm ();
+
+      LABEL_PRESERVE_P (entry.start_label) = 1;
+      LABEL_PRESERVE_P (entry.end_label) = 1;
+      LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
+
+      emit_label (entry.start_label);
+      emit_insns (insns);
+
+      enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
+
+      emit_label (entry.exception_handler_label);
+      expand_expr (entry.finalization, const0_rtx, VOIDmode, 0);
+      emit_label (entry.end_label);
+      emit_barrier ();
+    }
+
   {
-    static int have_done = 0;
-    if (! have_done && TREE_PUBLIC (current_function_decl)
-       && DECL_INTERFACE_KNOWN (current_function_decl)
-       && ! DECL_EXTERNAL (current_function_decl))
+    /* Mark the end of the stack unwinder.  */
+    rtx unwind_insns;
+    start_sequence ();
+    end_eh_unwinder (funcend);
+    expand_leftover_cleanups ();
+    unwind_insns = get_insns ();
+    end_sequence ();
+    if (unwind_insns)
       {
-       have_done = 1;
-       expand_builtin_throw ();
+       insns = unwind_insns;
+       emit_insns (insns);
       }
   }
+
   emit_label (funcend);
+
+  /* Only if we had previous insns do we want to emit the jump around
+     them.  If there weren't any, then insns will remain NULL_RTX.  */
+  if (insns)
+    insns = get_insns ();
+  end_sequence ();
+
+  emit_insns (insns);
 }
 
 
@@ -1567,27 +1515,35 @@ expand_throw (exp)
   if (exp)
     {
       tree throw_type;
-      rtx throw_type_rtx;
-      rtx throw_value_rtx;
+      tree e;
 
       /* throw expression */
       /* First, decay it. */
-      exp = default_conversion (exp);
+      exp = decay_conversion (exp);
 
-      /* Make a copy of the thrown object.  WP 15.1.5  */
-      exp = build_new (NULL_TREE, TREE_TYPE (exp),
-                      build_tree_list (NULL_TREE, exp),
-                      0);
+      if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
+       {
+         throw_type = build_eh_type (exp);
+         exp = build_reinterpret_cast (ptr_type_node, exp);
+       }
+      else
+       {
+         /* Make a copy of the thrown object.  WP 15.1.5  */
+         exp = build_new (NULL_TREE, TREE_TYPE (exp),
+                          build_tree_list (NULL_TREE, exp),
+                          0);
 
-      if (exp == error_mark_node)
-       error ("  in thrown expression");
+         if (exp == error_mark_node)
+           error ("  in thrown expression");
 
-      throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR));
-      throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
+         throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR));
+       }
 
-      throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0);
-      emit_move_insn (saved_throw_value, throw_value_rtx);
-      emit_move_insn (saved_throw_type, throw_type_rtx);
+      e = build_modify_expr (saved_throw_type, NOP_EXPR, throw_type);
+      expand_expr (e, const0_rtx, VOIDmode, 0);
+      e = build_modify_expr (saved_throw_value, NOP_EXPR, exp);
+      e = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (e), e);
+      expand_expr (e, const0_rtx, VOIDmode, 0);
     }
   else
     {
@@ -1595,14 +1551,9 @@ expand_throw (exp)
       /* This part is easy, as we don't have to do anything else.  */
     }
 
-  emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, label));
-  make_first_label(throw_label);
-  emit_jump (throw_label);
+  expand_internal_throw (gen_rtx (LABEL_REF, Pmode, label));
 }
 
-/* end of: my-cp-except.c */
-#endif
-
 void
 end_protect_partials () {
   while (protect_list)
@@ -1615,10 +1566,8 @@ end_protect_partials () {
 int
 might_have_exceptions_p ()
 {
-#ifdef TRY_NEW_EH
   if (eh_table_output_queue.head)
     return 1;
-#endif
   return 0;
 }
 
@@ -1628,7 +1577,6 @@ void
 emit_exception_table ()
 {
   int count = 0;
-#ifdef TRY_NEW_EH
   extern FILE *asm_out_file;
   struct ehEntry *entry;
   tree eh_node_decl;
@@ -1639,8 +1587,8 @@ emit_exception_table ()
   exception_section ();
 
   /* Beginning marker for table. */
-  ASM_OUTPUT_ALIGN (asm_out_file, 2);
-  ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_TABLE__");
+  assemble_align (GET_MODE_ALIGNMENT (Pmode));
+  assemble_label ("__EXCEPTION_TABLE__");
   output_exception_table_entry (asm_out_file,
                                const0_rtx, const0_rtx, const0_rtx);
 
@@ -1658,22 +1606,18 @@ emit_exception_table ()
   }
 
   /* Ending marker for table. */
-  ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__");
+  assemble_label ("__EXCEPTION_END__");
   output_exception_table_entry (asm_out_file,
                                constm1_rtx, constm1_rtx, constm1_rtx);
-
-#endif /* TRY_NEW_EH */
 }
 
 void
 register_exception_table ()
 {
-#ifdef TRY_NEW_EH
   emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__register_exceptions"), 0,
                     VOIDmode, 1,
                     gen_rtx (SYMBOL_REF, Pmode, "__EXCEPTION_TABLE__"),
                     Pmode);
-#endif /* TRY_NEW_EH */
 }
 
 /* Build a throw expression.  */
@@ -1689,3 +1633,58 @@ build_throw (e)
     }
   return e;
 }
+
+start_eh_unwinder ()
+{
+  start_protect ();
+}
+
+end_eh_unwinder (end)
+     rtx end;
+{
+  tree expr;
+  rtx return_val_rtx, ret_val, label;
+
+  if (! doing_eh (0))
+    return;
+
+  expr = make_node (RTL_EXPR);
+  TREE_TYPE (expr) = void_type_node;
+  RTL_EXPR_RTL (expr) = const0_rtx;
+  TREE_SIDE_EFFECTS (expr) = 1;
+  start_sequence_for_rtl_expr (expr);
+
+  ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
+                                       0, hard_frame_pointer_rtx);
+  return_val_rtx = copy_to_reg (ret_val);
+#ifdef NORMAL_RETURN_ADDR_OFFSET
+  return_val_rtx = plus_constant (return_val_rtx, NORMAL_RETURN_ADDR_OFFSET-1);
+#else
+  return_val_rtx = plus_constant (return_val_rtx, -1);
+#endif
+  emit_move_insn (DECL_RTL (saved_pc), return_val_rtx);
+  
+#ifdef JUMP_TO_THROW
+  emit_move_insn (ret_val, gen_rtx (SYMBOL_REF, Pmode, "__throw"));
+#else
+  label = gen_label_rtx ();
+  emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, label));
+#endif
+
+#ifdef NORMAL_RETURN_ADDR_OFFSET
+  return_val_rtx = plus_constant (ret_val, -NORMAL_RETURN_ADDR_OFFSET);
+  if (return_val_rtx != ret_val)
+    emit_move_insn (ret_val, return_val_rtx);
+#endif
+  
+  emit_jump (end);  
+
+#ifndef JUMP_TO_THROW
+  emit_label (label);
+  do_function_call (Throw, NULL_TREE, NULL_TREE);
+#endif
+  
+  RTL_EXPR_SEQUENCE (expr) = get_insns ();
+  end_sequence ();
+  end_protect (expr);
+}
index 0c549c3..99a611e 100644 (file)
@@ -105,7 +105,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
            && TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
            && DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
          {
-           type = TYPE_POINTER_TO (type);
+           type = build_pointer_type (type);
            /* Don't clobber a value that might be part of a default
               parameter value.  */
            mark_addressable (slot);
@@ -226,6 +226,14 @@ cplus_expand_expr (exp, target, tmode, modifier)
       expand_throw (TREE_OPERAND (exp, 0));
       return NULL;
 
+    case UNSAVE_EXPR:
+      {
+       rtx temp;
+       temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
+       TREE_OPERAND (exp, 0) = unsave_expr_now (TREE_OPERAND (exp, 0));
+       return temp;
+      }
+
     default:
       break;
     }
index 071cce6..ae016fa 100644 (file)
@@ -8,7 +8,7 @@
 \(**
 ..
 .SH NAME
-g++ \- GNU project C++ Compiler (v2.4)
+g++ \- GNU project C++ Compiler
 .SH SYNOPSIS
 .RB g++ " [" \c
 .IR option " | " filename " ].\|.\|.
@@ -31,8 +31,12 @@ C++ source files use one of the suffixes `\|\c
 .B .C\c
 \&\|', `\|\c
 .B .cc\c
-\&\|', or `\|\c
+\&\|', `\|\c
 .B .cxx\c
+\&\|', `\|\c
+.B .cpp\c
+\&\|', or `\|\c
+.B .c++\c
 \&\|'; preprocessed C++ files use the suffix `\|\c
 .B .ii\c
 \&\|'.
index 1e37d3f..e5465e8 100644 (file)
@@ -9,13 +9,9 @@ __asm, GCC_ASM_KEYWORD, NORID
 __asm__, GCC_ASM_KEYWORD, NORID
 __attribute, ATTRIBUTE, NORID
 __attribute__, ATTRIBUTE, NORID
-__classof, CLASSOF, NORID
-__classof__, CLASSOF, NORID
 __const, TYPE_QUAL, RID_CONST
 __const__, TYPE_QUAL, RID_CONST
 __extension__, EXTENSION, NORID
-__headof, HEADOF, NORID
-__headof__, HEADOF, NORID
 __inline, SCSPEC, RID_INLINE
 __inline__, SCSPEC, RID_INLINE
 __label__, LABEL, NORID
@@ -40,7 +36,6 @@ case, CASE, NORID,
 catch, CATCH, NORID,
 char, TYPESPEC, RID_CHAR,
 class, AGGR, RID_CLASS,
-classof, CLASSOF, NORID,
 compl, '~', NORID,
 const, TYPE_QUAL, RID_CONST,
 const_cast, CONST_CAST, NORID,
@@ -59,7 +54,6 @@ float, TYPESPEC, RID_FLOAT,
 for, FOR, NORID,
 friend, SCSPEC, RID_FRIEND,
 goto, GOTO, NORID,
-headof, HEADOF, NORID,
 if, IF, NORID,
 inline, SCSPEC, RID_INLINE,
 int, TYPESPEC, RID_INT,
index f307bab..015a33c 100644 (file)
@@ -924,28 +924,46 @@ will never be a problem.
 @node Templates, Access Control, Coding Conventions, Top
 @section Templates
 
-g++ uses the simple approach to instantiating templates: it blindly
-generates the code for each instantiation as needed.  For class
-templates, g++ pushes the template parameters into the namespace for the
-duration of the instantiation; for function templates, it's a simple
-search and replace.
+A template is represented by a @code{TEMPLATE_DECL}.  The specific
+fields used are:
 
-This approach does not support any of the template definition-time error
-checking that is being bandied about by X3J16.  It makes no attempt to deal
-with name binding in a consistent way.
+@table @code
+@item DECL_TEMPLATE_RESULT
+The generic decl on which instantiations are based.  This looks just
+like any other decl.
 
-Instantiation of a class template is triggered by the use of a template
-class anywhere but in a straight declaration like @code{class A<int>}.
-This is wrong; in fact, it should not be triggered by typedefs or
-declarations of pointers.  Now that explicit instantiation is supported,
-this misfeature is not necessary.
+@item DECL_TEMPLATE_PARMS
+The parameters to this template.
+@end table
 
-Important functions:
+The generic decl is parsed as much like any other decl as possible,
+given the parameterization.  The template decl is not built up until the
+generic decl has been completed.  For template classes, a template decl
+is generated for each member function and static data member, as well.
 
-@table @code
-@item instantiate_class_template
-This function 
-@end table
+Template members of template classes are represented by a TEMPLATE_DECL
+for the class' parameters around another TEMPLATE_DECL for the member's
+parameters.
+
+All declarations that are instantiations or specializations of templates
+refer to their template and parameters through DECL_TEMPLATE_INFO.
+
+How should I handle parsing member functions with the proper param
+decls?  Set them up again or try to use the same ones?  Currently we do
+the former.  We can probably do this without any extra machinery in
+store_pending_inline, by deducing the parameters from the decl in
+do_pending_inlines.  PRE_PARSED_TEMPLATE_DECL?
+
+If a base is a parm, we can't check anything about it.  If a base is not
+a parm, we need to check it for name binding.  Do finish_base_struct if
+no bases are parameterized (only if none, including indirect, are
+parms).  Nah, don't bother trying to do any of this until instantiation
+-- we only need to do name binding in advance.
+
+Always set up method vec and fields, inc. synthesized methods.  Really?
+We can't know the types of the copy folks, or whether we need a
+destructor, or can have a default ctor, until we know our bases and
+fields.  Otherwise, we can assume and fix ourselves later.  Hopefully.
 
 @node Access Control, Error Reporting, Templates, Top
 @section Access Control
@@ -1194,63 +1212,218 @@ the object was thrown.  This is so that there is always someplace for
 the exception object, and nothing can overwrite it, once we start
 throwing.  The only bad part, is that the stack remains large.
 
+The below points out some things that work in g++'s exception handling.
+
+All completely constructed temps and local variables are cleaned up in
+all unwinded scopes.  Completely constructed parts of partially
+constructed objects are cleaned up.  This includes partially built
+arrays.  Exception specifications are now handled.
+
 The below points out some flaws in g++'s exception handling, as it now
 stands.
 
 Only exact type matching or reference matching of throw types works when
 -fno-rtti is used.  Only works on a SPARC (like Suns), i386, arm and
-rs6000 machines.  Partial support is also in for alpha, hppa, m68k and
-mips machines, but a stack unwinder called __unwind_function has to be
-written, and added to libgcc2 for them.  See below for details on
-__unwind_function.  All completely constructed temps and local variables
-are cleaned up in all unwinded scopes.  Completed parts of partially
-constructed objects are cleaned up with the exception that partially
-built arrays are not cleaned up as required.  Don't expect exception
-handling to work right if you optimize, in fact the compiler will
-probably core dump.  If two EH regions are the exact same size, the
-backend cannot tell which one is first.  It punts by picking the last
-one, if they tie.  This is usually right.  We really should stick in a
-nop, if they are the same size.
-
-When we invoke the copy constructor for an exception object because it
-is passed by value, and if we take a hit (exception) inside the copy
-constructor someplace, where do we go?  I have tentatively chosen to
-not catch throws by the outer block at the same unwind level, if one
-exists, but rather to allow the frame to unwind into the next series of
-handlers, if any.  If this is the wrong way to do it, we will need to
-protect the rest of the handler in some fashion.  Maybe just changing
-the handler's handler to protect the whole series of handlers is the
-right way to go.  This part is wrong.  We should call terminate if an
-exception is thrown while doing things like trying to copy the exception
-object.
-
-Exception specifications are handled syntax wise, but not semantic wise.
-build_exception_variant should sort the incoming list, so that is
+rs6000 machines.  Partial support is in for all other machines, but a
+stack unwinder called __unwind_function has to be written, and added to
+libgcc2 for them.  See below for details on __unwind_function.  Don't
+expect exception handling to work right if you optimize, in fact the
+compiler will probably core dump.  RTL_EXPRs for EH cond variables for
+&& and || exprs should probably be wrapped in UNSAVE_EXPRs, and
+RTL_EXPRs tweaked so that they can be unsaved, and the UNSAVE_EXPR code
+should be in the backend, or alternatively, UNSAVE_EXPR should be ripped
+out and exactly one finalization allowed to be expanded by the backend.
+I talked with kenner about this, and we have to allow multiple
+expansions.
+
+We only do pointer conversions on exception matching a la 15.3 p2 case
+3: `A handler with type T, const T, T&, or const T& is a match for a
+throw-expression with an object of type E if [3]T is a pointer type and
+E is a pointer type that can be converted to T by a standard pointer
+conversion (_conv.ptr_) not involving conversions to pointers to private
+or protected base classes.' when -frtti is given.
+
+We don't call delete on new expressions that die because the ctor threw
+an exception.  See except/18 for a test case.
+
+15.2 para 13: The exception being handled should be rethrown if control
+reaches the end of a handler of the function-try-block of a constructor
+or destructor, right now, it is not.
+
+15.2 para 12: If a return statement appears in a handler of
+function-try-block of a constructor, the program is ill-formed, but this
+isn't diagnosed.
+
+15.2 para 11: If the handlers of a function-try-block contain a jump
+into the body of a constructor or destructor, the program is ill-formed,
+but this isn't diagnosed.
+
+15.2 para 9: Check that the fully constructed base classes and members
+of an object are destroyed before entering the handler of a
+function-try-block of a constructor or destructor for that object.
+
+build_exception_variant should sort the incoming list, so that it
 implements set compares, not exact list equality.  Type smashing should
 smash exception specifications using set union.
 
-Thrown objects are allocated on the heap, in the usual way, but they are
-never deleted.  They should be deleted by the catch clauses.  If one
-runs out of heap space, throwing an object will probably never work.
-This could be relaxed some by passing an __in_chrg parameter to track
-who has control over the exception object.
+Thrown objects are usually allocated on the heap, in the usual way, but
+they are never deleted.  They should be deleted by the catch clauses.
+If one runs out of heap space, throwing an object will probably never
+work.  This could be relaxed some by passing an __in_chrg parameter to
+track who has control over the exception object.  Thrown objects are not
+allocated on the heap when they are pointer to object types.
 
 When the backend returns a value, it can create new exception regions
 that need protecting.  The new region should rethrow the object in
 context of the last associated cleanup that ran to completion.
 
+The structure of the code that is generated for C++ exception handling
+code is shown below:
+
+@example
+Ln:                                    throw value;
+        copy value onto heap
+        jump throw (Ln, id, address of copy of value on heap)
+
+                                        try {
++Lstart:       the start of the main EH region
+|...                                           ...
++Lend:         the end of the main EH region
+                                        } catch (T o) {
+                                               ...1
+                                        }
+Lresume:
+        nop    used to make sure there is something before
+                the next region ends, if there is one
+...                                     ...
+
+        jump Ldone
+[
+Lmainhandler:    handler for the region Lstart-Lend
+       cleanup
+] zero or more, depending upon automatic vars with dtors
++Lpartial:
+|        jump Lover
++Lhere:
+        rethrow (Lhere, same id, same obj);
+Lterm:         handler for the region Lpartial-Lhere
+        call terminate
+Lover:
+[
+ [
+        call throw_type_match
+        if (eq) {
+ ] these lines disappear when there is no catch condition
++Lsregion2:
+|      ...1
+|      jump Lresume
+|Lhandler:     handler for the region Lsregion2-Leregion2
+|      rethrow (Lresume, same id, same obj);
++Leregion2
+        }
+] there are zero or more of these sections, depending upon how many
+  catch clauses there are
+----------------------------- expand_end_all_catch --------------------------
+                here we have fallen off the end of all catch
+                clauses, so we rethrow to outer
+        rethrow (Lresume, same id, same obj);
+----------------------------- expand_end_all_catch --------------------------
+[
+L1:     maybe throw routine
+] depending upon if we have expanded it or not
+Ldone:
+        ret
+
+start_all_catch emits labels: Lresume, 
+
+#end example
+
 The __unwind_function takes a pointer to the throw handler, and is
 expected to pop the stack frame that was built to call it, as well as
-the frame underneath and then jump to the throw handler.  It must not
-change the three registers allocated for the pointer to the exception
-object, the pointer to the type descriptor that identifies the type of
-the exception object, and the pointer to the code that threw.  On hppa,
-these are %r5, %r6, %r7.  On m68k these are a2, a3, a4.  On mips they
-are s0, s1, s2.  On Alpha these are $9, $10, $11.  It takes about a day
-to write this routine, if someone wants to volunteer to write this
-routine for any architecture, exception support for that architecture
-will be added to g++.  Please send in those code donations.
+the frame underneath and then jump to the throw handler.  It must
+restore all registers to their proper values as well as all other
+machine state as determined by the context in which we are unwinding
+into.  The way I normally start is to compile:
+
+        void *g;
+        foo(void* a) { g = a; }
+
+with -S, and change the thing that alters the PC (return, or ret
+usually) to not alter the PC, making sure to leave all other semantics
+(like adjusting the stack pointer, or frame pointers) in.  After that,
+replicate the prologue once more at the end, again, changing the PC
+altering instructions, and finally, at the very end, jump to `g'.
+
+It takes about a week to write this routine, if someone wants to
+volunteer to write this routine for any architecture, exception support
+for that architecture will be added to g++.  Please send in those code
+donations.  One other thing that needs to be done, is to double check
+that __builtin_return_address (0) works.
+
+@subsection Specific Targets
 
+For the alpha, the __unwind_function will be something resembling:
+
+@example
+void
+__unwind_function(void *ptr)
+@{
+  /* First frame */
+  asm ("ldq $15, 8($30)"); /* get the saved frame ptr; 15 is fp, 30 is sp */
+  asm ("bis $15, $15, $30"); /* reload sp with the fp we found */
+
+  /* Second frame */
+  asm ("ldq $15, 8($30)"); /* fp */
+  asm ("bis $15, $15, $30"); /* reload sp with the fp we found */
+
+  /* Return */
+  asm ("ret $31, ($16), 1"); /* return to PTR, stored in a0 */
+@}
+@end example
+
+@noindent
+However, there are a few problems preventing it from working.  First of
+all, the gcc-internal function @code{__builtin_return_address} needs to
+work given an argument of 0 for the alpha.  As it stands as of August
+30th, 1995, the code for @code{BUILT_IN_RETURN_ADDRESS} in @file{expr.c}
+will definitely not work on the alpha.  Instead, we need to define
+the macros @code{DYNAMIC_CHAIN_ADDRESS} (maybe),
+@code{RETURN_ADDR_IN_PREVIOUS_FRAME}, and definitely need a new
+definition for @code{RETURN_ADDR_RTX}.
+
+In addition (and more importantly), we need a way to reliably find the
+frame pointer on the alpha.  The use of the value 8 above to restore the
+frame pointer (register 15) is incorrect.  On many systems, the frame
+pointer is consistently offset to a specific point on the stack.  On the
+alpha, however, the frame pointer is pushed last.  First the return
+address is stored, then any other registers are saved (e.g., @code{s0}),
+and finally the frame pointer is put in place.  So @code{fp} could have
+an offset of 8, but if the calling function saved any registers at all,
+they add to the offset.
+
+The only places the frame size is noted are with the @samp{.frame}
+directive, for use by the debugger and the OSF exception handling model
+(useless to us), and in the initial computation of the new value for
+@code{sp}, the stack pointer.  For example, the function may start with:
+
+@example
+lda $30,-32($30)
+.frame $15,32,$26,0
+@end example 
+
+@noindent
+The 32 above is exactly the value we need.  With this, we can be sure
+that the frame pointer is stored 8 bytes less---in this case, at 24(sp)).
+The drawback is that there is no way that I (Brendan) have found to let
+us discover the size of a previous frame @emph{inside} the definition
+of @code{__unwind_function}.
+
+So to accomplish exception handling support on the alpha, we need two
+things: first, a way to figure out where the frame pointer was stored,
+and second, a functional @code{__builtin_return_address} implementation
+for except.c to be able to use it.
+
+@subsection Backend Exception Support
 
 The backend must be extended to fully support exceptions.  Right now
 there are a few hooks into the alpha exception handling backend that
@@ -1285,6 +1458,78 @@ semantics.
 The above is not meant to be exhaustive, but does include all things I
 have thought of so far.  I am sure other limitations exist.
 
+Below are some notes on the migration of the exception handling code
+backend from the C++ frontend to the backend.
+
+NOTEs are to be used to denote the start of an exception region, and the
+end of the region.  I presume that the interface used to generate these
+notes in the backend would be two functions, start_exception_region and
+end_exception_region (or something like that).  The frontends are
+required to call them in pairs.  When marking the end of a region, an
+argument can be passed to indicate the handler for the marked region.
+This can be passed in many ways, currently a tree is used.  Another
+possibility would be insns for the handler, or a label that denotes a
+handler.  I have a feeling insns might be the the best way to pass it.
+Semantics are, if an exception is thrown inside the region, control is
+transfered unconditionally to the handler.  If control passes through
+the handler, then the backend is to rethrow the exception, in the
+context of the end of the original region.  The handler is protected by
+the conventional mechanisms; it is the frontend's responsibility to
+protect the handler, if special semantics are required.
+
+This is a very low level view, and it would be nice is the backend
+supported a somewhat higher level view in addition to this view.  This
+higher level could include source line number, name of the source file,
+name of the language that threw the exception and possibly the name of
+the exception.  Kenner may want to rope you into doing more than just
+the basics required by C++.  You will have to resolve this.  He may want
+you to do support for non-local gotos, first scan for exception handler,
+if none is found, allow the debugger to be entered, without any cleanups
+being done.  To do this, the backend would have to know the difference
+between a cleanup-rethrower, and a real handler, if would also have to
+have a way to know if a handler `matches' a thrown exception, and this
+is frontend specific.
+
+The UNSAVE_EXPR tree code has to be migrated to the backend.  Exprs such
+as TARGET_EXPRs, WITH_CLEANUP_EXPRs, CALL_EXPRs and RTL_EXPRs have to be
+changed to support unsaving.  This is meant to be a complete list.
+SAVE_EXPRs can be unsaved already.  expand_decl_cleanup should be
+changed to unsave it's argument, if needed.  See
+cp/tree.c:cp_expand_decl_cleanup, unsave_expr_now, unsave_expr, and
+cp/expr.c:cplus_expand_expr(case UNSAVE_EXPR:) for the UNSAVE_EXPR code.
+Now, as to why...  because kenner already tripped over the exact same
+problem in Ada, we talked about it, he didn't like any of the solution,
+but yet, didn't like no solution either.  He was willing to live with
+the drawbacks of this solution.  The drawback is unsave_expr_now.  It
+should have a callback into the frontend, to allow the unsaveing of
+frontend special codes.  The callback goes in, inplace of the call to
+my_friendly_abort.
+
+The stack unwinder is one of the hardest parts to do.  It is highly
+machine dependent.  The form that kenner seems to like was a couple of
+macros, that would do the machine dependent grunt work.  One preexisting
+function that might be of some use is __builtin_return_address ().  One
+macro he seemed to want was __builtin_return_address, and the other
+would do the hard work of fixing up the registers, adjusting the stack
+pointer, frame pointer, arg pointer and so on.
+
+The eh archive (~mrs/eh) might be good reading for understanding the Ada
+perspective, and some of kenners mindset, and a detailed explanation
+(Message-Id: <9308301130.AA10543@vlsi1.ultra.nyu.edu>) of the concepts
+involved.
+
+Here is a guide to existing backend type code.  It is all in
+cp/except.c.  Check out do_unwind, and expand_builtin_throw for current
+code on how to figure out what handler matches an exception,
+emit_exception_table for code on emitting the PC range table that is
+built during compilation, expand_exception_blocks for code that emits
+all the handlers at the end of a functions, end_protect to mark the end
+of an exception region, start_protect to mark the start of an exception
+region, lang_interim_eh is the master hook used by the backend into the
+EH backend that now exists in the frontend, and expand_internal_throw to
+raise an exception.
+
+
 @node Free Store, Concept Index, Exception Handling, Top
 @section Free Store
 
index 6f6a97a..4848aba 100644 (file)
@@ -3,12 +3,12 @@
 /* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf  */
 struct resword { char *name; short token; enum rid rid;};
 
-#define TOTAL_KEYWORDS 101
+#define TOTAL_KEYWORDS 97
 #define MIN_WORD_LENGTH 2
 #define MAX_WORD_LENGTH 16
 #define MIN_HASH_VALUE 4
-#define MAX_HASH_VALUE 210
-/* maximum key range = 207, duplicates = 0 */
+#define MAX_HASH_VALUE 219
+/* maximum key range = 216, duplicates = 0 */
 
 #ifdef __GNUC__
 inline
@@ -20,19 +20,19 @@ hash (str, len)
 {
   static unsigned char asso_values[] =
     {
-     211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
-     211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
-     211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
-     211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
-     211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
-     211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
-     211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
-     211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
-     211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
-     211, 211, 211, 211, 211,   0, 211,  35,   1,  69,
-      61,   0,  19,  65,  20, 100, 211,   5,  11,  52,
-       3,  25,   6,   2,  31,  26,   4,  41,  24,  64,
-      10,  24, 211, 211, 211, 211, 211, 211,
+     220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
+     220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
+     220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
+     220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
+     220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
+     220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
+     220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
+     220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
+     220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
+     220, 220, 220, 220, 220,   0, 220,  88,  16,  19,
+      52,   0,   9,  72,   1,  77, 220,   0,   0,  38,
+      13,  44,  38,  30,  27,  57,   1,  14,   0,   2,
+       2,   7, 220, 220, 220, 220, 220, 220,
     };
   register int hval = len;
 
@@ -65,144 +65,144 @@ is_reserved_word (str, len)
     {
       {"",}, {"",}, {"",}, {"",}, 
       {"else",  ELSE, NORID,},
-      {"",}, {"",}, {"",}, 
       {"true",  CXX_TRUE, NORID,},
-      {"extern",  SCSPEC, RID_EXTERN,},
+      {"",}, 
+      {"while",  WHILE, NORID,},
+      {"virtual",  SCSPEC, RID_VIRTUAL,},
+      {"",}, {"",}, 
+      {"try",  TRY, NORID,},
+      {"",}, {"",}, {"",}, {"",}, 
+      {"typeof",  TYPEOF, NORID,},
       {"not",  '!', NORID,},
-      {"not_eq",  EQCOMPARE, NORID,},
+      {"new",  NEW, NORID,},
+      {"extern",  SCSPEC, RID_EXTERN,},
+      {"bool",  TYPESPEC, RID_BOOL,},
       {"",}, {"",}, 
-      {"__inline",  SCSPEC, RID_INLINE},
+      {"case",  CASE, NORID,},
+      {"__alignof__",  ALIGNOF, NORID},
       {"",}, 
-      {"__inline__",  SCSPEC, RID_INLINE},
+      {"typedef",  SCSPEC, RID_TYPEDEF,},
       {"",}, 
-      {"xor_eq",  ASSIGN, NORID,},
-      {"",}, {"",}, {"",}, 
-      {"template",  TEMPLATE, RID_TEMPLATE,},
-      {"",}, {"",}, 
-      {"__alignof__",  ALIGNOF, NORID},
       {"__extension__",  EXTENSION, NORID},
-      {"bool",  TYPESPEC, RID_BOOL,},
+      {"",}, {"",}, 
+      {"__alignof",  ALIGNOF, NORID},
+      {"xor",  '^', NORID,},
       {"",}, 
-      {"typeof",  TYPEOF, NORID,},
+      {"__inline",  SCSPEC, RID_INLINE},
       {"",}, 
-      {"try",  TRY, NORID,},
-      {"or_eq",  ASSIGN, NORID,},
-      {"__asm__",  GCC_ASM_KEYWORD, NORID},
+      {"__inline__",  SCSPEC, RID_INLINE},
       {"",}, 
-      {"__headof__",  HEADOF, NORID},
+      {"xor_eq",  ASSIGN, NORID,},
+      {"for",  FOR, NORID,},
+      {"",}, {"",}, 
+      {"continue",  CONTINUE, NORID,},
       {"",}, 
+      {"catch",  CATCH, NORID,},
       {"private",  VISSPEC, RID_PRIVATE,},
+      {"",}, 
+      {"typename",  TYPENAME_KEYWORD, NORID,},
+      {"template",  TEMPLATE, RID_TEMPLATE,},
+      {"not_eq",  EQCOMPARE, NORID,},
+      {"",}, {"",}, 
+      {"throw",  THROW, NORID,},
+      {"__const",  TYPE_QUAL, RID_CONST},
       {"__const__",  TYPE_QUAL, RID_CONST},
       {"__volatile",  TYPE_QUAL, RID_VOLATILE},
-      {"__const",  TYPE_QUAL, RID_CONST},
+      {"__wchar_t",  TYPESPEC, RID_WCHAR  /* Unique to ANSI C++ */,},
       {"__volatile__",  TYPE_QUAL, RID_VOLATILE},
-      {"__alignof",  ALIGNOF, NORID},
-      {"and_eq",  ASSIGN, NORID,},
-      {"xor",  '^', NORID,},
+      {"delete",  DELETE, NORID,},
+      {"typeid",  TYPEID, NORID,},
+      {"return",  RETURN, NORID,},
+      {"__typeof__",  TYPEOF, NORID},
+      {"compl",  '~', NORID,},
+      {"public",  VISSPEC, RID_PUBLIC,},
+      {"__asm__",  GCC_ASM_KEYWORD, NORID},
+      {"switch",  SWITCH, NORID,},
+      {"",}, 
+      {"friend",  SCSPEC, RID_FRIEND,},
+      {"__typeof",  TYPEOF, NORID},
+      {"",}, 
       {"static_cast",  STATIC_CAST, NORID,},
-      {"break",  BREAK, NORID,},
-      {"namespace",  NAMESPACE, NORID,},
-      {"__classof__",  CLASSOF, NORID},
-      {"typedef",  SCSPEC, RID_TYPEDEF,},
       {"false",  CXX_FALSE, NORID,},
       {"sizeof",  SIZEOF, NORID,},
-      {"__headof",  HEADOF, NORID},
-      {"for",  FOR, NORID,},
-      {"",}, 
-      {"__label__",  LABEL, NORID},
-      {"switch",  SWITCH, NORID,},
-      {"virtual",  SCSPEC, RID_VIRTUAL,},
       {"or",  OROR, NORID,},
-      {"__typeof__",  TYPEOF, NORID},
-      {"this",  THIS, NORID,},
-      {"",}, 
-      {"bitor",  '|', NORID,},
-      {"float",  TYPESPEC, RID_FLOAT,},
-      {"typename",  TYPENAME_KEYWORD, NORID,},
-      {"__classof",  CLASSOF, NORID},
-      {"short",  TYPESPEC, RID_SHORT,},
-      {"delete",  DELETE, NORID,},
       {"double",  TYPESPEC, RID_DOUBLE,},
       {"",}, 
-      {"new",  NEW, NORID,},
-      {"typeid",  TYPEID, NORID,},
-      {"",}, 
-      {"case",  CASE, NORID,},
       {"union",  AGGR, RID_UNION,},
-      {"sigof",  SIGOF, NORID          /* Extension */,},
-      {"__typeof",  TYPEOF, NORID},
+      {"char",  TYPESPEC, RID_CHAR,},
       {"struct",  AGGR, RID_RECORD,},
-      {"volatile",  TYPE_QUAL, RID_VOLATILE,},
+      {"or_eq",  ASSIGN, NORID,},
+      {"enum",  ENUM, NORID,},
+      {"int",  TYPESPEC, RID_INT,},
+      {"const",  TYPE_QUAL, RID_CONST,},
+      {"static",  SCSPEC, RID_STATIC,},
+      {"reinterpret_cast",  REINTERPRET_CAST, NORID,},
+      {"",}, 
+      {"explicit",  SCSPEC, RID_EXPLICIT,},
+      {"__signed__",  TYPESPEC, RID_SIGNED},
+      {"if",  IF, NORID,},
+      {"__attribute",  ATTRIBUTE, NORID},
+      {"short",  TYPESPEC, RID_SHORT,},
+      {"__attribute__",  ATTRIBUTE, NORID},
+      {"bitor",  '|', NORID,},
       {"signature",  AGGR, RID_SIGNATURE       /* Extension */,},
-      {"while",  WHILE, NORID,},
-      {"return",  RETURN, NORID,},
+      {"",}, 
+      {"__sigof__",  SIGOF, NORID              /* Extension */,},
+      {"volatile",  TYPE_QUAL, RID_VOLATILE,},
+      {"__label__",  LABEL, NORID},
+      {"do",  DO, NORID,},
       {"",}, 
       {"__asm",  GCC_ASM_KEYWORD, NORID},
       {"protected",  VISSPEC, RID_PROTECTED,},
-      {"reinterpret_cast",  REINTERPRET_CAST, NORID,},
-      {"friend",  SCSPEC, RID_FRIEND,},
       {"",}, 
-      {"do",  DO, NORID,},
-      {"auto",  SCSPEC, RID_AUTO,},
-      {"asm",  ASM_KEYWORD, NORID,},
-      {"compl",  '~', NORID,},
-      {"public",  VISSPEC, RID_PUBLIC,},
+      {"float",  TYPESPEC, RID_FLOAT,},
+      {"using",  USING, NORID,},
       {"",}, 
-      {"mutable",  SCSPEC, RID_MUTABLE,},
+      {"const_cast",  CONST_CAST, NORID,},
       {"",}, 
+      {"void",  TYPESPEC, RID_VOID,},
+      {"break",  BREAK, NORID,},
+      {"namespace",  NAMESPACE, NORID,},
+      {"",}, {"",}, {"",}, {"",}, 
+      {"sigof",  SIGOF, NORID          /* Extension */,},
+      {"",}, {"",}, {"",}, 
+      {"this",  THIS, NORID,},
+      {"",}, {"",}, {"",}, {"",}, 
+      {"and_eq",  ASSIGN, NORID,},
+      {"",}, {"",}, {"",}, 
       {"signed",  TYPESPEC, RID_SIGNED,},
-      {"",}, 
-      {"throw",  THROW, NORID,},
-      {"and",  ANDAND, NORID,},
+      {"asm",  ASM_KEYWORD, NORID,},
       {"",}, {"",}, {"",}, 
-      {"bitand",  '&', NORID,},
-      {"const",  TYPE_QUAL, RID_CONST,},
-      {"static",  SCSPEC, RID_STATIC,},
-      {"headof",  HEADOF, NORID,},
-      {"int",  TYPESPEC, RID_INT,},
-      {"enum",  ENUM, NORID,},
-      {"",}, 
-      {"__signed__",  TYPESPEC, RID_SIGNED},
+      {"mutable",  SCSPEC, RID_MUTABLE,},
+      {"",}, {"",}, {"",}, 
+      {"__signed",  TYPESPEC, RID_SIGNED},
+      {"class",  AGGR, RID_CLASS,},
+      {"register",  SCSPEC, RID_REGISTER,},
+      {"",}, {"",}, {"",}, 
+      {"and",  ANDAND, NORID,},
+      {"",}, {"",}, {"",}, {"",}, 
+      {"long",  TYPESPEC, RID_LONG,},
       {"default",  DEFAULT, NORID,},
+      {"operator",  OPERATOR, NORID,},
+      {"unsigned",  TYPESPEC, RID_UNSIGNED,},
+      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
+      {"inline",  SCSPEC, RID_INLINE,},
       {"",}, 
-      {"__wchar_t",  TYPESPEC, RID_WCHAR  /* Unique to ANSI C++ */,},
-      {"using",  USING, NORID,},
-      {"__attribute",  ATTRIBUTE, NORID},
-      {"",}, 
-      {"__attribute__",  ATTRIBUTE, NORID},
+      {"bitand",  '&', NORID,},
       {"",}, 
       {"goto",  GOTO, NORID,},
-      {"operator",  OPERATOR, NORID,},
-      {"if",  IF, NORID,},
-      {"continue",  CONTINUE, NORID,},
-      {"explicit",  SCSPEC, RID_EXPLICIT,},
-      {"",}, {"",}, 
-      {"class",  AGGR, RID_CLASS,},
-      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"char",  TYPESPEC, RID_CHAR,},
-      {"",}, {"",}, {"",}, {"",}, 
-      {"classof",  CLASSOF, NORID,},
-      {"",}, {"",}, {"",}, {"",}, 
-      {"long",  TYPESPEC, RID_LONG,},
-      {"",}, {"",}, {"",}, {"",}, 
-      {"void",  TYPESPEC, RID_VOID,},
-      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"overload",  OVERLOAD, NORID,},
-      {"",}, {"",}, 
-      {"catch",  CATCH, NORID,},
-      {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"__signed",  TYPESPEC, RID_SIGNED},
-      {"register",  SCSPEC, RID_REGISTER,},
       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"const_cast",  CONST_CAST, NORID,},
-      {"",}, {"",}, 
       {"dynamic_cast",  DYNAMIC_CAST, NORID,},
+      {"",}, {"",}, {"",}, {"",}, {"",}, 
+      {"__signature__",  AGGR, RID_SIGNATURE   /* Extension */,},
+      {"",}, 
+      {"auto",  SCSPEC, RID_AUTO,},
       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"inline",  SCSPEC, RID_INLINE,},
-      {"",}, {"",}, {"",}, 
-      {"unsigned",  TYPESPEC, RID_UNSIGNED,},
+      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
+      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
+      {"",}, {"",}, 
+      {"overload",  OVERLOAD, NORID,},
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
index 137c612..ccce6b7 100644 (file)
@@ -729,7 +729,7 @@ expand_virtual_init (binfo, decl)
   vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo));
   assemble_external (vtbl);
   TREE_USED (vtbl) = 1;
-  vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl);
+  vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
   decl = convert_pointer_to_real (vtype_binfo, decl);
   vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);
   if (vtbl_ptr == error_mark_node)
@@ -1075,6 +1075,8 @@ expand_member_init (exp, name, init)
    INIT comes in two flavors: it is either a value which
    is to be stored in EXP, or it is a parameter list
    to go to a constructor, which will operate on EXP.
+   If INIT is not a parameter list for a constructor, then set
+   LOOKUP_ONLYCONVERTING.
    If FLAGS is LOOKUP_ONLYCONVERTING then it is the = init form of
    the initializer, if FLAGS is 0, then it is the (init) form.
    If `init' is a CONSTRUCTOR, then we emit a warning message,
@@ -1113,19 +1115,23 @@ expand_aggr_init (exp, init, alias_this, flags)
 {
   tree type = TREE_TYPE (exp);
   int was_const = TREE_READONLY (exp);
+  int was_volatile = TREE_THIS_VOLATILE (exp);
 
   if (init == error_mark_node)
     return;
 
   TREE_READONLY (exp) = 0;
+  TREE_THIS_VOLATILE (exp) = 0;
+
+  if (init && TREE_CODE (init) != TREE_LIST)
+    flags |= LOOKUP_ONLYCONVERTING;
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
       /* Must arrange to initialize each element of EXP
         from elements of INIT.  */
-      int was_const_elts = TYPE_READONLY (TREE_TYPE (type));
       tree itype = init ? TREE_TYPE (init) : NULL_TREE;
-      if (was_const_elts)
+      if (TYPE_READONLY (TREE_TYPE (type)) || TYPE_VOLATILE (TREE_TYPE (type)))
        {
          TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
          if (init)
@@ -1151,6 +1157,7 @@ expand_aggr_init (exp, init, alias_this, flags)
       expand_vec_init (exp, exp, array_type_nelts (type), init,
                       init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1));
       TREE_READONLY (exp) = was_const;
+      TREE_THIS_VOLATILE (exp) = was_volatile;
       TREE_TYPE (exp) = type;
       if (init)
        TREE_TYPE (init) = itype;
@@ -1172,6 +1179,7 @@ expand_aggr_init (exp, init, alias_this, flags)
   expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
                      init, alias_this, LOOKUP_NORMAL|flags);
   TREE_READONLY (exp) = was_const;
+  TREE_THIS_VOLATILE (exp) = was_volatile;
 }
 
 static void
@@ -1229,6 +1237,8 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
     }
   else
     {
+      if (flags & LOOKUP_ONLYCONVERTING)
+       flags |= LOOKUP_NO_CONVERSION;
       rval = build_method_call (exp, constructor_name_full (type),
                                parms, binfo, flags);
 
@@ -1786,12 +1796,12 @@ build_member_call (cname, name, parmlist)
   if (dont_use_this)
     {
       basetype_path = TYPE_BINFO (type);
-      decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node);
+      decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
     }
   else if (current_class_decl == 0)
     {
       dont_use_this = 1;
-      decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node);
+      decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
     }
   else
     {
@@ -2192,7 +2202,8 @@ resolve_offset_ref (exp)
     {
       if (TREE_ADDRESSABLE (member) == 0)
        {
-         cp_error_at ("member `%D' is non-static in static member function context", member);
+         cp_error_at ("member `%D' is non-static but referenced as a static member",
+                      member);
          error ("at this point in file");
          TREE_ADDRESSABLE (member) = 1;
        }
@@ -3037,7 +3048,7 @@ build_new (placement, decl, init, use_global_new)
   if (! use_global_new && TYPE_LANG_SPECIFIC (true_type)
       && (TYPE_GETS_NEW (true_type) & (1 << has_array)))
     rval = build_opfncall (code, LOOKUP_NORMAL,
-                          TYPE_POINTER_TO (true_type), size, placement);
+                          build_pointer_type (true_type), size, placement);
   else if (placement)
     {
       rval = build_opfncall (code, LOOKUP_GLOBAL|LOOKUP_COMPLAIN,
@@ -3064,9 +3075,9 @@ build_new (placement, decl, init, use_global_new)
       /* See comment above as to why this is disabled.  */
       if (alignment)
        {
-         rval = build (PLUS_EXPR, TYPE_POINTER_TO (true_type), rval,
+         rval = build (PLUS_EXPR, build_pointer_type (true_type), rval,
                        alignment);
-         rval = build (BIT_AND_EXPR, TYPE_POINTER_TO (true_type),
+         rval = build (BIT_AND_EXPR, build_pointer_type (true_type),
                        rval, build1 (BIT_NOT_EXPR, integer_type_node,
                                      alignment));
        }
@@ -3100,7 +3111,7 @@ build_new (placement, decl, init, use_global_new)
       rval = convert (string_type_node, rval); /* lets not add void* and ints */
       rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra, 1));
       /* Store header info.  */
-      cookie = build_indirect_ref (build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type),
+      cookie = build_indirect_ref (build (MINUS_EXPR, build_pointer_type (BI_header_type),
                                          rval, extra), NULL_PTR);
       exp1 = build (MODIFY_EXPR, void_type_node,
                    build_component_ref (cookie, nc_nelts_field_id, 0, 0),
@@ -3187,8 +3198,13 @@ build_new (placement, decl, init, use_global_new)
 
          /* In case of static initialization, SAVE_EXPR is good enough.  */
          rval = save_expr (rval);
-         init = copy_to_permanent (init);
          rval = copy_to_permanent (rval);
+         init = copy_to_permanent (init);
+         init = expand_vec_init (decl, rval,
+                                 build_binary_op (MINUS_EXPR, nelts,
+                                                  integer_one_node, 1),
+                                 init, 0);
+         init = copy_to_permanent (init);
          static_aggregates = perm_tree_cons (init, rval, static_aggregates);
        }
       else
@@ -3306,6 +3322,174 @@ build_new (placement, decl, init, use_global_new)
   return rval;
 }
 \f
+static tree
+build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
+                   use_global_delete)
+     tree base, maxindex, type;
+     tree auto_delete_vec, auto_delete;
+     int use_global_delete;
+{
+  tree virtual_size;
+  tree ptype = build_pointer_type (type);
+  tree size_exp = size_in_bytes (type);
+
+  /* Temporary variables used by the loop.  */
+  tree tbase, tbase_init;
+
+  /* This is the body of the loop that implements the deletion of a
+     single element, and moves temp variables to next elements.  */
+  tree body;
+
+  /* This is the LOOP_EXPR that governs the deletion of the elements.  */
+  tree loop;
+
+  /* This is the thing that governs what to do after the loop has run.  */
+  tree deallocate_expr = 0;
+
+  /* This is the BIND_EXPR which holds the outermost iterator of the
+     loop.  It is convenient to set this variable up and test it before
+     executing any other code in the loop.
+     This is also the containing expression returned by this function.  */
+  tree controller = NULL_TREE;
+
+  /* This is the BLOCK to record the symbol binding for debugging.  */
+  tree block;
+
+  if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type))
+    {
+      loop = integer_zero_node;
+      goto no_destructor;
+    }
+
+  /* The below is short by BI_header_size */
+  virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
+
+  tbase = build_decl (VAR_DECL, NULL_TREE, ptype);
+  tbase_init = build_modify_expr (tbase, NOP_EXPR,
+                                 fold (build (PLUS_EXPR, ptype,
+                                              base,
+                                              virtual_size)));
+  DECL_REGISTER (tbase) = 1;
+  controller = build (BIND_EXPR, void_type_node, tbase, 0, 0);
+  TREE_SIDE_EFFECTS (controller) = 1;
+  block = build_block (tbase, 0, 0, 0, 0);
+  add_block_current_level (block);
+
+  if (auto_delete != integer_zero_node
+      && auto_delete != integer_two_node)
+    {
+      tree base_tbd = convert (ptype,
+                              build_binary_op (MINUS_EXPR,
+                                               convert (ptr_type_node, base),
+                                               BI_header_size,
+                                               1));
+      /* This is the real size */
+      virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
+      body = build_tree_list (NULL_TREE,
+                             build_x_delete (ptype, base_tbd,
+                                             2 | use_global_delete,
+                                             virtual_size));
+      body = build (COND_EXPR, void_type_node,
+                   build (BIT_AND_EXPR, integer_type_node,
+                          auto_delete, integer_one_node),
+                   body, integer_zero_node);
+    }
+  else
+    body = NULL_TREE;
+
+  body = tree_cons (NULL_TREE,
+                   build_delete (ptype, tbase, auto_delete,
+                                 LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
+                   body);
+
+  body = tree_cons (NULL_TREE,
+                   build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)),
+                   body);
+
+  body = tree_cons (NULL_TREE,
+                   build (EXIT_EXPR, void_type_node,
+                          build (EQ_EXPR, boolean_type_node, base, tbase)),
+                   body);
+
+  loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body));
+
+  loop = tree_cons (NULL_TREE, tbase_init,
+                   tree_cons (NULL_TREE, loop, NULL_TREE));
+  loop = build_compound_expr (loop);
+
+ no_destructor:
+  /* If the delete flag is one, or anything else with the low bit set,
+     delete the storage.  */
+  if (auto_delete_vec == integer_zero_node
+      || auto_delete_vec == integer_two_node)
+    deallocate_expr = integer_zero_node;
+  else
+    {
+      tree base_tbd;
+
+      /* The below is short by BI_header_size */
+      virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
+
+      if (! TYPE_VEC_NEW_USES_COOKIE (type))
+       /* no header */
+       base_tbd = base;
+      else
+       {
+         base_tbd = convert (ptype,
+                             build_binary_op (MINUS_EXPR,
+                                              convert (string_type_node, base),
+                                              BI_header_size,
+                                              1));
+         /* True size with header. */
+         virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
+       }
+      deallocate_expr = build_x_delete (ptype, base_tbd,
+                                       2 | use_global_delete,
+                                       virtual_size);
+      if (auto_delete_vec != integer_one_node)
+       deallocate_expr = build (COND_EXPR, void_type_node,
+                                build (BIT_AND_EXPR, integer_type_node,
+                                       auto_delete_vec, integer_one_node),
+                                deallocate_expr, integer_zero_node);
+    }
+
+  if (loop && deallocate_expr != integer_zero_node)
+    {
+      body = tree_cons (NULL_TREE, loop,
+                       tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
+      body = build_compound_expr (body);
+    }
+  else
+    body = loop;
+
+  /* Outermost wrapper: If pointer is null, punt.  */
+  body = build (COND_EXPR, void_type_node,
+               build (NE_EXPR, boolean_type_node, base, integer_zero_node),
+               body, integer_zero_node);
+  body = build1 (NOP_EXPR, void_type_node, body);
+
+  if (controller)
+    {
+      TREE_OPERAND (controller, 1) = body;
+      return controller;
+    }
+  else
+    return convert (void_type_node, body);
+}
+
+/* Build a tree to cleanup partially built arrays.
+   BASE is that starting address of the array.
+   COUNT is the count of objects that have been built, that need destroying.
+   TYPE is the type of elements in the array.  */
+static tree
+build_array_eh_cleanup (base, count, type)
+     tree base, count, type;
+{
+  tree expr = build_vec_delete_1 (base, count, type, integer_two_node,
+                                 integer_zero_node, 0);
+  return expr;
+}
+
 /* `expand_vec_init' performs initialization of a vector of aggregate
    types.
 
@@ -3350,12 +3534,12 @@ expand_vec_init (decl, base, maxindex, init, from_array)
 
   /* Set to zero in case size is <= 0.  Optimizer will delete this if
      it is not needed.  */
-  rval = get_temp_regvar (TYPE_POINTER_TO (type),
-                         convert (TYPE_POINTER_TO (type), null_pointer_node));
+  rval = get_temp_regvar (build_pointer_type (type),
+                         convert (build_pointer_type (type), null_pointer_node));
   base = default_conversion (base);
-  base = convert (TYPE_POINTER_TO (type), base);
+  base = convert (build_pointer_type (type), base);
   expand_assignment (rval, base, 0, 0);
-  base = get_temp_regvar (TYPE_POINTER_TO (type), base);
+  base = get_temp_regvar (build_pointer_type (type), base);
 
   if (init != NULL_TREE
       && TREE_CODE (init) == CONSTRUCTOR
@@ -3364,7 +3548,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
       /* Initialization of array from {...}.  */
       tree elts = CONSTRUCTOR_ELTS (init);
       tree baseref = build1 (INDIRECT_REF, type, base);
-      tree baseinc = build (PLUS_EXPR, TYPE_POINTER_TO (type), base, size);
+      tree baseinc = build (PLUS_EXPR, build_pointer_type (type), base, size);
       int host_i = TREE_INT_CST_LOW (maxindex);
 
       if (IS_AGGR_TYPE (type))
@@ -3441,6 +3625,8 @@ expand_vec_init (decl, base, maxindex, init, from_array)
 
       expand_start_cond (build (GE_EXPR, boolean_type_node,
                                iterator, integer_zero_node), 0);
+      if (TYPE_NEEDS_DESTRUCTOR (type))
+       start_protect ();
       expand_start_loop_continue_elsewhere (1);
 
       if (from_array)
@@ -3466,18 +3652,18 @@ expand_vec_init (decl, base, maxindex, init, from_array)
        {
          if (init != 0)
            sorry ("cannot initialize multi-dimensional array with initializer");
-         expand_vec_init (decl, build1 (NOP_EXPR, TYPE_POINTER_TO (TREE_TYPE (type)), base),
+         expand_vec_init (decl, build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), base),
                           array_type_nelts (type), 0, 0);
        }
       else
        expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0, 0);
 
       expand_assignment (base,
-                        build (PLUS_EXPR, TYPE_POINTER_TO (type), base, size),
+                        build (PLUS_EXPR, build_pointer_type (type), base, size),
                         0, 0);
       if (base2)
        expand_assignment (base2,
-                          build (PLUS_EXPR, TYPE_POINTER_TO (type), base2, size), 0, 0);
+                          build (PLUS_EXPR, build_pointer_type (type), base2, size), 0, 0);
       expand_loop_continue_here ();
       expand_exit_loop_if_false (0, build (NE_EXPR, boolean_type_node,
                                           build (PREDECREMENT_EXPR, integer_type_node, iterator, integer_one_node), minus_one));
@@ -3489,6 +3675,13 @@ expand_vec_init (decl, base, maxindex, init, from_array)
            use_variable (DECL_RTL (base2));
        }
       expand_end_loop ();
+      if (TYPE_NEEDS_DESTRUCTOR (type))
+       end_protect (build_array_eh_cleanup (rval,
+                                            build_binary_op (MINUS_EXPR,
+                                                             maxindex,
+                                                             iterator,
+                                                             1),
+                                            type));
       expand_end_cond ();
       if (obey_regdecls)
        use_variable (DECL_RTL (iterator));
@@ -3848,7 +4041,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
          else
            this_auto_delete = integer_zero_node;
 
-         expr = build_delete (TYPE_POINTER_TO (BINFO_TYPE (base_binfo)), addr,
+         expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), addr,
                               this_auto_delete, flags, 0);
          exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
        }
@@ -3862,10 +4055,10 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
            continue;
 
          /* May be zero offset if other baseclasses are virtual.  */
-         expr = fold (build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
+         expr = fold (build (PLUS_EXPR, build_pointer_type (BINFO_TYPE (base_binfo)),
                              addr, BINFO_OFFSET (base_binfo)));
 
-         expr = build_delete (TYPE_POINTER_TO (BINFO_TYPE (base_binfo)), expr,
+         expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), expr,
                               integer_zero_node,
                               flags, 0);
 
@@ -3906,7 +4099,7 @@ build_vbase_delete (type, decl)
 
   while (vbases)
     {
-      tree this_addr = convert_force (TYPE_POINTER_TO (BINFO_TYPE (vbases)),
+      tree this_addr = convert_force (build_pointer_type (BINFO_TYPE (vbases)),
                                      addr, 0);
       result = tree_cons (NULL_TREE,
                          build_delete (TREE_TYPE (this_addr), this_addr,
@@ -3941,34 +4134,12 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
      tree auto_delete_vec, auto_delete;
      int use_global_delete;
 {
-  tree ptype, type, virtual_size;
-
-  /* Temporary variables used by the loop.  */
-  tree tbase, size_exp, tbase_init;
-
-  /* This is the body of the loop that implements the deletion of a
-     single element, and moves temp variables to next elements.  */
-  tree body;
-
-  /* This is the LOOP_EXPR that governs the deletion of the elements.  */
-  tree loop;
-
-  /* This is the thing that governs what to do after the loop has run.  */
-  tree deallocate_expr = 0;
-
-  /* This is the BIND_EXPR which holds the outermost iterator of the
-     loop.  It is convenient to set this variable up and test it before
-     executing any other code in the loop.
-     This is also the containing expression returned by this function.  */
-  tree controller = NULL_TREE;
-
-  /* This is the BLOCK to record the symbol binding for debugging.  */
-  tree block;
+  tree type;
 
   if (TREE_CODE (base) == OFFSET_REF)
     base = resolve_offset_ref (base);
 
-  ptype = TREE_TYPE (base);
+  type = TREE_TYPE (base);
 
   base = stabilize_reference (base);
 
@@ -3976,23 +4147,23 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
   if (TREE_SIDE_EFFECTS (base))
     base = save_expr (base);
 
-  if (TREE_CODE (ptype) == POINTER_TYPE)
+  if (TREE_CODE (type) == POINTER_TYPE)
     {
       /* Step back one from start of vector, and read dimension.  */
-      tree cookie_addr = build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type),
+      tree cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type),
                                base, BI_header_size);
       tree cookie = build_indirect_ref (cookie_addr, NULL_PTR);
       maxindex = build_component_ref (cookie, nc_nelts_field_id, 0, 0);
       do
-       ptype = TREE_TYPE (ptype);
-      while (TREE_CODE (ptype) == ARRAY_TYPE);
+       type = TREE_TYPE (type);
+      while (TREE_CODE (type) == ARRAY_TYPE);
     }
-  else if (TREE_CODE (ptype) == ARRAY_TYPE)
+  else if (TREE_CODE (type) == ARRAY_TYPE)
     {
       /* get the total number of things in the array, maxindex is a bad name */
-      maxindex = array_type_nelts_total (ptype);
-      while (TREE_CODE (ptype) == ARRAY_TYPE)
-       ptype = TREE_TYPE (ptype);
+      maxindex = array_type_nelts_total (type);
+      while (TREE_CODE (type) == ARRAY_TYPE)
+       type = TREE_TYPE (type);
       base = build_unary_op (ADDR_EXPR, base, 1);
     }
   else
@@ -4000,129 +4171,7 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
       error ("type to vector delete is neither pointer or array type");
       return error_mark_node;
     }
-  type = ptype;
-  ptype = TYPE_POINTER_TO (type);
-
-  size_exp = size_in_bytes (type);
-
-  if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type))
-    {
-      loop = integer_zero_node;
-      goto no_destructor;
-    }
 
-  /* The below is short by BI_header_size */
-  virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
-
-  tbase = build_decl (VAR_DECL, NULL_TREE, ptype);
-  tbase_init = build_modify_expr (tbase, NOP_EXPR,
-                                 fold (build (PLUS_EXPR, ptype,
-                                              base,
-                                              virtual_size)));
-  DECL_REGISTER (tbase) = 1;
-  controller = build (BIND_EXPR, void_type_node, tbase, 0, 0);
-  TREE_SIDE_EFFECTS (controller) = 1;
-  block = build_block (tbase, 0, 0, 0, 0);
-  add_block_current_level (block);
-
-  if (auto_delete != integer_zero_node
-      && auto_delete != integer_two_node)
-    {
-      tree base_tbd = convert (ptype,
-                              build_binary_op (MINUS_EXPR,
-                                               convert (ptr_type_node, base),
-                                               BI_header_size,
-                                               1));
-      /* This is the real size */
-      virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
-      body = build_tree_list (NULL_TREE,
-                             build_x_delete (ptype, base_tbd,
-                                             2 | use_global_delete,
-                                             virtual_size));
-      body = build (COND_EXPR, void_type_node,
-                   build (BIT_AND_EXPR, integer_type_node,
-                          auto_delete, integer_one_node),
-                   body, integer_zero_node);
-    }
-  else
-    body = NULL_TREE;
-
-  body = tree_cons (NULL_TREE,
-                   build_delete (ptype, tbase, auto_delete,
-                                 LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
-                   body);
-
-  body = tree_cons (NULL_TREE,
-                   build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)),
-                   body);
-
-  body = tree_cons (NULL_TREE,
-                   build (EXIT_EXPR, void_type_node,
-                          build (EQ_EXPR, boolean_type_node, base, tbase)),
-                   body);
-
-  loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body));
-
-  loop = tree_cons (NULL_TREE, tbase_init,
-                   tree_cons (NULL_TREE, loop, NULL_TREE));
-  loop = build_compound_expr (loop);
-
- no_destructor:
-  /* If the delete flag is one, or anything else with the low bit set,
-     delete the storage.  */
-  if (auto_delete_vec == integer_zero_node
-      || auto_delete_vec == integer_two_node)
-    deallocate_expr = integer_zero_node;
-  else
-    {
-      tree base_tbd;
-
-      /* The below is short by BI_header_size */
-      virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
-
-      if (! TYPE_VEC_NEW_USES_COOKIE (type))
-       /* no header */
-       base_tbd = base;
-      else
-       {
-         base_tbd = convert (ptype,
-                             build_binary_op (MINUS_EXPR,
-                                              convert (string_type_node, base),
-                                              BI_header_size,
-                                              1));
-         /* True size with header. */
-         virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
-       }
-      deallocate_expr = build_x_delete (ptype, base_tbd,
-                                       2 | use_global_delete,
-                                       virtual_size);
-      if (auto_delete_vec != integer_one_node)
-       deallocate_expr = build (COND_EXPR, void_type_node,
-                                build (BIT_AND_EXPR, integer_type_node,
-                                       auto_delete_vec, integer_one_node),
-                                deallocate_expr, integer_zero_node);
-    }
-
-  if (loop && deallocate_expr != integer_zero_node)
-    {
-      body = tree_cons (NULL_TREE, loop,
-                       tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
-      body = build_compound_expr (body);
-    }
-  else
-    body = loop;
-
-  /* Outermost wrapper: If pointer is null, punt.  */
-  body = build (COND_EXPR, void_type_node,
-               build (NE_EXPR, boolean_type_node, base, integer_zero_node),
-               body, integer_zero_node);
-  body = build1 (NOP_EXPR, void_type_node, body);
-
-  if (controller)
-    {
-      TREE_OPERAND (controller, 1) = body;
-      return controller;
-    }
-  else
-    return convert (void_type_node, body);
+  return build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
+                            use_global_delete);
 }
index c767349..1861f9e 100644 (file)
@@ -1559,8 +1559,8 @@ reinit_parse_for_method (yychar, decl)
    output if something goes wrong.  This should really be cleaned up somehow,
    without loss of clarity.  */
 void
-reinit_parse_for_block (yychar, obstackp, is_template)
-     int yychar;
+reinit_parse_for_block (pyychar, obstackp, is_template)
+     int pyychar;
      struct obstack *obstackp;
      int is_template;
 {
@@ -1572,23 +1572,35 @@ reinit_parse_for_block (yychar, obstackp, is_template)
   int look_for_semicolon = 0;
   int look_for_lbrac = 0;
 
-  if (yychar == '{')
+  if (pyychar == '{')
     obstack_1grow (obstackp, '{');
-  else if (yychar == '=')
+  else if (pyychar == '=')
     look_for_semicolon = 1;
-  else if (yychar != ':' && (yychar != RETURN || is_template))
+  else if (pyychar == ':')
     {
-      yyerror (is_template
-              ? "parse error in template specification"
-              : "parse error in method specification");
-      obstack_1grow (obstackp, '{');
+      obstack_1grow (obstackp, pyychar);
+      look_for_lbrac = 1;
+      blev = 0;
     }
-  else
+  else if (pyychar == RETURN && !is_template)
+    {
+      obstack_grow (obstackp, "return", 6);
+      look_for_lbrac = 1;
+      blev = 0;
+    }
+  else if (pyychar == TRY && !is_template)
     {
-      obstack_1grow (obstackp, yychar);
+      obstack_grow (obstackp, "try", 3);
       look_for_lbrac = 1;
       blev = 0;
     }
+  else
+    {
+      yyerror (is_template
+              ? "parse error in template specification"
+              : "parse error in method specification");
+      obstack_1grow (obstackp, '{');
+    }
 
   if (nextchar != EOF)
     {
@@ -1640,7 +1652,26 @@ reinit_parse_for_block (yychar, obstackp, is_template)
            {
              blev--;
              if (blev == 0 && !look_for_semicolon)
-               goto done;
+               {
+                 if (pyychar == TRY)
+                   {
+                     if (peekyylex () == CATCH)
+                       {
+                         yylex ();
+                         obstack_grow (obstackp, " catch ", 7);
+                         look_for_lbrac = 1;
+                       }
+                     else
+                       {
+                         yychar = '{';
+                         goto done;
+                       }
+                   }
+                 else
+                   {
+                     goto done;
+                   }
+               }
            }
          else if (c == '\\')
            {
@@ -1783,7 +1814,8 @@ cons_up_default_function (type, full_name, kind)
     if (retref)
       declarator = build_parse_node (ADDR_EXPR, declarator);
     
-    fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
+    fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE,
+                   NULL_TREE, NULL_TREE);
   }
   
   if (fn == void_type_node)
@@ -2278,8 +2310,8 @@ check_newline ()
                }
 #endif
 #endif
+             goto skipline;
            }
-         goto skipline;
        }
       else if (c == 'd')
        {
@@ -2817,6 +2849,9 @@ identifier_type (decl)
 void
 see_typename ()
 {
+  looking_for_typename = 1;
+  if (yychar < 0)
+    if ((yychar = yylex()) < 0) yychar = 0;
   looking_for_typename = 0;
   if (yychar == IDENTIFIER)
     {
@@ -2920,8 +2955,6 @@ do_identifier (token)
   if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id))
     {
       tree shadowed = DECL_SHADOWED_FOR_VAR (id);
-      if (!shadowed)
-       shadowed = IDENTIFIER_GLOBAL_VALUE (DECL_NAME (id));
       if (shadowed)
        {
          if (!DECL_ERROR_REPORTED (id))
@@ -3143,6 +3176,12 @@ real_yylex ()
                *p++ = c;
                c = getc (finput);
              }
+
+           if (linemode && c == '\n')
+             {
+               put_back (c);
+               c = EOF;
+             }
          }
        else
          {
@@ -4668,7 +4707,10 @@ handle_sysv_pragma ()
          handle_pragma_token (NULL_PTR, NULL_TREE);
          return;
        default:
-         abort ();
+         handle_pragma_token (NULL_PTR, NULL_TREE);
+         while (yylex () != END_OF_LINE)
+           /* continue */;
+         return;
        }
     }
 }
index 3fa66c3..a0e1527 100644 (file)
@@ -165,14 +165,6 @@ report_type_mismatch (cp, parmtypes, name_kind)
                cp->function);
       return;
 
-    case -3:
-      if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))))
-       cp_error ("call to const %s `%#D' with non-const object", name_kind,
-                 cp->function);
-      else
-       cp_error ("call to non-const %s `%#D' with const object", name_kind,
-                 cp->function);
-      return;
     case -2:
       cp_error ("too few arguments for %s `%#D'", name_kind, cp->function);
       return;
@@ -180,14 +172,15 @@ report_type_mismatch (cp, parmtypes, name_kind)
       cp_error ("too many arguments for %s `%#D'", name_kind, cp->function);
       return;
     case 0:
-      if (TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE)
-       {
-         /* Happens when we have an ambiguous base class.  */
-         my_friendly_assert (get_binfo (DECL_CLASS_CONTEXT (cp->function),
-                            TREE_TYPE (TREE_TYPE (TREE_VALUE (parmtypes))), 1) == error_mark_node,
-                             241);
-         return;
-       }
+      if (TREE_CODE (TREE_TYPE (cp->function)) != METHOD_TYPE)
+       break;
+    case -3:
+      /* Happens when the implicit object parameter is rejected.  */
+      my_friendly_assert (! TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))),
+                         241);
+      cp_error ("call to non-const %s `%#D' with const object",
+               name_kind, cp->function);
+      return;
     }
 
   ttf = TYPE_ARG_TYPES (TREE_TYPE (cp->function));
@@ -512,6 +505,12 @@ build_overload_value (type, value)
          sorry ("template instantiation with pointer to method that is too complex");
          return;
        }
+      if (TREE_CODE (value) == INTEGER_CST)
+       {
+         build_overload_int (value);
+         numeric_output_need_bar = 1;
+         return;
+       }
       value = TREE_OPERAND (value, 0);
       if (TREE_CODE (value) == VAR_DECL)
        {
@@ -1803,7 +1802,9 @@ make_thunk (function, delta)
     {
       thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl));
       DECL_RESULT (thunk)
-       = build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (vtable_entry_type));
+       = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (vtable_entry_type)));
+      TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type));
+      TREE_THIS_VOLATILE (thunk) = TYPE_VOLATILE (TREE_TYPE (vtable_entry_type));
       make_function_rtl (thunk);
       DECL_INITIAL (thunk) = function;
       THUNK_DELTA (thunk) = delta;
@@ -2249,7 +2250,7 @@ synthesize_method (fndecl)
   input_filename = DECL_SOURCE_FILE (fndecl);
   interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (base);
   interface_only = CLASSTYPE_INTERFACE_ONLY (base);
-  start_function (NULL_TREE, fndecl, NULL_TREE, 1);
+  start_function (NULL_TREE, fndecl, NULL_TREE, NULL_TREE, 1);
   store_parm_decls ();
 
   if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR])
index 895abaa..52ac015 100644 (file)
@@ -131,7 +131,7 @@ empty_parms ()
 /* SCO include files test "ASM", so use something else. */
 %token SIZEOF ENUM /* STRUCT UNION */ IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
 %token BREAK CONTINUE RETURN GOTO ASM_KEYWORD GCC_ASM_KEYWORD TYPEOF ALIGNOF
-%token HEADOF CLASSOF SIGOF
+%token SIGOF
 %token ATTRIBUTE EXTENSION LABEL
 
 /* the reserved words... C++ extensions */
@@ -204,17 +204,17 @@ empty_parms ()
 %type <ttype> direct_notype_declarator direct_after_type_declarator
 
 %type <ttype> structsp opt.component_decl_list component_decl_list
-%type <ttype> component_decl components component_declarator
-%type <ttype> notype_components notype_component_declarator
+%type <ttype> component_decl component_decl_1 components notype_components
+%type <ttype> component_declarator component_declarator0
+%type <ttype> notype_component_declarator notype_component_declarator0
 %type <ttype> after_type_component_declarator after_type_component_declarator0
-%type <ttype> notype_component_declarator0 component_decl_1
 %type <ttype> enumlist enumerator
 %type <ttype> type_id absdcl type_quals
 %type <ttype> direct_abstract_declarator conversion_declarator
 %type <ttype> new_type_id new_declarator direct_new_declarator
 %type <ttype> xexpr parmlist parms parm bad_parm full_parm
 %type <ttype> identifiers_or_typenames
-%type <ttype> fcast_or_absdcl regcast_or_absdcl sub_cast_expr
+%type <ttype> fcast_or_absdcl regcast_or_absdcl
 %type <ttype> expr_or_declarator complex_notype_declarator
 %type <ttype> notype_unqualified_id unqualified_id qualified_id
 %type <ttype> overqualified_id notype_qualified_id any_id
@@ -227,13 +227,13 @@ empty_parms ()
 %token <ttype> PRE_PARSED_CLASS_DECL
 %type <ttype> fn.def1 /* Not really! */
 %type <ttype> fn.def2 return_id
+%type <itype> ctor_initializer_opt
 %type <ttype> named_class_head named_class_head_sans_basetype
 %type <ttype> unnamed_class_head
 %type <ttype> class_head base_class_list
 %type <itype> base_class_access_list
 %type <ttype> base_class maybe_base_class_list base_class.1
 %type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers
-%type <ttype> component_declarator0
 %type <ttype> operator_name
 %type <ttype> object aggr
 %type <itype> new delete
@@ -273,7 +273,12 @@ empty_parms ()
 %{
 /* List of types and structure classes of the current declaration.  */
 static tree current_declspecs;
-static tree prefix_attributes = NULL_TREE;
+/* List of prefix attributes in effect.
+   Prefix attributes are parsed by the reserved_declspecs and declmods
+   rules.  They create a list that contains *both* declspecs and attrs.  */
+/* ??? It is not clear yet that all cases where an attribute can now appear in
+   a declspec list have been updated.  */
+static tree prefix_attributes;
 
 /* When defining an aggregate, this is the most recent one being defined.  */
 static tree current_aggr;
@@ -331,8 +336,7 @@ lang_extdef:
          { if (pending_lang_change) do_pending_lang_change(); }
          extdef
          { if (! toplevel_bindings_p () && ! pseudo_global_level_p())
-             pop_everything ();
-           prefix_attributes = NULL_TREE; }
+             pop_everything (); }
        ;
 
 extdef:
@@ -423,6 +427,10 @@ template_type_parm:
                }
        | aggr identifier
                { $$ = build_tree_list ($1, $2); goto ttpa; }
+       | TYPENAME_KEYWORD
+               { $$ = build_tree_list (class_type_node, NULL_TREE); }
+       | TYPENAME_KEYWORD identifier
+               { $$ = build_tree_list (class_type_node, $2); }
        ;
 
 template_parm:
@@ -496,7 +504,7 @@ template_def:
                  momentary = suspend_momentary ();
                  d = start_decl ($<ttype>2, /*current_declspecs*/NULL_TREE, 0,
                                  $3);
-                 cplus_decl_attributes (d, $5, prefix_attributes);
+                 cplus_decl_attributes (d, $5, /*prefix_attributes*/NULL_TREE);
                  cp_finish_decl (d, NULL_TREE, $4, 0, 0);
                  end_template_decl ($1, d, 0, def);
                  if (def)
@@ -507,15 +515,13 @@ template_def:
          declarator exception_specification_opt maybeasm maybe_attribute
          fn_tmpl_end
                {
-                 tree d;
+                 tree d, specs, attrs;
                  int momentary;
                  int def = ($7 != ';');
-
-                 current_declspecs = $2;
+                 split_specs_attrs ($2, &specs, &attrs);
                  momentary = suspend_momentary ();
-                 d = start_decl ($<ttype>3, current_declspecs,
-                                 0, $<ttype>4);
-                 cplus_decl_attributes (d, $6, prefix_attributes);
+                 d = start_decl ($<ttype>3, specs, 0, $<ttype>4);
+                 cplus_decl_attributes (d, $6, attrs);
                  cp_finish_decl (d, NULL_TREE, $5, 0, 0);
                  end_template_decl ($1, d, 0, def);
                  if (def)
@@ -528,9 +534,11 @@ template_def:
                }
        | template_header declmods notype_declarator fn_tmpl_end
                {
+                 tree d, specs, attrs;
                  int def = ($4 != ';');
-                 tree d = start_decl ($<ttype>3, $<ttype>2, 0, NULL_TREE);
-                 cplus_decl_attributes (d, NULL_TREE, prefix_attributes);
+                 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, 0, 0);
                  end_template_decl ($1, d, 0, def);
                  if (def)
@@ -555,9 +563,10 @@ datadef:
                {}
        /* Normal case to make fast: "const i;".  */
        | declmods notype_declarator ';'
-               { tree d;
-                 d = start_decl ($<ttype>2, $<ttype>$, 0, NULL_TREE);
-                 cplus_decl_attributes (d, NULL_TREE, prefix_attributes);
+               { tree d, specs, attrs;
+                 split_specs_attrs ($1, &specs, &attrs);
+                 d = start_decl ($<ttype>2, specs, 0, NULL_TREE);
+                 cplus_decl_attributes (d, NULL_TREE, attrs);
                  cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
                }
        | typed_declspecs initdecls ';'
@@ -566,9 +575,10 @@ datadef:
                }
        /* Normal case: make this fast.  */
        | typed_declspecs declarator ';'
-               { tree d;
-                 d = start_decl ($<ttype>2, $<ttype>$, 0, NULL_TREE);
-                 cplus_decl_attributes (d, NULL_TREE, prefix_attributes);
+               { tree d, specs, attrs;
+                 split_specs_attrs ($1, &specs, &attrs);
+                 d = start_decl ($<ttype>2, specs, 0, NULL_TREE);
+                 cplus_decl_attributes (d, NULL_TREE, attrs);
                  cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
                  note_list_got_semicolon ($<ttype>$);
                }
@@ -577,7 +587,8 @@ datadef:
        | explicit_instantiation ';'
        | typed_declspecs ';'
          {
-           tree t = $<ttype>$;
+           tree t, attrs;
+           split_specs_attrs ($1, &t, &attrs);
            shadow_tag (t);
            if (TREE_CODE (t) == TREE_LIST
                && TREE_PURPOSE (t) == NULL_TREE)
@@ -599,42 +610,35 @@ datadef:
        | ';'
        ;
 
-fndef:
-         fn.def1 base_init compstmt_or_error
-               {
-                 finish_function (lineno, 1, 0);
-                 /* finish_function performs these three statements:
+ctor_initializer_opt:
+         nodecls
+               { $$ = 0; }
+       | base_init
+               { $$ = 1; }
+       ;
 
-                    expand_end_bindings (getdecls (), 1, 0);
-                    poplevel (1, 1, 0);
+maybe_return_init:
+         /* empty */
+       | return_init
+       | return_init ';'
+       ;
 
-                    expand_end_bindings (0, 0, 0);
-                    poplevel (0, 0, 1);
-                    */
+eat_saved_input:
+         /* empty */
+       | END_OF_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>$);
                }
-       | fn.def1 return_init base_init compstmt_or_error
+       | fn.def1 maybe_return_init function_try_block
                {
-                 finish_function (lineno, 1, 0);
-                 /* finish_function performs these three statements:
-
-                    expand_end_bindings (getdecls (), 1, 0);
-                    poplevel (1, 1, 0);
-
-                    expand_end_bindings (0, 0, 0);
-                    poplevel (0, 0, 1);
-                    */
                  if ($<ttype>$) process_next_inline ($<ttype>$);
                }
-       | fn.def1 nodecls compstmt_or_error
-               { finish_function (lineno, 0, 0);
-                 if ($<ttype>$) process_next_inline ($<ttype>$); }
-       | fn.def1 return_init ';' nodecls compstmt_or_error
-               { finish_function (lineno, 0, 0);
-                 if ($<ttype>$) process_next_inline ($<ttype>$); }
-       | fn.def1 return_init nodecls compstmt_or_error
-               { finish_function (lineno, 0, 0);
-                 if ($<ttype>$) process_next_inline ($<ttype>$); }
+         eat_saved_input
        | typed_declspecs declarator error
                {}
        | declmods notype_declarator error
@@ -645,22 +649,26 @@ fndef:
 
 fn.def1:
          typed_declspecs declarator exception_specification_opt
-               { if (! start_function ($$, $2, $3, 0))
+               { tree specs, attrs;
+                 split_specs_attrs ($1, &specs, &attrs);
+                 if (! start_function (specs, $2, $3, attrs, 0))
                    YYERROR1;
                  reinit_parse_for_function ();
                  $$ = NULL_TREE; }
        | declmods notype_declarator exception_specification_opt
-               { if (! start_function ($$, $2, $3, 0))
+               { tree specs = strip_attrs ($1);
+                 if (! start_function (specs, $2, $3, NULL_TREE, 0))
                    YYERROR1;
                  reinit_parse_for_function ();
                  $$ = NULL_TREE; }
        | notype_declarator exception_specification_opt
-               { if (! start_function (NULL_TREE, $$, $2, 0))
+               { if (! start_function (NULL_TREE, $$, $2, NULL_TREE, 0))
                    YYERROR1;
                  reinit_parse_for_function ();
                  $$ = NULL_TREE; }
        | PRE_PARSED_FUNCTION_DECL
-               { start_function (NULL_TREE, TREE_VALUE ($$), NULL_TREE, 1);
+               { start_function (NULL_TREE, TREE_VALUE ($$),
+                                 NULL_TREE, NULL_TREE, 1);
                  reinit_parse_for_function (); }
        ;
 
@@ -668,9 +676,9 @@ fn.def1:
    reduce/reduce conflict introduced by these rules.  */
 fn.def2:
          typed_declspecs '(' parmlist ')' type_quals exception_specification_opt
-               {
-                 $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1), $3, $5);
-                 $$ = start_method (TREE_CHAIN ($1), $$, $6);
+               { tree specs = strip_attrs ($1);
+                 $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), $3, $5);
+                 $$ = start_method (TREE_CHAIN (specs), $$, $6);
                 rest_of_mdef:
                  if (! $$)
                    YYERROR1;
@@ -678,16 +686,18 @@ fn.def2:
                    yychar = YYLEX;
                  reinit_parse_for_method (yychar, $$); }
        | typed_declspecs LEFT_RIGHT type_quals exception_specification_opt
-               {
-                 $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1),
+               { tree specs = strip_attrs ($1);
+                 $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
                                         empty_parms (), $3);
-                 $$ = start_method (TREE_CHAIN ($1), $$, $4);
+                 $$ = start_method (TREE_CHAIN (specs), $$, $4);
                  goto rest_of_mdef;
                }
        | typed_declspecs declarator exception_specification_opt
-               { $$ = start_method ($$, $2, $3); goto rest_of_mdef; }
+               { tree specs = strip_attrs ($1);
+                 $$ = start_method (specs, $2, $3); goto rest_of_mdef; }
        | declmods notype_declarator exception_specification_opt
-               { $$ = start_method ($$, $2, $3); goto rest_of_mdef; }
+               { tree specs = strip_attrs ($1);
+                 $$ = start_method (specs, $2, $3); goto rest_of_mdef; }
        | notype_declarator exception_specification_opt
                { $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; }
        ;
@@ -804,11 +814,13 @@ explicit_instantiation:
          TEMPLATE specialization template_instantiation
                { do_type_instantiation ($3 ? $3 : $2, NULL_TREE); }
        | TEMPLATE typed_declspecs declarator
-               { do_function_instantiation ($2, $3, NULL_TREE); }
+               { tree specs = strip_attrs ($2);
+                 do_function_instantiation (specs, $3, NULL_TREE); }
        | SCSPEC TEMPLATE specialization template_instantiation
                { do_type_instantiation ($4 ? $4 : $3, $1); }
        | SCSPEC TEMPLATE typed_declspecs declarator
-               { do_function_instantiation ($3, $4, $1); }
+               { tree specs = strip_attrs ($3);
+                 do_function_instantiation (specs, $4, $1); }
        ;
 
 template_type:
@@ -969,7 +981,8 @@ condition:
                  current_declspecs = $1;
                  $<itype>6 = suspend_momentary ();
                  $<ttype>$ = start_decl ($<ttype>2, current_declspecs, 1, $3);
-                 cplus_decl_attributes ($<ttype>$, $5, prefix_attributes);
+                 cplus_decl_attributes ($<ttype>$, $5,
+                                        /*prefix_attributes*/ NULL_TREE);
                }
        init
                { 
@@ -1160,8 +1173,8 @@ regcast_or_absdcl:
        ;
 
 cast_expr:
-         sub_cast_expr
-       | regcast_or_absdcl sub_cast_expr  %prec UNARY
+         unary_expr
+       | regcast_or_absdcl unary_expr  %prec UNARY
                { $$ = reparse_absdcl_as_casts ($$, $2); }
        | regcast_or_absdcl '{' initlist maybecomma '}'  %prec UNARY
                { 
@@ -1176,29 +1189,6 @@ cast_expr:
                }
        ;
 
-sub_cast_expr:
-         unary_expr
-       | HEADOF '(' expr ')'
-               { $$ = build_headof ($3); }
-       | CLASSOF '(' expr ')'
-               { $$ = build_classof ($3); }
-       | CLASSOF '(' TYPENAME ')'
-               { if (is_aggr_typedef ($3, 1))
-                   {
-                     tree type = IDENTIFIER_TYPE_VALUE ($3);
-                     if (! IS_SIGNATURE(type))
-                       $$ = CLASSTYPE_RTTI (type);
-                     else
-                       {
-                         sorry ("signature name as argument of `classof'");
-                         $$ = error_mark_node;
-                       }
-                   }
-                 else
-                   $$ = error_mark_node;
-               }
-       ;
-
 expr_no_commas:
          cast_expr
        /* Handle general members.  */
@@ -1736,10 +1726,6 @@ object:    primary '.'
                }
        ;
 
-setattrs: /* empty */
-               { prefix_attributes = chainon (prefix_attributes, $<ttype>0); }
-       ;
-
 decl:
        /* Normal case: make this fast.  */
          typespec declarator ';'
@@ -1752,10 +1738,12 @@ decl:
                    note_got_semicolon ($1);
                }
        | typed_declspecs declarator ';'
-               { tree d = $1;
-                 int yes = suspend_momentary ();
-                 d = start_decl ($2, d, 0, NULL_TREE);
-                 cplus_decl_attributes (d, NULL_TREE, prefix_attributes);
+               { tree d, specs, attrs;
+                 int yes;
+                 split_specs_attrs ($1, &specs, &attrs);
+                 yes = suspend_momentary ();
+                 d = start_decl ($2, specs, 0, NULL_TREE);
+                 cplus_decl_attributes (d, NULL_TREE, attrs);
                  cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
                  resume_momentary (yes);
                  note_list_got_semicolon ($1);
@@ -1816,7 +1804,8 @@ type_id:
 
 /* Declspecs which contain at least one type specifier or typedef name.
    (Just `const' or `volatile' is not enough.)
-   A typedef'd name following these is taken as a name to be declared.  */
+   A typedef'd name following these is taken as a name to be declared.
+   In the result, declspecs have a non-NULL TREE_VALUE, attributes do not.  */
 
 typed_declspecs:
          typed_typespecs %prec EMPTY
@@ -1852,15 +1841,16 @@ reserved_declspecs:
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = decl_tree_cons (NULL_TREE, $2, $$); }
-       | reserved_declspecs attributes setattrs
-               { $$ = $1; }
-       | attributes setattrs
-               { $$ = NULL_TREE; }
+       | reserved_declspecs attributes
+               { $$ = decl_tree_cons ($2, NULL_TREE, $1); }
+       | attributes
+               { $$ = decl_tree_cons ($1, NULL_TREE, NULL_TREE); }
        ;
 
 /* List of just storage classes and type modifiers.
    A declaration can start with just this, but then it cannot be used
-   to redeclare a typedef-name.  */
+   to redeclare a typedef-name.
+   In the result, declspecs have a non-NULL TREE_VALUE, attributes do not.  */
 
 declmods:
          nonempty_type_quals %prec EMPTY
@@ -1876,13 +1866,12 @@ declmods:
                             IDENTIFIER_POINTER ($2));
                  $$ = decl_tree_cons (NULL_TREE, $2, $$);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declmods attributes setattrs
-               { $$ = $1; }
-       | attributes setattrs
-               { $$ = NULL_TREE; }
+       | declmods attributes
+               { $$ = decl_tree_cons ($2, NULL_TREE, $1); }
+       | attributes
+               { $$ = decl_tree_cons ($1, NULL_TREE, NULL_TREE); }
        ;
 
-
 /* Used instead of declspecs where storage classes are not allowed
    (that is, for typenames and structure components).
 
@@ -1916,11 +1905,11 @@ typespec: structsp
        | complete_type_name
        | TYPEOF '(' expr ')'
                { $$ = TREE_TYPE ($3);
-                 if (pedantic)
+                 if (pedantic && !in_system_header)
                    pedwarn ("ANSI C++ forbids `typeof'"); }
        | TYPEOF '(' type_id ')'
                { $$ = groktypename ($3);
-                 if (pedantic)
+                 if (pedantic && !in_system_header)
                    pedwarn ("ANSI C++ forbids `typeof'"); }
        | SIGOF '(' expr ')'
                { tree type = TREE_TYPE ($3);
@@ -1983,7 +1972,8 @@ maybeasm:
 
 initdcl0:
          declarator exception_specification_opt maybeasm maybe_attribute '='
-               { current_declspecs = $<ttype>0;
+               { split_specs_attrs ($<ttype>0, &current_declspecs,
+                                    &prefix_attributes);
                  if (TREE_CODE (current_declspecs) != TREE_LIST)
                    current_declspecs = get_decl_list (current_declspecs);
                  if (have_extern_spec && !used_extern_spec)
@@ -2002,7 +1992,8 @@ initdcl0:
                  $$ = $<itype>5; }
        | declarator exception_specification_opt maybeasm maybe_attribute
                { tree d;
-                 current_declspecs = $<ttype>0;
+                 split_specs_attrs ($<ttype>0, &current_declspecs,
+                                    &prefix_attributes);
                  if (TREE_CODE (current_declspecs) != TREE_LIST)
                    current_declspecs = get_decl_list (current_declspecs);
                  if (have_extern_spec && !used_extern_spec)
@@ -2033,7 +2024,8 @@ initdcl:
 
 notype_initdcl0:
          notype_declarator exception_specification_opt maybeasm maybe_attribute '='
-               { current_declspecs = $<ttype>0;
+               { split_specs_attrs ($<ttype>0, &current_declspecs,
+                                    &prefix_attributes);
                  $<itype>5 = suspend_momentary ();
                  $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1, $2);
                  cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); }
@@ -2043,7 +2035,8 @@ notype_initdcl0:
                  $$ = $<itype>5; }
        | notype_declarator exception_specification_opt maybeasm maybe_attribute
                { tree d;
-                 current_declspecs = $<ttype>0;
+                 split_specs_attrs ($<ttype>0, &current_declspecs,
+                                    &prefix_attributes);
                  $$ = suspend_momentary ();
                  d = start_decl ($<ttype>1, current_declspecs, 0, $2);
                  cplus_decl_attributes (d, $4, prefix_attributes);
@@ -2053,6 +2046,7 @@ notype_initdcl0:
 nomods_initdcl0:
          notype_declarator exception_specification_opt maybeasm maybe_attribute '='
                { current_declspecs = NULL_TREE;
+                 prefix_attributes = NULL_TREE;
                  $<itype>5 = suspend_momentary ();
                  $<ttype>$ = start_decl ($1, current_declspecs, 1, $2);
                  cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); }
@@ -2063,6 +2057,7 @@ nomods_initdcl0:
        | notype_declarator exception_specification_opt maybeasm maybe_attribute
                { tree d;
                  current_declspecs = NULL_TREE;
+                 prefix_attributes = NULL_TREE;
                  $$ = suspend_momentary ();
                  d = start_decl ($1, current_declspecs, 0, $2);
                  cplus_decl_attributes (d, $4, prefix_attributes);
@@ -2333,23 +2328,22 @@ class_head: unnamed_class_head | named_class_head ;
 maybe_base_class_list:
          %prec EMPTY /* empty */
                { $$ = NULL_TREE; }
-       | ':'  %prec EMPTY
+       | ':' see_typename %prec EMPTY
                { yyungetc(':', 1); $$ = NULL_TREE; }
-       | ':' base_class_list  %prec EMPTY
-               { $$ = $2; }
+       | ':' see_typename base_class_list  %prec EMPTY
+               { $$ = $3; }
        ;
 
 base_class_list:
          base_class
-       | base_class_list ',' base_class
-               { $$ = chainon ($$, $3); }
+       | base_class_list ',' see_typename base_class
+               { $$ = chainon ($$, $4); }
        ;
 
 base_class:
          base_class.1
                {
                  tree type;
-                do_base_class1:
                  type = IDENTIFIER_TYPE_VALUE ($$);
                  if (! is_aggr_typedef ($$, 1))
                    $$ = NULL_TREE;
@@ -2373,14 +2367,13 @@ base_class:
                  else
                    $$ = build_tree_list ((tree)access_default, $$);
                }
-       | base_class_access_list base_class.1
+       | base_class_access_list see_typename base_class.1
                {
                  tree type;
-                do_base_class2:
-                 type = IDENTIFIER_TYPE_VALUE ($2);
+                 type = IDENTIFIER_TYPE_VALUE ($3);
                  if (current_aggr == signature_type_node)
                    error ("access and source specifiers not allowed in signature");
-                 if (! is_aggr_typedef ($2, 1))
+                 if (! is_aggr_typedef ($3, 1))
                    $$ = NULL_TREE;
                  else if (current_aggr == signature_type_node
                           && (! type) && (! IS_SIGNATURE (type)))
@@ -2392,7 +2385,7 @@ base_class:
                    {
                      sorry ("signature inheritance, base type `%s' ignored",
                             IDENTIFIER_POINTER ($$));
-                     $$ = build_tree_list ((tree)access_public, $2);
+                     $$ = build_tree_list ((tree)access_public, $3);
                    }
                  else if (type && IS_SIGNATURE (type))
                    {
@@ -2400,7 +2393,7 @@ base_class:
                      $$ = NULL_TREE;
                    }
                  else
-                   $$ = build_tree_list ((tree) $$, $2);
+                   $$ = build_tree_list ((tree) $$, $3);
                }
        ;
 
@@ -2453,12 +2446,12 @@ base_class.1:
        ;
 
 base_class_access_list:
-         VISSPEC
-       | SCSPEC
+         VISSPEC see_typename
+       | SCSPEC see_typename
                { if ($<ttype>$ != ridpointers[(int)RID_VIRTUAL])
                    sorry ("non-virtual access");
                  $$ = access_default_virtual; }
-       | base_class_access_list VISSPEC
+       | base_class_access_list VISSPEC see_typename
                { int err = 0;
                  if ($2 == access_protected)
                    {
@@ -2484,7 +2477,7 @@ base_class_access_list:
                        $$ = access_private_virtual;
                    }
                }
-       | base_class_access_list SCSPEC
+       | base_class_access_list SCSPEC see_typename
                { if ($2 != ridpointers[(int)RID_VIRTUAL])
                    sorry ("non-virtual access");
                  if ($$ == access_public)
@@ -2610,6 +2603,7 @@ component_decl_list:
 
 component_decl:
          component_decl_1 ';'
+               { }
        | component_decl_1 '}'
                { error ("missing ';' before right brace");
                  yyungetc ('}', 0); }
@@ -2617,6 +2611,10 @@ component_decl:
        /* note that INLINE is like a TYPESPEC */
        | fn.def2 ':' /* base_init compstmt */
                { $$ = finish_method ($$); }
+       | fn.def2 TRY /* base_init compstmt */
+               { $$ = finish_method ($$); }
+       | fn.def2 RETURN /* base_init compstmt */
+               { $$ = finish_method ($$); }
        | fn.def2 '{' /* nodecls compstmt */
                { $$ = finish_method ($$); }
        | ';'
@@ -2628,16 +2626,12 @@ component_decl_1:
           speed; we need to call grok_x_components for enums, so the
           speedup would be insignificant.  */
          typed_declspecs components
-               {
-                 $$ = grok_x_components ($$, $2);
-               }
+               { $$ = grok_x_components ($1, $2); }
        | declmods notype_components
-               { 
-                 $$ = grok_x_components ($$, $2);
-               }
+               { $$ = grok_x_components ($1, $2); }
        | notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
-               { $$ = grokfield ($$, NULL_TREE, $2, $5, $3);
-                 cplus_decl_attributes ($$, $4, prefix_attributes); }
+               { $$ = grokfield ($$, NULL_TREE, $2, $5, $3,
+                                 build_tree_list ($4, NULL_TREE)); }
        | ':' expr_no_commas
                { $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
        | error
@@ -2652,20 +2646,25 @@ component_decl_1:
           member? In other words, is "bar" an after_type_declarator or a
           parmlist? */
        | typed_declspecs '(' parmlist ')' type_quals exception_specification_opt maybeasm maybe_attribute maybe_init
-               { $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1),
+               { tree specs, attrs;
+                 split_specs_attrs ($1, &specs, &attrs);
+                 $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
                                         $3, $5);
-                 $$ = grokfield ($$, TREE_CHAIN ($1), $6, $9, $7);
-                 cplus_decl_attributes ($$, $8, prefix_attributes); }
+                 $$ = grokfield ($$, TREE_CHAIN (specs), $6, $9, $7,
+                                 build_tree_list ($8, attrs)); }
        | typed_declspecs LEFT_RIGHT type_quals exception_specification_opt maybeasm maybe_attribute maybe_init
-               { $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1),
+               { tree specs, attrs;
+                 split_specs_attrs ($1, &specs, &attrs);
+                 $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
                                         empty_parms (), $3);
-                 $$ = grokfield ($$, TREE_CHAIN ($1), $4, $7, $5);
-                 cplus_decl_attributes ($$, $6, prefix_attributes); }
+                 $$ = grokfield ($$, TREE_CHAIN (specs), $4, $7, $5,
+                                 build_tree_list ($6, attrs)); }
        | using_decl
                { $$ = do_class_using_decl ($1); }
        ;
 
 /* The case of exactly one component is handled directly by component_decl. */
+/* ??? Huh? ^^^ */
 components:
          /* empty: possibly anonymous */
                { $$ = NULL_TREE; }
@@ -2708,34 +2707,44 @@ component_declarator:
 
 after_type_component_declarator0:
          after_type_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
-               { current_declspecs = $<ttype>0;
-                 $$ = grokfield ($$, current_declspecs, $2, $5, $3);
-                 cplus_decl_attributes ($$, $4, prefix_attributes); }
+               { split_specs_attrs ($<ttype>0, &current_declspecs,
+                                    &prefix_attributes);
+                 $<ttype>0 = current_declspecs;
+                 $$ = grokfield ($$, current_declspecs, $2, $5, $3,
+                                 build_tree_list ($4, prefix_attributes)); }
        | TYPENAME ':' expr_no_commas maybe_attribute
-               { current_declspecs = $<ttype>0;
+               { split_specs_attrs ($<ttype>0, &current_declspecs,
+                                    &prefix_attributes);
+                 $<ttype>0 = current_declspecs;
                  $$ = grokbitfield ($$, current_declspecs, $3);
                  cplus_decl_attributes ($$, $4, prefix_attributes); }
        ;
 
 notype_component_declarator0:
          notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
-               { current_declspecs = $<ttype>0;
-                 $$ = grokfield ($$, current_declspecs, $2, $5, $3);
-                 cplus_decl_attributes ($$, $4, prefix_attributes); }
+               { split_specs_attrs ($<ttype>0, &current_declspecs,
+                                    &prefix_attributes);
+                 $<ttype>0 = current_declspecs;
+                 $$ = grokfield ($$, current_declspecs, $2, $5, $3,
+                                 build_tree_list ($4, prefix_attributes)); }
        | IDENTIFIER ':' expr_no_commas maybe_attribute
-               { current_declspecs = $<ttype>0;
+               { split_specs_attrs ($<ttype>0, &current_declspecs,
+                                    &prefix_attributes);
+                 $<ttype>0 = current_declspecs;
                  $$ = grokbitfield ($$, current_declspecs, $3);
                  cplus_decl_attributes ($$, $4, prefix_attributes); }
        | ':' expr_no_commas maybe_attribute
-               { current_declspecs = $<ttype>0;
+               { split_specs_attrs ($<ttype>0, &current_declspecs,
+                                    &prefix_attributes);
+                 $<ttype>0 = current_declspecs;
                  $$ = grokbitfield (NULL_TREE, current_declspecs, $2);
                  cplus_decl_attributes ($$, $3, prefix_attributes); }
        ;
 
 after_type_component_declarator:
          after_type_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
-               { $$ = grokfield ($$, current_declspecs, $2, $5, $3);
-                 cplus_decl_attributes ($$, $4, prefix_attributes); }
+               { $$ = grokfield ($$, current_declspecs, $2, $5, $3,
+                                 build_tree_list ($4, prefix_attributes)); }
        | TYPENAME ':' expr_no_commas maybe_attribute
                { $$ = grokbitfield ($$, current_declspecs, $3);
                  cplus_decl_attributes ($$, $4, prefix_attributes); }
@@ -2743,8 +2752,8 @@ after_type_component_declarator:
 
 notype_component_declarator:
          notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
-               { $$ = grokfield ($$, current_declspecs, $2, $5, $3);
-                 cplus_decl_attributes ($$, $4, prefix_attributes); }
+               { $$ = grokfield ($$, current_declspecs, $2, $5, $3,
+                                 build_tree_list ($4, prefix_attributes)); }
        | IDENTIFIER ':' expr_no_commas maybe_attribute
                { $$ = grokbitfield ($$, current_declspecs, $3);
                  cplus_decl_attributes ($$, $4, prefix_attributes); }
@@ -2926,8 +2935,12 @@ complex_direct_notype_declarator:
        | direct_notype_declarator '[' ']'
                { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
        | notype_qualified_id
-               { push_nested_class (TREE_TYPE (OP0 ($$)), 3);
-                 TREE_COMPLEXITY ($$) = current_class_depth; }
+               { if (TREE_TYPE (OP0 ($$)) != current_class_type)
+                   {
+                     push_nested_class (TREE_TYPE (OP0 ($$)), 3);
+                     TREE_COMPLEXITY ($$) = current_class_depth;
+                   }
+               }
        ;
 
 qualified_id:
@@ -3193,8 +3206,7 @@ stmt:
 
 simple_stmt:
          decl
-               { finish_stmt ();
-                 prefix_attributes = NULL_TREE; }
+               { finish_stmt (); }
        | expr ';'
                {
                  tree expr = $1;
@@ -3435,6 +3447,23 @@ simple_stmt:
        | try_block
        ;
 
+function_try_block:
+         TRY
+               {
+                 if (! current_function_parms_stored)
+                   store_parm_decls ();
+                 expand_start_early_try_stmts ();
+               }
+         ctor_initializer_opt compstmt_or_error
+               { expand_end_try_stmts ();
+                 expand_start_all_catch (); }
+         handler_seq
+               {
+                 expand_end_all_catch ();
+                 finish_function (lineno, (int)$3, 0);
+               }
+       ;
+
 try_block:
          TRY
                { expand_start_try_stmts (); }
@@ -3655,10 +3684,12 @@ parms_comma:
 named_parm:
 /*
          typed_declspecs dont_see_typename '*' IDENTIFIER
-               { $$ = build_tree_list ($$, build_parse_node (INDIRECT_REF, $4));
+               { tree specs = strip_attrs ($1);
+                 $$ = build_tree_list (specs, build_parse_node (INDIRECT_REF, $4));
                  see_typename (); }
        | typed_declspecs dont_see_typename '&' IDENTIFIER
-               { $$ = build_tree_list ($$, build_parse_node (ADDR_EXPR, $4));
+               { tree specs = strip_attrs ($1);
+                 $$ = build_tree_list (specs, build_parse_node (ADDR_EXPR, $4));
                  see_typename (); }
        | TYPENAME IDENTIFIER
                { $$ = build_tree_list (get_decl_list ($$), $2);  }
@@ -3668,17 +3699,21 @@ named_parm:
        /* Here we expand typed_declspecs inline to avoid mis-parsing of
           TYPESPEC IDENTIFIER.  */
          typed_declspecs1 declarator
-               { $$ = build_tree_list ($$, $2); }
+               { tree specs = strip_attrs ($1);
+                 $$ = build_tree_list (specs, $2); }
        | typed_typespecs declarator
                { $$ = build_tree_list ($$, $2); }
        | typespec declarator
                { $$ = build_tree_list (get_decl_list ($$), $2); }
        | typed_declspecs1 absdcl
-               { $$ = build_tree_list ($$, $2); }
+               { tree specs = strip_attrs ($1);
+                 $$ = build_tree_list (specs, $2); }
        | typed_declspecs1 %prec EMPTY
-               { $$ = build_tree_list ($$, NULL_TREE); }
+               { tree specs = strip_attrs ($1);
+                 $$ = build_tree_list (specs, NULL_TREE); }
        | declmods notype_declarator
-               { $$ = build_tree_list ($$, $2); }
+               { tree specs = strip_attrs ($1);
+                 $$ = build_tree_list (specs, $2); }
        ;
 
 full_parm:
index a1e718e..3ce0224 100644 (file)
@@ -43,7 +43,6 @@ Boston, MA 02111-1307, USA.  */
 #include "defaults.h"
 
 extern struct obstack permanent_obstack;
-extern tree grokdeclarator ();
 
 extern int lineno;
 extern char *input_filename;
@@ -102,7 +101,7 @@ process_template_parm (list, next)
       my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
       /* is a const-param */
       parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
-                            PARM, 0, NULL_TREE);
+                            PARM, 0, NULL_TREE, NULL_TREE);
       /* A template parameter is not modifiable.  */
       TREE_READONLY (parm) = 1;
       if (IS_AGGR_TYPE (TREE_TYPE (parm)))
@@ -239,7 +238,7 @@ end_template_decl (d1, d2, is_class, defn)
          my_friendly_assert (code == BIT_NOT_EXPR
                  || code == OP_IDENTIFIER
                  || code == SCOPE_REF, 264);
-         d2 = grokdeclarator (d2, NULL_TREE, MEMFUNCDEF, 0, NULL_TREE);
+         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;
@@ -407,12 +406,6 @@ coerce_template_parms (parms, arglist, in_decl)
        }
       if (is_type)
        val = groktypename (arg);
-      else if (TREE_CODE (arg) == STRING_CST)
-       {
-         cp_error ("string literal %E is not a valid template argument", arg);
-         error ("because it is the address of an object with static linkage");
-         val = error_mark_node;
-       }
       else
        {
          tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0),
@@ -431,14 +424,41 @@ coerce_template_parms (parms, arglist, in_decl)
                        arg);
              val = error_mark_node;
            }
-         else if (TREE_CODE (val) == ADDR_EXPR)
+         else if (POINTER_TYPE_P (TREE_TYPE (val))
+                  && ! integer_zerop (val)
+                  && TREE_CODE (TREE_TYPE (TREE_TYPE (val))) != OFFSET_TYPE
+                  && TREE_CODE (TREE_TYPE (TREE_TYPE (val))) != METHOD_TYPE)
            {
-             tree a = TREE_OPERAND (val, 0);
-             if ((TREE_CODE (a) == VAR_DECL
-                  || TREE_CODE (a) == FUNCTION_DECL)
-                 && ! DECL_PUBLIC (a))
+             t = val;
+             STRIP_NOPS (t);
+             if (TREE_CODE (t) == ADDR_EXPR)
+               {
+                 tree a = TREE_OPERAND (t, 0);
+                 STRIP_NOPS (a);
+                 if (TREE_CODE (a) == STRING_CST)
+                   {
+                     cp_error ("string literal %E is not a valid template argument", a);
+                     error ("because it is the address of an object with static linkage");
+                     val = error_mark_node;
+                   }
+                 else if (TREE_CODE (a) != VAR_DECL
+                          && TREE_CODE (a) != FUNCTION_DECL)
+                   goto bad;
+                 else if (! DECL_PUBLIC (a))
+                   {
+                     cp_error ("address of non-extern `%E' cannot be used as template argument", a);
+                     val = error_mark_node;
+                   }
+               }
+             else
                {
-                 cp_error ("address of non-extern `%E' cannot be used as template argument", a);
+               bad:
+                 cp_error ("`%E' is not a valid template argument", t);
+                 error ("it must be %s%s with external linkage",
+                        TREE_CODE (TREE_TYPE (val)) == POINTER_TYPE
+                        ? "a pointer to " : "",
+                        TREE_CODE (TREE_TYPE (TREE_TYPE (val))) == FUNCTION_TYPE
+                        ? "a function" : "an object");
                  val = error_mark_node;
                }
            }
@@ -1714,11 +1734,9 @@ instantiate_template (tmpl, targ_ptr)
   if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE
       && DECL_STATIC_FUNCTION_P (fndecl))
     {
-      tree olddecl = DECL_RESULT (tmpl);
       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 (olddecl) = TREE_CHAIN (DECL_ARGUMENTS (olddecl));
       DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
     }
      
@@ -1726,7 +1744,7 @@ instantiate_template (tmpl, targ_ptr)
 
   /* If we have a preexisting version of this function, don't expand
      the template version, use the other instead.  */
-  if (TREE_STATIC (fndecl))
+  if (TREE_STATIC (fndecl) || DECL_TEMPLATE_SPECIALIZATION (fndecl))
     {
       SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
       p = (struct pending_inline *)0;
@@ -1888,12 +1906,13 @@ overload_template_name (id, classlevel)
 #endif
 }
 
+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;
 {
-  extern struct pending_input *to_be_restored;
   tree t, decl;
 
   processing_template_defn--;
@@ -2502,7 +2521,8 @@ void
 do_function_instantiation (declspecs, declarator, storage)
      tree declspecs, declarator, storage;
 {
-  tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, 0);
+  tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0,
+                             NULL_TREE, NULL_TREE);
   tree name;
   tree fn;
   tree result = NULL_TREE;
index e61f2f2..0ac50a1 100644 (file)
@@ -428,6 +428,18 @@ get_vbase (parent, binfo, depth)
   return rval;
 }
 
+/* Convert EXPR to a virtual base class of type TYPE.  We know that
+   EXPR is a non-null POINTER_TYPE to RECORD_TYPE.  We also know that
+   the type of what expr points to has a virtual base of type TYPE.  */
+tree
+convert_pointer_to_vbase (type, expr)
+     tree type;
+     tree expr;
+{
+  tree vb = get_vbase (type, TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr))), NULL_PTR);
+  return convert_pointer_to_real (vb, expr);
+}
+
 /* This is the newer recursive depth first search routine. */
 #if 0                          /* unused */
 /* Return non-zero if PARENT is directly derived from TYPE.  By directly
@@ -2117,16 +2129,17 @@ get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
   /* Should we use something besides CLASSTYPE_VFIELDS? */
   if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
     {
-      /* Get around first entry reserved for RTTI.  */
-      tree tmp = TREE_CHAIN (BINFO_VIRTUALS (binfo));
+      tree virtuals = BINFO_VIRTUALS (binfo);
+
+      skip_rtti_stuff (&virtuals);
 
-      while (tmp)
+      while (virtuals)
        {
-         tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp));
+         tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
          tree base_fndecl = TREE_OPERAND (base_pfn, 0);
          if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
            abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
-         tmp = TREE_CHAIN (tmp);
+         virtuals = TREE_CHAIN (virtuals);
        }
     }
   return abstract_virtuals;
@@ -2139,7 +2152,7 @@ tree
 get_abstract_virtuals (type)
      tree type;
 {
-  tree vbases, tmp;
+  tree vbases;
   tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
 
   /* First get all from non-virtual bases. */
@@ -2148,17 +2161,17 @@ get_abstract_virtuals (type)
                                               
   for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases))
     {
-      if (! BINFO_VIRTUALS (vbases))
-       continue;
+      tree virtuals = BINFO_VIRTUALS (vbases);
 
-      tmp = TREE_CHAIN (BINFO_VIRTUALS (vbases));
-      while (tmp)
+      skip_rtti_stuff (&virtuals);
+
+      while (virtuals)
        {
-         tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp));
+         tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
          tree base_fndecl = TREE_OPERAND (base_pfn, 0);
          if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
            abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
-         tmp = TREE_CHAIN (tmp);
+         virtuals = TREE_CHAIN (virtuals);
        }
     }
   return nreverse (abstract_virtuals);
@@ -2293,7 +2306,7 @@ convert_pointer_to_single_level (to_type, expr)
   last = get_binfo (to_type, TREE_TYPE (TREE_TYPE (expr)), 0);
   BINFO_INHERITANCE_CHAIN (last) = binfo_of_derived;
   BINFO_INHERITANCE_CHAIN (binfo_of_derived) = NULL_TREE;
-  return build_vbase_path (PLUS_EXPR, TYPE_POINTER_TO (to_type), expr, last, 1);
+  return build_vbase_path (PLUS_EXPR, build_pointer_type (to_type), expr, last, 1);
 }
 
 /* The main function which implements depth first search.
@@ -2517,7 +2530,7 @@ dfs_find_vbases (binfo)
          tree binfo = binfo_member (vbase, vbase_types);
 
          CLASSTYPE_SEARCH_SLOT (vbase)
-           = (char *) build (PLUS_EXPR, TYPE_POINTER_TO (vbase),
+           = (char *) build (PLUS_EXPR, build_pointer_type (vbase),
                              vbase_decl_ptr, BINFO_OFFSET (binfo));
        }
     }
@@ -2549,7 +2562,7 @@ dfs_init_vbase_pointers (binfo)
 
   this_vbase_ptr = vbase_decl_ptr_intermediate;
 
-  if (TYPE_POINTER_TO (type) != TYPE_MAIN_VARIANT (TREE_TYPE (this_vbase_ptr)))
+  if (build_pointer_type (type) != TYPE_MAIN_VARIANT (TREE_TYPE (this_vbase_ptr)))
     my_friendly_abort (125);
 
   while (fields && DECL_NAME (fields)
@@ -2620,6 +2633,18 @@ virtual_context (fndecl, t, vbase)
   tree path;
   if (get_base_distance (DECL_CLASS_CONTEXT (fndecl), t, 0, &path) < 0)
     {
+      /* DECL_CLASS_CONTEXT can be ambiguous in t.  */
+      if (get_base_distance (DECL_CLASS_CONTEXT (fndecl), vbase, 0, &path) >= 0)
+       {
+         while (path)
+           {
+             /* Not sure if checking path == vbase is necessary here, but just in
+                case it is.  */
+             if (TREE_VIA_VIRTUAL (path) || path == vbase)
+               return binfo_member (BINFO_TYPE (path), CLASSTYPE_VBASECLASSES (t));
+             path = BINFO_INHERITANCE_CHAIN (path);
+           }
+       }
       /* This shouldn't happen, I don't want errors! */
       warning ("recoverable compiler error, fixups for virtual function");
       return vbase;
@@ -2666,10 +2691,8 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
       *vbase_offsets = delta;
     }
 
-  /* Skip RTTI fake object. */
-  n = 1;
-  if (virtuals)
-    virtuals = TREE_CHAIN (virtuals);
+  n = skip_rtti_stuff (&virtuals);
+
   while (virtuals)
     {
       tree current_fndecl = TREE_VALUE (virtuals);
@@ -2831,10 +2854,9 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
          else
            {
 #if 1
-             tree vb = get_vbase (TREE_TYPE (vbases), TYPE_BINFO (TREE_TYPE (vbase_decl)),
-                                  NULL_PTR);
-             addr = convert_pointer_to_real (vb, vbase_decl_ptr);
+             addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vbase_decl_ptr);
 #else
+             /* This should should never work better than the above.  (mrs) */
              tree vbinfo = get_binfo (TREE_TYPE (vbases),
                                       TREE_TYPE (vbase_decl),
                                       0);
@@ -3069,13 +3091,107 @@ note_debug_info_needed (type)
 \f
 /* Subroutines of push_class_decls ().  */
 
+/* Add in a decl to the envelope.  */
+static void
+envelope_add_decl (type, decl, values)
+     tree type, decl, *values;
+{
+  tree context, *tmp;
+  tree name = DECL_NAME (decl);
+  int dont_add = 0;
+
+  /* virtual base names are always unique. */
+  if (VBASE_NAME_P (name))
+    *values = NULL_TREE;
+
+  /* Possible ambiguity.  If its defining type(s)
+     is (are all) derived from us, no problem.  */
+  else if (*values && TREE_CODE (*values) != TREE_LIST)
+    {
+      tree value = *values;
+      /* Only complain if we shadow something we can access.  */
+      if (warn_shadow && TREE_CODE (decl) == FUNCTION_DECL
+         && ((DECL_LANG_SPECIFIC (*values)
+              && DECL_CLASS_CONTEXT (value) == current_class_type)
+             || ! TREE_PRIVATE (value)))
+       /* Should figure out access control more accurately.  */
+       {
+         cp_warning_at ("member `%#D' is shadowed", value);
+         cp_warning_at ("by member function `%#D'", decl);
+         warning ("in this context");
+       }
+
+      context = (TREE_CODE (value) == FUNCTION_DECL
+                && DECL_VIRTUAL_P (value))
+       ? DECL_CLASS_CONTEXT (value)
+         : DECL_CONTEXT (value);
+
+      if (context == type)
+       {
+         if (TREE_CODE (value) == TYPE_DECL
+             && DECL_ARTIFICIAL (value))
+           *values = NULL_TREE;
+         else
+           dont_add = 1;
+       }
+      else if (context && TYPE_DERIVES_FROM (context, type))
+       {
+         /* Don't add in *values to list */
+         *values = NULL_TREE;
+       }
+      else
+       *values = build_tree_list (NULL_TREE, value);
+    }
+  else
+    for (tmp = values; *tmp;)
+      {
+       tree value = TREE_VALUE (*tmp);
+       my_friendly_assert (TREE_CODE (value) != TREE_LIST, 999);
+       context = (TREE_CODE (value) == FUNCTION_DECL
+                  && DECL_VIRTUAL_P (value))
+         ? DECL_CLASS_CONTEXT (value)
+           : DECL_CONTEXT (value);
+
+       if (context && TYPE_DERIVES_FROM (context, type))
+         {
+           /* remove *tmp from list */
+           *tmp = TREE_CHAIN (*tmp);
+         }
+       else
+         tmp = &TREE_CHAIN (*tmp);
+      }
+
+  if (! dont_add)
+    {
+      /* Put the new contents in our envelope.  */
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       {
+         *values = tree_cons (name, decl, *values);
+         TREE_NONLOCAL_FLAG (*values) = 1;
+         TREE_TYPE (*values) = unknown_type_node;
+       }
+      else
+       {
+         if (*values)
+           {
+             *values = tree_cons (NULL_TREE, decl, *values);
+             /* Mark this as a potentially ambiguous member.  */
+             /* Leaving TREE_TYPE blank is intentional.
+                We cannot use `error_mark_node' (lookup_name)
+                or `unknown_type_node' (all member functions use this).  */
+             TREE_NONLOCAL_FLAG (*values) = 1;
+           }
+         else
+           *values = decl;
+       }
+    }
+}
+
 /* Add the instance variables which this class contributed to the
-   current class binding contour.  When a redefinition occurs,
-   if the redefinition is strictly within a single inheritance path,
-   we just overwrite (in the case of a data field) or
-   cons (in the case of a member function) the old declaration with
-   the new.  If the fields are not within a single inheritance path,
-   we must cons them in either case.
+   current class binding contour.  When a redefinition occurs, if the
+   redefinition is strictly within a single inheritance path, we just
+   overwrite the old declaration with the new.  If the fields are not
+   within a single inheritance path, we must cons them.
 
    In order to know what decls are new (stemming from the current
    invocation of push_class_decls) we enclose them in an "envelope",
@@ -3114,123 +3230,25 @@ dfs_pushdecls (binfo)
          continue;
        }
 
-#if 0
-      if (TREE_CODE (fields) != TYPE_DECL)
-       {
-         DECL_PUBLIC (fields) = 0;
-         DECL_PROTECTED (fields) = 0;
-         DECL_PRIVATE (fields) = 0;
-       }
-#endif
-
       if (DECL_NAME (fields))
        {
-         tree class_value = IDENTIFIER_CLASS_VALUE (DECL_NAME (fields));
-
-         /* If the class value is an envelope of the kind described in
-            the comment above, we try to rule out possible ambiguities.
-            If we can't do that, keep a TREE_LIST with possibly ambiguous
-            decls in there.  */
-         if (class_value && TREE_CODE (class_value) == TREE_LIST
-             && TREE_PURPOSE (class_value) != NULL_TREE
-             && (TREE_CODE (TREE_PURPOSE (class_value))
-                 != IDENTIFIER_NODE))
-           {
-             tree value = TREE_PURPOSE (class_value);
-             tree context;
-
-             /* Possible ambiguity.  If its defining type(s)
-                is (are all) derived from us, no problem.  */
-             if (TREE_CODE (value) != TREE_LIST)
-               {
-                 context = (TREE_CODE (value) == FUNCTION_DECL
-                            && DECL_VIRTUAL_P (value))
-                   ? DECL_CLASS_CONTEXT (value)
-                     : DECL_CONTEXT (value);
-
-                 if (context == type)
-                   {
-                     if (TREE_CODE (value) == TYPE_DECL
-                         && DECL_ARTIFICIAL (value))
-                       value = fields;
-                     /* else the old value wins */
-                   }
-                 else if (context && TYPE_DERIVES_FROM (context, type))
-                   value = fields;
-                 else
-                   value = tree_cons (NULL_TREE, fields,
-                                      build_tree_list (NULL_TREE, value));
-               }
-             else
-               {
-                 /* All children may derive from us, in which case
-                    there is no problem.  Otherwise, we have to
-                    keep lists around of what the ambiguities might be.  */
-                 tree values;
-                 int problem = 0;
-
-                 for (values = value; values; values = TREE_CHAIN (values))
-                   {
-                     tree sub_values = TREE_VALUE (values);
-
-                     if (TREE_CODE (sub_values) == TREE_LIST)
-                       {
-                         for (; sub_values; sub_values = TREE_CHAIN (sub_values))
-                           {
-                             register tree list_mbr = TREE_VALUE (sub_values);
-
-                             context = (TREE_CODE (list_mbr) == FUNCTION_DECL
-                                        && DECL_VIRTUAL_P (list_mbr))
-                               ? DECL_CLASS_CONTEXT (list_mbr)
-                                 : DECL_CONTEXT (list_mbr);
-
-                             if (! TYPE_DERIVES_FROM (context, type))
-                               {
-                                 value = tree_cons (NULL_TREE, TREE_VALUE (values), value);
-                                 problem = 1;
-                                 break;
-                               }
-                           }
-                       }
-                     else
-                       {
-                         context = (TREE_CODE (sub_values) == FUNCTION_DECL
-                                    && DECL_VIRTUAL_P (sub_values))
-                           ? DECL_CLASS_CONTEXT (sub_values)
-                             : DECL_CONTEXT (sub_values);
-
-                         if (context && ! TYPE_DERIVES_FROM (context, type))
-                           {
-                             value = tree_cons (NULL_TREE, values, value);
-                             problem = 1;
-                             break;
-                           }
-                       }
-                   }
-                 if (! problem) value = fields;
-               }
-
-             /* Mark this as a potentially ambiguous member.  */
-             if (TREE_CODE (value) == TREE_LIST)
-               {
-                 /* Leaving TREE_TYPE blank is intentional.
-                    We cannot use `error_mark_node' (lookup_name)
-                    or `unknown_type_node' (all member functions use this).  */
-                 TREE_NONLOCAL_FLAG (value) = 1;
-               }
-
-             /* Put the new contents in our envelope.  */
-             TREE_PURPOSE (class_value) = value;
-           }
-         else
+         tree name = DECL_NAME (fields);
+         tree class_value = IDENTIFIER_CLASS_VALUE (name);
+
+         /* If the class value is not an envelope of the kind described in
+            the comment above, we create a new envelope.  */
+         if (class_value == NULL_TREE || TREE_CODE (class_value) != TREE_LIST
+             || TREE_PURPOSE (class_value) == NULL_TREE
+             || TREE_CODE (TREE_PURPOSE (class_value)) == IDENTIFIER_NODE)
            {
              /* See comment above for a description of envelopes.  */
-             tree envelope = tree_cons (fields, class_value,
-                                        closed_envelopes);
-
-             closed_envelopes = envelope;
-             IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) = envelope;
+             closed_envelopes = tree_cons (NULL_TREE, class_value,
+                                           closed_envelopes);
+             IDENTIFIER_CLASS_VALUE (name) = closed_envelopes;
+             class_value = IDENTIFIER_CLASS_VALUE (name);
            }
+
+         envelope_add_decl (type, fields, &TREE_PURPOSE (class_value));
        }
     }
 
@@ -3241,78 +3259,32 @@ dfs_pushdecls (binfo)
       methods = &TREE_VEC_ELT (method_vec, 1);
       end = TREE_VEC_END (method_vec);
 
-      /* This does not work for multiple inheritance yet.  */
       while (methods != end)
        {
          /* This will cause lookup_name to return a pointer
-            to the tree_list of possible methods of this name.
-            If the order is a problem, we can nreverse them.  */
-         tree tmp;
-         tree class_value = IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods));
-
-         if (class_value && TREE_CODE (class_value) == TREE_LIST
-             && TREE_PURPOSE (class_value) != NULL_TREE
-             && TREE_CODE (TREE_PURPOSE (class_value)) != IDENTIFIER_NODE)
-           {
-             tree old = TREE_PURPOSE (class_value);
-
-             maybe_push_cache_obstack ();
-             if (TREE_CODE (old) == TREE_LIST)
-               tmp = tree_cons (DECL_NAME (*methods), *methods, old);
-             else
-               {
-                 /* Only complain if we shadow something we can access.  */
-                 if (old
-                     && warn_shadow
-                     && ((DECL_LANG_SPECIFIC (old)
-                          && DECL_CLASS_CONTEXT (old) == current_class_type)
-                         || ! TREE_PRIVATE (old)))
-                   /* Should figure out access control more accurately.  */
-                   {
-                     cp_warning_at ("member `%#D' is shadowed", old);
-                     cp_warning_at ("by member function `%#D'", *methods);
-                     warning ("in this context");
-                   }
-                 tmp = build_tree_list (DECL_NAME (*methods), *methods);
-               }
-             pop_obstacks ();
-
-             TREE_TYPE (tmp) = unknown_type_node;
-#if 0
-             TREE_OVERLOADED (tmp) = DECL_OVERLOADED (*methods);
-#endif
-             TREE_NONLOCAL_FLAG (tmp) = 1;
-             
-             /* Put the new contents in our envelope.  */
-             TREE_PURPOSE (class_value) = tmp;
-           }
-         else
+            to the tree_list of possible methods of this name.  */
+         tree name = DECL_NAME (*methods);
+         tree class_value = IDENTIFIER_CLASS_VALUE (name);
+
+         /* If the class value is not an envelope of the kind described in
+            the comment above, we create a new envelope.  */
+         if (class_value == NULL_TREE || TREE_CODE (class_value) != TREE_LIST
+             || TREE_PURPOSE (class_value) == NULL_TREE
+             || TREE_CODE (TREE_PURPOSE (class_value)) == IDENTIFIER_NODE)
            {
-             maybe_push_cache_obstack ();
-             tmp = build_tree_list (DECL_NAME (*methods), *methods);
-             pop_obstacks ();
-
-             TREE_TYPE (tmp) = unknown_type_node;
-#if 0
-             TREE_OVERLOADED (tmp) = DECL_OVERLOADED (*methods);
-#endif
-             TREE_NONLOCAL_FLAG (tmp) = 1;
-             
              /* See comment above for a description of envelopes.  */
-             closed_envelopes = tree_cons (tmp, class_value,
+             closed_envelopes = tree_cons (NULL_TREE, class_value,
                                            closed_envelopes);
-             IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods)) = closed_envelopes;
+             IDENTIFIER_CLASS_VALUE (name) = closed_envelopes;
+             class_value = IDENTIFIER_CLASS_VALUE (name);
            }
-#if 0
-         tmp = *methods;
-         while (tmp != 0)
-           {
-             DECL_PUBLIC (tmp) = 0;
-             DECL_PROTECTED (tmp) = 0;
-             DECL_PRIVATE (tmp) = 0;
-             tmp = DECL_CHAIN (tmp);
-           }
-#endif
+
+         /* Here we try to rule out possible ambiguities.
+            If we can't do that, keep a TREE_LIST with possibly ambiguous
+            decls in there.  */
+         maybe_push_cache_obstack ();
+         envelope_add_decl (type, *methods, &TREE_PURPOSE (class_value));
+         pop_obstacks ();
 
          methods++;
        }
@@ -3370,41 +3342,6 @@ push_class_decls (type)
   tree id;
   struct obstack *ambient_obstack = current_obstack;
 
-#if 0
-  tree tags = CLASSTYPE_TAGS (type);
-
-  while (tags)
-    {
-      tree code_type_node;
-      tree tag;
-
-      switch (TREE_CODE (TREE_VALUE (tags)))
-       {
-       case ENUMERAL_TYPE:
-         code_type_node = enum_type_node;
-         break;
-       case RECORD_TYPE:
-         code_type_node = record_type_node;
-         break;
-       case CLASS_TYPE:
-         code_type_node = class_type_node;
-         break;
-       case UNION_TYPE:
-         code_type_node = union_type_node;
-         break;
-       default:
-         my_friendly_abort (297);
-       }
-      tag = xref_tag (code_type_node, TREE_PURPOSE (tags),
-                     TYPE_BINFO_BASETYPE (TREE_VALUE (tags), 0), 0);
-#if 0 /* not yet, should get fixed properly later */
-      pushdecl (make_type_decl (TREE_PURPOSE (tags), TREE_VALUE (tags)));
-#else
-      pushdecl (build_decl (TYPE_DECL, TREE_PURPOSE (tags), TREE_VALUE (tags)));
-#endif
-    }
-#endif
-
   search_stack = push_search_level (search_stack, &search_obstack);
 
   id = TYPE_IDENTIFIER (type);
index b50eee4..135dc6d 100644 (file)
@@ -942,12 +942,12 @@ build_signature_method_call (basetype, instance, function, parms)
       deflt_call = build_function_call (pfn, parms);
     }
 
-  new_object_ptr = build (PLUS_EXPR, TYPE_POINTER_TO (basetype),
+  new_object_ptr = build (PLUS_EXPR, build_pointer_type (basetype),
                          convert (ptrdiff_type_node, object_ptr),
                          convert (ptrdiff_type_node, delta));
 
   parms = tree_cons (NULL_TREE,
-                    convert (TYPE_POINTER_TO (basetype), object_ptr),
+                    convert (build_pointer_type (basetype), object_ptr),
                     TREE_CHAIN (parms));
   new_parms = tree_cons (NULL_TREE, new_object_ptr, TREE_CHAIN (parms));
 
@@ -956,7 +956,7 @@ build_signature_method_call (basetype, instance, function, parms)
     tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))));
 
     TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) =
-      build_type_variant (TYPE_POINTER_TO (basetype),
+      build_type_variant (build_pointer_type (basetype),
                          TYPE_READONLY (old_this),
                          TYPE_VOLATILE (old_this));
 
index 5194cf5..4b30b95 100644 (file)
@@ -246,6 +246,13 @@ tree got_scope;
 tree got_object;
 
 int
+peekyylex()
+{
+  scan_tokens (0);
+  return nth_token (0)->yychar;
+}
+
+int
 yylex()
 {
   struct token tmp_token;
index caecaa5..7fb688e 100644 (file)
@@ -236,7 +236,7 @@ build_cplus_new (type, init, with_cleanup_p)
     {
       TREE_OPERAND (rval, 2) = error_mark_node;
       rval = build (WITH_CLEANUP_EXPR, type, rval, 0,
-                   build_delete (TYPE_POINTER_TO (type),
+                   build_delete (build_pointer_type (type),
                                  build_unary_op (ADDR_EXPR, slot, 0),
                                  integer_two_node,
                                  LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0));
@@ -1318,7 +1318,7 @@ void
 debug_binfo (elem)
      tree elem;
 {
-  int i;
+  unsigned HOST_WIDE_INT n;
   tree virtuals;
 
   fprintf (stderr, "type \"%s\"; offset = %d\n",
@@ -1332,20 +1332,17 @@ debug_binfo (elem)
     fprintf (stderr, "no vtable decl yet\n");
   fprintf (stderr, "virtuals:\n");
   virtuals = BINFO_VIRTUALS (elem);
-  if (virtuals != 0)
-    {
-      /* skip the rtti type descriptor entry */
-      virtuals = TREE_CHAIN (virtuals);
-    }
-  i = 1;
+
+  n = skip_rtti_stuff (&virtuals);
+
   while (virtuals)
     {
       tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
       fprintf (stderr, "%s [%d =? %d]\n",
               IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
-              i, TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
+              n, TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
+      ++n;
       virtuals = TREE_CHAIN (virtuals);
-      i += 1;
     }
 }
 
@@ -1567,11 +1564,11 @@ id_cmp (p1, p2)
   return (HOST_WIDE_INT)TREE_VALUE (*p1) - (HOST_WIDE_INT)TREE_VALUE (*p2);
 }
 
-/* Build the FUNCTION_TYPE or METHOD_TYPE which may raise exceptions
+/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions
    listed in RAISES.  */
 tree
-build_exception_variant (ctype, type, raises)
-     tree ctype, type;
+build_exception_variant (type, raises)
+     tree type;
      tree raises;
 {
   int i;
@@ -1903,3 +1900,96 @@ break_out_target_exprs (t)
 {
   return mapcar (t, bot_manip);
 }
+
+tree
+unsave_expr (expr)
+     tree expr;
+{
+  tree t;
+
+  t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr);
+  TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr);
+  return t;
+}
+
+/* Modify a tree in place so that all the evaluate only once things
+   are cleared out.  Return the EXPR given.  */
+tree
+unsave_expr_now (expr)
+     tree expr;
+{
+  enum tree_code code;
+  register int i;
+
+  if (expr == NULL_TREE)
+    return expr;
+
+  code = TREE_CODE (expr);
+  switch (code)
+    {
+    case SAVE_EXPR:
+      SAVE_EXPR_RTL (expr) = NULL_RTX;
+      break;
+
+    case TARGET_EXPR:
+      sorry ("TARGET_EXPR reused inside UNSAVE_EXPR");
+      break;
+      
+    case RTL_EXPR:
+      warning ("RTL_EXPR reused inside UNSAVE_EXPR");
+      RTL_EXPR_SEQUENCE (expr) = NULL_RTX;
+      break;
+
+    case CALL_EXPR:
+      CALL_EXPR_RTL (expr) = NULL_RTX;
+      if (TREE_OPERAND (expr, 1)
+         && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
+       {
+         tree exp = TREE_OPERAND (expr, 1);
+         while (exp)
+           {
+             unsave_expr_now (TREE_VALUE (exp));
+             exp = TREE_CHAIN (exp);
+           }
+       }
+      break;
+      
+    case WITH_CLEANUP_EXPR:
+      warning ("WITH_CLEANUP_EXPR reused inside UNSAVE_EXPR");
+      RTL_EXPR_RTL (expr) = NULL_RTX;
+      break;
+    }
+
+  switch (TREE_CODE_CLASS (code))
+    {
+    case 'c':  /* a constant */
+    case 't':  /* a type node */
+    case 'x':  /* something random, like an identifier or an ERROR_MARK.  */
+    case 'd':  /* A decl node */
+    case 'b':  /* A block node */
+      return expr;
+
+    case 'e':  /* an expression */
+    case 'r':  /* a reference */
+    case 's':  /* an expression with side effects */
+    case '<':  /* a comparison expression */
+    case '2':  /* a binary arithmetic expression */
+    case '1':  /* a unary arithmetic expression */
+      for (i = tree_code_length[(int) code] - 1; i >= 0; i--)
+       unsave_expr_now (TREE_OPERAND (expr, i));
+      return expr;
+
+    default:
+      my_friendly_abort (999);
+    }
+}
+
+/* Since cleanup may have SAVE_EXPRs in it, we protect it with an
+   UNSAVE_EXPR as the backend cannot yet handle SAVE_EXPRs in cleanups
+   by itself.  */
+int
+cp_expand_decl_cleanup (decl, cleanup)
+     tree decl, cleanup;
+{
+  return expand_decl_cleanup (decl, unsave_expr (cleanup));
+}
index 09001db..d4bab51 100644 (file)
@@ -440,7 +440,7 @@ common_type (t1, t2)
          {
            rval = build_function_type (valtype, p2);
            if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
-             rval = build_exception_variant (NULL_TREE, rval, raises);
+             rval = build_exception_variant (rval, raises);
            return build_type_attribute_variant (rval, attributes);
          }
        raises = TYPE_RAISES_EXCEPTIONS (t1);
@@ -448,12 +448,12 @@ common_type (t1, t2)
          {
            rval = build_function_type (valtype, p1);
            if (raises)
-             rval = build_exception_variant (NULL_TREE, rval, raises);
+             rval = build_exception_variant (rval, raises);
            return build_type_attribute_variant (rval, attributes);
          }
 
        rval = build_function_type (valtype, commonparms (p1, p2));
-       rval = build_exception_variant (NULL_TREE, rval, raises);
+       rval = build_exception_variant (rval, raises);
        return build_type_attribute_variant (rval, attributes);
       }
 
@@ -498,7 +498,7 @@ common_type (t1, t2)
          t2 = build_function_type (TREE_TYPE (t2), TREE_CHAIN (TYPE_ARG_TYPES (t2)));
          t3 = common_type (t1, t2);
          t3 = build_cplus_method_type (basetype, TREE_TYPE (t3), TYPE_ARG_TYPES (t3));
-         t1 = build_exception_variant (basetype, t3, raises);
+         t1 = build_exception_variant (t3, raises);
        }
       else
         compiler_error ("common_type called with uncommon method types");
@@ -672,9 +672,9 @@ comptypes (type1, type2, strict)
       return 0;
 
     case OFFSET_TYPE:
-      val = (comptypes (TYPE_POINTER_TO (TYPE_OFFSET_BASETYPE (t1)),
-                        TYPE_POINTER_TO (TYPE_OFFSET_BASETYPE (t2)), strict)
-             && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict));
+      val = (comptypes (build_pointer_type (TYPE_OFFSET_BASETYPE (t1)),
+                       build_pointer_type (TYPE_OFFSET_BASETYPE (t2)), strict)
+            && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict));
       break;
 
     case METHOD_TYPE:
@@ -686,11 +686,9 @@ comptypes (type1, type2, strict)
         to something expecting a derived member (or member function),
         but not vice-versa!  */
 
-      val = (comptypes (TYPE_POINTER_TO (TYPE_METHOD_BASETYPE (t2)),
-                        TYPE_POINTER_TO (TYPE_METHOD_BASETYPE (t1)), strict)
-             && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)
-             && compparms (TREE_CHAIN (TYPE_ARG_TYPES (t1)),
-                           TREE_CHAIN (TYPE_ARG_TYPES (t2)), strict));
+      val = (comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)
+            && compparms (TYPE_ARG_TYPES (t1),
+                          TYPE_ARG_TYPES (t2), strict));
       break;
 
     case POINTER_TYPE:
@@ -742,7 +740,7 @@ comptypes (type1, type2, strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      return 1;
+      return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2);
 
     case UNINSTANTIATED_P_TYPE:
       if (UPT_TEMPLATE (t1) != UPT_TEMPLATE (t2))
@@ -813,7 +811,30 @@ comp_target_types (ttl, ttr, nptrs)
            return comp_ptr_ttypes (ttl, ttr);
        }
 
-      return comp_target_types (ttl, ttr, nptrs - 1);
+      /* Const and volatile mean something different for function types,
+        so the usual checks are not appropriate.  */
+      if (TREE_CODE (ttl) == FUNCTION_TYPE || TREE_CODE (ttl) == METHOD_TYPE)
+       return comp_target_types (ttl, ttr, nptrs - 1);
+
+      /* Make sure that the cv-quals change only in the same direction as
+        the target type.  */
+      {
+       int t;
+       int c = TYPE_READONLY (ttl) - TYPE_READONLY (ttr);
+       int v = TYPE_VOLATILE (ttl) - TYPE_VOLATILE (ttr);
+
+       if ((c > 0 && v < 0) || (c < 0 && v > 0))
+         return 0;
+
+       if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr))
+         return (c + v < 0) ? -1 : 1;
+
+       t = comp_target_types (ttl, ttr, nptrs - 1);
+       if ((t == 1 && c + v >= 0) || (t == -1 && c + v <= 0))
+         return t;
+
+       return 0;
+      }
     }
 
   if (TREE_CODE (ttr) == REFERENCE_TYPE)
@@ -852,9 +873,9 @@ comp_target_types (ttl, ttr, nptrs)
     {
       if (nptrs < 0)
        return 0;
-      if (comptypes (TYPE_POINTER_TO (ttl), TYPE_POINTER_TO (ttr), 0))
+      if (comptypes (build_pointer_type (ttl), build_pointer_type (ttr), 0))
        return 1;
-      if (comptypes (TYPE_POINTER_TO (ttr), TYPE_POINTER_TO (ttl), 0))
+      if (comptypes (build_pointer_type (ttr), build_pointer_type (ttl), 0))
        return -1;
       return 0;
     }
@@ -1408,7 +1429,7 @@ decay_conversion (exp)
                              inner);
              TREE_REFERENCE_EXPR (inner) = 1;
            }
-         return convert (TYPE_POINTER_TO (TREE_TYPE (type)), inner);
+         return convert (build_pointer_type (TREE_TYPE (type)), inner);
        }
 
       if (TREE_CODE (exp) == COMPOUND_EXPR)
@@ -1845,11 +1866,15 @@ build_indirect_ref (ptr, errorstring)
   if (ptr == current_class_decl)
     return C_C_D;
 
-  ptr = build_expr_type_conversion (WANT_POINTER, pointer, 1);
-  if (ptr)
+  if (IS_AGGR_TYPE (type))
     {
-      pointer = ptr;
-      type = TREE_TYPE (pointer);
+      ptr = build_expr_type_conversion (WANT_POINTER, pointer, 1);
+
+      if (ptr)
+       {
+         pointer = ptr;
+         type = TREE_TYPE (pointer);
+       }
     }
 
   if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
@@ -2144,7 +2169,7 @@ build_x_function_call (function, params, decl)
              return error_mark_node;
            }
          /* Yow: call from a static member function.  */
-         decl = build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type),
+         decl = build1 (NOP_EXPR, build_pointer_type (current_class_type),
                         error_mark_node);
          decl = build_indirect_ref (decl, NULL_PTR);
        }
@@ -2223,14 +2248,14 @@ build_x_function_call (function, params, decl)
 
       /* Explicitly named method?  */
       if (TREE_CODE (function) == FUNCTION_DECL)
-       ctypeptr = TYPE_POINTER_TO (DECL_CLASS_CONTEXT (function));
+       ctypeptr = build_pointer_type (DECL_CLASS_CONTEXT (function));
       /* Expression with ptr-to-method type?  It could either be a plain
         usage, or it might be a case where the ptr-to-method is being
         passed in as an argument.  */
       else if (TYPE_PTRMEMFUNC_P (fntype))
        {
          tree rec = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (fntype)));
-         ctypeptr = TYPE_POINTER_TO (rec);
+         ctypeptr = build_pointer_type (rec);
        }
       /* Unexpected node type?  */
       else
@@ -2273,25 +2298,27 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
 
   if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
     {
-      tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
-      tree index = save_expr (build_component_ref (function,
-                                                  index_identifier,
-                                                  0, 0));
-      tree e1 = build (GT_EXPR, boolean_type_node, index,
-                      convert (delta_type_node, integer_zero_node));
-      tree delta = convert (ptrdiff_type_node,
-                           build_component_ref (function, delta_identifier, 0, 0));
-      tree delta2 = DELTA2_FROM_PTRMEMFUNC (function);
-      tree e2;
-      tree e3;
-      tree aref, vtbl;
-
+      tree fntype, index, e1, delta, delta2, e2, e3, aref, vtbl;
       tree instance;
+
       tree instance_ptr = *instance_ptrptr;
 
       if (TREE_SIDE_EFFECTS (instance_ptr))
        instance_ptr = save_expr (instance_ptr);
 
+      if (TREE_SIDE_EFFECTS (function))
+       function = save_expr (function);
+
+      fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
+      index = save_expr (build_component_ref (function,
+                                             index_identifier,
+                                             0, 0));
+      e1 = build (GT_EXPR, boolean_type_node, index,
+                 convert (delta_type_node, integer_zero_node));
+      delta = convert (ptrdiff_type_node,
+                      build_component_ref (function, delta_identifier, 0, 0));
+      delta2 = DELTA2_FROM_PTRMEMFUNC (function);
+
       /* convert down to the right base, before using the instance. */
       instance
        = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
@@ -4409,11 +4436,11 @@ unary_complex_lvalue (code, arg)
          targ = arg;
        else
          targ = build_cplus_new (TREE_TYPE (arg), arg, 1);
-       return build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (arg)), targ);
+       return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), targ);
       }
 
     if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == INDIRECT_REF)
-      return build (SAVE_EXPR, TYPE_POINTER_TO (TREE_TYPE (arg)),
+      return build (SAVE_EXPR, build_pointer_type (TREE_TYPE (arg)),
                     TREE_OPERAND (targ, 0), current_function_decl, NULL);
 
     /* We shouldn't wrap WITH_CLEANUP_EXPRs inside of SAVE_EXPRs, but in case
@@ -4516,6 +4543,8 @@ mark_addressable (exp)
        TREE_ADDRESSABLE (x) = 1;
        TREE_USED (x) = 1;
        TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
+       if (asm_out_file)
+         assemble_external (x);
        return 1;
 
       default:
@@ -4747,7 +4776,7 @@ build_conditional_expr (ifexp, op1, op2)
                cp_pedwarn ("`%T' and `%T' converted to `%T *' in conditional expression",
                            type1, type2, result_type);
 
-             result_type = TYPE_POINTER_TO (result_type);
+             result_type = build_pointer_type (result_type);
            }
        }
       else
@@ -5016,6 +5045,9 @@ tree build_const_cast (type, expr)
   tree intype = TREE_TYPE (expr);
   tree t1, t2;
 
+  if (type == error_mark_node || expr == error_mark_node)
+    return error_mark_node;
+
   if (TYPE_PTRMEMFUNC_P (type))
     type = TYPE_PTRMEMFUNC_FN_TYPE (type);
   if (TYPE_PTRMEMFUNC_P (intype))
@@ -6353,6 +6385,23 @@ build_ptrmemfunc (type, pfn, force)
       npfn = TREE_VALUE (CONSTRUCTOR_ELTS (npfn));
       if (integer_zerop (nindex))
        pfn = integer_zero_node;
+      else if (integer_zerop (fold (size_binop (PLUS_EXPR, nindex, integer_one_node))))
+       {
+         tree e3;
+         delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
+                                       TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
+                                       force);
+         delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1);
+         pfn = build1 (NOP_EXPR, type, npfn);
+         TREE_CONSTANT (pfn) = TREE_CONSTANT (npfn);
+
+         u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, pfn, NULL_TREE));
+         u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
+                                                  tree_cons (NULL_TREE, nindex,
+                                                             tree_cons (NULL_TREE, u, NULL_TREE))));
+         e3 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+         return e3;
+       }
       else
        {
          sorry ("value casting of variable nonnull pointer to member functions not supported");
@@ -6623,7 +6672,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
 
          if (ctt < 0)
            cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
-                       ttr, ttl);
+                       rhstype, type);
 
          if (TYPE_MAIN_VARIANT (ttl) != void_type_node
              && TYPE_MAIN_VARIANT (ttr) == void_type_node
@@ -7388,6 +7437,11 @@ c_expand_return (retval)
        {
          store_expr (result, original_result_rtx, 0);
          expand_cleanups_to (NULL_TREE);
+         use_variable (DECL_RTL (result));
+         if (ctor_label  && TREE_CODE (ctor_label) != ERROR_MARK)
+           expand_goto (ctor_label);
+         else
+           expand_null_return ();
        }
       else if (retval && retval != result)
        {
@@ -7408,12 +7462,6 @@ c_expand_return (retval)
        }
       else
        expand_return (result);
-
-      use_variable (DECL_RTL (result));
-      if (ctor_label  && TREE_CODE (ctor_label) != ERROR_MARK)
-       expand_goto (ctor_label);
-      else
-       expand_null_return ();
     }
   else
     {
@@ -7530,15 +7578,20 @@ comp_ptr_ttypes_real (to, from, constp)
       if (TREE_CODE (to) != TREE_CODE (from))
        return 0;
 
-      if (TYPE_READONLY (from) > TYPE_READONLY (to)
-         || TYPE_VOLATILE (from) > TYPE_VOLATILE (to))
-       return 0;
+      /* Const and volatile mean something different for function types,
+        so the usual checks are not appropriate.  */
+      if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
+       {
+         if (TYPE_READONLY (from) > TYPE_READONLY (to)
+             || TYPE_VOLATILE (from) > TYPE_VOLATILE (to))
+           return 0;
 
-      if (! constp
-         && (TYPE_READONLY (to) > TYPE_READONLY (from)
-             || TYPE_VOLATILE (to) > TYPE_READONLY (from)))
-       return 0;
-      constp &= TYPE_READONLY (to);
+         if (! constp
+             && (TYPE_READONLY (to) > TYPE_READONLY (from)
+                 || TYPE_VOLATILE (to) > TYPE_READONLY (from)))
+           return 0;
+         constp &= TYPE_READONLY (to);
+       }
 
       if (TREE_CODE (to) != POINTER_TYPE)
        return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1);
index ea24acb..653d6a5 100644 (file)
@@ -884,9 +884,15 @@ digest_init (type, init, tail)
 
   if (code == ARRAY_TYPE || code == RECORD_TYPE || code == UNION_TYPE)
     {
-      if (raw_constructor)
+      if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type))
+       {
+         cp_error ("subobject of type `%T' must be initialized by constructor, not by `%E'",
+                   type, init);
+         return error_mark_node;
+       }
+      else if (raw_constructor)
        return process_init_constructor (type, init, (tree *)0);
-      else if (TYPE_NEEDS_CONSTRUCTING (type))
+      else if (TYPE_NON_AGGREGATE_CLASS (type))
        {
          /* This can only be reached when caller is initializing
             ARRAY_TYPE.  In that case, we don't want to convert