summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1999-08-26 09:30:50 +0000
committerobrien <obrien@FreeBSD.org>1999-08-26 09:30:50 +0000
commit0bedf4fb30066e5e1d4342a1d3914dae7d37cba7 (patch)
tree68d8110b41afd0ebbf39167b1a4918eea667a7c5 /contrib/gcc/cp
parentd4db5fb866b7ad5216abd5047774a3973b9901a9 (diff)
downloadFreeBSD-src-0bedf4fb30066e5e1d4342a1d3914dae7d37cba7.zip
FreeBSD-src-0bedf4fb30066e5e1d4342a1d3914dae7d37cba7.tar.gz
Virgin import of gcc from EGCS 1.1.2
Diffstat (limited to 'contrib/gcc/cp')
-rw-r--r--contrib/gcc/cp/ChangeLog15356
-rw-r--r--contrib/gcc/cp/Make-lang.in192
-rw-r--r--contrib/gcc/cp/Makefile.in168
-rw-r--r--contrib/gcc/cp/NEWS226
-rw-r--r--contrib/gcc/cp/call.c6115
-rw-r--r--contrib/gcc/cp/class.c2837
-rw-r--r--contrib/gcc/cp/config-lang.in8
-rw-r--r--contrib/gcc/cp/cp-tree.def240
-rw-r--r--contrib/gcc/cp/cp-tree.h1549
-rw-r--r--contrib/gcc/cp/cvt.c1292
-rw-r--r--contrib/gcc/cp/decl.c8058
-rw-r--r--contrib/gcc/cp/decl.h2
-rw-r--r--contrib/gcc/cp/decl2.c3663
-rw-r--r--contrib/gcc/cp/errfn.c280
-rw-r--r--contrib/gcc/cp/error.c816
-rw-r--r--contrib/gcc/cp/except.c2131
-rw-r--r--contrib/gcc/cp/exception.cc324
-rw-r--r--contrib/gcc/cp/expr.c258
-rw-r--r--contrib/gcc/cp/friend.c484
-rw-r--r--contrib/gcc/cp/g++.132
-rw-r--r--contrib/gcc/cp/g++spec.c269
-rw-r--r--contrib/gcc/cp/gxx.gperf24
-rw-r--r--contrib/gcc/cp/gxxint.texi575
-rw-r--r--contrib/gcc/cp/inc/exception43
-rw-r--r--contrib/gcc/cp/inc/new46
-rw-r--r--contrib/gcc/cp/inc/new.h13
-rw-r--r--contrib/gcc/cp/inc/typeinfo62
-rw-r--r--contrib/gcc/cp/init.c2677
-rw-r--r--contrib/gcc/cp/input.c81
-rw-r--r--contrib/gcc/cp/lang-options.h182
-rw-r--r--contrib/gcc/cp/lang-specs.h67
-rw-r--r--contrib/gcc/cp/lex.c2257
-rw-r--r--contrib/gcc/cp/lex.h18
-rw-r--r--contrib/gcc/cp/method.c2878
-rw-r--r--contrib/gcc/cp/mpw-config.in11
-rw-r--r--contrib/gcc/cp/mpw-make.sed112
-rw-r--r--contrib/gcc/cp/new.cc42
-rw-r--r--contrib/gcc/cp/new1.cc89
-rw-r--r--contrib/gcc/cp/new2.cc80
-rw-r--r--contrib/gcc/cp/parse.y3187
-rw-r--r--contrib/gcc/cp/pt.c7895
-rw-r--r--contrib/gcc/cp/ptree.c61
-rw-r--r--contrib/gcc/cp/repo.c136
-rw-r--r--contrib/gcc/cp/rtti.c1135
-rw-r--r--contrib/gcc/cp/search.c1407
-rw-r--r--contrib/gcc/cp/semantics.c1393
-rw-r--r--contrib/gcc/cp/sig.c149
-rw-r--r--contrib/gcc/cp/spew.c232
-rw-r--r--contrib/gcc/cp/tinfo.cc134
-rw-r--r--contrib/gcc/cp/tinfo.h55
-rw-r--r--contrib/gcc/cp/tinfo2.cc300
-rw-r--r--contrib/gcc/cp/tree.c1801
-rw-r--r--contrib/gcc/cp/typeck.c4128
-rw-r--r--contrib/gcc/cp/typeck2.c514
-rw-r--r--contrib/gcc/cp/xref.c94
55 files changed, 46161 insertions, 30017 deletions
diff --git a/contrib/gcc/cp/ChangeLog b/contrib/gcc/cp/ChangeLog
index 420e25d..5102e32 100644
--- a/contrib/gcc/cp/ChangeLog
+++ b/contrib/gcc/cp/ChangeLog
@@ -1,9473 +1,11057 @@
-Thu Aug 22 23:47:38 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+Sun Mar 14 02:38:07 PST 1999 Jeff Law (law@cygnus.com)
- * Version 2.7.2.3 released.
+ * egcs-1.1.2 Released.
-Mon Apr 29 00:27:53 1996 Jason Merrill <jason@yorick.cygnus.com>
-
- * lex.c (real_yylex): Fix handling of __PRETTY_FUNCTION__ like C
- frontend.
-
-Thu Oct 26 16:45:58 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-
- * errfn.c: Include stdio.h.
- (cp_sprintf): Take out decl of sprintf, and cast sprintf to errorfn*.
-
-Mon Nov 20 14:06:28 1995 Mike Stump <mrs@cygnus.com>
-
- * Version 2.7.2 released.
-
-Mon Nov 20 14:05:00 1995 Mike Stump <mrs@cygnus.com>
-
- * g++.c (pfatal_with_name): Add missing third argument to concat.
-
-Thu Oct 26 13:59:54 1995 Mike Stump <mrs@cygnus.com>
-
- * init.c (expand_aggr_init): Handle cv qualifiers on the object's
- type.
-
-Sun Nov 12 18:09:35 1995 Mike Stump <mrs@cygnus.com>
-
- * Version 2.7.1 released.
-
-Thu Nov 2 17:02:47 1995 Jason Merrill <jason@yorick.cygnus.com>
-
- * call.c (convert_harshness): Handle references to arrays.
-
-Fri Oct 27 14:20:21 1995 Jason Merrill <jason@yorick.cygnus.com>
-
- * typeck.c (comp_target_types): Check multi-level pointer
- conversions in both directions.
-
-Tue Oct 17 21:39:05 1995 Jason Merrill <jason@yorick.cygnus.com>
-
- * parse.y (explicit_instantiation): Fix 'extern template' with no
- return type.
-
-Mon Oct 16 14:35:20 1995 Jason Merrill <jason@yorick.cygnus.com>
+Sun Feb 21 20:38:00 1999 H.J. Lu (hjl@gnu.org)
- * parse.y (explicit_instantiation): Support automatic instantiation
- of constructors.
- (named_class_head_*): Support out-of-class definition of nested
- types.
-
-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.
+ * decl2.c (start_objects): Make file scope constructors and
+ destructors local to the file if ASM_OUTPUT_CONSTRUCTOR and
+ ASM_OUTPUT_DESTRUCTOR are defined.
-Wed Oct 4 22:05:23 1995 Jeff Law (law@hurl.cygnus.com
+Sat Feb 20 15:08:42 1999 Jeffrey A Law (law@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.
+ 1999-01-25 Martin von Löwis <loewis@informatik.hu-berlin.de>
+ * tree.c (equal_functions): New function.
+ (ovl_member): Call it.
-Wed Oct 4 15:06:39 1995 Mike Stump <mrs@cygnus.com>
+Sat Feb 6 17:00:48 1999 Jeffrey A Law (law@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.
+ * typeck2.c: Update email addresses.
-Wed Oct 4 12:47:02 1995 Jason Merrill <jason@yorick.cygnus.com>
+1998-11-16 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>
+ * typeck2.c (my_friendly_abort): Don't fatal twice in a row.
- * tree.c (unsave_expr_now): Make sure we process the argument list
- of any called functions. Fixes incorrect code generation for
- cleanups.
+1998-11-15 Jason Merrill <jason@yorick.cygnus.com>
-Mon Oct 2 13:04:16 1995 Mike Stump <mrs@cygnus.com>
+ * typeck2.c (my_friendly_abort): Add URL in the other case, too.
- * typeck.c (get_member_function_from_ptrfunc): Save function if it
- needs it. Cures core dump on things like (this->*(f()))().
+1998-11-13 Jason Merrill <jason@yorick.cygnus.com>
-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.
+ * rtti.c (synthesize_tinfo_fn): Call import_export_decl here.
+ (get_tinfo_fn): Not here.
-Wed Sep 20 12:35:27 1995 Michael Meissner <meissner@cygnus.com>
+1998-11-08 Mark Mitchell <mark@markmitchell.com>
- * decl.c (init_decl_processing): Add __builtin_expect.
+ * decl.c (grokdeclarator): Tighten checks for invalid
+ destructors. Improve error-messages and error-recovery.
+ * decl2.c (check_classfn): Don't assume that mangled destructor
+ names contain type information.
-Tue Sep 19 16:48:11 1995 Mike Stump <mrs@cygnus.com>
+1998-11-02 Jason Merrill <jason@yorick.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.
+ * decl2.c (import_export_decl): Call import_export_class.
-Fri Sep 15 17:14:47 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+1998-10-28 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (resolve_offset_ref): Fix wording of non-static member
- being referenced as a static.
+ * class.c (finish_struct_1): Don't complain about non-copy
+ assignment ops in union members.
-Fri Sep 15 12:39:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * class.c (build_vtable): Don't pass at_eof to import_export_vtable.
+ (prepare_fresh_vtable): Likewise.
+ (finish_struct_1): Don't call import_export_class.
+ * decl2.c (finish_vtable_vardecl): Do import/export stuff.
+ (finish_prevtable_vardecl): Lose.
+ (finish_file): Don't call it.
+ * pt.c (instantiate_class_template): Likewise.
- * typeck.c (build_indirect_ref): Only bash pointer if we actually
- call build_expr_type_conversion.
+1998-10-23 Martin von Löwis <loewis@informatik.hu-berlin.de>
-Thu Sep 14 18:24:56 1995 Jason Merrill <jason@deneb.cygnus.com>
-
- * cvt.c (build_expr_type_conversion): Handle conversion from
+ * parse.y (condition): Convert VAR_DECL from reference to indirect
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).
+1998-10-18 Jason Merrill <jason@yorick.cygnus.com>
-Mon Sep 11 23:24:07 1995 Mike Stump <mrs@cygnus.com>
+ * method.c (hack_identifier): Just return a member function.
- * except.c (expand_throw): Never allocate storage for thrown pointer
- to objects.
+1998-10-18 Martin von Löwis <loewis@informatik.hu-berlin.de>
-Mon Sep 11 19:36:45 1995 Mike Stump <mrs@cygnus.com>
+ * decl2.c (validate_nonmember_using_decl): Fix using-directives of
+ std if std is ignored.
- * except.c (expand_start_catch_block): Pointers to objects come
- back from catch matching already dereferenced, don't dereference
- again.
+1998-10-14 Jason Merrill <jason@yorick.cygnus.com>
-Mon Sep 11 15:46:28 1995 Mike Stump <mrs@cygnus.com>
+ * spew.c (yylex): Clear looking_for_typename if we got
+ 'enum { ... };'.
- * 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.
+1998-10-13 Jason Merrill <jason@yorick.cygnus.com>
-Mon Sep 11 13:46:45 1995 Mike Stump <mrs@cygnus.com>
+ * tinfo2.cc (fast_compare): Remove.
+ (before): Just use strcmp.
+ * tinfo.cc (operator==): Just use strcmp.
- * error.c (dump_aggr_type): Deal with anonymous unions that don't
- have a TYPE_NAME.
+1998-10-12 Jason Merrill <jason@yorick.cygnus.com>
-Fri Sep 8 20:40:27 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+ * tinfo.cc (operator==): Always compare names.
- * lex.c (handle_sysv_pragma): Deal with getting a comma from yylex.
+1998-10-12 Jason Merrill <jason@yorick.cygnus.com>
-Fri Sep 8 15:51:41 1995 Mike Stump <mrs@cygnus.com>
+ * inc/typeinfo: Add #pragma interface.
+ (operator!=): Just call operator==.
+ * tinfo.cc: Add #pragma implementation.
+ (operator==): Move from inc/typeinfo and tinfo2.cc.
- * except.c (expand_end_eh_spec): Handle empty EH specifications.
+ * typeck2.c (my_friendly_abort): Add URL.
-Fri Sep 8 15:27:22 1995 Mike Stump <mrs@cygnus.com>
+1998-10-05 Martin von Löwis <loewis@informatik.hu-berlin.de>
- * 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.
+ * method.c (build_decl_overload_real): Clear
+ numeric_output_need_bar after __.
-Fri Sep 8 14:40:48 1995 Per Bothner <bothner@kalessin.cygnus.com>
+1998-10-04 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (do_identifier): Use global binding in preference of
- dead for local variable.
+ * decl.c (cp_finish_decl): Make statics in extern inlines and
+ templates common, if possible and the target doesn't support weak
+ symbols.
-Wed Sep 6 19:32:59 1995 Mike Stump <mrs@cygnus.com>
+1998-10-03 Jason Merrill <jason@yorick.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.
+ * decl2.c (merge_functions): Remove duplicates.
-Tue Sep 5 15:56:27 1995 Mike Stump <mrs@cygnus.com>
+ * typeck.c (build_conditional_expr): Only fold if ifexp is an
+ INTEGER_CST.
- * except.c (expand_throw): Run cleanups for the throw expression.
+Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
-Wed Aug 30 15:24:38 1995 Stephen L. Favor (sfavor@tigger.intecom.com)
+ * parse.y (nomods_initdcl0): Set up the parser stack correctly.
- * 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
- for-scoping, but supports (and warns about) old programs.
- Make the new mode (with value 1) the default.
- (lang_f_options): The on-value for flag_new_for_scope is now 2.
- * cp-tree.h (DECL_DEAD_FOR_LOCAL, DECL_ERROR_REPORTED): New macros
- (DECL_SHADOWED_FOR_VAR): Likewise.
- * decl.c (struct binding_level): New fields dead_vars_from_for
- and is_for_scope.
- (note_level_for_for): New function.
- (poplevel): Special processing if is_for_scope.
- (pushdecl): Warn if for-scope variable shadows local.
- * lex.c (do_identifier): Handle old (non-ANSI) for scoping,
- and warn if conflicts.
- * parse.y (FOR): Call note_level_for_for.
-
-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.
+1998-08-25 Jason Merrill <jason@yorick.cygnus.com>
-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>
+ * decl.c (duplicate_decls): Don't complain about different
+ exceptions from an internal decl even if pedantic.
- * 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.
+1998-08-24 Gavin Romig-Koch <gavin@cygnus.com>
- * 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.
+ * typeck.c (c_expand_return): Handle the case that valtype
+ is wider than the functions return type.
-Fri Aug 4 17:17:08 1995 Mike Stump <mrs@cygnus.com>
+1998-08-24 Martin von Löwis <loewis@informatik.hu-berlin.de>
- * 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.
+ * search.c (my_tree_cons): Reimplement.
-Mon Jul 31 13:24:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-08-17 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (report_type_mismatch): Don't talk about an object
- parameter for non-methods.
+ * decl.c (finish_enum): Also set TYPE_SIZE_UNIT.
+ * class.c (finish_struct_bits): Likewise.
-Sun Jul 30 13:13:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-08-17 Mark Mitchell <mark@markmitchell.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.
+ * pt.c (check_explicit_specialization): Don't abort on bogus
+ explicit instantiations.
- * 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.
+1998-08-14 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (report_type_mismatch): Deal with a bad_arg of 0.
+ * rtti.c (get_tinfo_fn): Don't mess with the context for now.
- * init.c (expand_aggr_init): Handle volatile objects, too.
+1998-08-13 Mumit Khan <khan@xraylith.wisc.edu>
-Sat Jul 29 13:42:03 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (import_export_class): Don't use dllexport
+ attribute as a heuristic.
- * 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.
+1998-07-29 Jason Merrill <jason@yorick.cygnus.com>
-Fri Jul 28 15:26:44 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (push_overloaded_decl): Use current_namespace instead of
+ DECL_CONTEXT (decl) to determine where we go.
- * typeck.c (comp_target_types): Don't check const and volatile for
- function types.
- (comp_ptr_ttypes_real): Ditto.
+ * decl.c (lookup_name_real): Fix typo.
-Thu Jul 27 15:40:48 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-07-28 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (comp_target_types): Fix.
+ * class.c (finish_struct_1): Convert integer_zero_node to
+ ssizetype before passing it to set_rtti_entry.
+ * typeck2.c (initializer_constant_valid_p): Allow conversion of 0
+ of any size to a pointer.
-Thu Jul 27 15:10:48 1995 Mike Stump <mrs@cygnus.com>
+1998-07-27 Jason Merrill <jason@yorick.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.
+ * typeck2.c (build_functional_cast): Handle default-initialization.
-Thu Jul 27 10:38:43 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+ * call.c (build_over_call): Pass 1 to popclass.
- * parse.y (typespec): Only complain about typeof if we're not
- getting it from a system header.
+ * parse.y (direct_notype_declarator): Add precedence declaration
+ to notype_unqualified_id case.
+ * Makefile.in (EXPECT): Adjust.
-Thu Jul 27 10:26:23 1995 Doug Evans <dje@canuck.cygnus.com>
+ * tree.c (ovl_member): Fix for single function in OVL.
- 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.
+1998-07-24 Jason Merrill <jason@yorick.cygnus.com>
-Mon Jul 24 13:37:53 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (lookup_name_real): OK, do return the from_obj value
+ unless got_object depends on template parms.
- * 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.
+ * parse.y (nested_name_specifier_1): Pull out the TYPE_MAIN_VARIANT.
- * typeck.c (comp_target_types): Avoid assigning D const * to B *.
+ * pt.c (coerce_template_parms): Also complain about local enums.
-Mon Jul 24 08:54:46 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+ * cp-tree.h: Add prototype for set_identifier_local_value.
+ * decl.c (set_identifier_local_value_with_scope): Make static,
+ prototype.
+ * search.c (covariant_return_p): Likewise.
+ * except.c (build_terminate_handler, alloc_eh_object): Likewise.
- * pt.c (to_be_restored): Move decl to global scope.
+ * call.c (build_method_call): Only pull out the type of a destructor
+ if it's a template type parm.
+ * decl.c (lookup_name_real): Never return the from_obj value.
-Sat Jul 22 12:22:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-07-23 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_decl): Put back clearing of DECL_IN_AGGR_P.
+ * except.c (process_start_catch_block_old): Call start_decl_1 for
+ catch parm.
+ * decl.c (start_decl_1): Avoid duplicate error.
-Fri Jul 21 17:09:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * init.c (expand_default_init): Only perform the initialization if
+ it will do something.
- * decl.c (grokdeclarator): Downgrade error about 'extern int A::i'
- to pedwarn.
+1998-07-23 H.J. Lu (hjl@gnu.org)
- * pt.c (instantiate_template): Also avoid instantiation if the
- function has already been declared to be a specialization.
+ * parse.y (base_class): Check for invalid base class.
- * decl2.c (check_classfn): Ignore cname argument, and return the
- matching function.
+1998-07-23 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_decl): Handle declarations of member functions
- outside of the class (i.e. specialization declarations).
+ * decl2.c (import_export_template): Fold in...
+ (import_export_class): ...to here. Handle dllimport/export.
-Thu Jul 20 10:34:48 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * class.c (build_vtable): Pass at_eof to import_export_vtable.
+ (prepare_fresh_vtable): Likewise.
+ * decl2.c (import_export_class): Split out...
+ (finish_prevtable_vardecl): From here.
+ * class.c (finish_struct_1): Call import_export_class if at_eof.
- * class.c (finish_struct): Don't mess with the type of bitfields.
+ * decl.c (start_function): #if 0 mysterious code I wrote and have
+ forgotten why.
+ * rtti.c (get_tinfo_fn): If this is for a class type, set
+ DECL_CONTEXT.
- * various.c: s/TYPE_POINTER_TO/build_pointer_type/.
+1998-07-22 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jul 20 01:43:10 1995 Mike Stump <mrs@cygnus.com>
+ * inc/exception: Change terminate and unexpected to ().
- * 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.
+ * parse.y (named_class_head_sans_basetype_defn): A
+ named_class_head_sans_basetype followed by '{' or ':' is a defn.
-Wed Jul 19 20:32:01 1995 Mike Stump <mrs@cygnus.com>
+1998-07-21 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (expand_default_init): Don't allow two-level conversions
- during construction.
+ * tree.c (canonical_type_variant): New fn to handle arrays.
+ * cp-tree.h (CANONICAL_TYPE_VARIANT): Remove.
+ * pt.c (unify, default case): Also fold arg. Fix array bounds case.
+ * method.c (process_overload_item): Use build_overload_value for
+ arrays.
-Wed Jul 19 18:06:37 1995 Mike Stump <mrs@cygnus.com>
+1998-07-19 Jason Merrill <jason@yorick.cygnus.com>
- * gc.c (build_headof): The type of dyncasting to a pointer to cv
- void, should be pointer to cv void.
+ * lex.c (do_identifier): Look for class value even if we don't
+ have a global value. Do implicit declaration if parsing is 2.
+ * semantics.c (finish_call_expr): Pass 2 if we're doing Koenig
+ lookup.
-Wed Jul 19 17:25:43 1995 Mike Stump <mrs@cygnus.com>
+1998-07-19 Mark Mitchell <mark@markmitchell.com>
- * gc.c (build_dynamic_cast): Allow casting in const.
+ * decl.c (pushtag): Revert previous change.
+ * pt.c (lookup_template_class): Don't put out debugging
+ information for types that use template parameters.
-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.
- (vt_off_identifier): Renamed from offset_identifier.
- (vb_off_identifier): Added extern declaration.
-
- * decl.c (vt_off_identifier): Renamed from offset identifier.
- (vb_off_identifier): New variable to hold the identifier for the
- sigtable field vb_off.
- (init_decl_processing): Initialize vb_off_identifier.
- Renamed vt_off_identifier from offset_identifier.
- * sig.c (build_signature_method_call): Renamed offset_identifier and
- local variable offset to vt_off_identifer and vt_off, respecitively.
- * sig.c (build_signature_table_constructor): Renamed offset to vt_off.
-
- * decl.c (init_decl_processing): Add vb_off field to
- sigtable_entry_type. Reorder fields so that pfn gets properly
- aligned at a 64 bit boundary on the Alpha.
- * sig.c (build_signature_table_constructor): Build the constructor
- according to the new layout. Set the vb_off field to -1 for now.
-
- * 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>
+ * decl.c (pushtag): Don't put out debugging information for
+ compiler-generated typedefs.
+
+ * error.c (dump_type_real): Don't crash when presented with
+ intQI_type_node or the like.
- * typeck.c (comptypes, case OFFSET_REF): If either offset basetype
- is a TEMPLATE_TYPE_PARM, give a match.
+ * semantics.c (finish_translation_unit): Fix spelling error in
+ comment.
-Mon Jul 3 15:17:20 1995 Steve Chamberlain <sac@slash.cygnus.com>
+1998-07-17 Jason Merrill <jason@yorick.cygnus.com>
- * g++.c (sys/file.h): Remove change of Jun 28.
+ * decl.c (lookup_name_real): Pull out single function here.
+ (select_decl): Not here.
+ (unqualified_namespace_lookup): Use CP_DECL_CONTEXT.
-Fri Jun 30 15:42:57 1995 Mike Stump <mrs@cygnus.com>
+ * decl.c (qualify_lookup): Tweak again.
- * method.c (build_overload_value): Handle encoding of null pointer
- constants (or any pointer with a constant numeric value) for
+ * pt.c (lookup_template_class): Don't mess with the context of the
+ instantiation.
+ * decl2.c (current_decl_namespace): Remove special handling for
templates.
-Fri Jun 30 13:45:51 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+ * pt.c (tsubst, case FUNCTION_DECL): Fix getting complete args for
+ a member template specialization.
- * call.c (convert_harshness): Add QUAL_CODE when we're faced with
- const vs non-const for void conversions.
+ * tree.c (ovl_member): Use decls_match to compare functions.
+ * decl.c (decls_match): Check the context of a function.
-Fri Jun 30 10:19:52 1995 Mike Stump <mrs@cygnus.com>
+ * parse.y (primary): Use notype_unqualified_id instead of IDENTIFIER
+ in Koenig lookup support rules.
+ * semantics.c (finish_call_expr): Handle the new cases.
- * 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.
+ * typeck.c (build_x_function_call): Handle overloaded methods.
-Fri Jun 30 02:22:26 1995 Mike Stump <mrs@cygnus.com>
+ * decl.c (grokvardecl): Don't call build_static_name for extern "C".
- * search.c (dfs_pushdecls): Consume 2 or 3 orders of magnitude less
- memory please when virtual bases are used.
+1998-07-16 Mark Mitchell <mark@markmitchell.com>
-Thu Jun 29 19:03:47 1995 Mike Stump <mrs@cygnus.com>
+ * semantics.c (finish_object_call_expr): Revert previous change.
+ * call.c (build_new_method_call): Likewise. Instead, convert
+ TYPE_DECLs to IDENTIFIERs here, in the presence of templates.
- * 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.
+1998-07-16 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jun 29 09:35:05 1995 Mike Stump <mrs@cygnus.com>
+ * decl.c (qualify_lookup): Handle templates.
- * decl.c (BOOL_TYPE_SIZE): Fix broken SLOW_BYTE_ACCESS check.
+ * decl2.c (do_using_directive): Don't pass ancestor.
+ * decl.c (push_using_directive): Calculate ancestor.
-Thu Jun 29 03:43:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (do_nonmember_using_decl): Allow for type shadowing.
+ * decl.c (pushdecl): Move type shadowing handling from here...
+ (duplicate_decls): ...to here.
+ * decl.c (set_identifier_local_value_with_scope): New fn.
+ (pushdecl): Use it.
+ (set_identifier_local_value, lookup_type_current_level): New fns.
+ * decl2.c (do_local_using_decl): Handle types and binding level
+ stuff properly.
- * pt.c (instantiate_template): Don't strip 'this' twice.
+ * init.c (build_offset_ref): Don't call mark_used on an OVERLOAD.
+ * decl.c (select_decl): Extract a lone function from an OVERLOAD.
+ (lookup_namespace_name): Likewise.
+ * typeck.c (build_unary_op): Not here anymore.
- * pt.c (coerce_template_parms): Allow null pointer constants.
+ * decl2.c (do_class_using_decl): Make sure we get an identifier.
+ * class.c (handle_using_decl): Ignore TYPE_DECLs.
- * decl.c (revert_static_member_fn): But only if DECL_ARGUMENTS is
- set.
+ * decl.c (qualify_lookup): New fn.
+ (lookup_name_real): Use it.
-Wed Jun 28 23:34:58 1995 Steve Chamberlain <sac@slash.cygnus.com>
+1998-07-16 Martin v. Loewis <loewis@informatik.hu-berlin.de>
- * g++.c (pfatal_with_name): Use my_strerror to get error
- string.
- (sys/file.h): Include if HAVE_FILE_H defined.
+ * decl2.c (add_using_namespace): When directly using a namespace
+ that was indirect before, promote it.
-Wed Jun 28 18:39:03 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cp-tree.h (LOOKUP_PREFER_TYPES, LOOKUP_PREFER_NAMESPACES,
+ LOOKUP_PREFER_BOTH, LOOKUP_NAMESPACES_ONLY, LOOKUP_TYPES_ONLY,
+ LOOKUP_QUALIFIERS_ONLY, LOOKUP_TEMPLATES_EXPECTED): New macros.
+ * decl.c (select_decl): Replace two flag parameters by one.
+ (unqualified_namespace_lookup): Likewise, pass flag.
+ (lookup_flags): New function.
+ (lookup_name_real): Compute flags, pass them.
+ (lookup_namespace_name): Call with zero-flag.
+ * decl2.c (ambiguous_decl): Add flag parameter, complain only
+ according to flags.
+ (lookup_using_namespace, qualified_lookup_using_namespace):
+ Add flag parameter, pass them through.
+ * lex.c (do_scoped_id): Call with zero-flag.
- * 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.
+1998-07-16 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jun 28 14:07:27 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+ * typeck.c (convert_for_assignment): Use comptypes.
- * parse.y (component_decl): Clear PREFIX_ATTRIBUTES here.
+1998-07-16 Mark Mitchell <mark@markmitchell.com>
-Wed Jun 28 11:05:13 1995 Mike Stump <mrs@cygnus.com>
+ * semantics.c (finish_object_call_expr): Move test for the
+ function called being a TYPE_DECL to ...
+ * call.c (build_new_method_call): Here.
- * 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.
+1998-07-15 Jason Merrill <jason@yorick.cygnus.com>
-Mon Jun 26 13:38:06 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (arg_assoc_class): Also look at template arguments, if any.
+ (arg_assoc): Handle error_mark_node and multiple levels of TREE_LIST.
- * expr.c (cplus_expand_expr): Don't mess with temp slots.
+ * lex.c (looking_for_typename): Don't initialize.
- * decl2.c (warn_if_unknown_interface): Don't crash if tinst_for_decl
- returns null.
+ * decl2.c (ambiguous_decl): Clarify error message.
- * decl2.c (check_classfn): Use revert_static_member_fn.
- * decl.c (revert_static_member_fn): Diagnose static member functions
- declared const or volatile.
+ * decl.c (push_using_directive): Iterate over namespaces used
+ indirectly.
- * decl2.c (grokfield): Check for missing default args here, too.
- (check_default_args): Function to do the checking.
- * decl.c (pushdecl): Use it.
+1998-07-15 Martin v. Löwis <loewis@informatik.hu-berlin.de>
- * decl.c (pushdecl): Don't warn about shadowing a member of `this'
- if there is no `this'.
+ * decl2.c (add_using_namespace): Iterate over namespaces used
+ indirectly.
-Sun Jun 25 11:34:25 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (lookup_name_real): Accept namespace aliases as locals.
+ (cat_namespace_levels): Ignore aliases.
+ (duplicate_decls): Ignore duplicate aliases.
+ * decl2.c (do_namespace_alias): Process block level namespace
+ aliases. Store alias with pushdecl. Remove odr errors.
+ * parse.y (namespace_alias): New non-terminal.
+ (extdef): Use it.
- * call.c (build_method_call): Downgrade 'called before definition'
- to a warning, as it ought to go away after Monterey.
+1998-07-15 Jason Merrill <jason@yorick.cygnus.com>
-Sat Jun 24 14:18:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (arg_assoc_type): Handle METHOD_TYPE like FUNCTION_TYPE.
+ Handle TEMPLATE_TYPE_PARM.
+ (arg_assoc): Rewrite.
- * pt.c (coerce_template_parms): Don't do extra checking on pointer
- to member arguments.
+ * pt.c (complete_template_args): Don't look at the context unless
+ we have to.
- * class.c (finish_struct): const and reference members don't prevent
- a class from being an aggregate.
+ * method.c (build_decl_overload_real): Fix namespace handling.
- * class.c (finish_struct): Signatures are always aggregates.
+ * typeck.c (build_unary_op): Extract a lone function from an
+ OVERLOAD.
-Fri Jun 23 17:20:29 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (build_scoped_method_call): Handle getting a namespace
+ for basetype in a destructor call.
+ (check_dtor_name): Handle enums.
- * decl2.c (check_classfn): Improve error message.
+ * parse.y (using_directive): New nonterminal.
+ (extdef, simple_stmt): Use it.
- * pt.c (tsubst): Handle PROMOTE_PROTOTYPES.
+1998-07-14 Martin von Löwis <loewis@informatik.hu-berlin.de>
-Thu Jun 22 01:50:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (add_function): Move error message ...
+ (arg_assoc_namespace): ... from here.
- * typeck.c (comptypes): Don't ignore method quals.
+1998-07-14 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Non-abstract virtuals are always USED.
+ * parse.y (namespace_qualifier): Fix multiple level handling.
+ * decl2.c (namespace_ancestor): Use CP_DECL_CONTEXT.
+ (arg_assoc): Don't skip the first argument of a function.
- * 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.
+ * call.c (joust): Don't warn about "confusing" conversions to the
+ same type.
- * 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.
+1998-07-14 Martin von Löwis <loewis@informatik.hu-berlin.de>
- * 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.
+ * class.c (push_nested_class): Complain about namespaces.
+ * decl.c (start_decl): Enter the object's namespace.
+ (cp_finish_decl): Leave it.
+ (grokdeclarator): Likewise.
+ * decl2.c (check_decl_namespace): New function.
+ (finish_file): Call it.
+ * parse.y (complex_direct_notype_declarator): Set complexity
+ of namespace-qualified ids to -1, enter the namespace.
- * typeck.c (build_conditional_expr): Use convert (boolean_type_node
- instead of truthvalue_conversion.
+ * method.c (build_template_decl_overload): Expect _DECL as first
+ parameter. Put context temporarily into current_namespace.
+ * pt.c (check_explicit_specialization): Change caller.
+ (tsubst): Likewise.
- * class.c (finish_struct): A data member with the same name as the
- class doesn't suppress constructors.
+ * init.c (build_offset_ref): Call mark_used and
+ convert_from_reference for namespace members.
-Fri Jun 16 18:11:39 1995 Gerald Baumgartner (gb@alexander.cs.purdue.edu)
+Mon Jul 13 23:25:28 1998 Martin von Lvwis <loewis@informatik.hu-berlin.de>
- * decl.c (start_function): If current_class_decl is a signature
- pointer, don't dereference it but set C_C_D to current_class_decl.
+ * search.c (my_tree_cons): The bitfield is at index 2.
-Fri Jun 16 17:06:28 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Mon Jul 13 17:21:01 1998 Nick Clifton <nickc@cygnus.com>
- * decl.c (duplicate_decls): Complain about virtual functions
- redeclared to be inline.
+ * lang-options.h: Format changed to work with new --help support
+ in gcc/toplev.c
+
+1998-07-12 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl2.c (build_expr_from_tree): Change calls of do_identifier.
+ Do Koenig lookup in CALL_EXPR.
+ (arg_assoc): Handle error_mark.
+ * lex.c (is_global): New function.
+ (do_identifier): Expect arguments for Koenig lookup.
+ * parse.y (primary): Add rules for calls of unqualified function calls.
+ (do_id): Change call of do_identifier.
+ * pt.c (finish_stmt_expr): Likewise.
+ * semantics.c (finish_id_expr): Likewise.
+ (finish_call_expr): Add integer parameter to indicate
+ argument-dependent lookup.
+
+ * decl.c (struct binding_level): New field using_directives.
+ (push_using_decl): Not sorry anymore.
+ (push_using_directive): New function.
+ (lookup_tag): Use CP_DECL_CONTEXT to iterate.
+ (unqualified_namespace_lookup): New function, code from ...
+ (lookup_name_real): ... here.
+ * decl2.c (lookup_using_namespace): Pass using list instead of
+ initial scope.
+ (validate_nonmember_using_decl): New function.
+ (do_nonmember_using_decl): New function.
+ (do_toplevel_using_decl): Use them.
+ (do_local_using_decl): New function.
+ (do_using_directive): Support block-level directives.
+ * parse.y (simple_stmt): Support using declarations and
+ directives.
+ (namespace_qualifier, namespace_using_decl): New non-terminals.
+
+ * xref.c (classname): New function.
+ (GNU_xref_hier): Change class and base parameters to tree.
+ * decl.c (xref_baseypes): Change caller.
+ * friend.c (make_friend_class): Likewise.
+
+1998-07-12 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+
+ * typeck.c (comptypes, case TEMPLATE_TEMPLATE_PARM): Add parameter
+ comparison.
+
+ * pt.c (for_each_template_parm, case TEMPLATE_DECL): If it is a
+ template template parameter, record its use.
+ (for_each_template_parm, case TEMPLATE_TEMPLATE_PARM): Traverse
+ its template arguments if exists.
+
+ * pt.c (coerce_template_template_parms): New function equivalent
+ to coerce_template_parms when IS_TMPL_PARM is true.
+ (coerce_template_parms): Use it. Remove the IS_TMPL_PARM parameter,
+ all callers changed.
+
+ (coerce_template_parms): Access ARGLIST properly when creating a
+ new vector. Only accept implicit TYPE_DECL as valid argument for
+ a template template parameter when it is a base class of
+ current_class_type. Don't display error message when COMPLAIN is
+ false.
+
+1998-07-12 Klaus Kaempf (kkaempf@progis.de)
+
+ * repo.c (get_base_filename): Use file_name_nondirectory.
+ (open_repo_file): Ditto.
+ * cp-tree.h (file_name_nondirectory): Add prototype.
+
+1998-07-12 Jason Merrill <jason@yorick.cygnus.com>
+
+ * friend.c (do_friend): Pull the identifier out of declarator.
+ Use cp_error and friends.
+ * decl2.c (qualified_lookup_using_namespace): Fix call to
+ purpose_member.
+ * decl.c (lookup_name_real): Don't call complete_type on a namespace.
+ (grokvardecl): Use DECL_CLASS_SCOPE_P.
+ * cvt.c (convert_pointer_to_real): Check for error_mark_node sooner.
+ * class.c (warn_hidden): Fix for OVERLOAD.
+ From grahams@rcp.co.uk:
+ * cp-tree.h (DEFARG_NODE_CHECK): New macro.
+ (DEFARG_LENGTH, DEFARG_POINTER): Use it.
+
+Sun Jul 12 01:20:57 1998 Jeffrey A Law (law@cygnus.com)
+
+ * g++.1 (-traditional): Remove duplicated documentation.
+
+1998-07-11 Mark Mitchell <mark@markmitchell.com>
+
+ * method.c (flush_repeats): Add nrepeats parameter.
+ (issue_nrepeats): Likewise.
+ (is_back_referenceable_type): New function. Don't back-reference
+ TEMPLATE_TYPE_PARMs as well as simple types like integers.
+ (build_mangled_name_for_type): Likewise.
+ (build_mangled_name_for_type_with_Gcode): Likewise.
+ (lasttype): Remove.
+ (nrepeats): Likewise.
+ (Nrepeats): Likewise.
+ (start_squangling): Don't clear the variables removed above.
+ (end_squangling): Likewise.
+ (flush_repeats): Tidy. Use nrepeats parameter rather than
+ Nrepeats global.
+ (issue_nrepeats): Likewise, but with nrepeats global. Use
+ is_backreferenceable_type.
+ (build_overload_nested_name): Tidy. Add comment. Use
+ build_mangled_name_for_type.
+ (build_underscore_int): Comment.
+ (build_overload_scope_ref): Use build_mangled_name_for_type.
+ (build_overload_int): Likewise.
+ (build_template_template_parm_names): Tidy.
+ (build_template_parm_names): Use build_mangled_name_for_type.
+ (build_overload_identifier): Add comments.
+ (build_mangled_name_for_type_with_Gcode): Split out from
+ build_mangled_name.
+ (build_mangled_name_for_type): Use it.
+ (build_mangled_name): Rework to use build_mangled_name_for_type
+ and to not use global nrepeats/Nrepeats. Tidy.
+ (process_modifiers): Tidy.
+ (check_btype): Use is_backreferenceable_type. Add comment.
+ Rename `node' to `type'.
+ (process_overload_item): Set numeric_output_need_bar here.
+ Use build_mangled_name_for_type. Tidy.
+ (build_decl_overload_real): Tidy. Don't use Nrepeats. Use
+ build_mangled_name_for_type.
+
+ * pt.c (push_template_decl_real): Don't look at DECL_TEMPLATE_INFO
+ for TYPE_DECLs.
+
+1998-07-08 Vladimir N. Makarov <vmakarov@cygnus.com>
+
+ * cp-tree.h (warn_long_long): Define.
+ * decl.c (grokdeclarator): Add flag `warn_long_long' as guard for
+ warning "ANSI C++ does not support `long long'".
+ * decl2.c (warn_long_long): Define.
+ (lang_decode_option): Parse -Wlong-long, -Wno-long-long options.
+
+1998-07-07 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (xref_tag): Handle attributes between 'class' and name.
+ * parse.y (aggr): Likewise.
+ * semantics.c (finish_class_definition): Likewise.
+ * Makefile.in (EXPECTED): Adjust.
+
+ * cp-tree.h: Declare flag_optional_diags and warn_multichar.
+ * decl2.c: Define them.
+ (lang_decode_option): Handle them.
+ * lang-options.h: Add -foptional-diags.
+ * class.c (finish_struct): Don't complain about multiple meanings of
+ name if -fno-optional-diags.
+ * decl.c (pushdecl_class_level): Likewise.
+ * lex.c (real_yylex): Check warn_multichar.
+
+1998-07-06 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (lookup_tag): Use CP_DECL_CONTEXT.
+
+ * tree.c (make_binfo): Fix length.
+
+1998-06-30 Benjamin Kosnik <bkoz@bliss.nabi.net>
+
+ * decl2.c (lang_decode_option): Remove warn_template_debugging.
+ * lang-options.h: Ditto.
-Fri Jun 16 13:20:38 1995 Mike Stump <mrs@cygnus.com>
+Mon Jun 29 20:17:40 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * except.c (build_eh_type_type_ref): Remove unused variable `susp'.
+ (process_start_catch_block): Likewise for variables
+ `false_label_rtx', `call_rtx' and `return_value_rtx'.
+
+1998-06-29 Brendan Kehoe <brendan@cygnus.com>
+
+ * tree.c (build_srcloc): Make sure we allocate this node on the
+ permanent obstack.
+
+Sat Jun 27 23:34:18 1998 Fred Fish <fnf@ninemoons.com>
+
+ * g++spec.c (NEED_MATH_LIBRARY): Define to 1 if not already defined.
+ (lang_specific_driver): Initialize need_math with NEED_MATH_LIBRARY.
+ (lang_specific_driver): Only add -lm automatically if need_math is
+ nonzero.
- * decl.c (get_unique_name): New routine to name unnamed namespaces.
- (push_namespace): Use get_unique_name for naming unnamed namespaces.
+Sat Jun 27 12:22:56 1998 Jeffrey A Law (law@cygnus.com)
-Fri Jun 16 15:07:29 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+ * Make-lang.in (g++): Depend on mkstemp.o. Link in mkstemp.o
- * Make-lang.in (DEMANGLER_PROG): Add LIBS.
+Sat Jun 27 07:36:09 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Thu Jun 15 15:00:41 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * Makefile.in (EXPR_H): New dependency variable.
+ (decl2.o): Depend on $(EXPR_H).
+ (typeck.o): Likewise.
+ (init.o): Likewise.
+ (expr.o): Likewise.
+
+1998-06-25 Benjamin Kosnik <bkoz@lisa.cygnus.com>
- * decl.c (define_function): Don't set DECL_INTERFACE_KNOWN.
+ * decl.c (start_enum): Put local enums on permanent_obstack.
- * parse.y: Call cplus_decl_attributes with prefix_attributes where
- appropriate.
+1998-06-25 Mark Mitchell <mark@markmitchell.com>
-Wed Jun 14 19:24:49 1995 Mike Stump <mrs@cygnus.com>
+ * cp-tree.h (c_get_alias_set): Declare.
+ * decl.c (init_decl_processing): Set lang_get_alias_set.
- * search.c (get_vbase): New routine to switch hierarchies from the
- CLASSTYPE_VBASECLASSES to the normal one.
- (expand_indirect_vtbls_init): Use get_vbase to figure out how we
- want to convert to a vbase pointer.
+1998-06-25 Andrew MacLeod <amacleod@cygnus.com>
-Mon Jun 12 17:50:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cp-tree.h (mark_all_runtime_matches): Add function prototype.
+ * except.c (mark_all_runtime_matches): Set TREE_SYMBOL_REFERENCED
+ flag for all function decls which are in the exception table.
+ * exception.cc (__cplus_type_matcher): Check for CATCH_ALL_TYPE match.
+ * decl2.c (finish_file): Call mark_all_runtime_matches to make sure
+ code is emitted for any referenced rtti function.
- * pt.c (instantiate_class_template): Add the new instantiation to
- template_classes.
- (do_pending_expansions): Call instantiate_member_templates on all of
- the classes in template_classes.
+1998-06-25 Dave Brolley <brolley@cygnus.com>
-Mon Jun 12 12:36:59 1995 Mike Stump <mrs@cygnus.com>
+ * lang-specs.h: Use new | syntax to eliminate
+ string concatenation.
- * decl.c (complete_array_type): Fill in the TYPE_DOMAIN of our
- TYPE_MAIN_VARIANT if it is not filled in.
- * init.c (build_delete): If the TYPE_DOMAIN is not set, give an
- error instead of core dumping.
+1998-06-25 Jason Merrill <jason@yorick.cygnus.com>
-Mon Jun 12 10:41:40 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cp-tree.h (CP_DECL_CONTEXT): New macro.
+ * decl2.c (is_namespace_ancestor, lookup_using_namespace): Use it.
+ * method.c (build_overload_nested_name): Likewise.
+ * sig.c (build_signature_pointer_or_reference_type): Don't set
+ DECL_CONTEXT.
- * call.c (can_convert): Also check for distance > 0.
- (can_convert_arg): Ditto.
- (user_harshness): Ditto.
+1998-06-24 Martin v. Löwis <loewis@informatik.hu-berlin.de>
-Fri Jun 9 19:17:21 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ Set DECL_CONTEXT for globals to NULL_TREE instead of global_namespace.
+ * cp-tree.h (FROB_CONTEXT): New macro.
+ (DECL_MAIN_P): ::main should have a DECL_CONTEXT of NULL_TREE.
+ * decl.c (namespace_binding): Replace NULL_TREE with
+ global_namespace.
+ (set_namespace_binding, pop_namespace, lookup_name_real): Likewise.
+ * decl2.c (is_namespace_ancestor, lookup_using_namespace):
+ Likewise.
+ * decl.c (pushtag): Use FROB_CONTEXT.
+ (pushdecl, make_typename_type, define_function, grokdeclarator):
+ Likewise.
+ * decl2.c (set_decl_namespace, do_namespace_alias): Likewise.
+ * pt.c (push_template_decl_real, lookup_template_class, tsubst):
+ Likewise.
+ * decl2.c (decl_namespace): Return global_namespace if no context.
+ * method.c (build_overload_nested_name): Expect null as context.
+ * pt.c (mangle_class_name_for_template): Do nothing for null
+ contexts.
+ (lookup_template_class): Allow for null id_context.
- * g++.c (MATH_LIBRARY): Provide default.
- (main): Always link with the math library if we link with libstdc++.
+1998-06-25 Richard Henderson <rth@cygnus.com>
- * decl.c (start_function): Complain about redefinition of a function
- even when the pending_inline version is compiled after the other
- version.
+ * method.c (emit_thunk): Set current_function_is_thunk for the
+ ASM_OUTPUT_MI_THUNK case as well.
-Thu Jun 8 15:44:38 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-06-23 Andrew MacLeod <amacleod@cygnus.com>
- * gc.c (build_dynamic_cast): Build up a reference to a parameter of
- aggregate type.
+ * exception.cc (__cplus_type_matcher): Get a match_info pointer
+ instead of an exception table entry as a parameter.
-Wed Jun 7 20:00:31 1995 Mike Stump <mrs@cygnus.com>
+1998-06-23 Andrew MacLeod <amacleod@cygnus.com>
- * *.[chy]: Change all callers of finish_decl to cp_finish_decl.
- * decl.c (finish_decl): New routine to handle call backs from the
- mid end (declare_hidden_char_array).
+ * parse.y (function_try_block): Don't call start_catch_handler.
+ * except.c (call_eh_info): Remove coerced field from declaration.
+ (build_eh_type_type_ref): New function to create an address of a
+ rtti function for the new style exception tables.
+ (expand_start_catch_block): Split function, this contains the
+ common part.
+ (process_start_catch_block_old): New function to perform the rest
+ of expand_start_catch_block under old style exceptions.
+ (process_start_catch_block_old): New function to perform the rest
+ of expand_start_catch_block under new style exceptions.
+ (expand_end_catch_block): Only pop the false label off the stack under
+ the old style of exceptions.
+ * semantics.c (finish_try_block): Don't call start_catch_handler.
+ * exception.cc (struct cp_eh_info): Add original_value field.
+ (__cplus_type_matcher): Perform type matching on the original exception
+ value, and if we have a match, set the current value.
+ (__cp_push_exception): Set the original expcetion value.
-Wed Jun 7 19:02:50 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-06-23 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_function): Handle setting C_C_D here.
- (set_C_C_D): Removed.
- (struct saved_scope): Remove class_decl.
- (push_to_top_level): Don't save current_class_decl.
- (pop_from_top_level): Don't restore current_class_decl or C_C_D.
- (struct cp_function): Add C_C_D.
- (push_cp_function_context): Save C_C_D.
- (pop_cp_function_context): Restore C_C_D.
+ * call.c (joust): Fix confusing conversion warning.
-Wed Jun 7 15:31:57 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * call.c (build_op_delete_call): Add placement parm. Check
+ LOOKUP_SPECULATIVELY.
+ * cp-tree.h, decl2.c, init.c: Adjust.
+ * decl.c (finish_function): Use it.
- * init.c (build_vec_delete): Resolve an offset ref before we try to
- use it.
+ * pt.c (tsubst): Diagnose creating void fields or variables.
-Wed Jun 7 14:19:32 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Mon Jun 22 08:50:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * typeck.c (build_modify_expr): If the class lacks a constructor or
- assignment operator, return error_mark_node.
- (common_type): Use build_cplus_array_type.
+ * call.c (build_scoped_method_call): Remove unused variable `tmp'.
-Tue Jun 6 09:41:27 1995 Mike Stump <mrs@cygnus.com>
+ * cp-tree.h (check_dtor_name): Add prototype.
- * class.c (dont_allow_type_definitions): New variable set when types
- cannot be defined.
- (finish_struct): Use it.
- * cp-tree.h (dont_allow_type_definitions): Define it.
- * parse.y (primary, handler_seq): Set it.
+ * init.c (expand_member_init): Remove unused variables
+ `ptr_type_node', `parm' and `rval'.
-Mon Jun 5 18:49:38 1995 Mike Stump <mrs@cygnus.com>
+ * ptree.c (print_lang_type): Use HOST_WIDE_INT_PRINT_DEC specifier
+ in call to fprintf.
+ (lang_print_xnode): Likewise.
- * method.c (build_opfncall): Use DECL_CHAIN, not TREE_CHAIN for
- results from lookup_fnfields. Always give warning/error on bad
- code.
+ * typeck2.c (enum_name_string): Cast argument to sprintf to long
+ and use %ld specifier.
-Mon Jun 5 11:39:37 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * init.c (member_init_ok_or_else): Don't allow initialization of
- an ancestor's member from within a constructor.
-
-Mon Jun 5 11:20:34 1995 Gerald Baumgartner (gb@alexander.cs.purdue.edu)
-
- * sig.c (build_signature_table_constructor): Use DECL_CONTEXT
- instead of DECL_CLASS_CONTEXT for calculating the vfield offset so
- abstract virtual functions are handled correctly.
-
- * sig.c (build_signature_table_constructor): Store the correct
- delta in signature table entries. It does not yet work for
- classes with virtual base classes as implementations of signatures.
- (build_signature_method_call): Add the delta to the object_ptr
- before generating the function call.
-
- * call.c (build_method_call): Make instance_ptr the signature
- pointer itself instead of dereferencing the optr.
- * sig.c (build_signature_method_call): Dereference the optr for the
- direct and virtual calls.
-
- * sig.c (build_signature_table_constructor): Make the tag for
- default implementations -1 instead of 2.
- (build_signature_method_call): Change the generated conditional
- expression correspondingly.
-
- * sig.c (build_signature_pointer_constructor): Deleted the sorry
- message that said we can't handle multiple inheritance for
- implementations of signatures
- (build_signature_method_call): Use the offset from the sigtable
- entry instead of the vptr field from the signature pointer for
- building a virtual function call.
-
- * class.c (build_vfn_ref): Deleted signature specific code, we don't
- call this function anymore from build_signature_method_call.
-
- * cp-tree.h (SIGNATURE_VPTR_NAME): Deleted. We use the right vptr
- field in the object now instead of in the signature pointer/ref.
- (build_vptr_ref): Deleted extern declaration.
- * sig.c (build_vptr_ref): Deleted.
- (build_signature_pointer_or_reference_type): Deleted construction of
- the vptr field.
- (build_signature_pointer_constructor): Deleted initialization of/
- assignment to the vptr field.
-
- * sig.c (build_signature_table_constructor): Convert the signature
- table entry fields to their correct types.
-
- * sig.c (build_signature_table_constructor): Don't call digest_init
- for the fields of a sigtable entry, it's wasted time.
-
- * sig.c (build_signature_table_constructor): Correctly set the
- offset and index fields of a sigtable entry. Build the constructor
- the way digest_init does, digest_init can't handle initializing an
- anonymous union inside a struct.
- (build_signature_method_call): Use the index field instead of the
- delta field to get the vtable index.
-
- * decl.c (init_decl_processing): Fix number of fields for building
- sigtable_entry_type.
-
- * cp-tree.h (tag_identifier, offset_identifier): Added extern decls.
- (SIGTABLE_CODE_NAME): Renamed to SIGTABLE_TAG_NAME.
- (SIGTABLE_PFN_NAME): Deleted, we'll use VTABLE_PFN_NAME instead.
- * decl.c (tag_identifier, offset_identifier): New variables to
- hold the identifiers for the sigtable fields tag and offset.
- (init_decl_processing): Initialize these variables.
- (init_decl_processing): Use these variables to build the
- sigtable_entry_type structure. Rename the code and offset fields
- to tag and delta, respectively; add offset and index fields. Changed
- types of fields from short_integer_type_node to delta_type_node.
- * sig.c (build_signature_table_constructor): Rename code and offset
- to tag and delta, respectively.
- (build_signature_method_call): Ditto. Use above variables.
-
-Fri Jun 2 11:05:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (set_C_C_D): New function. suspend_momentary before
- building C_C_D.
- (pop_from_top_level): Call it.
- (start_function): Ditto.
- (pop_cp_function_context): Ditto.
+ * xref.c (GNU_xref_end_scope): Use HOST_WIDE_INT_PRINT_DEC
+ specifier in call to fprintf.
+ (GNU_xref_member): Cast argument to sprintf to int.
- * class.c, cp-tree.h, decl.c, decl2.c, parse.y: Lose all references
- to current_vtable_decl, CLASSTYPE_INST_VAR and CLASSTYPE_VTBL_PTR.
+Fri Jun 19 23:22:42 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * decl.c (push_cp_function_context): Save current_class_decl.
- (pop_cp_function_context): Restore current_class_decl and set C_C_D.
- (pop_from_top_level): Don't use CLASSTYPE_INST_VAR to set C_C_D.
- (start_function): Ditto.
+ * typeck2.c (pop_init_level): Warn about implicit zero initialization
+ of struct members.
- * class.c (popclass): Don't mess with current_class_decl,
- current_vtable_decl, or C_C_D.
+Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Mon May 29 12:45:10 1995 Paul Eggert <eggert@twinsun.com>
+ * cp-tree.h: Prototype function `check_java_method'.
- * Make-lang.in (c++.mostlyclean): Remove $(DEMANGLER_PROG).
+1998-06-17 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jun 1 17:03:51 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * class.c (finish_struct): Make conflicting use of id a pedwarn.
+ * decl.c (pushdecl_class_level): Likewise.
- * decl.c (lookup_name_real): Don't try to look anything up in an
- erroneous object.
+1998-06-17 Mark Mitchell <mark@markmitchell.com>
-Fri Jun 2 10:30:14 1995 Mike Stump <mrs@cygnus.com>
+ * pt.c (convert_nontype_argument): Issue an error when presented
+ with an integer (real) constant that cannot be simplified to an
+ INT_CST (REAL_CST).
- * method.c (build_overload_int): New routine. Break out
- functionality from build_overload_value so we can reuse it.
- (build_overload_value): Handle pointer to member functions as value
- parameters for templates.
- (build_overload_identifier): Since template parameters are shared
- among all instantiations, we have to substitute in the real types
- in TREE_TYPE (parm).
- pt.c (coerce_template_parms): Ditto.
- (push_template_decls): Ditto.
- (grok_template_type): Deleted as template parameters are shared
- among all instantiations.
+ * cp-tree.h (c_get_alias_set): Remove declaration added in
+ 1998-06-13 change that should never have been checked in.
-Wed May 31 19:10:32 1995 Mike Stump <mrs@cygnus.com>
+1998-06-17 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Always give errors on constant overflow
- for array indices.
+ * typeck.c (build_binary_op_nodefault): Change % in format strings
+ to %%.
-Wed May 31 11:39:43 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (grokvardecl): Don't build_static_name for decls that
+ aren't at namespace scope.
- * typeck.c (commonparms): Don't abort if simple_cst_equal returns < 0.
- (build_c_cast): Don't tack on a NON_LVALUE_EXPR when casting to
- reference type.
- (build_indirect_ref): Fix check for *&.
+ * init.c (perform_member_init): Catch default-initialization of
+ references.
-Wed May 24 15:55:18 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+1998-06-17 Mark Mitchell <mark@markmitchell.com>
- * decl.c (duplicate_decls): Check simple_cst_equal result against 0.
- * decl2.c (finish_anon_union): Likewise.
- * method.c (largest_union_member): Likewise.
+ * errfn.c (cp_thing): Handle the `%%' formatting sequence.
-Wed May 24 14:41:11 1995 H.J. Lu (hjl@nynexst.com)
+1998-06-17 Jason Merrill <jason@yorick.cygnus.com>
- * Make-lang.in (cxxmain.o): Replace single quotes with backslashes.
+ * method.c (hack_identifier): Complain about getting a namespace
+ or class template.
+ * typeck.c (decay_conversion): Remove check for namespaces.
+ * typeck2.c (incomplete_type_error): Likewise.
+ * parse.y (template_arg): Add PTYPENAME expansion.
-Mon May 22 17:38:48 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+1998-06-16 Andrew MacLeod <amacleod@cygnus.com>
- * Make-lang.in (g++, g++-cross, cc1plus, DEMANGLER_PROG):
- Use $@ instead of output name so works even if have .exe.
- (cxxmain.o): Use cp if ln -s fails.
- (c++.install-man): Use $(exeext) in executable names.
- (c++.mostlyclean, stage[1-4]): Use $(objext) in object file names.
- * Makefile.in (../cc1plus): Use $(exeext) in name of executable.
+ * decl.c (grokvardecl): Don't build external assembler names for
+ TYPENAMEs in other namespaces as there is no declarator.
+ * error.c (cp_file_of, cp_line_of): Don't extract file or line number
+ info from DECL_CONTEXT if it is NULL.
-Wed May 24 01:39:03 1995 Jason Merrill <jason@deneb.cygnus.com>
+1998-06-16 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): parms can be null, duh.
+ * call.c (check_dtor_name): Split out.
+ (build_scoped_method_call): Use it.
+ (build_method_call): Use it.
+ * init.c (build_offset_ref): Use it.
-Tue May 23 01:32:09 1995 Jason Merrill <jason@deneb.cygnus.com>
+ * typeck.c (build_static_cast): Fix handling of pointers to members.
- * call.c (build_method_call): If convert_arguments failed, just bail.
+ * decl.c (finish_function): Just return nothing from a constructor.
+ * typeck.c (c_expand_return): Complain about returning a void
+ expression from a destructor.
-Fri May 19 10:31:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-06-13 Mark Mitchell <mark@markmitchell.com>
- * cvt.c (convert_force): Pass LOOKUP_NORMAL to cp_convert.
+ * class.c (alter_access): Accept a BINFO explaining how to get
+ from the entity whose accessed is being altered to the type doing
+ the altering.
+ (handle_using_decl): New function containing code split out from ...
+ (finish_struct_1): Here.
- * tree.c (copy_to_permanent): Oops.
+ * cp-tree.h (complete_type_or_else): Declare.
+ * init.c (build_new_1, build_delete): Use it.
+ * typeck.c (require_complete_type): Use complete_type, rather than
+ expanding it inline.
+ (complete_type_or_else): New function.
+ (build_component_ref): Use it.
+ (pointer_int_sum): Make sure the type pointed to is complete.
+ (pointer_diff): Likewise.
-Fri May 19 10:01:07 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * pt.c (for_each_template_parm): Traverse the TYPE_CONTEXT for
+ types.
- * cp-tree.h (break_out_target_exprs): Add decl.
+ * search.c (get_matching_virtual): Note that member templates
+ cannot override virtual functions.
-Thu May 18 13:02:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-06-12 Brendan Kehoe <brendan@cygnus.com>
- * decl.c (start_function): Move *all* interface handling stuff after
- the pushdecl.
+ * pt.c (check_explicit_specialization): If DECLARATOR turned into
+ an error_mark_node from lookup_template_function, return the same.
+ (determine_specialization): Also make sure TEMPLATE_ID isn't an
+ error_mark_node, before we try to read its operands.
+ * decl.c (grokdeclarator): If we got an error_mark_node from
+ check_explicit_specialization, just return it right back.
- * tree.c (mapcar): Renamed from make_deep_copy and generalized.
- (perm_manip): Return t if permanent, otherwise 0.
- (copy_to_permanent): Use them.
- (bot_manip): Helper for break_out_target_exprs.
- (break_out_target_exprs): New function. Uses mapcar.
+1998-06-12 Mark Mitchell <mark@markmitchell.com>
- * typeck.c (convert_arguments): Use it.
+ * class.c (instantiate_type): Don't treat template-ids that don't
+ specify any template arguments as equivalent to ordinary
+ identifiers. Use OFFSET_REF instead of SCOPE_REF to refer to
+ pointer-to-members for member templates. Tidy slightly.
+ * cp-tree.def (TEMPLATE_ID_EXPR): Revise documentation.
+ * init.c (build_offset_ref): Handle template-ids like ordinary
+ identifiers, for the most part, but store a TEMPLATE_ID_EXPR in the
+ offset part of the OFFSET_REF.
+ * typeck.c (build_unary_op): Change check for unknown types to
+ look for OFFSET_REFs, not SCOPE_REFs.
- * method.c (hack_identifier): Use convert_from_reference to
- dereference a reference.
+1998-06-11 Mark Mitchell <mark@markmitchell.com>
-Wed May 17 17:54:54 1995 Mike Stump <mrs@cygnus.com>
+ * pt.c (is_member_template_class): New function.
+ (push_template_decl_real): Use it.
- * call.c (convert_harshness): Move reference bashing before pointer
- to member bashing.
+1998-06-11 Benjamin Kosnik <bkoz@elmo.cygnus.com>
-Wed May 17 16:57:53 1995 Mike Stump <mrs@cygnus.com>
+ * friend.c (do_friend): Add support for nested classes using
+ member functions of the enclosing class as friends.
- * cvt.c (convert_to_reference): Only complain, if complaints are
- wanted.
- * typeck.c (build_function_call_real): Ditto. If LOOKUP_SPECULATIVELY
- is set and something won't work, return NULL_TREE.
- * cvt.c (cp_convert): Ditto. Pass flags down to build_method_call.
- (convert): Pass LOOKUP_NORMAL to cp_convert.
- * typeck.c (convert_for_assignment): Ditto.
- (convert_force): Pass LOOKUP_COMPLAIN to cp_convert.
- (convert_arguments): Get out early if we get an error_mark_node.
- (convert_for_initialization): Use cp_convert instead of convert so
- that we can pass flags down.
- * cp-tree.h (LOOKUP_SPECULATIVELY): Added documentation.
+1998-06-10 Mark Mitchell <mark@markmitchell.com>
-Wed May 17 01:43:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (convert_default_arg): Make global, not static.
+ (convert_arg_for_ellipsis): Split out from ...
+ (build_over_call): Here.
+ * cp-tree.h (convert_default_arg); Declare.
+ (convert_arg_to_ellipsis): Likewise.
+ (do_member_init): Remove.
+ * init.c (do_member_init): Remove; this code is dead.
+ (expand_member_init): Remove much of this code; it is dead.
+ * typeck.c (convert_arguments): Use convert_default_arg and
+ convert_arg_for_ellipsis, rather than duplicating here.
+
+ * call.c (convert_like): Don't fail silently if
+ build_user_type_conversion fails. Always return error_mark_node
+ for failure.
- * typeck2.c (store_init_value): Don't take the MAIN_VARIANT of the
- decl type.
+1998-06-10 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Don't complain about a class with no
- user-defined constructors but with a member that has no default
- constructor, as this is OK for aggregates.
+ * search.c (covariant_return_p): Complain about ambiguous base.
- * expr.c (cplus_expand_expr, NEW_EXPR): If this is an explicit
- constructor call, mark slot addressable.
+ * typeck.c (build_component_ref): Diagnose ref to nested type.
-Tue May 16 18:37:51 1995 Douglas Rupp (drupp@cs.washington.edu)
+1998-06-10 Brendan Kehoe <brendan@cygnus.com>
- * g++.c: Changed WINNT to _WIN32.
+ * decl.c (grokparms): Check that INIT isn't an error_mark_node
+ before giving error about invalid type for default arg.
-Tue May 16 12:40:16 1995 Jason Merrill <jason@lisa.cygnus.com>
+1998-06-10 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (handle_sysv_pragma): Don't use token_buffer.
+ * call.c (build_method_call): Fix thinko.
-Tue May 16 12:05:26 1995 Mike Stump <mrs@cygnus.com>
+1998-06-10 Dave Brolley <brolley@cygnus.com>
- * call.c (resolve_scope_to_name): Add initial semantic support for
- namespaces.
- * class.c (finish_struct): Ditto.
- * cp-tree.h (NAMESPACE_LEVEL): Ditto.
- * cvt.c (build_up_reference, convert_to_reference): Ditto.
- * decl.c (binding_level::namespace_p, suspend_binding_level): Ditto.
- (resume_binding_level, toplevel_bindings_p): Ditto
- (namespace_bindings_p, declare_namespace_level): Ditto.
- (resume_level, push_namespace, pop_namespace): Ditto.
- (pop_everything, pushtag, duplicate_decls, pushdecl): Ditto.
- (implicitly_declare, lookup_namespace_name, lookup_name_real): Ditto.
- (start_decl, make_temporary_for_reference), Ditto.
- (obscure_complex_init, finish_decl, expand_static_init): Ditto.
- (grokvardecl, grokdeclarator, parmlist_is_exprlist): Ditto.
- (store_parm_decls, hack_incomplete_structures): Ditto.
- * decl2.c (get_temp_name, finish_anon_union, current_namespace): Ditto.
- (push_namespace, pop_namespace, do_namespace_alias): Ditto.
- (do_toplevel_using_decl, do_class_using_decl): Ditto.
- * error.c (dump_decl): Ditto.
- * init.c (build_member_call, build_offset_ref): Ditto.
- * lex.c (identifier_type): Ditto.
- * parse.y (lang_extdef, using_decl, extdef, component_decl_1): Ditto.
- (nested_name_specifier_1): Ditto.
- * spew.c (yylex): Ditto.
- * tree.def (NAMESPACE_DECL): Ditto.
+ * decl2.c (lang_decode_option): New argc/argv interface.
+ * cp-tree.h (lang_decode_option): New argc/argv interface.
+ * lang-specs.h (default_compilers): Only call cpp if -E, -M or -MM is
+ specified for cpplib-enabled compilers.
+ * lex.c (lang_init): Don't check_newline for cpplib.
+ (init_parse): Don't initialize cpplib here.
-Tue May 16 11:55:35 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-06-10 Brendan Kehoe <brendan@cygnus.com>
- * decl.c (push_overloaded_decl): Return the new decl even if it
- can't be pushed.
+ * typeck.c (build_component_ref): Make sure FIELD has a lang_specific
+ piece before checking DECL_MUTABLE_P.
-Tue May 16 11:00:37 1995 Jason Merrill <jason@lisa.cygnus.com>
+1998-06-10 John Carr <jfc@mit.edu>
- * typeck.c (decay_conversion): Split out from default_conversion.
- (default_conversion): Call it.
- (build_binary_op): Ditto.
- (build_binary_op_nodefault): Use decay_conversion for truth ops.
+ * tree.c (debug_binfo): Make printf format match arguments.
-Mon May 15 12:47:56 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * error.c (OB_PUTI): Make printf format match arguments.
- * decl.c (warn_extern_redeclared_static): This is a pedwarn.
- (duplicate_decls): Always use the old decl's linkage info. Don't
- play with linkage of consts.
- (pushdecl): Don't play with linkage of consts.
- (redeclaration_error_message): Don't complain about an old public
- decl and a new non-public decl here.
- (grokvardecl): Handle linkage of consts here.
- (grokdeclarator): An 'extern inline' is public. Pass constp to
- grokvardecl.
- (start_function): Wait until after the pushdecl to do some linkage
- stuff.
+1998-06-10 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (import_export_vtable): Make duplicates weak rather than
- static if supported.
- (import_export_inline): Ditto.
- * pt.c (do_pending_expansions): Ditto.
+ * init.c (perform_member_init): Handle default-initialization.
- * class.c (build_vbase_path): flag_assume_nonnull_objects only
- affects reference conversion.
+ * except.c (build_throw): Handle throwing NULL.
- * init.c (emit_base_init): Build up an RTL_EXPR and add it to
- rtl_expr_chain.
- * decl.c, decl2.c: s/base_init_insns/base_init_expr/.
+ * typeck.c (build_x_function_call): Use resolve_offset_ref.
-Tue May 16 07:06:28 1995 Paul Eggert <eggert@twinsun.com>
+ * search.c (compute_access): Only strip an anonymous union
+ for a FIELD_DECL.
- * method.c (numeric_output_need_bar): Renamed from misspelling.
+ * call.c (add_builtin_candidates): Tweak.
- * typeck.c (build_ptrmemfunc): Fix misspellings in messages.
+ * cvt.c (build_expr_type_conversion): Restore code for conversion
+ from class types.
+ * decl2.c (delete_sanity): Use it. Clean up.
-Sun May 14 10:26:22 1995 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * typeck.c (comp_ptr_ttypes_real): Fix cv-qual comparisons.
- * lang-options.h, lang-specs.h: New files.
+1998-06-10 Branko Cibej <branko.cibej@hermes.si>
-Thu May 11 00:31:48 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * typeck.c (c_expand_return): Don't warn about void expressions on
+ return statements in functions returning void.
- * typeck.c (default_conversion): Don't check for BLKmode before
- pulling out the decl_constant_value.
+1998-06-09 Mark Mitchell <mark@markmitchell.com>
- * decl.c (start_function): Clear named_labels and shadowed_labels.
+ * pt.c (fn_type_unification): Revise documentation. Tidy.
+ (type_unification): Likewise.
- * typeck.c (build_function_call_real): Also synthesize methods here.
+1998-06-09 Andrew MacLeod <amacleod@cygnus.com>
-Wed May 10 00:55:59 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * semantics.c (finish_try_block): Rename expand_start_catch, and delete
+ expand_end_catch.
+ * parse.y (function_try_block): Rename expand_start_catch, and delete
+ expand_end_catch.
+ * except.c (expand_end_eh_spec): Rename expand_start_catch, and delete
+ expand_end_catch.
- * decl2.c (finish_file): Synthesize exported methods before the
- reconsider loop.
+1998-06-09 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y: Move declaration of flag_new_for_scope to file scope.
+ * search.c (lookup_member): New fn.
+ * class.c (finish_struct_1): Use it.
+ * decl.c (lookup_name_real): Use it.
-Tue May 9 19:10:33 1995 Mike Stump <mrs@cygnus.com>
+Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * decl2.c: Add flag_new_for_scope for new -ffor-scope flag.
- * parse.y (FOR): Conditionalize the pushing and poping of scope for
- the for-init-statement upon the new flag_new_for_scope.
- * parse.y (try_block): Simplify and use compstmt.
+ * Makefile.in (decl2.o): Depend on dwarf2out.h and dwarfout.h.
-Mon May 8 12:41:52 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cp-tree.h: Add prototype for `maybe_print_template_context' and
+ `maybe_make_one_only'.
- * decl.c (define_function): Mark function decl artificial.
+ * decl.c (auto_function): Remove unused variable `decl'.
-Sun May 7 00:51:28 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c: Include dwarf2out.h and dwarfout.h.
- * parse.y (simple_stmt, FOR): Put back push/pop for condition scope.
+ * lex.c: Remove redundant declarations of `set_float_handler' and
+ `asm_out_file'.
- * decl2.c (grokclassfn): DECLs don't have cv-qualified types.
- * tree.c (build_cplus_method_type): Ditto.
+1998-06-08 Andrew MacLeod <amacleod@cygnus.com>
- * cp-tree.h (SET_DECL_ARTIFICIAL): Just set DECL_ARTIFICIAL to 1.
+ * except.c (init_exception_processing): Remove NEW_EH_MODEL compile
+ time flag. Call __cp_eh_info instead of __cp_exception_info.
+ * exception.cc (struct cp_eh_info): Remove NEW_EH_MODEL flag.
+ (__cp_exception_info): Return offset into cp_eh_info structure to
+ match what use to be the start of this structure.
+ (__cp_eh_info): New function to return a pointer to cp_eh_info struct.
+ (__cplus_type_matcher, __cp_push_exception): Remove NEW_EH_MODEL
+ compile time flag.
+ (__uncatch_exception, __check_eh_spec, std::uncaught_exception): Call
+ __cp_eh_info instead of __cp_exception_info.
- * typeck.c (build_function_call_real): If convert_arguments failed,
- just bail.
- (convert_arguments): If one of the arguments is error_mark_node,
- just bail.
+1998-06-08 Jason Merrill <jason@yorick.cygnus.com>
-Sat May 6 02:39:41 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (cp_finish_decl): Disable inlining of extern inlines
+ with static variables.
- * decl.c (duplicate_decls): Don't check DECL_NOT_REALLY_EXTERN for
- decls that don't include it.
+1998-06-08 Mark Mitchell <mark@markmitchell.com>
-Fri May 5 14:23:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * init.c (build_offset_ref): Correct previous change to use build,
+ not build_min.
- * decl.c (duplicate_decls): Decls that have DECL_INTERFACE_KNOWN or
- DECL_NOT_REALLY_EXTERN set aren't extern decls.
+1998-06-07 Mark Mitchell <mark@markmitchell.com>
- * typeck.c (build_indirect_ref): Don't call default_conversion for a
- parameter of reference_type.
- * cvt.c (convert_from_reference): Just use build_indirect_ref.
+ * class.c (instantiate_type): Handle pointer-to-members where the
+ member is a template.
+ * init.c (build_offset_ref): Likewise.
+ * typeck.c (build_unary_op): Likewise.
- * pt.c (do_type_instantiation): Only instantiate member functions
- that actually come from templates.
+1998-06-07 Richard Henderson <rth@cygnus.com>
-Fri May 5 09:46:05 1995 Mike Stump <mrs@cygnus.com>
+ * lex.c (lang_init_options): New function.
+ (lang_init): Remove flag_exceptions == 2 hack.
+
+1998-06-05 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y: Generalized cleanup of poplevels, and compound statements
- and compound statements in try blocks. Rewritten `for' rule so that
- the scope of variables declared in the for clause is shortened to
- span just to the end of the statement, instead of the whole
- containing block.
+ * search.c (envelope_add_decl): Tweak for implicit typename.
-Fri May 5 00:37:14 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (joust): Also warn about confusing conversion op/constructor
+ overload resolution.
- * call.c (convert_harshness): Handle pointers to members better.
+ * spew.c (yylex): Also return the TYPE_DECL if got_object.
+ Don't clear got_object after '~'.
+ * call.c (build_scoped_method_call): Tweak destructor handling.
+ (build_method_call): Likewise.
+ * pt.c (tsubst_copy, case METHOD_CALL_EXPR): Don't mess with
+ TYPE_MAIN_VARIANT for destructors.
+ * semantics.c (finish_object_call_expr): Complain about calling a
+ TYPE_DECL.
-Thu May 4 16:00:26 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-06-05 Per Bothner <bothner@cygnus.com>
- * decl2.c (delete_sanity): Do access control here.
- * init.c (build_delete): Instead of here.
+ * g++spec.c (lang_specific_pre_link, lang_specific_extra_ofiles):
+ Define - update needed by gcc.c change.
- * Make-lang.in: Build c++filt.
+1998-06-05 Jason Merrill <jason@yorick.cygnus.com>
-Wed May 3 02:59:53 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * error.c (cp_printers): Use 'o' instead of '_' for the null entry.
- * decl2.c (cplus_decl_attributes): If we just modified a TYPE_DECL,
- update our IDENTIFIER_TYPE_VALUE.
+1998-06-05 Martin v. Loewis <loewis@informatik.hu-berlin.de>
-Fri Apr 28 07:58:41 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cp-tree.h (DECL_NAMESPACE_ALIAS, ORIGINAL_NAMESPACE): Declare.
+ * decl.c (lookup_name_real): Add namespaces_only parameter.
+ If set, return only NAMESPACE_DECLs.
+ (select_decl): Likewise.
+ (identifier_type_value): Give additional parameter.
+ (lookup_name_nonclass): Likewise.
+ (lookup_name): Likewise.
+ (find_binding): Skip namespace aliases.
+ (binding_for_name): Likewise.
+ (push_namespace): Check for namespace aliases.
+ (lookup_name_namespace_only): New function.
+ (begin_only_namespace_names, end_only_namespace_names): New functions.
+ * decl2.c (set_decl_namespace): Skip namespace aliases.
+ (do_using_directive): Likewise.
+ (do_namespace_alias): Produce namespace aliases, fix alias
+ redeclaration.
+ * error.c (dump_decl): Support SCOPE_REF.
+ * parse.y (extdef): Wrap lookup with namespace_only for namespace
+ aliases and using declarations.
- * lex.c (cons_up_default_function): Fix linkage of #pragma
- implemented functions.
+1998-06-04 Jason Merrill <jason@yorick.cygnus.com>
-Thu Apr 27 16:56:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * tree.c (really_overloaded_fn): Only see through one TREE_LIST.
- * method.c (build_overload_name): Simplify and fix repeated type
- folding.
+ * error.c (dump_expr): Clean up NEW_EXPR case.
- * decl.c (grokdeclarator): Prohibit pointers to void or reference
- members.
+1998-06-04 Martin von Löwis <loewis@informatik.hu-berlin.de>
-Thu Apr 27 09:49:07 1995 Mike Stump <mrs@cygnus.com>
+ Suggested by Brendan Kehoe
+ * decl2.c (do_toplevel_using_decl): When decl is a TYPE_DECL,
+ treat it as using ::decl.
- * typeck2.c (process_init_constructor): Make sure initializers are
- fully digested.
+ * decl2.c (arg_assoc_type): Process unknown_type_node and OFFSET_TYPE.
-Thu Apr 27 01:11:55 1995 Jason Merrill <jason@python.cygnus.com>
+ * tree.c (mapcar): Support NEW_EXPR.
- * lex.c (cons_up_default_function): Always defer synthesis.
+ * error.c (dump_expr): Support NEW_EXPR.
-Thu Apr 27 00:20:37 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-06-03 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (mark_inline_for_output): Don't play with pending_inline
- stuff.
+ * method.c (make_thunk): Use overload machinery to make name.
+ * search.c (covariant_return_p): New fn.
+ (get_matching_virtual): Use it.
-Wed Apr 26 17:48:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * init.c (build_new_1): Fix check for void.
- * call.c (user_harshness): New function; like build_type_conversion,
- but doesn't actually build anything.
- (compute_conversion_costs): Use it instead of build_type_conversion.
+1998-06-01 Per Bothner <bothner@cygnus.com>
-Wed Apr 26 17:11:25 1995 Jason Merrill <jason@deneb.cygnus.com>
+ * cp-tree.h (TYPE_FOR_JAVA): New macro.
+ * decl.c, cp-tree.h (java_byte_type_node, java_short_type_node,
+ java_int_type_node, java_long_type_node, java_float_type_node,
+ java_double_type_node, java_char_type_node, java_boolean_type_node):
+ New "primitive" types, with predefined names __java_byte etc.
+ (record_builtin_java_type): New function.
+ (init_decl_processing): Make Java types with record_builtin_java_type.
+ (pushtag, grokdeclarator): Set TYPE_FOR_JAVA if in extern "JAVA".
+ (xref_baseypes): If base class was TYPE_FOR_JAVA, so is this class.
+ (grokfndecl): Call check_java_method for Java classes.
+ * method.c (is_java_type): Removed. Replaced with TYPE_FOR_JAVA.
+ (process_overload_item): Match types against specific
+ java_XX_type_node types, rather than using is_java_type.
+ * class.c (finish_struct_1): Don't add default copy constructor
+ or operator= if TYPE_FOR_JAVA.
+ (pop_lang_conext): Restore strict_prototyp proper if Java.
+ * decl2.c (acceptable_java_type, check_java_method): New functions.
+ * pt.c (instantiate_class_template): Copy TYPE_FOR_JAVA from pattern.
+ (tsubst): Move common statement after if statement.
+ * typeck.c (comptypes): If strict, TYPE_FOR_JAVA must match.
- * typeck.c (build_function_call_real): Improve error message for
- calling a non-function.
+1998-06-01 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (hack_identifier): Lose check for calling a data member.
+ * pt.c (for_each_template_parm): Use first_rtl_op.
-Wed Apr 26 16:59:13 1995 Mike Stump <mrs@cygnus.com>
+ * tree.c (build_cplus_array_type_1): Also check index_type for
+ template parms.
- * typeck2.c (build_functional_cast): Remove very old cruft.
- Seems like good code is generated without it.
+1998-05-31 Jason Merrill <jason@yorick.cygnus.com>
-Wed Apr 26 00:47:16 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (tsubst): Always copy BINFO_BASETYPES.
- * method.c (do_build_assign_ref): Fix handling of anonymous unions.
- (do_build_copy_constructor): Ditto.
+1998-05-29 scott snyder <snyder@d0sgif.fnal.gov>
- * parse.y (simple_stmt, SWITCH): Call {push,pop}_switch.
+ * tree.c (layout_basetypes): If we change TYPE_SIZE, change
+ TYPE_SIZE_UNIT too.
- * decl.c (push_switch): New function.
- (pop_switch): Ditto.
- (define_case_label): Check for jumping over initialization.
+1998-05-29 Mark Mitchell <mark@markmitchell.com>
- * call.c (build_method_call): Check for an inline function being
- called before its definition has been seen.
- * typeck.c (build_function_call_real): Ditto.
+ * decl.c (grokdeclarator): Don't complain about in-class
+ initialization of static consts if we don't really know the type
+ of the variable.
- * decl.c (duplicate_decls): Check for a function being redeclared
- inline after its address has been taken.
+1998-05-29 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_conditional_expr): Handle related class lvalues.
+ * cp-tree.h (DECL_DESTRUCTOR_P): New macro.
+ * method.c (build_destructor_name): New fn.
+ * decl2.c (maybe_retrofit_in_chrg): Split out...
+ (grokclassfn): From here. Reorganize.
+ * decl.c (grok_ctor_properties): Make sure ctors for types with
+ vbases have the in_chrg parm.
+ * pt.c (instantiate_class_template): Update
+ TYPE_USES_VIRTUAL_BASECLASSES from tsubsted bases. Don't call
+ grok_*_properties.
+ (tsubst): Call grok_ctor_properties and maybe_retrofit_in_chrg.
-Tue Apr 25 13:20:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-05-28 Mark Mitchell <mark@markmitchell.com>
- * pt.c (do_pending_expansions): Don't expand unused templates.
+ * pt.c (instantiate_decl): Make test for whether or not static
+ variables should be instantiated early match its comment.
- * parse.y (component_decl): Accept a lone semicolon.
+1998-05-28 Jason Merrill <jason@yorick.cygnus.com>
-Tue Apr 25 00:25:56 1995 Jason Merrill <jason@rtl.cygnus.com>
+ * decl.c (start_decl): Always pedwarn about vacuously redeclaring
+ a member.
+ (start_function): Call check_default_args.
+ * decl2.c (grokfield): Don't call check_default_args.
+ (check_default_args): Use cp_error_at.
+ * lex.c (do_pending_defargs): Call check_default_args.
- * call.c (build_method_call): Don't allow an RTL_EXPR to serve as the
- object parameter anymore.
+1998-05-27 Brendan Kehoe <brendan@cygnus.com>
- * expr.c (cplus_expand_expr): Don't create RTL_EXPRs with no insns.
+ * call.c (build_method_call): Make sure get_type_value returns
+ something before we try to use its TYPE_MAIN_VARIANT.
+ (build_scoped_method_call): Likewise.
-Mon Apr 24 12:35:48 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-05-27 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (simple_stmt, decl case): Clear prefix_attributes.
- (lang_extdef): Ditto.
+ * typeck2.c (digest_init): Complain about getting a TREE_LIST to
+ initialize an array.
- * parse.y (maybe_parmlist): New rule for use in declarators where
- this could either be a list of expressions or parameters. Calls
- suspend_momentary before deciding which.
- (direct_after_type_declarator): Use it.
- (complex_direct_notype_declarator): Use it.
+ * search.c (expand_upcast_fixups): Don't set DECL_CONTEXT and
+ DECL_VIRTUAL_P.
- * pt.c (tsubst): Propagate attributes const and noreturn.
+ * friend.c (do_friend): Clarify template warning.
- * typeck.c (build_modify_expr): If warn_synth, call build_opfncall
- before doing the default thing.
+1998-05-27 Mark Mitchell <mark@markmitchell.com>
-Thu Apr 27 21:49:36 1995 Doug Evans <dje@cygnus.com>
+ * decl.c (shadow_label): Don't treat decls as identifiers.
+ (maybe_push_to_top_level): Clear shadowed_labels.
- * typeck.c (common_type): Call lookup_attribute instead of
- value_member.
+ * pt.c (instantiate_decl): Reset lineno and filename after calling
+ regenerate_decl_from_template.
-Tue Apr 25 18:07:43 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+ * decl.c (grokdeclarator): Don't try to use TYPE_OBSTACK on an
+ error_mark_node.
- * Make-lang.in: Change "realclean" to "maintainer-clean".
+1998-05-27 Kevin Buhr <buhr@stat.wisc.edu>
-Sun Apr 23 12:32:38 1995 Mike Stump <mrs@cygnus.com>
+ * parse.y (base_class): Use is_aggr_type, not IS_AGGR_TYPE.
- * decl2.c (finish_file): Fix broken linked list handling.
+1998-05-26 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
-Fri Apr 21 18:08:43 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (process_template_parm): Accept TYPENAME_TYPE nodes.
+ (convert_nontype_argument): Handle cases when nontype template
+ parameters become classes after substitution.
- * class.c (finish_base_struct): Don't set TYPE_HAS_COMPLEX_*_REF
- as often.
- (finish_struct): Ditto.
+1998-05-26 Mark Mitchell <mark@markmitchell.com>
- * various: Use TYPE_HAS_TRIVIAL_* instead of TYPE_HAS_COMPLEX_*.
+ * friend.c (is_friend): Use comptypes, rather than == to compare
+ types. Modify for new representation of template friends.
+ (make_friend_class): Likewise.
+ * pt.c (tsubst_friend_class): Undo 1998-05-21 change. Tweak.
+ (instantiate_class_template): Deal with template friends.
- * cp-tree.h (TYPE_HAS_TRIVIAL_INIT_REF): New macro.
- (TYPE_HAS_TRIVIAL_ASSIGN_REF): New macro.
+ * decl.c (store_parm_decls): Remove redundant call to
+ expand_main_function.
-Fri Apr 21 15:52:22 1995 Jason Merrill <jason@python.cygnus.com>
+1998-05-26 Benjamin Kosnik <bkoz@loony.cygnus.com>
- * typeck.c (c_expand_return): Only expand a returned TARGET_EXPR if
- it is of the same type as the return value.
+ * decl.c (start_decl): Check for DECL_LANG_SPECIFIC before
+ DECL_USE_TEMPLATE.
-Fri Apr 21 03:01:46 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-05-26 Per Bothner <bothner@cygnus.com>
- * decl2.c (finish_file): Reconsider if synthesizing a method wrote
- out its assembly.
+ * language_as_string: Handle lang_java.
- * typeck.c (convert_for_initialization): Don't call a trivial copy
- constructor.
+1998-05-26 Jason Merrill <jason@yorick.cygnus.com>
- * typeck2.c (store_init_value): Only abort if the type has a
- non-trivial copy constructor.
+ * decl.c (pushdecl): Don't copy the type_decl.
- * typeck.c (c_expand_return): If we're returning in a register and
- the return value is a TARGET_EXPR, expand it. Only do
- expand_aggr_init if we're returning in memory.
- (expand_target_expr): Function to expand a TARGET_EXPR.
- (build_modify_expr): Use it.
+1998-05-26 Martin v. Löwis <loewis@informatik.hu-berlin.de>
- * tree.c (build_cplus_new): Layout the slot.
+ * class.c (pushclass): Always store TYPE_MAIN_VARIANT in
+ current_class_type.
+ * decl.c (grokdeclarator): Put typedefs on the type's obstack.
- * expr.c (cplus_expand_expr): Use expand_call to expand the call
- under a NEW_EXPR, so the target is not discarded.
+ * parse.y (complex_direct_notype_declarator): Use $1 to access
+ scope of notype_qualified_id.
-Thu Apr 20 14:59:31 1995 Mike Stump <mrs@cygnus.com>
+1998-05-26 Dave Brolley <brolley@cygnus.com>
- * gc.c (build_dynamic_cast): Tighten error checking.
+ * lex.c (parse_options,yy_cur,yy_lim): Add for cpplib.
+ (init_parse): Initialize cpplib interface.
-Thu Apr 20 11:23:54 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * Makefile.in (CXX_OBJS): Make sure dependencies never end with an
+ empty continuation.
- * expr.c (cplus_expand_expr): Only abort if the returned target is
- different from what we expected if the type has a non-trivial copy
- constructor.
+1998-05-26 Mark Mitchell <mark@markmitchell.com>
- * decl2.c (cplus_decl_attributes): Attributes applied to a template
- really apply to the template's result.
+ * decl.c (pushtag): Avoid crashing on erroneous input.
- * tree.c (lvalue_p): Check IS_AGGR_TYPE instead of TREE_ADDRESSABLE
- to decide whether to consider a CALL_EXPR an lvalue.
+1998-05-25 Martin v. Löwis <loewis@informatik.hu-berlin.de>
- * class.c (finish_struct_bits): Only set TREE_ADDRESSABLE if the
- type has a non-trivial copy constructor.
+ * decl.c (push_namespace): Only produce one unique name for
+ anonymous namespaces.
+ (get_unique_name): Remove.
- * decl.c (start_function): If interface_known, unset
- DECL_NOT_REALLY_EXTERN on the function.
+1998-05-25 Mark Mitchell <mark@markmitchell.com>
-Wed Apr 19 16:53:13 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (tourney): Don't do any extra comparisons.
- * pt.c (do_function_instantiation): Handle explicit instantiation of
- member functions.
- (do_type_instantiation): Handle 'inline template class foo<int>',
- meaning just spit out the vtable.
+ * decl2.c (build_anon_union_vars): Don't crash on empty sub-unions.
- * lex.c (cons_up_default_function): Set DECL_NOT_REALLY_EXTERN on
- the consed functions.
+ * cp-tree.h (processing_template_parmlist): Declare.
+ * decl.c (pushtag): Don't call push_template_decl when we
+ shouldn't.
+ * pt.c (processing_template_parmlist): New variable.
+ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro.
+ (complete_template_args): Use it.
+ (add_to_template_args): Likewise.
+ (innermost_args): Likewise.
+ (tsubst): Likewise.
+ (begin_template_parm_list): Use processing_template_parmlist.
+ (end_template_parm_list): Likewise.
- * decl2.c (import_export_inline): Set DECL_INTERFACE_KNOWN.
+ * cp-tree.h (ANON_UNION_TYPE_P): New macro.
+ * decl.c (grokdeclarator): Use it.
+ * decl2.c (grok_x_components): Likewise.
+ * init.c (initializing_context): Likewise.
+ * method.c (do_build_copy_constructor): Likewise.
+ (do_build_assign_ref): Likewise.
+ * search.c (compute_access): Likewise.
+ * typeck.c (build_component_ref): Likewise.
-Wed Apr 19 16:28:17 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl.c (grokdeclarator): Don't give a cv-qualified version of an
+ unnamed type a typedef name "for linkage purposes".
- * call.c, class.c, decl2.c, gc.c, init.c, parse.y, pt.c, search.c,
- typeck.c: Include output.h.
+ * pt.c (lookup_template_class): Don't look at
+ IDENTIFIER_CLASS_VALUE when there's no current_class_type.
-Wed Apr 19 14:57:21 1995 Gerald Baumgartner (gb@alexander.cs.purdue.edu)
+ * method.c (build_overload_int): Handle error cases gracefully.
- * call.c (build_method_call): Allow a signature member functions to
- be called from a default implementation.
+ * pt.c (instantiate_decl): Handle static member variables
+ correctly.
-Wed Apr 19 10:21:17 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (tsubst): Use the tsubst'd type when producing new
+ TEMPLATE_PARM_INDEX nodes.
- * repo.c (finish_repo): Remember what directory we are in.
+1998-05-24 Mark Mitchell <mark@markmitchell.com>
- * search.c (expand_upcast_fixups): Don't mess with abort_fndecl.
+ * tree.c (cp_tree_equal): Handle pointers to member functions.
- * repo.c: Use obstacks instead of fixed-size buffers. Don't spit
- out the second copy of the symbol name. Don't remember COLLECT_GCC.
+ * call.c (maybe_handle_implicit_object): Handle QUAL_CONVs. Make
+ sure the type of the REF_BIND is a reference type.
+ (maybe_handle_ref_bind, compare_ics): Rename reference_type to
+ target_type for clarity.
-Wed Apr 19 02:32:40 1995 Mike Stump <mrs@cygnus.com>
+ * parse.y (xcond): Move call to condition_conversion ...
+ * semantics.c (finish_for_cond): Here.
+ * parse.c: Regenerated.
+
+1998-05-24 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (virtual_context): New function to get the virtual
- context of a function.
- (expand_upcast_fixups): New function to generate runtime vtables.
- (fixup_virtual_upcast_offsets): Ditto.
- (expand_indirect_vtbls_init): Use fixup_virtual_upcast_offsets to
- ensure that the this offsets for upcasts from virtual bases into
- other virtual bases or non-virtual bases are correct at construction
- time and destruction time.
- * class.c (fixup_vtable_deltas): Modify to fixup all offsets in all
- vtables in all virtual bases, instead of just one vtable in each
- virtual base.
- (fixup_vtable_deltas1): Ditto.
+ * decl.c (push_namespace): Namespaces have type void.
+ * typeck2.c (incomplete_type_error): Complain about namespace
+ used as expression.
+ * typeck.c (decay_conversion): Likewise.
-Tue Apr 18 03:57:35 1995 Michael Meissner (meissner@cygnus.com)
+1998-05-24 Martin von Löwis <loewis@informatik.hu-berlin.de>
- * Makefile.in (lex.o): Add dependency on c-pragma.h.
+ * error.c (dump_expr): Support namespaces.
- * lex.c (handle_sysv_pragma): Use NULL_PTR and NULL_TREE as
- appropriate, instead of 0.
+1998-05-23 Jason Merrill <jason@yorick.cygnus.com>
-Mon Apr 17 12:28:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cp-tree.def: Add SRCLOC.
+ * cp-tree.h: Add struct tree_srcloc and accessor macros.
+ * tree.c (build_srcloc, build_srcloc_here): New fns.
+ * pt.c (add_pending_template): Use build_srcloc_here.
+ (push_tinst_level): Update last_template_error_tick before erroring.
+ (instantiate_decl): Restore lineno and input_filename before
+ calling add_pending_template.
+ * decl2.c (finish_file): Set up lineno and input_filename for
+ pending templates.
- * decl.c (pushdecl): Use decls_match, not duplicate_decls, for
- comparing local and global decls.
+1998-05-22 Jason Merrill <jason@yorick.cygnus.com>
-Fri Apr 14 01:46:52 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (lang_print_error_function): New fn.
+ (init_decl_processing): Set print_error_function to use it.
+ * errfn.c (cp_thing): Don't call maybe_print_template_context here.
- * typeck.c (convert_arguments): Only prohibit passing to ... of
- types with non-trivial copy constructors.
+ * call.c (maybe_handle_ref_bind): Propagate ICS_USER_FLAG and
+ ICS_BAD_FLAG.
- * repo.c (repo_template_used): Don't try to mess with no id.
+ * cvt.c (ocp_convert): Don't set LOOKUP_NO_CONVERSION for
+ copy-initialization.
-Fri Apr 14 23:32:50 1995 Per Bothner <bothner@rtl.cygnus.com>
+ * class.c (build_vtable_entry): Use int_fits_type_p.
+ (build_vtable): Pass a signed offset to build_vtable_entry.
+ (prepare_fresh_vtable, modify_one_vtable, fixup_vtable_deltas1,
+ set_rtti_entry): Likewise.
- * decl.c (duplicate_decls): Use cp_warning_at for redundant-decls.
+1998-05-22 Per Bothner <bothner@cygnus.com>
-Thu Apr 13 15:37:42 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * cp-tree.h: Add comments documenting which LANG_FLAGS are used.
+ (C_TYPE_VARIABLE_SIZE, C_DECL_VARIABLE_SIZE): Removed, not used.
- * cp-tree.h (current_tinst_level): Delete declaration, since it's
- static inside pt.c.
+1998-05-22 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_modify_expr): Catch incompatible array assignment.
+ * pt.c (print_template_context): Use fprintf instead of cp_error.
- * parse.y (attribute_list, attrib): Rewrite actions to feed the
- right stuff to decl_attributes.
+ * pt.c (determine_specialization): Just return an error_mark_node.
+ Also print the decl we want in error messages. If we complain,
+ return error_mark_node.
+ (tsubst_friend_function): Set lineno and input_filename so
+ error messages will be useful.
+ (instantiate_template): Just return an error_mark_node.
+ (check_explicit_specialization): Don't mess with a returned
+ error_mark_node.
-Thu Apr 13 11:24:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (print_template_context): Add new argument.
+ (maybe_print_template_context): New fn.
+ (push_tinst_level): Increment tinst_level_tick.
+ (pop_tinst_level): Likewise.
+ * errfn.c (cp_thing): Call maybe_print_template_context. Use
+ xrealloc instead of xmalloc.
- * search.c (dfs_debug_mark): Check for magic virtual like
- import_export_vtable.
+ * typeck.c (build_unary_op, CONVERT_EXPR): Propagate TREE_CONSTANT.
- * typeck.c (build_binary_op_nodefault): Don't call cp_pedwarn with
- four args.
+1998-05-21 Jason Merrill <jason@yorick.cygnus.com>
-Wed Apr 12 12:02:57 1995 Jason Merrill <jason@deneb.cygnus.com>
+ * pt.c (tsubst_friend_class): Don't call redeclare_class_template
+ if the template we looked up is the same as the one we already
+ have.
- * decl2.c (finish_file): Move prevtable pass before needs_messing_up
- decision.
+Thu May 21 11:54:44 1998 Dave Brolley <brolley@cygnus.com>
-Tue Apr 11 11:20:27 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * lex.c: (handle_sysv_pragma): FILE* parameter not used.
+ (cpp_reader,parse_in): Add for cpplib.
+ (check_newline): Call handle_sysv_pragma with new interface.
+ (check_newline): Call GET_DIRECTIVE_LINE, not get_directive_line.
- * decl.c (finish_decl): If we're writing out a static data member of
- a class, we want the debug info for that class.
+ * input.c: (yy_cur,yy_lim,yy_get_token,GETC): Add for cpplib.
+ (sub_getch): Call GETC for cpplib.
- * gc.c (build_t_desc): Check linkage of a class properly.
+ * cp-tree.h: (get_directive_line): Different prototype for cpplib.
+ (GET_DIRECTIVE_LINE): Macro wrapper for get_directive_line.
- * class.c (finish_struct): Set the 'headof' offset for the main
- vtable properly.
- (prepare_fresh_vtable): Fix typeinfo pointer here.
- (modify_one_vtable): Instead of here.
+ * Makefile.in (CXX_OBJS): add @extra_cxx_objs@ for cpplib.
-Mon Apr 10 12:15:59 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-05-21 Jason Merrill <jason@yorick.cygnus.com>
- * repo.c (repo_get_id): New function to return the interesting
- identifier for a repo entity.
- (repo_template_used): Use it.
- (repo_template_instantiated): Mark the id as chosen.
- (init_repo): Record whether or not the id was chosen.
- (finish_repo): Note if an id was newly chosen.
+ * decl2.c (maybe_make_one_only): New fn.
+ (import_export_vtable): Use it.
+ (import_export_decl): Likewise.
+ * pt.c (mark_decl_instantiated): Likewise.
- * pt.c (do_function_instantiation): Call repo_template_instantiated.
- (do_type_instantiation): Ditto. Don't diagnose multiple
- instantiation.
+1998-05-21 Mark Mitchell <mmitchell@usa.net>
- * decl2.c (finish_file): Use DECL_NOT_REALLY_EXTERN when deciding
- whether or not to synthesize a method.
+ * decl2.c (find_representative_member): Rename to ...
+ (build_anon_union_vars): New function.
+ (finish_anon_union): Fix stupidity of previous change.
- Undo these changes:
- * class.c (finish_vtbls): build more vtables if flag_rtti is on.
- * class.c (modify_all_direct_vtables): ditto.
- * init.c (expand_direct_vtbls_init): expand more vtables if
- flag_rtti is on.
+1998-05-20 Jason Merrill <jason@yorick.cygnus.com>
-Sat Apr 8 17:45:41 1995 Mike Stump <mrs@cygnus.com>
+ * decl.c (grokfndecl): Handle definition of specialization in
+ friend declaration.
- * gc.c (build_headof): Use ptrdiff_type_node instead of
- integer_type_node on pointer arithmetic.
+ * error.c (dump_decl): Fix LOOKUP_EXPR handling.
-Sat Apr 8 11:57:04 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-05-20 Mark Mitchell <mmitchell@usa.net>
- * typeck.c (build_modify_expr): Undo previous change.
+ * class.c (delete_duplicate_fields_1): Use DECL_DECLARES_TYPE_P
+ to look for type declarations.
+ (finish_struct): Deal with templates on the CLASSTYPE_TAGS list.
+ * cp-tree.h (DECL_DECLARES_TYPE_P): New macro.
+ (finish_member_class_template): Declare.
+ * decl.c (pushtag): Put member class templates on the
+ CLASSTYPE_TAGS list, just as for ordinary member classes.
+ (pushdecl_class_level): Use DECL_DECLARES_TYPE_P.
+ (lookup_tag): Look for IDENTIFIER_CLASS_VALUEs, just as with
+ IDENTIFIER_NAMESPACE_VALUEs.
+ * parse.y (component_decl): Move code to ...
+ * semantics.c (finish_member_class_template): New function.
+ Don't put member class templates on the list of components for a
+ class.
+ * parse.c: Regenerated.
+ * pt.c (classtype_mangled_name): Don't try DECL_CONTEXT on types.
+ In fact, don't use DECL_CONTEXT at all here.
-Thu Apr 6 01:23:50 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-05-20 Martin von Loewis <loewis@informatik.hu-berlin.de>
- * Makefile.in (compiler): Remove ../cc1plus before rebuilding it.
+ * decl.c (record_unknown_type): New function.
+ (init_decl_processing): Call it for the unknown and global type
+ nodes.
- * repo.c (get_base_filename): Put the .rpo file in the directory
- with the object file, not the source.
+1998-05-20 Mark Mitchell <mmitchell@usa.net>
- * typeck.c (build_conditional_expr): Handle pmf's better.
+ * decl2.c (find_representative_member): New function.
+ (finish_anon_union): Use it.
- * repo.c (finish_repo): Also use ASM_OUTPUT_LABELREF to print out
- the name of the symbol.
+ * cp-tree.h (MAIN_NAME_P): New macro.
+ (DECL_MAIN_P): Likwise.
+ * decl.c (pushdecl): Avoid crashing on redefinitions of `main'.
+ (grokfndecl): Use the new macros.
+ (grokdeclarator): Likewise.
+ (start_function): Likewise.
+ (store_parm_decls): Likewise.
+ (finsh_function): Likewise.
+ * friend.c (do_friend): Likewise.
+ * typeck.c (build_function_call_real): Likewise.
+ (build_unary_op): Likewise.
-Wed Apr 5 15:24:12 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed May 20 02:16:01 1998 Jason Merrill <jason@yorick.cygnus.com>
- * repo.c (open_repo_file): Make repo filename DOS-compliant.
- (*): Also write a new repo file if some previously-used
- templates are no longer used. Only remember the identifier.
+ * decl2.c (start_objects, finish_objects, do_dtors,
+ do_ctors): Split out from...
+ (finish_file): ...here.
- * lex.c (cons_up_default_function): If this function belongs to a
- template class, call repo_template_used for it.
+Tue May 19 20:36:23 1998 Jason Merrill <jason@yorick.cygnus.com>
- * repo.c (repo_template_used): Using a class means using its vtable,
- if any.
- (finish_repo): Ditto.
+ * tree.c (is_overloaded_fn): Don't abort on placeholders from
+ push_class_decls.
- * typeck.c (build_modify_expr): Only wrap TARGET_EXPRs in RTL_EXPRs
- if the type has a complex copy constructor.
+Tue May 19 15:16:22 1998 Brendan Kehoe <brendan@cygnus.com>
- * decl2.c (lang_decode_option): -frepo implies
- -fno-implicit-templates.
+ * class.c (is_empty_class): Return 0 if TYPE is an error_mark_node.
- * decl.c (start_function): Clear current_{base,member}_init_list.
+ * error.c (dump_expr): Handle an ARROW_EXPR.
- * lex.c (init_lex): Also unset *_eq if ! flag_operator_names.
+Tue May 19 15:13:39 1998 Mark Mitchell <mmitchell@usa.net>
-Tue Apr 4 16:11:08 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (saveable_obstack): Declare.
+ (pushdecl): Copy TYPE_DECLs to the same obstack as the type they
+ declare, if necessary.
- * decl.c (struct cp_function): Add {base,member}_init_list.
- (push_cp_function_context): Save current_{base,member}_init_list.
- (pop_cp_function_context): Restore them.
+Tue May 19 14:50:27 1998 Mark Mitchell <mmitchell@usa.net>
-Mon Apr 3 16:55:08 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (compare_qual): Remove.
+ (is_subseq): Tweak.
+ (is_properly_derived_from): New function.
+ (maybe_handle_ref_bind): Likewise.
+ (maybe_handle_implicit_object): Likewise.
+ (compare_ics): Modify substantially to bring into conformance with
+ the standard.
+ * cp-tree.h (TYPE_PTRMEMFUNC_OBJECT_TYPE): New macro.
+ (comp_cv_qualification): Declare.
+ (comp_cv_qual_signature): Likewise.
+ * typeck.c (comp_cv_qualification): Likewise.
+ (comp_cv_qual_signature): Likewise.
- * repo.c (get_base_filename): Take filename parm, fix logic bug.
+Tue May 19 10:05:02 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * typeck.c (build_compound_expr): Do not warn about a compound expr
- in which the first expression has no side effects.
- (build_x_compound_expr): Warn here instead.
- (build_conditional_expr): Don't warn about a conditional expression
- between an enum and the type it promotes to.
+ * Makefile.in (parse.o): Depend on toplev.h.
- * init.c (build_new): Handle initialization of arrays of builtins
- properly.
+ * class.c (typecode_p): Remove prototype and definition.
-Mon Apr 3 15:08:04 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * cp-tree.h (currently_open_class, is_empty_class, member_p):
+ Add prototype.
- * repo.c: Include config.h to get definitions of bcopy and rindex
- on systems that don't have them (e.g., SVR4).
+ * decl.c (push_overloaded_decl_top_level): Remove prototype and
+ definition.
-Mon Apr 3 14:41:55 1995 Mike Stump <mrs@cygnus.com>
+ * errfn.c (cp_error): Cast function pointer `error' to (errorfn *)
+ in call to `cp_thing'.
+ (cp_warning): Likewise for function pointer `warning'.
- * decl2.c (finish_table): Pass NULL_TREE instead of init to
- finish_decl so that it won't try and do error checking on the
- initializer.
+ * except.c (do_function_call): Remove prototype and definition.
+ (call_eh_info): Wrap variable `t1' in macro NEW_EH_MODEL.
-Mon Apr 3 10:45:50 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * method.c (is_java_type): Add prototype and make it static.
- * repo.c (get_base_filename): Analyze COLLECT_GCC_OPTIONS to
- determine whether this compile used -c -o.
- (open_repo_file): Use get_base_filename. Remove the extension.
- (finish_repo): Spit out the values of main_input_filename,
- COLLECT_GCC and COLLECT_GCC_OPTIONS.
+ * parse.y: Include toplev.h.
- * parse.y (structsp): Add TYPENAME_KEYWORD complex_type_name.
+ * pt.c (type_unification): Remove unused variable `arg'.
+ (instantiate_decl): likewise for `save_ti'.
-Sun Apr 2 23:43:51 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * tree.c (propagate_binfo_offsets): Likewise for `base_binfos'.
+
+Tue May 19 02:43:25 1998 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (compute_access): Don't try to do access control on
- nested types.
+ * init.c (build_member_call): Handle template_ids.
+ * parse.y (primary): Add global_scope template_id.
-Fri Mar 31 10:14:23 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Mon May 18 23:22:52 1998 Jason Merrill <jason@yorick.cygnus.com>
- * repo.c: New file to handle things repo.
+ * decl2.c (get_sentry): Use end_temporary_allocation.
+ Don't declare permanent_obstack.
- * pt.c (instantiate_template): Call repo_template_used if the
- definition is accessible.
- (mark_function_instantiated): Split out from
- do_function_instantiation.
- (mark_class_instantiated): Split out from do_type_instantiation.
+Mon May 18 12:28:44 1998 Mark Mitchell <mmitchell@usa.net>
- * parse.y (template_instantiate_once): Call repo_template_used.
+ * parse.y (.finish_new_placement): New non-terminal.
+ (unary_expr, new_type_id): Use it.
+ * parse.c: Regenerated.
+
+Mon May 18 12:20:27 1998 Brendan Kehoe <brendan@cygnus.com>
- * lex.c (lang_init): Call init_repo.
+ * pt.c (redeclare_class_template): Say where the original definition
+ of the template-parameter's default argument appeared.
- * decl2.c: Handle flag_use_repository.
- (finish_file): Call finish_repo.
+Mon May 18 03:00:57 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_method): Call repo_template_used if this is a
- template method.
+ * call.c (build_over_call): Tweak empty class handling.
- * Makefile.in (CXX_OBJS): Add repo.o.
- (repo.o): Add dependencies.
+ * decl.c (make_typename_type): Use currently_open_class.
- * Make-lang.in (CXX_SRCS): Add repo.c.
+ * class.c (instantiate_type): Don't abort on TREE_NONLOCAL_FLAG.
- * decl.c (start_function): If DECL_INTERFACE_KNOWN and
- DECL_NOT_REALLY_EXTERN are both set, unset DECL_EXTERNAL.
+Mon May 18 01:43:01 1998 Martin v. Loewis <loewis@informatik.hu-berlin.de>
- * typeck.c (build_binary_op_nodefault): Identify the invalid operand
- types used.
+ * decl.c (lookup_name_real): Don't look at IDENTIFIER_LOCAL_VALUE
+ for a type unless it is one.
- * decl.c (duplicate_decls): Propagate DECL_NOT_REALLY_EXTERN.
+ * class.c (finish_struct_1): Use OVL_CURRENT in error message.
-Thu Mar 30 17:54:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Mon May 18 01:24:08 1998 Jeffrey A Law (law@cygnus.com)
- * typeck.c (build_binary_op_nodefault): Tidy up use of build_type
- and result_type. When checking for comparison between signed
- and unsigned, use result_type rather than the (possibly shortened)
- type of op0. Also, don't warn about equality comparison of a
- signed operand to an unsigned constant that fits in the signed
- type.
+ * Makefile.in (program_transform_name, objdir): Define.
- * method.c (do_build_copy_constructor): Reverse
- current_base_init_list after we've built it up.
+ * Makefile.in (BISON): Use bison from the build tree if it exists.
+ (FLEX): Similarly.
-Thu Mar 30 14:35:18 1995 Mike Stump <mrs@cygnus.com>
+Sun May 17 14:52:08 1998 Martin v. Loewis <loewis@informatik.hu-berlin.de>
- * except.c (build_throw): Never warn about the value of throw not
- being used.
+ * typeck.c (type_unknown_p): Return true for TREE_LIST also.
-Thu Mar 30 13:16:54 1995 Mike Stump <mrs@cygnus.com>
+ * call.c (build_method_call): Use TYPE_MAIN_VARIANT on typedefs.
- * except.c (expand_start_catch_block): Check for bad catch parameter
- declarations.
+Sun May 17 14:51:41 1998 Jason Merrill <jason@yorick.cygnus.com>
-Thu Mar 30 13:06:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (build_scoped_method_call): Likewise.
- * decl.c (finish_function): Only set DECL_NOT_REALLY_EXTERN if
- DECL_EXTERNAL is not already set.
+Sun May 17 13:53:48 1998 Mark Mitchell <mmitchell@usa.net>
-Thu Mar 30 11:26:24 1995 Mike Stump <mrs@cygnus.com>
+ * init.c (build_new_1): Call suspend_momentary around the creation
+ of values that must be saved for exception handling.
+ * parse.y (.build_new_placement): New non-terminal.
+ (unary_expr, new_placement): Use it.
+ * parse.c: Regenerated.
+
+Sun May 17 12:32:08 1998 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (emit_thunk): Let poplevel know that the last level is
- for a function so it can create a BLOCK_NODE and set DECL_INITIAL.
+ * decl.c (duplicate_decls): Use CANONICAL_TYPE_VARIANT to compare
+ old and new types.
-Thu Mar 30 11:15:06 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (tsubst): Make sure that BINFO_TYPE of new binfos is the
+ canonical type.
- * decl2.c (import_export_inline): Don't set DECL_NOT_REALLY_EXTERN
- here.
+ * call.c (build_over_call): Don't use IS_SIGNATURE on a namespace.
- * decl.c (grokdeclarator): OK, don't abort if we see a decl with
- METHOD_TYPE.
- (finish_function): Set DECL_EXTERNAL and DECL_NOT_REALLY_EXTERN on
- all deferred inlines.
+Fri May 15 20:28:00 1998 Jason Merrill <jason@yorick.cygnus.com>
-Wed Mar 29 19:35:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (start_decl): Revert problem change.
- * cp-tree.h (DECL_THIS_INLINE): New macro.
- (DECL_NOT_REALLY_EXTERN): New macro.
- (DECL_THIS_STATIC): New macro.
+ * Makefile.in (CONFLICTS): Fix.
- * decl.c: Lose all references to current_extern_inline. Break
- inline semantics into DECL_INLINE for actual inlining and
- DECL_THIS_INLINE for the linkage wierdness. Use DECL_THIS_STATIC.
- * decl2.c: Use DECL_NOT_REALLY_EXTERN to indicate that we want to
- emit an inline here. Associated changes.
- * lex.c: Ditto.
- * pt.c: Ditto.
- * typeck.c: Ditto.
+Fri May 15 15:34:02 1998 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * call.c (build_method_call): Don't bother trying to handle inlines
- specially.
- * cvt.c (convert_to_aggr): Ditto.
+ * decl.c (duplicate_decls): Clean up, add DECL_DATA_AREA bits.
- * pt.c (do_function_instantiation): Handle instantiation of
- public inlines, too.
+Fri May 15 00:46:05 1998 Jason Merrill <jason@yorick.cygnus.com>
-Wed Mar 29 16:04:25 1995 Mike Stump <mrs@cygnus.com>
+ * class.c (finish_struct_1): Use BINFO_SIZE.
- * except.c (init_exception_processing): Change the interface for
- __throw_type_match and add decl for new rtti matching routine
- __throw_type_match_rtti.
- (build_eh_type): New routine to build a run time descriptor for the
- expression given.
- (expand_start_catch_block): Update to use new calling convention for
- the matcher.
- (expand_throw): Update to use build_eh_type.
+ * decl.c (start_decl): Use 'tem'.
-Mon Mar 27 07:14:33 1995 Warner Losh <imp@village.org>
+Thu May 14 16:30:47 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
- * g++.c: Removed __NetBSD__ from conditional.
- Declare strerror if HAVE_STRERROR is defined; otherwise
- declare sys_errlist and sys_nerr.
- (my_strerror): New function.
+ * exception.cc: Include eh-common.h.
+ (struct cp_eh_info): add eh_info struct with NEW_EH_MODEL.
+ (__cplus_type_matcher): First stab at new C++ runtime type matcher.
+ (__cp_push_exception): Initialize eh_info struct as well.
+ * except.c: Remove local structs and include eh-common.h.
+ (init_exception_processing): Set language and version codes.
+ (call_eh_info): add presence of eh_info to runtime description of
+ struct cp_eh_info.
+ (expand_end_eh_spec): call start_catch_block() and end_catch_block().
+ * semantics.c (finish_try_block): call start_catch_block() and
+ end_catch_block().
+ * parse.y (function_try_block): call start_catch_block() and
+ end_catch_block().
-Tue Mar 28 14:16:35 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Thu May 14 12:27:34 1998 Brendan Kehoe <brendan@cygnus.com>
- * search.c (get_binfo): Don't try to be so clever.
+ * typeck.c (original_type): New function.
+ (common_type): Use it to get the DECL_ORIGINAL_TYPE for T1 and T2,
+ to see if they're actually the same.
+ * cp-tree.h (original_type): Declare.
- * tree.c (copy_to_permanent): Also suspend_momentary().
+Wed May 13 12:54:30 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * cvt.c (cp_convert_to_pointer): Hand off to convert_fn_pointer even
- if the types are the same.
+ * Makefile.in (lex.o): Depend on output.h.
+
+ * call.c (add_function_candidate): Remove unused variable `cand'.
+ (add_conv_candidate): Likewise.
+ (build_builtin_candidate): Likewise.
+
+ * cp-tree.h: Add prototype for `types_overlap_p'.
+
+ * decl.c (signal_catch): Mark parameter `sig' with ATTRIBUTE_UNUSED.
+
+ * decl2.c (merge_functions): Remove unused variables `tmp' and
+ `tempn'.
+
+ * error.c (expr_as_string): Mark parameter `v' with ATTRIBUTE_UNUSED.
+ (code_as_string): Likewise.
+ (language_as_string): Likewise.
+ (parm_as_string): Likewise.
+ (op_as_string): Likewise.
+ (assop_as_string): Likewise.
+ (cv_as_string): Likewise.
+
+ * lex.c: Include output.h.
+
+ * pt.c (type_unification): Cast first argument of `bzero' to a char*.
+
+ * search.c (dfs_no_overlap_yet): Mark parameter `t' with
+ ATTRIBUTE_UNUSED.
+
+ * tinfo.cc (__class_type_info::dcast): Change the type of variable
+ `i' from int to size_t.
+
+ * typeck.c (language_lvalue_valid): Mark parameter `exp' with
+ ATTRIBUTE_UNUSED.
+
+Tue May 12 21:37:49 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * error.c (dump_simple_decl): Use DECL_CLASS_SCOPE_P and/or
+ DECL_NAMESPACE_SCOPE_P.
+ (lang_decl_name): Likewise.
+ * pt.c (tsubst_friend_function, tsubst): Likewise.
+ * decl.c (pushdecl, redeclaration_error_message, start_decl,
+ cp_finish_decl, start_function): Likewise.
+ * class.c (finish_struct_1): Likewise.
+ * call.c (build_over_call): Likewise.
+ (compare_ics): Use DERIVED_FROM_P.
+
+Tue May 12 07:24:18 1998 Mark Mitchell <mmitchell@usa.net>
+
+ * cp-tree.h (CANONICAL_TYPE_VARIANT): New macro.
+ * method.c (build_mangled_name): Use it.
+ (build_decl_overload_real): Likewise.
+
+ * error.c (dump_simple_decl): New function, broken out from ...
+ (dump_decl): Use it.
+
+Mon May 11 11:38:07 1998 Mark Mitchell <mmitchell@usa.net>
+
+ * ptree.c (lang_print_xnode): Add missing `break'.
+
+ * pt.c (tsubst): Remove duplicate check for IDENTIFIER_NODE.
+
+ * call.c (add_template_candidate): Adjust for changes to
+ fn_type_unification.
+ (add_template_candidate_real): Likewise.
+ (add_template_conv_candidate): Likewise.
+ (build_user_type_conversion_1): Likewise.
+ (build_new_function_call): Likewise.
+ (build_object_call): Likewise.
+ (build_new_op): Likewise.
+ (build_new_method_call): Likewise.
+ * class.c (instantiate_type): Likewise.
+ * cp-tree.h (unification_kind_t): New type.
+ (fn_type_unification): Adjust prototype.
+ (type_unificaiton): Likewise.
+ * pt.c (UNIFY_ALLOW_NONE): New macro.
+ (UNIFY_ALLOW_MORE_CV_QUAL): Likewise.
+ (UNIFY_ALLOW_LESS_CV_QUAL): Likewise.
+ (UNIFY_ALLOW_DERIVED): Likewise.
+ (unify): Change prototype.
+ (maybe_adjust_types_for_deduction): New function.
+ (check_cv_quals_for_unify): Likewise.
+ (determine_specialization): Adjust.
+ (fn_type_unification): Likewise.
+ (type_unification): Likewise.
+ (type_unification_real): Likewise. Use
+ maybe_adjust_types_for_deduction. Fix mishandling of
+ back-unification of template functions passed as arguments. Pass
+ appropriate combination of UNIFY_ALLOW_* to unify.
+ (unify): Remove unused NTPARMS parameter. Use
+ check_cv_quals_for_unify. Remove bogus code that allowed
+ too-generous unification in order to adhere more closely to standard.
+ (get_bindings_real): Adjust.
+ (get_class_bindings): Likewise.
+
+ * method.c (build_overload_identifier): Only use the innermost
+ template arguments when mangling.
+ * pt.c (tsubst_template_argument_vector): New function.
+ (complete_template_args): Deal with the situation where the
+ extra_args contain more than one level of arguments.
+ (lookup_template_class): Deal with member template classes, which
+ may have more than one level of arguments.
+ (tsubst): Don't tsbust into the TREE_TYPE of an IDENTIFIER_NODE.
+ Improve handling of member template classes. Use
+ DECL_PRIMARY_TEMPLATE instead of inline expansion. Use
+ tsubst_template_argument_vector where appropriate.
+ (regenerate_decl_from_template): Break out from ...
+ (instantiate_decl): Here.
+
+ * lex.c (yyprint): Remove TYPENAME_ELLIPSIS.
+ * parse.h: Regenerated.
+ * parse.c: Really regenerated.
+
+ * cp-tree.h (finish_unary_op_expr): New function.
+ (finish_id_expr): Likewise.
+ (begin_new_placement): Likewise.
+ (finish_new_placement): Likewise.
+ (finish_declarator): Likewise.
+ (finish_translation_unit): Likewise.
+ (finish_parmlist): Likewise.
+ (begin_class_definition): Likewise.
+ (finish_class_definition): Likewise.
+ (finish_default_args): Likewise.
+ (finish_inline_definitions): Likewise.
+ * parse.y (GCC_ASM_KEYWORD): Remove.
+ (TYPENAME_ELLIPSIS): Likewise.
+ * parse.c: Regenerated.
+ Use new functions in semantics.c in the actions for many rules.
+ * gxx.gperf (GCC_ASM_KEYWORD): Just use ASM_KEYWORD.
+ * hash.h: Regenerated.
+ * semantics.c (finish_expr_stmt): Allow NULL expr.
+ (finish_unary_op_expr): New function, containing
+ code previously in parse.y.
+ (finish_id_expr): Likewise.
+ (begin_new_placement): Likewise.
+ (finish_new_placement): Likewise.
+ (finish_declarator): Likewise.
+ (finish_translation_unit): Likewise.
+ (finish_parmlist): Likewise.
+ (begin_class_definition): Likewise.
+ (finish_class_definition): Likewise.
+ (finish_default_args): Likewise.
+ (finish_inline_definitions): Likewise.
+
+Sun May 10 23:43:13 1998 Mark Mitchell <mmitchell@usa.net>
+
+ * typeck.c (build_c_cast): Don't decay arrays and functions to
+ pointer type when converting to a class type.
+
+Sun May 10 22:53:56 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (DECL_NAMESPACE_SCOPE_P): New macro.
+ (DECL_CLASS_SCOPE_P): Likewise.
+
+Sun May 10 22:48:22 1998 H.J. Lu (hjl@gnu.org)
+
+ * class.c (finish_struct_1): Use OVL_CURRENT on TREE_VEC_ELT.
+ * decl2.c (constructor_name_full): Likewise.
+
+Sun May 10 22:48:12 1998 Mike Stump <mrs@wrs.com>
+
+ * tree.c (mapcar): Add OVERLOAD support.
+
+ * init.c (resolve_offset_ref): We must use basetype_path before we
+ destroy it with a call to convert_pointer_to.
+
+Sat May 9 14:44:37 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c (currently_open_class): New fn.
+ * decl.c (lookup_name_real): Use it.
+ * search.c (lookup_field): Likewise.
+
+Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+ * cp-tree.def (OVERLOAD): New node.
+ * cp-tree.h (BINDING_TYPE, SET_IDENTIFIER_GLOBAL_VALUE,
+ SET_IDENTIFIER_NAMESPACE_VALUE): Define.
+ (NAMESPACE_BINDING): Remove.
+ (IDENTIFIER_GLOBAL_VALUE, IDENTIFIER_NAMESPACE_VALUE): Use
+ namespace_binding.
+ (OVL_FUNCTION, OVL_CHAIN, OVL_CURRENT, OVL_NEXT, OVL_USED):
+ Define.
+ (tree_overload): New struct.
+ (IDENTIFIER_TYPE_VALUE): Use identifier_type_value.
+ (REAL_IDENTIFIER_TYPE_VALUE): Define.
+ (IDENTIFIER_HAS_TYPE_VALUE): Use IDENTIFIER_TYPE_VALUE.
+ (lang_decl_flags): Remove in_namespace.
+ (lang_decl): Remove chain.
+ (DECL_CHAIN, DECL_NAMESPACE): Remove.
+ (flag_honor_std): Declare extern.
+ (identifier_type_value, pushdecl_namespace_level, push_using_decl,
+ namespace_binding, set_namespace_binding,
+ lookup_function_nonclass, cat_namespace_levels,
+ set_decl_namespace, lookup_arg_dependent, binding_init, ovl_cons,
+ scratch_ovl_cons, ovl_member, build_overload): Declare.
+ (decl_list_length, get_namespace_id, current_namespace_id,
+ overloaded_globals_p): Remove.
+ (lookup_using_namespace, qualified_lookup_using_namespace): Change
+ return type.
+ (push_scratch_obstack): New macro.
+ * call.c (add_function_candidate): Special-case type of OVERLOAD node.
+ (build_user_conversions_1): Iterate using OVL_NEXT for ctors,
+ convs, fns.
+ (build_new_function_call): Iterate using OVL_CHAIN.
+ Print DECL_NAME in when reporting ambiguities.
+ (build_object_call): Iterate using OVL_NEXT for fns, convs.
+ (build_new_op): Call lookup_function_nonclass.
+ Iterate using OVL_NEXT.
+ (build_op_delete_call): Change detection of members.
+ Do not wrap TREE_LIST around fields and single global functions.
+ (build_over_call): Don't push a class level if the context is a
+ namespace.
+ (build_new_method_call): Iterate using OVL_NEXT.
+ * class.c (add_method): Chain overloaded members using
+ build_overload. Remove copying of method.
+ (grow_method): When iterating through the obstack, expect OVERLOAD
+ nodes. Chain overload members.
+ (finish_struct_methods): Chain overload members. Unpack OVERLOAD
+ nodes in call to get_baselinks.
+ (duplicate_tag_error): Expect OVERLOAD nodes when unchaining.
+ (finish_struct_1): Iterate over ctor using OVL_NEXT. Handle
+ fdecls that are OVERLOAD nodes.
+ (validate_lhs): New function.
+ (instantiate_type): Do not copy OVERLOAD nodes. Remove dead
+ code. Use DECL_NAME in error messages. Split code between global
+ and member function processing.
+ * decl.c (global_type_node): New static variable.
+ (in_std): New global.
+ (struct binding_level): New field usings.
+ (resume_binding_level): Assert that we are not in a class.
+ (toplevel_bindings_p): Just check for namespace_p or
+ pseudo_global.
+ (resume_level): Remove.
+ (find_binding): New function.
+ (binding_for_name): Call it.
+ (namespace_binding, set_namespace_binding): New functions.
+ (push_namespace): Associate binding level with new namespace,
+ resume_binding_level for existing namespace. Remove old code.
+ Fake std by counting.
+ (store_bindings): Use REAL_IDENTIFIER_TYPE_VALUE.
+ (maybe_push_to_top_level): Save current namespace.
+ (pop_from_top_level): Restore saved namespace.
+ (pop_namespace): Call suspend_binding_level. Remove old code.
+ (cat_namespace_levels): New function.
+ (set_identifier_type_value_with_scope): For namespace bindings,
+ set BINDING_TYPE, and use global_type_node.
+ Use REAL_IDENTIFIER_TYPE_VALUE otherwise.
+ (identifier_type_value): New function.
+ (pushtag): If no context, use current_namespace.
+ (duplicate_decls): Don't process DECL_CHAIN.
+ (pushdecl): Set DECL_CONTEXT to current_namespace, if it is not
+ already set. Never reset it to NULL_TREE. Lookup global variables
+ in their namespace. Push overloaded templates if they are on
+ namespace level.
+ (pushdecl_namespace_level): New function.
+ (pushdecl_top_level): Implement using pushdecl_namespace_level.
+ (pushdecl_using_decl): New function.
+ (overloaded_globals_p): Remove.
+ (push_overloaded_decl): Create OVERLOAD nodes, and iterate through
+ them. Use namespace_binding and set_namespace_value.
+ (redeclaration_error_message): Complain if the declarations come
+ from different namespaces.
+ (lookup_tag): On namespace level, look in the BINDING_TYPE.
+ (lookup_namespace_name): Pass tree_bindings from stack. Remove
+ old code.
+ (select_decl): New function.
+ (lookup_name_real): Call it for qualified and unqualified lookup.
+ Pass tree_bindings from the stack.
+ If prefer_type is 1, also accept namespaces.
+ (lookup_function_nonclass): New function.
+ (init_decl_processing): Set the binding level of the global
+ namespace to global_binding_level.
+ Build a proper type list for __builtin_apply.
+ Initialize std_node to "fake std" if flag_honor_std is set.
+ Initialize global_type_node.
+ Allocated bad_alloc in namespace std if flag_honor_std.
+ (define_function): Set the DECL_CONTEXT to the current_namespace.
+ (start_decl): A namespace is not considered as a context here. If
+ the DECL_CONTEXT is a namespace, push the decl.
+ (cp_finish_decl): Check for namespaces used as initializers.
+ (grokfndecl): Add namespace parameter. Remove processing of
+ DECL_CHAIN.
+ (grokvardecl): Add namespace parameter.
+ (grokdeclarator): Process SCOPEs that are namespaces. For
+ mangling, temporarily set the DECL_CONTEXT on anonymous structs.
+ (start_function): Check for contexts that are namespaces.
+ Set context for declarations that have not been pushed.
+ (store_parm_decls): Check for ::main only.
+ (finish_function): Likewise.
+ (start_method): Check for contexts that are namespaces.
+ (start_method): Remove DECL_CHAIN processing.
+ * decl2.c (flag_honor_std): Declare.
+ (lang_decode_option): Set it if -fhonor-std or -fnew-abi is given.
+ (decl_namespace_list): New static global.
+ (grok_x_components): Ignore namespaces as type contexts.
+ (check_classfn): Expect OVERLOAD nodes.
+ (grokfield): Remove DECL_CHAIN processing.
+ (finish_file): Call cat_namespace_levels.
+ (merge_functions): New function.
+ (ambiguous_decl): Rewrite.
+ (lookup_using_namespace): Produce tree_bindings.
+ (qualified_lookup_using_namespace): Likewise.
+ (set_decl_namespace, decl_namespace, current_decl_namespace,
+ push_decl_namespace, pop_decl_namespace): New functions.
+ (arg_lookup): New struct.
+ (add_function, arg_assoc_namespace, arg_assoc_class,
+ arg_assoc_type, arg_assoc_args, arg_assoc, lookup_arg_dependent):
+ New functions.
+ (get_namespace_id, current_namespace_id): Remove.
+ (do_toplevel_using_decl): Rewrite.
+ (do_class_using_decl): Complain about namespace qualifiers.
+ (do_using_directive): Sorry if not on namespace level. Complain
+ about unknown namespaces.
+ * error.c (dump_aggr_type): Check for namespace contexts.
+ * except.c (init_exception_processing): Push terminate into std.
+ * friend.c (is_friend): A namespace is not a context, here.
+ * init.c (expand_member_init): Remove DECL_CHAIN processing.
+ (build_offset_ref): Process OVERLOAD nodes.
+ * lang-specs.h (__HONOR_STD): Define if -fnew-abi or -fhonor-std.
+ * lex.c (identifier_type): Loop using OVL_CHAIN.
+ (see_typename): Set looking_for_typename to 2.
+ (real_yylex): Likewise.
+ (do_identifier): Expect OVERLOAD nodes instead of TREE_LISTs.
+ (do_scoped_id): Expect OVERLOAD nodes.
+ Change calling convention for qualified_lookup_using_namespace.
+ (build_lang_decl): Don't set in_namespace anymore.
+ * method.c (typevec_size): New global.
+ (build_overload_nested_name): Return if global_namespace.
+ Otherwise, always expect a declaration context.
+ (build_qualified_name): Likewise.
+ Make sure we don't write beyond typevec_size.
+ (build_decl_overload_real): Likewise.
+ Allocate one extra slot for the namespace.
+ (hack_identifier): Mark code dead.
+ Process OVERLOAD and NAMESPACE_DECL nodes.
+ * parse.y (program): Pop namespaces until in global namespace.
+ (extdef): In a using-declaration, don't discard the identifier if
+ there is no declaration.
+ (left_curly): Ignore type contexts which are namespaces.
+ (typename_sub2): Use IDENTIFIER_TYPE_VALUE to retrieve the type
+ used as scope.
+ * pt.c (template_class_depth): Expect types to be namespaces.
+ (determine_specialization): Simplify by expecting OVERLOAD nodes.
+ (push_template_decl): Push into namespace level.
+ Reset ctx if it is a namespace.
+ Set DECL_CONTEXT to current_namespace if not set already.
+ Ignore real contexts that are namespaces.
+ (mangle_class_name_for_template): Skip global_namespace.
+ Mangle other namepaces as declarations.
+ (lookup_template_function): Set type of OVERLOAD nodes to unknown.
+ (lookup_template_class): Push into namespace of context.
+ If the context is a namespace, set it to global_namespace.
+ Use id_context for mangling.
+ (for_each_template_parm): Handle OVERLOAD and NAMESPACE_DECL nodes.
+ (tsubst_friend_function): Ignore namespace contexts.
+ Push into namespace level.
+ (tsubst): Handle NAMESPACE_DECL nodes.
+ Remove DECL_CHAIN processing.
+ (type_unification_real): Recognize OVERLOAD instead of TREE_LIST nodes.
+ * ptree.c (print_lang_identifier): Print bindings.
+ (lang_print_xnode): Print OVERLOAD nodes.
+ * rtti.c (init_rtti_processing): Push type_info into std.
+ * search.c (lookup_fnfields_here): Expect OVERLOAD nodes.
+ (lookup_fnfields_1, get_virtuals_named_this, get_matching_virtual,
+ dfs_debug_mark, dfs_pushdecls, dfs_compress_decls, add_conversions,
+ lookup_fnfields_here): Likewise.
+ Process all nodes, instead of going through TREE_CHAIN.
+ * sig.c (build_signature_pointer_or_reference_type): Set context
+ to global_namespace.
+ (build_signature_table_constructor): Expect OVERLOAD nodes.
+ * spew.c (yylex): Save old setting of looking_for_typename.
+ * tree.c (decl_list_length): Remove.
+ (binding_init): New function.
+ (count_functions): Rewrite.
+ (is_overloaded_fn): Expect OVERLOAD nodes.
+ (really_overloaded_fn, get_first_fn, lvalue_type): Likewise.
+ (ovl_cons, scratch_ovl_cons, build_overload, build_overload_after,
+ ovl_member): New functions.
+ * typeck.c (require_complete_type): Expect OVERLOAD nodes.
+ (type_unknown_p): Likewise.
+ (require_instantiated_type): Likewise.
+ (build_component_ref): Declare code dead.
+ (build_x_function_call): Create and expect OVERLOAD nodes.
+ (build_function_call_real): Check for ::main only.
+ (build_unary_op): Likewise. Expect OVERLOAD nodes.
+ (convert_for_assignment): Check for TREE_LIST before accessing
+ TREE_VALUE.
+ * decl.c (duplicate_decls): Check for namespace bindings instead
+ of global bindings.
+ (pushdecl, push_overloaded_decl, lookup_tag, lookup_name_real,
+ lookup_name_current_level, start_decl, xref_tag,
+ finish_enum): Likewise.
+ * init.c (build_offset_ref): Likewise.
+ * search.c (lookup_field): Likewise.
+ (lookup_fnfields): Likewise.
+ (dfs_debug_mark): Likewise.
+ * decl.c (poplevel): Use SET_IDENTIFIER_TYPE_VALUE.
+ (poplevel_class, pop_from_top_level): Likewise.
+ * decl2.c (finish_method): Likewise.
+ * class.c (build_vtable): Use SET_IDENTIFIER_GLOBAL_VALUE.
+ * decl.c (record_builtin_type): Likewise.
+ (init_decl_processing, grokfndecl): Likewise.
+ * lex.c (get_time_identifier, do_identifier, do_scoped_id): Likewise.
+ (make_lang_type): Likewise.
+ * parse.y (make_thunk): Likewise.
+ * pt.c (tsubst): Likewise.
+ * tree.c (debug_binfo): Likewise.
+ * exception.cc, new.cc, new1.cc, new2.cc, tinfo.cc, tinfo.h,
+ tinfo2.cc, inc/new.h: Add std qualifications.
+ * inc/new: Wrap with namespace std if __HONOR_STD.
+ * inc/typeinfo: Likewise.
+
+Fri May 8 00:43:50 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (build_user_type_conversion_1): Handle second_conv
+ properly for templates.
+
+Thu May 7 17:09:25 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+
+ * method.c (build_decl_overload_real): Set TREE_USED flag to
+ zero for build_type_variants nodes as well.
+
+Wed May 6 19:27:09 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst): Don't tsubst the type of an IDENTIFIER_NODE.
+
+Wed May 6 16:49:48 1998 Jim Wilson <wilson@cygnus.com>
+
+ * Makefile.in (call.o, class.o, decl.o, decl2.o, errfn.o, error.o,
+ except.o, expr.o, friend.o, init.o, lex.o, method.o, pt.o, repo.o,
+ rtti.o, search.o, semantics.o, sig.o, tree.o, typeck.o, typeck2.o,
+ xref.o): Add toplev.h dependencies.
+
+Wed May 6 16:44:58 1998 Jeffrey A Law (law@cygnus.com)
+
+ * errfn.c (cp_error, cp_warning): Remove declarations for
+ error and warning respectively.
+
+Wed May 6 14:28:18 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * error.c: Convert to using ctype macros defined in system.h.
+ * method.c: Likewise.
+ * xref.c: Likewise.
+ * lex.c: Likewise. Also remove redundant system header stuff.
+
+Wed May 6 06:36:41 1998 Robert Lipe <robertl@dgii.com>
+
+ * call.c, class.c, decl.c, decl2.c, errfn.c, error.c, except.c,
+ expr.c, friend.c, init.c, lex.c, method.c, pt.c, repo.c, rtti.c,
+ search.c, semantics.c, sig.c, tree.c, typeck.c, typeck2.c,
+ xref.c: Add include of toplev.h.
+
+Wed May 6 02:33:39 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (perm_manip): Also regenerate the RTL of an extern.
+ (copy_to_permanent): Use end_temporary_allocation.
+
+Tue May 5 23:54:04 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * init.c (expand_vec_init): The initialization of each array
+ element is a full-expression.
+
+Tue May 5 18:24:13 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+
+ * method.c (build_mangled_name): Add a call to build_type_variant
+ to get the right type.
+
+Tue May 5 01:25:03 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * Makefile.in: Add .SUFFIXES.
+
+ * cp-tree.def: Remove NAMESPACE_DECL.
+
+Sun May 3 01:32:14 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (build_over_call): Do evaluate arg even if it has empty
+ class type.
+ * decl.c (start_function): Don't push a member function.
+
+Thu Apr 30 18:59:23 1998 Jim Wilson <wilson@cygnus.com>
+
+ * Makefile.in (g++FAQ.info): Put -o option before input file.
+
+Thu Apr 30 13:05:33 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+
+ * gxxint.texi: Add info for squangling codes K and B.
- * decl.c (start_function): Handle extern inlines more like C++ says
- we should.
+Tue Apr 28 13:22:01 1998 Mark Mitchell <mmitchell@usa.net>
- * init.c (build_member_call): Hand constructor calls off to
- build_functional_cast.
+ * semantics.c (begin_stmt_expr): Avoid duplicating the effect of
+ the expression in templates.
+ (finish_stmt_expr): Likewise.
- * typeck2.c (build_functional_cast): Use DECL_NESTED_TYPENAME to get
- the name of the type.
+1998-04-28 Brendan Kehoe <brendan@cygnus.com>
-Tue Mar 28 13:13:56 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl2.c (ambiguous_decl): Fix NAME parm to be a tree, not int.
- * decl.c (grokdeclarator): Check for the decl returned by
- grokfndecl to be null before using build_decl_attribute_variant.
+Mon Apr 27 13:58:10 1998 Mark Mitchell <mmitchell@usa.net>
-Mon Mar 27 18:04:41 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl.c (maybe_push_to_top_level): Always clear
+ current_template_parms and processing_template_decl.
+ (pushtag): Remove check of current_class_type and some comments,
+ since maybe_push_to_top_level no longer creates confusion.
- * init.c (build_new): Use build_pointer_type instead of
- TYPE_POINTER_TO.
+Sun Apr 26 12:10:18 1998 Mark Mitchell <mmitchell@usa.net>
-Fri Mar 24 12:11:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cp-tree.h (CLASSTYPE_IS_TEMPLATE): New macro.
+ (DECL_CLASS_TEMPLATE_P): Likewise.
+ (DECL_PRIMARY_TEMPLATE): Likewise.
+ (PRIMARY_TEMPLATE_P): Use it.
+ (push_template_decl_real): New function.
+ (redeclare_class_template): Take new template parameters as
+ input.
+ (is_specialization_of): New function.
+ (comp_template_args): Declare.
+ * decl.c (pushtag): Handle friend template classes.
+ (xref_tag): Likewise. Use new calling convention for
+ redeclare_class_template.
+ * decl2.c (grok_x_components): Handle friend templates.
+ * friend.c (is_friend): Use is_specialization_of where
+ appropriate. Deal with friend class templates.
+ (make_friend_class): Let a class template be friends with itself.
+ * pt.c (comp_template_args): Remove declaration.
+ (tsubst_friend_class): New function.
+ (push_template_decl_real): New function.
+ (push_template_decl): Use it.
+ (redeclare_class_template): Adjust for new calling convention.
+ (comp_template_args): Give it external linkage.
+ (instantiate_class_type): Use tsubst_friend_class to deal
+ with friend templates.
+ * typeck.c (comptypes): Use comp_template_args, rather than
+ expanding it inline.
+ * parse.y (component_decl): Handle a nested template type
+ like other component type declarations.
- * typeck.c (build_conditional_expr): Handle pmfs.
- (convert_for_assignment): Fix pmf support.
+ * pt.c (check_explicit_specialization): Handle overloaded
+ constructors correctly.
- * cvt.c (convert_fn_ptr): Support !flag_vtable_thunks.
- (cp_convert_to_pointer): Handle pmfs.
- (cp_convert): Pass pmfs to cp_convert_to_pointer.
+ * pt.c (mabybe_get_template_decl_from_type_decl): New function.
+ (lookup_template_class): Use it.
- * typeck.c (common_type): Handle inheritance for pmfs.
+Thu Apr 23 21:19:06 1998 Jason Merrill <jason@yorick.cygnus.com>
- * typeck2.c (build_m_component_ref): Do access control.
+ * cp-tree.def: Add WRAPPER. USER_CONV now only has two ops.
+ * cp-tree.h: Add WRAPPER support.
+ * call.c (add_candidate): Split out from add_*_candidate fns.
+ (build_over_call): Take the candidate instead of function and args.
+ Enforce access control here. Emit overload warnings here.
+ (add_warning): New fn.
+ (joust): Add WARN parm. If not set, call add_warning instead of
+ printing a warning. Reenable some warnings.
+ (tourney): Pass it.
+ (convert_like): Adjust.
+ (build_new_op): Adjust.
+ (build_new_function_call): Adjust.
+ (build_user_type_conversion_1): Adjust.
+ (USER_CONV_FN): Adjust.
+ * tree.c (build_expr_wrapper, build_expr_ptr_wrapper,
+ build_int_wrapper): New fns.
- * typeck.c (comp_target_types): Check for conversion to void *
- before checking trickier conversions.
+Thu Apr 23 18:27:53 1998 Mark P. Mitchell <mmitchell@usa.net>
- * decl.c (duplicate_decls): Propagate DECL_ABSTRACT_VIRTUAL_P.
+ * pt.c (unify): Fix typo in previous change.
- * pt.c (push_tinst_level): Complain if template instantiation depth
- is greater than max_tinst_depth.
+Thu Apr 23 09:32:58 1998 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (common_type): Assume that we can call common_type to
- unify the target type of a pointer.
+ * error.c (dump_type_real): Declare canonical_name.
-Thu Mar 23 00:48:44 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * typeck.c (comp_target_types): Fix PMFs.
- * decl2.c (finish_file): Don't synthesize methods at
- finish_vtable_prevardecl time. Do synthesize methods that are not
- used, but are public and not external.
+Wed Apr 22 13:24:48 1998 Mark Mitchell <mmitchell@usa.net>
- * cvt.c (build_type_conversion): Only give an error if for_sure.
+ * class.c (finish_struct): Set TREE_PRIVATE and TREE_PROTECTED for
+ the DECL_RESULTs of a member TEMPLATE_DECL, not just the
+ TEMPLATE_DECL.
- * typeck.c (comp_target_types): Only support pointer conversions if
- nptrs > 0.
+ * pt.c (tsubst): Decrease the template-level of
+ TEMPLATE_TEMPLATE_PARMS. Likewise for the DECL_INITIAL of a
+ TEMPLATE_PARM_INDEX.
+ (template_decl_level): New function.
+ (unify): Make sure to record unifications for template
+ parameters, even when the parameters exactly match the arguments.
+ Combine duplicated code for TEMPLATE_TEMPLATE_PARMs and
+ TEMPLATE_TYPE_PARMS. Don't try to unify template parameters that
+ aren't from the level we're currently working on.
-Wed Mar 22 19:30:15 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Tue Apr 21 22:00:04 1998 Mark Mitchell <mmitchell@usa.net>
- * init.c (build_new): Catch use of an initializer list where it
- shouldn't be.
+ * errfn.c (cp_thing): Use xrealloc, not xmalloc, to copy memory.
-Wed Mar 22 16:21:07 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (check_member_template): Set DECL_IGNORED for member
+ class templates, too.
- * init.c (build_new): Wrap alloc_expr in an RTL_EXPR if nelts is
- non-constant.
+ * decl2.c (grokfield): Remangle the name of a member TYPE_DECL.
- * decl2.c: temp_name_counter is now public.
+Tue Apr 21 18:59:11 1998 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * decl.c (struct cp_function): Add temp_name_counter field.
- (push_cp_function_context): Save it.
- (pop_cp_function_context): Restore it.
+ * decl.c (duplicate_decls): Only check DECL_FRIEND_P if function.
- * typeck.c (common_type): Handle unifying function types, and unify
- unmatched things to void* with a compiler_error, rather than
- silently like before.
+Tue Apr 21 14:22:00 1998 Jeffrey A Law (law@cygnus.com)
-Wed Mar 22 15:10:34 1995 Mike Stump <mrs@cygnus.com>
+ * cp-tree.h (intTI_type_node, unsigned_intTI_type_node): Declare.
+ * decl.c (intTI_type_node, unsigned_intTI_type_node): Define.
+ (init_decl_processing): Handle TI types.
+ * typeck.c (unsigned_type, signed_type): Handle TI types.
- * decl2.c (finish_prevtable_vardecl, finish_vtable_vardecl): Revert
- Brendan's last change and fix latent problem that causes TD entries
- to not come out when the things that need them has yet to be
- expanded.
+Sat Apr 18 15:25:21 1998 Jim Wilson <wilson@cygnus.com>
-Wed Mar 22 15:12:00 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * g++spec.c (lang_specific_driver): New argument in_added_libraries.
+ New local added_libraries. Increment count when add library to
+ arglist.
- * typeck.c (build_binary_op_nodefault, comparison ops): Update type0
- and type1, since we might have changed op0 or op1.
+Fri Apr 17 21:25:00 1998 Mark Mitchell <mmitchell@usa.net>
-Wed Mar 22 13:33:45 1995 Jason Merrill <jason@python.cygnus.com>
+ * cp-tree.h (type_as_string_real): New function.
+ * pt.c (mangle_class_name_for_template): Use it.
+ * error.c (dump_aggr_type): Change prototype.
+ (dump_type_prefix): Likewise.
+ (dump_type_suffix): Likewise.
+ (dump_type_real): Convert from dump_type. If desired, the
+ "canonica" name of a typedef, i.e., the name of the underlying
+ type, can be printed.
+ (dump_type): Call dump_type_real.
- * typeck.c (common_type): Don't mess up templates.
+Fri Apr 17 14:30:45 1998 Jason Merrill <jason@yorick.cygnus.com>
-Wed Mar 22 04:56:00 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (lang_decode_option): -fnew-abi implies -fvtable-thunks.
- * typeck.c (common_type): Handle ptms properly. Also handle
- T* -> void*.
- (build_binary_op_nodefault): New variable build_type controls what
- type is given to the expression when it is created. Set this to
- boolean_type_node for comparison ops instead of using result_type.
- (comp_target_types): Allow T * -> void *.
+ * typeck.c (comp_target_types): Tweak pedantic case.
+ (comp_target_parms): Tweak pedantic case. Clean up somewhat.
+ Return -1 or 1 instead of 1 or 2.
+ (compparms): Remove STRICT handling.
+ (convert_for_assignment): Fix handling of pmfs.
- * cvt.c (cp_convert_to_pointer): Do access control when converting
- ptms, too.
+Fri Apr 17 14:04:16 1998 Mark Mitchell <mmitchell@usa.net>
-Tue Mar 21 17:25:06 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * typeck.c (comp_target_types): Handle references like pointers.
+ (comp_target_parms): Note that return code from comp_target_types
+ can be negative to indicate failure.
- * parse.y (extern_lang_string): Catch use of linkage specs that
- aren't all naming the same language.
+Fri Apr 17 09:10:52 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
- * class.c (finish_struct): Delete accidental duplicate code.
+ * Make-lang.in (c++.all.build): Don't depend on $(DEMANGLER_PROG),
+ which requires a working target compiler to build.
-Tue Mar 21 14:00:57 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Fri Apr 17 08:57:35 1998 Jeffrey A Law (law@cygnus.com)
- * typeck.c (build_binary_op_nodefault): Disable pedwarns about
- comparing functions and incomplete types.
+ * tree.c (avoid_overlap): Add prototype.
- * decl.c (finish_function): Only unset current_function_decl if
- !nested.
- (duplicate_decls): Last change went too far; we only want to stop
- checking for value/reference ambiguity.
+ * spew.c (num_tokens): Add prototype.
+ (nth_noken, add_token, consume_token, debug_yychar): Likewise.
-Tue Mar 21 01:26:39 1995 Mike Stump <mrs@cygnus.com>
+ * search.c (dfs_check_overlap): Add prototype.
+ (dfs_no_overlap_yet): Likewise.
- * gc.c (build_generic_desc): Zap the DECL_SIZE so that we can lay it
- out fresh, as the new type may be larger.
+ * pt.c (original_template): Add prototype.
+ (inline_needs_template_parms): Likewise.
+ (push_inline_template_parms_recursive): Likewise.
+ (retrieve_specialization, register_specialization): Likewise.
+ (print_candidates, reduce_template_parm_level): Likewise.
+ (build_template_decl, mark_template_parm): Likewise.
+ (tsubst_friend_function, get_bindings_real): Likewise.
-Mon Mar 20 19:01:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * method.c (start_squangling): Add prototype.
+ (end_squangling, check_ktype, issue_ktype): Likewise.
+ (build_overloaded_scope_ref, check_btype): Likewise.
+ (build_mangled_template_parm_index): Likewise.
- * expr.c (extract_init): Try to expand the RTL for the
- initialization and figure out what it will look like so we can avoid
- run-time initialization. Disabled for now.
- (extract_scalar_init): Helper for scalar initialization.
- (extract_aggr_init): Helper for aggregate initialization.
+ * lex.c (init_cpp_parse): Add prototype.
+ (handle_cp_pragma, handle_sysv_pragma): Likewise.
+ (reduce_cmp, token_cmp): Likewise.
- * decl.c (duplicate_decls): Don't complain about ambiguous
- declarations.
- (obscure_complex_init): Now returns a tree. Call extract_init if
- we're optimizing and this is a toplevel decl.
- (finish_decl): Update accordingly.
+ * except.c (call_eh_info): Add prototype.
+ (push_eh_info, get_eh_info, get_eh_value, get_eh_type): Likewise.
+ (get_eh_caught, get_eh_handlers, do_pop_exception): Likewise.
- * lex.c (check_newline): If we're just changing files (not pushing
- or popping), update input_file_stack->name.
+ * decl2.c (is_namespace_ancestor): Add prototype.
+ (namespace_ancestor, add_using_namespace): Likewise.
+ (ambiguous_decl): Likewise.
-Mon Mar 20 17:55:04 1995 Mike Stump <mrs@cygnus.com>
+ * decl.c (indent): Add prototype.
- * pt.c (type_unification): Only TEMPLATE_DECLs are handled right now
- in the transitive unification code.
+ * call.c (add_template_candidate_real): Add prototype.
-Mon Mar 20 16:07:50 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Fri Apr 17 01:57:12 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (shadow_tag): Don't allow inline, virtual, or explicit on
- non-functions.
- (grokdeclarator): Don't allow friends to be defined in local classes.
+ * decl2.c (build_expr_from_tree): Just return a PMF.
-Sat Mar 18 04:03:33 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Fri Apr 17 00:45:12 1998 Mark Mitchell <mmitchell@usa.net>
- * decl2.c (finish_prevtable_vardecl): Use DECL_DECLARED_STATIC
- rather than DECL_SAVED_INSNS to decide whether or not this method
- was declared inline.
+ * typeck2.c (process_init_constructor): Don't strip cv-qualifiers
+ when doing initializations.
- * method.c (synthesize_method): Turn off DECL_INLINE if
- function_cannot_inline_p thinks we're too large.
+ * pt.c (unify): Use comptypes to compare type args.
- * typeck.c (build_indirect_ref): Use build_expr_type_conversion.
+Fri Apr 17 00:24:22 1998 Jason Merrill <jason@yorick.cygnus.com>
-Fri Mar 17 17:47:36 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (duplicate_decls): Fix check for when it's safe to free
+ the new decl.
- * class.c (instantiate_type): Handle pmfs.
+ * pt.c (mangle_class_name_for_template): Don't pass a typedef type
+ to type_as_string.
- * typeck.c (convert_for_assignment): Check types when assigning one
- pmf to another.
+Thu Apr 16 17:47:30 1998 Jeffrey A Law (law@cygnus.com)
- * decl.c (define_label): Fix logic for printing out the name of the
- label in an error message.
+ * pt.c (build_template_parm_index): Add prototype.
- * error.c (dump_expr): Support ARRAY_REF.
+ * search.c (my_tree_cons): Don't clear words outside the
+ newly allocated node.
-Fri Mar 17 17:43:02 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Wed Apr 15 15:34:44 1998 Dave Brolley <brolley@cygnus.com>
- * decl2.c (finish_vtable_vardecl): Call build_t_desc here.
- (finish_prevtable_vardecl): Instead of here.
+ * lex.c (init_parse): Now returns char* containing the filename.
-Fri Mar 17 14:40:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed Apr 15 13:20:06 1998 John Carr <jfc@mit.edu>
+ Jeff Law <law@cygnus.com>
- * decl.c (expand_static_init): Also use expand_aggr_init if the
- initializer is a TREE_LIST.
- (grokdeclarator): Only pedwarn about extra qualification if -pedantic.
+ * errfn.c: Rework to avoid problems when HOST_WIDE_INT is longer
+ than a pointer.
- * pt.c (unify): Fix unification of return type.
+Sun Apr 12 22:31:19 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
- * expr.c (fixup_result_decl): Use store_expr, rather than
- emit_move_insn, to move the return value into the place where
- callers will expect it.
+ * cvt.c (cp_convert_to_pointer): Use TYPE_PRECISION.
-Thu Mar 16 22:05:25 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Fri Apr 10 12:16:49 1998 Benjamin Kosnik <bkoz@loony.cygnus.com>
- * init.c (build_offset_ref): Call assmble_external on functions.
- * typeck.c (build_component_ref): Ditto.
+ * decl.c (duplicate_decls): Don't warn for redundant decls if
+ friend: let add_friend take care of it.
-Thu Mar 16 20:28:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Thu Apr 9 02:40:48 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (struct saved_scope): Add members base_init_list and
- member_init_list.
- (push_to_top_level): Save current_base_init_list and
- current_member_init_list to them.
- (pop_from_top_level): Put it back.
+ * sig.c (build_signature_pointer_constructor): Don't set
+ TREE_HAS_CONSTRUCTOR for a signature pointer.
+ * cvt.c (ocp_convert): Don't force a temporary for internal structs.
+ * init.c (resolve_offset_ref): Warn about implicit & on pmfs
+ here, too.
+ * typeck.c (build_unary_op): Only allow taking the address of a
+ real constructor.
+ * typeck2.c (digest_init): Simplify.
+ (store_init_value): Don't pedwarn about using { } for pmfs.
-Thu Mar 16 19:21:14 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Thu Apr 9 22:16:57 1998 Per Bothner <bothner@cygnus.com>
- * pt.c (instantiate_template): Call assemble_external.
+ * cp-tree.h (start_decl): Update prototype.
+ * decl.c (start_decl): Like the C version, new parameters
+ for the attributes. Call cplus_decl_attributes here,
+ (pushdecl): Like C version, do build_type_copy if TYPE_DECL,
+ (grokdeclarator): Pass NULL for new start_decl arguments.
+ * pt.c (tsubst_expr): Likewise.
+ * parse.y: Merge cplus_decl_attribute calls into start_decl calls.
+ * typeck.c (common_type): Check TYPE_MAIN_VARIANT.
+ * lex.c (build_lang_decl): Add lang_name_java.
+ * class.c (push_lang_context): Add lang_name_java.
+ * method.c (build_mangled_name): Check for is_java_type.
-Thu Mar 16 18:07:54 1995 Brendan Kehoe (brendan@phydeaux.cygnus.com)
+Thu Apr 9 22:16:57 1998 Benjamin Kosnik <bkoz@loony.cygnus.com>
- * class.c: Include rtl.h, to get NULL_RTX.
- (finish_struct): Also zero out DECL_SAVED_INSNS, to avoid problems
- on hosts with different sizes for each part of the union.
- * tree.c: Also include rtl.h.
- (layout_basetypes): Same change for DECL_SAVED_INSNS.
+ * decl.c (grokdeclarator): Check TYPE_MAIN_VARIANT.
+ * call.c (build_scoped_method_call): Check for TREE_CODE for
+ VOID_TYPE instead of type == void_type_node.
+ (build_method_call): Ditto.
+ * decl.c (lookup_name_real): Ditto.
+ (grokdeclarator): Ditto.
+ (start_decl): Ditto.
+ (grokparms): Ditto.
+ (start_function): Ditto.
+ (finish_function): Ditto.
+ (start_method): Ditto.
-Thu Mar 16 13:57:36 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Thu Apr 9 00:18:44 1998 Dave Brolley (brolley@cygnus.com)
- * pt.c (unify): Fix array domain unification for 64-bit targets.
+ * lex.c (finput): New variable.
+ (init_cpp_parse): Renamed from init_parse.
+ (init_parse): Handle !USE_CPPLIB. Call init_cpp_parse when finished.
+ (finish_parse): New function.
+ * cp-tree.h (init_lex, init_parse): Remove declarations.
- * decl2.c (finish_file): Push bizarre type decl before walking the
- vtables the first time.
- (walk_vtables): OK, don't set prev to vars if the vardecl_fn messed
- with TREE_CHAIN (prev).
+Mon Apr 6 02:25:05 1998 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (emit_base_init): Use convert_pointer_to_real instead of
- convert_pointer_to when converting to a direct base.
+ * call.c (build_call): Still evaluate the actual argument.
+ * class.c (is_empty_class): Update for -fnew-abi.
-Wed Mar 15 20:26:29 1995 Mike Stump <mrs@cygnus.com>
+ * decl2.c: -fnew-abi implies -fsquangle.
- * pt.c (type_unification): Handle transitive unification better.
+ * method.c (do_build_assign_ref): Don't do anything to copy
+ an empty class.
+ (do_build_copy_constructor): Likewise.
+ * call.c (build_over_call): Likewise.
-Wed Mar 15 13:56:16 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Sat Apr 4 18:43:58 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (walk_vtables): Always set prev to vars.
- (mark_vtable_entries): Call assemble_external on the vtable entries.
+ * tree.c (avoid_overlap): Return a value.
- * class.c (finish_struct): Set the vtable's size to NULL_TREE before
- calling layout_decl, so that it gets updated properly.
+Sat Apr 4 12:52:35 1998 Jeffrey A Law (law@cygnus.com)
- Finally re-enable dynamic synthesis. This time it works.
- * method.c (synthesize_method): Pass decl_function_context (fndecl)
- to {push,pop}_cp_function_context.
- * decl.c (push_cp_function_context): Now takes a tree argument.
- (pop_cp_function_context): Ditto.
- * call.c (build_method_call): Enable synthesis.
- * lex.c (cons_up_default_function): Ditto.
+ * method.c (check_btype): Add missing argument to xrealloc.
+ (check_ktype): Likewise.
-Tue Mar 14 19:14:19 1995 Doug Evans <dje@chestnut.cygnus.com>
+Fri Apr 3 02:22:59 1998 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (setattrs): Chain onto prefix_attributes rather than
- setting it.
+ Implement empty base optimization.
+ * class.c (finish_struct_1): Add vbase fields earlier. Set
+ CLASSTYPE_SIZE of an empty base to 0. Types with bases can be empty.
+ * search.c (dfs_check_overlap, dfs_no_overlap_yet): New fns.
+ (types_overlap_p): New fn.
+ * tree.c (avoid_overlap): New fn.
+ (build_base_fields): Use it to avoid overlapping empty bases.
+ * cp-tree.h, decl2.c, lang-options.h: Add -fnew-abi.
-Wed Mar 15 13:00:00 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl.c (cplus_expand_expr_stmt): Strip unused INDIRECT_REFs.
- * decl.c (pushdecl): Check if the type of the VAR_DECL is an
- error_mark_node before trying to read TYPE_LANG_SPECIFIC.
+ Re-implement allocation of base class subobjects.
+ * tree.c (unshare_base_binfos): New fn.
+ (layout_basetypes): Use it. Now handles offsets of both virtual and
+ non-virtual bases, after layout_type.
+ (layout_vbasetypes): Remove.
+ (build_base_fields): Generate FIELD_DECLs for each non-virtual base.
+ (build_vbase_pointer_fields): Split out from old layout_basetypes.
+ * class.c (finish_base_struct): Lose offset handling code.
+ Move nonvdtor warning here. Don't mess with t_binfo anymore.
+ (finish_struct_1): Don't mess with t_binfo anymore. Use fns above.
+ * cp-tree.h: Adjust.
-Mon Mar 13 21:00:28 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Thu Apr 2 14:25:13 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator, case ARRAY_REF): Wrap the exp with fold,
- and convert the size and integer_one_node to the index type.
+ * cp-tree.h: Lose CLASSTYPE_VBASE_SIZE, some unused stuff.
+ * decl.c, decl2.c, pt.c, ptree.c, lex.c: Likewise.
+ * class.c (duplicate_tag_error): Likewise.
+ (finish_struct_1): Set CLASSTYPE_SIZE, CLASSTYPE_MODE, CLASSTYPE_ALIGN.
+ * tree.c (layout_vbasetypes): Update from layout_record, remove
+ var_size support, use CLASSTYPE_SIZE instead of CLASSTYPE_VBASE_SIZE.
+ (layout_basetypes): Likewise.
-Mon Mar 13 08:01:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed Apr 1 18:22:25 1998 Jeffrey A Law (law@cygnus.com)
- * typeck.c (get_member_function_from_ptrfunc): Save the instance
- argument, and tack it onto the front of the COND_EXPR to make the
- semantics come out right. Grab the instance argument from
- '*instance_ptrptr', rather than having it passed in separately.
+ * class.c, Make sure system.h is included just after config.h.
+ Delete lingering stdio and errno references too.
+ * decl.c, errfn.c, parse.y, ptree.c search.c, xref.c: Likewise.
- * various: Change various consed-up comparison operations to have
- boolean type. Remove the instance argument in calls to
- get_member_function_from_ptrfunc.
-
- * error.c (dump_expr): Dump true and false as "true" and "false".
+Wed Apr 1 15:38:36 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (finish_file): Also set DECL_STATIC_FUNCTION_P on the
- global init function.
+ * friend.c (is_friend): Fix access control for local classes.
- * decl.c (finish_function): Only set DECL_EXTERNAL here if the
- inline function is public.
+ * class.c (is_empty_class): New fn.
+ * call.c (build_call): Don't pass empty class objects to a function.
-Sat Mar 11 00:58:03 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed Apr 1 14:58:35 1998 Mark Mitchell <mmitchell@usa.net>
- * init.c (is_friend): Be more careful about checking
- DECL_CLASS_CONTEXT on non-member functions.
+ * call.c (build_over_call): Do name resolution for default
+ arguments of function templates in the scope of the templates.
- * decl2.c (finish_vtable_vardecl): Don't bother calling
- assemble_external here.
- (prune_vtable_vardecl): New function that just splices out the
- vtable decl from the top-level decls.
- (import_export_inline): Unset DECL_EXTERNAL at first.
- (finish_file): Don't bother calling assemble_external here. Do
- splice out all of the vtables.
+Tue Mar 31 13:43:57 1998 Jeffrey A Law (law@cygnus.com)
-Fri Mar 10 14:42:29 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c: Include system.h. Remove includes, declarations and
+ defines provided by system.h.
+ * class.c, cvt.c, decl.c, decl2.c, errfn.c error.c: Likewise.
+ * except.c, expr.c friend.c, g++spec.c, init.c, input.c: Likewise.
+ * lex.c, parse.y, pt.c, ptree.c repo.c rtti.c, search.c: Likewise.
+ * semantics.c, sig.c, spew.c, tree.c, typeck.c: Likewise.
+ * typeck2.c, xref.c: Likewise.
+ * Makefile.in: Dependencies updated as appropriate.
+ * Make-lang.in: Likewise.
- * decl.c (finish_function): If we're not emitting the function yet,
- call assemble_external for it.
+Mon Mar 30 12:15:00 1998 Mark Mitchell <mmitchell@usa.net>
- * decl2.c (finish_prevtable_vardecl): Don't call mark_vtable_entries
- here.
- (finish_vtable_vardecl): Don't do the linkage deduction thing here.
- Also don't splice out the current vtable if it is unused.
- (finish_file): Move the second walk_vtables and the synthesis check
- inside the 'reconsider' loop. Move thunk emission after the
- 'reconsider' loop.
-
-Thu Mar 9 16:28:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * pt.c (tsubst): Don't bother calling cp_build_type_variant, since it
- was passing bogus values for readonly and volatile from the original
- template decl, not the resultant type of the tsubst call.
-
- * class.c (duplicate_tag_error): Use cp_error_at to point out the
- previous definition of the tag.
-
-Thu Mar 9 10:46:17 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (start_function): Clear base_init_insns and protect_list.
- (struct cp_function): Add base_init_insns field.
- (push_cp_function_context): Also save base_init_insns.
- (pop_cp_function_context): Also restore base_init_insns.
-
-Wed Mar 8 13:31:44 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * init.c (member_init_ok_or_else): Check for initializing a static
- member here.
- (emit_base_init): Instead of here.
-
-Tue Mar 7 16:03:26 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * call.c (build_method_call): Disable synthesis as needed.
- * lex.c (cons_up_default_function): Ditto.
-
-Tue Mar 7 10:14:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * parse.y: New rules to allow attributes in a prefix position.
- (prefix_attributes): New variable. Pass it into cplus_decl_attributes.
- (setattr): New rule.
- (reserved_declspecs, declmods): Catch attributes here.
- * decl2.c (cplus_decl_attributes): Add PREFIX_ATTRIBUTES argument.
- * decl.c (duplicate_decls): Pass DECL_MACHINE_ATTRIBUTES to
- descendent typedef.
- (grokdeclarator): Added code to support machine attributes.
- * Makefile.in (stamp-parse): Expect 5 shift/reduce failures.
-
-Mon Mar 6 15:07:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (fn_type_unification): Allow incomplete unification without
+ an immediate error message.
- * call.c (build_method_call): Don't synthesize methods outside of a
- function.
+Mon Mar 30 08:55:42 1998 Jason Merrill <jason@yorick.cygnus.com>
- Make base initialization more re-entrant so that synthesis on the
- fly will work (and, eventually, template instantation on the fly).
- * init.c (sort_member_init): Don't bother with members that can't be
- initialized. Reorganize a bit. Don't initialize base members here.
- (sort_base_init): New function, like sort_member_init, but for base
- classes. Steals some code from emit_base_init.
- (emit_base_init): Simplify. Call sort_{member,base}_init before
- doing any initialization, so we don't have to save
- current_{member,base}_init_list in push_cp_function_context.
- (expand_aggr_vbase_init_1): Adjust for sort_base_init.
- (expand_aggr_vbase_init): Simplify.
- * decl.c (struct cp_function): Add protect_list field.
- (push_cp_function_context): Also save protect_list.
- (pop_cp_function_context): Also restore protect_list.
- * call.c (build_method_call): Enable synthesis at point of call.
- * lex.c (cons_up_default_function): Ditto.
+ * tree.c (member_p): New fn.
+ * decl2.c (finish_file): Only set DECL_STATIC_FUNCTION_P for
+ initializing class members.
- * parse.y: Turn -ansi checks back into -pedantic checks.
+ * cp-tree.def (TEMPLATE_PARM_INDEX): Class 'x'.
+ * ptree.c (lang_print_xnode): Handle TEMPLATE_PARM_INDEX.
- * init.c (build_new): Fix -fcheck-new for array new.
+ * call.c (build_method_call): Handle non-scoped destructors, too.
+ * pt.c (tsubst_copy): Likewise.
-Sat Mar 4 15:55:42 1995 Fergus Henderson <fjh@cs.mu.oz.au>
+ * pt.c (print_template_context): Split out...
+ (push_tinst_level): ...from here.
- * typeck.c (build_compound_expr): warn if left-hand operand of
- comma expression has no side-effects.
+ * friend.c (is_friend): Don't pass a type to decl_function_context.
-Fri Mar 3 15:16:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * typeck.c (convert_for_initialization): Always hand off
+ conversions to class type.
- * parse.y (primary): Change 'object qualified_id *' rules to 'object
- overqualified_id *'.
+Sun Mar 29 20:01:59 1998 Jason Merrill <jason@yorick.cygnus.com>
-Fri Mar 3 12:48:17 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * friend.c (is_friend): Local classes have the same access as the
+ enclosing function.
- * parse.y (unary_expr): Catch doing sizeof an overloaded function.
- Make the error look the same as the one we issue in c_sizeof.
+Sun Mar 29 00:47:32 1998 Jeffrey A Law (law@cygnus.com)
- * typeck.c (build_binary_op_nodefault): Give an error for trying
- to compare a pointer-to-member to `void *'.
+ * typeck.c (expand_target_expr): Delete dead function.
-Fri Mar 3 11:28:50 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (build_unary_op): Handle bool increment with smoke and
- mirrors here, rather than in expand_increment where it belongs,
- because Kenner doesn't agree with me.
-
-Fri Mar 3 00:08:10 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * decl.c (grokparms): Catch a PARM_DECL being used for a default
- argument as well.
-
-Thu Mar 2 20:05:54 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * init.c (build_new): Don't allow new on a function type.
-
- * parse.y (primary): Avoid a crash when seeing if the arg is of
- the same type as that given for the typespec in an explicit dtor call.
-
-Thu Mar 2 00:49:38 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (finish_function): Change test for calling
- mark_inline_for_output.
-
-Wed Mar 1 11:23:46 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (build_modify_expr): Complain if
- build_default_binary_type_conversion fails.
-
- * init.c (expand_default_init): Handle arguments of unknown type
- properly.
+ * search.c: Put various prototypes inside #ifdef MI_MATRIX.
- * cvt.c (build_expr_type_conversion): Only complain about ambiguity
- if 'complain'.
- * various: Pass 'complain'.
+ * repo.c (save_string): Delete dead function.
- * typeck.c (comptypes): Be more picky about comparing UPTs.
+ * method.c (thunk_printable_name): Delete dead function.
-Wed Mar 1 11:03:41 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * lex.c (yynextch): Delete dead function.
- * decl.c (grokdeclarator): If declarator is null, say that the
- type used has an incomplete type.
+ * expr.c (tree_extract_aggr_init): #if 0 out.
-Wed Mar 1 10:06:20 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * except.c (do_unwind): Delete dead function.
+ (easy_expand_asm): Likewise.
- * pt.c (instantiate_template): Copy the template arguments to the
- permanent_obstack. Also use simple_cst_equal to compare them when
- looking for a previous instantiation.
+ * cvt.c (build_conversion_type_1): Delete dead function.
- * tree.c (make_deep_copy): Support copying INTEGER_TYPEs (assuming
- they are array domain types).
+ * cp-tree.h (push_expression_obstack): Declare.
-Tue Feb 28 23:24:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (source_type): #if 0 out.
- * cp-tree.h: Define WANT_* constants for passing to
- build_expr_type_conversion.
- * cvt.c (build_expr_type_conversion): New function to build
- conversion to one of a group of suitable types.
- (build_default_binary_type_conversion): Use it.
- * decl2.c (grok_array_decl): Ditto.
- * typeck.c (build_unary_op): Ditto.
- (build_array_ref): Tidy up a bit.
- (build_binary_op): Ditto.
+ * class.c (alter_access): Remove unused label. Add braces
+ around empty else clause.
-Tue Feb 28 19:57:31 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * lex.c (yyprint): Fix argument to printf.
- * decl.c (grokdeclarator): Don't allow decl of an argument as `void'.
+Sat Mar 28 17:43:52 1998 Mark Mitchell <mmitchell@usa.net>
-Tue Feb 28 17:23:36 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (tsubst): Clear TREE_USED for new FUNCTION_DECLs.
- * parse.y (typed_declspecs1): Add 'typespec reserved_typespecquals
- reserved_declspecs' rule.
+ * pt.c (instantiate_class_template): Make sure template
+ arguments are permanent.
+ * init.c (resolve_offset_ref): Don't go looking around in
+ template types.
- * parse.y (expr_or_declarator): Remove notype_qualified_id rule.
- (direct_notype_declarator): Ditto.
- (complex_direct_notype_declarator): Add notype_qualified_id rule.
+ * semantics.c: Add routines to handle expressions, and some
+ declaration processing.
+ * parse.y: Use them.
+ (current_class_depth): Move declaration to cp-tree.h.
+ * parse.c: Regenerated.
+ * cp-tree.h: Use them.
+ (current_class_depth): Declare.
+ * pt.c (tsubst_copy): Use begin_stmt_expr and finish_stmt_expr.
- * lex.c (real_yylex): Handle :> digraph properly.
+Fri Mar 27 20:23:18 1998 Mark Mitchell <mmitchell@usa.net>
-Tue Feb 28 12:26:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * decl.c (grokdeclarator): Check if it's a friend, not if it's
- non-virtual, that's being initialized. Move the check up to
- before FRIENDP would get cleared. Catch an unnamed var/field
- being declared void. Say just `field' instead of `structure field'
- in the error message. Only go for the operator name if DECLARATOR
- is non-null.
-
-Tue Feb 28 00:08:01 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (start_function): Complain about abstract return type.
- (grokdeclarator): Complain about declaring constructors and
- destructors to be const or volatile. Complain about declaring
- destructors to be static.
-
- * pt.c (uses_template_parms): Handle pmfs.
-
- * decl.c (grokdeclarator): Don't call variable_size for array bounds
- that only depend on template constant parameters.
-
-Mon Feb 27 15:38:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * error.c (dump_decl): Only look to see if it's a vtable if we
- actually have a name to check out.
+ * error.c (dump_decl): Be a bit more explicit with template
+ type arguments, when verbose.
+
+Fri Mar 27 18:16:40 1998 Jason Merrill <jason@yorick.cygnus.com>
-Mon Feb 27 13:37:53 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * inc/exception: Reorder closing braces.
- * cvt.c (convert_to_aggr): Lose misleading shortcut.
+Fri Mar 27 13:22:18 1998 Mark Mitchell <mmitchell@usa.net>
-Sun Feb 26 17:27:32 1995 Doug Evans <dje@canuck.cygnus.com>
+ * pt.c (redeclare_class_template): New function.
+ * cp_tree.h (redeclare_class_template): Declare it.
+ * decl.c (xref_tag): Use it.
- * decl.c (set_nested_typename): Always set DECL_IGNORED_P,
- not just for dwarf.
+Thu Mar 26 11:16:30 1998 Jason Merrill <jason@yorick.cygnus.com>
-Sun Feb 26 00:10:18 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * call.c (build_over_call): Check IS_AGGR_TYPE, not
+ TYPE_LANG_SPECIFIC.
+ * typeck.c (convert_arguments): Likewise.
- * decl.c (grokdeclarator): Don't allow a static member to be
- declared `register'.
+ * decl.c (grokdeclarator): Remove const and volatile from type after
+ setting constp and volatilep.
- * init.c (make_friend_class): Move up to a pedwarn for the warning
- about a class declaring friends with itself.
+ * class.c (finish_struct_1): Don't warn about bool bitfield larger
+ than one bit.
- * decl.c (grokdeclarator): You can't do `volatile friend class foo'
- or `inline friend class foo'. Only try to make a friend out of
- TYPE if we didn't already reset it to integer_type_node.
+Thu Mar 26 10:25:52 1998 Mark Mitchell <mmitchell@usa.net>
-Sat Feb 25 22:32:03 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * pt.c (convert_nontype_argument): STRIP_NOPS where appropriate.
- * decl.c (grokdeclarator): Don't allow initialization of a
- non-virtual function.
+Thu Mar 26 10:24:05 1998 Mark Mitchell <mmitchell@usa.net>
- * decl.c (start_function): Do a pedwarn if we're changing `main'
- to have an int return type.
+ * call.c (build_object_call): Complain about ambiguous operator(),
+ rather that crashing.
+ (build_new_op): Likewise.
+ (build_op_delete_call): Likewise.
-Sat Feb 25 00:02:05 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Thu Mar 26 10:23:24 1998 Mark Mitchell <mmitchell@usa.net>
- * typeck.c (build_modify_expr): Handle simple assignment from
- TARGET_EXPRs by building up an RTL_EXPR to force expansion. Whew.
+ * cvt.c (perform_qualification_conversions): Use comp_target_types
+ instead of comp_ptr_ttypes.
-Fri Feb 24 18:27:14 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Wed Mar 25 16:10:50 1998 Mark Mitchell <mmitchell@usa.net>
- * decl.c (grokdeclarator): Also don't allow virtual outside of a
- class decl for a scope method definition performed at global binding.
+ * cp-tree.h (enforce_access): Declare.
+ * call.c (enforce_access): Make it extern, not static.
+ * class.c (alter_access): Use enforce_access; modify code for ISO
+ compliance, rather than ARM rules.
- * init.c (build_offset_ref): Don't allow creation of an OFFSET_REF
- of a bitfield.
+Wed Mar 25 12:10:45 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
- * decl.c (grokdeclarator): Don't allow a const to be declared mutable.
+ * cp-tree.h: Fix typo.
- * typeck.c (build_binary_op): Return an error_mark_node if either
- one of the args turned into an error_mark_node when we tried to
- use default_conversion.
+Wed Mar 25 02:01:02 1998 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_unary_op): Forbid using postfix -- on a bool.
+ * expr.c (cplus_expand_expr): Only do PCC_STATIC_STRUCT_RETURN thing
+ if (aggregate_value_p (type)).
- * decl.c (grokdeclarator): Allow `signed' and `unsigned' to be
- used on `__wchar_t'.
+ * decl2.c (constructor_name_full): Handle TYPENAME_TYPE.
-Fri Feb 24 13:59:53 1995 Mike Stump <mrs@cygnus.com>
+Tue Mar 24 16:12:01 1998 Mark Mitchell <mmitchell@usa.net>
- * except.c (end_protect_partials): Do it the right way.
+ * tree.c (mapcar): When dealing with a DECL, use it's constant
+ value, if any.
+ * pt.c (lookup_template_class): Don't mangle the names of template
+ classes whose arguments are unknown.
-Wed Feb 22 15:42:56 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (tsubst_expr): Handle GOTO_STMT correctly.
- * typeck.c (build_binary_op_nodefault): Upgrade warning about
- comparing distinct pointer types to pedwarn.
+Tue Mar 24 12:21:55 1998 Benjamin Kosnik <bkoz@lisa.cygnus.com>
- * typeck2.c (digest_init): Cope with extra braces.
+ * decl.c (init_decl_processing): Set TYPE_PRECISON for bools to 1.
- * typeck.c (build_binary_op_nodefault): Use tree_int_cst_sgn instead
- of INT_CST_LT (..., interger_zero_node).
+Tue Mar 24 12:21:48 1998 Jim Wilson <wilson@cygnus.com>
-Wed Feb 22 14:45:52 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl.c (init_decl_processing): Initialize TYPE_MAX_VALUE for
+ boolean_type_node to 1.
- * except.c [!TRY_NEW_EH] (end_protect_partials): Define dummy
- function for systems that don't have EH.
+Tue Mar 24 10:23:47 1998 Mark Mitchell <mmitchell@usa.net>
-Tue Feb 21 19:18:31 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * error.c (dump_expr): Remove unused variable `l'.
- * call.c (can_convert_arg): Like can_convert, but takes an arg as
- well.
+ * pt.c (for_each_template_parm): New function, created by
+ converting uses_template_parms.
+ (tree_fn_t): New typedef.
+ (uses_template_parms): Use it.
+ (mark_template_parm): New function.
+ (push_template_decl): Check that the argument list of a partial
+ specialization uses all the template parameters.
- * pt.c (type_unification): Allow implicit conversions for parameters
- that do not depend on template parameters.
+ * Make-lang.in (c++filt): Don't delete cxxmain.c after we're done
+ with it; we might want it for debugging.
+ * cp-tree.h (type_unification): Change interface.
+ * class.c (finish_struct_1): Skip nested template types, just like
+ ordinary nested types.
+ (instantiate_type): Use new interface to type_unification.
+ * lex.c (init_lex): Add __sz as opname for sizeof.
+ * method.c (build_overload_scope_ref): New function.
+ (build_overload_int): Handle complex expressions. Set
+ numeric_output_need_bar if necessary.
+ (build_overload_value): Handle non-PARM_DECL nodes; this
+ routine is now used by build_overload_int. Remove some
+ assignments to numeric_output_need_bar. Use
+ build_overload_scope_ref.
+ (build_qualified_name): Note that some template mangled names end
+ with digits, and set numeric_output_need_bar appropriately. Use
+ build_underscore_int.
+ * pt.c (unify): Change interface.
+ (type_unification_real): Likewise.
+ (determine_specialization): Use new interfaces.
+ (tsubst): Deal gracefully with situations in which the argument
+ vector is not fully filled.
+ (fn_type_unification): Use new interfaces.
+ (type_unification): Likewise. Remove NOP_EXPR hack.
+ (type_unification_real): Likewise.
+ (unify): Likewise. Deal with unification of complex expresions.
-Tue Feb 21 18:43:48 1995 Douglas Rupp (drupp@cs.washington.edu)
+Mon Mar 23 12:24:37 1998 Jason Merrill <jason@yorick.cygnus.com>
- * Make-lang.in, config-lang.in: ($exeext): New macro.
- * Make-lang.in: Try a "cp" if "ln" fails.
- * cp-tree.h (decl_attributes): Added argument.
- * decl2.c (cplus_decl_attribute): Add arg to decl_attributes.
- * cp/g++.c: Added #ifdefs for sys/file.h and process.h for NT.
- Modified spawnvp to have to correct number of arguments for OS/2, NT.
+ * pt.c (complete_template_args): Initialize skip properly.
-Tue Feb 21 18:36:55 1995 Mike Stump <mrs@cygnus.com>
+ * decl.c (make_typename_type): Revert.
+ (make_implicit_typename): Remove.
+ (lookup_name_real): Don't call it. Call lookup_field if we see a
+ TYPE_DECL from a template base.
+ * search.c (lookup_field): Do implicit typename stuff.
- * decl.c (finish_function): Add calls to end_protect_partials to end
- the exception region that protects constructors so that partially
- constructed objects can be partially destructed when the constructor
- throws an exception.
- * init.c (perform_member_init, sort_member_init, emit_base_init):
- Added support for partially constructed objects.
- * init.c (build_partial_cleanup_for): New routine to do partial
- cleanups of a base class.
- * decl2.c (finish_file): Move the emitting of the exception table
- down, after we emit all code that might have exception regions in
- them.
- * except.c (end_protect_partials, might_have_exceptions_p): New
- routines.
- (emit_exception_table): Always output table if called.
- * cp-tree.h (protect_list, end_protect_partials,
- might_have_exceptions_p, emit_exception_table): Added.
+Sun Mar 22 00:50:42 1998 Nick Clifton <nickc@cygnus.com>
+ Geoff Noer <noer@cygnus.com>
-Tue Feb 21 16:05:59 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * Makefile.in: Various fixes for building cygwin32 native toolchains.
+ * Make-lang.in: Likewise.
- * gc.c (build_typeid): Pass a NULL_TREE, not the bogus, unused
- address of a local variable.
- * class.c (build_vfn_ref): Only try to build the PLUS_EXPR if we
- were given a non-null PTR_TO_INSTPTR.
+Fri Mar 20 18:07:39 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
-Tue Feb 21 01:53:18 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (tsubst, TEMPLATE_TEMPLATE_PARM): Simplify.
- * decl.c (duplicate_decls): Always lay out the merged decl.
+Fri Mar 20 10:42:07 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (finish_vtable_vardecl): Don't do vtable hack on templates.
- (finish_prevtable_vardecl): Ditto.
+ * decl.c (make_implicit_typename): Rewrite removed code.
+ (make_typename_type): Call it if the type we look up comes from
+ a base that uses template parms.
- * method.c (synthesize_method): Set interface_{unknown,only}
- according to the settings for our class, not the file where it comes
- from.
+ * pt.c (complete_template_args): Rewrite.
+ (tsubst, FUNCTION_DECL): Use it.
-Sat Feb 18 12:26:48 1995 Mike Stump <mrs@cygnus.com>
+Fri Mar 20 08:12:43 1998 H.J. Lu (hjl@gnu.org)
- * except.c: Handle systems that define __i386__ but not __i386.
+ * semantics.c (finish_asm_stmt): Fix combine strings. Call
+ c_expand_asm_operands () if output_operands, input_operands or
+ clobbers is not NULL_TREE.
-Fri Feb 17 15:31:31 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Fri Mar 20 00:10:19 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
- * decl2.c (reparse_decl_as_expr): Support being called without a
- type argument.
+ * pt.c (complete_template_args): New function.
+ (get_bindings): Deal with specializations of function templates
+ with return type containing parameters from outer class
+ templates.
+ (tsubst, TEMPLATE_TEMPLATE_PARM): When reducing parameter level,
+ substitute arguments and compose a new type.
- * parse.y (primary): Add '(' expr_or_declarator ')'. Adds 4 r/r
- conflicts. Sigh.
+Thu Mar 19 19:01:48 1998 Mark Mitchell <mmitchell@usa.net>
-Fri Feb 17 12:02:06 1995 Mike Stump <mrs@cygnus.com>
+ * pt.c (tsubst): Clear DECL_PENDING_INLINE_INFO for new
+ FUNCTION_DECLs.
- * parse.y (template_def, fndef, fn.def1, return_init, condition,
- initdcl0, initdcl, notype_initdcl0, nomods_initdcl0,
- component_decl_1, after_type_component_declarator0,
- notype_component_declarator0, after_type_component_declarator,
- notype_component_declarator, after_type_component_declarator,
- full_parm, maybe_raises, exception_specification_opt): Fix up,
- include exception_specification_opt maybeasm maybe_attribute and
- maybe_init if missing. Rename maybe_raises to
- exception_specification_opt to match draft wording. Use maybe_init
- to simplify rules.
+Thu Mar 19 11:51:58 1998 Jason Merrill <jason@yorick.cygnus.com>
-Fri Feb 17 01:54:46 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (make_implicit_typename): Lose useless code.
- * init.c (build_new): Set TREE_NO_UNUSED_WARNING on COMPOUND_EXPRs
- built for news of scalar types.
+ * call.c (standard_conversion): Handle A* -> const A* properly.
-Thu Feb 16 17:48:28 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (get_bindings_real): Rename from get_bindings. Add
+ check_rettype parm.
+ (get_bindings): Pass 1.
+ (get_bindings_overload): Pass 0.
- * typeck.c (build_binary_op_nodefault): Update code for warning
- about signed/unsigned comparisons from C frontend. Realize that the
- code in the C frontend is, if anything, even more bogus. Fix it.
- (build_binary_op): Undo default_conversion if it wasn't useful.
+Wed Mar 19 09:08:12 1998 Mark Mitchell <mmitchell@usa.net>
- * typeck.c (build_unary_op, ADDR_EXPR): Lose bogus special case for
- PRE*CREMENT_EXPR.
+ * pt.c (check_explicit_specialization): When reverting a static
+ member function, also remove the `this' parameter from
+ last_function_parms.
- * decl2.c (import_export_vtable): Don't try the vtable hack
- if the class doesn't have any real non-inline virtual functions.
- (finish_vtable_vardecl): Don't bother trying to find a non-inline
- virtual function in a non-polymorphic class.
- (finish_prevtable_vardecl): Ditto.
+Thu Mar 19 02:27:48 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (import_export_vtable): Use and set DECL_INTERFACE_KNOWN.
+ * pt.c (tsubst_copy, CONST_DECL): Don't bother tsubsting
+ a function context.
- * cp-tree.h (DECL_INTERFACE_KNOWN): Use DECL_LANG_FLAG_5.
+ * decl.c (store_bindings): Use free_binding_vecs.
+ (pop_from_top_level): Likewise.
- * init.c (expand_virtual_init): Always call assemble_external.
+Wed Mar 18 12:41:43 1998 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (build_vfn_ref): Always call assemble_external.
- (build_vtable): Always call import_export_vtable.
- (prepare_fresh_vtable): Ditto.
- (add_virtual_function): Don't bother setting TREE_ADDRESSABLE.
+ * decl.c (make_implicit_typename): Only change the type of a
+ TYPENAME_TYPE.
-Thu Feb 16 03:28:49 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed Mar 18 10:09:51 1998 Mark Mitchell <mmitchell@usa.net>
- * class.c (finish_struct): Use TYPE_{MIN,MAX}_VALUE to determine
- whether an enumerated type fits in a bitfield.
+ * semantics.c: New file, containing routines to perform the
+ semantic phase of parsing.
+ * parse.y: Use it.
+ * pt.c (tsubst_expr): Likewise.
+ * cp-tree.h: Declare the various functions in semantics.c.
+ Provide macros to access _STMT tree nodes.
+ * cp-tree.def: Add ASM_STMT tree node.
+ * Makefile.in, Make-lang.in: Add dependencies on and for
+ semantics.c.
+
+Wed Mar 18 00:24:10 1998 Jason Merrill <jason@yorick.cygnus.com>
-Wed Feb 15 15:38:12 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (push_template_decl): Only check primary templates.
- * class.c (grow_method): Update method_vec after growing the class
- obstack.
+ * pt.c (check_explicit_specialization): Complain about default args
+ in explicit specialization.
-Wed Feb 15 13:42:59 1995 Mike Stump <mrs@cygnus.com>
+ * parse.y (nomods_initdcl0): Also call cp_finish_decl for a
+ constructor_declarator.
- * parse.y (handler_seq): Push a level for the catch parameters.
+Tue Mar 17 14:44:54 1998 Mark Mitchell <mmitchell@usa.net>
-Wed Feb 15 12:42:57 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * typeck2.c (build_x_arrow): Don't crash when an aggregate type
+ has no overloaded operator ->.
- * init.c (emit_base_init): Update BINFO_INHERITANCE_CHAIN on my
- bases, in case they've been clobbered.
+ * call.c (build_field_call): Don't crash when presented with a
+ field that is actually a nested type.
-Wed Feb 15 12:07:29 1995 Mike Stump <mrs@cygnus.com>
+ * decl.c (pushtag): Deal with friend class injection in local
+ classes.
- * class.c (finish_base_struct): Set up BINFO_INHERITANCE_CHAIN here,
- so that one day it will always be valid.
- * tree.c (propagate_binfo_offsets, layout_vbasetypes): Ditto.
+ * call.c (build_object_call): Don't crash if OBJ is a
+ pointer-to-member-function.
- * cp-tree.h (copy_binfo): Removed, unused.
- * tree.c (copy_binfo): Ditto.
+Tue Mar 17 11:40:26 1998 Jason Merrill <jason@yorick.cygnus.com>
-Wed Feb 15 00:05:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (push_template_decl): Complain about template with C linkage,
+ anonymous template class.
- * init.c (build_new): Save the allocation before calling
- expand_vec_init on it.
+Mon Mar 16 12:10:39 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (finish_enum): The TYPE_PRECISION of the enum type mush
- match the TYPE_PRECISION of the underlying type for constant folding
- to work.
+ * class.c (pushclass): Only use the mi_matrix stuff #ifdef MI_MATRIX.
+ * search.c: Likewise.
-Tue Feb 14 15:31:25 1995 Mike Stump <mrs@cygnus.com>
+ * lex.c (do_pending_defargs): Only call
+ maybe_{begin,end}_member_template_processing for FUNCTION_DECLs.
- * except.c (push_eh_entry, expand_start_all_catch,
- expand_leftover_cleanups, expand_end_catch_block): Keep track of
- the context in which the exception region occurs.
- (build_exception_table): If the region was not output, don't output
- the entry in the eh table for it.
+ * parse.y (initdcl0_innards): Move maybeasm back into initdcl0 et al.
-Tue Feb 14 02:15:43 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Mon Mar 16 10:47:22 1998 Mark Mitchell <mmitchell@usa.net>
- * init.c (expand_default_init): Only use a previous constructor call
- if it's a call to our constructor. Does the word "Duh" mean
- anything to you?
+ * parse.y: Deal with CONSTRUCTORS in new_initializers.
- * decl.c (grokparms): Fine, just don't call
- convert_for_initialization at all. OK? Happy now?
+Mon Mar 16 10:54:21 1998 Mark Mitchell <mmitchell@usa.net>
-Mon Feb 13 02:23:44 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (tsubst_copy): Deal with BIND_EXPR in a way that more
+ closely mimics the behavior in parse.y.
+ (tsubst_expr): Return the resuting BLOCK when making a tsubst'ing
+ into a compound statement.
+
+Sun Mar 15 02:07:26 1998 Jason Merrill <jason@yorick.cygnus.com>
- * cp-tree.h (CLASSTYPE_FIRST_CONVERSION): Make sure that the class
- method vector has a second element before returning it.
+ * cp-tree.h (TEMPLATE_PARMS_FOR_INLINE): New macro.
+ * pt.c (inline_needs_template_parms): New fn.
+ (original_template): New fn.
+ (push_inline_template_parms_recursive): New fn.
+ (maybe_begin_member_template_processing): Use them.
+ (maybe_end_member_template_processing): Likewise.
+ (is_member_or_friend_template): Rename to is_member_template.
+ Member functions of local classes are never member templates.
- * decl.c (grokparms): Don't strip REFERENCE_TYPE before calling
- convert_for_initialization.
+Sun Mar 15 01:14:22 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
-Sun Feb 12 03:57:06 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * lex.c (do_identifier): Handle TEMPLATE_DECL that was
+ added in the class scope to catch redefinition error.
- * typeck.c (build_modify_expr): Compare function name to
- constructor_name (current_class_type) instead of current_class_name.
+ * pt.c (reduce_template_parm_level): Also copy
+ the DECL_TEMPLATE_PARMS field.
- * decl.c (grokparms): Don't do anything with the return value of
- convert_for_initialization.
+Sun Mar 15 10:54:08 1998 Mark Mitchell <mmitchell@usa.net>
- * error.c (dump_decl): Also dump_readonly_or_volatile on the decl.
+ * pt.c (tsubst): Clear TYPE_REFERENCE_TO when creating a
+ reduced-level template type parameter.
- * decl.c (duplicate_decls): Tweak error message.
+Sun Mar 15 12:26:02 1998 Manfred Hollstein <manfred@s-direktnet.de>
- * typeck.c (build_const_cast): Implement checking.
- (build_reinterpret_cast): Implement some checking.
+ * cp-tree.h (struct lang_decl_flags): Add needs_final_overrider.
+ (DECL_NEEDS_FINAL_OVERRIDER_P): New macro.
+ * class.c (override_one_vtable): Set DECL_NEEDS_FINAL_OVERRIDER_P.
+ * decl.c (duplicate_decls): Propagate it.
+ * typeck2.c (abstract_virtuals_error): Use two loops to emit
+ abstract virtual functions and virtual functions which need a
+ final overrider separately.
+
+Thu Mar 12 09:39:40 1998 Manfred Hollstein <manfred@s-direktnet.de>
- * cp-tree.h (CONV_FORCE_TEMP): Require a new temporary when
- converting to the same aggregate type.
- (CONV_STATIC_CAST): Include it.
- (CONV_C_CAST): Ditto.
- * cvt.c (convert_force): Use CONV_C_CAST instead of CONV_OLD_CONVERT.
- (cp_convert): Only force a new temporary if CONV_FORCE_TEMP.
+ * lang-specs.h: Properly put brackets around array elements in
+ initializer.
-Fri Feb 10 16:18:52 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * typeck.c (build_binary_op_nodefault): Correctly place parens around
+ && and || in expression.
- * typeck.c (build_c_cast): Use non_lvalue to tack something on
- where necessary.
+Thu Mar 12 09:26:04 1998 Manfred Hollstein <manfred@s-direktnet.de>
- * decl.c (auto_function): Now a function.
- * except.c (init_exception_processing): terminate, unexpected,
- set_terminate, and set_unexpected have C++ linkage.
+ * call.c (default_parm_conversions): Remove prototype definition.
+ (build_method_call): Remove unused variable result.
- * typeck.c (build_unary_op, TRUTH_NOT_EXPR): Use convert instead of
- truthvalue_conversion for converting to bool, as it handles
- user-defined conversions properly.
- (condition_conversion): Ditto.
+ * cvt.c (ocp_convert): Remove unused variable conversion.
- * except.c (expand_throw): Don't call convert_to_reference.
- Pass the correct parameters to build_new.
+ * decl2.c (ambiguous_decl): Add explicit parameter definition for name.
- * method.c (do_build_assign_ref): Don't use access control when
- converting to a base reference here.
- (do_build_copy_constructor): Or here.
+ * except.c (do_unwind): #if 0 definition of unused variables fcall
+ and next_pc.
- * init.c (build_new): Unset TREE_READONLY on the dereferenced
- pointer before assigning to it.
+ * expr.c (extract_scalar_init): #if 0 prototype and function
+ definition.
- * decl.c (maybe_build_cleanup): Don't bother stripping const here.
+ * init.c (expand_aggr_init_1): Remove unused variable init_type.
+ (build_new_1): Remove unused variable t.
- * decl2.c (delete_sanity): You can now delete pointer to const.
+ * pt.c (instantiate_class_template): Remove unused variable newtag;
+ cast called function return value to void.
+ (do_decl_instantiation): Remove unused variables name and fn.
-Fri Feb 10 13:28:38 1995 Jason Merrill <jason@python.cygnus.com>
+ * tree.c (get_type_decl): Add default return to shut up compiler from
+ complaining control reaches end of non-void function.
- * decl.c (finish_function): Don't rely on actual parameters being
- evaluated left-to-right.
- * except.c (expand_end_catch_block): Ditto.
+ * typeck.c (build_x_conditional_expr): Remove unused variable rval.
-Fri Feb 10 00:52:04 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Thu Mar 12 09:12:15 1998 Manfred Hollstein <manfred@s-direktnet.de>
- * 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.
+ * call.c (default_parm_conversions): Remove prototype definition.
+ (build_method_call): Remove unused variable result.
+ (build_over_call): Add default case in enumeration switch.
- * cvt.c (build_type_conversion_1): Don't call convert on aggregate
- types.
- (convert_to_reference): Fix erroneous text substitution.
+Thu Mar 12 08:39:13 1998 Manfred Hollstein <manfred@s-direktnet.de>
- * typeck2.c (initializer_constant_valid_p): Update from C frontend.
- Add new argument to all callers.
+ * decl2.c (lang_decode_option): Change j's type to size_t.
- * typeck.c (convert_arguments): Check for error_mark_node before
- trying to do anything with the actual parameter.
+ * tree.c (layout_vbasetypes): record_align and desired_align are of
+ type unsigned int; const_size and nonvirtual_const_size likewise.
- * typeck.c (condition_conversion): Build up a CLEANUP_POINT_EXPR and
- fold it.
- (bool_truthvalue_conversion): Remove. Fix all callers to call
- truthvalue_conversion instead.
- (various): Fold CLEANUP_POINT_EXPRs.
+Wed Mar 11 07:25:20 1998 Mark Mitchell <mmitchell@usa.net>
- * parse.y (conditions): Call condition_conversion rather than
- building up a CLEANUP_POINT_EXPR.
+ * parse.y (new_initializer): Make sure all initializers are
+ lists.
- * pt.c (end_template_decl): Don't warn_if_unknown_interface here
- under -falt-external-templates.
+Tue Mar 10 07:32:36 1998 Mark Mitchell <mmitchell@usa.net>
-Thu Feb 9 05:24:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (import_export_decl): Mark tinfo functions for
+ cv-qualified versions of class types as DECL_NOT_REALLY_EXTERN.
- * init.c (build_new): Complain about new of const type without
- initializer. Other cleanup.
+Fri Mar 6 23:27:35 1998 Jeffrey A Law (law@cygnus.com)
- * call.c (compute_conversion_costs): Don't call
- build_type_conversion with a reference type; convert to the target
- type and check its lvaluetude.
- * cvt.c (convert_to_reference): Ditto.
+ * method.c: Fix typo.
- * cvt.c (build_type_conversion_1): There will never be any need to
- dereference references here now.
+Fri Mar 6 10:06:59 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Thu Feb 9 00:37:47 1995 Mike Stump <mrs@cygnus.com>
+ * method.c: Include "system.h" to get stdlib.h, stdio.h,
+ ctype.h, string.h, etc.
+ (issue_nrepeats): Add default case in enumeration switch.
+ (check_btype): Likewise.
+ (process_overload_item): Likewise.
+
+ * Makefile.in (method.o): Depend on system.h.
- * except.c (expand_builtin_throw): Make sure we only `use' the
- value of return_val_rtx.
+Wed Mar 4 22:26:53 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
-Wed Feb 8 15:45:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * lex.c (do_scoped_id): Fix parenthesizing.
- * parse.y (structsp): Don't complain about declaring a type being
- defined to be a friend.
+Wed Mar 4 12:11:53 1998 Michael Tiemann <tiemann@axon.cygnus.com>
- * decl2.c (warn_if_unknown_interface): Note the template in question
- and the point of instantiation, for -falt-external-templates.
- * lex.c (reinit_parse_for_method): Pass the decl to
- warn_if_unknown_interface.
- * pt.c (instantiate_template): Ditto.
- (end_template_decl): Ditto.
+ * rtti.c (get_tinfo_fn_dynamic): If this function is called an
+ FLAG_RTTI is unset, initialize type info machinery and continue
+ with FLAG_RTTI enabled.
+ (get_typeid): Ditto.
- * decl.c (set_nested_typename): Set IDENTIFIER_TYPE_VALUE on the
- nested name again, to make local classes work a bit better.
+Wed Mar 4 11:47:55 1998 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_function_call_real): Dereference reference after
- checking for incomplete type.
+ * typeck.c (unary_complex_lvalue): &D::i has type B::* if i comes
+ from B.
- * init.c (build_new): Accept new of const and volatile types.
+Wed Mar 4 11:28:08 1998 Mark Mitchell <mmitchell@usa.net>
-Wed Feb 8 14:04:16 1995 Jason Merrill <jason@deneb.cygnus.com>
+ * pt.c (finish_member_template_decl): Deal more gracefully with
+ invalid declarations.
- * decl.c (grokdeclarator): Fix error message.
+Tue Mar 3 01:38:17 1998 Jason Merrill <jason@yorick.cygnus.com>
-Wed Feb 8 03:16:15 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cvt.c, decl.c, decl2.c, init.c, rtti.c, typeck.c, typeck2.c,
+ cp-tree.h: Clean up more old overloading code, old RTTI code, and
+ some formatting quirks.
- * typeck.c (convert_for_initialization): Do bash arrays when
- converting to a reference to non-array.
+ * call.c, class.c, cp-tree.h, cvt.c, decl.c, init.c, lex.c,
+ method.c, pt.c, ptree.c, typeck.c: Remove support for
+ -fno-ansi-overloading and overloading METHOD_CALL_EXPR.
+ * class.h: Remove.
+ * Makefile.in: Adjust.
-Tue Feb 7 15:50:33 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (unify): Don't allow reduced cv-quals when strict.
- * cvt.c (cp_convert): Don't call convert_to_reference, or
- automatically dereference references. Do pass reference conversions
- to cp_convert_to_pointer.
- (cp_convert_to_pointer): Support references.
+ * call.c, class.c, pt.c, cp-tree.h: Remove nsubsts parm from
+ *type_unification* and unify.
- * call.c (build_method_call): Don't build up a reference to the
- parameter here; let build_overload_call handle that.
+Mon Mar 2 12:11:06 1998 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_c_cast): Call convert_to_reference directly if
- converting to a reference type.
- * method.c (do_build_copy_constructor): Ditto.
- * method.c (do_build_copy_constructor): Ditto.
- (do_build_assign_ref): Ditto.
+ * parse.y (explicit_template_type): Remove TEMPLATE keyword.
+ (nested_name_specifier): And add it before this use.
+ (typename_sub0): And this use. Also add use without the keyword.
+ (typename_sub1): Likewise.
+ * pt.c (instantiate_class_template): Don't actually instantiate
+ anything if our type uses template parms.
- * call.c (build_method_call): Dereference a returned reference.
- * typeck.c (build_function_call_real): Ditto.
+Mon Mar 2 11:04:59 1998 Jim Wilson <wilson@cygnus.com>
- * decl.c (xref_basetypes): Check for unions with basetypes here.
- (xref_tag): Instead of here.
+ * decl.c (start_function): Don't call temporary_allocation for a
+ nested function.
- * pt.c (process_template_parm): Template type parm decls are
- artificial.
+Sun Mar 1 21:06:37 1998 Jason Merrill <jason@yorick.cygnus.com>
-Mon Feb 6 04:32:09 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (instantiate_class_template): Don't mess with friends if
+ our type uses template parms.
- * parse.y (typed_declspecs): Add missing semicolon.
- (do_xref_defn): Resurrect.
- (named_class_head_sans_basetype): Move template specialization
- definition cases to named_class_head_sans_basetype_defn.
+Sat Feb 28 12:06:44 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (grokfield): Call pushdecl_class_level after setting the
- TYPE_NAME, not before.
+ * parse.y (nested_name_specifier): Use explicit_template_type.
+ (typename_sub): Allow a template_type, an explicit_template_type,
+ or an implicit template type at the end.
+ * lex.c (yyprint): Handle a PTYPENAME being a TEMPLATE_DECL.
+ * decl.c (make_typename_type): Handle template-id where the name
+ is a TEMPLATE_DECL.
+ * call.c (build_scoped_method_call): Handle member template
+ destructor call.
+ * pt.c (tsubst_copy, METHOD_CALL_EXPR): Don't assume a member
+ destructor is represented by the type.
-Sun Feb 5 02:50:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cp-tree.h (TYPENAME_TYPE_FULLNAME): New macro.
+ * parse.y (nested_name_specifier): Add 'template' case.
+ (explicit_template_type): New rule.
+ (typename_sub): Use it.
+ * decl.c (make_typename_type): Handle getting a template-id for NAME.
+ * pt.c (tsubst): Likewise.
- * call.c (convert_harshness): Don't call sorry here. Don't allow
- conversions between function pointer types if pedantic.
+Fri Feb 27 11:17:50 1998 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (overload_template_name): Pass globalize=1 to xref_tag.
+ * pt.c (add_to_template_args): Fix thinko.
+ (instantiate_class_template): Call it later.
- * lex.c (cons_up_default_function): Use the full name for the return
- type of op=.
+ * pt.c (get_class_bindings): Add outer_args parm.
+ (most_specialized_class): Likewise.
+ (instantiate_class_template): Pass it.
+ (more_specialized_class): Likewise.
+ (lookup_template_class): Get context from template if none
+ was specified.
+ (finish_member_template_decl): Don't do anything with a
+ partial specialization.
+ * decl2.c (check_member_template): Use IS_AGGR_TYPE instead of
+ AGGREGATE_TYPE_P.
+ * class.c (finish_struct): Member class templates have already been
+ checked for name clashes.
+ * decl.c (pushdecl_with_scope): Handle pushing at class level.
+
+Fri Feb 27 02:25:16 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst, TEMPLATE_DECL): Support member class templates.
+ (tsubst, *_PARM): Support multiple levels of template classes.
+ (instantiate_class_template): Look up the pattern from the
+ original template.
+ (lookup_template_class): Handle getting a template for d1.
+ (push_template_decl): Correct setting of 'primary'.
+ (reduce_template_parm_level): Add 'levels' parm.
+ (finish_member_template_decl): Support member class templates.
+ (template_class_depth): Handle multiple levels.
+ * parse.y (component_decl_1, fn.def2): Remove member template case.
+ (component_decl): Add member template cases.
+ * decl2.c (check_member_template): We now handle member template
+ classes.
+ * decl.c (pushtag): Handle member templates.
+ * method.c (do_inline_function_hair): Don't touch
+ IDENTIFIER_GLOBAL_VALUE.
+ * init.c (build_offset_ref): If name isn't an identifier, just
+ return it.
+ * spew.c (yylex): Handle PTYPENAME like TYPENAME.
+
+ * typeck.c (get_delta_difference): Do adjust for conversions to
+ and from virtual base.
+
+Wed Feb 25 09:51:29 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (get_delta_difference): Give hard error for conversion
+ from virtual base.
+
+ * cp-tree.h: Tweak formatting.
+
+Wed Feb 25 00:35:33 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (push_namespace): Handle redeclaration error.
+
+ * cp-tree.h (IDENTIFIER_NAMESPACE_VALUE): New macro.
+ (IDENTIFIER_NAMESPACE_BINDINGS): New macro.
+ (NAMESPACE_BINDING): New macro.
+ (IDENTIFIER_GLOBAL_VALUE): Use NAMESPACE_BINDING.
+ * *.c: Use them.
+
+ * pt.c (push_template_decl): Use innermost_args.
+
+ * decl.c (get_unique_name): Tweak from earlier in the name.
+
+Tue Feb 24 22:15:04 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+ * cp-tree.def: Add CPLUS_BINDING node.
+ * cp-tree.h (tree_binding): new struct
+ (BINDING_SCOPE, BINDING_VALUE): new macros
+ (current_namespace, global_namespace): declare extern
+ (struct lang_decl_flags): new field in_namespace
+ (DECL_NAMESPACE_USING, DECL_NAMESPACE_USERS): new macros
+ (DECL_NAMESPACE, SET_DECL_NAMESPACE): new macros
+ (TREE_INDIRECT_USING): new macro
+ * decl2.c (current_namespace, global_namespace): Declare. The
+ value is a NAMESPACE_DECL now, not a TREE_LIST.
+ (is_namespace_ancestor, namespace_ancestor):new static functions.
+ (add_using_namespace, ambiguous_decl): likewise.
+ (lookup_using_namespace): new support function for lookup_name.
+ (qualified_lookup_using_namespace): new support function for
+ do_scoped_id and lookup_namespace_name
+ (get_namespace_id): mark as obsolete.
+ (current_namespace_id): Likewise.
+ (do_namespace_alias): Implement.
+ (do_using_directive): Implement as call to add_using_namespace.
+ * decl.c (binding_for_name): new function.
+ (push_namespace, pop_namespace): implement.
+ (push_decl): don't install a FUNCTION_DECL in the global branch.
+ (lookup_namespace_name): implement using qualified lookup.
+ (lookup_name_real): For global scoping, lookup in
+ global_namespace. For namespace scoping, lookup in given
+ namespace. For unscoped lookup, iterate over namespace,
+ considering using directives.
+ (init_decl_processing): initialize global_namespace.
+ (grokvardecl): Build assembler name as static name for globals.
+ (grokdeclarator): Remove old namespace mangling.
+ (xref_tag): When installing a global binding for the
+ tag, make sure we have an identifier.
+ * method.c (build_overload_nested_name): mangle namespaces.
+ (build_qualified_name): Likewise.
+ (build_decl_overload_real): Likewise.
+ * lex.c (build_lang_decl): set namespace for new declaration to
+ current_namespace.
+ (do_scoped_id): find global names in global or current
+ namespace, or using qualified namespace lookup, depending on
+ context.
+ * init.c (build_member_call): When scope is namespace, use
+ build_x_function_call instead.
+ (build_offset_ref): When scope is namespace, collapse processing
+ to lookup_namespace_name instead.
+ * error.c (dump_decl): Support NAMESPACE_DECL.
+ * decl.c (pushdecl): Bind globals to current namespace.
+ (push_overloaded_decl): Likewise.
+ (lookup_tag): Likewise.
+ (lookup_name_current_level): Likewise.
+ (xref_tag): Likewise.
+ (start_function): Likewise.
+ * lex.c (do_identifier): Likewise.
+ (identifier_typedecl_value): Likewise.
+ (real_yylex): Likewise.
+ * method.c (do_inline_function_hair): Likewise.
+ * parse.y (unscoped): Likewise.
+ * pt.c (check_explicit_specialization): Likewise.
+ (lookup_template_class): Likewise.
+ * rtti.c (call_void_fn): Likewise.
+ * sig.c (build_sigtable): Likewise.
+ * ptree.c (lang_print_xnode): New function.
+
+Tue Feb 24 01:40:24 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (instantiate_class_template): Don't instantiate if pedantic
+ and the args use template parms.
+
+ * pt.c (push_tinst_level): If the instantiaton uses template parms,
+ fail silently.
+ * decl.c (xref_basetypes): Do call complete_type for basetypes
+ that involve template parameters.
+
+Tue Feb 24 00:36:43 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck2.c (process_init_constructor): Fix labeled init check.
+
+Mon Feb 23 05:08:55 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c, call.c, decl.c, method.c, cp-tree.h: Remove unused NARGS
+ argument to tsubst and friends.
+
+ * pt.c (tsubst, FUNCTION_DECL): Tidy.
+
+ * typeck.c (build_x_function_call): Handle static member function
+ templates like non-templates. Handle friend templates like normal
+ function templates.
+ * pt.c (tsubst, *_PARM): Don't use orig_level.
+ (get_bindings): Don't call add_to_template_args.
+ (instantiate_template): Likewise.
+ (tsubst, FUNCTION_DECL): Call add_to_template_args as appropriate.
+ * ptree.c (print_lang_type): Print index/level for template parms.
- * decl.c (set_nested_typename): Don't worry about anonymous types,
- as they already have a unique name.
- (pushdecl): Remove redundant set_nested_typename
- (xref_tag): Split out base handling into xref_basetypes.
+Mon Feb 23 02:52:29 1998 Mark Mitchell <mmitchell@usa.net>
- * cp-tree.h (TYPE_INCOMPLETE): New macro; TEMPLATE_TYPE_PARMs are
- not considered incomplete even though their definition is unknown.
+ * Make-lang.in (cc1plus): Note that cc1plus depends on
+ cp/cp-tree.h and cp/cp-tree.def.
+
+ * cp-tree.def (TEMPLATE_CONST_PARM): Remove.
+ (TEMPLATE_PARM_INDEX): New tree code, used to indicate a
+ position in a template parameter list.
+ * cp-tree.h (template_parm_index): New structure, used as the tree
+ structure for a TEMPLATE_PARM_INDEX.
+ (TEMPLATE_PARM_IDX): New macro.
+ (TEMPLATE_PARM_LEVEL): Likewise.
+ (TEMPLATE_PARM_DESCENDANTS): Likewise.
+ (TEMPLATE_PARM_ORIG_LEVEL): Likewise.
+ (TEMPLATE_PARM_DECL): Likewise.
+ (TEMPLATE_TYPE_PARM_INDEX): Likewise.
+ (TEMPLATE_TYPE_ORIG_LEVEL): Likewise.
+ (TEMPLATE_TYPE_DECL): Likewise.
+ (TEMPLATE_CONST_IDX): Remove.
+ (TEMPLATE_CONST_LEVEL): Likewise.
+ (TEMPLATE_CONST_SET_INFO): Likewise.
+ (TEMPLATE_TYPE_SET_INFO): Likewise.
+ (TEMPLATE_TYPE_IDX): Redefine in terms of TEMPLATE_PARM_INDEX
+ node.
+ (TEMPLATE_TYPE_LEVEL): Likewise.
+ * decl.c (decls_match): Call comp_template_parms, rather than
+ expanding it inline.
+ (duplicate_decls): If two template declarations are being merged,
+ then their TEMPLATE_INFOs should be merged as well.
+ (grokfndecl): Save template-id information when declaring a friend
+ with explicit template arguments. Pass arguments to
+ check_explicit_specialization via correct convention; at some
+ point check_explicit_specialization changed, but these call-sites
+ did not.
+ (grokdeclarator): Tidy up slightly.
+ * decl2.c (check_classfn): Tidy up slightly. Don't assume that
+ two template functions with the same DECL_ASSEMBLER_NAME the same,
+ since the names are not yet mangled.
+ * error.c (dump_decl): Use TEMPLATE_PARM_INDEX instead of
+ TEMPLATE_CONST_PARM.
+ (dump_expr): Likewise. Use the TEMPLATE_PARM_DECL to get at the
+ decl for a non-type parameter, rather than printing `<tparm ...>'.
+ * friend.c (is_friend): Handle TEMPLATE_DECL friends.
+ (do_friend): Deal with template friends.
+ * lex.c (do_pending_inlines): Call
+ maybe_begin_member_template_processing, rather than
+ conditionally calling begin_member_template_processing.
+ (process_next_inline): Likewise. Call
+ maybe_end_member_template_processing, rather than
+ conditionally calling end_member_template_processing.
+ (do_pending_defargs): Likewise.
+ (do_identifier): Use TEMPLATE_PARM_INDEX instead of
+ TEMPLATE_CONST_PARM.
+ * method.c (build_mangled_template_parm_index): New function.
+ (build_overload_value): Use it.
+ (build_overload_name): Likewise.
+ * pt.c (finish_member_template_decl): Allow friend declarations.
+ (template_class_depth): New function.
+ (is_member_template): Rename, and modify, to become...
+ (is_member_or_friend_template): New function.
+ (end_member_template_processing): Rename, and modify, to become...
+ (maybe_end_member_template_processing).
+ (build_template_parm_index): New function.
+ (reduce_template_parm_level): New function.
+ (process_template_parm): Modify to use build_template_parm_index.
+ (push_template_decl): Deal with friend templates.
+ (uses_template_parms): Use TEMPLATE_PARM_INDEX instead of
+ TEMPLATE_CONST_PARM.
+ (tsubst_friend_function): New function.
+ (instantiate_class_template): Generate the DECL_FRIENDLIST
+ for a new instantiation by using tsubst_friend_function rather
+ than just tsubst.
+ (tsubst): Don't tsubst into a type which is a TEMPLATE_DECL.
+ Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM, and the
+ appropriate new macros. Use reduce_template_parm_level to
+ generate lower-level template parameters. Handle tsubst'ing into
+ TEMPLATE_DECLS that declare TEMPLATE_TEMPLATE_PARMS. Don't forget
+ to tsubst the DECL_CONTEXT and DECL_CLASS_CONTEXT of newly created
+ templates. Similarly for the template parameters for a new
+ template.
+ (tsubst_copy): Tidy up slightly. Use TEMPLATE_PARM_INDEX instead
+ of TEMPLATE_CONST_PARM. Handle TYPE_DECLs by tsubsting into them.
+ (unify): Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM.
+ (get_bindings): Call add_to_template_args if necessary.
+ (instantiate_decl): Handle instantiations of friend templates.
+ * search.c (lookup_field_1): Don't treat the TYPE_FIELDS of a
+ TEMPLATE_TYPE_PARM as a list of fields; it's not!
+ * spew.c (yylex): Do a little manual constant propogation to
+ clarify the code.
+
+Sun Feb 22 19:53:29 1998 Jeffrey A Law (law@cygnus.com)
- * decl.c (xref_defn_tag): Lose.
- (xref_tag): xref_next_defn = ! globalize.
- (pushdecl): Don't set DECL_NESTED_TYPENAME on artificial decls. The
- ones that should have it set will have it set by pushtag.
- (pushdecl_class_level): Ditto.
- (pushtag): Tidy up a bit.
- (set_nested_typename): Push a decl for the nested typename from
- here, rather than from xref_defn_tag.
+ * error.c: Include sys/types.h.
- * parse.y (do_xref): Lose.
- (named_class_head): If we see 'class foo:' we know it's a
- definition, so don't worry about base lists for non-definitions.
+Thu Feb 19 14:49:09 1998 Jeffrey A Law (law@cygnus.com)
- * pt.c (push_template_decls): Template parm decls are artificial.
+ * method.c (build_mangled_name): Start CPP directives in column zero.
- * decl.c (duplicate_decls): Restore check for qualifier
- disagreement for non-functions.
- (decls_match): Remove check for qualifier disagreement.
+Thu Feb 19 10:36:48 1998 Jason Merrill <jason@yorick.cygnus.com>
-Fri Feb 3 14:58:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * typeck2.c (process_init_constructor): Sorry about non-trivial
+ labeled initializers.
+ * parse.y (initlist): Reenable labeled initializers.
- * decl.c (grok_reference_init): Convert initializer from
- reference.
- * typeck.c (convert_for_initialization): Ditto.
+Thu Feb 19 10:15:55 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
- * decl.c (duplicate_decls): Propagate DECL_NESTED_TYPENAME.
+ * pt.c (coerce_template_parms) Add a new parameter, is_tmpl_parm,
+ all callers changed. Rely on the new parameter instead of arg
+ being a TREE_LIST when determine whether we are working inside
+ template template parameter. Clean up is_type test.
+
+Thu Feb 19 10:04:12 1998 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (cp_convert): Don't convert to the same class type by just
- tacking on a NOP_EXPR.
- (convert_to_reference): Use comp_target_types instead of comptypes
- so that we don't allow conversions two levels down.
+ * cvt.c (cp_convert_to_pointer): Preserve TREE_CONSTANT.
+ * typeck2.c (initializer_constant_valid_p): Allow conversions
+ between pointers and refrerences.
-Thu Feb 2 15:07:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+1998-02-19 Brendan Kehoe <brendan@cygnus.com>
- * class.c (build_vbase_path): Bash types to make the backend happy.
- * cvt.c (build_up_reference): Bash the types bashed by
- build_vbase_path to be reference types instead of pointer types.
- (convert_to_reference): Ditto.
+ * typeck.c (build_unary_op): Only warn about incr/decr a pointer
+ if pedantic || warn_pointer_arith.
- * typeck.c (build_c_cast): Don't strip NOPs if we're converting to a
- reference type.
+Thu Feb 19 09:37:21 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
- * parse.y (structsp): Put back error for 'struct B: public A;'.
+ * pt.c (unify): Handle TEMPLATE_DECL.
-Wed Feb 1 23:02:06 1995 Mike Stump <mrs@cygnus.com>
+1998-02-18 Brendan Kehoe <brendan@cygnus.com>
- * except.c: Add support for mips systems that don't define __mips
- but do define mips, like Ultrix.
+ * cp-tree.h (strip_attrs): Remove decl.
-Wed Feb 1 22:39:07 1995 Mike Stump <mrs@cygnus.com>
+1998-02-18 Doug Evans <devans@cygnus.com>
- * except.c: Add support for exception handling on the Alpha.
+ * decl.c (duplicate_decls): Call merge_machine_decl_attributes.
+ Update olddecl's attributes too.
+ (strip_attrs): Remove function.
+ * typeck.c (common_type): Call merge_machine_type_attributes.
-Wed Feb 1 10:12:14 1995 Mike Stump <mrs@cygnus.com>
+Tue Feb 17 14:07:52 1998 Mark Mitchell <mmitchell@usa.net>
- * decl2.c (finish_file): Fix bug in Jan 31st change.
+ * parse.y (initdcl0_innards): New grammar symbol.
+ (nomods_initdecls, nomods_initdcl0): Change type from itype to
+ none, since the resulting value is never used.
+ (parse_decl): New function.
+ (datadef): Remove redundant actions.
+ (initdcl0, notype_initdcl0, nomods_initdcl0): Use initdcl0_innards.
+ * parse.c: Regenerated.
+
+Tue Feb 17 11:54:16 1998 Jason Merrill <jason@yorick.cygnus.com>
-Tue Jan 31 16:59:15 1995 Gerald Baumgartner (gb@lorenzo.cs.purdue.edu)
+ * parse.y (simple_stmt): Use getdecls() to check for decl.
- * sig.c (build_signature_pointer_or_reference_type): Don't set
- IS_AGGR_TYPE for signature pointers/reference so expand_default_init
- doesn't expect to find a copy constructor.
- * call.c (build_method_call): Treat signature pointers/reference
- as if IS_AGGR_TYPE were set.
-
-Tue Jan 31 13:28:56 1995 Mike Stump <mrs@cygnus.com>
-
- * gc.c (get_typeid): Pawn off error messages to build_t_desc.
- (build_t_desc): Inform the user here if they try and build
- with -frtti and don't include <typeinfo.h>.
-
- * decl2.c (finish_prevtable_vardecl): Support rescanning.
- (finish_file): Move finish_prevtable_vardecl up to before the global
- initializers are done as tdecls are initialized in the global
- initializer. Also Pick up any new tdecls or vtables needed by
- synthesized methods.
-
- * class.c (finish_struct): Simplify. We have to do rtti scanning at
- end, so we might as well do all of it there.
-
-Tue Jan 31 05:35:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * call.c (build_method_call): Fix -fthis-is-variable for 32-bit
- targets, too.
-
-Tue Jan 31 00:11:04 1995 Mike Stump <mrs@cygnus.com>
-
- * decl2.c (finish_prevtable_vardecl): New routine, mostly split from
- finish_vtable_vardecl. It has the first half functionality from
- that routine.
- * decl2.c (finish_vtable_vardecl): Update to not include stuff not
- in finish_prevtable_vardecl.
- * decl2.c (finish_file): Call finish_prevtable_vardecl.
- * gc.c (build_generic_desc): Allow it to be called when not at the
- global binding layer, but behave as if we were.
- (build_t_desc): Rearrange a bit so that it really works and is
- easier to follow.
- * class.c (finish_struct): Don't decide on tdecls here, as we have
- to wait until the end of the file in general to decide whether or
- not they come out.
-
-Mon Jan 30 01:00:40 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * init.c (build_delete): Check access to operator delete before
- calling the destructor.
- * method.c (build_opfncall, DELETE_EXPR): build_method is allowed to
- return error_mark_node.
- * call.c (build_method_call): Use the one-argument op delete even if
- it's an error.
+Sat Feb 14 11:50:51 1998 Manfred Hollstein <manfred@s-direktnet.de>
- * init.c (build_new): Fix -fthis-is-variable support.
- * call.c (build_method_call): Ditto.
+ * Make-lang.in (DEMANGLER_INSTALL_NAME, DEMANGLER_CROSS_NAME): New
+ macros.
+ (c++.install-common): Install c++filt properly as native or as cross
+ variant.
+ (c++.uninstall): Add c++filt.
- * call.c (convert_harshness): Make conversion from a pointer to bool
- worse than conversion to another pointer.
+Fri Feb 13 14:55:37 1998 Jason Merrill <jason@yorick.cygnus.com>
-Sat Jan 28 16:46:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (standard_conversion): Fix multi-level ptr conversions.
- * init.c (build_new): Check new return value if -fcheck-new.
+Fri Feb 13 14:06:22 1998 Mike Stump <mrs@wrs.com>
- * lex.c (check_newline): Clear end_of_file when we're done, too.
+ * init.c (build_new): Propagate error_mark_node up.
-Sat Jan 28 10:38:39 1995 Mike Stump <mrs@cygnus.com>
+Fri Feb 13 13:24:32 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (finish_vtable_vardecl): Make rtti TD tables follow
- vtables whereever they go.
+ * parse.y (simple_stmt): If the condition isn't a declaration,
+ start the controlled block after the test.
- * gc.c (build_t_desc): Remove old way of setting it up, as it wasn't
- right.
+Fri Feb 13 02:26:10 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
-Sat Jan 28 09:10:44 1995 Mike Stump <mrs@cygnus.com>
+ * call.c (build_over_call): Convert builtin abs, labs and fabs to
+ tree-codes.
+ * decl.c (init_decl_processing): Reenable abs, labs and fabs as
+ builtins.
- * decl2.c (finish_vtable_vardecl): Now set the
- interface/implementation of vtables on the first virtual function,
- if one exists, otherwise we use the old method. This is a major win
- in terms of cutting down the size of objects and executables in
- terms of text space and data space. Now most of the savings that
- #pragma interface/implementation gives is automatic in a fair number
- of cases.
+Fri Feb 13 01:36:42 1998 Jason Merrill <jason@yorick.cygnus.com>
-Sat Jan 28 04:57:33 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (standard_conversion): A BASE_CONV replaces an RVALUE_CONV.
- * decl.c (grokdeclarator): Discard the template parameters in a
- template constructor declaration so that the function is always
- named constructor_name (ctype).
+Fri Feb 13 00:21:59 1998 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (check_newline): Use ungetc to put back the character before
- calling HANDLE_PRAGMA.
+ * cp-tree.h: Add access_protected_virtual_node.
+ * class.c (init_class_processing): Initialize it.
+ * decl.c (xref_basetypes): Use it.
+ * parse.y (base_class_access_list): Likewise.
-Fri Jan 27 17:23:47 1995 Mike Stump <mrs@cygnus.com>
+ * Make-lang.in (DEMANGLER_PROG): Add $(exeext).
+ (c++.install-common): Install c++filt.
- * decl2.c (check_classfn): If the cname is T<int> and fn_name is T,
- make sure we still match them.
+Thu Feb 12 12:46:51 1998 Benjamin Kosnik <bkoz@rhino.cygnus.com>
-Fri Jan 27 16:32:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (shadow_tag): Give error for typedef-ing built-in types.
- * parse.y: Add END_OF_LINE token.
+Wed Feb 11 23:28:05 1998 Mark Mitchell <mmitchell@usa.net>
- * lex.c (check_newline): Set linemode when we see a # directive, and
- unset it when we're done. Turn all 'return's into 'goto skipline'.
- Fix all uses of '\n', since we won't see it anymore. Put back the
- character we read before checking for a sysv or target pragma.
- (real_yylex): If we see an EOF in linemode, return END_OF_LINE.
- (handle_sysv_pragma): Don't look at the input stream; quit when we
- see an END_OF_LINE token.
+ * call.c (reference_binding): Use comptypes when comparing
+ TYPE_MAIN_VARIANTS to handle non-canonical array/index types.
- * input.c (getch): Return EOF if we're in line mode and at the end
- of a line.
- (put_back): Don't put back an EOF.
+Wed Feb 11 16:42:04 1998 Mark Mitchell <mmitchell@usa.net>
-Thu Jan 26 19:26:34 1995 Mike Stump <mrs@cygnus.com>
+ * tree.c (is_overloaded_fn): Use really_overloaded_fn.
+ (really_overloaded_fn): Move check here from is_overloaded_fn.
+ (get_first_fn): Use really_overloaded_fn and is_overloaded_fn.
- * except.c (expand_throw): Do the newing of the exception object
- before we load the type descriptor or the address so that we don't
- wipe any of the values out.
+Wed Feb 11 15:54:18 1998 Mark Mitchell <mmitchell@usa.net>
-Thu Jan 26 19:20:00 1995 Mike Stump <mrs@cygnus.com>
+ * typeck.c (build_ptrmemfunc): Type-check pointer-to-member
+ conversions.
- * except.c (init_exception_processing): Don't use r12 on the rs6000.
+Mon Feb 9 22:23:31 1998 Mark Mitchell <mmitchell@usa.net>
+
+ * cp-tree.h (push_template_decl): Return the decl passed in, or an
+ equivalent duplicate.
+ * decl.c (pushtag): Use the return value from push_template_decl.
+ (duplicate_decls): When duplicating a template declaration, merge
+ the DECL_TEMPLATE_RESULTs as well.
+ (make_implicit_typename): Don't try to dive into typename types to
+ find a context for making a new implicit typename.
+ (start_decl): Use the return value from push_template_decl.
+ (grokdeclarator): Complain about declarations list `const operator
+ int'. Since we don't correctly handle in-class initializations of
+ non-static data members, complain about this (now illegal)
+ practice. Issue an error for initializations of non-const statics
+ since that is illegal as well, and since we don't handle that case
+ correctly either.
+ (start_function): Use the return value from push_template_decl.
+ (start_method): Likewise.
+ * decl2.c (grokfield): Likewise. Since the change to
+ grokdeclarator ensures that all initialized fields are in fact
+ static, remove a redundant test for TREE_PUBLIC.
+ * parse.y (initlist): Disable labeled initializers since they do
+ not work as per the documentation, and since they do not use the
+ same syntax as the C front end.
+ * pt.c (push_template_decl): Return the decl passed in, or an
+ equivalent duplicate.
+ (lookup_template_class): When searching in a nested context,
+ use the right arguments.
+ (uses_template_parms): Handle the DECL_INITIAL for a CONST_DECL.
+ * typeck.c (build_component_ref): Assign the correct type to the
+ result of build_vfn_ref.
+
+Tue Feb 10 23:56:46 1998 Jason Merrill <jason@yorick.cygnus.com>
-Tue Jan 24 16:36:31 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (convert_nontype_argument): Fix typo.
+ (check_explicit_specialization): Allow old-style specialization
+ of class template members.
- * decl.c (grokparms): Don't try to build up a reference at this point.
+Tue Feb 10 20:36:52 1998 Jason Merrill <jason@yorick.cygnus.com>
+ Manfred Hollstein <manfred@s-direktnet.de>
- * typeck2.c (build_functional_cast): Don't assume that a NOP_EXPR
- will suffice to convert from integer_zero_node.
+ * decl.c (grokdeclarator): Use DECL_USE_TEMPLATE instead
+ when deciding to override DECL_ASSEMBLER_NAME.
-Wed Jan 25 15:02:09 1995 David S. Miller (davem@nadzieja.rutgers.edu)
+Tue Feb 10 15:30:55 EST 1998 Andrew MacLeod <amacleod@torpedo.to.cygnus.com>
- * class.c (instantiate_type): Change error message text.
- * typeck2.c (store_init_value): Likewise.
+ * decl2.c (lang_f_options): Add -fsquangle to option processing list.
+ * cp-tree.h (flag_do_squangling): Add declaration.
+ * lang-options.h: Add -fsquangle and -fno-squangle.
+ * method.c: Add macros and static variables for squangling.
+ (build_overload_name): Rename to build_mangled_name, add logic for B
+ compression, and split into process_modifiers and
+ process_overload_item.
+ (process_modifiers): New function, to handle constant, reference,
+ and pointer types.
+ (process_overload_item): New function, handles issue of type codes.
+ (build_overload_name): New function, start squangling and call
+ build_mangled_name.
+ (ALLOCATE_TYPEVEC, DEALLOCATE_TYPEVEC): Remove macro and expand inline.
+ (start_squangling): New function to initialize squangling structs.
+ (end_squangling): New function to destroy squangling structs.
+ (nrepeats): Rename variable to Nrepeats.
+ (issue_nrepeats): New function for issuing 'n' type repeats.
+ (check_ktype): New function to check for type K name compression.
+ (build_overload_nested_name): Add a check for K name compression.
+ (build_qualified_name): Add a check for K name compression and don't
+ use DECL_ASSEMBLER_NAME when squangling is on.
+ (check_btype): New function, checks for B type compression.
+ (build_static_name, build_decl_overload_real): Initiate squangling.
+ (build_typename_overload, build_overload_with_type): Initiate
+ squangling
-Mon Jan 23 21:57:14 1995 Mike Stump <mrs@cygnus.com>
+Sun Feb 8 23:47:38 1998 scott snyder <sss@d0linux01.fnal.gov>
- * pt.c (tsubst): When we copy a node, don't forget to copy
- TREE_CHAIN, we use it later.
+ * method.c (make_thunk): Avoid name buffer overflow.
-Mon Jan 23 03:33:47 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Sat Feb 7 16:48:54 1998 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (convert_for_assignment): Initialize variable before use.
+ * pt.c (instantiate_decl): Call cp_finish_decl for vars even if we
+ don't define them yet.
-Fri Jan 20 01:17:59 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * parse.y (nomods_initdcl0): Add constructor_declarator case.
- * g++.c (main): Link with both libstdc++ and libg++ if called as
- something ending with "g++", otherwise only libstdc++. Move -lm to
- the end of the line.
+Fri Feb 6 21:32:25 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
-Thu Jan 19 15:43:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * config-lang.in (diff_excludes): Use basename only.
- * call.c (build_method_call): Don't mess with 'this' before calling
- compute_conversion_costs.
+Thu Feb 5 19:10:40 1998 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jan 18 15:40:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * tinfo2.cc: Add tinfo for signed char.
- * search.c (get_matching_virtual): Give line number for previous
- declaration.
+Thu Feb 5 14:38:23 1998 Mike Stump <mrs@wrs.com>
- * call.c (convert_harshness): Handle conversions to references
- better.
+ * search.c (compute_access): Handle protected constructors in derived
+ classes as accessible.
- * cvt.c (build_up_reference): OK, handle {MIN,MAX}_EXPR *properly*.
+Wed Feb 4 01:26:49 1998 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jan 18 15:21:38 1995 Mike Stump <mrs@cygnus.com>
+ * expr.c (cplus_expand_expr, PCC_STATIC_STRUCT_RETURN code):
+ Call convert_from_reference sooner.
- * class.c (instantiate_type): Use DECL_CHAIN to walk lists instead,
- as the TREE_CHAIN for methods will take us to the next differently
- named function, DECL_CHAIN won't.
+Tue Feb 3 23:50:52 1998 Mark Mitchell <mmitchell@usa.net>
-Wed Jan 18 14:26:59 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cvt.c (ocp_convert): Obtain the constant values from constant
+ decls even if the destination type is the same as the type of the
+ decl.
- * tree.c (lvalue_p): Handle {MIN,MAX}_EXPR.
+ * decl2.c (finish_file): Make sure that static inlines with
+ definitions are not marked DECL_EXTERNAL before returning.
- * decl2.c (lang_decode_option): -Wall implies -Wparentheses.
- warn_parentheses defaults to 0.
+Tue Feb 3 22:43:42 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokparms): Put back call to require_instantiated_type.
+ * decl.c: Lose arg_looking_for_template.
+ (lookup_name_real): Likewise.
+ * parse.y: Lose processing_template_arg, template_arg1
+ (primary): Likewise.
+ * spew.c (yylex): Set lastiddecl for PTYPENAMEs, too.
-Tue Jan 17 19:56:15 1995 Mike Stump <mrs@cygnus.com>
+Tue Feb 3 22:04:01 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
- * except.c (exception_section): Use the data section on the rs6000.
- Change calling convention for named_section.
+ * error.c (dump_decl): Fix type of default arguments for template
+ template parameters and nontype template parameters.
+ * parse.y (template_parm): Handle invalid default template
+ template arguments here.
-Wed Jan 17 18:20:57 1994 Fergus Henderson <fjh@munta.cs.mu.oz.au>
+ * parse.y (template_parm): Use template_arg instead of PTYPENAME
+ for default template template argument.
+ * pt.c (coerce_template_parms): Merge default template argument
+ codes. Can treat RECORD_TYPE as template name if it is implicitly
+ created. Fix argument index in error message.
+ * typeck.c (comptypes): Merge template argument comparison codes in
+ TEMPLATE_TEMPLATE_PARM and RECORD_TYPE.
- * cp-tree.h : Make if (x=0) warn with wall
- * parse.y : Make if (x=0) warn with wall
+Tue Jan 6 01:42:44 1998 Mumit Khan <khan@xraylith.wisc.edu>
-Tue Jan 17 14:12:00 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * lex.c (file_name_nondirectory): Also check for '/'.
- * decl.c (BOOL_TYPE_SIZE): BITS_PER_WORD if SLOW_BYTE_ACCESS,
- BITS_PER_UNIT otherwise.
+Mon Feb 2 11:24:22 1998 Mark Mitchell <mmitchell@usa.net>
- * search.c (get_matching_virtual): Don't check the binfo if the
- types are the same.
+ * parse.y (primary): Deal with statement-expressions in
+ templates.
+ * pt.c (tsubst_copy): Handle BIND_EXPR.
+ * tree.c (mapcar): Likewise.
- * cvt.c (cp_convert): Just call truthvalue_conversion to convert to
- bool.
+ * call.c (add_template_candidate_real): Pass extra parameter to
+ fn_type_unification.
+ * cp-tree.h (fn_type_unification): Add parameter.
+ * pt.c (fn_type_unification): Add additional parameter to deal with
+ static member functions.
+ (get_bindings): Deal with static member functions.
+
+ * cp-tree.h (DECL_NONSTATIC_MEMBER_FUNCTION_P): New macro.
+ (revert_static_member_fn): Declare.
+ * decl.c (revert_static_member_fn): Remove declaration. Change
+ linkage from internal to external.
+ (cp_finish_decl): Deal with virtual functions in classes local to
+ template functions.
+ * decl2.c (finish_file): Don't forget to emit increment/decrement
+ expressions in initializers for file-scope variables.
+ * parse.y (typename_sub2): If the typename doesn't names a
+ template, rather than a type, issue an error message.
+ * pt.c (check_explicit_specialization): Handle specializations of
+ static member functions.
+ (coerce_template_parms): Handle offset references to lists of
+ member functions.
+ * search.c (note_debug_info_needed): Don't crash when handed a
+ type which is being defined.
+ * typeck.c (complete_type): Don't crash when handed NULL_TREE;
+ that can happen with some illegal code.
+
+Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * call.c (user_harshness): Initialize `code' to 0.
+ (build_method_call): Initialize `candidates', `cp' and `len' to 0.
+ (null_ptr_cst_p): Add parentheses around && within ||.
+ (standard_conversion): Likewise.
+ (z_candidate): Likewise.
+ (build_user_type_conversion_1): Initialize `args' to NULL_TREE.
+ (build_object_call): Likewise for `mem_args'.
+ (build_new_op): Likewise for `mem_arglist'. Add `return' from
+ default case in enumeration switch.
+
+ * class.c (build_vtable_entry): Add explicit braces to avoid
+ ambiguous `else'.
+ (build_class_init_list): Likewise.
+ (finish_struct_1): Initialize `width' to 0.
+ (instantiate_type): Initialize `name' to NULL_TREE. Add
+ explicit braces to avoid ambiguous `else'.
+
+ * cvt.c (convert_to_aggr): Add explicit braces to avoid ambiguous
+ `else'.
+
+ * decl.c (grok_reference_init): Eliminate unused parameter, all
+ callers changed.
+ (record_builtin_type): Initialize `tdecl' to NULL_TREE.
+ (init_decl_processing): Initialize `vb_off_identifier' to NULL_TREE.
+ (cp_finish_decl): Initialize `ttype' to NULL_TREE.
+ (grokdeclarator): Add parentheses around && within ||. Add
+ explicit braces to avoid ambiguous `else'.
+ (grokparms): Initialize `type' to NULL_TREE.
+ (xref_tag): Remove unused label `just_return'.
+ (finish_enum): Initialize `minnode' and `maxnode' to NULL_TREE.
+ (finish_function): Initialize `cond' and `thenclause' to NULL_TREE.
+ (hack_incomplete_structures): Add parentheses around assignment
+ used as truth value.
+
+ * decl2.c (coerce_delete_type): Hide definition of `e3'.
+
+ * error.c: Include <stdlib.h>.
+ (dump_expr): Change the type of `i' to size_t. Remove unused
+ label `error'.
+
+ * except.c (init_exception_processing): Remove unused variable `d'.
+ (expand_throw): Likewise for `label'.
+
+ * friend.c (add_friends): Add explicit braces to avoid ambiguous
+ `else'.
+
+ * init.c (sort_member_init): Initialize `last_field' to NULL_TREE.
+ (sort_base_init): Likewise for `binfo'.
+ (expand_member_init): Likewise for `rval'.
+ (build_member_call): Add parentheses around assignment used as
+ truth value.
+ (build_offset_ref): Add explicit braces to avoid ambiguous `else'.
+ (build_new): Initialize `nelts' to NULL_TREE. Initialize
+ `old_immediate_size_expand' to 0.
+ (build_new_1): Initialize `nelts' and `alloc_node' to NULL_TREE.
+ (build_vec_delete_1): Remove unused variable `block'.
+ (expand_vec_init): Initialize `itype' to NULL_TREE.
+
+ * lex.c: Include <strings.h> if we don't have <string.h>. Protect
+ declaration of `index' and `rindex' with autoconf macros.
+ (reinit_parse_for_expr): Remove unused variables
+ `look_for_semicolon' and `look_for_lbrac'.
+ (cons_up_default_function): Initialize `args' to NULL_TREE.
+ (readescape): Initialize `firstdig' to 0.
+ (real_yylex): Add parentheses around assignment used as truth value.
+
+ * method.c: Include <strings.h> if we don't have <string.h>.
+ Protect declaration of `index' with autoconf macro.
+
+ * parse.y (primary): Add explicit braces to avoid ambiguous `else'.
+ Initialize `type' to NULL_TREE.
+ (structsp): Remove unused variable `id'.
+
+ * pt.c (coerce_template_parms): Add explicit braces to avoid
+ ambiguous `else'.
+ (lookup_template_class): Initialize `template' to NULL_TREE.
+ (instantiate_class_template): Remove unused variable `name' and `e'.
+ (tsubst): Likewise for `i'. Initialize `last' to NULL_TREE.
+ (do_poplevel): Initialize `saved_warn_unused' to 0.
+ (type_unification): Remove unused varable `parm'.
+ (unify): Likewise for `j'.
+
+ * repo.c (init_repo): Add parentheses around assignment used as
+ truth value.
+ (finish_repo): Remove unused varable `p'.
+
+ * search.c (get_binfo): Initiize `type' to NULL_TREE.
+ (get_base_distance): Likewise.
+ (lookup_field): Initialize `rval_binfo_h', `type', `basetype_path'
+ and `new_v' to NULL_TREE.
+ (lookup_fnfields): Likewise for `rval_binfo_h'.
+ (breadth_first_search): Add parentheses around assignment used as
+ truth value.
+ (get_template_base): Initialize `type' to NULL_TREE.
+
+ * sig.c (append_signature_fields): Initialize `last_mfptr' to
+ NULL_TREE.
+ (build_signature_table_constructor): Likewise for
+ `last_rhs_field', `pfn' and `vt_off'.
+ (build_sigtable): Likewise for `init'.
+
+ * tree.c (break_out_calls): Initialize `t2' to NULL_TREE.
+ (propagate_binfo_offsets): Likewise for `delta'.
+ (hash_tree_cons): Initialize hashcode to 0.
+ (can_free): Likewise for `size'.
+ (cp_tree_equal): Add explicit braces to avoid ambiguous `else'.
+
+ * typeck.c (convert_sequence): Hide prototype.
+ (common_type): Add explicit braces to avoid ambiguous `else'.
+ (comp_target_types): Likewise.
+ (build_x_function_call): Initialize `ctypeptr' to NULL_TREE.
+ (build_function_call_real): Add explicit braces to avoid ambiguous
+ `else'.
+ (convert_arguments): Initialize `called_thing' to 0.
+ (convert_for_initialization): Initialize `savew' and `savee' to 0.
+
+ * typeck2.c (incomplete_type_error): Initialize `errmsg' to 0.
+ (digest_init): Initialize `old_tail_contents' to NULL_TREE.
+ (build_x_arrow): Likewise for `last_rval'.
+
+ * xref.c (GNU_xref_decl): Initialize `cls' to 0.
+
+Sun Feb 1 12:45:34 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * decl.c (init_decl_processing): Use set_sizetype.
+ * decl2.c (sizetype): Don't declare.
+ * typeck.c (c_sizeof): Convert result of *_DIV_EXPR to sizetype.
+ (c_sizeof_nowarn, build_binary_op_nodefault): Likewise.
+ (build_component_addr, unary_complex_lvalue): Likewise.
+ * rtti.c (expand_class_desc): Likewise.
+ * class.c (get_vfield_offset): Likewise.
+
+Thu Jan 29 10:39:30 1998 Mark Mitchell <mmitchell@usa.net>
+
+ * pt.c (convert_nontype_argument): Move check for is_overloaded_fn
+ early to avoid bogus error. Handle overloaded function
+ names provided as template arguments correctly.
+ (coerce_template_parms): Don't mishandle overloaded functions when
+ dealing with template template parameters.
+ (lookup_template_class): Issue an error message, rather than
+ crashing, when the TYPE_DECL provided is not a template type.
+
+Wed Jan 28 23:14:44 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c (instantiate_type): Don't just return a known type if
+ it's wrong.
+
+Wed Jan 28 11:04:07 1998 Mark Mitchell <mmitchell@usa.net>
+
+ * class.c (instantiate_type): Remove handling of FUNCTION_DECL
+ since that code could never be reached.
+
+ * error.c (dump_decl): Avoid aborting in the midst of printing an
+ error message about an illegal template declaration.
-Mon Jan 16 13:28:48 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * parse.y (structsp): Print an error message, rather than crashing,
+ when a class-head does not name a class.
- * various: Use boolean_type_node, boolean_true_node,
- boolean_false_node.
+ * pt.c (convert_nontype_argument): Allow REAL_TYPE and COMPLEX_TYPE
+ template arguments as a g++ extension.
+
+ * cp-tree.def (ALIGNOF_EXPR): New tree code.
+ * decl2.c (grok_alignof): If processing_template_decl, just store
+ the expression.
+ * typeck.c (c_alignof): Likewise.
+ * decl2.c (build_expr_from_tree): Handle ALIGNOF_EXPR.
+ * error.c (dump_expr): Likewise.
+ * pt.c (tsubst_copy): Likewise.
+ * tree.c (cp_tree_equal): Likewise.
+ * pt.c (uses_template_parms): Correctly determine whether or not a
+ SIZEOF_EXPR/ALIGNOF_EXPR uses template parameters so that constant
+ folding can be done.
+
+ * cp-tree.h (grok_enum_decls): Remove type parameter.
+ * decl.c (grok_enum_decls): Likewise.
+ * decl2.c (grok_x_components): Call grok_enum_decls
+ unconditionally, since it will do nothing if there is no
+ current_local_enum. Use the new calling sequence.
+ * pt.c (tsubst_enum): Use the new calling sequence for
+ grok_enum_decls.
+
+ * decl.c (start_function): Make member functions of local classes
+ in extern inline functions have comdat linkage here...
+ (grokdeclarator): Rather than here.
+
+Wed Jan 28 10:55:47 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (convert_nontype_argument): Use decl_constant_value.
+
+Tue Jan 27 16:42:21 1998 Mark Mitchell <mmitchell@usa.net>
+
+ * call.c (add_template_candidate_real): New function.
+ (add_template_candidate): Use it.
+ (add_template_conv_candidate): Likewise.
+ (joust): Pass extra argument to more_specialized.
+ * class.c (instantiate_type): Handle a single FUNCTION_DECL.
+ (is_local_class): Remove.
+ (finish_struct): Check TI_PENDING_SPECIALIZATION_FLAG.
+ * cp-tree.h (is_local_class): Remove.
+ (perform_array_to_pointer_conversion): Likewise.
+ (finish_member_template_decl): Add.
+ (check_explicit_specialization): Return a tree, not an int.
+ (more_specialized): Take additional argument.
+ (get_bindings): Likewise.
+ (TI_PENDING_SPECIALIZATION_FLAG): New macro.
+ * cvt.c (perform_qualification_conversions): Use comp_ptr_ttypes.
+ (perform_array_to_pointer_conversion): Remove.
+ * decl.c (saved_scope): Add processing_specialization,
+ processing_explicit_instantiation fields.
+ (maybe_push_to_top_level): Save them.
+ (pop_from_top_level): Restore them.
+ (grokfndecl): Use new return value from
+ check_explicit_specialization.
+ (start_decl): Don't check flag_guiding_decls before pushing
+ decls.
+ (cp_finish_decl): Remove previous (bogus) change.
+ (grok_declarator): Use decl_function_context rather than
+ is_local_class.
+ * decl2.c (finish_file): Pass extra argument to get_bindings.
+ (build_expr_from_tree): Let build_x_component_ref check
+ validity of arguments rather than doing it here.
+ * lex.c (cons_up_default_function): Remove code fooling with
+ processing_specialization, processing_explicit_instantiation
+ flags, as that is now done in {maybe_push_top,pop_from}_top_level.
+ * method.c (build_overload_identifier): Mangle local classes in
+ template functions correctly.
+ * parse.y (finish_member_template_decl): Move to pt.c.
+ * pt.c (finish_member_template_decl): Moved here from parse.y.
+ (print_candidates): New function.
+ (determine_specialization): Change interface. Properly look for
+ most specialized versions of template candidates.
+ (check_explicit_specialization): Fully process explicit
+ instantiations.
+ (push_template_decl): Avoid looking at CLASSTYPE fields in
+ FUNCTION_DECLS.
+ (determine_overloaded_function): Remove.
+ (convert_nontype_argument): Change name from
+ convert_nontype_parameter. Use determine_overloaded_function
+ instead of instantiate_type.
+ (mangle_class_name_for_template): Handle type contexts as well as
+ function contexts.
+ (classtype_mangled_name): Likewise.
+ (lookup_template_class): Likewise.
+ (tsubst): Likewise.
+ (more_specialized): Take explict template arguments as a
+ parameter.
+ (most_specialized): Likewise.
+ (get_bindings): Likewise. Check that return types match before
+ proclaiming a function a match.
+ (do_decl_instantiation): Remove code searching for function to
+ instantiate; that is now done in check_explicit_specialization.
+ (add_maybe_template): Pass extra argument to get_bindings.
+ * tree.c (really_overloaded_fn): Use is_overloaded_fn to simplify
+ implementation.
+ * typeck.c (build_component_ref): Check for invalid arguments.
+
+Tue Jan 27 01:44:02 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * expr.c (cplus_expand_expr, AGGR_INIT_EXPR): Don't check that
+ return_target and call_target are equivalent.
+
+ * pt.c (type_unification_real): Just accept function parms that
+ don't use any template parms.
+
+Sun Jan 25 03:30:00 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (cp_finish_decl): When bailing on a comdat variable, also
+ unset DECL_NOT_REALLY_EXTERN.
+
+ * parse.y (typename_sub*): Fix std::.
+
+Sat Jan 24 12:13:54 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * error.c (dump_decl): Fix type default template args.
+ (dump_type): Hand TEMPLATE_DECL off to dump_decl.
+
+Fri Jan 23 18:34:37 1998 Mumit Khan <khan@xraylith.wisc.edu>
+
+ * lex.c (DIR_SEPARATOR): Define to be '/' if not already defined.
+ (file_name_nondirectory): Use.
+
+Wed Jan 21 10:29:57 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
+
+ * pt.c (coerce_template_parms): Don't access elements of ARGLIST
+ that are not really present. Substitute default arguments in
+ template template arguments. Correctly convert TEMPLATE_DECL to
+ TEMPLATE_TEMPLATE_PARM.
+ (comp_template_args): TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM
+ are no longer treated specially here.
+ * parse.y (template_template_parm): Fix copy error.
+ * decl.c (grokdeclarator): Warn about missing `typename' for nested
+ type created from template template parameters.
+ * parse.y (bad_parm): Likewise
+
+ * class.c (finish_struct): Handle TEMPLATE_TEMPLATE_PARM.
+ (push_nested_class): Likewise.
+ * cp-tree.def (TEMPLATE_TEMPLATE_PARM): New tree code.
+ * cp-tree.h (DECL_TEMPLATE_TEMPLATE_PARM_P): New macro.
+ (copy_template_template_parm): Declare.
+ * decl.c (arg_looking_for_template): New variable.
+ (lookup_name_real): Handle TEMPLATE_TEMPLATE_PARM.
+ Try to return TEMPLATE_DECL or TEMPLATE_TEMPLATE_PARM
+ node if arg_looking_for_template is nonzero.
+ (pushdecl): Handle TEMPLATE_TEMPLATE_PARM.
+ (grok_op_properties, xref_tag, xref_basetypes): Likewise.
+ (grokdeclarator): Handle TEMPLATE_DECL.
+ * decl2.c (constructor_name_full): Handle TEMPLATE_TEMPLATE_PARM.
+ * error.c (dump_type): Add TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM.
+ (dump_type_prefix, dump_type_suffix) Handle TEMPLATE_TEMPLATE_PARM.
+ (dump_decl): Handle unnamed template type parameters.
+ Handle template template parameters.
+ (dump_function_name): Handle template template parameters.
+ * init.c (is_aggr_typedef, is_aggr_type, get_aggr_from_typedef):
+ Handle TEMPLATE_TEMPLATE_PARM.
+ * method.c (build_template_template_parm_names): New function.
+ (build_template_parm_names): Handle TEMPLATE_DECL.
+ (build_overload_nested_name, build_overload_name):
+ Handle TEMPLATE_TEMPLATE_PARM.
+ * parse.y (maybe_identifier): New nonterminal.
+ (template_type_parm): Use it.
+ (template_template_parm, template_arg1): New nonterminal.
+ (template_parm): Add template_template_parm rules.
+ (template_arg): Set processing_template_arg.
+ (template_arg1): Rules moved from template_arg.
+ (primary, nonnested_type): Set arg_looking_for_template if we are
+ processing template arguments.
+ * pt.c (begin_member_template_processing): Handle TEMPLATE_DECL.
+ (process_template_parm): Handle template template parameters.
+ (coerce_template_parms, comp_template_args): Likewise.
+ (mangle_class_name_for_template, lookup_template_class): Likewise.
+ (uses_template_parms): Handle TEMPLATE_DECL and
+ TEMPLATE_TEMPLATE_PARM.
+ (current_template_args): Handle TEMPLATE_DECL.
+ (tsubst, tsubst_copy, unify): Handle TEMPLATE_TEMPLATE_PARM.
+ * search.c (dfs_walk, dfs_record_inheritance):
+ Handle TEMPLATE_TEMPLATE_PARM.
+ * tree.c (copy_template_template_parm): New function.
+ (mapcar): Handle TEMPLATE_TEMPLATE_PARM.
+ * typeck.c (comptypes): Handle TEMPLATE_TEMPLATE_PARM.
+
+Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
+
+ * decl.c (start_decl): Don't allow duplicate definitions of static
+ data members.
+
+ * call.c (build_user_type_conversion_1): Handle user-defined
+ template conversion operators correctly.
+
+ * decl2.c (build_expr_from_tree): Issue an error message if the
+ object in a COMPONENT_REF is a TEMPLATE_DECL.
+
+ * typeck.c (incomplete_type_error): Handle TEMPLATE_TYPE_PARMs.
+
+ * class.c (is_local_class): New function.
+ * cp-tree.h (is_local_class): Declare it.
+ (last_tree): Likewise.
+ (begin_tree): Likewise.
+ (end_tree): Likewise.
+ (lookup_template_class): Change prototype.
+ * decl.c (cp_finish_decl): Check for NULL where necesary.
+ Consider FUNCTION_DECLS to declare objects with top-level binding,
+ when calling make_decl_rtl.
+ (grokdeclarator): Give members of local classes internal linkage.
+ (start_function): Remove declaration of last_tree.
+ (finish_function): Set flag_keep_inline_functions around call to
+ rest_of_compilation if we are processing a member function in a
+ local class.
+ (start_method): Call push_template_decl for member functions of
+ local classes in template functions.
+ * decl2.c (import_export_decl): Don't give external linkage to
+ instantiations of templates with internal linkage.
+ * parse.y (last_tree): Remove declaration.
+ (template_type): Pass extra parameter to lookup_template_class.
+ (self_template_type): Likewise.
+ (structsp): Move call to reset_specialization into left_curly.
+ (left_curly): Call reset_specialization, and begin_tree.
+ * pt.c (saved_trees): New variable.
+ (mangle_class_name_for_template): Change prototype. Use
+ additional function context to name local classes in templates
+ correctly.
+ (classtype_mangled_name): Pass the context.
+ (push_template_decl): Handle local classes and templates, and
+ member functions for such classes.
+ (convert_nontype_parameter): Fix handling of pointer-to-member
+ constants.
+ (lookup_template_class): Handle local classes in templates.
+ (tsubst): Likewise. Don't assume that template instantiations
+ have external linkage; pay attention to the template declaration.
+ (mark_decl_instantiated): Likewise.
+ (begin_tree): New function.
+ (end_tree): Likewise.
+
+ * decl.c (xref_basetypes): Don't call complete_type for basetypes
+ that involve template parameters; that can lead to infinite
+ recursion unnecessarily.
- * search.c (get_matching_virtual): Allow covariant returns that
- don't require pointer adjustment.
+ * pt.c (register_specialization): Do not register specializations
+ that aren't ready to be registered yet.
+ (check_explicit_specialization): Handle explicit specialization of
+ constructors and destructors.
+ (build_template_decl): New function.
+ (push_template_delc): Handle out-of-class specializations of
+ member templates.
+
+ * pt.c (check_explicit_specialization): Set up the template
+ information before registering the specialization.
+ (coerce_template_parms): Fix thinko.
+ (tsubst): Handle specializations of member templates correctly.
+
+ * class.c (finish_struct_methods): Remove calls to
+ check_explicit_specialization from here.
+ (finish_struct): And insert them here.
+ * cp-tree.h (perform_qualification_conversions): New function.
+ (perform_array_to_pointer_conversion): Likewise.
+ (begin_explicit_instantiation): Likewise.
+ (end_explicit_instantiation): Likewise.
+ (determine_specialization): Renamed from
+ determine_explicit_specialization.
+ (comp_template_parms): New function.
+ (processing_explicit_instantiation): New variable.
+ * cvt.c (perform_qualification_conversions): New function.
+ (perform_array_to_pointer_conversion): Likewise.
+ * decl.c (duplicate_decls): Don't consider template functions
+ alike unless they have the same parameters. Refine handling of
+ instantiation/specialization mismatches.
+ (start_decl): Don't call pushdecl for template specializations,
+ since they don't affect overloading.
+ (start_function): Likewise
+ (grokfndecl): Call check_explicit_specialization a little later.
+ Don't call duplicate_decls for memberm template specializations.
+ (grokdeclarator): Don't update template_count for classes that are
+ themselves specializations. Remove use of `2' as parameter to
+ grokfndecl since that value isn't used.
+ * lex.c (cons_up_default_function): Save and restore
+ processing_explicit_instantiation around calls to grokfield.
+ * parse.y (finish_member_template_decl): New function.
+ (component_decl_1): Use it.
+ (fn.def2): Likewise.
+ (template_arg_list_opt): New nonterminal.
+ (template_type): Use it.
+ (self_template_type): Likewise.
+ (template_id): Likewise.
+ (object_template_id): Likewise.
+ (notype_template_declarator): Likwise.
+ (begin_explicit_instantiation): Likewise.
+ (end_explicit_instantiation): Likewise.
+ (explicit_instantiation): Use them.
+ * pt.c (coerce_template_parms): Add parameters.
+ (processing_explicit_instantiation): New variable.
+ (convert_nontype_parameter): New function.
+ (determine_overloaded_function): Likewise.
+ (begin_explicit_instantiation): Likewise.
+ (end_explicit_instantiation): Likewise.
+ (retrieve_specialization): Likewise.
+ (register_specialization): Likewise.
+ (processing_explicit_specialization): Removed.
+ (determine_specialization): Handle specializations of member
+ functions of template class instantiations.
+ (check_explicit_specialization): Refine to conform to standard.
+ (comp_template_parms): New function.
+ (coerce_template_parms): Call convert_nontype_parameter.
+ (tsubst): Refine handling of member templates. Use
+ register_specialization.
+ (instantiate_template): Use retrieve_specialization.
+ (do_decl_instantiation): Likewise.
+ (instantiate_decl): Likewise.
+ (type_unification): Improve handling of explict template
+ arguments.
+ * tree.c (mapcar): Return error_mark_node, rather than aborting,
+ on VAR_DECLS, FUNCTION_DECLS, and CONST_DECLS.
+ * typeck.c (build_unary_op): Call determine_specialization, rather
+ than determine_explicit_specialization.
+
+Mon Jan 19 13:18:51 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cvt.c (build_up_reference): A TARGET_EXPR has side effects.
+
+Fri Jan 16 11:40:50 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
+
+ * error.c (dump_decl): For enum tags, output the tag, not its value.
+
+1998-01-13 Brendan Kehoe <brendan@cygnus.com>
+
+ * decl.c (init_decl_processing): Only call init_rtti_processing
+ FLAG_RTTI is set.
+
+Mon Jan 12 01:35:18 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * init.c (build_new_1): Split out from build_new.
+ (build_new): Just return a NEW_EXPR.
+ * expr.c (cplus_expand_expr): Handle NEW_EXPR.
+
+ * decl2.c (get_temp_regvar): Tweak.
+
+ * cp-tree.h (TREE_CALLS_NEW): Comment out.
+ * class.c (resolves_to_fixed_type_p): Remove use.
+ * method.c (build_opfncall): Likewise.
+ * call.c (build_new_op): Likewise.
+
+Wed Jan 7 23:47:13 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * exception.cc (__eh_alloc, __eh_free): New fns.
+ (__cp_push_exception, __cp_pop_exception): Use them.
+ (__uncatch_exception): Call terminate here if no exception.
+ * except.c (build_terminate_handler): New fn.
+ (expand_start_catch_block): Use it.
+ (expand_exception_blocks): Likewise.
+ (alloc_eh_object): New fn.
+ (expand_throw): Use it. Protect exception init with terminate.
+ * typeck.c (build_modify_expr): Remove code that ignores trivial
+ methods.
- * typeck.c (build_conditional_expr): Don't call default_conversion
- on ifexp.
+Mon Dec 22 11:36:27 1997 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * call.c (add_builtin_candidate): Add default case in enumeration
+ switch.
+ (build_new_op): Likewise.
+ (convert_like): Likewise.
+ * cvt.c (build_expr_type_conversion): Likewise.
+ * tree.c (real_lvalue_p): Likewise.
+ (lvalue_p): Likewise.
+ (cp_tree_equal): Likewise.
+ * typeck.c (comptypes): Likewise.
+ (build_component_ref): Likewise.
+ (build_function_call_real): Likewise.
+ (build_binary_op_nodefault): Likewise.
+ (build_unary_op): Likewise.
+ (build_modify_expr): Likewise.
+ * typeck2.c (initializer_constant_valid_p): Likewise.
- * cvt.c (build_up_reference): Handle MIN_EXPR and MAX_EXPR.
+Sun Dec 21 15:59:00 1997 Nick Clifton <nickc@cygnus.com>
- * decl.c (grokdeclarator): Upgrade warning about &const to pedwarn.
+ * decl2.c (lang_decode_option): Add support for -Wunknown-pragmas.
-Sun Jan 15 22:17:32 1995 dcb@lovat.fmrco.COM (David Binderman)
+Thu Dec 18 14:51:50 1997 Mark Mitchell <mmitchell@usa.net>
- * pt.c (do_function_instantiation): Free targs once we're done.
+ * pt.c (coerce_template_parms): Make sure to digest_init if
+ possible.
-Sun Jan 15 22:17:32 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (duplicate_decls): Make the newdecl virtual if the
+ olddecl was, just as is done with other attributes of olddecl.
- * decl.c (BOOL_TYPE_SIZE): Defaults to BITS_PER_WORD.
- (init_decl_processing): Use BOOL_TYPE_SIZE instead of CHAR_TYPE_SIZE
- for bool.
+Thu Dec 18 14:43:19 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sat Jan 14 05:33:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * typeck.c (unary_complex_lvalue): Ignore op0 when taking the
+ address of an OFFSET_REF.
- * decl2.c (finish_file): We need to mess up if there are any
- variables in the list, not just if there is one with a constructor.
+ * cp-tree.def: Add AGGR_INIT_EXPR.
+ * error.c, tree.c, typeck.c: Replace uses of NEW_EXPR with
+ AGGR_INIT_EXPR where appropriate.
+ * expr.c (cplus_expand_expr): Likewise. Simplify.
-Fri Jan 13 14:42:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (finish_file): Remove call to register_exception_table.
- * decl.c (duplicate_decls): Propagate DECL_STATIC_{CON,DE}STRUCTOR.
- (finish_function): Handle DECL_STATIC_{CON,DE}STRUCTOR.
- (finish_function): Trust rest_of_compilation.
+Wed Dec 17 17:08:52 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * decl2.c (finish_file): Also call functions designated as static
- constructors/destructors.
+ * pt.c (instantiate_class_template): Don't do injection when
+ processing_template_decl is true, as pollutes current_binding_level
+ for base classes.
- * decl.c (grokdeclarator): Allow access decls of operator functions.
- (grokparms): Only do convert_for_initialization if the initializer
- has a type.
- (duplicate_decls): Put back push_obstacks_nochange call.
+Wed Dec 17 21:17:39 1997 Peter Schmid <schmid@ltoi.iap.physik.tu-darmstadt.de>
- * lex.c (real_yylex): Downgrade complaint about the escape sequence
- being too large from pedwarn to warning.
+ * pt.c (maybe_fold_nontype_arg): Add prototype.
- * decl.c (grokdeclarator): Don't complain about long long in system
- headers.
+Tue Dec 16 10:31:20 1997 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (real_yylex): Handle digraphs.
+ * tree.c (mapcar): Handle TRY_CATCH_EXPR et al.
+ * error.c (dump_expr): Likewise.
-Thu Jan 12 12:17:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Mon Dec 15 12:22:04 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (init_decl_processing): -f{no-,}strict-prototype only
- affects C linkage declarations now.
+ * typeck.c (build_function_call_real): Remove "inline called before
+ definition" pedwarn.
- * typeck.c (comp_target_types): Grok simple contravariant conversions.
- (common_type): t1 and t2 are interchangeable.
+ * pt.c (coerce_template_parms): Use maybe_fold_nontype_arg.
- * various: Test return value of comp_target_types differently in
- different places; it now returns -1 for a contravariant conversion
- (which is fine in symmetric cases).
+Sun Dec 14 22:34:20 1997 Jason Merrill <jason@yorick.cygnus.com>
- (common_type): Prefer long double to double even when
- they have the same precision.
+ * cvt.c (cp_convert_to_pointer): Fix base conversion of pm's.
- * decl.c (grokparms): Call convert_for_initialization to check
- default arguments.
+ * pt.c (type_unification_real): Change __null to type void* with
+ a warning.
- * init.c (build_new): void_type_node has a size (of 0).
+Sun Dec 14 20:38:35 1997 Mark Mitchell <mmitchell@usa.net>
- * decl.c (decls_match): Also check for agreement of TREE_READONLY
- and TREE_THIS_VOLATILE.
- (push_class_level_binding): Properly handle shadowing of
- nested tags by fields.
+ * call.c (implicit_conversion): Don't call
+ build_user_type_conversion_1 with a NULL expr, since it will
+ crash.
- * search.c (dfs_pushdecls): Ditto.
+ * pt.c (unify): Don't try to unify array bounds if either array is
+ unbounded.
- * decl2.c (finish_file): Don't second-guess self-initialization.
+Fri Dec 12 16:09:14 1997 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (convert_to_reference): Work with expr directly, rather than
- a copy.
+ * errfn.c (cp_pedwarn, cp_pedwarn_at, cp_error_at, cp_warning_at):
+ Replace extern decls with casts.
- * decl.c (push_overloaded_decl): Only shadow artificial TYPE_DECLs.
+ * decl.c (expand_start_early_try_stmts): Don't mess with a sequence.
+ Update last_parm_cleanup_insn.
+ (store_after_parms): Remove.
+ * cp-tree.h: Adjust.
- * init.c (add_friend): Downgrade duplicate friend message from
- pedwarn to warning.
+Thu Dec 11 22:18:37 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (duplicate_decls): Push obstacks before calling common_type.
+ * decl2.c (comdat_linkage): Also set DECL_COMDAT.
+ (finish_file): Check DECL_COMDAT instead of weak|one_only.
+ (import_export_vtable): Use make_decl_one_only instead of
+ comdat_linkage for win32 tweak.
+ (import_export_decl): Likewise.
+ * pt.c (mark_decl_instantiated): Likewise.
-Thu Jan 12 17:15:21 1995 Michael Ben-Gershon <mybg@cs.huji.ac.il>
+ * decl2.c (finish_file): Lose handling of templates in pending_statics.
- * except.c (push_eh_entry): set LABEL_PRESERVE_P flag for
- exception table labels.
- (expand_start_all_catch): Ditto.
- (expand_leftover_cleanups): Ditto.
- (expand_end_catch_block): Ditto.
- * except.c (make_first_label): new function.
- (expand_start_all_catch): add a call to make_first_label() before
- using a label as a jump destination.
- (expand_end_all_catch): Ditto.
- (expand_leftover_cleanups): Ditto.
- (expand_end_catch_block): Ditto.
- (expand_builtin_throw): Ditto.
- (expand_throw): Ditto.
- * except.c: Add ARM processor support for exception handling.
+Thu Dec 11 21:12:09 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jan 12 12:17:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (finish_file): Lose call to expand_builtin_throw.
+ * except.c (expand_builtin_throw): Remove.
+ * cp-tree.h: Remove ptr_ptr_type_node.
+ * decl.c: Likewise.
- (complete_array_type): Copy code from C frontend.
+Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
+
+ * decl.c (ptr_ptr_type_node): Define.
+ (init_decl_processing): Initialize it.
+ * cp-tree.h: Declare it.
+ * exception.cc (__cp_exception_info): Use __get_eh_info.
+ (__cp_push_exception): Ditto.
+ (__cp_pop_exception): Ditto.
- * lex.c (real_yylex): Don't multiply the length of a wide string
- literal by WCHAR_BYTES.
+ From Scott Snyder <snyder@d0sgif.fnal.gov>:
+ * except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
+ saved_pc.
+ (init_exception_processing): Removed saved_pc initialization.
- * decl.c (pushdecl): Check for redeclaration of wchar_t here.
- (duplicate_decls): Instead of here.
- (define_label): Complain about a label named wchar_t.
- (grokdeclarator): Complain about declarations of
- operator-function-ids as non-functions.
+Wed Dec 10 11:04:45 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (unary_complex_lvalue): Also wrap prefix -- and ++ in
- COMPOUND_EXPRs.
- (build_unary_op): Wrap unary plus in a NON_LVALUE_EXPR.
+ * pt.c (instantiate_decl): Defer all templates but inline functions.
- * lex.c (real_yylex): Don't skip whitespace when reading the next
- character after ->.
+Mon Dec 8 23:17:13 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jan 11 16:32:49 1995 Mike Stump <mrs@cygnus.com>
+ * init.c (expand_vec_init): Don't fold a list of parameters.
- * except.c: Allow cc1plus to be built with native compiler on rs6000.
- (expand_start_all_catch): Add assemble_external calls for various
- routines we call.
- (expand_leftover_cleanups): Ditto.
- (expand_start_catch_block): Ditto.
- (do_unwind): Ditto.
- (expand_builtin_throw): Ditto.
+ * decl.c (copy_args_p): Handle copy elision for types with virtual
+ bases.
+ * call.c (build_over_call): Likewise.
-Wed Jan 11 01:05:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Sun Dec 7 22:38:12 1997 Mark Mitchell <mmitchell@usa.net>
- * decl.c (pushtag): Only look for a previous decl in the current
- binding level. Use explicit global scope in DECL_NESTED_TYPENAME.
+ * pt.c (lookup_template_function): Copy the template arguments,
+ not just the list containing them, to the permanent obstack.
- * gxx.gperf: Add __signature__ and __sigof__ keywords.
+Sun Dec 7 15:53:06 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (lang_decode_option): -ansi does not set flag_no_asm. It
- does set flag_no_gnu_keywords and flag_operator_names.
+ * except.c (expand_start_catch_block): suspend_momentary for the
+ terminate handler.
- * lex.c (init_lex): 'overload' is not a keyword unless -traditional.
- Unset extension keywords if -fno-gnu-keywords.
- Allow operator names ('bitand') if -foperator-names.
- Never unset 'asm'; -fno-asm only affects 'typeof'.
+ * error.c (dump_decl): Handle LOOKUP_EXPR.
- * decl.c (lookup_name_real): The got_object special lookup only
- applies to types.
+Sun Dec 7 15:45:07 1997 Mark Mitchell <mmitchell@usa.net>
-Tue Jan 10 18:07:51 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * rtti.c (build_dynamic_cast): Copy the cast-to type to the
+ permanent obstack if we are processing a template decl.
+ * typeck.c (build_static_cast): Likewise.
+ (build_const_cast): Likewise.
+ (build_reinterpret_cast): Likewise.
- * spew.c (yylex): Also use DECL_NESTED_TYPENAME if got_object is set.
+ * pt.c (coerce_template_parms): Coerce some expressions, even
+ when processing_template_decl.
- * parse.y (primary): Unset got_object after all rules that use the
- 'object' nonterminal.
- (object): Set got_object.
+Sun Dec 7 01:46:33 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * lex.h: Declare got_object.
+ * typeck.c (build_binary_op_nodefault, pointer_diff): Symmetric
+ handling of pointer difference expressions.
- * decl.c (lookup_name_real): Also lookup names in the context of an
- object specified.
+ * typeck.c (comp_target_types): Comparison of function/method types
+ is independent of nptrs.
-Tue Jan 10 14:30:30 1995 Mike Stump <mrs@cygnus.com>
+Sun Dec 7 01:40:27 1997 Mark Mitchell <mmitchell@usa.net>
- * typeck.c (get_member_function_from_ptrfunc): Use ptrdiff_type_node
- for things that have to be added to pointers, not size_type. Cures
- problems with pointer to members on Alphas.
- (build_binary_op_nodefault): Ditto.
- (get_delta_difference_: Ditto.
- (build_ptrmemfunc): Ditto.
+ * pt.c (tsubst): Avoid creating pointer to reference and
+ reference to reference types.
-Tue Jan 10 01:49:25 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Sat Dec 6 01:29:37 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (pushtag): Stick the new decl in TYPE_NAME before pushing
- it.
+ * parse.y (do_id): New nonterminal.
+ (template_id): Use it.
- * typeck.c (build_component_ref): Don't build up a COMPONENT_REF
- when dealing with overloaded member functions; just act like
- build_offset_ref.
- (commonparms): Remove misleading comment.
+Fri Dec 5 01:17:34 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (duplicate_decls): Complain about repeated default
- arguments here.
- (redeclaration_error_message): Instead of here.
- (pushdecl): Complain about missing default arguments here.
- (grokparms): Instead of here.
- (lookup_name_current_level): Also match on DECL_ASSEMBLER_NAME.
- (grok_reference_init): Do not complain about missing initializer if
- declared 'extern'.
+ * parse.y (template_id): do_identifier for PFUNCNAMEs, too.
+ * spew.c (yylex): Don't do_identifier here.
+ * decl2.c (build_expr_from_tree): Revert last change.
- * search.c (lookup_field): Don't return a TYPE_DECL if there is a
- function alternative and want_type is not set.
+ * decl2.c (build_expr_from_tree): Expand the name for a method call.
+ * parse.y (object_template_id): Don't try to take the DECL_NAME.
-Mon Jan 9 18:16:23 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed Dec 3 20:02:39 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (pushtag): Don't set TYPE_NAME to an identifier. Do push
- the decl when the type has no TYPE_NAME.
- (lookup_nested_type): Don't assume that type has TYPE_NAME set.
- (lookup_name_real): Call lookup_field with want_type =
- prefer_type.
+ * init.c (build_new): Use a TARGET_EXPR instead of SAVE_EXPR for
+ alloc_expr.
+ * call.c (build_op_delete_call): Adjust.
- * search.c (lookup_field): Handle want_type properly in the presence
- of fields with the same name.
+ * except.c (expand_end_catch_block): Lose rethrow region.
+ (expand_start_catch_block): Likewise.
+ (expand_end_catch_block): Don't expand_leftover_cleanups.
- * decl.c (set_nested_typename): Set nested name for file-scope types
- to include leading ::.
- (pushdecl): Set the nested typename if the decl doesn't have one,
- rather than if the type's canonical decl doesn't have one.
+Wed Dec 3 13:24:04 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
-Mon Jan 9 16:48:16 1995 Steve Chamberlain (sac@jonny.cygnus.com)
+ * pt.c (tsubst): Remove tree_cons call (places redundant info into
+ DECL_TEMPLATE_INSTANTIATION).
- * typeck.c (pointer_int_sum): Use offset size when calculating
- index expression.
+Wed Dec 3 11:44:52 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Jan 9 03:44:33 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * tree.c (is_overloaded_fn): Handle getting a fn template.
+ (really_overloaded_fn): Likewise.
+ * error.c (dump_decl): Handle TEMPLATE_ID_EXPRs better.
+ * pt.c (check_explicit_specialization): Tweak.
+ (determine_explicit_specialization): Tweak.
- * typeck.c (convert_for_assignment): Complain about contravariance
- violation here.
- (comp_target_types): Instead of here.
- (build_unary_op): resolve_offset_ref before checking for a valid
- type.
+ * tree.c, cp-tree.h (get_target_expr): New fn.
- * spew.c (yylex): Decrement looking_for_typename after we see a
- _DEFN.
+Wed Dec 3 08:47:27 1997 Paul Eggert <eggert@twinsun.com>
- * decl.c (pushdecl): Don't install an artificial TYPE_DECL in
- IDENTIFIER_LOCAL_VALUE if we already have a decl with that name.
+ * pt.c (check_explicit_specialization): Fix misspelling in
+ diagnostic: `preceeded'.
+ * typeck.c (get_delta_difference): Fix misspelling in diagnostic:
+ `conversiona'.
- * typeck.c (convert_for_assignment): Converting pointers to bool
- does not need a cast.
+1997-12-02 Mark Mitchell <mmitchell@usa.net>
-Sun Jan 8 18:16:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (determine_explicit_specialization): Avoid an internal
+ error for bad specializations.
- * class.c (instantiate_type): Initialize nsubsts parm.
+ * method.c (build_overload_value): Handle SCOPE_REF.
- * pt.c (do_function_instantiation): Ditto.
+Tue Dec 2 19:18:50 1997 Mike Stump <mrs@wrs.com>
-Sat Jan 7 14:37:05 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * class.c (prepare_fresh_vtable): Enable even more complex MI
+ vtable names.
- * pt.c (tsubst): Use TREE_STATIC instead of DECL_INLINE &&
- DECL_SAVED_INSNS to determine whether or not we've seen a definition
- of this function.
- (instantiate_template): Ditto.
+Tue Dec 2 01:37:19 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (convert_harshness): Allow const reference binding when
- called from the overloading code, but not when called from
- can_convert (since it isn't a conversion).
- (convert_harshness): Put back some disabled code.
+ * exception.cc (__check_eh_spec): Optimize a bit.
-Fri Jan 6 14:10:57 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * exception.cc (__cp_pop_exception): Lose handler arg.
+ * except.c (do_pop_exception): Likewise.
+ (push_eh_cleanup): Let the cleanup mechanism supply the handler.
+ (expand_end_catch_block): Likewise.
- * call.c (convert_harshness): There is no implicit conversion from
- void* to other pointer types (unless the parameter is (void*)0).
- (convert_harshness): Non-lvalues do not convert to reference types.
+Fri Nov 28 01:58:14 1997 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct_methods): Still set
- TYPE_HAS_{INT,REAL}_CONVERSION.
+ * pt.c (check_explicit_specialization): Complain about using a
+ template-id for a non-specialization.
- * call.c (can_convert): Don't use aggregate initialization.
+Fri Nov 28 12:35:19 1997 Scott Christley <scottc@net-community.com>
- * cp-tree.h: Declare lookup_conversions.
+ * repo.c: Prototype rindex only if needed.
+ * xref.c: Likewise.
-Thu Jan 5 21:08:00 1995 Mike Stump <mrs@cygnus.com>
+Fri Nov 28 01:56:35 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * parse.y (simple_stmt): Fix duplicate case value error messages to
- be more readable.
+ * error.c (dump_decl): Handle TEMPLATE_ID_EXPR.
-Wed Jan 4 16:44:19 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Thu Nov 27 00:59:46 1997 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (build_type_conversion): Total rewrite to use
- convert_harshness instead of reproducing conversion logic here. Now
- much shorter.
+ * typeck.c (build_const_cast): Handle references here instead of
+ handing off to convert_to_reference.
- * call.c (convert_harshness): Support conversions to bool.
- (can_convert): Checks whether a conversion is less harsh
- than USER_CODE, for build_type_conversion.
+ * except.c: Lose Unexpected, SetTerminate, SetUnexpected,
+ TerminateFunctionCall.
+ (init_exception_processing): Likewise. Terminate et al are now
+ the fns, not ADDR_EXPRs.
+ (various): Lose redundant assemble_external calls.
+ (do_unwind): s/BuiltinReturnAddress/builtin_return_address_fndecl/.
- * search.c (add_conversions): Function for passing to dfs_walk which
- adds all the type conversion operators in the current type to a list.
- (lookup_conversions): Calls dfs_walk with add_conversions and return
- the list.
- (dfs_walk): Don't require a qfn.
+ * cp-tree.h (struct lang_decl_flags): Add comdat.
+ (DECL_COMDAT): New macro.
+ * decl.c (duplicate_decls): Propagate it.
+ (cp_finish_decl): Handle it.
+ * decl2.c (import_export_decl): Just set DECL_COMDAT on VAR_DECLs.
- * cp-tree.h: Lose CLASSTYPE_CONVERSIONS hackery.
- (CLASSTYPE_FIRST_CONVERSION): Points to elt 1 of CLASSTYPE_METHOD_VEC.
+ * class.c: Remove static pending_hard_virtuals.
+ (add_virtual_function): Take pointers to pending_virtuals
+ and pending_hard_virtuals.
+ (finish_struct_1): Pass them. Declare pending_hard_virtuals.
- * class.c (finish_struct_bits): Lose CLASSTYPE_CONVERSIONS hackery.
- (grow_method): A separate function for building onto the growing
- method vector.
- (finish_struct_methods): Use it. Put all type conversion operators
- right after the constructors. Perhaps we should sort the methods
- alphabetically?
+Wed Nov 26 20:28:49 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Jan 2 14:42:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (import_export_vtable): If we support one_only but not
+ weak symbols, mark instantiated template vtables one_only.
+ (import_export_decl): Likewise for tinfo functions.
+ (finish_vtable_vardecl): Also write out vtables from explicitly
+ instantiated template classes.
+ * pt.c (mark_class_instantiated): Revert last change.
- * call.c (build_method_call): Lose another misleading shortcut.
+ * except.c (expand_throw): Call mark_used on the destructor.
-Fri Dec 30 17:57:30 1994 Mike Stump <mrs@cygnus.com>
+Wed Nov 26 15:13:48 1997 Jeffrey A Law (law@cygnus.com)
- * gc.c (build_bltn_desc): Handle bool as a built-in type.
+ * lex.c (lang_init): Enable flag_exceptions by default if no
+ command line switch was specified.
-Fri Dec 30 14:20:21 1994 Mike Stump <mrs@cygnus.com>
+1997-11-26 Mark Mitchell <mmitchell@usa.net>
- * tree.c (layout_vbasetypes): Ensure that we don't loose alignment
- on the complete type because of small virtual bases.
+ * pt.c (unify): Handle `void' template parameters in
+ specializations.
-Fri Dec 30 12:22:29 1994 Mike Stump <mrs@cygnus.com>
+Wed Nov 26 01:11:24 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (n_incomplete): Bump n_incomplete up to int to match C
- front end.
- (pushdecl): Also count decls pushed that are of a type being defined
- as incomplete things.
- * class.c (finish_struct): Move hack_incomplete_structures up to
- just after we set it as not being defined, so that the decls we
- build for RTTI don't count as incomplete.
+ * rtti.c (build_dynamic_cast): Handle template case here.
+ (build_dynamic_cast_1): Not here.
-Thu Dec 29 18:20:57 1994 Mike Stump <mrs@cygnus.com>
+ * typeck2.c (digest_init): Make copies where appropriate.
- * pt.c (tsubst): Fix problem with defining constructors in templated
- classes with virtual bases.
+ * decl2.c (delete_sanity): resolve_offset_ref.
-Wed Dec 28 08:31:00 1994 Mike Stump <mrs@cygnus.com>
+ * except.c: Call terminate without caching so many bits.
- * parse.y (TYPEID): Strip top-level cv-qualifiers on typeid
- expressions.
- * gc.c (build_typeid): Ditto.
+ * except.c (expand_start_catch_block): Fix catching a reference
+ to pointer.
-Thu Dec 22 17:26:33 1994 Mike Stump <mrs@cygnus.com>
+Tue Nov 25 11:28:21 1997 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (build_up_reference): Fix breakage introduced on Nov 29,
- don't assert on complex AGGR inits.
+ * init.c (build_new): Copy size to the saveable obstack.
-Thu Dec 22 14:32:31 1994 Mike Stump <mrs@cygnus.com>
+ * init.c (build_new): Stick a CLEANUP_POINT_EXPR inside the
+ TRY_CATCH_EXPR for now.
- * method.c (build_overload_value): Handle pointer to members as
- template arguments.
+Mon Nov 24 12:15:55 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Dec 22 13:09:07 1994 Mike Stump <mrs@cygnus.com>
+ * typeck.c (mark_addressable): Don't assume a FUNCTION_DECL
+ has DECL_LANG_SPECIFIC.
- * typeck.c (unary_complex_lvalue): Don't call sorry if we know how
- to do take the address of a data member for a pointer to data
- member.
+ * exception.cc (struct cp_eh_info): Add handlers field.
+ (__cp_push_exception): Initialize it.
+ (__cp_pop_exception): Decrement it. Don't pop unless it's 0.
+ (__throw_bad_exception): Remove.
+ * except.c (call_eh_info): Add handlers field.
+ (get_eh_handlers): New fn.
+ (push_eh_cleanup): Increment handlers.
-Thu Dec 22 10:04:19 1994 Mike Stump <mrs@cygnus.com>
+Fri Nov 21 12:22:07 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Use the typedef name for linkage if the
- type doesn't otherwise have a name.
+ * except.c (expand_start_eh_spec): Use the try/catch code.
+ (expand_end_eh_spec): Likewise. Call __check_eh_spec instead of
+ doing everything inline.
+ (init_exception_processing): throw_type_match now takes
+ const void pointers.
+ * exception.cc (__check_eh_spec): New fn.
+ * inc/exception: Neither terminate nor unexpected return.
+ * decl.c: Make const_ptr_type_node public.
+ * tinfo2.cc (__throw_type_match_rtti): Take the typeinfos constly.
- * decl2.c (grokfield): Ditto.
+ * except.c (expand_start_catch_block): We only need the rethrow
+ region for non-sjlj exceptions.
+ (expand_end_catch_block): Likewise. Use outer_context_label_stack.
- * class.c (finish_struct): Since we reuse the TYPE_DECL for the
- DECL_NAME of enums, structs and classes, we have to avoid trying to
- put it in the TYPE_FIELDS again.
+Thu Nov 20 14:40:17 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Dec 21 11:07:05 1994 Mike Stump <mrs@cygnus.com>
+ * Make-lang.in (CXX_LIB2FUNCS): Add new op new and op delete objs.
+ (various.o): Likewise.
+ * inc/new: Add placement deletes. Add throw specs for default new.
+ * new.cc (set_new_handler): Move here from libgcc2.
+ * new1.cc (new (nothrow)): Catch a bad_alloc thrown from the handler.
+ (new): Move from libgcc2. Throw bad_alloc.
+ * new2.cc: Move the rest of the op news and op deletes from libgcc2.
+ * decl.c (init_decl_processing): Update exception specs on new and
+ delete.
- * decl2.c (check_classfn): Ignore this parameter on static functions
- when checking to see if we match.
+ * method.c (build_decl_overload_real): Don't mess with global
+ placement delete.
-Tue Dec 20 17:47:02 1994 Mike Stump <mrs@cygnus.com>
+ * init.c (build_new): Check for null throw spec, not nothrow_t.
- * typeck.c (unary_complex_lvalue): Handle address of non-left most
- pointers to members by calling get_delta_difference.
+ * decl.c (duplicate_decls): Don't complain about different exceptions
+ from an internal declaration.
-Mon Dec 19 22:40:53 1994 Mike Stump <mrs@cygnus.com>
+ * call.c (build_op_delete_call): Fix check for member fns again.
- * decl2.c (check_classfn): Don't use decls_match yet, as it modifies
- static functions to early.
+ * decl2.c (import_export_decl): Interface hackery affects
+ virtual synthesized methods.
-Thu Dec 19 22:37:48 1994 Mike Stump <mrs@cygnus.com>
+Wed Nov 19 18:24:14 1997 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (make_thunk): Handle encoding of positive thunk offsets.
+ * decl.c (start_decl): Don't just complain about a mismatched
+ scope, fix it.
-Sat Dec 17 13:29:50 1994 Doug Evans <dje@canuck.cygnus.com>
+ * decl.c (make_implicit_typename): Handle case where t is not
+ actually from context.
+ * tree.c (get_type_decl): Lose identifier case.
+ * spew.c (yylex): Lose useless call to identifer_typedecl_value.
+ * parse.y (nonnested_type): Just use lookup_name.
+ (complex_type_name): Just use IDENTIFIER_GLOBAL_VALUE.
- * Make-lang.in (.PHONY): Tell GNU make C++ and c++ are phony targets.
+Wed Nov 19 11:45:07 1997 Michael Tiemann <tiemann@axon.cygnus.com>
-Thu Dec 15 16:32:12 1994 Mike Stump <mrs@cygnus.com>
+ * error.c (dump_function_name): Test DECL_LANG_SPECIFIC in case
+ T was built in C language context (for example, by
+ output_func_start_profiler).
- * decl2.c (check_classfn): Use decls_match to check if this has
- already been declared, as the DECL_ASSEMBLER_NAME may have been
- changed via asm("new_name").
- * decl.c (decls_match): Make public.
+Wed Nov 19 10:39:27 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Dec 15 15:17:55 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (make_implicit_typename): New fn.
+ (lookup_name_real): Use it. Use current_class_type as the context.
- * *.[chy] (expand_aggr_init) Add fourth argument to handle
- distinction between = init and (init) style of initializations.
- * *.[chy] (finish_decl): Add fifth argument to to handle
- distinction between = init and (init) style of initializations.
+Mon Nov 17 23:42:03 1997 Bruno Haible <haible@ilog.fr>
-Tue Dec 13 19:16:05 1994 Mike Stump <mrs@cygnus.com>
+ * pt.c (do_poplevel): Don't prohibit jumps into this contour.
- Fix some random `explicit' bugs.
+Mon Nov 17 02:01:28 1997 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (convert_to_reference): Add third parameter to
- convert_force.
- (convert_force): Ditto.
- * call.c (build_method_call): Ditto.
- * decl2.c (setup_vtbl_ptr): Ditto.
- * init.c (expand_virtual_init): Ditto.
- (build_member_call): Ditto.
- (build_delete): Ditto.
- (build_vbase_delete): Ditto.
- * typeck.c (build_component_addr): Ditto.
- (build_c_cast): Ditto.
- (build_modify_expr): Ditto.
- * cp-tree.h (CONV_NONCONVERTING): Ditto. Add so that we can
- distinguish the context in which the conversion appears. Add thrid
- argument to build_c_cast.
- * cvt.c (cp_convert): Pass whether or not we want to consider
- non-converting constructors down to build_method_call.
- * decl2.c (reparse_absdcl_as_casts): Add third argument to
- build_c_cast.
- * gc.c (build_m_desc): Ditto.
- * init.c (build_new): Ditto.
- * parse.y (expr_no_commas): Ditto.
- (primary): Ditto.
- * typeck.c (build_x_function_call): Ditto.
- (build_static_cast): Ditto.
- (build_reinterpret_cast): Ditto.
- (build_const_cast): Ditto.
- (build_c_cast): Ditto.
- (build_ptrmemfunc): Ditto.
- * typeck2.c (build_functional_cast): Ditto.
- * init.c (expand_aggr_init): Added LOOKUP_ONLYCONVERTING to
- expand_aggr_init_1 as inits are converted to the destination type.
+ * friend.c (do_friend): Warn about non-template friends in templates.
-Tue Dec 13 16:18:57 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (build_op_delete_call): Fix handling of inherited delete.
- * Make-lang.in (cc1plus): Depends on c-pragma.o.
+ * search.c (dfs_record_inheritance): Ignore template type parms.
- * Makefile.in (OBJ{DEP,}S): Add ../c-pragma.o.
+Sat Nov 15 00:30:51 1997 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (check_newline): If the #pragma is not recognized by g++,
- try machine-specific ones too.
- (handle_sysv_pragma): Copied from c-lex.c.
+ * call.c (build_new_op): Fix copy error.
+ (build_op_new_call): New fn.
+ (build_op_delete_call): New fn.
+ * cp-tree.h: Declare them.
+ * init.c (build_new): Use them. Support placement delete.
+ (build_x_delete): Use build_op_delete_call.
+ (build_delete): Likewise.
+ * decl2.c (delete_sanity): Likewise.
+ (coerce_delete_type): Don't complain about placement delete.
-Mon Dec 12 23:53:06 1994 Mike Stump <mrs@cygnus.com>
+Thu Nov 13 01:52:36 1997 Jason Merrill <jason@yorick.cygnus.com>
- * except.c (expand_throw): Fix Dec 6th change, build_new likes a
- reference better.
+ * call.c (build_new_function_call): Remove unused 'obj' parm.
+ * cp-tree.h, typeck.c: Adjust.
-Mon Dec 12 18:01:00 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * init.c (build_new): Make the cleanup last longer.
+ (expand_vec_init): Call do_pending_stack_adjust.
- * typeck.c (build_binary_op): Lose checks on TYPE_PTRMEMFUNC_P with
- IS_AGGR_TYPE, since now they will not both be set on the same type.
+Wed Nov 12 11:04:33 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (do_pending_expansions): Don't clear TREE_PUBLIC on
- instantiations controlled by -fexternal-templates.
+ * pt.c (do_type_instantiation): Fix typo.
+ (mark_class_instantiated): If we support one_only but not weak
+ symbols, don't mark this as known.
- * decl.c (duplicate_decls): Don't complain about different values of
- __attribute__ ((const)) and ((noreturn)).
+ * init.c (build_new): Handle vec delete in EH cleanup.
-Fri Dec 9 18:17:37 1994 Doug Evans <dje@cygnus.com>
+Wed Nov 12 08:11:55 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * Makefile.in (BISONFLAGS): Delete --yacc.
- (PARSE_H): Depend on $(PARSE_C), for parallel makes.
- (PARSE_C): Undo last patch.
+ * call.c (build_method_call): Call complete_type before checking
+ for destructor.
-Fri Dec 2 10:44:36 1994 Mike Stump (mrs@wombat.gnu.ai.mit.edu)
+Sun Nov 9 01:29:55 1997 Jim Wilson (wilson@cygnus.com)
- * Makefile.in (BISONFLAGS): Add --yacc so that output winds up in
- y.tab.c.
+ * decl.c (add_block_current_level): Delete.
+ * init.c (build_vec_delete_1): Delete build_block and
+ add_block_current_level calls.
-Thu Dec 8 17:39:46 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed Nov 12 00:48:16 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (finish_decl): Don't call obscure_complex_init for decls
- of indeterminate size.
+ * init.c (build_new): Handle freeing allocated memory when the
+ constructor throws.
-Wed Dec 7 16:49:22 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (build_new_method_call): Fix flags arg.
- * decl.c (obscure_complex_init): Function to tweak the decl to
- prevent expand_decl from tring to initialize it.
- (finish_decl): Use it rather than writing the same code in three
- different places.
+ * pt.c (do_type_instantiation): Don't try to instantiate
+ member templates.
+ (mark_decl_instantiated): If we support one_only but not
+ weak symbols, mark this one_only.
+ * decl2.c (import_export_vtable): Don't defer handling of vtables
+ if MULTIPLE_SYMBOL_SPACES.
- * parse.y (bad_parm): Stop trying to support parms without types.
+Tue Nov 11 12:02:12 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Dec 7 12:06:56 1994 Mike Stump <mrs@cygnus.com>
+ * except.c (expand_end_catch_block): Lose call to __sjpopnthrow.
- * decl2.c (grokfield): Make asm specs on static member functions
- work.
+Tue Nov 11 02:53:44 1997 Jason Merrill <jason@lasher.cygnus.com>
-Tue Dec 6 15:43:20 1994 Mike Stump <mrs@cygnus.com>
+ * except.c (do_pop_exception): Return a value.
- * except.c (expand_throw): Make a copy of the thrown object.
+Mon Nov 10 20:25:31 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue Dec 6 14:16:34 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (build_new_method_call): Handle getting a
+ TEMPLATE_ID_EXPR around a TEMPLATE_DECL. Don't look for a field
+ if we got template parms.
+ * typeck.c (build_x_function_call): Remember the TEMPLATE_ID_EXPR,
+ not just the args.
+ * decl2.c (build_expr_from_tree): Tweak last change.
+ * pt.c (tsubst_copy): Use get_first_fn instead of TREE_VALUE.
+ (maybe_fold_nontype_arg): Split out from tsubst_copy.
+ * tree.c (get_first_fn): Just return a TEMPLATE_ID_EXPR.
- * parse.y: : has lower precedence than =.
+Mon Nov 10 20:08:38 1997 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
-Tue Dec 6 12:46:17 1994 Mike Stump <mrs@cygnus.com>
+ * pt.c (tsubst_copy): Handle explicit template arguments in
+ function calls.
+ * typeck.c (build_x_function_call): Likewise.
+ * decl2.c (build_expr_from_tree): Lookup function name if it
+ hasn't been done.
- * decl.c (pushdecl): Use DECL_NAME of VAR_DECLs to avoid namespace
- manglings.
- (grokvardecl): Add namespace into variable name.
+ * pt.c (tsubst): Instantiate template functions properly when
+ template parameter does not appear in function arguments and return
+ type.
+ (comp_template_args): Handle member templates required by tsubst.
-Tue Dec 6 11:26:55 1994 Mike Stump <mrs@cygnus.com>
+Mon Nov 10 20:08:38 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (current_namespace_id): New routine to transform a simple
- name into a name in a namespace.
- * decl.c (grokdeclarator): Use it.
- * decl2.c (get_namespace_id): Find the name of the current
- namespace.
- (push_namespace, pop_namespace): Complete out missing
- functionality.
-
-Mon Dec 5 17:11:51 1994 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * class.c (finish_struct): Don't use LONG_LONG_TYPE_SIZE, as it may
- not be defined. Fix warning message for enums and restore warning
- for non-enums.
-
- * decl2.c (push_namespace): Dummy function.
- (pop_namespace): Ditto.
- (do_namespace_alias): Ditto.
- (do_using_decl): Ditto.
- (do_using_directive): Ditto.
-
- * parse.y: New token NSNAME for namespace names.
- (extdef): Add namespace, using definitions.
- (using_decl): New rule for using declarations.
- (any_id): New rule for identifiers with any degree of scoping.
- (identifier): Add NSNAME.
- (notype_identifier): Ditto.
- (component_decl): Add using_decl.
- (nested_name_specifier): Add NSNAME SCOPE.
-
- * typeck.c (convert_for_assignment): Handle conversions between
- enums and bool.
-
- * decl.c (duplicate_decls): Only propagate DECL_MAIN_VARIANT on
- FUNCTION_DECLs.
+ * decl.c (grokdeclarator): Tweak conditions for pedwarn in
+ previous change.
-Mon Dec 5 13:03:16 1994 Mike Stump <mrs@cygnus.com>
+Mon Nov 10 20:08:29 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * class.c (finish_struct): Give an error if one tries to declare a
- bit-field's size greater than a long long, as the backend will dump.
- It is not an error to declare an enum bit-field greater than its
- precision. Warn if an enum bit-field is too small to hold all
- its values.
+ * pt.c (coerce_template_parms): Tweak error message.
-Mon Dec 5 11:41:50 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (grokdeclarator): If -Wreturn-type, warn everytime a
+ return type defaults to `int', even if there are storage-class
+ specifiers.
- * typeck.c (convert_for_assignment): Use cp_convert instead of
- convert so that we don't get static casts.
+Mon Nov 10 03:04:20 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sun Dec 4 11:59:01 1994 Mike Stump <mrs@cygnus.com>
+ Complete nested exception support.
+ * except.c (do_pop_exception): Split out...
+ (push_eh_cleanup): From here. Handle the EH region by hand.
+ (expand_start_catch_block): Add a new level for the catch parm.
+ Move the rethrow region outside the two cleanup regions.
+ Protect the initializer for the catch parm with terminate.
+ (expand_end_catch_block): Likewise. End the region for the eh_cleanup.
+ * exception.cc (__cp_pop_exception): Now takes two parms. Handle
+ popping off the middle of the stack.
+ * tree.c (lvalue_p, real_lvalue_p): Handle TRY_CATCH_EXPR,
+ WITH_CLEANUP_EXPR, and UNSAVE_EXPR.
+ (build_cplus_new): Only wrap CALL_EXPRs.
+ * init.c (expand_default_init): Handle a TRY_CATCH_EXPR around
+ the constructor call.
- * cvt.c (cp_convert): Don't complain about int->enum conversion if
- we are doing static casts.
+Sun Nov 9 18:00:26 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
-Fri Dec 2 18:32:41 1994 Mike Stump <mrs@cygnus.com>
+ * Make-lang.in (c++.distdir): Make inc subdirectory.
- * error.c (dump_expr): Do something more intelligent with SAVE_EXPRs
- when dumping expressions in error messages.
+Fri Nov 7 11:57:28 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Dec 2 17:04:27 1994 Mike Stump <mrs@cygnus.com>
+ * decl2.c (finish_file): Put back some code.
- * gc.c (build_dynamic_cast): Change interface to libg++, ensure that
- the return type is the right type, and make references work.
+Thu Nov 6 11:28:14 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Dec 2 16:36:43 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (finish_file): Remove redundant code.
+ * method.c (emit_thunk): Don't let the backend defer generic thunks.
- * decl.c (poplevel): Don't be confused by function-scope
- declarations of non-nested functions.
- (duplicate_decls): Propagate DECL_MAIN_VARIANT.
- (pushdecl): Use duplicate_decls to copy info from old decl into new
- function-scope one rather than doing it here.
+Wed Nov 5 23:52:50 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (mark_inline_for_output): Deal with the DECL_MAIN_VARIANT
- of this decl, in case this is a function-scope declaration.
+ * except.c (call_eh_info): Split out...
+ (push_eh_info): From here.
+ (expand_builtin_throw): Use it.
+ (expand_start_catch_block): Move region start back.
- * decl.c (finish_enum): Make sure that the type has the right
- precision when we call fixup_*_type.
+Tue Nov 4 13:45:10 1997 Doug Evans <devans@canuck.cygnus.com>
-Tue Nov 29 19:12:07 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * lex.c (MULTIBYTE_CHARS): #undef if cross compiling.
+ (real_yylex): Record wide strings using target endianness, not host.
- * cvt.c (build_up_reference): Strip superfluous NOP_EXPRs; we do
- want to build up references to rvalues if possible.
- (cp_convert): Stick on a NOP_EXPR when converting to the same type.
+1997-11-03 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue Nov 29 11:28:59 1994 Mike Stump <mrs@cygnus.com>
+ * repo.c (rindex): Add decl unconditionally.
+ (get_base_filename, open_repo_file): Don't cast rindex.
+ * xref.c (rindex): Add decl unconditionally.
+ (index): Remove unused decl.
+ (open_xref_file): Don't cast rindex.
- * parse.y (maybe_raises): Handle throw ().
- * parse.y (ansi_raise_identifier): grok type-ids in exception
- specifications.
- * tree.c (build_exception_variant): Use list compare to check if
- two exception specifications match.
- * decl.c (duplicate_decls, bad_specifiers): Enhance wording on error
- messages.
- * call.c (build_method_call): Remove TREE_RAISES.
- * cvt.c (convert_to_aggr): Ditto.
- * typeck.c (build_function_call_real, convert_arguments): Ditto.
- * init.c (expand_aggr_init_1): Ditto.
+Sun Nov 2 15:04:12 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue Nov 29 09:50:39 1994 Mike Stump <mrs@cygnus.com>
+ * class.c (build_vbase_path): Propagate the result type properly.
- * except.c: Add support for m68k and mips exception handling
- support.
+1997-11-01 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue Nov 29 08:48:33 1994 Mike Stump <mrs@cygnus.com>
+ * except.c (expand_builtin_throw) [!DWARF2_UNWIND_INFO]: Replace
+ remaining use of saved_throw_type with a call to get_eh_type.
- * except.c (expand_end_all_catch): Throw into outer context, if we
- fall off end of catch handlers.
+1997-10-31 Brendan Kehoe <brendan@lisa.cygnus.com>
-Mon Nov 28 16:44:41 1994 Mike Stump <mrs@cygnus.com>
+ * lex.c (FILE_NAME_NONDIRECTORY): Delete macro.
+ (file_name_nondirectory): New function, doing the same as the macro.
+ (set_typedecl_interface_info): Use it instead of the macro.
+ (check_newline): Likewise.
+ (handle_cp_pragma): Likewise.
- * Makefile.in: Make is easier to decide where parse.[ch] will be
- built.
+ * repo.c (get_base_filename): Cast result of rindex to char*.
+ (open_repo_file): Likewise.
+ * xref.c (open_xref_file): Likewise.
+ * error.c (dump_char): Make its arg int, not char.
-Thu Nov 17 20:11:24 1994 Doug Evans <dje@cygnus.com>
+ * except.c (push_eh_info): Pass the number of fields - 1 down, not
+ the exact number of fields.
- * cp/Make-lang.in (CXX_INSTALL_NAME) Use program_transform_name.
- (GXX_INSTALL_NAME) Likewise.
- (CXX_CROSS_NAME) Use program_transform_cross_name.
- (GXX_CROSS_NAME) Likewise.
- (c++.install-man): Use program_transform_name on g++.1.
- (c++.uninstall): Likewise.
+Fri Oct 31 01:47:57 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Nov 3 18:48:19 1994 Paul Eggert <eggert@twinsun.com>
+ Support for nested exceptions.
+ * tinfo2.cc (__is_pointer): New fn.
+ * exception.cc (struct cp_eh_info): Define.
+ (__cp_exception_info, __uncatch_exception): New fns.
+ (__cp_push_exception, __cp_pop_exception): New fns.
+ * except.c: Lose saved_throw_{type,value,cleanup,in_catch}.
+ Lose empty_fndecl.
+ (init_exception_processing): Likewise. __eh_pc is now external.
+ (push_eh_info): New fn.
+ (get_eh_{info,value,type,caught}): New fns.
+ (push_eh_cleanup): Just call __cp_pop_exception.
+ (expand_start_catch_block): Use push_eh_info. Start the eh region
+ sooner.
+ (expand_end_eh_spec): Use push_eh_info.
+ (expand_throw): Call __cp_push_exception to set up the exception info.
+ Just pass the destructor or 0 as the cleanup. Call __uncatch_exception
+ when we rethrow.
+ (expand_builtin_throw): Don't refer to empty_fndecl.
- * Makefile.in (spew.o, lex.o, pt.o):
- Depend on $(srcdir)/parse.h, not parse.h.
+Thu Oct 23 02:01:30 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Nov 28 13:53:03 1994 Mike Stump <mrs@cygnus.com>
+ * pt.c (instantiate_decl): SET_DECL_IMPLICIT_INSTANTIATION on new decl.
- * parse.y (THROW): Fix precedence of throw expressions.
+1997-10-22 Brendan Kehoe <brendan@cygnus.com>
-Mon Nov 28 13:15:16 1994 Mike Stump <mrs@cygnus.com>
+ * method.c (build_template_parm_names, build_decl_overload_real):
+ Add static to definitions.
+ * pt.c (add_to_template_args, note_template_header,
+ processing_explicit_specialization, type_unification_real): Likewise.
+ ({determine,check}_explicit_specialization): Use a single string for
+ error messages.
- * typeck.c (build_unary_op): Allow promotions from bool to int on
- unary ~.
+Mon Oct 20 12:06:34 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sun Nov 27 00:16:21 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * except.c (expand_exception_blocks): Call do_pending_stack_adust.
+ (expand_end_catch_block): Likewise.
+ (expand_end_eh_spec): Likewise.
- * method.c (build_overload_name): Use DECL_ASSEMBLER_NAME for
- classes when appropriate.
- (build_overload_nested_name): When dealing with a function context,
- use ASM_FORMAT_PRIVATE_NAME to tweak the name of the function to
- avoid conflicts between local classes of the same name.
+Mon Oct 20 11:44:20 1997 Mark Mitchell <mmitchell@usa.net>
-Wed Nov 23 17:59:42 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (duplicate_decls): Handle template specializations
+ correctly.
+ * error.c (dump_function_name): Fix printing of specializations of
+ member functions that are not member templates.
+ * cp-tree.h (processing_specialization): Make global.
+ * pt.c (processing_specialization): Likewise.
+ * lex.c (cons_up_default_function): Save and restore
+ processing_specialization to avoid confusion.
+
+Mon Oct 20 10:52:22 1997 Jason Merrill <jason@yorick.cygnus.com>
- * gxx.gperf, parse.y, lex.h, hash.h, lex.c (init_lex), delc.c
- (duplicate_decls, grokdeclarator), cp-tree.h: Add support for
- `explicit'.
- * cvt.c (convert_to_reference, cp_convert, build_type_conversion_1,
- build_type_conversion): Use LOOKUP_ONLYCONVERTING in
- build_method_calls so that non-converting constructors are not used.
- * call.c (build_method_call): If we shouldn't use a non-converting
- constructor, then don't.
+ * decl.c (init_decl_processing): Give null_node unknown* type.
+ * typeck.c (comp_target_types): Handle UNKNOWN_TYPE.
+ (common_type): Likewise.
+ * error.c (args_as_string): Recognize null_node.
-Wed Nov 23 14:46:56 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+Sun Oct 19 09:13:01 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
- * call.c (build_method_call): Don't try to synthesize methods yet.
+ * typeck.c (rationalize_conditional_expr): Handle {MIN,MAX}_EXPR.
+ (unary_complex_lvalue): Call it for {MIN,MAX}_EXPR.
-Tue Nov 22 12:45:21 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (init_decl_processing): Call using_eh_for_cleanups.
- * pt.c (push_template_decls): Create CONST_DECLs for template
- constant parameters, not VAR_DECLs.
+ * Make-lang.in (g++): Include prefix.o.
-Sat Nov 19 15:28:31 1994 Jim Wilson (wilson@chestnut.cygnus.com)
+Thu Oct 16 15:31:09 1997 Judy Goldberg <judygold@sanwafp.com>
- * typeck.c (build_binary_op_nodefault): Can shorten shift only if
- shift count is less than size in bits of arg0.
+ * pt.c (determine_explicit_specialization): Initialize "dummy"
+ to keep Purify quiet.
-Thu Nov 17 15:30:50 1994 Mike Stump <mrs@cygnus.com>
+Thu Oct 16 00:14:48 1997 Jason Merrill <jason@yorick.cygnus.com>
- * gxx.gperf, hash.h, lex.c (init_lex, real_yylex), parse.y: Add new
- ANSI keywords and, and_eq, bitand, bitor, explicit, namespace, not,
- not_eq, or, or_eq, typename, using, xor, xor_eq to g++. Still need
- to add support for explicit, namespace, typename, and using, support
- for the rest is already in.
+ * method.c (build_overload_value): Handle TEMPLATE_CONST_PARMs here.
+ (build_overload_int): Not here.
-Thu Nov 17 10:56:50 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed Oct 15 00:35:28 1997 Mike Stump <mrs@wrs.com>
- * typeck2.c (build_m_component_ref): Check the basetype of the
- member pointer against the main variant of the object type.
+ * class.c (build_type_pathname): Remove.
+ (prepare_fresh_vtable): Fix problem with complex MI vtable names.
-Mon Nov 14 14:21:52 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+1997-10-14 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cvt.c (convert_to_reference): Make sure that the original expr
- gets its type back when converting a reference.
+ * parse.y (unary_expr): Give a pedwarn if someone tries to use the
+ &&label GNU extension.
- * method.c (build_overload_name): Clear numeric_outputed_need_bar here.
- (build_decl_overload): Instead of here.
+Tue Oct 14 12:01:00 1997 Mark Mitchell <mmitchell@usa.net>
-Tue Nov 8 17:11:24 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (pushtag): Unset DECL_ASSEMBLER_NAME before setting it,
+ so as to avoid incorrect manglings.
+ * method.c (build_decl_overload_real): Don't mangle return types
+ for constructors.
+
+Tue Oct 14 11:46:14 1997 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (cp_convert): Don't build a TARGET_EXPR if we're not in a
- function.
+ * cp-tree.h (scratchalloc, build_scratch_list, make_scratch_vec,
+ scratch_tree_cons): Define as macros for now.
+ * call.c, class.c, cvt.c, decl.c, decl2.c, except.c, expr.c, init.c,
+ lex.c, method.c, parse.y, pt.c, rtti.c, search.c, tree.c, typeck.c,
+ typeck2.c: Use them and the expression_obstack variants.
- * typeck.c (convert_for_initialization): Handle initialization from
- a TARGET_EXPR.
+Mon Oct 13 17:41:26 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
-Sun Nov 6 01:34:24 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * decl.c (store_return_init): Allow classes with explicit ctors to
+ be used with the named return values extension.
- * pt.c (lookup_nested_type_by_name): Fix list-walking logic.
- (tsubst): When replacing a TEMPLATE_TYPE_PARM, propagate
- TYPE_READONLY and TYPE_VOLATILE from the argument.
- (unify): When unifying with a TEMPLATE_TYPE_PARM, remove cv-quals
- present in parm from arg.
- (type_unification): Strip REFERENCE_TYPE from the argument type.
- (unify): Don't strip REFERENCE_TYPE from the argument type.
+Fri Oct 10 12:21:11 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sat Nov 5 22:42:15 1994 Greg McGary (gkm@magilla.cichlid.com)
+ * pt.c (instantiate_decl): Fix previous change.
- * pt.c (do_type_instantiation): Check to see if there's a
- IDENTIFIER_TEMPLATE on a class before calling
- instantiate_member_templates().
+Thu Oct 9 12:08:21 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Nov 4 19:04:18 1994 Mike Stump <mrs@cygnus.com>
+ * pt.c (tsubst): Fix thinko.
+ (instantiate_decl): Really use the original template.
- * gc.c (get_bad_cast_node): New routine to support compile time
- throws of bad_cast.
- * gc.c (build_dynamic_cast): Support throwing of bad_cast at compile
- time.
+ * call.c (build_new_method_call): Use simple constructor_name for
+ error messages.
-Fri Nov 4 11:12:00 1994 Mike Stump <mrs@cygnus.com>
+Wed Oct 8 22:44:42 1997 Jeffrey A Law (law@cygnus.com)
- * except.c: Add hppa support.
+ * method.c (build_underscore_int): Don't use ANSI specific
+ features.
-Fri Nov 4 10:50:50 1994 Mike Stump <mrs@cygnus.com>
+Wed Oct 8 00:18:22 1997 Jason Merrill <jason@yorick.cygnus.com>
- * except.c: Add rs6000 support.
+ * decl2.c (finish_prevtable_vardecl): Check DECL_REALLY_EXTERN
+ for our key method; it might have been inlined by -O3.
-Thu Nov 3 14:24:23 1994 Mike Stump <mrs@cygnus.com>
+Tue Oct 7 23:00:12 1997 Mark Mitchell <mmitchell@usa.net>
- * except.c (do_unwind): Add i[34]86 support.
+ * decl.c (make_typename_type): Do not try to call lookup_field for
+ non-aggregate types.
-Thu Nov 3 00:10:46 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+Tue Oct 7 22:52:10 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (do_pending_expansions): Unset TREE_PUBLIC on implicit
- instantiations.
+ * typeck.c (build_reinterpret_cast): Tweak.
-Wed Nov 2 15:08:24 1994 Kung Hsu (kung@mexican.cygnus.com)
+Tue Oct 7 22:45:31 1997 Alexandre Oliva <oliva@dcc.unicamp.br>
- * decl.c (finish_function): emit types used in method parameters
- into symbol table.
+ * typeck.c (build_reinterpret_cast): converting a void pointer
+ to function pointer with a reinterpret_cast produces a warning
+ if -pedantic is issued
-Wed Nov 2 15:05:47 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+Tue Oct 7 22:43:43 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * pt.c (process_template_parm): Allow pointer to member function
- template parameter types.
- (uses_template_parms): Handle pointer to member function
- CONSTRUCTORs.
+ * typeck.c (c_expand_return): Don't warn about returning a
+ reference-type variable as a reference.
- * g++.c (main): Cast first argument of bzero to (char *).
- Pass -lstdc++ instead of -lg++ unless we are invoked as 'g++'.
+Tue Oct 7 21:11:22 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Oct 31 14:50:48 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * method.c (build_static_name): Fix typo.
- * gc.c (build_dynamic_cast): rewrite to make it work.
- * class.c (finish_vtbls): build more vtables if flag_rtti is on.
- * class.c (modify_all_direct_vtables): ditto.
- * init.c (expand_direct_vtbls_init): expand more vtables if
- flag_rtti is on.
- * decl.c (init_type_desc): add default return.
+1997-10-07 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue Oct 25 17:13:09 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * decl.c (duplicate_decls): Make sure DECL_LANG_SPECIFIC is set on
+ OLDDECL before we try to do DECL_USE_TEMPLATE.
- * tree.c (debug_binfo): get rid of the initial size entry of
- vtable.
- * cp-tree.h: change flag_dossier to flag rtti, define type
- descriptor type nodes.
- * decl.c (init_type_desc): new function to initialize type
- descriptor type nodes.
- * decl.c (record_builtin_type): change flag_dossier to flag_rtti.
- * lex.c (init_lex): ditto.
- * decl.c : change variable flag_dossier to flag_rtti.
- * decl.c (duplicate_decls): get rid initial size entry of vtable.
- * decl.c (hack_incomplete_structures): take out assert 164.
- * search.c (get_abstract_virtuals_1): ditto.
- * search.c (dfs_init_vbase_pointers): change CLASSTYPE_DOSSIER to
- CLASSTYPE_RTTI.
- * parse.y: ditto.
- * class.c (prepare_fresh_vtable): for virtual bases, get right
- offset.
- * class.c (add_virtual_function): change flag_dossier to
- flag_rtti.
- * class.c (modify_one_vtable): modify the right rtti entry.
- * class.c (override_one_vtable): get rid of size entry.
- * class.c (finish_struct): change flag_dossier to flag_rtti, and
- build extra vtables, build type descriptors for polymorphic
- classes.
- * gc.c (build_headof): make headof() works correctly with new
- rtti.
- * gc.c (build_typeid): make this function work with new rtti.
- * gc.c (get_typeid): make this function work with new rtti.
- * gc.c (build_bltn_desc): new function for new rtti.
- * gc.c (build_user_desc): ditto.
- * gc.c (build_class_desc): ditto.
- * gc.c (build_ptr_desc): ditto.
- * gc.c (build_attr_desc): ditto.
- * gc.c (build_func_desc): ditto.
- * gc.c (build_ptmf_desc): ditto.
- * gc.c (build_ptmd_desc): ditto.
- * gc.c (build_t_desc): ditto.
- * gc.c : comment out old build_t_desc, build_i_desc, build_m_desc.
+Tue Oct 7 00:48:36 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue Oct 25 13:37:41 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * decl.c (duplicate_decls): Don't warn about template instances.
- * call.c (convert_harshness): Check for TREE_UNSIGNED differences
- after checking for integral conversions.
+ * typeck.c (mark_addressable): Lose ancient code that unsets
+ DECL_EXTERNAL.
-Sun Oct 23 13:19:55 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * pt.c (do_decl_instantiation): Lose support for instantiating
+ non-templates.
- * decl2.c: Declare flag_access_control.
- (struct lang_f_options): Add access-control.
- * expr.c (cplus_expand_expr, NEW_EXPR): Unset flag_access_control
- for the call to expand_aggr_init to copy the object out of the
- pcc_struct_return slot.
- * search.c (compute_access): if (!flag_access_control) return
- access_public.
+ * call.c (build_new_function_call): Fix handling of null explicit
+ template args.
+ (build_new_method_call): Likewise.
-Fri Oct 21 00:32:54 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+Mon Oct 6 23:44:34 1997 Mark Mitchell <mmitchell@usa.net>
- * lex.c (cons_up_default_function): Don't try to defer method
- synthesis now.
+ * method.c (build_underscore_int): Fix typo.
- * decl.c (init_decl_processing): Use __pure_virtual for abort_fndecl
- instead of abort, since the OSF/1 dynamic linker doesn't like to see
- relocation entries for abort.
+1997-10-06 Brendan Kehoe <brendan@lisa.cygnus.com>
- * tree.c (array_type_nelts_total): Use sizetype, not
- integer_type_node.
- (array_type_nelts_top): Ditto.
+ * tree.c (print_lang_statistics): #if 0 call to
+ print_inline_obstack_statistics until its definition is checked in.
-Thu Oct 20 15:48:27 1994 Mike Stump <mrs@cygnus.com>
+Mon Oct 6 09:27:29 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Added handling for catch parameters
- (CATCHPARM).
- * except.c (expand_start_catch_block): Use the new CATCHPARM context
- instead of NORMAL.
- * except.c (expand_throw): Don't let convert_to_reference complain
- about what we are doing.
+ * decl2.c (finish_file): Move dump_tree_statistics to end.
-Thu Oct 20 12:55:24 1994 Jim Wilson (wilson@cygnus.com)
+ * pt.c (instantiate_decl): Look for the original template.
+ (tsubst): Set DECL_IMPLICIT_INSTANTIATION on partial instantiations
+ of member templates.
- * method.c (emit_thunk): Call instantiate_virtual_regs.
+Wed Oct 1 08:41:38 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Oct 19 14:15:33 1994 Mike Stump <mrs@cygnus.com>
+ * Makefile.in (g++FAQ.*): New rules.
+ (CONFLICTS): Update.
+ * g++FAQ.texi: Moved from libg++.
- * except.c (expand_exception_blocks): Make sure throw code doesn't
- get put in function that won't be output.
+ * parse.y (PFUNCNAME): Only specify the type once.
-Mon Oct 17 18:03:15 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+1997-10-01 Brendan Kehoe <brendan@lasher.cygnus.com>
- * decl.c (init_decl_processing): Make alloca a builtin.
+ * lex.c (real_yylex): Clean up the code to fully behave the way
+ the c-lex.c parser does for complex and real numbers.
-Thu Oct 27 21:10:25 1994 Craig Burley (craig@burley)
+Tue Sep 30 08:51:36 1997 Jason Merrill <jason@yorick.cygnus.com>
- * g++.c (main): Only decrement "added" and set "library" to
- NULL when "library" != NULL (just like 940829 fix).
+ * method.c (build_decl_overload_real): Reformat.
-Mon Oct 17 15:56:11 1994 Mike Stump <mrs@cygnus.com>
+Tue Sep 30 00:18:26 1997 Jason Merrill <jason@yorick.cygnus.com>
- * except.c (expand_start_catch_block): Make sure the false label
- gets onto the permanent obstack, as it is used for the exception
- table.
+ * method.c (synthesize_method): If at_eof, determine our linkage.
-Fri Oct 14 18:54:48 1994 Mike Stump <mrs@cygnus.com>
+1997-09-29 Paul Eggert <eggert@twinsun.com>
- * class.c (modify_one_vtable): Since the DECL_CONTEXT of fndecl can
- be set just below, use current_fndecl instead.
+ * lex.c (real_yylex): Treat `$' just like `_', except issue a
+ diagnostic if !dollars_in_ident or if pedantic.
-Fri Oct 14 15:12:22 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * lang-specs.h (@c++): -ansi no longer implies -$.
- * init.c (expand_aggr_vbase_init_1): Don't call expand_aggr_init_1
- with LOOKUP_SPECULATIVELY.
- (expand_default_init): Abort if build_method_call returns NULL_TREE.
+ * decl2.c (lang_decode_option):
+ -traditional and -ansi now do not mess with
+ dollars_in_ident.
- * typeck.c (build_modify_expr): Don't just build a MODIFY_EXPR if
- the rhs is a TARGET_EXPR.
+Mon Sep 29 19:57:51 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
- * parse.y (left_curly): Anonymous types are not affected by #pragma
- interface/implementation.
+ * Makefile.in (parse.o, decl.o): Also depend on
+ $(srcdir)/../except.h $(srcdir)/../output.h.
+ (decl2.o): Also depend on $(srcdir)/../expr.h ../insn-codes.h
+ $(srcdir)/../except.h $(srcdir)/../output.h.
+ (typeck.o, init.o): Also depend on $(srcdir)/../expr.h
+ ../insn-codes.h.
- * method.c (synthesize_method): Don't call setup_vtbl_ptr for the
- default constructor if it isn't needed.
+ * call.c, cp-tree.h, decl.c, tree.c: Finish prototyping.
- * lex.c (cons_up_default_function): Do synthesize methods for
- anonymous types if necessary.
+ * expr.c (cplus_expand_expr): Make it static.
-Thu Oct 13 17:44:55 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * decl2.c, init.c, typeck.c: Include "expr.h".
+ (expand_expr): Use proper values when calling the function.
- * method.c (build_decl_overload): Set numeric_outputed_need_bar to 0.
+Mon Sep 29 11:05:54 1997 Alexandre Oliva <oliva@dcc.unicamp.br>
-Wed Oct 12 13:27:57 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * lang-options.h: new -Wold-style-cast flag.
+ * cp-tree.h (warn_old_style_cast): new variable.
+ * decl2.c (warn_old_style_cast): ditto.
+ (lang_decode_option): support -Wold-style-cast.
+ (reparse_absdcl_as_casts): produce old-style-cast warning.
- * typeck.c (build_modify_expr): Understand how to copy an aggregate.
+Mon Sep 29 09:20:53 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * init.c (expand_default_init): Ditto. Also remove some of the
- crufty code that assumes methods will not be synthesized properly.
+ * decl.c (cp_finish_decl): Allow expand_aggr_init to set
+ TREE_USED, reset value based on already_used.
- * lex.c (cons_up_default_function): If the containing type has no
- name, these functions should never need to be called, so just
- declare them.
+ * init.c (expand_member_init): Revert change.
+
+Mon Sep 29 08:57:53 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h, decl.c, decl2.c, pt.c:
+ Lose DECL_C_STATIC and DECL_PUBLIC. Don't pretend statics are public.
+
+ * decl2.c (lang_decode_option): Add missing ;.
+
+Sat Sep 27 16:22:48 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * friend.c (do_friend): Disable injection for all template-derived
+ decls.
+ * decl2.c (lang_decode_option): Handle -fguiding-decls.
+ * parse.y (notype_template_declarator): New nonterminal.
+ (direct_notype_declarator): Use it.
+ (complex_direct_notype_declarator): Likewise.
+ (object_template_id): Accept any kind of identifier after TEMPLATE.
+ (notype_qualified_id): Don't add template declarators here.
+
+Sat Sep 27 16:21:58 1997 Mark Mitchell <mmitchell@usa.net>
+
+ * call.c (add_template_candidate): Add explicit_targs parameter.
+ (build_scoped_method_call): Use it.
+ (build_overload_call_real): Likewise.
+ (build_user_type_conversion_1): Likewise.
+ (build_new_function_call): Likewise.
+ (build_object_call): Likewise.
+ (build_new_op): Likewise.
+ (build_new_method_call): Likewise.
+ (build_new_function_call): Handle TEMPLATE_ID_EXPR.
+ (build_new_method_call): Likewise.
+
+ * class.c (finish_struct_methods): Add specialization pass to
+ determine which methods were specializing which other methods.
+ (instantiate_type): Handle TEMPLATE_ID_EXPR.
+
+ * cp-tree.def (TEMPLATE_ID_EXPR): New tree code.
+
+ * cp-tree.h (name_mangling_version): New variable.
+ (flag_guiding_decls): Likewise.
+ (build_template_decl_overload): New function.
+ (begin_specialization): Likewise.
+ (reset_specialization): Likewise.
+ (end_specialization): Likewise.
+ (determine_explicit_specialization): Likewise.
+ (check_explicit_specialization): Likewise.
+ (lookup_template_function): Likewise.
+ (fn_type_unification): Add explicit_targs parameter.
+ (type_unification): Likewise.
+
+ * decl.c (duplicate_decls): Add smarts for explicit
+ specializations.
+ (grokdeclarator): Handle TEMPLATE_ID_EXPR, and function
+ specializations.
+ (grokfndecl): Call check_explicit_specialization.
+
+ * decl2.c (lang_decode_option): Handle -fname-mangling-version.
+ (build_expr_from_tree): Handle TEMPLATE_ID_EXPR.
+ (check_classfn): Handle specializations.
+
+ * error.c (dump_function_name): Print specialization arguments.
+
+ * friend.c (do_friend): Don't call pushdecl for template
+ instantiations.
+
+ * init.c (build_member_call): Handle TEMPLATE_ID_EXPR.
+
+ * lang-options.h: Add -fname-mangling-version, -fguiding-decls,
+ and -fno-guiding-decls.
+
+ * lex.c (identifier_type): Return PFUNCNAME for template function
+ names.
+
+ * method.c (build_decl_overload_real): New function.
+ (build_template_parm_names): New function.
+ (build_overload_identifier): Use it.
+ (build_underscore_int): New function.
+ (build_overload_int): Use it. Add levels for template
+ parameters.
+ (build_overload_name): Likewise. Also, handle TYPENAME_TYPEs.
+ (build_overload_nested_names): Handle template type parameters.
+ (build_template_decl_overload): New function.
+
+ * parse.y (YYSTYPE): New ntype member.
+ (nested_name_specifier): Use it.
+ (nested_name_specifier_1): Likewise.
+ (PFUNCNAME): New token.
+ (template_id, object_template_id): New non-terminals.
+ (template_parm_list): Note specializations.
+ (template_def): Likewise.
+ (structsp): Likewise.
+ (fn.def2): Handle member template specializations.
+ (component_decl_1): Likewise.
+ (direct_notype_declarator): Handle template-ids.
+ (component_decl_1): Likewise.
+ (direct_notype_declarator): Handle template-ids.
+ (primary): Handle TEMPLATE_ID_EXPR, and template-ids.
+
+ * pt.c (processing_specializations): New variable.
+ (template_header_count): Likewise.
+ (type_unification_real): New function.
+ (processing_explicit_specialization): Likewise.
+ (note_template_header): Likewise.
+ (is_member_template): Handle specializations.
+ (end_template_decl): Call reset_specialization.
+ (push_template_decl): Handle member template specializations.
+ (tsubst): Likewise.
+ (tsubst_copy): Handle TEMPLATE_ID_EXPR.
+ (instantiate_template): Handle specializations.
+ (instantiate_decl): Likewise.
+ (fn_type_unification): Handle explicit_targs.
+ (type_unification): Likewise. Allow incomplete unification
+ without an error message, if allow_incomplete.
+ (get_bindings): Use new calling sequence for fn_type_unification.
+
+ * spew.c (yylex): Handle PFUNCNAME.
+
+ * tree.c (is_overloaded_fn): Handle TEMPLATE_ID_EXPR.
+ (really_overloaded_fn): Likewise.
+ (get_first_fn): Handle function templates.
+
+ * typeck.c (build_x_function_call): Use really_overloaded_fn.
+ Handle TEMPLATE_ID_EXPR.
+ (build_x_unary_op): Likewise.
+ (build_unary_op): Likewise.
+ (mark_addressable): Templates whose address is taken are marked
+ as used.
+
+1997-09-25 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * decl.c (init_decl_processing): Declare __builtin_constant_p as
+ accepting any kind of type, not only int.
+
+Fri Sep 26 00:22:56 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * search.c (get_matching_virtual): Notice virtual bases when sorrying
+ about covariant returns.
+
+ * parse.y (member_init): Also imply typename here. Remove ancient
+ extension for initializing base members.
+
+Thu Sep 25 11:11:13 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ Handle multi-level typenames and implicit typename in base list.
+ * parse.y (typename_sub{,[0-2]}): New rules.
+ (structsp, rule TYPENAME_KEYWORD): Use typename_sub.
+ (nonnested_type): New rule.
+ (complete_type_name): Use it.
+ (base_class.1): Use typename_sub and nonnested_type.
+ (nested_name_specifier): Don't elide std:: here.
+ * decl.c (make_typename_type): Handle getting a type for NAME.
+ (lookup_name_real): Turn std:: into :: here.
+
+ Rvalue conversions were removed in London.
+ * call.c (is_subseq): Don't consider lvalue transformations.
+ (build_conv): LVALUE_CONV and RVALUE_CONV get IDENTITY_RANK.
+ (joust): Reenable ?: kludge.
+
+1997-09-22 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * decl.c (start_function): Up warning of no return type to be a
+ pedwarn.
+
+Mon Sep 22 14:15:34 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
+
+ * init.c (expand_member_init): Don't set TREE_USED.
+ * decl.c (cp_finish_decl): Mark decls used if type has TREE_USED
+ set,don't clear TREE_USED wholesale.
+
+Sat Sep 20 15:31:00 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (build_over_call): Do require_complete_type before
+ build_cplus_new.
- * lex.c (real_yylex): Use HOST_BITS_PER_WIDE_INT to determine the
- bitmask for lexing character constants.
+Thu Sep 18 16:47:52 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Disable code that tries to do tricky
- stuff with a default parameter that is a constructor call, but
- actually does other tricky stuff that breaks things.
+ * search.c (lookup_field): Call complete_type in all cases.
-Wed Oct 12 16:14:01 1994 Benoit Belley <belley@cae.ca>
+ * decl.c (finish_function): Just warn about flowing off the end.
- * decl.c (finish_enum): Disable code which forces enums to be signed,
- since this conflicts with their use as bitfields. type_promotes_to
- handles promotion of enums of underlying unsigned types to signed
- integer types.
+Wed Sep 17 10:31:25 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Oct 12 13:24:03 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * decl.c (grokparms): Don't bash a permanent list node if we're
+ in a function.
- * cvt.c (type_promotes_to): Also promote enums to long if
- appropriate.
+1997-09-17 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck.c (default_conversion): Don't expect type_promotes_to to
- return a main variant.
+ * Makefile.in (CONFLICTS): Fix s/r conflict count to 18.
-Wed Oct 12 12:19:45 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+Tue Sep 16 14:06:56 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_scoped_method_call): Don't lose side effects in the
- object expression when calling a non-existent destructor.
+ * call.c (build_new_op): Give better error for syntactically
+ correct, but semantically invalid, use of undeclared template.
-Fri Sep 2 19:05:21 1994 Rohan Lenard (rjl@iassf.easams.com.au)
+ * call.c (compare_qual): Handle pmfs.
- * call.c (build_scoped_method_call): Remove erroneous error message
- when destructor call is written as a scoped call.
+ * decl.c (store_parm_decls): last_parm_cleanup_insn is the insn
+ after the exception spec.
-Tue Oct 11 23:48:31 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+Mon Sep 15 11:52:13 1997 Jason Merrill <jason@yorick.cygnus.com>
- * various: Cast pointer arguments to bzero and bcopy to char *.
+ * call.c (null_ptr_cst_p): Integer type, not integral type.
-Tue Oct 11 19:34:32 1994 Mike Stump <mrs@cygnus.com>
+ * call.c (joust): Disable warnings until they can be moved to the
+ right place.
- * class.c (get_derived_offset): Added a type parameter to limit how
- far up the CLASSTYPE_VFIELD_PARENT chain we search.
- * class.c (modify_one_vtable, fixup_vtable_deltas): When forming the
- offset to put into the vtable for the this parameter, make sure we
- don't offset from a parent of the DECL_CONTEXT of the function.
+Fri Sep 12 16:11:13 1997 Per Bothner <bothner@cygnus.com>
-Tue Oct 11 16:10:52 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * Makefile.in, config-lang.in: Convert to autoconf.
- * pt.c (do_function_instantiation): Set DECL_EXTERNAL and
- TREE_STATIC when setting DECL_INTERFACE_KNOWN.
- (do_type_instantiation): Ditto.
+Thu Sep 11 17:14:55 1997 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (cons_up_default_function): Set DECL_INTERFACE_KNOWN,
- DECL_EXTERNAL and TREE_STATIC as appropriate.
+ * decl.c (lookup_name_real): Add implicit 'typename' to types from
+ base classes.
- * decl2.c (finish_file): Also synthesize methods that don't have
- DECL_EXTERNAL set. Set interface_unknown before doing so.
+ * pt.c (most_specialized_class): Fix typo.
+ (tsubst): Move constant folding to TREE_VEC case.
- * decl.c (start_function): If DECL_INTERFACE_KNOWN is set on the
- function decl, don't muck with TREE_PUBLIC and DECL_EXTERNAL.
+Thu Sep 11 10:08:45 1997 Mark Mitchell <mmitchell@usa.net>
-Mon Oct 10 00:56:53 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * pt.c (do_poplevel): Don't warn about unused local variables
+ while processing_template_decl since we don't always know whether
+ or not they will need constructing/destructing.
- * lex.c (cons_up_default_function): Mark methods in a template class
- as template instances. Store the values of interface_unknown and
- interface_only for do_pending_inlines.
- (do_pending_inlines): Use them.
+ * pt.c (uses_template_parms): Check the values of an enumeration
+ type to make sure they don't depend on template parms.
- * decl2.c (finish_file): If we haven't seen a definition of a
- function declared static, make the decl non-PUBLIC so compile_file
- can give an error.
+ * decl.c (make_typename_type): Don't lookup the field if the
+ context uses template parms, even if we're not
+ processing_template_decl at the moment.
-Sun Oct 9 02:42:29 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * pt.c (coerce_template_parms): Avoid looking at the
+ TYPE_LANG_DECL portion of a typename type, since there won't be
+ one.
+ (tsubst): Do constant folding as necessary to make sure that
+ arguments passed to lookup_template_class really are constants.
- * method.c (do_build_copy_constructor): Handle anonymous unions.
- (do_build_assign_ref): Ditto.
- (largest_union_member): Move from lex.c.
+Wed Sep 10 11:21:55 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sat Oct 8 14:59:43 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * except.c (expand_builtin_throw): #ifndef DWARF2_UNWIND_INFO.
+ * decl2.c (finish_file): Only register exception tables if we
+ need to.
- Re-implement g++'s vague linkage independent of TREE_PUBLIC.
- * pt.c (instantiate_member_templates): Lose redundant
- -fexternal-templates handling.
- (tsubst): Set TREE_PUBLIC and DECL_EXTERNAL on new decls. Don't set
- TREE_STATIC or DECL_INTERFACE_KNOWN.
- (do_pending_expansions): Predicate on DECL_INTERFACE_KNOWN instead
- of DECL_EXTERNAL for explicit instantiations.
- (do_function_instantiation): Do the new thing.
- (do_type_instantiation): Ditto.
- (instantiate_template): Deal with member templates defined in a .cc
- file with -fexternal-templates.
- * except.c (expand_exception_blocks): Use DECL_LINKAGE_KNOWN to
- decide whether to stick builtin_throw here.
- * decl2.c (import_export_inline): Predicate on DECL_INTERFACE_KNOWN
- rather than TREE_PUBLIC. Generally fix rules.
- (finish_file): Use DECL_INITIAL to determine whether or not a method
- has been synthesized, rather than TREE_ASM_WRITTEN.
- * decl.c (warn_extern_redeclared_static): Use DECL_PUBLIC instead of
- TREE_PUBLIC.
- (pushdecl): Ditto.
- (duplicate_decls): Ditto. Deal with DECL_DECLARED_STATIC and
- DECL_INTERFACE_KNOWN.
- (redeclaration_error_message): Fix checking for conflicting linkage.
- (define_function): Set DECL_INTERFACE_KNOWN.
- (grokfndecl): Function decls are PUBLIC until we are sure about
- their linkage. Set DECL_DECLARED_STATIC as needed.
- (start_function): Deal with linkage. Move pushdecl after linkage
- magic.
- (finish_function): Don't set TREE_ASM_WRITTEN on discarded inlines.
- * cp-tree.h (lang_decl_flags): Add interface_known and
- declared_static.
- (DECL_INTERFACE_KNOWN): New macro.
- (DECL_DECLARED_STATIC): New macro.
- (DECL_PUBLIC): New macro.
+ * decl.c (init_decl_processing): Add __builtin_[fs]p.
- Clean up bogus use of TREE_PUBLIC.
- * class.c (alter_access): Fix mistaken use of TREE_PUBLIC (it
- doesn't correspond to TREE_PROTECTED and TREE_PRIVATE).
- * init.c (do_friend): Don't arbitrarily set TREE_PUBLIC.
+Tue Sep 9 19:49:38 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Oct 5 13:44:41 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * pt.c (unify): Just return 0 for a TYPENAME_TYPE.
- * call.c (build_overload_call_real): Don't immediately do
- array->pointer conversion.
+Tue Sep 9 17:57:25 1997 Mark Mitchell <mmitchell@usa.net>
- * pt.c (type_unification): If not passing to a reference, strip
- cv-quals. Also handle array->pointer conversion.
+ * error.c (dump_decl): Avoid crashing when presented with a
+ uninitialized constant, as can occur with a template parameter.
+ (dump_expr): Make sure that there are enough levels of
+ current_template_parms before we start diving through them.
-Tue Oct 4 17:45:37 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+1997-09-09 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (grokdeclarator): Don't warn about applying const to a
- const typedef or template type parameter.
+ * typeck.c (build_indirect_ref): Heed FLAG_VOLATILE similar to
+ c-typeck.c.
- * decl2.c (finish_file): Also synthesize methods after walking the
- vtables. Ugly ugly ugly.
+Tue Sep 9 09:36:39 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
-Mon Oct 3 15:02:41 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * except.c (expand_throw): Call build_delete for all
+ exception types, not just objects with destructors.
- * various: Remove lingering remnants of old exception handling code.
+Mon Sep 8 02:33:20 1997 Jody Goldberg <jodyg@idt.net>
- * decl2.c (finish_file): Synthesize methods before walking the
- vtables, so that the vtables get emitted as needed.
+ * decl.c (current_local_enum): Remove static.
+ * pt.c (tsubst_enum): Save and restore value of current_local_enum
+ in case template is expanded in enum decl.
+ (instantiate_class_template) : Use new tsubst_enum signature.
+ (tsubst_expr): Likewise.
- * decl.c (shadow_tag): Remove obsolete code for pushing tags and
- dealing with exceptions.
+Mon Sep 8 01:21:43 1997 Mark Mitchell <mmitchell@usa.net>
-Mon Oct 3 13:05:27 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+ * pt.c (begin_member_template_processing): Take a function as
+ argument, not a set of template arguments. Use the template
+ parameters, rather than the arguments. Handle non-type parameters
+ correctly. Push a binding level for the parameters so that multiple
+ member templates using the same parameter names can be declared.
+ (end_member_template_processing): Pop the binding level.
+ (push_template_decl): Mark member templates as static when
+ appropriate.
- * Make-lang.in (g++-cross): Depend upon version.o and $(LIBDEPS).
+ * lex.c (do_pending_inlines): Pass the function, not its template
+ arguments, to begin_member_template_processing.
+ (process_next_inline): Likewise.
+ (do_pending_defargs): Likewise.
-Mon Oct 3 02:59:28 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * error.c (dump_expr): Obtain the correct declaration for a
+ TEMPLATE_CONST_PARM.
- * decl2.c (finish_file): Fix inline handling.
+ * call.c (add_template_conv_candidate): New function.
+ (build_object_call): Handle member templates, as done in the other
+ build_ functions.
+
+Sat Sep 6 10:20:27 1997 Mark Mitchell <mmitchell@usa.net>
-Sun Oct 2 00:21:56 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * decl.c (replace_defag): Undo previous change.
+ * lex.c (do_pending_defargs): Deal with member templates.
+
+ * pt.c (is_member_template): Avoid crashing when passed a
+ non-function argument.
- * decl.c (grokdeclarator): Handle redundant scope even better.
- ({push,pop}_cp_function_context): Take toplev parameter.
+Fri Sep 5 17:27:38 1997 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (synthesize_method): Pass toplev parameter to
- {push,pop}_cp_function_context depending on decl_function_context
- (fndecl).
+ * class.c (grow_method): Remove check for redeclaration.
- * typeck.c (build_x_unary_op): Unary & on OFFSET_REFs is always the
- built-in version.
+Fri Sep 5 01:37:17 1997 Mark Mitchell <mmitchell@usa.net>
- * method.c (synthesize_method): Don't be confused by __in_chrg
- parameter.
+ * cp-tree.h (INNERMOST_TEMPLATE_PARMS): New macro.
+ (DECL_INNERMOST_TEMPLATE_PARMS): Likewise.
+ (PRIMARY_TEMPLATE_P): Use it.
+ * call.c (build_overload_call_real): Use it.
+ * class.c (instantiate_type): Likewise.
+ * decl.c (decls_match): Likewise.
+ * method.c (build_overload_identifier): Likewise.
+ * pt.c (push_template_decl): Likewise.
+ (classtype_mangled_name): Likewise.
+ (lookup_template_class): Likewise.
+
+ * cp-tree.h (DECL_NTPARMS): Change name from DECL_NT_PARMS to
+ DECL_NTPARMS to conform to usage elsewhere.
+ * call.c (add_template_candidate): Likewise.
+ * class.c (instantiate_type): Likewise.
+ * pt.c (instantiate_template): Likewise.
+ (get_bindings): Likewise.
+
+ * class.c (grow_method): Use DECL_FUNCTION_TEMPLATE_P instead of
+ is_member_template.
+
+ * pt.c (unify): Undo changes to allow multiple levels of template
+ parameters.
+ (type_unification): Likewise.
+ (fn_type_unification): Likewise.
+ (get_class_bindings): Likewise.
+ * cp-tree.h (Likewise).
+
+ * decl.c (replace_defarg): Check that the type of the default
+ parameter does not invlove a template type before complaining
+ about the initialization.
+
+ * error.c (dump_expr): Deal with template constant parameters in
+ member templates correctly.
+
+ * pt.c (is_member_template): Deal with class specializations
+ correctly.
+ (tsubst): Handle "partial instantiation" of member templates
+ correctly.
+
+Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
+
+ * pt.c (type_unification): Change calling squence to allow for
+ multiple levels of template parameters.
+ (tsubst_expr): Likewise.
+ (tsubst): Likewise.
+ (tsubst_copy): Likewise.
+ (instantiate_template): Likewise.
+ (unify): Likewise.
+ * call.c (build_overload_call_real): Use it.
+ (add_builtin_candidate): Use it.
+ (build_new_method_call): Use it.
+ * class.c (instantiate_type): Use it.
+ * decl.c (grokdeclarator): Use it.
+ * decl2.c (finish_file): Use it.
+ * method.c (build_overload_identifier): Use it.
+
+ * call.c (add_template_candidate): Add additional parameter for
+ the function return type. Call fn_type_unification istead of
+ type_unification.
+ (build_user_type_conversion_1): Handle member templates.
+ (build_new_function_call): Likewise.
+ (build_new_op): Likewise.
+ (build_new_method_call): Likewise.
+
+ * class.c (grow_method): Don't give an error message indicating
+ that two member templates with the same name are ambiguous.
+ (finish_struct): Treat member template functions just like member
+ functions.
+
+ * cp-tree.h (check_member_template): Add declaration.
+ (begin_member_template_processing): Likewise.
+ (end_member_template_processing): Likewise.
+ (fn_type_unification): Likewise.
+ (is_member_template): Likewise.
+ (tsubst): Change prototype.
+ (tsubst_expr): Likewise.
+ (tsubst_copy): Likewise.
+ (instantiate_template): Likewise.
+ (get_bindings): Likewise.
+
+ * decl.c (decls_match): Handle multiple levels of template
+ parameters.
+ (pushdecl): Handle template type params just like other type
+ declarations.
+ (push_class_level_binding): Return immediately if the
+ class_binding_level is NULL.
+ (grokfndecl): If check_classfn() returns a member_template, use
+ the result of the template, not the template itself.
+
+ * decl2.c (check_member_template): New function. Check to see
+ that the entity declared to be a member template can be one.
+ (check_classfn): Allow redeclaration of member template functions
+ with different types; the new functions can be specializations or
+ explicit instantiations.
+
+ * error.c (dump_decl): Handle multiple levels of template
+ parameters.
+ (dump_function_decl): Update to handle function templates.
- * class.c (popclass): Set C_C_D like start_function does.
+ * lex.c (do_pending_inlines): Set up template parameter context
+ for member templates.
+ (process_next_inline): Likewise.
- * decl.c (grokdeclarator): Handle redundant scope better.
+ * method. (build_overload_identifier): Adjust for multiple levels
+ of template parameters.
+
+ * parse.y (fn.def2): Add member templates.
+ (component_decl_1): Likewise.
+
+ * pt.c (begin_member_template_processing): New function.
+ (end_member_template_processing): Likewise.
+ (is_member_template): Likewise.
+ (fn_type_unification): Likewise.
+ (current_template_parms): Return a vector of all the template
+ parms, not just the innermost level of parms.
+ (push_template_decl): Deal with the possibility of member
+ templates.
+ (lookup_template_class): Likewise.
+ (uses_template_parms): Likewise.
+ (tsubst): Modify processing to TEMPLATE_TYPE_PARM and
+ TEMPLATE_CONST_PARM to deal with multiple levels of template
+ arguments. Add processing of TEMPLATE_DECL to produce new
+ TEMPLATE_DECLs from old ones.
+ (do_decl_instantiation): Handle member templates.
+
+ * search.c (lookup_fnfields_1): Handle member template conversion
+ operators.
+
+ * tree.c (cp_tree_equal): Check the levels, as well as the
+ indices, of TEMPLATE_CONST_PARMs.
+
+ * typeck.c (comptypes): Check the levels, as well as the indices,
+ fo TEMPLATE_TYPE_PARMs.
+ (build_x_function_call): Treat member templates like member
+ functions.
+
+Wed Sep 3 11:09:25 1997 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (expr_or_declarator): Add '(' expr_or_declarator ')' rule.
- (direct_notype_declarator): Ditto.
- (complex_direct_notype_declarator): Remove it here.
+ * typeck.c (c_expand_return): Always convert_for_initialization
+ before checking for returning a pointer to local.
-Sat Oct 1 21:42:18 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * init.c (resolve_offset_ref): Fix types used in resolving .*
- expressions.
-
-Sat Oct 1 15:18:49 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * pt.c (type_unification): If strict and the function parm doesn't
+ use template parms, just compare types.
- Beginnings of work to synthesize methods only when needed.
- * call.c (build_method_call): Synthesize methods as necessary
- (currently never necessary).
- * class.c (popclass): Don't try to set C_C_D here, as it'll end up
- on the wrong obstack.
- * decl.c (push_cp_function_context): Mostly copied from
- push_c_function_context.
- (pop_cp_function_context): Similarly.
- (finish_function): Reverse order of poplevel and pop_nested_class so
- that current_class_decl is restored properly.
- (start_function): Ditto.
- (finish_function): Add parameter 'nested'. Don't call
- permanent_allocation if (nested).
- * various: Pass extra parameter to finish_function.
- * decl2.c (finish_file): Reorganize end-of-file inline handling,
- synthesizing methods as necessary.
- * lex.c (cons_up_default_function): Call mark_inline_for_output.
- Only synthesize methods immediately if #pragma implementation
- (currently disabled).
- (do_pending_inlines): Call synthesize_method.
- * method.c (synthesize_method): New function; all method synthesis
- goes through here. Calls do_build_assign_ref and
- do_build_copy_constructor.
- (build_default_constructor): Remove.
- (build_dtor): Ditto.
- (build_assign_ref): Rename to do_build_assign_ref and remove stuff
- done by synthesize_method.
- (build_copy_constructor): Similarly.
+Wed Sep 3 10:35:49 1997 Klaus Espenlaub <kespenla@student.informatik.uni-ulm.de>
-Thu Sep 29 16:58:52 1994 Mike Stump <mrs@cygnus.com>
+ * method.c (build_overloaded_value): Replace direct call
+ to the floating point emulator with REAL_VALUE_TO_DECIMAL macro.
- * typeck.c (c_expand_return): Use magic so the backend can fixup the
- assignment into the return register, so cleanups won't clobber it.
+Wed Sep 3 00:02:53 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Sep 29 13:08:50 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (convert_arguments): Don't arbitrarily choose the first
+ of a set of overloaded functions.
- * method.c (hack_identifier): Don't call assemble_external for
- template decls.
+Tue Sep 2 12:09:13 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (finish_decl): Also end temporary allocation if the decl in
- question has a type of error_mark_node.
+ * lex.c (real_yylex): Don't elide __FUNCTION__.
-Wed Sep 28 21:45:00 1994 Mike Stump <mrs@cygnus.com>
+ * method.c (build_overload_value): Add in_template parm.
+ (build_overload_int): Likewise.
+ (build_overload_identifier): Pass it.
- * typeck.c (build_modify_expr): When optimizing ?: on lhs, make sure
- that if the ?: was a reference type, that the subparts will be also.
+ * decl.c (duplicate_decls): Don't bash a previous template
+ definition with a redeclaration.
-Wed Sep 28 16:14:04 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * pt.c (unify): float doesn't match double.
- * except.c (register_exception_table): Use Pmode, not PTRmode.
+ * pt.c (do_type_instantiation): Handle getting a _TYPE or a
+ TYPE_DECL. Handle getting non-template types.
+ * parse.y (explicit_instantiation): Use typespec instead of
+ aggr template_type.
-Fri Sep 23 13:54:27 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Sep 2 10:27:08 1997 Richard Henderson <rth@cygnus.com>
- * lex.c (do_pending_inlines): Do method synthesis after the
- pending_inlines have been reversed.
+ * typeck.c (build_ptrmemfunc1): Clean up ptr->int cast warnings.
-Thu Sep 22 12:53:03 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Mon Sep 1 13:19:04 1997 Eugene Mamchits <eugin@ips.ras.ru>
- * decl2.c (finish_file): Fix Brendan's fix: Only call
- register_exception_table if there is a non-empty exception table.
+ * call.c (add_builtin_candidate): Add missing TREE_TYPE.
+ (compare_ics): Likewise.
-Thu Sep 22 12:03:46 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+Mon Sep 1 13:19:04 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (finish_file): Only do register_exception_table if
- -fhandle-exceptions is being used.
+ * call.c (joust): Warn about choosing one conversion op over
+ another because of 'this' argument when the other return type is
+ better.
+ (source_type): New fn.
-Wed Sep 21 19:01:51 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * call.c (build_new_op): Strip leading REF_BIND from first operand
+ to builtin operator.
- * except.c (output_exception_table_entry): Simplify
- by using assemble_integer.
- (build_exception_table): Change to return a count.
- Cleanup to use standard macros, instead of hard-wired
- sparc asm format. Don't make __EXCEPTION_TABLE__ global.
- (register_exception_table): New function. Generate call to builtin.
- * decl2.c (finish_file): Call register_exception_table.
- * cp-tree.h (build_exception_table): Fix prototype.
+ * decl2.c (mark_vtable_entries): Mark abort_fndecl as used when we
+ use its RTL.
-Wed Sep 21 13:20:42 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+Thu Aug 28 09:45:23 1997 Jason Merrill <jason@yorick.cygnus.com>
- * tree.c (break_out_calls): Don't try to duplicate the DECL_INITIAL.
+ * call.c (null_ptr_cst_p): Remove support for (void*)0.
- * decl2.c (delete_sanity): Give an error at trying to delete a
- function.
+Wed Aug 27 02:03:34 1997 Jeffrey A Law (law@cygnus.com)
-Wed Sep 21 11:47:10 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (expand_target_expr): Make definition match declaration.
- * lex.c (cons_up_default_function): Mark synthesized destructors
- inline.
+ * class.c (get_basefndecls): Make definition match declaration.
- * decl.c (duplicate_decls): Ignore redeclarations of wchar_t as
- something other than __wchar_t, complaining if -pedantic and not in
- a system header.
+Mon Aug 25 14:30:02 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue Sep 20 09:43:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * input.c (sub_getch): Eventually give up and release the input file.
- * decl.c (xref_tag): Set up BINFO_INHERITANCE_CHAIN on base binfos
- here.
+ * decl.c (cp_finish_decl): If #p i/i, put inline statics in the
+ right place.
- * typeck.c (build_modify_expr): Require complete type after checking
- for error_mark_node.
+ * call.c (joust): Tweak message.
- * call.c (build_method_call): Print parmtypes when complaining of
- ambiguous call.
+Sat Aug 23 18:02:59 1997 Mark Mitchell <mmitchell@usa.net>
- * typeck.c (build_modify_expr): Handle assignment to array from
- non-array.
+ * error.c (type_as_string): Put const/volatile on template type
+ parameters where appropriate.
- * decl.c (lookup_name_real): Deal with got_scope == error_mark_node.
+Sat Aug 23 17:47:22 1997 Jeffrey A Law (law@cygnus.com)
- * call.c (build_method_call): Don't bother with the exact match.
+ * call.c (strictly_better): Make arguments unsigned ints.
-Mon Sep 19 00:51:39 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Aug 21 18:48:44 1997 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (expand_aggr_init): If we munge the type of the variable,
- also munge the type of the initializer.
+ * lex.c (real_yylex): Refer to __complex instead of complex.
- * decl.c (grokdeclarator): Use <= when comparing to RID_LAST_MODIFIER.
- (init_decl_processing): Push artificial declaration of wchar_t so
- people don't have to declare it before they can use it.
+Thu Aug 21 22:25:46 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
- * error.c (cp_line_of): return lineno in lieu of 0.
+ * lex.c (real_yylex): Don't use getc directly.
- * typeck.c (convert_for_assignment): Handle conversion of pmfs to
- int and bool.
- (build_component_ref): Fold the COMPONENT_REF in case it can be
- reduced.
+Wed Aug 20 17:25:08 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck2.c (store_init_value): Don't pedwarn about non-constant
- bracketed initializers for automatic variables.
+ * call.c (is_subseq): Don't try to be clever.
-Sun Sep 18 10:12:12 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Aug 20 03:13:36 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
- * error.c (dump_decl): Don't say `typedef enum foo foo'.
+ * parse.y, pt.c: Include "except.h".
+ * call.c, class.c, class.h, cp-tree.h, cvt.c, decl.c, decl2.c,
+ error.c, except.c, expr.c, friend.c, g++spec.c, init.c, input.c,
+ lex.c, lex.h, method.c, parse.y, pt.c, repo.c, rtti.c, search.c,
+ sig.c, spew.c, tree.c, typeck.c, typeck2.c, xref.c: Finish
+ prototyping.
- * decl.c (start_decl): Don't set TREE_PUBLIC on template decls just
- because they're affected by #pragma i/i. We'll deal with that when
- they get instantiated.
+Wed Aug 20 01:34:40 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_unary_op): Clean up cruft in ADDR_EXPR case.
+ * decl2.c (mark_vtable_entries): Instead of replacing pure
+ virtuals with a reference to __pure_virtual, copy the decl and
+ change the RTL.
- * class.c (instantiate_type): Set TREE_CONSTANT on instantiated
- ADDR_EXPRs if appropriate.
+Tue Aug 19 02:26:07 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (build_ptrmemfunc_type): Unset IS_AGGR_TYPE on pmf types.
+ * pt.c (lookup_nested_type_by_name): Handle typedef wierdness.
- * typeck.c (build_ptrmemfunc): Handle &overloaded_method as an
- initializer properly.
- * typeck2.c (digest_init): Ditto.
+ * typeck2.c (my_friendly_abort): Report bugs to egcs-bugs@cygnus.com.
- * tree.c (cp_build_type_variant): Like c_build_type_variant, except
- it uses build_cplus_array_type.
- * *.c: Use cp_build_type_variant instead of c_build_type_variant.
+ * pt.c (instantiate_class_template): Call repo_template_used
+ before finish_prevtable_vardecl.
- * pt.c (do_type_instantiation): Don't try to instantiate nested
- enums.
+ * call.c (is_subseq): New fn.
+ (compare_ics): Use it.
-Tue Sep 13 10:56:58 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * repo.c (finish_repo): Don't crash on no args.
- * cvt.c (build_up_reference): Handle preincrement and predecrement
- properly.
+ * parse.y (named_complex_class_head_sans_basetype): Handle
+ explicit global scope.
+ * decl2.c (handle_class_head): New fn.
-Tue Sep 13 09:51:59 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * pt.c (unify): Add CONST_DECL case.
- * decl.c (finish_decl): Only lay out the rtl for DECL if it is, in
- fact, static.
+Thu Aug 14 10:05:13 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Mon Sep 12 14:40:30 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * rtti.c (permanent_obstack): Fix decl to not be a pointer.
- * decl.c (finish_decl): Lay out the rtl for DECL before doing
- grok_reference_init, in case it's static.
+ * cp-tree.h (report_type_mismatch): Add prototype.
+ * call.c (build_overload_call_real): Remove erroneous fourth
+ argument to report_type_mismatch.
+ (build_user_type_conversion_1): Remove erroneous second arg to
+ tourney.
+ (build_new_function_call): Likewise.
+ (build_object_call): Likewise.
+ (build_new_op): Likewise.
+ (build_new_method_call): Likewise.
-Mon Sep 12 12:45:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Aug 13 19:19:25 1997 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Don't synthesize constructors if the
- class has a field with the same name as the class. Don't die on
- classes with no constructors or destructors. Don't die if the head
- and tail of the class are in different files.
+ * error.c (dump_decl): Don't bother processing a function with no
+ DECL_LANG_SPECIFIC.
- * decl.c (grokdeclarator): Don't treat a function pointer field
- with the same name as the class as a constructor.
+ * method.c (emit_thunk): Call init_function_start in the macro case.
-Fri Sep 9 13:17:00 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Aug 13 10:46:19 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
- * typeck.c (build_c_cast): Pull constant values out of their
- variables here.
+ * decl2.c (DEFAULT_VTABLE_THUNKS): Define to be 0 if not
+ defined and used to set flag_vtable_thunks.
- * decl.c (duplicate_decls): Only propagate DECL_CHAIN in
- FUNCTION_DECLs and TEMPLATE_DECLs.
+Tue Aug 12 20:13:57 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Sep 8 10:07:48 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * parse.y: Don't clear the inlines from their obstack until they've
+ all been processed.
- * decl.c (duplicate_decls): Propagate DECL_CHAIN in all DECLs that
- have it.
+ * decl.c (duplicate_decls): Don't complain about exception
+ specification mismatch if flag_exceptions is off.
- * pt.c (unify): REALs and INTEGERs only unify with their own genus.
- (instantiate_member_templates): Don't muck with DECL_EXTERNAL and
- TREE_PUBLIC unless -fexternal-templates.
+Mon Aug 11 15:01:56 1997 Marc Lehmann <pcg@goof.com>
-Wed Sep 7 13:17:10 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * Make-lang.in (c++.distclean): Remove g++.c on make distclean.
- * pt.c (do_type_instantiation): Call instantiate_member_templates.
- Deal with specializations.
- (tsubst): Don't stick the mangled name in DECL_NAME for function
- instantiations. Don't push them, either.
+Sun Aug 10 12:06:09 1997 Paul Eggert <eggert@twinsun.com>
- * decl2.c (grokfield): Move code for generating the
- DECL_ASSEMBLER_NAME for static members from here.
- * method.c (build_static_name): To here.
- * decl.c (grokvardecl): Call build_static_name.
- (duplicate_decls): Keep old DECL_ASSEMBLER_NAME.
+ * cp-tree.h: Replace STDIO_PROTO with PROTO in include files.
+ * cvt.c, error.c, except.c, expr.c, friend.c, init.c, rtti.c:
+ Include <stdio.h> before include files that formerly used STDIO_PROTO.
-Mon Sep 5 12:49:18 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c, g++spec.c, lex.c, method.c, repo.c:
+ Include "config.h" first, as per autoconf manual.
- * call.c (build_method_call): if -Wsynth, warn when selecting
- synthesized op= over user-supplied one cfront would select.
- * decl2.c (lang_decode_option): Handle -Wsynth.
+Fri Aug 8 11:47:48 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Sep 2 15:11:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (duplicate_decls): Tweak wording.
+ * lex.c (do_pending_defargs): Don't die if we see a default arg
+ that isn't a DEFAULT_ARG.
+ * error.c (dump_expr): Handle DEFAULT_ARG.
- * decl.c (finish_enum): Overhaul to fix several bugs.
- (start_enum): Disable useless code.
+ * decl2.c (lang_decode_option): Handle -fhandle-exceptions.
+ * lang-options.h: Add -fhandle-exceptions.
-Thu Sep 1 16:04:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * class.c (build_vtable): vtables are artificial.
+ (prepare_fresh_vtable): Likewise.
- * typeck.c (c_expand_return): Warn about returning a reference to a
- temporary.
- (convert_arguments): Increment argument counter when using default
- arguments, too.
+Wed Aug 6 11:02:36 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Aug 31 14:29:22 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cvt.c (ocp_convert): After converting to the target type, set
+ LOOKUP_NO_CONVERSION.
- * decl.c (finish_decl): If the type of decl is error_mark_node,
- don't bother trying to do anything.
+ * call.c (joust): Warn about potentially confusing promotion rules
+ with -Wsign-promo.
+ * cp-tree.h, lang-options.h, decl2.c: Support -Wsign-promo.
- * typeck.c (convert_for_initialization): If the rhs contains a
- constructor call, pretend the lhs type needs to be constructed.
+Tue Aug 5 15:15:07 1997 Michael Meissner <meissner@cygnus.com>
- * init.c (expand_default_init): If we stick the object inside the
- initializer, mark the initializer used.
+ * exception.cc: Declare __terminate_func with noreturn attribute.
-Tue Aug 30 13:50:18 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Aug 1 03:18:15 1997 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (build_assign_ref): return *this;
- (build_assign_ref): Fix base assignment order.
- (build_copy_constructor): Fix member init order.
+ * parse.y: Break out eat_saved_input, handle errors.
+ (function_try_block): Use compstmt instead of compstmt_or_error.
-Mon Aug 29 13:54:39 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+Thu Jul 31 17:14:04 1997 Jason Merrill <jason@yorick.cygnus.com>
- * g++.c (main): Remember to clear out SAW_SPECLANG after we see
- its argument.
+ * tree.c (build_cplus_new): Don't set TREE_ADDRESSABLE.
-Sat Aug 27 09:36:03 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Jul 4 01:45:16 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
- * method.c (build_copy_constructor): Also copy virtual bases.
+ * Make-lang.in (cplib2.txt, cplib2.ready): Instead of checking for
+ existence of cc1plus check whether $(LANGUAGES) contains C++.
-Fri Aug 26 17:05:15 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Jul 30 13:04:21 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
- * lex.c (do_pending_inlines): Clear out pending_inlines before doing
- any synthesis. Also first set deja_vu on all pending_inlines.
+ * method.c (do_build_copy_constructor): When copying an anonymous
+ union member loop around to handle nested anonymous unions. Use
+ the offset of the member relative to the outer structure, not the
+ union.
- * method.c (build_assign_ref): Use build_member_call to invoke base
- operator=, rather than build_modify_expr. And use
- build_reference_type instead of TYPE_REFERENCE_TO.
- (build_copy_constructor): Use TYPE_NESTED_NAME to identify the
- basetype.
+Tue Jul 29 21:17:29 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (grokfield): Don't complain about undefined local class
- methods.
+ * call.c (resolve_args): New fn.
+ (build_new_function_call): Use it.
+ (build_object_call): Likewise.
+ (build_new_method_call): Likewise.
- * class.c (finish_struct): Don't try to synthesize methods here.
- * lex.c (do_pending_inlines): Instead, synthesize them here.
- (init_lex): Initialize synth_obstack.
- (cons_up_default_function): Stick synthesis request on
- pending_inlines.
+Mon Jul 28 16:02:36 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Aug 26 12:24:14 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * call.c (build_over_call): tsubst all default parms from templates.
- * call.c (build_method_call) [PCC_STATIC_STRUCT_RETURN]: Also
- accept an RTL_EXPR in what we're about to use for the instance,
- since anything which would end up with pcc_struct_return set
- inside cplus_expand_expr.
+Wed Jul 23 13:36:25 1997 Jason Merrill <jason@yorick.cygnus.com>
- * cp-tree.h (cons_up_default_function): Note change of prototype.
+ * decl.c (struct cp_function): Add static_labelno.
+ (push_cp_function_context): Save it.
+ (pop_cp_function_context): Restore it.
-Thu Aug 25 23:05:30 1994 Gerald Baumgartner (gb@cs.purdue.edu)
+Tue Jul 22 14:43:29 1997 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Undid change from Aug 21 testing
- CLASSTYPE_INTERFACE and CLASSTYPE_VTABLE_NEEDS_WRITING.
- * parse.y (left_curly): Ditto, undid change from Aug 21.
- * decl.c (xref_tag): Undid change from Aug 21, set
- CLASSTYPE_INTERFACE correctly, and added comments.
+ * typeck.c (build_component_ref_1): Convert from reference.
-Thu Aug 25 00:36:31 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Jul 22 11:06:23 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- Rework approach to synthesized methods; don't go through the parser
- anymore.
- * class.c (finish_struct): Use new synthesis approach.
- * lex.c (cons_up_default_function): Now just creates declaration,
- not code.
- (largest_union_member): #if 0 out.
- (default_assign_ref_body): Ditto.
- (default_copy_constructor_body): Ditto.
- * method.c (build_default_constructor): New function to synthesize X().
- (build_copy_constructor): Synthesize X(X&).
- (build_assign_ref): Synthesize X::operator=(X&).
- (build_dtor): Synthesize ~X().
+ * parse.y (current_declspecs, prefix_attributes): Initialize to
+ NULL_TREE.
- * error.c (cp_line_of): If we're dealing with an artificial
- TYPE_DECL, look at the type instead.
+ * parse.y (initdcl0): Make sure CURRENT_DECLSPECS is non-nil
+ before we try to force it to be a TREE_LIST.
+ (decl): Make sure $1.t is non-nil.
-Wed Aug 24 11:11:50 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sun Jul 20 11:53:07 1997 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (sort_member_init): Check warn_reorder.
- * decl2.c (lang_decode_option): Handle -W{no-,}reorder.
+ * pt.c (uses_template_parms): Handle template first-parse codes.
- * cp-tree.h (CLASSTYPE_SOURCE_LINE): New macro.
- * error.c (cp_line_of): Use CLASSTYPE_SOURCE_LINE for aggregates.
- * class.c (finish_struct): Set CLASSTYPE_SOURCE_LINE.
+ * decl.c (cp_finish_decl): Only warn about user-defined statics.
-Tue Aug 23 09:28:35 1994 Mike Stump <mrs@cygnus.com>
+Fri Jul 18 17:56:08 1997 Jason Merrill <jason@yorick.cygnus.com>
- * error.c (dump_decl): Improve wording, so that error messages
- dont't read template<, class foo>...
+ * pt.c (unify): Handle BOOLEAN_TYPE.
-Mon Aug 22 15:30:51 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * cp-tree.h: Lose PARM_DEFAULT_FROM_TEMPLATE.
+ * pt.c (tsubst): Don't set it.
+ * call.c (build_over_call): Use uses_template_parms.
- * parse.y (label_colon): Also match a TYPENAME as a label name,
- since they may have declared a class by that name but have also
- tried to have a local label under the same name.
+Thu Jul 17 18:06:30 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (coerce_template_parms): Call cp_error, not cp_error_at,
- for the message so they know at what point it was instantiated.
+ * method.c (build_overload_nested_name): Use static_labelno
+ instead of var_labelno.
+ (build_qualified_name): New fn.
+ (build_overload_name): Split out from here.
+ (build_static_name): Use build_qualified_name.
+ * decl.c (cp_finish_decl): Statics in extern inline functions
+ have comdat linkage.
+ (start_function): Initialize static_labelno.
-Sun Aug 21 23:07:35 1994 Gerald Baumgartner (gb@cs.purdue.edu)
+Thu Jul 17 11:20:17 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * class.c (finish_struct): Move setting of CLASSTYPE_INTERFACE and
- CLASSTYPE_VTABLE_NEEDS_WRITING for signatures up to left_curly time.
- * decl.c (xref_tag): Move setting of CLASSTYPE_INTERFACE and
- CLASSTYPE_VTABLE_NEEDS_WRITING for signatures down to left_curly time.
- * parse.y (left_curly): New final resting place for setting
- CLASSTYPE_INTERFACE and CLASSTYPE_VTABLE_NEEDS_WRITING for signatures.
+ * class.c (finish_struct_methods): add check of warn_ctor_dtor_privacy
+ before "all member functions in class [] are private"
- * class.c (finish_struct): Don't test for function/field name
- conflicts in signatures, since all the fields are compiler-constructed.
+Wed Jul 16 23:47:08 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Aug 19 14:04:47 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * lex.c (do_scoped_id): convert_from_reference.
+ * init.c (build_offset_ref): Likewise.
- * method.c (build_overload_nested_name): in qualified name
- mangling, the template with value instantiation will have numeric
- at end and may mixed with the name length of next nested level.
- Add a '_' in between.
- * method.c (build_overload_name): ditto.
- * method.c (build_overload_identifier): ditto.
+Wed Jul 16 12:34:29 1997 Benjamin Kosnik <bkoz@lisa.cygnus.com>
-Thu Aug 18 16:24:43 1994 Mike Stump <mrs@cygnus.com>
+ * error.c (dump_expr): Check TREE_OPERAND before dump_expr_list.
- * error.c (dump_decl): Handle NULL args.
+Mon Jul 14 03:23:46 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Sep 29 16:15:36 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+ * typeck.c (get_member_function_from_ptrfunc): Promote index
+ before saving it.
- * g++.c: Rework last change so it's done like collect.c (and
- gcc.c).
+Sun Jul 13 00:11:52 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Sep 14 10:17:27 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+ * tree.c (layout_basetypes): Move non-virtual destructor warning.
+ * decl.c (xref_basetypes): Remove non-virtual destructor warning.
- * g++.c: Include <sys/errno.h> in case `errno' is a macro
- as permitted by ANSI C.
+Sat Jul 12 12:47:12 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Aug 18 12:48:09 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (grokdeclarator): Call add_defarg_fn for the function
+ type, too.
+ * lex.c (add_defarg_fn): Adjust.
+ (do_pending_defargs): Adjust. Don't skip the first parm.
- * class.c (finish_struct): Move setting of CLASSTYPE_INTERFACE and
- CLASSTYPE_VTABLE_NEEDS_WRITING up to left_curly time.
- * decl.c (xref_tag): Move setting of CLASSTYPE_INTERFACE and
- CLASSTYPE_VTABLE_NEEDS_WRITING down to left_curly time.
- * parse.y (left_curly): New final resting place for setting
- CLASSTYPE_INTERFACE and CLASSTYPE_VTABLE_NEEDS_WRITING.
+Fri Jul 11 01:39:50 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Aug 11 11:32:42 1994 H.J. Lu (hjl@nynexst.com)
+ * decl.c (build_enumerator): Global enumerators are also readonly.
- * g++.c (main): Only decrement "added" and set "library" to
- NULL when "library" != NULL.
+ * rtti.c (build_dynamic_cast_1): Renamed from build_dynamic_cast.
+ (build_dynamic_cast): Call it and convert_from_reference.
-Sat Aug 13 00:14:52 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * lex.c (add_defarg_fn): New fn.
+ (snarf_defarg): Don't add to defarg_types.
+ (do_pending_defargs): Lose defarg_types. All fns we process now
+ have defargs.
+ * decl.c (grokfndecl): Call add_defarg_fn.
- * decl.c (grokdeclarator): Don't set TREE_PUBLIC on a function decl
- just because its class has a known interface.
- (decls_match): Deal with new format of template parms.
+ * Makefile.in (CONFLICTS): Expect 18 s/r conflicts.
+ * cp-tree.def: Add DEFAULT_ARG.
+ * spew.c (yylex): Call snarf_defarg as appropriate.
+ * parse.y: New tokens DEFARG and DEFARG_MARKER.
+ (defarg_again, pending_defargs, defarg, defarg1): New rules.
+ (structsp): Use pending_defargs.
+ (parms, full_parm): Use defarg.
+ * lex.c (init_lex): Initialize inline_text_firstobj.
+ (do_pending_inlines): Never pass the obstack to feed_input.
+ (process_next_inline): Call end_input instead of restore_pending_input.
+ (clear_inline_text_obstack, reinit_parse_for_expr, do_pending_defargs,
+ finish_defarg, feed_defarg, snarf_defarg, maybe_snarf_defarg): New fns.
+ * input.c (end_input): New fn.
+ (sub_getch): At the end of some fed input, just keep returning EOF
+ until someone calls end_input.
+ Remove 'obstack' field from struct input_source.
+ * decl.c (grokparms): Handle DEFAULT_ARG.
+ (replace_defarg): New fn.
+ * cp-tree.h (DEFARG_LENGTH, DEFARG_POINTER): New macros.
- * lex.c (cons_up_default_function): Don't play with TREE_PUBLIC and
- DECL_EXTERNAL here.
+Wed Jul 9 13:44:12 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Aug 12 01:55:15 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (implicit_conversion): If nothing else works, try binding
+ an rvalue to a reference.
- * decl.c (pushtag): SET_DECL_ARTIFICIAL on gratuitous typedefs.
- (xref_defn_tag): Ditto.
- (pushdecl): Only allow artificial typedefs to be shadowed.
+Wed Jul 9 13:04:38 1997 Geoffrey Noer <noer@cygnus.com>
- * init.c (emit_base_init): Pass the right binfos to
- expand_aggr_init_1.
+ * decl.c (init_decl_processing): fix Jun 30 patch -- move
+ ifndef for Cygwin32 to include SIGSEGV.
- * class.c (delete_duplicate_fields_1): Make it work right.
- (finish_struct): Catch function/field name conflict.
+Thu Jul 3 01:44:05 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (check_classfn): Pass the function to cp_error, not just
- the name.
+ * class.c (finish_struct_1): Only complain about pointers without
+ copy stuff if there are any constructors.
- * init.c (sort_member_init): Warn when order of member initializers
- does not match order of member declarations.
- (emit_base_init): Call expand_aggr_init_1 with LOOKUP_PROTECT.
+ * rtti.c (build_dynamic_cast): Call complete_type on the types.
- * error.c (dump_expr): Handle lists of functions.
+ * decl.c (grokfndecl): If the function we chose doesn't actually
+ match, die.
- * decl.c (start_function): #pragma interface only affects functions
- that would otherwise be static.
- (finish_decl): Don't warn about an unused variable if it has both
- constructor and destructor, since the 'resource allocation is
- initialization' idiom is relatively common.
+ * decl2.c (grokclassfn): Don't specify 'const int' for the
+ artificial destructor parm.
- * typeck.c (comp_target_types): Don't handle TEMPLATE_TYPE_PARMs.
- (comp_target_parms): Ditto.
- (compparms): Never consider default parms.
- (common_base_type): Don't choose a virtual baseclass if there is a
- more derived class in common.
- (build_conditional_expr): If pedantic, pedwarn about conversion to
- common base in conditional expr.
+ * pt.c (type_unification): If we are called recursively, nothing
+ decays.
- * class.c (instantiate_type): Handle template instantiation better.
+Mon Jun 30 17:53:21 1997 Geoffrey Noer <noer@cygnus.com>
- * typeck.c (convert_arguments): Don't try to get tricky and convert
- to int directly when PROMOTE_PROTOTYPES is set, as it breaks
- user-defined conversions.
+ * decl.c (init_decl_processing): Stop trying to catch signals
+ other than SIGABRT since the Cygwin32 library doesn't support
+ them correctly yet. This fixes a situation in which g++ causes
+ a hang on SIGSEGVs and other such signals in our Win32-hosted
+ tools.
- * lex.c (check_for_missing_semicolon): Also give error at end of
- file.
+Mon Jun 30 14:50:01 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Don't promote arrays to pointers here.
+ * tree.c (mapcar, case CALL_EXPR): Handle all the parse node data.
- * typeck.c (convert_arguments): Don't require the actual parameter
- to be of a complete type if the formal parameter is a reference.
+Fri Jun 27 15:18:49 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Aug 11 15:21:40 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck2.c (store_init_value): Always return the value if our
+ type needs constructing.
- * decl.c (grokdeclarator): Soften 'static' on member function error
- to pedwarn.
+ * method.c (hack_identifier): Convert class statics from
+ reference, too.
- * init.c (build_new): Don't automatically save rval.
- (build_offset_ref): Do field lookup with proper basetype_path.
+Thu Jun 26 11:44:46 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Aug 11 12:46:54 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * Make-lang.in (cplib2.ready): Add $(LANGUAGES) dependency.
- * errfn.c (cp_silent): Declare to mark when we should avoid
- emitting warnings and errors.
- (cp_error): Check it.
- (cp_warning): Likewise.
- (cp_pedwarn): Likewise.
- (cp_compiler_error): Likewise.
- (cp_error_at): Likewise.
- (cp_warning_at): Likewise.
- (cp_pedwarn_at): Likewise.
- * call.c (compute_conversion_costs): Set CP_SILENT when we start
- out, and make sure we turn it off before we leave.
+Thu Jun 19 16:49:28 1997 Mike Stump <mrs@cygnus.com>
-Thu Aug 11 00:02:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (c_expand_return): Make sure we clean up temporaries at
+ the end of return x;
- * decl2.c (grok_array_decl): Try computing *(A+B) if neither
- argument is obviously an array.
+Thu Jun 19 12:28:43 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Aug 10 15:32:04 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * lex.c (check_for_missing_semicolon): Also check for CV_QUALIFIER.
- * typeck.c (c_expand_start_case): Do cleanups here.
+Tue Jun 17 18:35:57 1997 Mike Stump <mrs@cygnus.com>
- * parse.y (xcond): Do bool conversion here, too.
- (simple_stmt, SWITCH case): Don't do cleanups here.
+ * except.c (expand_builtin_throw): Add support
+ -fno-sjlj-exceptions -fPIC exception handling on the SPARC.
- * decl.c (duplicate_decls): Don't treat builtins that have been
- explicitly declared specially.
+Mon Jun 16 01:24:37 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue Aug 9 01:16:09 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * repo.c (extract_string): Null-terminate.
- * tree.c (make_deep_copy): Support copying pointer, reference,
- function, array, offset and method types.
+ * cp-tree.h (TI_SPEC_INFO): New macro.
+ (CLASSTYPE_TI_SPEC_INFO): New macro.
+ * pt.c (push_template_decl): Correctly determine # of template parms
+ for partial specs.
- * decl.c (init_decl_processing): Mark exit and abort as
- BUILT_IN_NONANSI so that duplicate_decls is kinder about
- redeclaration.
- (duplicate_decls): Don't give two errors for redeclaring a C
- function with the same parms but a different return type.
+ * call.c (compare_ics): Really fix 'this' conversions.
- * parse.y (paren_cond_or_null): Do cleanup and bool conversion here.
- (condition): Instead of here.
- (simple_stmt, SWITCH case): Also do cleanup here.
+ * pt.c (do_decl_instantiation): Don't crash on explicit inst of
+ non-template fn.
- * decl2.c (finish_anon_union): Only break out FIELD_DECLs.
+ * pt.c (push_template_decl): Complain about mismatch in # of
+ template parms between a class template and a member template.
- * call.c (build_method_call): Don't throw away the side effects of
- the object in a call to a non-existent constructor.
- * parse.y (primary): Ditto.
+Sun Jun 15 02:38:20 1997 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (build_decl_overload): Oop.
+ * method.c (synthesize_method): You can't call
+ function_cannot_inline_p after finish_function.
+ * decl.c (finish_function): Turn on flag_inline_functions and turn
+ off DECL_INLINE before handing a synthesized method to the
+ backend.
- * decl2.c (lang_decode_option): Deal with flag_no_nonansi_builtin,
- warn about uselessness of specifying -fansi-overloading.
+Thu Jun 12 17:35:28 1997 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (build_decl_overload): Treat any non-member new with one
- parameter as __builtin_new.
+ * method.c (synthesize_method): Remove July 30 change to never set
+ DECL_INLINE if at_eof.
- * decl.c (init_decl_processing): Setup built-in meanings of exit,
- _exit and abort.
+Thu Jun 12 15:25:08 1997 Mike Stump <mrs@cygnus.com>
-Mon Aug 8 15:03:30 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * xref.c (GNU_xref_member): Ensure that the node has a
+ decl_lang_specific part before checking DECL_FRIEND_P.
- * error.c (dump_readonly_or_volatile): Put a space between const and
- volatile if both apply.
+Thu Jun 12 12:36:05 1997 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (perform_member_init): Clean up after this initialization.
- (emit_base_init): Clean up after each base init, not after all have
- been done.
- (expand_aggr_vbase_init_1): Clean up after this init.
+ * pt.c (instantiate_class_template): Diagnose non-class types used
+ as bases.
-Sun Aug 7 14:55:05 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Jun 11 17:33:40 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Deal with destroying references.
+ * typeck.c (build_conditional_expr): Use convert_for_initialization
+ instead of convert_and_check.
- * parse.y (condition): Do bool_truthvalue_conversion here.
- (paren_expr_or_null): And here.
- (simple_if): Not here.
- (simple_stmt): Or here.
+Wed Jun 11 12:31:33 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Sat Aug 6 22:29:45 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * parse.y (typespec): Don't pedwarn for typeof.
- * parse.y (paren_expr_or_null): Wrap the expression in a
- CLEANUP_POINT_EXPR.
- (condition): Ditto.
+Tue Jun 10 00:22:09 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sat Aug 6 19:46:37 1994 Rohan Lenard (rjl@easams.com.au)
+ * repo.c (finish_repo): Only check changes if we would write a
+ repo file.
- * call.c (build_scoped_method_call): Fix error message when
- destructor call refers to a nonexistent type.
+ * call.c (compare_ics): Fix handling of 'this' conversions.
-Sat Apr 16 22:43:30 1993 Gerald Baumgartner (gb@cs.purdue.edu)
+ * pt.c (do_decl_instantiation): Support static data too. Rename
+ from do_function_instantiation.
+ * cp-tree.h: Adjust.
+ * parse.y: Adjust.
- * lex.h (rid): Deleted RID_RAISES, it's never used.
- Moved RID_PUBLIC, RID_PRIVATE, RID_PROTECTED, RID_EXCEPTION,
- RID_TEMPLATE and RID_SIGNATURE to the end of the enumeration,
- they don't need to be touched in `grokdeclarator.'
- (RID_LAST_MODIFIER): Defined macro to be RID_MUTABLE.
+ * repo.c (extract_string): New fn.
+ (get_base_filename): Use it.
+ (init_repo): Compare old args with current args.
- * decl.c (grokdeclarator): Use RID_LAST_MODIFIER instead of
- RID_MAX as loop limit for finding declaration specifiers.
+Mon Jun 9 14:25:30 1997 Mike Stump <mrs@cygnus.com>
-Sat Apr 3 21:59:07 1993 Gerald Baumgartner (gb@cs.purdue.edu)
+ * Makefile.in, Make-lang.in: Protect C-ls with a comment
+ character, idea from Paul Eggert <eggert@twinsun.com>.
- * lex.c (debug_yytranslate): Moved to parse.y since it needs to
- access `yytname,' which is static in parse.c.
+Mon Jun 9 01:52:03 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Apr 2 23:36:57 1993 Gerald Baumgarnter (gb@cs.purdue.edu)
+ * typeck.c (c_expand_return): Be more persistent in looking for
+ returned temps.
- * cp-tree.h (GNU_xref_ref): Fixed typo in extern declaration, it
- was `GNU_xref_def' instead of `GNU_xref_ref.'
+ * cvt.c (build_up_reference): Use NOP_EXPR for switching from
+ pointer to reference.
-Fri Aug 5 14:20:16 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * class.c (build_vbase_path): Don't do anything if PATH has no steps.
- * pt.c (do_function_instantiation): Don't set TREE_PUBLIC and
- DECL_EXTERNAL on 'extern' instantiations; wait until EOF to do that.
- (do_type_instantiation): Ditto.
+Sun Jun 8 03:07:05 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (import_export_inline): Decides at EOF what an inline's
- linkage should be.
- (finish_file): Call it.
+ * init.c (build_member_call, build_offset_ref):
+ Use do_scoped_id instead of do_identifier.
- * decl.c (start_function): Don't rely on the settings of TREE_PUBLIC
- and DECL_EXTERNAL from do_*_instantiation. Only set
- DECL_DEFER_OUTPUT on inlines whose linkage might actually change.
- (finish_function): Use DECL_DEFER_OUTPUT to decide which inlines to
- mark for later consideration, rather than DECL_FUNCTION_MEMBER_P.
+ * cvt.c (convert): Remove bogosity.
-Fri Aug 5 01:12:20 1994 Mike Stump <mrs@cygnus.com>
+Sat Jun 7 20:50:17 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * class.c (get_class_offset_1, get_class_offset): New routine to
- find the offset of the class where a virtual function is defined,
- from the complete type.
- * class.c (modify_one_vtable, fixup_vtable_deltas): Use
- get_class_offset instead of virtual_offset as get_class_offset will
- always provide the right answer.
- * tree.c (virtual_offset): Remove. It only ever worked some of the
- time.
+ * cvt.c (build_up_reference): Do checks of ARGTYPE and
+ TARGET_TYPE before trying to use get_binfo.
-Tue Aug 2 12:44:21 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Jun 6 17:36:39 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Put back unary_complex_lvalue call
- that I thought was redundant.
+ * cvt.c (build_up_reference): Call get_binfo to get access control.
- * typeck.c (c_expand_return): Fix a case I missed before.
+ * decl2.c (import_export_decl): If we don't support weaks, leave
+ statics undefined.
-Sun Jul 31 17:54:02 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Jun 6 15:55:49 1997 Mike Stump <mrs@cygnus.com>
- * pt.c (unify): Strip cv-quals from template type arguments (when
- 'const T*' is matched to 'const char*', that does not mean that T is
- 'const char').
+ * except.c (expand_builtin_throw): Add support for machines that
+ cannot access globals after throw's epilogue when
+ -fno-sjlj-exceptions is used.
-Fri Jul 29 01:03:06 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Jun 5 16:28:43 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (do_type_instantiation): Instantiate nested TAGS, not
- typedefs. Third time's the charm?
+ * parse.y: 'std::' becomes '::'.
+ * lex.c (real_yylex): Remove 'namespace' warning.
+ * init.c (build_member_call): Ignore 'std::'.
+ (build_offset_ref): Likewise.
+ * decl2.c (do_using_directive): Ignore 'using namespace std;'.
+ (do_toplevel_using_decl): Ignore 'using std::whatever'.
+ * decl.c (push_namespace): Just sorry.
+ (pop_namespace): Nop.
+ (init_decl_processing): Declare std namespace.
- * parse.y (template_parm): Support default template parms.
- * pt.c (process_template_parm): Ditto.
- (end_template_parm_list): Ditto.
- (coerce_template_parms): Ditto.
- (mangle_class_name_for_template): Ditto.
- (push_template_decls): Ditto.
- (unify): Ditto.
- * method.c (build_overload_identifier): Ditto.
- * error.c (dump_decl): Ditto.
+Tue Jun 3 18:08:23 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jul 27 17:47:00 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * search.c (push_class_decls): A name which ambiguously refers to
+ several instantiations of the same template just refers to the
+ template.
- * pt.c (do_type_instantiation): Only instantiate nested *classes*.
+Tue Jun 3 12:30:40 1997 Benjamin Kosnik <bkoz@cirdan.cygnus.com>
-Tue Jul 26 13:22:40 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (build_enumerator): fix problem with unsigned long
+ enumerated values being smashed to ints, causing overflow
+ when computing next enumerated value. (for enum values around
+ MAX_VAL).
- * search.c (note_debug_info_needed): Also emit debugging information
- for the types of fields.
+Mon Jun 2 17:40:56 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Jul 25 00:34:44 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (build_component_ref): Only call mark_used on a decl.
- * pt.c (lookup_template_class): Pass 'template' to
- coerce_template_parms instead of 'in_decl', since it's a more
- meaningful context.
+Thu May 29 15:54:17 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck.c (c_expand_return): Make sure any cleanups for the return
- expression get run.
- (build_c_cast): Use CONVERT_EXPR for conversion to void.
+ * typeck.c (build_c_cast): Make the check for a ptr to function
+ more specific before possible default_conversion call.
- * pt.c (do_type_instantiation): Also instantiate nested types.
+Thu May 29 13:02:06 1997 Mike Stump <mrs@cygnus.com>
- * typeck.c (convert_for_assignment): Don't die when comparing
- pointers with different levels of indirection.
+ * except.c (expand_exception_blocks): Simplify and fix and make
+ sure we don't end a region in a sequence, as expand_end_bindings
+ doesn't like it.
- * decl.c (grokdeclarator): The sub-call to grokdeclarator for
- class-local typedefs sets DECL_ARGUMENTS, so we need to clear it
- out.
+Wed May 28 17:08:03 1997 Mike Stump <mrs@cygnus.com>
- * decl2.c (finish_anon_union): Don't die if the union has no
- members.
+ * except.c (init_exception_processing): Mark terminate as not
+ returning so that the optimizer can optimize better.
- * decl.c (grokdeclarator): Undo changes to declspecs when we're done
- so that 'typedef int foo, bar;' will work.
+Tue May 27 19:49:19 1997 Mike Stump <mrs@cygnus.com>
- * decl2.c (finish_file): Don't call expand_aggr_init for
- non-aggregates.
+ * cvt.c (convert): Don't do any extra work, if we can avoid it
+ easily.
-Mon Jul 25 00:03:10 1994 Teemu Torma (tot@trema.fi)
+Tue May 27 18:21:47 1997 Mike Stump <mrs@cygnus.com>
- * decl.c (finish_function): We can't inline constructors and
- destructors under some conditions with -fpic, but don't unset
- DECL_INLINE.
+ * *.[chy]: Change cp_convert to ocp_convert, change convert to
+ cp_convert. convert is now reserved for the backend, and doesn't
+ have the semantics a frontend person should ever want.
-Mon Jul 25 00:03:10 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri May 23 10:58:31 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_object_ref): Make sure 'datum' is a valid object.
+ * lang-specs.h: Define __EXCEPTIONS if exceptions are enabled.
+ Lose -traditional support.
-Sun Jul 24 14:19:31 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu May 22 15:41:28 1997 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Don't set DECL_FIELD_BITPOS on
- non-fields.
- (finish_struct_methods): Use copy_assignment_arg_p.
+ * rtti.c (get_tinfo_var): Use TYPE_PRECISION (sizetype).
- * cvt.c (cp_convert): If expr is an OFFSET_REF, resolve it instead
- of giving an error.
+ * parse.y (self_reference): Do it for templates, too.
+ * class.c (pushclass): Don't overload_template_name; the alias
+ generated by build_self_reference serves the same purpose.
- * typeck.c (build_binary_op_nodefault): Don't set result_type if we
- don't know how to compare the operands.
+ * tree.c (list_hash): Make static, take more args.
+ (list_hash_lookup): Likewise.
+ (list_hash_add): Make static.
+ (list_hash_canon): Lose.
+ (hash_tree_cons): Only build a new node if one isn't already in the
+ hashtable.
+ (hash_tree_chain): Use hash_tree_cons.
+ * cp-tree.h: Adjust.
+ * decl.c (grokfndecl): Just check IDENTIFIER_GLOBAL_VALUE instead
+ of calling lookup_name.
- * decl.c (grokdeclarator): Avoid seg fault when someone uses '__op'
- as a declarator-id in their program. Like the Linux headers do.
- Arrgh.
+Wed May 21 18:24:19 1997 Jason Merrill <jason@yorick.cygnus.com>
- * tree.c (lvalue_p): Treat calls to functions returning objects by
- value as lvalues again.
+ * pt.c (instantiate_class_template): TYPE_VALUES for an enum
+ doesn't refer to the CONST_DECLs.
- * typeck.c (build_component_addr): Use convert_force to convert the
- pointer in case the component type is also a private base class.
+Tue May 20 21:09:32 1997 Bob Manson <manson@charmed.cygnus.com>
- * search.c (get_matching_virtual): Fix bogus warning of overloaded
- virtual.
+ * rtti.c (get_tinfo_var): Either INT_TYPE_SIZE or 32, whichever
+ is bigger.
+ (expand_class_desc): Convert the last argument to a sizetype.
- * pt.c (overload_template_name): Set DECL_ARTIFICIAL on the created
- TYPE_DECL to fix bogus shadowing warnings.
+Tue May 20 13:55:57 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Fri Jul 22 01:15:32 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * gxx.gperf (__complex, __complex__, __imag, __imag__, __real,
+ __real__): Add reswords.
+ * hash.h: Regenerate.
+ * lex.h (rid): Add RID_COMPLEX.
+ (RID_LAST_MODIFIER): Set to RID_COMPLEX.
+ * lex.c (init_lex): Add building of RID_COMPLEX.
+ (real_yylex): General cleanup in line with what c-lex.c also has,
+ sans the cruft for traditional; add handling of SPEC_IMAG, complex
+ types, and imaginary numeric constants.
+ * parse.y (REALPART, IMAGPART): Add tokens.
+ (unary_expr): Add REALPART and IMAGPART rules.
+ * cp-tree.h (complex_{integer,float,double,long}_type_node): Declare.
+ * decl.c (complex_{integer,float,double,long}_type_node): Define
+ types.
+ (init_decl_processing): Set up the types.
+ (grokdeclarator): Add handling of RID_COMPLEX. Set and use
+ DEFAULTED_INT instead of EXPLICIT_INT when we default to int type.
+ * call.c (build_new_op): Add REALPART_EXPR and IMAGPART_EXPR cases.
+ * cvt.c (cp_convert): Handle COMPLEX_TYPE.
+ * error.c (dump_type_prefix, dump_type, dump_type_suffix): Add
+ COMPLEX_TYPE case.
+ * method.c (build_overload_name): Add handling of the different
+ COMPLEX_TYPEs, prefixing them with `J'.
+ * pt.c (process_template_parm): Don't let them use a COMPLEX_TYPE
+ as a template parm.
+ (uses_template_parms, tsubst, unify): Add COMPLEX_TYPE case.
+ * tree.c (lvalue_p): Add REALPART_EXPR and IMAGPART_EXPR cases.
+ (mapcar): Handle COMPLEX_CST.
+ * typeck.c (build_binary_op_nodefault): Handle COMPLEX_TYPE.
+ (common_type): Add code for complex types.
+ (build_unary_op): Add REALPART_EXPR and IMAGPART_EXPR cases.
+ (convert_for_assignment): Likewise.
+ (mark_addressable): Add REALPART_EXPR and IMAGPART_EXPR cases.
+
+Mon May 19 12:26:27 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst): Don't pass the MINUS_EXPR for an array domain to
+ tsubst_expr, as it might try to do overload resolution.
+
+Sat May 17 10:48:31 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (instantiate_class_template): Oops.
+
+Fri May 16 14:23:57 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.def: Add TAG_DEFN.
+ * pt.c (tsubst_enum): New fn.
+ (instantiate_class_template): Use it.
+ (tsubst_expr): Support TAG_DEFN.
+ (tsubst): Support local enums.
+ (tsubst_copy): Likewise.
+ * decl.c (finish_enum): Likewise.
+ (start_enum): If this is a local enum, switch to permanent_obstack.
+
+Wed May 14 19:08:28 1997 Mike Stump <mrs@cygnus.com>
+
+ * decl.c (store_parm_decls): Set last_parm_cleanup_insn here.
+ (finish_function): Put the base init code for constructors just
+ after the parm cleanup insns.
+ (struct cp_function): Add last_parm_cleanup_insn.
+ (push_cp_function_context): Likewise.
+ (pop_cp_function_context): Likewise.
+
+Tue May 13 15:51:20 1997 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (expand_aggr_init_1): const and volatile mismatches do not
- prevent a TARGET_EXPR from initializing an object directly.
+ * pt.c (tsubst_copy): Handle BIT_NOT_EXPR.
-Tue Jul 19 17:55:37 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed May 7 11:17:59 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cvt.c (build_up_reference): Allow building up references to
- `this', don't warn about making references to artificial variables
- (like `this').
+ * method.c (emit_thunk) [ASM_OUTPUT_MI_THUNK]: Build up the RTL
+ for THUNK_FNDECL before we switch to temporary allocation.
- * tree.c (lvalue_p): `this' is not an lvalue.
+Mon May 5 14:46:53 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Accept using a typedef name (or
- template type parameter) for explicit destructor calls.
+ * call.c (build_new_op): Handle null arg2 for ?:.
-Wed Jul 13 03:57:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu May 1 18:26:37 1997 Mike Stump <mrs@cygnus.com>
- * method.c (hack_identifier): Put back old code so lists of
- non-functions will be handled properly.
+ * except.c (expand_exception_blocks): Ensure that we flow through
+ the end of the exception region for the exception specification.
+ Move exception region for the exception specification in, so that
+ it doesn't protect the parm cleanup. Remove some obsolete code.
+ * decl.c (store_parm_decls): Likewise.
+ (finish_function): Likewise.
- * cp-tree.h (TYPE_NEEDS_CONSTRUCTING): #if 0 out; this macro is now
- defined in the language-independent tree.h.
+Tue Apr 29 15:38:54 1997 Jason Merrill <jason@yorick.cygnus.com>
- * tree.c (count_functions): Avoid bogus warning when compiling this
- function.
+ * init.c (build_new): Fix nothrow handling.
-Mon Jul 11 18:37:20 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Apr 29 14:29:50 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (grok_reference_init): Always save the initializer of a
- reference.
+ * init.c (emit_base_init): Don't warn about the initialization
+ list for an artificial member.
-Fri Jul 8 17:41:46 1994 Mike Stump <mrs@cygnus.com>
+Fri Apr 25 17:47:59 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (cplus_expand_expr_stmt): Wrap statement expressions inside
- CLEANUP_POINT_EXPRs so that the stack slots can be reused.
- (disabled for now)
+ * expr.c (do_case): Handle !START case for the error msg.
-Fri Jul 8 12:59:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Apr 25 11:55:23 1997 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (hack_identifier): Fix for new overloading.
+ * decl2.c, lang-options.h: New option -Weffc++.
+ * class.c, decl.c, init.c, typeck.c: Move Effective C++ warnings
+ to -Weffc++.
- * typeck.c (build_binary_op_nodefault): Don't mess with division by
- zero.
+ * decl2.c (finish_prevtable_vardecl): Change NO_LINKAGE_HEURISTICS
+ to MULTIPLE_SYMBOL_SPACES.
-Fri Jul 8 13:20:28 1994 Gerald Baumgartner (gb@cs.purdue.edu)
+Wed Apr 23 18:06:50 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (finish_file): Only call walk_sigtables, if
- flag_handle_signatures is turned on, don't waste time otherwise.
+ * method.c (emit_thunk, generic case): Set current_function_is_thunk.
-Fri Jul 8 02:27:41 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * method.c (emit_thunk, macro case): Set up DECL_RESULT.
- * decl.c (push_overloaded_decl): Don't create overloads of one when
- shadowing a class type.
- * typeck.c (build_x_function_call): Complain about overloads of one.
+ * typeck.c (c_expand_return): Don't complain about returning void
+ to void in an artificial function.
+ * method.c (make_thunk): Change settings of READONLY/VOLATILE,
+ don't set DECL_RESULT, set DECL_ARTIFICIAL.
+ (emit_thunk, generic code): Also set up DECL_LANG_SPECIFIC.
- * decl.c (grokdeclarator): Don't try to treat a char* as a tree.
- (grokdeclarator): Fix setting of TREE_STATIC.
- (start_decl): Clear DECL_IN_AGGR_P after calling duplicate_decls.
+Wed Apr 23 14:43:06 1997 Mike Stump <mrs@cygnus.com>
-Thu Jul 7 22:20:46 1994 Gerald Baumgartner (gb@andros.cygnus.com)
+ * init.c (init_decl_processing): Add supoprt for setjmp/longjmp based
+ exception handling.
+ * except.c (init_exception_processing): Likewise.
+ (expand_end_catch_block): Likewise.
+ (expand_exception_blocks): Likewise.
+ (expand_throw): Likewise.
+ * exception.cc (__default_terminate): Likewise.
- * cp-tree.h (walk_sigtables): Created extern declaration.
- * decl2.c (walk_sigtables): Created function, patterned after
- walk_vtables, even though we only need it to write out sigtables.
- (finish_sigtable_vardecl): Created function.
- (finish_vtable_vardecl): Changed 0 to NULL_PTR.
- (finish_file): Call walk_sigtables.
+ * init.c (perform_member_init): Use new method of expr level
+ cleanups, instead of cleanups_this_call and friends.
+ (emit_base_init): Likewise.
+ (expand_aggr_vbase_init_1): Likewise.
+ (expand_vec_init): Likewise.
+ * decl.c (cp_finish_decl): Likewise.
+ (expand_static_init): Likewise.
+ (store_parm_decls): Likewise.
+ (cplus_expand_expr_stmt): Likewise.
+ * decl2.c (finish_file): Likewise.
+
+ * Make-lang.in (exception.o): Ok to compile with -O now.
- * sig.c (build_signature_table_constructor): Mark class member
- function pointed to from signature table entry as addressable.
+ * decl.c (maybe_build_cleanup_1): We no longer have to unsave, as
+ we know it will be done later by the backend.
-Thu Jul 7 13:39:37 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (lang_f_options): Remove support for short temps.
+ * lang-options.h: Likewise.
+
+Wed Apr 23 04:12:06 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_decl): Check new decl of static member variable
- against the declaration in the class here.
- (grokvardecl): Instead of here.
+ * tree.c (varargs_function_p): New fn.
+ * method.c (emit_thunk): Replace broken generic code with code to
+ generate a heavyweight thunk function.
- * class.c (prepare_fresh_vtable): Call import_export_vtable if not
- -fvtable-thunks.
- (build_vtable): Ditto.
+Tue Apr 22 02:45:18 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (import_export_vtable): Move logic for deciding the
- interface of a template class from here.
- (import_export_template): To here.
- (finish_vtable_vardecl): Call import_export_template before
- import_export_vtable.
+ * pt.c (process_template_parm): pedwarn about floating-point parms.
-Wed Jul 6 20:25:48 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (grokdeclarator): inline no longer implies static.
- * except.c (init_exception_processing): Setup interim_eh_hook to
- call lang_interim_eh.
- * except.c (do_unwind): Propagate throw object value across
- stack unwinding.
- * except.c (saved_throw_value): Used to hold the value of the object
- being thrown. It is always a reference to the real value.
- * except.c (expand_start_catch_block): Add handling for the
- value of the exception object.
- * except.c (expand_start_catch_block): Add handler for the handler,
- so that throws inside the handler go to the outer block.
- * except.c (expand_end_catch_block): Ditto.
- * parse.y (handler_args): Use parm instead, as the other doesn't yet
- handle references correctly.
+ * spew.c (yylex): Always return the TYPE_DECL if we got a scope.
-Wed Jul 6 17:55:32 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Mon Apr 21 15:42:27 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (mark_vtable_entries): If -ftable-thunks, set the
- vtable entry properly to abort.
+ * class.c (check_for_override): The signature of an overriding
+ function is not changed.
-Tue Jul 5 14:07:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_over_call): Move setting of conv into the loop.
+ Note: this change, along with the related changes of the 18th thru
+ the 20th of April, fix an infinite loop problem in conversions.
- * typeck.c (build_binary_op_nodefault): Downgrade division by zero
- errors to warnings.
+Sun Apr 20 16:24:29 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_overload_call_real): Handle fnname being a list of
- functions.
- * typeck.c (build_x_function_call): Pass list of functions to
- build_overload_call, not just the name.
- * tree.c (count_functions): Complain when called for invalid
- argument.
+ * call.c (build_user_type_conversion_1): Really ignore rvalue
+ conversions when looking for a REFERENCE_TYPE.
- * decl.c (grokdeclarator): Fix settings of TREE_STATIC, TREE_PUBLIC
- and DECL_EXTERNAL on static members and initialized const members.
- * decl2.c (grokfield): Reflect this change.
+ * cvt.c (build_up_reference): Eviscerate, use build_unary_op.
+ * cp-tree.h (TREE_REFERENCE_EXPR): #if 0.
+ * typeck.c (decay_conversion): Don't set TREE_REFERENCE_EXPR.
+ (build_unary_op): Likewise.
+ * call.c (build_over_call): See through a CONVERT_EXPR around the
+ ADDR_EXPR for on a temporary.
+ * typeck.c (c_expand_return): See through a CONVERT_EXPR around
+ the ADDR_EXPR for a local variable.
-Fri Jul 1 09:35:51 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Apr 18 12:11:33 1997 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (init): ANSI C++ does not forbid { }.
+ * call.c (build_user_type_conversion_1): If we're trying to
+ convert to a REFERENCE_TYPE, only consider lvalue conversions.
+ (build_new_function_call): Print candidates.
+ (implicit_conversion): Try a temp binding if the lvalue conv is BAD.
+ (reference_binding): Binding a temporary of a reference-related type
+ is BAD.
-Thu Jun 30 00:35:22 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Apr 17 14:37:22 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl2.c (lang_decode_option): Set warn_nonvdtor along with -Wall.
- warn_nonvdtor defaults to off.
+ * inc/typeinfo (type_info::before): Add cv-qualifier-seq.
+ * tinfo2.cc (type_info::before): Likewise.
- * class.c (instantiate_type): Use comptypes rather than relying on
- types to satisfy ==.
+Mon Apr 14 12:38:17 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_function): Set DECL_DEFER_OUTPUT on all inlines that
- might be static.
+ * call.c (implicit_conversion): Oops.
- * tree.c (build_cplus_new): Never build WITH_CLEANUP_EXPRs.
+Fri Apr 11 02:18:30 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grok_reference_init): Deal with ADDR_EXPRs of TARGET_EXPRs.
+ * call.c (implicit_conversion): Try to find a reference conversion
+ before binding a const reference to a temporary.
- * cvt.c (cp_convert): Pass 0 to with_cleanup_p arg of
- build_cplus_new.
+Wed Apr 2 12:51:36 1997 Mike Stump <mrs@cygnus.com>
-Wed Jun 29 22:31:09 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * exception.cc (__default_unexpected): Call terminate by default,
+ so that if the user overrides terminate, the correct function will
+ be called.
+
+Wed Mar 19 14:14:45 1997 Mike Stump <mrs@cygnus.com>
- * decl2.c (finish_file): Maybe consider static inlines multiple
- times, in case they reference each other.
+ * parse.y (left_curly): Avoid trying to use any fields of
+ error_mark_node, as there aren't any.
-Tue Jun 28 11:58:38 1994 Gerald Baumgartner (gb@cs.purdue.edu)
+Thu Mar 13 16:33:22 1997 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Don't `cons_up_default_function's
- for signatures.
- (finish_struct): Handle an empty method_vec correctly.
+ * lex.c (do_identifier): Avoid breaking on overloaded methods
+ as default arguments.
- * decl.c (grokdeclarator): Don't warn about a signature being
- empty in a signature pointer declaration if we only saw a
- forward declaration of the signature. Changed `warning's into
- `cp_warning's.
+Wed Mar 12 13:55:10 1997 Hans-Peter Nilsson <Hans-Peter.Nilsson@axis.se>
- * sig.c (build_sigtable): Don't die if a null signature table
- constructor is returned.
- (build_signature_pointer_constructor): If the signature table
- constructor is null, the _sptr field is set to a null pointer
- and cast to the appropriate type. Make copies of all null
- pointers so that the type null_pointer_node doesn't get changed.
- (build_signature_table_constructor): Added comments.
+ * call.c (add_template_candidate): Initialize the variable "dummy".
- * sig.c (build_signature_pointer_constructor): Complain if we
- try to assign to/initialize a signature pointer/reference of
- an undefined signature.
+Mon Mar 10 15:13:14 1997 Brendan Kehoe <brendan@canuck.cygnus.com>
-Mon Jun 27 14:05:16 1994 Gerald Baumgartner (gb@cs.purdue.edu)
+ * decl.c (start_decl): Make sure TYPE isn't an error_mark_node
+ before we try to use TYPE_SIZE and TREE_CONSTANT on it.
- * typeck2.c (store_init_value): Don't be pedantic about
- non-constant initializers of signature tables/pointers/references.
+Fri Mar 7 13:19:36 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Fri Jun 24 16:49:41 1994 Gerald Baumgartner (gb@cs.purdue.edu)
+ * cp-tree.h (comp_ptr_ttypes, more_specialized): Add decl.
+ (debug_binfo): Delete decl, not needed.
- * decl.c (grokdeclarator): If we are grokking an opaque typedef
- in a signature, don't complain about it begin static.
+ * tree.c (fnaddr_from_vtable_entry, function_arg_chain,
+ promotes_to_aggr_type): Delete fns.
+ * cp-tree.h (FNADDR_FROM_VTABLE_ENTRY,
+ SET_FNADDR_FROM_VTABLE_ENTRY, FUNCTION_ARG_CHAIN,
+ PROMOTES_TO_AGGR_TYPE): Delete alternates to #if 1.
-Wed Jun 29 16:44:45 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (pending_invalid_xref{,_file,_line}): Delete unused vars.
- Fixes a problem of the this pointer being wrong in virtual calls to
- methods that are not overridden in more derived classes.
+ * friend.c (is_friend_type): Delete fn.
+ * cp-tree.h (is_friend_type): Delete decl.
- * class.c (fixup_vtable_delta): New routine. It will fixup the
- delta entries in vtables, wheever they need updating.
- * class.c (finish_struct): Call the new routine for all virtual
- bases, as they can have different offsets, than those used in base
- classes that we derive our vtable from.
+ * decl.c (original_result_rtx, double_ftype_double,
+ double_ftype_double_double, int_ftype_int, long_ftype_long,
+ float_ftype_float, ldouble_ftype_ldouble, last_dtor_insn): Make static.
+ * typeck.c (original_result_rtx, warn_synth): Delete extern decls.
-Tue Jun 28 23:49:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (push_overloaded_decl{,_top_level}): Make static, adding
+ fwd decls.
+ * cp-tree.h (push_overloaded_decl{,_top_level}): Delete decls.
- * typeck.c (build_binary_op): Use the types before default
- conversions in the error message.
+ * decl.c (pushdecl_nonclass_level): #if 0, unused.
+ * cp-tree.h (pushdecl_nonclass_level): #if 0 decl.
- * *.c: Use c_build_type_variant instead of build_type_variant where
- the type might be an array.
+ * lex.c (reinit_lang_specific): #if 0, unused.
+ * cp-tree.h (reinit_lang_specific): #if 0 decl.
- * call.c (build_method_call): Call build_type_variant and
- build_reference_type in the right order.
- * decl.c (record_builtin_type): Ditto.
+ * decl.c (revert_static_member_fn): Make static, adding fwd decl.
+ * cp-tree.h (revert_static_member_fn): Delete decl.
-Wed Jun 29 16:58:53 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * class.c (root_lang_context_p): Delete fn.
+ * cp-tree.h (root_lang_context_p): Delete decl.
- * call.c (build_method_call): Call build_type_variant and
- build_reference_type in the right order.
- * decl.c (record_builtin_type): Ditto.
+ * decl.c (set_current_level_tags_transparency): #if 0, unused.
+ * cp-tree.h (set_current_level_tags_transparency): #if 0 decl.
-Tue Jun 28 23:49:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * lex.c (set_vardecl_interface_info): Make static.
+ * cp-tree.h (set_vardecl_interface_info): Delete decl.
- * typeck.c (build_binary_op): Use the types before default
- conversions in the error message.
+ * call.c (find_scoped_type): Make static.
+ * cp-tree.h (find_scoped_type): Delete decl.
- * *.c: Use c_build_type_variant instead of build_type_variant where
- the type might be an array.
+ * search.c (convert_pointer_to_vbase): Make static.
+ * cp-tree.h (convert_pointer_to_vbase): Delete decl.
-Sat Jun 25 11:50:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (const_ptr_type_node): Likewise.
+ * cp-tree.h (const_ptr_type_node): Delete decl.
- * cvt.c (convert_to_reference): Try UDC's before doing the
- reinterpret_cast thang, though.
+ * typeck.c (common_base_type): Make static.
+ * cp-tree.h (common_base_types): Delete erroneous decl.
-Fri Jun 24 01:24:01 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (classtype_mangled_name): Make static.
+ * cp-tree.h (classtype_mangled_name): Delete decl.
- * typeck.c (c_expand_return): Don't USE the return value location
- after we've expanded the jump.
+ * lex.c (check_newline): Make static.
+ * cp-tree.h (check_newline): Delete decl.
- * decl2.c (finish_file): Make sure DECL_SAVED_INSNS is not 0 before
- trying to write out an inline.
+ * typeck.c (build_x_array_ref): Delete fn, same idea as
+ grok_array_decl.
+ * cp-tree.h (build_x_array_ref): Delete decl.
- * cvt.c (build_up_reference): Also do address adjustment when the
- target type uses MI.
- (convert_to_reference): Try UDCs only after built-in conversions.
- (build_type_conversion_1): Don't play games with the argument to the
- method.
- (build_type_conversion): #if 0 out code for binding to reference.
+ * lex.c (copy_decl_lang_specific): Delete fn, same idea as
+ copy_lang_decl.
+ * cp-tree.h (copy_decl_lang_specific): #if 0 decl.
-Thu Jun 23 00:22:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * class.c (build_vtable_entry): Make static.
+ * cp-tree.h (build_vtable_entry): Delete decl.
- * decl2.c (finish_file): Use TREE_SYMBOL_REFERENCED to decide
- whether to emit inlines.
+ * class.c (build_vbase_pointer): Make static.
+ * cp-tree.h (build_vbase_pointer): Delete decl.
- * decl.c (grokdeclarator): Set explicit_int for decls that just
- specify, say, 'long'.
+ * sig.c (build_sptr_ref): Add forward decl and make static.
+ * cp-tree.h (build_sptr_ref): Delete decl.
- * init.c (do_friend): Do overload C functions (or call pushdecl,
- anyaway).
+ * call.c (build_new_method_call): Add forward decl and make static.
+ * cp-tree.h (build_new_method_call): Delete decl.
-Wed Jun 22 13:40:49 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_object_call): Make static.
+ * class.c (check_for_override, complete_type_p, mark_overriders):
+ Likewise.
+ * decl.c (cp_function_chain): Likewise.
+ * lex.c (set_typedecl_interface_info, reinit_parse_for_block):
+ Likewise.
+ * pt.c (comp_template_args, get_class_bindings, push_tinst_level):
+ Likewise.
+ * tree.c (build_cplus_array_type_1): Likewise.
+ * typeck.c (comp_ptr_ttypes_{const,real,reinterpret}): Likewise.
+ (comp_target_parms): Likewise.
- * cvt.c (build_up_reference): Don't call readonly_error.
- (convert_to_reference): Propagate const and volatile from expr to
- its type.
+ * init.c (build_builtin_call): Make static.
+ * cp-tree.h (build_builtin_call): Delete decl.
- * tree.c (lvalue_p): Random CALL_EXPRs are not lvalues.
+ * typeck.c (binary_op_error): Delete decl.
+ * cp-tree.h (binary_op_error): Likewise.
- * cvt.c (build_up_reference): Break out WITH_CLEANUP_EXPR when
- creating a temporary.
- (convert_to_reference): Lose excessive and incorrect trickiness.
- (cp_convert): Call build_cplus_new with with_cleanup_p set.
+Thu Mar 6 16:13:52 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck2.c (build_functional_cast): Ditto.
+ * call.c (build_method_call): Compare against error_mark_node
+ directly, rather than the ERROR_MARK tree code.
+ * cvt.c (cp_convert): Likewise.
+ * decl.c (print_binding_level): Likewise.
+ (duplicate_decls): Likewise.
+ (grokdeclarator): Likewise.
+ (grokdeclarator): Likewise.
+ * init.c (expand_aggr_init_1): Likewise.
+ (decl_constant_value): Likewise.
+ * method.c (build_opfncall): Likewise.
+ (hack_identifier): Likewise.
+ * typeck.c (build_modify_expr): Likewise.
-Tue Jun 21 17:38:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (build_c_cast): Don't decl TYPE as register tree.
- * decl.c (grokdeclarator): signed, unsigned, long and short all
- imply 'int'.
+Sun Mar 2 02:54:36 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * decl.c (grokdeclarator): Allow "this is a type" syntax.
- (grok_reference_init): Simplify and fix.
+ * pt.c (unify): Strip NOP_EXPR wrappers before unifying integer values.
-Sun Jun 19 17:08:48 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (coerce_template_parms): Add new error message.
- * decl.c (grokdeclarator): pedwarn about a typedef that specifies no
- type.
+ * method.c (build_overload_value): Implement name mangling for
+ floating-point template arguments.
-Sat Jun 18 04:16:50 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * method.c (build_overload_int, icat, dicat): Fix mangling of template
+ arguments whose absolute value doesn't fit in a signed word.
- * decl.c (start_function): Move TREE_PUBLIC and DECL_EXTERNAL
- tinkering to after call to pushdecl.
+Mon Mar 3 12:14:54 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Fri Jun 17 14:48:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * friend.c: New file; put all of the friend stuff in here.
+ * init.c: Instead of here.
+ * Makefile.in (CXX_OBJS): Add friend.o.
+ (friend.o): Add dependencies.
+ * Make-lang.in (CXX_SRCS): Add $(srcdir)/cp/friend.c.
- * call.c (build_method_call): Handle destructors for non-aggregate
- types properly.
+Sun Mar 2 11:04:43 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jun 16 16:48:05 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_scoped_method_call): Complain if the scope isn't a
+ base.
- * call.c (build_method_call): Make sure that the name given for the
- destructor matches the constructor_name of the instance.
+Wed Feb 26 11:31:06 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (do_function_instantiation): A non-extern instantiation
- overrides a later extern one.
- (do_type_instantiation): Ditto.
+ * parse.y (left_curly): Don't crash on erroneous type.
-Wed Jun 15 19:34:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * init.c (build_delete): Fix type of ref.
- * init.c (expand_aggr_init): Use TYPE_MAIN_VARIANT to get the
- unqualified array type.
+Tue Feb 25 12:41:48 1997 Jason Merrill <jason@yorick.cygnus.com>
- * cp-tree.h (EMPTY_CONSTRUCTOR_P): Tests whether NODE is a
- CONSTRUCTOR with no elements.
+ * search.c (get_vbase_1): Renamed from get_vbase.
+ (get_vbase): Wrapper, now non-static.
+ (convert_pointer_to_vbase): Now static.
- * decl.c (various): Lose empty_init_node.
- (finish_decl): Use EMPTY_CONSTRUCTOR_P, do the empty CONSTRUCTOR
- thing depending on the value of DECL_COMMON instead of
- flag_conserve_space, do the empty CONSTRUCTOR thing for types that
- don't have constructors, don't treat a real empty CONSTRUCTOR
- specially.
+ * call.c (build_scoped_method_call): Accept a binfo for BASETYPE.
+ * init.c (build_delete): Pass one.
+ (build_partial_cleanup_for): Use build_scoped_method_call.
+ * decl.c (finish_function): Pass a binfo.
- * typeck2.c (process_init_constructor): Don't treat empty_init_node
- specially.
+Mon Feb 24 15:00:12 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jun 15 19:05:25 1994 Mike Stump <mrs@cygnus.com>
+ * call.c (build_over_call): Only synthesize non-trivial copy ctors.
- * class.c (override_one_vtable): Don't forget to merge in an old
- overrider when we wanted to reuse a vtable, but couldn't.
+ * typeck.c (build_c_cast): Lose other reference to flag.
-Wed Jun 15 15:03:16 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_field_call): Don't look for [cd]tor_identifier.
+ * decl2.c (delete_sanity): Remove meaningless use of
+ LOOKUP_HAS_IN_CHARGE.
+ * decl.c (finish_function): Use build_scoped_method_call instead
+ of build_delete for running vbase dtors.
+ * init.c (build_delete): Call overload resolution code instead of
+ duplicating it badly.
- * decl.c (start_decl): Put statics in common again.
+Thu Feb 20 15:12:15 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Return NULL_TREE for an error rather than
- setting the type to error_mark_node.
+ * call.c (build_over_call): Call mark_used before trying to elide
+ the call.
- * typeck.c (build_modify_expr): Build up a COMPOUND_EXPR for enum
- bitfield assignments.
+ * decl.c (implicitly_declare): Don't set DECL_ARTIFICIAL.
-Tue Jun 14 12:23:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Feb 19 11:18:53 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (grok_op_properties): Const objects can be passed by value.
+ * typeck.c (build_modify_expr): Always pedwarn for a cast to
+ non-reference used as an lvalue.
-Mon Jun 13 03:10:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Feb 19 10:35:37 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (import_export_vtable): Force implicit instantiations to
- be interface_only when -fno-implicit-templates.
+ * cvt.c (cp_convert_to_pointer): Convert from 0 to a pmf properly.
- * decl.c (duplicate_decls): Redeclaring a class template name is an
- error.
+Tue Feb 18 15:40:57 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (end_template_decl): Call GNU_xref_decl for class templates.
- * xref.c (GNU_xref_decl): Support templates.
+ * parse.y (handler): Fix template typo.
-Sat Jun 11 17:09:05 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sun Feb 16 02:12:28 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grok_op_properties): Split out checking for whether this
- function should suppress the default assignment operator.
- * decl2.c (grok_function_init): Ditto.
- (copy_assignment_arg_p): New function do do just that.
- Now considers virtual assignment operators that take a base as an
- argument to count as copy assignment operators.
+ * error.c (lang_decl_name): New fn.
+ * tree.c (lang_printable_name): Use it.
- * search.c (dfs_debug_mark): Lose checks for DWARF_DEBUG and
- TREE_ASM_WRITTEN, as they are redundant.
+Fri Feb 14 16:57:05 1997 Mike Stump <mrs@cygnus.com>
- * pt.c (end_template_decl): Don't try to set DECL_CLASS_CONTEXT on a
- decl that has no LANG_SPECIFIC part.
- (do_type_instantiation): Force the debugging information for this
- type to be emitted.
+ * g++spec.c: Include config.h so that we can catch bzero #defines
+ from the config file.
- * decl.c (start_decl): Clear up uses of various types of templates
- (say sorry for static data members, rather than "invalid template").
- (expand_static_init): Fix initialization of static data members of
- template classes.
+Tue Feb 11 13:50:48 1997 Mike Stump <mrs@cygnus.com>
-Fri Jun 10 00:41:19 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * new1.cc: Include a declaration for malloc, to avoid warning, and
+ avoid lossing on systems that require one (ones that define malloc
+ in xm.h).
- * decl.c (grokdeclarator): Set DECL_CONTEXT on static data members.
+Mon Feb 10 22:51:13 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * g++.c (main): Use -xc++-cpp-output for .i files.
+ * decl2.c (max_tinst_depth): New variable.
+ (lang_decode_option): Parse "-ftemplate-depth-NN" command line
+ option.
+ * pt.c (max_tinst_depth): Variable moved.
+ * lang-options.h: Declare "-ftemplate-depth-NN" command line option
+ as legal.
- * pt.c (tsubst): Give meaningful error about declaring template for
- a copy constructor which was not declared in the class template.
- (do_type_instantiation): Explicit instantiation before the class
- template is an error.
- (instantiate_template): Don't die if tsubst returns error_mark_node.
+Fri Feb 7 15:43:34 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jun 9 19:04:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (xref_basetypes): Allow a base class that depends on
+ template parms to be incomplete.
- Don't synthesize the copy assignment operator if the one in a base
- class is pure virtual.
- * cp-tree.h (TYPE_HAS_ABSTRACT_ASSIGN_REF): New macro to indicate
- whether the type has a pure virtual copy assignment operator.
- * class.c (finish_base_struct): Don't generate the copy assignment
- operator if a base class has a pure virtual one.
- * decl.c (grok_op_properties): Add disabled code to set
- TYPE_HAS_ABSTRACT_ASSIGN_REF with comment pointing to where it is
- actually set.
- * decl2.c (grok_function_init): Set TYPE_HAS_ABSTRACT_ASSIGN_REF.
+ * decl2.c (build_expr_from_tree): Support typeid(type).
+ * rtti.c (get_typeid): Support templates.
+ (expand_si_desc, expand_class_desc): Fix string length.
+ (expand_ptr_desc, expand_attr_desc, expand_generic_desc): Likewise.
- * decl2.c (import_export_vtable): Always treat template
- instantiations as if write_virtuals >= 2, and treat implicit
- instantiations as external if -fno-implicit-templates.
- (finish_file): Output all pending inlines if
- flag_keep_inline_functions.
+Tue Feb 4 11:28:24 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jun 8 20:48:02 1994 Mike Stump <mrs@cygnus.com>
+ * pt.c (unify, case TEMPLATE_CONST_PARM): Use cp_tree_equal.
- * tree.c (layout_vbasetypes): Align virtual base classes inside
- complete objects, so that we don't core dump on machines such as
- SPARCs when we access members that require larger than normal
- alignments, such as a double. Also, we bump up the total alignment
- on the complete type, as necessary.
+ * pt.c (tsubst): Put it back for -fno-ansi-overloading.
-Wed Jun 8 16:18:14 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Feb 3 18:41:12 1997 Jason Merrill <jason@yorick.cygnus.com>
- * gxxint.texi (Free Store): New section with code for examining
- cookie.
- (Limitations of g++): Remove operator delete entry, since it is no
- longer accurate. Fix access control entry.
+ * pt.c (tsubst, case FUNCTION_DECL): Lose obsolete code that
+ smashes together template and non-template decls of the same
+ signature.
- * typeck.c (build_unary_op): Pedwarn about taking the address of or
- incrementing a cast to non-reference type.
- (build_modify_expr): Use convert instead of convert_force again.
+Thu Jan 30 19:18:00 1997 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (get_base_distance): Use IS_AGGR_TYPE_CODE to check for
- class type, not == RECORD_TYPE.
+ * pt.c (tsubst): Don't recurse for the type of a TYPENAME_TYPE.
- * decl.c (grokdeclarator): Cope with grokfndecl returning NULL_TREE.
+Wed Jan 29 11:40:35 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck2.c (report_case_error): #if 0 out.
- * lex.c (real_yylex): Lose RANGE.
- * parse.y: Ditto.
+ * decl.c (duplicate_decls): Next route, pedwarn about different
+ exceptions if -pedantic *or* olddecl !DECL_IN_SYSTEM_HEADER.
-Tue Jun 7 18:17:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Jan 28 20:43:29 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * parse.y (simple_stmt, case ranges): Use ELLIPSIS instead of RANGE.
+ * cp-tree.h (HAS_DEFAULT_IMPLEMENTATION): Delete macro.
+ (struct lang_type): Delete has_default_implementation member.
+ Increase dummy to 21.
+ * decl.c (start_method): Delete usage.
-Mon Jun 6 19:39:57 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cp-tree.h (build_call, null_ptr_cst_p, in_function_p,
+ store_after_parms, start_decl_1, auto_function): Add decls.
+ (get_arglist_len_in_bytes, declare_implicit_exception,
+ have_exceptions_p, make_type_decl, typedecl_for_tag,
+ store_in_parms, pop_implicit_try_blocks, push_exception_cleanup,
+ build_component_type_expr, cplus_exception_name,
+ {make,clear}_anon_parm_name, dont_see_typename): Removed decls.
+ * call.c (build_this): Make static.
+ (is_complete): Likewise.
+ (implicit_conversion): Likewise.
+ (reference_binding): Likewise.
+ (standard_conversion): Likewise.
+ (strip_top_quals): Likewise.
+ (non_reference): Likewise.
+ (build_conv): Likewise.
+ (user_harshness): Likewise.
+ (rank_for_ideal): Likewise.
+ * decl.c (start_decl_1): Delete forward decl.
+ (push_decl_level): Make static.
+ (resume_binding_level): Make static.
+ (namespace_bindings_p): Make static.
+ (declare_namespace_level): Make static.
+ (lookup_name_real): Make static.
+ (duplicate_decls): Make static. Take register off NEWDECL and
+ OLDDECL parm decls.
+ * decl2.c (get_sentry): Make static.
+ (temp_name_p): Delete fn.
+ * except.c (auto_function): Delete decl.
+ * lex.c (handle_{cp,sysv}_pragma): Make static.
+ (handle_sysv_pragma) [HANDLE_SYSV_PRAGMA]: Add forward decl.
+ * method.c (do_build_{copy_constructor,assign_ref}): Make static.
+ * pt.c (tsubst_expr_values): Make static.
+ * rtti.c (combine_strings): Delete decl.
- * typeck.c (build_c_cast): Don't shortcut conversions to the same
- type. Don't replace consts with their values here, since that's now
- done in cp_convert.
+Tue Jan 28 16:40:40 1997 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (cp_convert): When converting to bool, take
- integer_zero_node to false_node and all other INTEGER_CSTs to
- true_node.
- (build_type_conversion): Don't complain about multiple conversions
- to float if we're not really converting.
+ * pt.c (push_template_decl): Handle getting a typedef.
-Fri Jun 3 02:10:56 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_new_function_call): Complain about void arg.
- Implement 'extern template class A<int>;' syntax for suppressing
- specific implicit instantiations.
- * cp-tree.h: Update prototypes for do_*_instantiation.
- * pt.c (do_pending_expansions): Don't compile 'extern' explicit
- instantiations.
- (do_function_instantiation): Set DECL_EXTERNAL on 'extern' explicit
- instantiations.
- (do_type_instantiation): Ditto.
- * parse.y (explicit_instantiation): Support 'extern template class
- A<int>;' syntax.
- * decl.c (start_function): Don't modify the settings of TREE_PUBLIC
- and DECL_EXTERNAL on explicit instantiations.
+Tue Jan 28 15:25:09 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cvt.c (cp_convert): Replace constants with their values before
- converting.
- (cp_convert): Consistently use 'e' instead of 'expr'.
+ * decl.c (duplicate_decls): Give pedwarn of different exceptions
+ if -pedantic, instead of olddecl !DECL_IN_SYSTEM_HEADER.
-Thu Jun 2 03:53:30 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Jan 27 19:21:29 1997 Mike Stump <mrs@cygnus.com>
- * typeck2.c (build_x_arrow): Resolve OFFSET_REFs first.
+ * except.c (expand_throw): Don't expand the cleanup tree here,
+ since we are not going to write the rtl out. Fixes problem with
+ -g -O on SPARC.
-Wed Jun 1 18:57:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Jan 27 16:24:35 1997 Sean McNeil <sean@mcneil.com>
- * typeck2.c (digest_init): Handle initializing a pmf with an
- overloaded method.
- * typeck.c (build_ptrmemfunc): Handle overloaded methods.
+ * Make-lang.in: Add $(exeext) as necessary.
- * decl.c (pushtag): Use build_decl to make TYPE_DECLs.
- (xref_defn_tag): Ditto.
- * pt.c (process_template_parm): Ditto.
- (lookup_template_class): Ditto.
- (push_template_decls): Ditto.
- (instantiate_class_template): Ditto.
- (create_nested_upt): Ditto.
- * class.c (finish_struct): Don't try to set DECL_CLASS_CONTEXT on
- TYPE_DECLs.
+Mon Jan 27 13:20:39 1997 Mike Stump <mrs@cygnus.com>
- * typeck.c (convert_arguments): Make sure type is not NULL before
- checking its TREE_CODE.
+ * parse.y (handler_seq): Must have at least one catch clause.
-Wed Jun 1 17:40:39 1994 Mike Stump <mrs@cygnus.com>
+Sat Jan 25 12:00:05 1997 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (get_derived_offset): New routine.
- * class.c (finish_base_struct): Make sure we set BINFO_VTABLE and
- BINFO_VIRTUALS when we choose a new base class to inherit from.
- * class.c (modify_one_vtable): Use get_derived_offset to get the
- offset to the most base class subobject that we derived this binfo
- from.
- * class.c (finish_struct): Move code to calculate the
- DECL_FIELD_BITPOS of the vfield up, as we need might need it for
- new calls to get_derived_offset in modify_one_vtable.
-
-Wed Jun 1 16:50:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (add_builtin_candidate): Restore ?: hack.
- * init.c (build_member_call): Use build_pointer_type instead of
- TYPE_POINTER_TO.
-
-Wed Jun 1 11:11:15 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl.c (grok_op_properties): More warnings.
- * decl.c (grokdeclarator): Make sure we have a DNAME set before we
- try to use it in an error.
+Sat Jan 25 08:50:03 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Jun 1 09:48:49 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (duplicate_decls): On second thought, do it as a pedwarn
+ still but only if !DECL_IN_SYSTEM_HEADER (olddecl).
- * typeck.c (convert_arguments, convert_for_initialization): Don't
- strip NOP_EXPRs, when we are converting to a reference.
+ * decl.c (duplicate_decls): Scale back to a warning, and only do
+ 'em if -pedantic.
-Wed Jun 1 01:11:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Jan 24 17:52:54 1997 Mike Stump <mrs@cygnus.com>
- * typeck.c (build_modify_expr): Don't dereference references when
- initializing them.
+ * decl.c (duplicate_decls): pedwarn mismatched exception
+ specifications.
- * decl2.c (grokfield): Don't check for grokdeclarator returning
- error_mark_node any more.
+Thu Jan 23 18:18:54 1997 Mike Stump <mrs@cygnus.com>
- * decl.c (grokfndecl): Return NULL_TREE instead of error_mark_node.
- (start_method): Return void_type_node instead of error_mark_node.
+ * call.c (build_new_method_call): Don't display the invisible
+ argument for controlling virtual bases.
- * typeck.c (build_modify_expr): Resolve offset refs earlier.
+Thu Jan 23 16:48:10 1997 Mike Stump <mrs@cygnus.com>
-Tue May 31 16:06:58 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * new: Add nothrow new and delete, bad_alloc and throw specifications
+ for delete.
+ * decl.c (init_decl_processing): Add throw specification for delete.
+ * new.cc (nothrow): Define.
+ * lex.c (real_yylex): Removing warning that throw and friends are
+ keywords.
+ * new1.cc (operator new (size_t sz, const nothrow_t&)): Define.
+ * new2.cc (operator new[] (size_t sz, const nothrow_t&): Define.
+ * Make-lang.in: Add new{1,2}.{cc,o}.
- * call.c (build_method_call): Resolve OFFSET_REFs in the object.
+Thu Jan 23 16:39:06 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_modify_expr): Dereference references before trying
- to assign to them.
-
- * call.c (build_method_call): Don't confuse type conversion
- operators with constructors.
- * typeck2.c (build_functional_cast): Just call build_c_cast if there
- was only one parameter.
- * method.c (build_typename_overload): Don't set
- IDENTIFIER_GLOBAL_VALUE on these identifiers.
- * decl.c (grok_op_properties): Warn about defining a type conversion
- operator that converts to a base class (or reference to it).
- * cvt.c (cp_convert): Don't try to use a type conversion operator
- when converting to a base class.
- (build_type_conversion_1): Don't call constructor_name_full on an
- identifier.
- * cp-tree.h (DERIVED_FROM_P): Should be self-explanatory.
-
- * decl.c (start_decl): Don't complain that error_mark_node is an
- incomplete type.
- (finish_decl): Check for type == error_mark_node.
+ * lex.c (cons_up_default_function): Fix return type of synth op=.
-Mon May 30 23:38:55 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * init.c (emit_base_init): Add warnings for uninitialized members
+ and bases.
- * decl.c (start_function): Set DECL_DEFER_OUTPUT on implicit
- instantiations and inline members.
+ * decl.c (xref_basetypes): Add warning for non-polymorphic type
+ with destructor used as base type.
- * spew.c (yylex): Set looking_for_template if the next token is a '<'.
+ * decl.c (grok_op_properties): Add warning for op= returning void.
+ * typeck.c (c_expand_return): Add warning for op= returning anything
+ other than *this.
- * lex.h: Declare looking_for_template.
+ * class.c (finish_struct_1): Add warning for class with pointers
+ but not copy ctor or copy op=.
- * decl.c (lookup_name_real): Use looking_for_template to arbitrate
- between type and template interpretations of an identifier.
+ * cp-tree.h (TI_PENDING_TEMPLATE_FLAG): New macro.
+ * pt.c (add_pending_template): Use it instead of LANG_FLAG_0.
+ (instantiate_template): If -fexternal-templates, add this
+ instantiation to pending_templates.
-Sat May 28 04:07:40 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (copy_assignment_arg_p): Disable old hack to support
+ Booch components.
- * pt.c (instantiate_template): Zero out p if we found a
- specialization.
+Tue Jan 21 18:32:04 1997 Mike Stump <mrs@cygnus.com>
- * decl.c (grokdeclarator): Elucidate warning.
- (grokdeclarator): If pedantic AND -ansi, complain about long long.
+ * cvt.c (cp_convert): Pedwarn enum to pointer conversions.
- Make explicit instantiation work reasonably. It is now appropriate
- to deprecate the use of -fexternal-templates.
- * pt.c (instantiate_template): Set DECL_TEMPLATE_SPECIALIZATION or
- DECL_IMPLICIT_INSTANTIATION on fndecl as appropriate.
- (end_template_instantiation): Reflect changes in USE_TEMPLATE
- semantics.
- (do_pending_expansions): if (!flag_implicit_templates) DECIDE(0);
- (do_function_instantiation): Don't set EXPLICIT_INST if
- flag_external_templates is set. Do set TREE_PUBLIC and DECL_EXTERN
- appropriately otherwise.
- (do_type_instantiation): Set interface info for class. Set
- TREE_PUBLIC and DECL_EXTERN for methods. Do none of this if
- flag_external_templates is set.
- * parse.y: Reflect changes in USE_TEMPLATE semantics.
- * decl2.c: New flag flag_implicit_templates determines whether or
- not implicit instantiations get emitted. This flag currently
- defaults to true, and must be true for -fexternal-templates to work.
- (finish_file): Consider flag_implement_inlines when
- setting DECL_EXTERNAL. Consider flag_implicit_templates when
- deciding whether or not to emit a static copy.
- * decl.c (start_function): Set TREE_PUBLIC and DECL_EXTERNAL
- properly for template instantiations.
- (start_method): Set DECL_IMPLICIT_INSTANTIATION on methods of a
- template class.
- * cp-tree.h (CLASSTYPE_USE_TEMPLATE): Change semantics.
- (DECL_USE_TEMPLATE): Parallel macro for FUNCTION and VAR_DECLs.
- (various others): Accessor macros for the above.
+Mon Jan 20 17:59:51 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri May 27 13:57:40 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (standard_conversion): Handle getting references. Tack
+ on RVALUE_CONV here. Do it for non-class types, too.
+ (reference_binding): Pass references to standard_conversion.
+ (implicit_conversion): Likewise.
+ (add_builtin_candidate): Disable one ?: kludge.
+ (convert_like): Handle RVALUE_CONVs for non-class types.
+ (joust): Disable the other ?: kludge.
- * typeck.c (build_binary_op_nodefault): Division by constant zero is
- an error.
+Mon Jan 20 14:53:13 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Fri May 27 13:50:15 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (init_decl_processing): Add code to build up common
+ function types beforehand, to avoid creation then removal of
+ things already in the hash table.
- * class.c (override_one_vtable): Don't modify things we don't own.
+Mon Jan 20 14:43:49 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri May 27 01:42:58 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (finish_function): Also zero out DECL_INCOMING_RTL for
+ the arguments.
- * decl.c (finish_decl): Don't postpone processing the initializer of
- a decl with DECL_EXTERNAL set, and do call rest_of_compilation for a
- PUBLIC const at toplevel.
- (grokdeclarator): pedwarn about initializing non-const or
- non-integral statics in the class body.
-
- * decl.c (pushtag): Don't try to set DECL_CLASS_CONTEXT on a
- TYPE_DECL.
+ * error.c (dump_expr, TEMPLATE_CONST_PARM): Don't require
+ current_template_parms.
- * call.c (convert_harshness): Dereference reference on rhs before
- proceeding, properly grok passing const things to non-const
- references.
+Fri Jan 17 10:25:42 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_unary_op): Soften error about taking the address
- of main() to a pedwarn.
+ * search.c (lookup_field): Don't return a function, check want_type.
- * lex.c (default_copy_constructor_body): Unambiguously specify base
- classes (i.e. A((const class ::A&)_ctor_arg) ).
- (default_assign_ref_body): Ditto.
+Thu Jan 16 18:14:35 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Thu May 26 13:13:55 1994 Gerald Baumgartner (gb@mexican.cygnus.com)
+ * init.c (build_new): Make sure PLACEMENT has a type.
- * decl2.c (grokfield): Don't complain about local signature
- method declaration without definition.
+Thu Jan 16 17:40:28 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (convert_harshness): If `type' is a signature pointer
- and `parmtype' is a pointer to a signature, just return 0. We
- don't really convert in this case; it's a result of making the
- `this' parameter of a signature method a signature pointer.
+ * init.c (build_new): Support new (nothrow).
- * call.c (build_method_call): Distinguish calling the default copy
- constructor of a signature pointer/reference from a signature
- member function call.
+Wed Jan 15 12:38:14 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu May 26 12:56:25 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (instantiate_decl): Also do push_to_top_level before setting
+ up DECL_INITIAL.
- * decl2.c (grokfield): Don't set TREE_PUBLIC on member function
- declarations.
+ * cp-tree.h (PARM_DEFAULT_FROM_TEMPLATE): New macro.
+ * pt.c (tsubst): Defer instantiation of default args.
+ * call.c (build_over_call): Until here.
- * decl.c (duplicate_decls): A previous function declaration as
- static overrides a subsequent non-static definition.
- (grokdeclarator): Don't set TREE_PUBLIC on inline method
- declarations.
+Wed Jan 15 10:08:10 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed May 25 14:36:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * search.c (lookup_field): Make sure we have an
+ IDENTIFIER_CLASS_VALUE before we try to return it.
- * decl.c (grokdeclarator): Handle initialization of static const
- members.
- (finish_decl): Ditto.
+Thu Jan 9 07:19:01 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl2.c (grokfield): Allow initialization of static const members
- even when pedantic.
+ * call.c (build_method_call): Delete unused var PARM.
+ (build_overload_call_real): Likewise.
+ (build_object_call): Delete unused var P.
+ (build_new_op): Likewise.
+ * decl.c (builtin_type_tdescs_{arr, len, max}): #if 0 out static
+ var definitions, which are never used.
+ (shadow_tag): Delete unused var FN.
+ * expr.c (cplus_expand_expr): Delete unused var ORIGINAL_TARGET.
+ * init.c (build_new): Delete unused var ALLOC_TEMP.
+ * method.c (hack_identifier): Delete unused var CONTEXT.
+ (do_build_copy_constructor): Delete unused var NAME.
+ (synthesize_method): Delete unused var BASE.
+ * pt.c (lookup_template_class): Delete unused var CODE_TYPE_NODE.
+ * rtti.c (build_headof): Delete unused var VPTR.
+ (get_typeid): Delete unused var T.
+ * typeck.c (build_conditional_expr): Delete unused vars ORIG_OP1
+ and ORIG_OP2.
+ (build_ptrmemfunc): Delete unused vars U and NINDEX.
+ * typeck2.c (build_functional_cast): Delete unused var BINFO.
- * decl2.c (grokfield): Deal with grokdeclarator returning
- error_mark_node.
+Wed Jan 8 13:09:54 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grok_ctor_properties): Return 0 for A(A) constructor.
- (grokfndecl): Check the return value of grok_ctor_properties.
- (start_method): Ditto.
+ * search.c (lookup_field): Use IDENTIFIER_CLASS_VALUE to look up
+ things in a type being defined.
+ * decl.c (finish_enum): Reverse the values so that they are in
+ the correct order.
- * parse.y (absdcl): Expand type_quals inline.
+ * pt.c (instantiate_class_template): Don't initialize
+ BINFO_BASETYPES until the vector is filled out.
+ (unify): Don't abort on conflicting bindings, just fail.
+ (instantiate_decl): Do push_tinst_level before any tsubsting.
-Tue May 24 19:10:32 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * method.c (build_overload_value): Handle getting a
+ TEMPLATE_CONST_PARM for a pointer.
- * decl.c (pushtag): Use IS_AGGR_TYPE rather than checking for a
- RECORD_TYPE.
+Tue Jan 7 14:00:58 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue May 24 18:09:16 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * init.c (expand_member_init): Don't give 'not a base' error for
+ templates.
- * cp-tree.h (VTABLE_NAME_FORMAT): If flag_vtable_thunks,
- always use "__vt_%s".
- * decl2.c (finish_vtable_vardecl): Don't consider abstract virtuals
- when looking for a "sentinal" method (to decide on emitting vtables).
- * decl2.c (finish_file): Scan all decls for thunks that need
- to be emitted.
- * decl2.c (finish_vtable_vardecl): Don't bother calling emit_thunk.
- * method.c (make_thunk): Use a more meaningful label. If there
- exists a matching top-level THUNK_DECL re-use it; otherwise
- create a new THUNK_DECL (and declare it).
- * method.c (emit_thunk): Make thunk external/public depending
- on the underlying method.
+ * pt.c (instantiate_decl): Call import_export_decl later.
-Tue May 24 00:22:04 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (instantiate_class_template): Return a value.
- * pt.c (tsubst): Use lookup_name_nonclass to find guiding decls, not
- lookup_name.
+ * parse.y (extension): New rule for __extension__.
+ (extdef, unary_expr, decl, component_decl): Use it.
- * call.c (build_overload_call_real): Don't immediately pick a
- function which matches perfectly.
+Tue Jan 7 09:20:28 1997 Mike Stump <mrs@cygnus.com>
- * decl.c (grokdeclarator): Use c_build_type_variant for arrays.
- (grokdeclarator): Warn about, and throw away, cv-quals attached to a
- reference (like 'int &const j').
+ * class.c (base_binfo): Remove unused base_has_virtual member.
+ (finish_base_struct): Likewise.
+ (finish_struct_1): Likewise.
- * typeck.c (convert_arguments): Don't mess with i for methods.
- * call.c (build_method_call): Pass the function decl to
- convert_arguments.
+Tue Dec 31 20:25:50 1996 Mike Stump <mrs@cygnus.com>
- * typeck.c (comp_ptr_ttypes_real): New function. Implements the
- checking for which multi-level pointer conversions are allowed.
- (comp_target_types): Call it.
- (convert_for_assignment): Check const parity on the ultimate target
- type, too. And make those warnings pedwarns.
+ * search.c (expand_upcast_fixups): Fix bogus code generation
+ problem where the generated code uses the wrong index into the
+ runtime built vtable on the stack. Old code could clobber random
+ stack values.
-Mon May 23 14:11:24 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Dec 31 15:16:56 1996 Mike Stump <mrs@cygnus.com>
- * error.c (dump_char): Use TARGET_* for character constants.
+ * init.c (perform_member_init): Make sure the partial EH cleanups
+ live on the function_obstack.
-Mon May 23 13:03:03 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+Fri Dec 27 10:31:40 1996 Paul Eggert <eggert@twinsun.com>
- * tree.c (debug_no_list_hash): Make static.
+ * Make-lang.in (g++spec.o): Don't use $< with an explicit target;
+ this isn't portable to some versions of `make' (e.g. Solaris 2.5.1).
- * decl.c (decls_match): Say the types don't match if newdecl ends up
- with a null type, after we've checked if olddecl does.
- (pushdecl): Check if the decls themselves match before looking for
- an extern redeclared as static, to avoid inappropriate and incorrect
- warnings.
+Tue Dec 24 10:24:03 1996 Jeffrey A Law (law@cygnus.com)
-Fri May 20 14:04:34 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (grokvardecl): Avoid ANSI style initialization.
- * decl.c (grokdeclarator): Make warning about duplicate short, etc.
- a pedwarn.
+Sun Dec 22 04:22:06 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_c_cast): Casting to function or method type is an
- error.
+ * pt.c (tsubst): Tweak arg types for a FUNCTION_TYPE.
- * class.c (finish_struct): Make warning for anonymous class with no
- instances a pedwarn.
+Fri Dec 20 17:09:25 1996 Jason Merrill <jason@yorick.cygnus.com>
- * Makefile.in (stamp-parse): Expect a s/r conflict.
+ * pt.c (instantiate_class_template): Call grok_{ctor,op}_properties.
- * typeck.c (build_modify_expr): pedwarn about using a non-lvalue
- cast as an lvalue.
+Fri Dec 20 12:17:12 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Thu May 19 12:08:48 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * g++spec.c (lang_specific_driver): Put missing hyphen in front of
+ arguments we compare against. Start the count of I at 1, not 0,
+ since argv[0] is still the command.
- * cvt.c (type_promotes_to): Make sure bool promotes to int rather
- than unsigned on platforms where sizeof(char)==sizeof(int).
+Thu Dec 19 11:53:57 1996 Stan Shebs <shebs@andros.cygnus.com>
-Wed May 18 14:27:06 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * lang-specs.h: Accept .cp as an C++ extension.
- * typeck.c (build_c_cast): Tack on a NOP_EXPR when casting to
- another variant.
- (build_modify_expr): Don't strip NOP_EXPRs, and don't get tricky
- and treat them as lvalues.
+Mon Dec 16 22:43:31 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (shadow_tag): Do complain about forward declarations of
- enums and empty declarations.
- * parse.y: Don't complain about forward declarations of enums and
- empty declarations.
+ * cp-tree.h (ptr_reasonably_similar): Add decl.
- * typeck.c (convert_for_assignment): Complain about changing
- the signedness of a pointer's target type.
+Thu Dec 12 15:00:35 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * parse.y (stmt): Move duplicated code for checking case values from
- here.
- * decl2.c (check_cp_case_value): To here. And add a call to
- constant_expression_warning.
+ * decl.c (grokvardecl): Change SPECBITS parm to be the SPECBITS_IN
+ pointer. New local SPECBITS with the parm's value.
+ (grokdeclarator): Pass &specbits down.
- * typeck.c (convert_for_assignment): Don't complain about assigning
- a negative value to bool.
+ * parse.y (expr_no_commas): Make sure $$ is not an error_mark_node
+ before we try to do C_SET_EXP_ORIGINAL_CODE on it.
- * decl.c (init_decl_processing): Make bool unsigned.
+ * search.c (envelope_add_decl): Check that the CLASSTYPE_CID of
+ CONTEXT is not 0 before we try to use TYPE_DERIVES_FROM.
- * class.c (finish_struct): Allow bool bitfields.
+ * decl.c (cplus_expand_expr_stmt): Only expand the expr if EXP is
+ not an error_mark_node.
-Wed May 18 12:35:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+Sat Dec 7 17:20:22 1996 Jason Merrill <jason@yorick.cygnus.com>
- * Make-lang.in (c++.install-man): Get g++.1 from $(srcdir)/cp.
+ * cp-tree.h (TYPE_MAIN_DECL): Use TYPE_STUB_DECL.
+ * *.c: Use TYPE_MAIN_DECL instead of TYPE_NAME where appropriate.
+
+Fri Dec 6 14:40:09 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed May 18 03:28:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (grokdeclarator): When giving an anonymous struct a name,
+ replace TYPE_NAME instead of TYPE_IDENTIFIER (so TYPE_STUB_DECL is
+ not affected).
- * cvt.c (build_type_conversion): Lose special handling of
- truthvalues.
+ * typeck2.c (build_m_component_ref): If component is a pointer
+ to data member, resolve the OFFSET_REF now.
- * search.c (dfs_pushdecls): Improve shadowing warning.
+ * call.c (convert_like): Don't go into infinite recursion.
-Tue May 17 13:34:46 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (coerce_template_parms): Use tsubst_expr for non-type args.
- * init.c (build_delete): Throw away const and volatile on `this'.
+ * class.c (finish_struct_1): Set DECL_ARTIFICIAL on the vptr.
+ * tree.c (layout_basetypes): And on the vbase ptr.
- * decl.c (finish_enum): Put the constants in TYPE_VALUES again,
- rather than the enumerators.
- (pushtag): s/cdecl/c_decl/g
+Thu Dec 5 02:11:28 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon May 16 23:04:01 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de)
+ * decl.c (BOOL_TYPE_SIZE): Define in terms of POINTER_SIZE or
+ CHAR_TYPE_SIZE so bool is always the same size as another type.
- * cp/typeck.c (common_type): Attribute merging.
- (comp_types): Utilise COMP_TYPE_ATTRIBUTES macro.
+ * decl.c (pushtag): Set DECL_IGNORED_P for DWARF, too.
- * cp/parse.y: Revamp attribute parsing.
+Tue Dec 3 23:18:37 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon May 16 01:40:34 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (grok_x_components): Remove synthesized methods from
+ TYPE_METHODS of an anonymous union, complain about member
+ functions.
+ * decl.c (shadow_tag): Wipe out memory of synthesized methods in
+ anonymous unions.
+ (finish_function): Just clear the DECL_RTL of our arguments.
- * decl.c (shadow_tag): Also check for inappropriate use of auto and
- register.
+Fri Nov 29 21:54:17 1996 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (build_overload_name): Clarify that the illegal case is a
- pointer or reference to array of unknown bound.
+ * decl2.c (finish_file): Emit DWARF debugging info for static data
+ members.
- * error.c (dump_type_prefix): Print references to arrays properly.
+ * pt.c (tsubst): If t is a stub decl, return the stub decl for type.
- * typeck.c (various): Be more helpful in pointer
- comparison diagnostics.
+Wed Nov 27 14:47:15 1996 Bob Manson <manson@charmed.cygnus.com>
- * tree.c (lvalue_p): MODIFY_EXPRs are lvalues again. Isn't this
- fun?
+ * typeck.c (build_component_ref): Don't die if COMPONENT isn't a
+ IDENTIFIER_NODE.
- * parse.y: Also catch an error after valid stmts.
+Wed Nov 27 16:05:19 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * search.c (dfs_init_vbase_pointers): Don't abort because `this' is
- const.
+ * Make-lang.in (g++-cross$(exeext)): Fix typo.
- * typeck.c (convert_for_initialization): If call to
- convert_to_reference generated a diagnostic, print out the parm
- number and function decl if any.
+Wed Nov 27 08:14:00 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * errfn.c (cp_thing): Check atarg1 to determine whether or not we're
- specifying a line, not atarg.
+ Make the g++ driver now be a standalone program, rather than one
+ that tries to run the gcc driver after munging up the options.
+ * Make-lang.in (g++.c, g++spec.o): New rules.
+ (g++.o): New rule, based on gcc.o with -DLANG_SPECIFIC_DRIVER
+ added.
+ (g++$(exeext)): New rule, based on xgcc rule.
+ (g++-cross$(exeext)): Now just copies g++$(exeext) over.
+ * g++spec.c: New file.
+ * g++.c: Removed file.
- * tree.c (build_cplus_method_type): Always make `this' const.
+Tue Nov 26 19:01:09 1996 Mike Stump <mrs@cygnus.com>
- * decl2.c (grokclassfn): If -fthis-is-variable and this function is
- a constructor or destructor, make `this' non-const.
+ * cvt.c (build_up_reference): Arrange for any temporary values
+ that have been keep in registers until now to be put into memory.
- * typeck.c (build_modify_expr): Don't warn specially about
- assignment to `this' here anymore, since it will be caught by the
- usual machinery.
+Mon Nov 25 15:16:41 1996 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * various: Disallow specific GNU extensions (variable-size arrays,
- etc.) when flag_ansi is set, not necessarily when pedantic is set,
- so that people can compile with -pedantic-errors for tighter const
- checking and such without losing desirable extensions.
+ * Make-lang.in (c++.stage[1234]): Depend upon stage[1-4]-start, so
+ that make -j3 bootstrap works better.
- * typeck2.c (build_functional_cast): Call build_method_call with
- LOOKUP_PROTECT.
- (process_init_constructor): Only process FIELD_DECLs.
+Sun Nov 24 02:09:39 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (finish_decl): Also force static consts with no explicit
- initializer that need constructing into the data segment.
+ * decl.c (pushtag): Do pushdecl for anon tags.
- * init.c (build_delete): Undo last patch, as it interferes with
- automatic cleanups.
+Thu Nov 21 16:30:24 1996 Jason Merrill <jason@yorick.cygnus.com>
-Sat May 14 01:59:31 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (c_expand_return): Fix logic.
+ (unary_complex_lvalue): Avoid unused warning on address of INIT_EXPR.
- * call.c, class.h, cp-tree.h, cvt.c, decl2.c: Lose old overloading
- code.
+Wed Nov 20 18:47:31 1996 Bob Manson <manson@charmed.cygnus.com>
- * init.c (build_delete): pedwarn about using plain delete to delete
- an array.
+ * g++.c (main): Make sure arglist has a final NULL entry. Add
+ PEXECUTE_LAST to the flags passed to pexecute, as otherwise
+ stdin/stdout of the invoked program are redirected to
+ nowheresville.
-Fri May 13 16:45:07 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Nov 19 16:12:44 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (comp_target_types): Be more helpful in contravariance
- warnings, and make them pedwarns.
+ * decl.c (implicitly_declare): Set DECL_ARTIFICIAL.
- * decl.c (grokdeclarator): Use decl_context to decide whether or not
- this is an access declaration.
+Tue Nov 19 15:48:19 1996 Mike Stump <mrs@cygnus.com>
- * class.c (finish_struct_bits): Set TYPE_HAS_INT_CONVERSION if it
- has a conversion to enum or bool, too.
+ * init.c (resolve_offset_ref): Handle obj.vfn better.
+ * typeck.c (build_component_ref): Set TREE_TYPE on result from
+ build_vfn_ref.
-Fri May 13 16:31:27 1994 Mike Stump <mrs@cygnus.com>
+Tue Nov 19 13:14:33 1996 Mike Stump <mrs@cygnus.com>
- * method.c (emit_thunk): Make declaration for
- current_call_is_indirect local (needed for hppa).
+ * typeck.c (convert_for_assignment): Also handle anachronistic
+ implicit conversions from (::*)() to cv void*.
+ * cvt.c (cp_convert_to_pointer): Likewise.
-Fri May 13 16:16:37 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Nov 18 17:05:26 1996 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (uses_template_parms): Grok BOOLEAN_TYPE.
- (tsubst): Ditto.
+ * lex.c (handle_cp_pragma): Fix bogus warning.
-Fri May 13 16:23:32 1994 Mike Stump <mrs@cygnus.com>
+Mon Nov 18 16:10:43 1996 Mike Stump <mrs@cygnus.com>
- * pt.c (tsubst): If there is already a function for this expansion,
- use it.
- * pt.c (instantiate_template): Ditto.
-
-Fri May 13 10:30:42 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * parse.y (implicitly_scoped_stmt, simple_stmt case): Use
- kept_level_p for MARK_ENDS argument to expand_end_bindings, to avoid
- generating debug info for unemitted symbols on some systems.
-
- * cp-tree.h (build_static_cast, build_reinterpret_cast,
- build_const_cast): Add declarations.
-
-Fri May 13 09:50:31 1994 Mike Stump <mrs@cygnus.com>
-
- * search.c (expand_indirect_vtbls_init): Fix breakage from Apr 27
- fix. We now try get_binfo, and if that doesn't find what we want,
- we go back to the old method, which still sometimes fails.
-
-Fri May 13 01:43:18 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * parse.y (initdcl): Call cplus_decl_attributes on the right
- variable.
- * decl2.c (cplus_decl_attributes): Don't call decl_attributes for
- void_type_node.
-
- * typeck.c (build_binary_op_nodefault): Change result_type for
- comparison ops to bool.
- (build_binary_op): Convert args of && and || to bool.
- * cvt.c (build_default_binary_type_conversion): Convert args of &&
- and || to bool.
- (build_default_unary_type_conversion): Convert arg of ! to bool.
- (type_promotes_to): bool promotes to int.
-
-Fri May 13 01:43:18 1994 Mike Stump <mrs@cygnus.com>
-
- Implement the new builtin `bool' type.
- * typeck.c (build_binary_op_nodefault): Convert args of && and || to
- bool.
- (build_unary_op): Convert arg of ! to bool.
- * parse.y: Know true and false. Use bool_truthvalue_conversion.
- * method.c (build_overload_value): Know bool.
- (build_overload_name): Ditto.
- * lex.c (init_lex): Set up RID_BOOL.
- * gxx.gperf: Add bool, true, false.
- * error.c (*): Know bool.
- * decl.c (init_decl_processing): Set up bool, true, false.
- * cvt.c (cp_convert): Handle conversion to bool.
- (build_type_conversion): Ditto.
- * *.c: Accept bool where integers and enums are accepted (use
- INTEGRAL_CODE_P macro).
-
-Thu May 12 19:13:54 1994 Richard Earnshaw (rwe11@cl.cam.ac.uk)
-
- * g++.c: Use #ifdef for __MSDOS__, not #if.
-
-Thu May 12 18:05:18 1994 Mike Stump <mrs@cygnus.com>
-
- * decl2.c (lang_f_options): Handle -fshort-temps. -fshort-temps
- gives old behavior , and destroys temporaries earlier. Default
- behavior now conforms to the ANSI working paper.
-
-Thu May 12 14:45:35 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * typeck.c (build_modify_expr): Understand MODIFY_EXPR as an lvalue.
- Use convert_force to convert the result of a recursive call when we
- are dealing with a NOP_EXPR. Don't automatically wrap MODIFY_EXPRs
- in COMPOUND_EXPRs any more.
- (various): Lose pedantic_lvalue_warning.
- (unary_complex_lvalue): Understand MODIFY_EXPR.
-
- * cvt.c (convert_to_reference): Allow DECL to be error_mark_node if
- we don't know what we're initializing.
-
-Wed May 11 01:59:36 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cvt.c (convert_to_reference): Modify to use convtype parameter.
- Only create temporaries when initializing a reference, not when
- casting.
- (cp_convert): New main function.
- (convert): Call cp_convert.
- * cvt.c, decl.c, typeck.c: Fix calls to convert_to_reference.
- * cp-tree.h (CONV_*): New constants used by conversion code for
- selecting conversions to perform.
-
- * tree.c (lvalue_p): MODIFY_EXPRs are no longer lvalues.
-
- * typeck.c (build_{static,reinterpret,const_cast): Stubs that just
- call build_c_cast.
- * parse.y: Add {static,reinterpret,const}_cast.
- * gxx.gperf: Ditto.
-
- * typeck.c (common_type): Allow methods with basetypes of different
- UPTs.
- (comptypes): Deal with UPTs.
- (build_modify_expr): Wrap all MODIFY_EXPRs in a COMPOUND_EXPR.
-
- * pt.c (end_template_decl): Check for multiple definitions of member
- templates.
+ * cvt.c (cp_convert_to_pointer): Avoid thinking a POINTER_TYPE
+ (METHOD_TYPE) is a TYPE_PTRMEMFUNC_P.
- * call.c (build_method_call): Complain about calling an abstract
- virtual from a constructor.
+Thu Nov 14 23:18:17 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (pointer_int_sum): Check for the integer operand being 0
- after checking the validity of the pointer operand.
+ * class.c (finish_struct_1): Support DWARF2_DEBUG.
+ * search.c (dfs_debug_mark): Likewise.
+ * decl2.c (finish_vtable_vardecl): Likewise.
+ * decl.c (pushtag, finish_enum): Likewise.
+ * lex.c (check_newline): Use debug_* instead of calling *out
+ functions directly.
- * typeck2.c (digest_init): Pedwarn about string initializer being
- too long.
+Thu Nov 14 15:21:46 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue May 10 12:10:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * Make-lang.in (cplib2.ready): Add else clause to avoid problems
+ on some picky hosts.
- * decl.c (push_overloaded_decl): Only throw away a builtin if the
- decl in question is the artificial one.
+Wed Nov 13 12:32:07 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (simple_stmt, switch): Use implicitly_scoped_stmt because
- expand_{start,end}_case cannot happen in the middle of a block.
+ * class.c (finish_struct_1): A class has a non-trivial copy
+ constructor if it has virtual functions.
- * cvt.c (build_type_conversion_1): Use convert again.
+ * cvt.c (cp_convert): Always call a constructor.
-Tue May 10 11:52:04 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * call.c (reference_binding): Still tack on a REF_BIND
+ for bad conversions.
+ (build_user_type_conversion_1): Propagate ICS_BAD_FLAG.
- * typeck2.c (digest_init): Make sure we check for signed and
- unsigned chars as well when warning about string initializers.
+ * typeck.c (convert_arguments): Pass LOOKUP_ONLYCONVERTING.
+ (c_expand_return): Likewise.
+ * typeck2.c (digest_init): Likewise for { }.
+ * init.c (expand_aggr_init_1): Keep the CONSTRUCTOR handling.
+ * cvt.c (cp_convert): Handle failure better.
- * init.c (emit_base_init): Check if there's a DECL_NAME on the
- member before trying to do an initialization for it.
+Wed Nov 13 11:51:20 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue May 10 11:34:37 1994 Mike Stump <mrs@cygnus.com>
+ * g++.c (main): Also set PEXECUTE_SEARCH, to make the invocation
+ of GCC be path-relative.
- * except.c: Don't do anything useful when cross compiling.
+Wed Nov 13 11:27:16 1996 Michael Meissner <meissner@tiktok.cygnus.com>
-Tue May 10 03:04:13 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * Make-lang.in (g++-cross): G++-cross doesn't need version.o, but
+ it does need choose-temp.o and pexecute.o.
- * decl.c (duplicate_decls): Fix up handling of builtins yet again.
- (push_overloaded_decl): Ditto.
+Wed Nov 13 07:53:38 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cvt.c (convert): Don't look for void type conversion.
+ * g++.c (error) [!HAVE_VPRINTF]: Put error back for the only time
+ that we still use it.
+ (P_tmpdir, R_OK, W_OK, X_OK) [__MSDOS__]: Delete unnecessary macros.
-Mon May 9 18:05:41 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Nov 13 02:00:26 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (do_friend): Only do a pushdecl for friends, not
- pushdecl_top_level.
+ * init.c (expand_default_init): Avoid calling constructors to
+ initialize reference temps.
-Mon May 9 13:36:34 1994 Jim Wilson (wilson@sphagnum.cygnus.com)
+ * cvt.c (convert_to_reference): Fix.
- * decl.c (lookup_name_current_level): Put empty statement after
- the label OUT to make the code valid C.
+Tue Nov 12 19:10:07 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon May 9 12:20:57 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cvt.c (cp_convert): Simplify for flag_ansi_overloading.
+ (convert_to_reference): Likewise.
+ * typeck.c (convert_for_initialization): Likewise.
+ * init.c (expand_default_init): Likewise.
+ (expand_aggr_init_1): Likewise.
+ * cp-tree.h (CONV_NONCONVERTING): Lose.
+ * typeck.c (build_c_cast): Lose allow_nonconverting parm.
+ * *.c: Adjust.
+ * call.c (build_user_type_conversion_1): Assume LOOKUP_ONLYCONVERTING.
- * typeck.c (build_binary_op_nodefault): Only complain about
- comparing void * and a function pointer if void * is smaller.
+Tue Nov 12 16:29:04 1996 Brendan Kehoe <brendan@canuck.cygnus.com>
-Sun May 8 01:29:13 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (tsubst_expr): Reverse args to expand_start_catch_block.
- * decl.c (lookup_name_current_level): Move through temporary binding
- levels.
+Tue Nov 12 15:26:17 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (already_scoped_stmt): Revive.
- (simple_stmt): Use it again.
+ * init.c (expand_aggr_init_1): Don't crash on non-constructor
+ TARGET_EXPR.
- * decl.c (poplevel): Always call poplevel recursively if we're
- dealing with a temporary binding level.
+Tue Nov 12 14:00:50 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Sat May 7 10:52:28 1994 Mike Stump <mrs@cygnus.com>
+ * g++.c: Include gansidecl.h.
+ (VPROTO, PVPROTO, VA_START): Delete.
+ (choose_temp_base_try, choose_temp_base, perror_exec,
+ run_dos) [__MSDOS__]: Delete fns.
+ (pfatal_with_name): Delete fn.
+ (temp_filename): Declare like in gcc.c.
+ (pexecute, pwait, choose_temp_base): Declare from gcc.c.
+ (error_count, signal_count): Define.
+ (error): Delete both definitions.
+ (PEXECUTE_{FIRST,LAST,SEARCH,VERBOSE}): Define from gcc.c.
+ (pfatal_pexecute): Add fn from gcc.c.
+ (main): Rename local VERBOSE var to VERBOSE_FLAG. Rewrite the
+ code to use the pexecute stuff also used by gcc.c.
+ (MIN_FATAL_STATUS): Define.
+ * Make-lang.in (g++): Add dependency on and linking with
+ choose-temp.o and pexecute.o.
- * decl.c (finish_decl): Make sure we run cleanups for initial values
- of decls. Cures memory leak.
- * decl.c (expand_static_init): Ditto for static variables.
- * decl2.c (finish_file): Ditto for globals.
+ * cp-tree.h: Include gansidecl.h.
+ (STDIO_PROTO): Delete #undef/#define.
+ * cvt.c (NULL): Delete #undef/#define.
+ * expr.c (NULL): Likewise.
+ * init.c (NULL): Likewise.
+ * rtti.c (NULL): Likewise.
+ * xref.c (NULL): Likewise.
-Sat May 7 03:57:44 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cp-tree.h (build_user_type_conversion): Add prototype.
+ * call.c (build_user_type_conversion): Delete prototype. Correct
+ decl of FLAGS arg to be an int.
+ * cvt.c (build_user_type_conversion): Likewise.
- * typeck.c (commonparms): Don't complain about redefining default
- args.
+Tue Nov 12 12:16:20 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (duplicate_decls): Don't complain twice about conflicting
- function decls.
- (decls_match): Don't look at default args.
- (redeclaration_error_message): Complain about redefining default
- args.
+ * cp-tree.def: Add TRY_BLOCK and HANDLER.
+ * except.c (expand_start_catch_block): Support templates.
+ * parse.y (try_block, handler_seq): Likewise.
+ * pt.c (tsubst_expr): Support TRY_BLOCK and HANDLER.
- * call.c (build_overload_call_real): Also deal with guiding
- declarations coming BEFORE the template decl.
+Mon Nov 11 13:57:31 1996 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (unify): Allow different parms to have different
- cv-qualifiers.
- (unify): Allow trivial conversions on non-template parms.
+ * pt.c (current_template_args): New fn.
+ (push_template_decl): Use it.
+ * decl.c (grokdeclarator): Use it.
-Fri May 6 03:53:23 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (build_expr_from_tree): Dereference ref vars.
- * pt.c (tsubst): Support OFFSET_TYPEs.
- (unify): Ditto.
+ * decl.c (grokdeclarator): Generalize handling of TYPENAME_TYPEs in
+ the decl-specifier-seq.
- * decl2.c (finish_decl_parsing): Call push_nested_class with a type.
+ * decl.c (grok_op_properties): Don't force the type of a conversion
+ op to be complete. Don't warn about converting to the same type
+ for template instantiations.
- * init.c (build_offset_ref): Fix error message.
- * search.c (lookup_field): Ditto.
+ * decl2.c (finish_file): Don't call instantiate_decl on synthesized
+ methods.
- * call.c (build_scoped_method_call): Pass binfo to
- build_method_call.
- * typeck.c (build_object_ref): Ditto.
+Mon Nov 11 13:20:34 1996 Bob Manson <manson@charmed.cygnus.com>
- * typeck2.c (binfo_or_else): Don't return a _TYPE.
+ * typeck.c (get_delta_difference): Remove previous bogusness.
+ Don't give errors if force is set.
- * class.c (finish_struct): Don't complain about re-use of inherited
- names or shadowing of type decls.
- * decl.c (pushdecl_class_level): Ditto.
+Fri Nov 8 17:38:44 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (finish_enum): Set the type of all the enums.
+ * decl2.c (finish_file): Don't emit debug info.
+ * decl.c (pushdecl): Lose obsolete code.
+ (grokdeclarator): Still do the long long thing after complaining.
+ * search.c (note_debug_info_needed): Don't do anything if we're in a
+ template.
+ * method.c (synthesize_method): For non-local classes,
+ push_to_top_level first.
- * class.c (finish_struct): Don't get confused by access decls.
+Fri Nov 8 11:52:28 1996 Bob Manson <manson@charmed.cygnus.com>
- * cp-tree.h (TYPE_MAIN_DECL): New macro to get the _DECL for a
- _TYPE. You can stop using TYPE_NAME for that now.
+ * typeck.c (get_delta_difference): Add no_error parameter.
+ (build_ptrmemfunc): Call get_delta_difference with no_error set;
+ we don't want error messages when converting unrelated
+ pointer-to-member functions.
- * parse.y: Lose doing_explicit (check $0 instead).
- * gxx.gperf: 'template' now has a RID.
- * lex.h (rid): Ditto.
- * lex.c (init_lex): Set up the RID for 'template'.
+Thu Nov 7 11:16:24 1996 Mike Stump <mrs@cygnus.com>
- * parse.y (type_specifier_seq): typed_typespecs or
- nonempty_type_quals. Use it.
- (handler_args): Fix bogus syntax.
- (raise_identifier{,s}, optional_identifier): Lose.
- * except.c (expand_start_catch_block): Use grokdeclarator to parse
- the catch variable.
- (init_exception_processing): The second argument to
- __throw_type_match is ptr_type_node.
+ * error.c (dump_expr): Improve the wording on error messages that
+ involve pointer to member functions.
- Fri May 6 07:18:54 1994 Chip Salzenberg (chip@fin)
+Tue Nov 5 17:12:05 1996 Mike Stump <mrs@cygnus.com>
- [ change propagated from c-decl.c of snapshot 940429 ]
- * cp/decl.c (finish_decl): Setting asmspec_tree should not
- zero out the old RTL.
+ * cvt.c (cp_convert_to_pointer): Move code for conversions from
+ (::*)() to void* or (*)() up a bit, so that we can convert from
+ METHOD_TYPEs as well.
-Fri May 6 01:25:38 1994 Mike Stump <mrs@cygnus.com>
+Tue Nov 5 14:54:17 1996 Jason Merrill <jason@yorick.cygnus.com>
- Add alpha exception handling support to the compiler.
- Quick and dirty backend in except.c.
+ * rtti.c (get_tinfo_fn): Make sure 'type' is permanent.
+ There are no 'member' types.
+ (get_tinfo_fn_dynamic): Diagnose typeid of overloaded fn.
+ (build_x_typeid): Handle errors.
- * cp/*: Remove most remnants of old exception handling support.
- * decl.c (finish_function): Call expand_exception_blocks to put
- the exception hanlding blocks at the end of the function.
- * dec.c (hack_incomplete_structures): Make sure expand_decl_cleanup
- comes after expand_decl_init.
- * except.c: Reimplementation.
- * expr.c (cplus_expand_expr): Handle THROW_EXPRs.
- * lex.c (init_lex): Always have catch, try and throw be reserved
- words, so that we may always parse exception handling.
- * parse.y: Cleanup to support new interface into exception handling.
- * tree.def (THROW_EXPR): Add.
+Mon Nov 4 17:43:12 1996 Mike Stump <mrs@cygnus.com>
-Thu May 5 17:35:37 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (convert_for_assignment): Handle anachronistic implicit
+ conversions from (::*)() to void* or (*)().
+ * cvt.c (cp_convert_to_pointer): Likewise.
+ (cp_convert_to_pointer_force): Remove cp_convert_to_pointer
+ conversions from here.
+ * decl2.c (lang_decode_option): Add -W{no-,}pmf-conversions.
+ * lang-options.h: Likewise.
+ * decl2.c (warn_pmf2ptr): Define.
+ * cp-tree.h: Declare it.
+ * typeck2.c (digest_init): Allow pmfs down into
+ convert_for_initialization.
- * parse.y (simple_stmt, for loops): Use implicitly_scoped_stmt.
- (various): Lose .kindof_pushlevel and partially_scoped_stmt.
+Sun Nov 3 09:43:00 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu May 5 16:17:27 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * typeck.c (c_expand_return): Fix for returning overloaded fn.
- * parse.y (already_scoped_stmt): move expand_end_binding() to
- fix the unmatched LBB/LBE in stabs.
+Fri Nov 1 08:53:17 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu May 5 14:36:17 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cp-tree.h (DIRECT_BIND): Change from INDIRECT_BIND.
+ * decl.c (grok_reference_init): Pass DIRECT_BIND.
+ * cvt.c (build_up_reference): Don't mark 'this' addressable. Use
+ DIRECT_BIND.
+ * call.c (convert_like): Don't pass INDIRECT_BIND.
+ * typeck.c (convert_arguments): Likewise.
+ * typeck.c (mark_addressable): Allow &this if flag_this_is_variable.
- * decl.c (set_nested_typename): Set TREE_MANGLED on the new
- identifiers.
- (pushdecl): Check TREE_MANGLED.
- (xref_tag): Ditto.
- * cp-tree.h (TREE_MANGLED): This identifier is a
- DECL_NESTED_TYPENAME (named to allow for future use to denote
- mangled function names as well).
+Thu Oct 31 17:08:49 1996 Jason Merrill <jason@yorick.cygnus.com>
- Implement inconsistency checking specified in [class.scope0].
- * decl.c (lookup_name_real): Don't set ICV here after all.
- (finish_enum): Also set the type of the enumerators themselves.
- (build_enumerator): Put the CONST_DECL in the list instead of its
- initial value.
- (pushdecl_class_level): Check inconsistent use of a name in the
- class body.
- * class.c (finish_struct): Check inconsistent use of a name in the
- class body. Don't set DECL_CONTEXT on types here anymore.
- * parse.y (qualified_type_name): Note that the identifier has now
- been used (as a type) in the class body.
- * lex.c (do_identifier): Note that the identifier has now been used
- (as a constant) in the class body.
- * error.c (dump_decl): Print type and enum decls better.
+ * typeck.c (mark_addressable): Support TARGET_EXPR, unify with
+ similar code in build_up_ref.
+ * cvt.c (build_up_reference): Drastically simplify.
-Thu May 5 09:35:35 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+Mon Oct 28 12:45:05 1996 Jeffrey A Law (law@cygnus.com)
- * typeck.c (build_modify_expr): Warn about assignment to `this'.
+ * typeck.c (signed_or_unsigned_type): If the given type already
+ as the correct signedness, then just return it.
-Wed May 4 15:55:49 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c ({un,}signed_type): If can't do anything, call
+ signed_or_unsigned_type.
- * init.c (build_delete): Use the global operator delete when
- requested.
+Thu Oct 24 14:21:59 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (lookup_name_real): If we find the type we're looking in a
- base class while defining a class, set IDENTIFIER_CLASS_VALUE for
- the type.
+ * decl2.c (copy_assignment_arg_p): Don't buy the farm if
+ current_class_type is NULL.
- * class.c (finish_struct): Remove a couple of dependencies on
- language linkage.
+Wed Oct 23 00:43:10 1996 Jason Merrill <jason@gerbil.cygnus.com>
- * decl.c (pushtag): Classes do nest in extern "C" blocks.
- (pushdecl): Only set DECL_NESTED_TYPENAME on the canonical one for
- the type.
- (pushtag): Remove another dependency on the language linkage.
+ * class.c (finish_struct_1): Avoid empty structs by adding a field
+ so layout_type gets the mode right.
- * lex.c (cons_up_default_function): Don't set DECL_CLASS_CONTEXT to
- a const-qualified type.
+ * typeck.c (c_expand_return): Drastically simplify.
- * decl.c (push_overloaded_decl): Throw away built-in decls here.
- (duplicate_decls): Instead of here.
+Mon Oct 21 22:34:02 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed May 4 15:27:40 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * typeck.c (decay_conversion): Handle overloaded methods.
- * typeck.c (get_member_function_from_ptrfunc): Do The Right
- Thing (I hope) if we're using thunks.
+Fri Oct 18 16:03:48 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed May 4 13:52:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_over_call): A TARGET_EXPR has side-effects.
- * parse.y (specialization): aggr template_type_name ';'.
- (named_class_head_sans_basetype): Use it.
- (explicit_instantiation): Ditto.
- (tmpl.2): Revert.
+Thu Oct 17 11:31:59 1996 Mike Stump <mrs@cygnus.com>
- * cvt.c (build_type_conversion_1): Use convert_for_initialization,
- rather than convert, to do conversions after the UDC.
+ * cvt.c (convert_to_pointer_force): Add code to support pointer to
+ member function to pointer to function conversions.
+ * init.c (resolve_offset_ref): Add code to allow faked up objects,
+ ignoring them if they are not used, and giving an error, if they
+ are needed.
+ * typeck.c (get_member_function_from_ptrfunc): Fold e1 to improve
+ code, and so that we can give an error, if we needed an object,
+ and one was not provided.
+ (build_c_cast): Don't call default_conversion when we want to
+ convert to pointer to function from a METHOD_TYPE.
- * cp-tree.h (SHARED_MEMBER_P): This member is shared between all
- instances of the class.
+Mon Oct 14 00:28:51 1996 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (lookup_field): If the entity found by two routes is the
- same, it's not ambiguous.
+ * Make-lang.in (cplib2.ready): Fix logic.
-Wed May 4 12:10:00 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * decl.c (shadow_tag): Only complain about non-artificial function
+ members.
- * decl.c (lookup_name_real): Check for a NULL TREE_VALUE,
- to prevent the compiler from crashing ...
+ * class.c (finish_struct_1): Add synthesized methods to TYPE_METHODS.
-Wed May 4 11:19:45 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Oct 11 16:12:40 1996 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): If we don't have an object, check
- basetype_path to figure out where to look up the function.
+ * expr.c (cplus_expand_expr): Pre-tweak call_target like
+ expand_inline_function would.
- * typeck.c (convert_for_initialization): Pass TYPE_BINFO (type) to
- build_method_call in case exp is NULL_TREE.
+ * pt.c (mark_decl_instantiated): If extern_p, call
+ mark_inline_for_output.
-Tue May 3 16:02:53 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Thu Oct 10 15:58:08 1996 Mike Stump <mrs@cygnus.com>
- Give a vtable entries a unique named type, for the sake of gdb.
- * class.c (build_vtable_entry): The addres of a thunk now has
- type vtable_entry_type, not ptr_type_node.
- * method.c (make_thunk): Fix type of THUNK_DECL.
- * class.c (add_virtual_function, override_one_vtable): Use
- vfunc_ptr_type_node, instead of ptr_type_node.
- * cp-tree.h (vfunc_ptr_type_node): New macro.
- * decl.c (init_decl_processing): Make vtable_entry_type
- be a unique type of pointer to a unique function type.
+ * typeck.c (unary_complex_lvalue): Add code to handle intermediate
+ pmd conversions.
-Tue May 3 09:20:44 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (get_delta_difference): Fix wording, as we can be used
+ for pointer to data members.
- * parse.y (do_explicit): Sets doing_explicit to 1.
- (explicit_instantiation): Use do_explicit rather than TEMPLATE
- directly, add "do_explicit error" rule.
- (datadef): Set doing_explicit to 0 after an explicit instantiation.
- (tmpl.2): Don't instantiate if we see a ';' unless we're doing an
- explicit instantiation.
- (named_class_head_sans_basetype): Remove aggr template_type_name
- ';' again.
+Tue Oct 8 12:43:51 1996 Bob Manson <manson@charmed.cygnus.com>
-Mon May 2 23:17:21 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (tsubst): If the function decl isn't a member of this
+ template, return a copy of the decl (including copying the
+ lang-specific part) so we don't hose ourselves later.
- * search.c (lookup_nested_tag): Lose.
+Thu Oct 3 16:24:28 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (grokfield): Set DECL_CONTEXT on TYPE_DECLs.
- (lookup_name_nonclass): Lose.
+ * class.c (finish_struct): Remove DWARF-specific tag handling.
+ * decl.c (pushtag): Likewise.
+ (finish_function): Always clear DECL_ARGUMENTS on function decls with
+ no saved RTX.
+ * decl2.c (finish_file): Emit DWARF debugging info for static data
+ members.
- * decl.c (poplevel_class): Add force parameter.
- (lookup_name_real): Fix handling of explicit scoping which specifies
- a class currently being defined. Add 'nonclass' argument.
- (lookup_name, lookup_name_nonclass): Shells for lookup_name_real.
+Wed Oct 2 21:58:01 1996 Bob Manson <manson@charmed.cygnus.com>
- * class.c (finish_struct): Don't unset IDENTIFIER_CLASS_VALUEs here.
- (popclass): Force clearing of IDENTIFIER_CLASS_VALUEs if we're being
- called from finish_struct.
+ * decl.c (duplicate_decls): Make sure the old DECL_LANG_SPECIFIC
+ isn't the same as the new one before we whack it.
-Mon May 2 19:06:21 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Mon Sep 30 13:38:24 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (init_decl_processing), cp-tree.h: Removed memptr_type.
- (It seeems redundant, given build_ptrmemfunc_type.)
- * typeck.c (get_member_function_from_ptrfunc), gc.c (build_headof,
- build_classof): Use vtable_entry_type instead of memptr_type.
- * method.c (emit_thunk): Call poplevel with functionbody==0
- to prevent DECL_INITIAL being set to a BLOCK.
+ * class.c, cp-tree.h, cvt.c, decl.c, decl2.c, gxx.gperf, hash.h,
+ lex.c, method.c, parse.y, typeck.c, typeck2.c: Remove
+ warn_traditional and warn_strict_prototypes; remove ancient
+ 'overload' code; remove references to flag_traditional.
-Mon May 2 15:02:11 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Sep 30 12:58:40 1996 Mike Stump <mrs@cygnus.com>
- * parse.y (named_class_head_sans_basetype): Add "aggr
- template_type_name ';'" rule for forward declaration of
- specializations.
+ * input.c (sub_getch): Handle 8-bit characters in string literals.
-Mon May 2 15:02:11 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sun Sep 29 03:12:01 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (instantiate_type): Deal with pmf's.
+ * tree.c (mapcar): Handle CONSTRUCTORs.
+ (copy_to_permanent): Handle expression_obstack properly.
- * Make-lang.in (cc1plus): Don't depend on OBJS or BC_OBJS, since
- stamp-objlist does.
+ * Make-lang.in (cplib2.txt): Also depend on the headers.
- * Makefile.in (../cc1plus): Depend on OBJDEPS.
- (OBJDEPS): Dependency version of OBJS.
+ * rtti.c (get_tinfo_var): Don't assume that POINTER_SIZE ==
+ INT_TYPE_SIZE.
+ (expand_class_desc): Use USItype for offset field.
+ * tinfo.h (struct __class_type_info): Likewise.
-Mon May 2 12:51:31 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * method.c (build_overload_int): TYPE_PRECISION should be applied
+ to types.
- * search.c (dfs_debug_mark): unmark TYPE_DECL_SUPPRESS_DEBUG, not
- DECL_IGNORED_P.
+Sat Sep 28 14:44:50 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Apr 29 12:29:56 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_new_op): A COND_EXPR involving void must be a
+ builtin.
- * class.c (finish_struct): Clear out memory of local tags. And
- typedefs.
+Fri Sep 27 16:40:30 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (grokclassfn): Don't set DECL_CONTEXT to a cv-qualified
- type.
- * search.c (get_matching_virtual): Be more helpful in error message.
+ * typeck.c (build_x_component_ref): New fn.
+ (build_object_ref): Use it.
+ * parse.y (primary): Use it.
+ * decl2.c (build_expr_from_tree): Use it.
+ * cp-tree.h: Declare it.
- * *: Use DECL_ARTIFICIAL (renamed from DECL_SYNTHESIZED).
+ * decl.c (start_decl): variable-sized arrays cannot be initialized.
+ * error.c (dump_type_suffix): Handle variable arrays.
- * lex.c (default_assign_ref_body): Expect TYPE_NESTED_NAME to work.
- (default_copy_constructor_body): Ditto.
+Fri Sep 27 13:14:05 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * class.c (finish_struct): Don't gratuitously create multiple decls
- for nested classes.
+ * Make-lang.in (exception.o): Put back compiling it with -fPIC.
-Thu Apr 28 23:39:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Sep 27 03:00:09 1996 Jason Merrill <jason@yorick.cygnus.com>
- Avoid clobbering the arg types of other functions when reverting
- static member functions.
- * decl.c (revert_static_member_fn): Rearrange arguments, don't
- require values for 'fn' and 'argtypes', add warning to comment
- above.
- (decls_match): Rearrange arguments in call to rsmf.
- (grok_op_properties): Don't pass values for fn and argtypes.
- * pt.c (instantiate_template): Don't pass values for fn and argtypes.
+ * decl.c (lookup_name_real): Don't try to look up anything in a
+ TYPENAME_TYPE.
-Thu Apr 28 16:29:11 1994 Doug Evans (dje@canuck.cygnus.com)
+ * tinfo2.cc (__throw_type_match_rtti): Oops.
- * Make-lang.in (cc1plus): Depend on stamp-objlist.
- * Makefile.in (BC_OBJS): Delete.
- (OBJS): Cat ../stamp-objlist to get language independent files.
- Include ../c-common.o.
- (../cc1plus): Delete reference to BC_OBJS.
+Thu Sep 26 22:11:05 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Thu Apr 28 02:12:08 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * Make-lang.in (exception.o): Use -fno-PIC for now.
- * search.c (compute_access): No really, deal with static members
- properly. Would I lie to you?
+Thu Sep 26 10:59:00 1996 Jason Merrill <jason@yorick.cygnus.com>
- Implement lexical hiding of function declarations.
- * pt.c (tsubst): Use lookup_name to look for function decls to guide
- instantiation.
- * method.c (build_opfncall): Use lookup_name_nonclass to look for
- non-member functions.
- * init.c (do_friend): Use lookup_name_nonclass to look for
- functions.
- * error.c (ident_fndecl): Use lookup_name to look for functions.
- * decl2.c (lookup_name_nonclass): New function, skips over
- CLASS_VALUE.
- * decl.c (struct binding_level): Lose overloads_shadowed field.
- (poplevel): Don't deal with overloads_shadowed.
- (push_overloaded_decl): Do lexical hiding for functions.
- * class.c (instantiate_type): Don't check non-members if we have
- members with the same name.
- * call.c (build_method_call): Use lookup_name_nonclass instead of
- IDENTIFIER_GLOBAL_VALUE to check for non-member functions.
- (build_overload_call_real): Ditto.
-
- * decl.c (duplicate_decls): Check for ambiguous overloads here.
- (push_overloaded_decl): Instead of here.
+ * rtti.c (build_dynamic_cast): Pass tinfo fns rather than
+ calling them.
+ (get_tinfo_fn_dynamic): Extracted from build_typeid.
+ * tinfo2.cc (__dynamic_cast): Adjust.
- * decl.c (pushdecl): Back out Chip's last change.
+ * rtti.c (build_typeid): Use resolves_to_fixed_type_p.
+ (build_x_typeid): Likewise.
- * decl.c (grok_op_properties): operators cannot be static members.
+ * parse.y: Call build_x_typeid instead of build_typeid.
+ * cp-tree.def: Add TYPEID_EXPR.
+ * pt.c (tsubst_copy): Handle typeid.
+ * decl2.c (build_expr_from_tree): Likewise.
+ * rtti.c (build_x_typeid): Throw bad_typeid from here.
+ (build_typeid): Not here.
+ * cp-tree.h: Declare build_x_typeid.
- * cp-tree.h (DECL_SYNTHESIZED): DECL_SOURCE_LINE == 0
- (SET_DECL_SYNTHESIZED): DECL_SOURCE_LINE = 0
- * lex.c (cons_up_default_function): Use SET_DECL_SYNTHESIZED.
+Wed Sep 25 17:26:16 1996 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (do_inline_function_hair): Don't put friends of local
- classes into global scope, either.
+ * call.c (convert_like): Pull out constant values.
- * typeck2.c (build_functional_cast): Don't look for a function call
- interpretation.
+ * tree.c (mapcar): Use build_cplus_array_type, not build_array_type.
-Thu Apr 28 15:19:46 1994 Mike Stump <mrs@cygnus.com>
+Wed Sep 25 17:28:53 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * cp-tree.h: disable use of backend EH.
+ * decl.c (init_decl_processing): Create short int types before
+ creating size_t in case a machine description needs to use
+ unsigned short for size_t.
-Wed Apr 27 21:01:24 1994 Doug Evans (dje@canuck.cygnus.com)
+Tue Sep 24 18:18:44 1996 Jason Merrill <jason@yorick.cygnus.com>
- * Make-lang.in (c++.distdir): mkdir tmp/cp first.
- * Makefile.in (INCLUDES): Move definition to same place as
- parent makefile.
- (ALLOCA): Define.
- (OLDAR_FLAGS): Delete.
- (OLDCC): Define.
- (DIR): Delete.
- (CLIB): Define.
- (####site): Delete.
- (SUBDIR_USE_ALLOCA): Don't use ALLOCA if compiling with gcc.
+ * Make-lang.in (exception.o): Turn off pic.
-Wed Apr 27 19:10:04 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * tinfo2.cc (__throw_type_match_rtti): Fix cv-variants of the same
+ type, multi-level ptr conversions.
- * decl.c (xref_tag): not to use strstr(), it's not available on
- all platforms.
+ * rtti.c (call_void_fn): Renamed and genericized from throw_bad_cast.
+ (throw_bad_cast): Use it.
+ (throw_bad_typeid): New fn.
+ (build_typeid): Throw bad_typeid as needed.
+ Use build_call.
+ (synthesize_tinfo_fn): Handle functions and arrays before checking
+ for cv-quals.
-Wed Apr 27 18:10:12 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * Remove .h from standard C++ headers, add new.h, move into inc
+ subdirectory.
- * class.c (finish_struct): Resolve yet another class/pmf confusion.
+ * exception*: Remove pointer from object, constructors. Add
+ default exception::what that uses type_info::name. Add
+ __throw_bad_typeid.
- * call.c (build_overload_call_real): Don't take the single-function
- shortcut if we're dealing with an overloaded operator.
+ * init.c (build_new): Don't add a cookie to new (void *) T[2].
-Wed Apr 27 17:35:37 1994 Mike Stump <mrs@cygnus.com>
+Mon Sep 23 15:21:53 1996 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (get_base_distance): Search the virtual base class
- binfos, incase someone wants to convert to a real virtual base
- class.
- * search.c (expand_indirect_vtbls_init): Use convert_pointer_to_real
- instead of convert_pointer_to, as it now will work.
+ * Make-lang.in: Building C++ code depends on cc1plus.
-Wed Apr 27 15:36:49 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Sep 23 12:38:40 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cvt.c (convert_to_reference): Don't complain about casting away
- const and volatile.
+ * decl.c (struct saved_scope): Declare PROCESSING_TEMPLATE_DECL as
+ a HOST_WIDE_INT, not a tree.
- * typeck.c (build_unary_op): References are too lvalues.
+Mon Sep 23 12:36:02 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Apr 27 13:58:05 1994 Mike Stump <mrs@cygnus.com>
+ * exception.cc: Don't include <stdlib.h>.
- * class.c (override_one_vtable): We have to prepare_fresh_vtable
- before we modify it, not after, also, we cannot reuse an old vtable,
- once we commit to a new vtable. Implement ambiguous overrides in
- virtual bases as abstract. Hack until we make the class
- ill-formed.
+ * Make-lang.in (c++.clean): Remove cplib2.*.
-Wed Apr 27 01:17:08 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Sep 23 09:42:19 1996 Doug Evans <dje@canuck.cygnus.com>
- * parse.y (unary_expr): Expand new_placement[opt] and
- new_initializer[opt] inline.
+ * parse.y (component_decl_1, component_costructor_declarator case):
+ Pass attributes/prefix_attributes in tree list.
- * search.c (lookup_fnfields): Don't throw away the inheritance
- information here, either.
- (compute_access): Handle static members properly.
+Mon Sep 23 01:18:50 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (build_member_call): Always set basetype_path, and pass it
- to lookup_fnfields.
+ * tinfo{,2}.cc: #include <stddef.h> instead of <stdlib.h>.
- * search.c (lookup_field): Deal properly with the case where
- xbasetype is a chain of binfos; don't throw away the inheritance
- information.
- (compute_access): protected_ok always starts out at 0.
+Sun Sep 22 05:31:22 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (resolve_offset_ref): Don't cast `this' to the base type
- until we've got our basetype_path.
+ * lex.c (do_identifier): Don't do deferred lookup in a template
+ header.
- * cp-tree.h (IS_OVERLOAD_TYPE): aggregate or enum.
+ * typeck2.c (store_init_value): Oops.
- * cvt.c (build_up_reference): Use build_pointer_type rather than
- TYPE_POINTER_TO.
+ * new.{h,cc}, exception.{h,cc}, typeinfo.h, tinfo{2.cc,.cc,.h}:
+ New files for C++ lang-support library.
+ * Make-lang.in (CXX_EXTRA_HEADERS): Define.
+ (CXX_LIB2FUNCS): Define.
+ And rules for building the C++ lang-support code.
+ * config-lang.in (headers): Define.
+ (lib2funcs): Define.
- * call.c (convert_harshness_ansi): Call type_promotes_to for reals
- as well.
+Sat Sep 21 19:17:28 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (type_promotes_to): Retain const and volatile, add
- float->double promotion.
-
- * decl.c (grokdeclarator): Don't bash references to arrays into
- references to pointers in function parms. Use type_promotes_to.
+ * decl2.c (build_expr_from_tree): If CONSTRUCTOR has a type, call
+ digest_init.
+ * pt.c (tsubst_copy): Compute type for CONSTRUCTOR.
+ * typeck2.c (store_init_value): Check for initializing pmf with { }
+ here.
+ (process_init_constructor): Not here.
-Tue Apr 26 23:44:36 1994 Mike Stump <mrs@cygnus.com>
+Thu Sep 19 16:41:07 1996 Jason Merrill <jason@yorick.cygnus.com>
- Finish off Apr 19th work.
+ * pt.c (begin_template_parm_list): Increment
+ processing_template_decl here.
+ (end_template_parm_list): Not here.
+ (process_template_parm): No need to add 1 to it now.
+ * *.c: Use processing_template_decl instead of current_template_parms
+ to check for being in a template.
- * class.c (finish_struct_bits): Rename has_abstract_virtuals to
- might_have_abstract_virtuals.
- * class.c (strictly_overrides, override_one_vtable,
- merge_overrides): New routines to handle virtual base overrides.
- * class.c (finish_struct): Call merge_overrides to handle overrides
- in virtual bases.
+ * pt.c (uses_template_parms): Handle SCOPE_REF. Fix CONSTRUCTOR.
+ (tsubst_copy): Handle CONSTRUCTOR.
+ (instantiate_decl): Set up context properly for variables.
+ * decl2.c (build_expr_from_tree): Handle CONSTRUCTOR.
+ * class.c (finish_struct): Reverse CLASSTYPE_TAGS.
-Tue Apr 26 12:45:53 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Sep 18 13:30:20 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck.c (build_function_call): Call build_function_call_real with
- LOOKUP_NORMAL.
+ * lex.c (enum tree_node_kind) [GATHER_STATISTICS]: Put the enum back.
- * *: Don't deal with TYPE_EXPRs.
+Wed Sep 18 04:24:07 1996 Jason Merrill <jason@yorick.cygnus.com>
- * tree.c (lvalue_p): If the type of the expression is a reference,
- it's an lvalue.
+ * method.c (make_thunk): Call comdat_linkage before setting the
+ TREE_CODE.
- * cvt.c (convert_to_reference): Complain about passing const
- lvalues to non-const references.
- (convert_from_reference): Don't arbitrarily throw away const and
- volatile on the target type.
+ * decl2.c (comdat_linkage): Use make_decl_one_only.
+ (import_export_decl): Likewise.
+ * decl.c (init_decl_processing): Check supports_one_only instead of
+ SUPPORTS_WEAK.
- * parse.y: Simplify and fix rules for `new'.
+Sat Sep 14 08:34:41 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grok_op_properties): operator void is illegal.
+ * decl2.c (grokfield): Tighten checking for access decls.
-Mon Apr 25 02:36:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (make_typename_type): Resolve references to
+ current_class_type. Set CLASSTYPE_GOT_SEMICOLON.
+ (lookup_name_real): Types that depend on a template parameter get
+ an implicit 'typename' unless they're in the current scope.
+ (start_decl_1): We don't care about incomplete types that depend
+ on a template parm.
+ (grokdeclarator): Resolve 'typename's in the type specifier that
+ refer to members of the current scope.
- * parse.y (components): Anonymous bitfields can still have declspecs.
+ * call.c (build_over_call): Remove 'inline called before
+ definition' diagnostic.
+ (build_method_call): Likewise.
+ * decl.c (duplicate_decls): Downgrade 'used before declared
+ inline' to a warning, only with -Winline.
- * decl.c (pushdecl): Postpone handling of function templates like we
- do C functions.
+Fri Sep 13 17:31:40 1996 Stan Shebs <shebs@andros.cygnus.com>
- * search.c (expand_indirect_vtbls_init): Fix infinite loop when
- convert_pointer_to fails.
+ * mpw-make.sed: Fix include paths, add @DASH_C_FLAG@ to compile.
- * call.c (compute_conversion_costs_ansi): A user-defined conversion
- by itself is better than that UDC followed by standard conversions.
- Don't treat integers and reals specially.
+Wed Sep 11 22:38:13 1996 Gerald Baumgartner <gb@cs.purdue.edu>
- * cp-tree.h: Declare flag_ansi.
+ * call.c (build_method_call): When calling a signature
+ default implementation, as in other cases, let instance_ptr simply
+ be instance.
- * typeck.c (c_expand_return): pedwarn on return in void function
- even if the expression is of type void.
- (build_c_cast): Don't do as much checking for casts to void.
- (build_modify_expr): pedwarn about array assignment if this code
- wasn't generated by the compiler.
+Wed Sep 11 22:14:44 1996 Mike Stump <mrs@cygnus.com>
- * tree.c (lvalue_p): A comma expression is an lvalue if its second
- operand is.
+ * parse.y (simple_stmt): Cleanup and use do_poplevel ().
- * typeck.c (default_conversion): Move code for promoting enums and
- ints from here.
- * cvt.c (type_promotes_to): To here.
- * call.c (convert_harshness_ansi): Use type_promotes_to. Also fix
- promotion semantics for reals.
+Wed Sep 11 22:10:48 1996 Mike Stump <mrs@cygnus.com>
-Sun Apr 24 16:52:51 1994 Doug Evans (dje@canuck.cygnus.com)
+ * except.c (expand_start_catch_block): Add a pushlevel so that -g
+ works on hppa and SPARC.
- * Make-lang.in (c++.install-common): Check for g++-cross.
- * Makefile.in: Remove Cygnus cruft.
- (config.status): Delete.
- (RTL_H): Define.
- (TREE_H): Use complete pathname, some native makes have minimal
- VPATH support.
- (*.o): Use complete pathname to headers in parent dir.
- (doc, info, dvi): Delete.
+Wed Sep 11 10:18:06 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Sun Apr 24 16:52:51 1994 Doug Evans (dje@canuck.cygnus.com)
+ * typeck.c (build_indirect_ref): Catch PTR being an error_mark_node.
- * Make-lang.in (c++.install-common): Check for g++-cross.
- * Makefile.in: Remove Cygnus cruft.
- (config.status): Delete.
- (RTL_H): Define.
- (TREE_H): Use complete pathname, some native makes have minimal
- VPATH support.
- (*.o): Use complete pathname to headers in parent dir.
- (doc, info, dvi): Delete.
+Mon Sep 9 19:51:14 1996 Gerald Baumgartner <gb@cs.purdue.edu>
-Sun Apr 24 00:47:49 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_over_call): Check first whether DECL_CONTEXT exists
+ before testing whether it's a signature.
- * decl.c (pushdecl): Avoid redundant warning on redeclaring function
- with different return type.
- (decls_match): Compare return types strictly.
+Sun Sep 8 16:06:57 1996 Gerald Baumgartner <gb@cs.purdue.edu>
-Fri Apr 22 12:55:42 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_new_method_call): Don't complain about signature
+ pointers and references not being an aggr type.
+ (build_this): If a signature pointer or reference was passed in,
+ just return it.
+ (build_new_method_call): If instance is a signature pointer, set
+ basetype to the signature type of instance.
+ * sig.c (build_signature_method_call): Deleted basetype and
+ instance parameters, they can be found as the DECL_CONTEXT of
+ function and as the first argument passed in.
+ * cp-tree.h: Changed declaration of build_signature_method_call.
+ * call.c (build_method_call): Deleted first two arguments in call
+ of build_signature_method_call.
+ (build_over_call): Added call to build_signature_method_call.
- * cvt.c (build_type_conversion): Do try to convert through other
- pointers. This will fail if the class defines multiple pointer
- conversions.
+Thu Sep 5 16:51:28 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (build_c_cast): Don't tack a non_lvalue_expr onto a
+ target_expr.
+
+Thu Sep 5 10:05:38 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * cvt.c (convert_to_reference): Use %#T, not %#D, for error.
+
+Wed Sep 4 17:16:09 1996 Bob Manson <manson@charmed.cygnus.com>
+
+ * except.c (expand_start_try_stmts): Move to except.c in the backend.
+ (expand_end_try_stmts): Remove.
+
+ * init.c (perform_member_init): Use add_partial_entry () instead
+ of directly manipulating lists.
+ (emit_base_init): Ditto.
+
+Wed Sep 4 12:14:36 1996 Mike Stump <mrs@cygnus.com>
- * error.c (dump_type_prefix): Print out pointers to arrays properly.
- (dump_type_suffix): Ditto. (was 'int *[]', now 'int (*)[]')
+ * except.c (expand_exception_blocks): Always make sure USE and
+ CLOBBER insns that came at the end still do, the backend relies
+ upon this.
- * typeck.c (build_unary_op): Disallow ++/-- on pointers to
- incomplete type.
+Wed Sep 4 07:44:48 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (build_over_call): We can only use a TARGET_EXPR of the
+ right type.
+
+Tue Sep 3 19:26:05 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cvt.c (convert_to_reference): Revert last change, don't complain
+ about temp without target decl.
+
+Tue Sep 3 10:22:56 1996 Mike Stump <mrs@cygnus.com>
+
+ * decl.c (grokdeclarator): Don't core dump when void() is given.
+
+Tue Sep 3 02:38:56 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (copy_args_p): Don't crash.
+
+Fri Aug 30 14:26:57 1996 Mike Stump <mrs@cygnus.com>
+
+ * pt.c (tsubst): And support template args inside the exception
+ specification.
+
+ * pt.c (tsubst): Add support for exception specifications in
+ template functions.
+
+Fri Aug 30 10:01:55 1996 Mike Stump <mrs@cygnus.com>
+
+ * cp-tree.def (DECL_STMT): Eliminate the throw spec field, only 3
+ fields now.
+ * cp-tree.h (start_decl): Eliminate the throw spec parameter.
+ (start_function): Likewise.
+ (start_method): Likewise.
+ (grokfield): Likewise.
+ (make_call_declarator): Add throw spec parameter.
+ (set_quals_and_spec): Add routine.
+ * lex.c (set_quals_and_spec): Likewise.
+ * decl.h (grokdeclarator): Eliminate the throw spec parameter.
+ * decl.c (shadow_tag): Eliminate the throw spec parameter to
+ grokdeclarator.
+ (groktypename): Likewise.
+ (start_decl): Eliminate the throw spec parameter. Eliminate the
+ throw spec parameter to grokdeclarator. Eliminate the throw spec
+ field in DECL_STMT.
+ (cp_finish_decl): Eliminate the throw spec field in DECL_STMT.
+ (grokfndecl): Remove useless set of raises.
+ (grokdeclarator): Eliminate the throw spec parameter. Eliminate
+ the throw spec parameter to start_decl. Pull the throw spec out
+ of the call declarator.
+ (grokparms): Eliminate the throw spec parameter to grokdeclarator.
+ (start_function): Eliminate the throw spec parameter. Eliminate
+ the throw spec parameter to grokdeclarator.
+ (start_method): Likewise.
+ * decl2.c (grokfield): Likewise.
+ (grokbitfield): Eliminate the throw spec parameter to grokdeclarator.
+ (grokoptypename): Likewise.
+ (finish_file): Eliminate the throw spec parameter to
+ start_function. Add throw spec to make_call_declarator.
+ * except.c (init_exception_processing): Add throw spec to
+ make_call_declarator. Eliminate the throw spec parameter to
+ start_decl.
+ (expand_start_catch_block): Eliminate the throw spec parameter to
+ grokdeclarator.
+ (expand_builtin_throw): Add throw spec to make_call_declarator.
+ Eliminate the throw spec parameter to start_function.
+ (start_anon_func): Likewise.
+ * lex.c (make_call_declarator): Add throw spec parameter.
+ (set_quals_and_spec): New routine.
+ (cons_up_default_function): Add throw spec to make_call_declarator.
+ Eliminate the throw spec parameter to grokfield.
+ * method.c (synthesize_method): Eliminate the throw spec parameter
+ to start_function.
+ * pt.c (process_template_parm): Eliminate the throw spec parameter
+ to grokdeclarator.
+ (tsubst): Add throw spec to make_call_declarator.
+ (tsubst_expr): Eliminate the throw spec parameter to start_decl.
+ (do_function_instantiation): Eliminate the throw spec parameter to
+ grokdeclarator. Eliminate the throw spec parameter to
+ start_function.
+ * rtti.c (synthesize_tinfo_fn): Eliminate the throw spec parameter
+ to start_function.
+ * parse.y (datadef): Remove non-winning optimization.
+ (decl): Likewise.
+ (fndef): Remove ambiguous error productions uncovered by grammer
+ fixing.
+ (constructor_declarator): Add exception_specification_opt here.
+ (component_constructor_declarator): Likewise.
+ (direct_after_type_declarator): Likewise.
+ (complex_direct_notype_declarator): Likewise.
+ (direct_abstract_declarator): Likewise.
+ (fn.def1): Remove exception_specification_opt.
+ (fn.def2): Likewise.
+ (condition): Likewise.
+ (initdcl0): Likewise.
+ (initdcl): Likewise.
+ (notype_initdcl0): Likewise.
+ (nomods_initdcl0): Likewise.
+ (component_decl_1): Likewise.
+ (component_declarator): Likewise.
+ (after_type_component_declarator0): Likewise.
+ (after_type_component_declarator): Likewise.
+ (notype_component_declarator): Likewise.
+
+Wed Aug 28 01:40:30 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (build_over_call): Also use an INIT_EXPR when
+ initializing anything from an rvalue.
+
+ * call.c (build_over_call): Call stabilize_reference when building
+ an INIT_EXPR instead of calling the copy ctor.
+
+ * call.c (joust): Extend the previous change to all comparisons.
+
+ * decl2.c, method.c, lex.c: Use MAKE_DECL_ONE_ONLY and
+ NO_LINKAGE_HEURISTICS.
+
+ * decl2.c (finish_file): Emit any statics that weren't already.
+
+ * typeck.c (build_static_cast): Implement.
+ * tree.c (build_cplus_new): Handle getting a TARGET_EXPR.
+ * decl.c (grokparms): Use can_convert_arg instead of
+ implicit_conversion directly.
+ (copy_args_p): New fn.
+ * cvt.c (convert_to_reference): Don't complain about temp with
+ static_cast.
+ (build_up_reference): Handle TARGET_EXPRs.
+ * call.c (build_over_call): Elide unnecessary temps.
+ (can_convert*): Use new overloading code.
+
+Tue Aug 27 13:12:21 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c: Move TYPE_PTR*_MACROS ...
+ * cp-tree.h: To here.
+ * typeck.c (build_reinterpret_cast): Implement.
+
+ * call.c (add_builtin_candidate): Use TYPE_PTROB_P instead of
+ ptr_complete_ob.
+ (joust): If we're comparing a function to a builtin and the worst
+ conversion for the builtin is worse than the worst conversion for the
+ function, take the function.
+
+ * typeck.c (build_const_cast): Implement.
+ (comp_ptr_ttypes_const): Like comp_ptr_ttypes, for const_cast.
+ (comp_ptr_ttypes_reinterpret): Like cpt, for reinterpret_cast.
+
+Tue Aug 27 13:14:58 1996 Bob Manson <manson@charmed.cygnus.com>
+
+ * rtti.c (build_dynamic_cast): Don't try to dereference exprtype
+ too early. Make sure we explode if exprtype turns out to be a
+ NULL_TREE when it shouldn't be.
+
+Tue Aug 27 10:56:21 1996 Mike Stump <mrs@cygnus.com>
+
+ * cp-tree.h: New routine make_call_declarator.
+ * lex.c (make_call_declarator): Define it.
+ * except.c (init_exception_processing): Use it.
+ (expand_builtin_throw): Likewise.
+ (start_anon_func): Likewise.
+ * decl2.c (finish_file): Likewise.
+ * lex.c (cons_up_default_function): Likewise.
+ * parse.y: Likewise.
+ * pt.c (tsubst): Likewise.
+
+Mon Aug 26 17:40:03 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (duplicate_decls): Check mismatched TREE_CODES after
- checking for shadowing a builtin. If we're redeclaring a builtin
- function, bash the old decl to avoid an ambiguous overload.
+ * decl2.c (groktypefield): Remove unused code.
- * cvt.c (convert_to_reference): Don't force arrays to decay here.
+Mon Aug 26 17:00:33 1996 Mike Stump <mrs@cygnus.com>
- * tree.c (lvalue_p): A MODIFY_EXPR is an lvalue.
+ * gxx.gperf: Change TYPE_QUAL into CV_QUALIFIER.
+ * parse.y: Likewise. Change maybe_type_qual into maybe_cv_qualifier.
+ Change type_quals into cv_qualifiers. Change nonempty_type_quals into
+ nonempty_cv_qualifiers.
+ * hash.h: Rebuild.
+
+ * lex.c (make_pointer_declarator): Change type_quals into
+ cv_qualifiers.
+ (make_reference_declarator): Likewise.
+
+Thu Aug 22 01:09:22 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (duplicate_decls): Don't assume that the decls will have
- types.
+ * decl.c (start_function): Only check interface_* for templates
+ with flag_alt_external_templates.
- Mon Apr 18 11:35:32 1994 Chip Salzenberg (chip@fin.uucp)
+ * call.c (build_new_op): Check for comparison of different enum types.
+ (build_over_call): Fix arg # output.
- [ cp/* changes propagated from c-* changes in 940318 snapshot ]
- * c-decl.c (pushdecl): Warn if type mismatch with another external decl
- in a global scope.
+ * typeck.c (build_component_ref): Handle pre-found TYPE_DECL.
- Fri Apr 22 06:38:56 1994 Chip Salzenberg (chip@fin.uucp)
+Wed Aug 21 00:13:15 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp/typeck2.c (signature_error): Use cp_error for "%T".
+ * call.c (build_new_op): Check for erroneous args.
- Mon Apr 18 11:59:59 1994 Chip Salzenberg (chip@fin.uucp)
+ * call.c (build_new_method_call): Add missing args to cp_error.
- [ cp/* changes propagated from c-* changes in 940415 snapshot ]
- * cp/decl.c (duplicate_decls, pushdecl, builtin_function):
- Use DECL_FUNCTION_CODE instead of DECL_SET_FUNCTION_CODE.
+ * tree.c (error_type): Dont print reference-to-array.
- Mon Apr 18 11:55:18 1994 Chip Salzenberg (chip@fin.uucp)
+ * typeck.c (convert_for_assignment): Don't say contravariance for
+ removing const.
- [ cp/* changes propagated from c-* changes in 940409 snapshot ]
- * cp/decl.c (duplicate_decls): Put new type in same obstack as
- old ones, or permanent if old ones in different obstacks.
+Tue Aug 20 13:23:00 1996 Jason Merrill <jason@yorick.cygnus.com>
- Mon Apr 18 11:48:49 1994 Chip Salzenberg (chip@fin.uucp)
+ * call.c (build_over_call): Diagnose bad convs for `this'.
- [ cp/* changes propagated from c-* changes in 940401 snapshot ]
- * cp/parse.y (attrib): Handle string args as expressions,
- merging the two rules. `mode' attribute now takes a string arg.
- Delete the rule for an identifier as arg.
+ * lex.c (cons_up_default_function): Set DECL_ARTIFICIAL
+ on _ctor_arg.
- Mon Apr 18 11:24:00 1994 Chip Salzenberg (chip@fin.uucp)
+ * call.c (convert_like): Handle bad convs.
+ (build_over_call): Handle bad convs better.
- [ cp/* changes propagated from c-* changes in 940312 snapshot ]
- * cp/typeck.c (pointer_int_sum): Multiplication should be done signed.
- (pointer_diff): Likewise the division.
+ * decl2.c: -fansi-overloading is now the default.
- Sun Mar 6 19:43:39 1994 Chip Salzenberg (chip@fin.uucp)
+ * call.c (build_new_method_call): Check for erroneous args.
- [ cp/* changes propagated from c-* changes in 940304 snapshot ]
- * cp/decl.c (finish_decl): Issue warning for large objects,
- if requested.
+ * pt.c (instantiate_class_template): Propagate
+ TYPE_USES_MULTIPLE_INHERITANCE.
- Sat Feb 19 22:20:32 1994 Chip Salzenberg (chip@fin.uucp)
+Tue Aug 20 13:09:57 1996 Mike Stump <mrs@cygnus.com>
- [ cp/* changes propagated from c-* changes in 940218 snapshot ]
- * cp/parse.y (attrib): Handle attribute ((section ("string"))).
- * cp/decl.c (duplicate_decls): Merge section name into new decl.
+ * call.c (enforce_access): Add static to routine.
- Tue Feb 8 09:49:17 1994 Chip Salzenberg (chip@fin.uucp)
+Sun Aug 18 14:35:54 1996 Jason Merrill <jason@yorick.cygnus.com>
- [ cp/* changes propagated from c-* changes in 940206 snapshot ]
- * cp/typeck.c (signed_or_unsigned_type): Check for any
- INTEGRAL_TYPE_P not just INTEGER_TYPE.
+ * call.c (build_user_type_conversion_1): Fix bad handling.
+ (compare_ics): Likewise.
- Mon Dec 6 13:35:31 1993 Norbert Kiesel (norbert@i3.INformatik.rwth-aachen.DE)
+Sat Aug 17 21:54:11 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp/decl.c (finish_enum): Start from 0 when determining precision
- for short enums.
+ * call.c (standard_conversion): Oops.
- Fri Dec 3 17:07:58 1993 Ralph Campbell (ralphc@pyramid.COM)
+Sat Aug 17 16:28:11 1996 Geoffrey Noer <noer@cygnus.com>
- * cp/parse.y (unary_expr): Look at $1 for tree_code rather than
- casting $$.
+ * g++.c: Update test for win32 (&& ! cygwin32).
- Wed Nov 17 19:22:09 1993 Chip Salzenberg (chip@fin.uucp)
+Sat Aug 17 03:45:31 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp/typeck.c (build_binary_op_nodefault): Propagate code
- from C front-end to optimize unsigned short division.
- (build_conditional_expr): Fix bug in "1 ? 42 : (void *) 8".
+ * typeck.c (comp_ptr_ttypes_real): Handle OFFSET_TYPEs properly.
+ (ptr_reasonably_similar): New fn.
+ * call.c (BAD_RANK): New rank.
+ (ICS_BAD_FLAG): New macro.
+ (standard_conversion): Handle almost-right pointer conversions.
+ (reference_binding): Handle bad rvalue bindings.
+ (add_*_candidate): Stuff.
+ (build_over_call): Pass bad conversions to convert_for_initialization.
+ (compare_ics): Handle bad convs.
+ (joust): Likewise.
- Wed Nov 17 19:17:18 1993 Chip Salzenberg (chip@fin.uucp)
+Fri Aug 16 15:02:19 1996 Bob Manson <manson@charmed.cygnus.com>
- * cp/call.c (convert_harshness_ansi): Given an (e.g.) char
- constant, prefer 'const char &' to 'int'.
+ * init.c (expand_vec_init): Use ptrdiff_type_node instead of
+ integer_type_node when computing pointer offsets.
- Wed Feb 3 13:11:48 1993 Chip Salzenberg (chip@fin.uucp)
+Fri Aug 16 01:28:32 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp/class.c (finish_struct_methods): Handle multiple
- constructors in fn_fields list.
+ * tree.c (lvalue_type): New fn.
+ (error_type): New fn.
+ * call.c (op_error): Use error_type.
+ (add_conv_candidate): Use lvalue_type.
+ (add_builtin_candidates): Likewise.
+ * error.c (args_as_string): Use error_type.
-Fri Apr 22 12:48:10 1994 Kung Hsu (kung@mexican.cygnus.com)
+Thu Aug 15 17:27:13 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): use TYPE_DECL_SUPPRESS_DEBUG to flag
- types not to be dumped in stabs, like types in #pragma interface.
- * decl.c (init_decl_processing): use TYPE_DECL_SUPPRESS_DEBUG to
- mark unknown type.
+ * pt.c (instantiate_decl): Evaluate DECL_INITIAL of a VAR_DECL here.
+ (tsubst): Not here.
-Fri Apr 22 03:27:26 1994 Doug Evans (dje@cygnus.com)
+ * decl.c (init_decl_processing): With -ansi, __null's type is the
+ signed integral type with the same number of bits as a pointer.
+ Introduce a new variable null_node for it.
+ * cp-tree.h: Adjust.
+ * call.c (null_ptr_cst_p): Adjust.
- * Language directory reorganization.
- See parent makefile.
+Thu Aug 15 17:09:54 1996 Mike Stump <mrs@cygnus.com>
-Thu Apr 21 18:27:57 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * except.c (do_unwind): Mark %i7 as used on the SPARC so we can
+ optimize.
- * cp-tree.h (THUNK_DELTA): It is normally negative, so
- use signed .i variant of frame_size rather than unsigned .u.
- * cp-tree.h (VTABLE_NAME_FORMAT): If flag_vtable_thunks,
- use "VT" rather than "vt" due to binary incompatibility.
- * class.c (get_vtable_name): Use strlen of VTABLE_NAME_FORMAT,
- rather than sizeof, since it is now an expression.
- * class.c (modify_one_vtable): Modify to skip initial element
- containing a count of the vtable.
+Thu Aug 15 01:36:49 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Apr 21 00:09:02 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (import_export_decl): Ignore #pragma interface for tinfo
+ fns of classes without virtual functions.
- * lex.c (check_newline): Force interface_unknown on main input file.
+ * call.c (add_function_candidate): Handle `this' specially.
+ (compare_ics): Likewise.
- * pt.c (do_pending_expansions): Always emit functions that have been
- explicitly instantiated.
- (do_function_instantiation): Set DECL_EXPLICITLY_INSTANTIATED.
- (do_type_instantiation): Set CLASSTYPE_VTABLE_NEEDS_WRITING and
- DECL_EXPLICITLY_INSTANTIATED on all my methods.
- * parse.y (explicit_instantiation): Call do_type_instantiation for
- types.
- * decl2.c (finish_vtable_vardecl): Call import_export_vtable.
- * decl.c (start_function): Don't set DECL_EXTERNAL on a function
- that has been explicitly instantiated.
- * cp-tree.h (DECL_EXPLICITLY_INSTANTIATED): Alias for
- DECL_LANG_FLAG_4.
- * class.c: Move import_export_vtable to decl2.c, and comment out all
- uses.
-
-Wed Apr 20 16:51:06 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * lex.c (process_next_inline): Don't muck with DECL_INLINE.
- (do_pending_inlines): Ditto.
-
-Tue Apr 19 22:25:41 1994 Mike Stump <mrs@cygnus.com>
-
- Reimplement vtable building, and most vtable pointer setting.
- Allows for earier maintenance, easier understandability, and most
- importantly, correct semantics.
-
- * class.c (build_vtable): Removed unneeded
- SET_BINFO_VTABLE_PATH_MARKED.
- * class.c (prepare_fresh_vtable): Ditto. Added argument.
- * class.c (modify_vtable_entry): General cleanup.
- * class.c (related_vslot, is_normal, modify_other_vtable_entries,
- modify_vtable_entries): Removed.
- * class.c (add_virtual_function): General cleanup.
- * class.c (finish_base_struct): Setup BINFO_VTABLE and
- BINFO_VIRTUALS as early as we can, so that modify_all_vtables can
- work.
- * class.c (finish_vtbls): New routine, mostly from
- unmark_finished_struct.
- * class.c (overrides): New routine.
- * class.c (modify_one_vtable): New routine, mostly from
- modify_other_vtable_entries and modify_vtable_entries.
- * class.c (modify_all_direct_vtables, modify_all_indirect_vtables,
- modify_all_vtables): New routines.
- * class.c (finish_struct): Added arguemnt to prepare_fresh_vtable
- call. General cleanup on how pending_hard_virtuals are handled.
- General cleanup on modifying vtables. Use finish_vtbls, instead of
- unmark_finished_struct.
- * cp-tree.h (init_vtbl_ptrs, expand_direct_vtbls_init,
- get_first_matching_virtual, get_matching_virtual,
- expand_vbase_vtables_init, expand_indirect_vtbls_init): Update.
- * cvt.c (convert_pointer_to_real): cleanup error message.
- * decl.c (grokfndecl): General cleanup.
- * decl.c (finish_function): Change init_vtbl_ptrs call to
- expand_direct_vtbls_init. Change expand_vbase_vtables_init call to
- expand_indirect_vtbls_init.
- * init.c (expand_virtual_init): Remove unneeded argument.
- * init.c (init_vtbl_ptrs): Rename to expand_direct_vtbls_init, added
- two arguments to make more general. Made more general. Now can be
- used for vtable pointer initialization from virtual bases.
- * init.c (emit_base_init): Change expand_vbase_vtables_init call to
- expand_indirect_vtbls_init. Change init_vtbl_ptrs call to
- expand_direct_vtbls_init.
- * init.c (expand_virtual_init): General cleanup.
- * init.c (expand_default_init): Change expand_vbase_vtables_init
- call to expand_indirect_vtbls_init.
- * init.c (expand_recursive_init_1): Change expand_vbase_vtables_init
- call to expand_indirect_vtbls_init.
- * init.c (expand_recursive_init): Change expand_vbase_vtables_init
- call to expand_indirect_vtbls_init.
- * search.c (get_first_matching_virtual): Rename to
- get_matching_virtual. General cleanup and remove setting of
- DECL_CONTEXT. That is now done in a cleaner way in
- modify_vtable_entry and add_virtual_function.
- * search.c (expand_vbase_vtables_init): Rename to
- expand_indirect_vtbls_init. General cleanup. Use
- expand_direct_vtbls_init to do hard work. Ensures that _all_ vtable
- pointers from virtual bases are set up.
- * search.c (bfs_unmark_finished_struct, unmark_finished_struct):
- Removed.
-
- * *.[chy]: Remove support for VTABLE_USES_MASK.
-
-Tue Apr 19 12:51:59 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cvt.c (convert_to_reference): Use NOP_EXPRs to switch between
- reference and pointer types instead of bashing the types directly.
-
- * call.c (build_overload_call_real): Use the TREE_CODE to determine
- whether the function is overloaded or not, rather than
- TREE_OVERLOADED.
- * *: Remove all uses of TREE_OVERLOADED.
-
- * decl.c (grokdeclarator): Only complain about initializing const
- fields when -ansi or -pedantic.
-
-Tue Apr 19 12:42:42 1994 Doug Evans (dje@canuck.cygnus.com)
-
- * cp-tree.h (THUNK_DELTA): frame_size is now a union.
-
-Mon Apr 18 00:17:13 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- Do overloading on a block-by-block basis, not function-by-function.
- * decl.c: Lose overloads_to_forget.
- (struct binding_level): Add overloads_shadowed field.
- (poplevel): Restore overloads_shadowed.
- (push_overloaded_decl): Use overloads_shadowed instead of
- overloads_to_forget.
- (finish_function): Don't look at overloads_to_forget.
-
- Copy enum_overflow logic from c-decl.c.
- * decl.c (start_enum): Initialize enum_overflow.
- (build_enumerator): Use enum_overflow. Also use current_scope().
-
- * search.c (current_scope): Move Brendan's comment from
- build_enumerator here.
-
- * typeck.c (convert_for_assignment): Change warnings to pedwarns for
- discarding const/volatile.
-
-Sat Apr 16 01:18:21 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * typeck.c (comp_target_parms): Accept TEMPLATE_TYPE_PARMs on the rhs.
- (comp_target_types): Ditto.
-
- * decl.c (lookup_name): Don't unset got_scope here.
-
- * spew.c (yylex): Only replace yylval with the TYPE_NESTED_NAME if
- got_scope != NULL_TREE.
-
-Fri Apr 15 16:36:33 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- Horrible kludge to prevent templates from being instantiated by
- their base classes.
- * parse.y (template_instantiate_once): Unset TYPE_BEING_DEFINED
- before we get to left_curly.
- * pt.c (instantiate_class_template): Set TYPE_BEING_DEFINED.
-
- * error.c (dump_decl): If it's a typedef, print out the name of the
- decl, not just the underlying type.
-
- * decl.c (pushdecl): If the old duplicate decl was a TYPE_DECL,
- update the IDENTIFIER_TYPE_VALUE of its name.
-
- * decl2.c (finish_file): When processing the initializer for a
- static member, pretend that the dummy function is a member of the
- same class.
-
-Fri Apr 15 15:56:35 1994 Kung Hsu (kung@mexican.cygnus.com)
-
- * class.c (build_vtable_entry): revert Apr 4 change.
- * decl2.c (mark_vtable_entries): replace pure virtual function
- decl with abort's.
+Tue Aug 13 12:16:10 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Apr 15 13:49:33 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (build_conditional_expr): Fix handling of __null.
- * typeck.c (build_conditional_expr): Pedwarn on pointer/integer
- mismatch, and don't pedwarn on 0/function pointer mismatch.
+ * decl2.c (comdat_linkage): New fn.
+ (import_export_vtable): Use it.
+ (import_export_decl): Use it.
+ * method.c (make_thunk): Use it.
- * typeck2.c (digest_init): Lose code for special handling of unions.
- (process_init_constructor): Since they're handled just fine here.
- Pedwarn on excess elements.
+Mon Aug 12 00:09:18 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (grokfield): Complain about local class method declaration
- without definition.
+ * pt.c (end_template_decl): If we don't actually have parms, return.
+ * parse.y (template_header): Accept 'template <>'.
-Fri Apr 15 13:19:40 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * errfn.c: Allow 5 args.
- * method.c (emit_thunk): Add extern declaration for
- current_call_is_indirect (needed for hppa).
+Sun Aug 11 15:20:58 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Apr 14 16:12:31 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * tree.c (make_temp_vec): New fn.
+ * pt.c (push_template_decl): Handle partial specs.
+ (instantiate_class_template): Likewise.
+ (more_specialized): Use get_bindings.
+ (more_specialized_class): New fn.
+ (get_class_bindings): New fn.
+ (most_specialized_class): New fn.
+ (do_function_instantiation): List candidates for ambiguous case.
+ * decl.c (duplicate_decls): Lose reference to DECL_TEMPLATE_MEMBERS.
+ (shadow_tag): Call push_template_decl for partial specializations.
+ * parse.y: Likewise.
+ * cp-tree.h (DECL_TEMPLATE_SPECIALIZATIONS): Replaces
+ DECL_TEMPLATE_MEMBERS.
+ * call.c (print_z_candidates): Reduce duplication.
- Improve local class support; allow classes in different blocks to
- have the same name.
- * decl.c (pushtag): Support local classes better.
- (pushdecl_nonclass_level): New function for pushing mangled decls of
- nested types into the appropriate scope.
- (xref_defn_tag): Use pushdecl_nonclass_level instead of
- pushdecl_top_level.
- (grokfndecl): Don't mess with IDENTIFIER_GLOBAL_VALUE for local
- class methods.
- * method.c (do_inline_function_hair): Ditto.
+Fri Aug 9 14:36:08 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): It is legal for a class with no
- constructors to have nonstatic const and reference members.
+ * decl2.c (lang_decode_option): Allow -fansi-overloading.
-Thu Apr 14 07:15:11 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+Thu Aug 8 17:04:18 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (push_overloaded_decl): Avoid giving errors about
- built-ins, since duplicate_decls will have given warnings/errors
- for them.
+ * pt.c (get_bindings): New fn.
+ (most_specialized): Likewise.
+ (do_function_instantiation): Use them.
+ (add_maybe_template): New fn.
+ * cp-tree.h (DECL_MAYBE_TEMPLATE): New macro.
+ * call.c (build_new_op): Handle guiding decls.
+ (build_new_function_call): Likewise.
+ * decl2.c (finish_file): Likewise.
-Thu Apr 14 03:45:12 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (mark_used): Do synthesis here.
+ * call.c (build_method_call): Not here.
+ (build_over_call): Or here.
+ * typeck.c (build_function_call_real): Or here.
+ * tree.c (bot_manip): Call mark_used on functions used in default
+ args.
- * cvt.c (convert_to_reference): Warn about casting pointer type to
- reference type when this is probably not what they wanted.
+Thu Aug 8 17:48:16 1996 Michael Meissner <meissner@tiktok.cygnus.com>
-Wed Apr 13 13:12:35 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * decl2.c (import_export_vtable): Delete code that disabled vtable
+ heuristic on systems with ASM_OUTPUT_EXTERNAL.
- * decl.c (finish_decl): Don't mindlessly set TREE_USED for
- static consts any more (toplev.c has now been modified to
- not emit warnings if they are unused).
+Wed Aug 7 12:44:11 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Apr 13 00:22:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (build_x_function_call): Handle static call context
+ better.
- * decl.c (grok_op_properties): If op new/delete get here with
- METHOD_TYPEs, do a revert_static_member_fn.
+ * decl.c (finish_function): Set the DECL_CONTEXT of the result to
+ the function, not its outer block.
- * cp-tree.h (IDENTIFIER_CLASS_TYPE_VALUE): Lose.
- * init.c (is_aggr_typedef): Don't look at
- IDENTIFIER_CLASS_TYPE_VALUE.
- (get_aggr_from_typedef): Ditto.
- (get_type_value): Ditto.
- * call.c (build_scoped_method_call): Don't rely on overloaded
- template names having IDENTIFIER_CLASS_VALUE set.
+ * call.c (build_field_call): Pass fields on to build_opfncall
+ regardless of TYPE_OVERLOADS_CALL_EXPR.
+ (build_method_call): Pass on to build_new_method_call sooner.
- * parse.y (component_decl_1, fn.def2): Revert rules for
- constructors.
- (component_decl_1, fn.def2): Use $1 instead of $$, since $$ is being
- clobbered.
+ * typeck.c (build_ptrmemfunc): Just return what instantiate_type
+ gives us.
+ * class.c (instantiate_type): Don't put a POINTER_TYPE to
+ METHOD_TYPE on an expression. Also make a copy of rhs instead of
+ modifying it.
- * decl.c (start_function): Only warn about `void main()' if pedantic
- || warn_return_type.
+Tue Aug 6 12:58:46 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue Apr 12 02:14:17 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (compare_ics): Handle qual_conv after lvalue_conv.
+ (add_builtin_candidate): Don't take enums for ++.
+ (build_new_method_call): Handle non-aggregates and field calls.
+ Move new overloading code from...
+ * cvt.c: Here.
- Clean up overloading of the template name.
- * class.c (pushclass): overload the template name whenever pushing
- into the scope of a template class, not just if it is
- uninstantiated.
- (popclass): Correspondingly.
- * search.c (push_class_decls): Don't overload_template_name.
- * pt.c (overload_template_name): Don't set IDENTIFIER_LOCAL_VALUE or
- DECL_CONTEXT on things.
- * parse.y (left_curly): Don't overload_template_name.
- * class.c (finish_struct): Don't undo_template_name_overload.
+ * decl.c (grokparms): Don't check default args in templates.
- * method.c (build_opfncall): Only pass one argument to global op
- delete.
+Mon Aug 5 17:17:06 1996 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Use TYPE_VEC_DELETE_TAKES_SIZE to
- decide how many arguments to use for vec delete.
+ * cvt.c (build_new_op): Fix args to build_unary_op.
+ (add_builtin_candidates): Don't call type_promotes_to on float.
- * decl.c (grok_op_properties): Be consistent in modifying
- current_class_type.
- (grokdeclarator): Only complain about function decls with no return
- type if we're being pedantic.
-
-Mon Apr 11 00:10:53 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- Add support for operator new [] and operator delete [].
-
- * tree.def: Add VEC_NEW_EXPR and VEC_DELETE_EXPR.
- * ptree.c (print_lang_type): Indicate vec new/delete.
- * parse.y: Support vec new/delete.
- * method.c (build_decl_overload): Deal with vec new/delete.
- (build_opfncall): Ditto.
- * lex.c (init_lex): Set up values of ansi_opname and opname_tab for
- vec new/delete. vec new uses "__vn", and vec delete uses "__vd".
- * init.c (init_init_processing): Set up BIVN and BIVD.
- (do_friend): Don't clean up after mistaken setting of TREE_GETS_NEW,
- since it doesn't happen any more.
- (build_new): Support vec new. Always call something.
- (build_x_delete): Support vec delete.
- (build_vec_delete): Lose dtor_dummy argument, add use_global_delete,
- and pass it to build_x_delete.
- * decl2.c (delete_sanity): Don't change behavior by whether or not
- the type has a destructor. Pass use_global_delete to
- build_vec_delete.
- (coerce_delete_type): Make sure that the type returned has a first
- argument of ptr_type_node.
- * decl.c (init_decl_processing): Also declare the global vec
- new/delete.
- (grokdeclarator): Also force vec new/delete to be static.
- (grok_op_properties): Note presence of vec new/delete, and play with
- their args. If vec delete takes the optional size_t argument, set
- TYPE_VEC_DELETE_TAKES_SIZE.
- * cp-tree.h (TYPE_GETS_{REG,VEC}_DELETE): New macros to simplify
- checking for one delete or the other.
- (lang_type): gets_new and gets_delete are now two bits long. The
- low bit is for the non-array version. Lose gets_placed_new.
- (TYPE_VEC_DELETE_TAKES_SIZE): New macro indicating that the vec
- delete defined by this class wants to know how much space it is
- deleting.
- (TYPE_VEC_NEW_USES_COOKIE): New macro to indicate when vec new must
- add a header containing the number of elements in the vector; i.e.
- when the elements need to be destroyed or vec delete wants to know
- the size.
- * class.c (finish_struct_methods): Also check for overloading vec
- delete.
- * call.c (build_method_call): Also delete second argument for vec
- delete.
+ * decl.c (grokparms): Check the type of the default arg.
- * decl.c (grokdeclarator): Correct complaints again.
- (grokdeclarator): Fix segfault on null declarator.
- (decls_match): Also accept redeclaration with no arguments if both
- declarations were in C context. Bash TREE_TYPE (newdecl) here.
- (duplicate_decls): Instead of here.
+ * cvt.c (build_new_op): Pass non-overloaded cases on rather than
+ returning NULL_TREE.
- * parse.y (nested_name_specifier_1): Lose rules for dealing with
- syntax errors nicely, since they break parsing of 'const i;'.
+ * typeck.c (build_x_binary_op): Avoid doing extra work.
+ (build_x_unary_op): Likewise.
+ (build_x_conditional_expr): Likewise.
+ * cvt.c (build_over_call): Return.
+ (add_builtin_candidate): Fix MEMBER_REF.
+ (build_new_op): Likewise.
- * decl.c (lookup_name): if (got_scope == current_class_type)
- val = IDENTIFIER_CLASS_VALUE (name).
+Mon Aug 5 17:07:47 1996 Mike Stump <mrs@cygnus.com>
- * search.c (lookup_nested_tag): Look in enclosing classes, too.
+ * method.c (build_overload_name): Put bug fix into code but leave
+ disabled for now so we can be bug compatible with older releases
+ that do repeats incorrectly. In the future, we can enable it.
- * spew.c (yylex): Only look one character ahead when checking for a
- SCOPE.
+Mon Aug 5 13:46:28 1996 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (check_newline): Read first nonwhite char before
- incrementing lineno.
+ * cvt.c (convert_like): Don't call build_cplus_new twice.
- * decl.c (grokdeclarator): Don't claim that typedefs are variables
- in warning.
+ * call.c, cp-tree.h, cvt.c, decl2.c, init.c, method.c, pt.c, typeck.c:
+ Control new overloading code with -fansi-overloading.
- * parse.y: Divide up uses of unqualified_id into
- notype_unqualified_id and unqualified_id, so that TYPENAME can be
- used as an identifier after an object.
+Sun Aug 4 15:29:11 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (push_nested_class): Don't push into non-class scope.
+ * cvt.c (build_over_call): Call build_cplus_new.
+ * call.c (build_method_call): Likewise.
+ * typeck.c (build_function_call_real): Likewise.
+ (build_conditional_expr): If both operands are TARGET_EXPRs, wrap
+ the COND_EXPR in a TARGET_EXPR so they use the same slot.
- * decl.c (grokdeclarator): If an identifier could be a type
- conversion operator, but has no associated type, it's not a type
- conversion operator.
+ * cvt.c (build_up_reference): Propagate INDIRECT_BIND to
+ recursive calls.
+ * typeck.c (complete_type): Propagate
+ TYPE_NEEDS_{CONSTRUCTING,DESTRUCTOR}.
- * pt.c (unify): Check for equality of constants better.
+Sat Aug 3 14:05:07 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Don't complain about access decls.
+ * cvt.c (joust): More ?: kludging. Sigh.
+ (build_over_call): Don't try to synthesize global fns.
-Sun Apr 10 02:39:55 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * search.c (lookup_conversions): Use binfo marking.
- * decl.c (grokdeclarator): pedwarn about data definitions without
- types here.
+Sat Aug 3 12:33:42 1996 Bob Manson <manson@charmed.cygnus.com>
- * parse.y (datadef): Don't pedwarn about decls without types here,
- since that is valid for functions.
- (fn.def2, component_decl): Support constructors with declmods again.
- (nomods_initdecls): For decls without any mods, so that we don't try
- to get declspecs from some arbitrary $0.
+ * search.c (build_mi_matrix): Use the correct value of cid
+ when determining the new mi_size.
- * search.c (lookup_field): Use cp_error.
+Sat Aug 3 01:27:41 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (nested_name_specifier_1): Don't check aggr/non-aggr type
- here; it breaks destructors for non-aggr types.
+ * cvt.c (add_builtin_candidates): Do consider type conversion ops
+ for the first parms of += et al.
+ (strip_top_quals): New fn.
+ (reference_binding): Use it instead of TYPE_MAIN_VARIANT.
+ (implicit_conversion): Likewise.
+ (add_builtin_candidates): Be careful about arrays.
+ (build_new_method_call): Handle vtable optimization.
- * decl.c (lookup_name): Only look for TYPE_DECLs in base classes of
- a type being defined, like the comment says.
- If got_scope is not an aggregate, just return NULL_TREE.
+Fri Aug 2 01:26:59 1996 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (create_nested_upt): Kung's code for creating types nested
- within uninstantiated templates now lives here (it used to live in
- hack_more_ids). It needs to be expanded.
+ * cp-tree.h (LOOKUP_NO_TEMP_BIND): New flag.
+ * cvt.c (reference_binding): Use it.
+ (implicit_conversion): Use it.
+ (add_builtin_candidate, COND_EXPR): Use it.
- * parse.y: Stop calling see_typename so much.
+ * cvt.c (build_new_function_call): Check for error args.
- * decl.c (lookup_name): Deal with TTPs and UPTs.
+ * typeck.c (comptypes): Just check DERIVED_FROM_P, not UNIQUELY.
- * lex.c (real_yylex): Don't set looking_for_typename just because we
- saw a 'new'.
- (dont_see_typename): #if 0 out.
+ * gxx.gperf: Add __null.
+ * hash.h: Regenerate.
+ * lex.h: Add RID_NULL.
+ * lex.c (init_lex): Create null_pointer_node here, stick it in
+ RID_NULL.
+ * decl.c (init_decl_processing): Still set its type here.
+ * cvt.c (cp_convert_to_pointer): Don't produce null_pointer_node.
+ (convert_to_pointer_force): Likewise.
+ (null_ptr_cst_p): Check for null_pointer_node; only accept (void*)0
+ if (! pedantic).
+ * call.c (convert_harshness): Use null_ptr_cst_p.
+ * typeck.c (convert_for_assignment): Likewise. Don't produce
+ null_pointer_node.
- * spew.c (yylex): Increment looking_for_typename if the next
- character is SCOPE, rather than setting it to 1; this way, the value
- from seeing an aggr specifier will not be lost. This kinda relies
- on looking_for_typename never being < 0, which is now true.
+ * error.c (args_as_string): Handle lists of actual args, too.
+ * cvt.c (null_ptr_cst): Support (void*)0 for now.
+ (build_user_type_conversion_1): Improve diagnostics.
+ (build_new_function_call): Likewise.
+ (build_object_call): Likewise.
+ (build_new_method_call): Likewise. Move call before def diagnostic...
+ (build_over_call): Here.
- * parse.y (nested_name_specifier_1): Accept TEMPLATE_TYPE_PARMs,
- too.
- (named_class_head_sans_basetype): Accept template types, too. Oops.
+ * cvt.c (build_new_method_call): Don't complain about no match if
+ LOOKUP_SPECULATIVELY.
+ (build_over_call): Fix 'this' for virtual fn.
+ (build_new_method_call): Add diagnostic.
-Fri Apr 8 16:39:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Aug 1 16:45:09 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (reparse_decl_as_expr1): Handle SCOPE_REFs.
+ * cvt.c (add_function_candidate): Expect 'this' and 'in_chrg' for
+ constructors to be passed in.
+ (build_over_call): Likewise.
+ (build_user_type_conversion_1): Pass them in.
+ (convert_like): Likewise.
+ (build_object_call): Handle overloaded conversions.
+ (build_over_call): Pass the right args to build_vfn_ref.
+ (standard_conversion): Fix pmf convs.
+ (joust): Handle comparing statics and non-statics.
+ (build_new_method_call): New fn.
+ * call.c (build_method_call): Call it if NEW_OVER.
- * parse.y: Lose START_DECLARATOR.
+Thu Aug 1 16:06:14 1996 Mike Stump <mrs@cygnus.com>
- * search.c (lookup_nested_tag): New function to scan CLASSTYPE_TAGS
- for a class.
+ * lex.c (do_identifier): Don't use %O on IDENTIFIER_OPNAME_Ps, use
+ %D instead.
- * parse.y: Simplify fn.def2 and component_decl. Support 'enum
- A::foo' syntax. Catch invalid scopes better.
+Thu Aug 1 15:24:02 1996 Mike Stump <mrs@cygnus.com>
- * parse.y, lex.c: lose TYPENAME_COLON.
+ * except.c (expand_throw): Use maybe_build_cleanup_and_delete
+ instead of just maybe_build_cleanup so that we deallocate the
+ thrown object.
- * decl2.c (groktypefield): #if 0 out.
+Thu Aug 1 15:18:00 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (lookup_name): If the type denoted by got_scope is
- currently being defined, look in CLASSTYPE_TAGS rather than FIELDS.
+ * decl2.c (finish_prevtable_vardecl): Make non-static for pt.c's use.
+ * cp-tree.h (finish_prevtable_vardecl): Add decl.
- * class.c (push_nested_class): Don't try to push into
- error_mark_node.
+Thu Aug 1 11:53:51 1996 Bob Manson <manson@charmed.cygnus.com>
-Fri Apr 8 07:26:36 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * pt.c (instantiate_class_template): Call complete_type. Also, if
+ we're at the end of the file and we just instantiated a template
+ class with a vtable, call finish_prevtable_vardecl.
- * Makefile.in (stamp-parse): Update count of conflicts to 33.
+ * error.c (dump_decl): Don't explode (or explode more gracefully
+ as appropriate) if the object being dumped has a null type.
+ (dump_expr): Likewise.
-Thu Apr 7 17:47:53 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * search.c (build_mi_matrix): Ensure that mi_size is large enough,
+ by counting the number of nodes that we'll need before allocating
+ the array.
+ (lookup_fnfields): Fix comment.
+ (breadth_first_search): Fix comment.
- A saner implementation of nested types that treats template types
- no differently from non-template types. There are still some
- shortcomings of our system; most notably, it is difficult to look
- for a nested type that is hidden by another name, because of the way
- we keep track of hidden types. But this shouldn't be a problem for
- just about anyone. Perhaps lookup_field should be fixed up a bit.
+Wed Jul 31 09:57:05 1996 Jason Merrill <jason@yorick.cygnus.com>
- * spew.c: Moved handling of nested types/scoping from the lexer
- into the parser. Removed variable template_type_seen_before_scope.
- Removed functions frob_identifier, hack_more_ids, and various cruft
- that was #if 0'd out in the past, reducing the size of the file from
- 1146 lines to 450 lines. We can't quite do away with spew.c yet,
- though; we still need it for do_aggr () and checking for SCOPE after
- the current identifier. And setting lastiddecl.
+ * pt.c (instantiate_class_template): Propagate TYPE_PACKED and
+ TYPE_ALIGN.
+ * class.c (finish_struct): Call cplus_decl_attributes here.
+ (finish_struct_1): Not here.
+ * cp-tree.h: Adjust.
- * parse.y: Moved handling of nested types/scoping from the lexer
- into the parser, using a new global variable `got_scope'. Reduced
- the number of states by 53. Implemented all uses of explicit global
- scope. Removed terminals SCOPED_TYPENAME and SCOPED_NAME. Removed
- nonterminals tmpl.1, scoped_base_class, id_scope, typename_scope,
- scoped_typename. Added nonterminals nested_type,
- qualified_type_name, complete_type_name, qualified_id, ptr_to_mem,
- nested_name_specifier, global_scope, overqualified_id, type_name.
- Changed many others. Added 9 new reduce/reduce conflicts, which are
- nested type parallels of 9 that were already in the grammar for
- non-nested types. Eight of the now 33 conflicts should be removed
- in the process of resolving the late binding between variable and
- function decls.
+ * pt.c (type_unification): New parameter STRICT.
+ (unify): If STRICT, don't allow cv addition or base deduction.
+ * call.c, class.c, cvt.c, cp-tree.h: Adjust.
- * gxxint.texi (Parser): Update.
+Tue Jul 30 13:06:13 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-tree.h (IS_AGGR_TYPE_CODE): Add UNINSTANTIATED_P_TYPE.
+ * search.c (get_template_base{_recursive}): New fns.
+ * pt.c (more_specialized): New fn.
+ (do_function_instantiation): Use it.
+ (unify): Handle base deduction.
+ * cvt.c (joust): Use more_specialized.
+ Don't arbitrarily choose between non-builtin candidates.
+ (build_over_call): Call require_complete_type.
- * lex.h: Add decl for got_scope.
+ * decl.c (start_function): Statics are static even in a #pragma
+ interface file.
- * lex.c (see_typename): Claim to be the lexer when calling
- lookup_name.
+ * decl2.c (import_export_vtable): Disable vtable heuristic on
+ systems with ASM_OUTPUT_EXTERNAL.
- * decl.c (lookup_name): When called from the lexer, look at
- got_scope and looking_at_typename; otherwise don't.
+ * cvt.c (compare_ics): Fix comparison of PMEM_CONV and BASE_CONV.
+ (standard_conversion): No std conv to enum type.
-Thu Apr 7 22:05:47 1994 Mike Stump <mrs@cygnus.com>
+ * cvt.c (standard_conversion): Fix order of args to DERIVED_FROM_P
+ for ptm's.
- 31th Cygnus<->FSF merge.
+ * cvt.c (reference_binding): Bind directly to a base subobject of
+ a class rvalue.
-Thu Apr 7 17:47:53 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cvt.c (build_new_op): Enforce access control.
- * decl2.c (mark_vtable_entries): Call this to mark all the
- entries in the vtable addressable.
- (finish_decl_parsing): Handle SCOPE_REFs.
+Tue Jul 30 09:22:53 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (decls_match): Always call compparms with strict == 1.
- Handle the special case of C function redecl here.
- (duplicate_decls): Only keep the old type if the new decl takes no
- arguments.
+ * typeck2.c (process_init_constructor): When scanning the
+ union for a named field, skip things that aren't FIELD_DECLs.
- * typeck.c (compparms): Also allow t1 to be ... if strict == 0.
+ * method.c (synthesize_method): Don't scan fndecl's rtl if
+ we're at the end of the file; just assume the function can't
+ be inlined.
-Thu Apr 7 16:17:50 1994 Mike Stump <mrs@cygnus.com>
+Mon Jul 29 15:48:30 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (build_vtable_entry): Fix breakage introduced Apr 5
- 17:48:41.
+ * cvt.c (build_builtin_candidate): Stick a dummy conversion in if
+ it failed.
-Wed Apr 6 16:05:10 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * cvt.c (build_user_type_conversion_1): Handle overloaded
+ conversion ops.
- * init.c (build_virtual_init), search.c (build_vbase_vtables_init),
- ch-tree.h: Every place these functions were called, the result was
- immediately passed to expand_expr_stmt. Reduce redundancy by
- calling expand_expr_init *inside* these functions. These
- makes for a simpler interface, and we don't have to build
- compound expressions. Hence, rename these function to:
- expand_virtual_init and expand_vbase_vtables_init respectively.
- * init.c, decl.c: Change callers of these functions.
- * init.c, cp-tree.h (expand_virtual_init): Make static.
+ * cvt.c (add_builtin_candidates): Don't consider type conversion
+ operators for the first parameter of operator=.
- * decl2.c (finish_file): Check TREE_PUBLIC||TREE_ADDRESSABLE
- rather than DECL_SAVED_INSNS before emitting inlines.
+Mon Jul 29 15:33:55 1996 Bob Manson <manson@charmed.cygnus.com>
-Wed Apr 6 13:06:39 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (complete_type): Only call layout_type if we're not
+ expanding a template.
- * spew.c (init_spew): #if 0 out stuff used by arbitrate_lookup.
+Mon Jul 29 14:40:38 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (duplicate_decls): If this is a new declaration of an
- extern "C" function, keep the type (for the argtypes).
- (redeclaration_error_message): Don't check DECL_LANGUAGE here.
- (decls_match): Call compparms with a value of strict dependent on
- the value of strict_prototypes for DECL_LANGUAGE (oldecl).
+ * cvt.c (compare_ics): Oops.
- * typeck.c (compparms): ... is only equivalent to non-promoting
- parms if we're not being strict.
+ * cvt.c (op_error): Oops.
- * parse.y (empty_parms): Don't check flag_ansi || pedantic here.
+ * cp-tree.def: Add RVALUE_CONV, rename EXACT_CONV to IDENTITY_CONV.
+ * cvt.c: Add IDENTITY_RANK before others. Use real_lvalue_p.
+ (build_conv): Use them.
+ (implicit_conversion): Use them.
+ (convert_like): Handle them.
+ (build_new_op): Handle builtin COND_EXPR again.
+ (add_builtin_candidates): Strip cv-quals. Fix oops. Include enums
+ in lists of types for COND_EXPR.
+ (add_builtin_candidate): Add enum candidates for COND_EXPR.
- * decl.c (init_decl_processing): if (flag_ansi || pedantic)
- strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
+Mon Jul 29 12:05:40 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl2.c (grok_function_init): Don't set DECL_INITIAL on pure
- virtuals.
+ * typeck.c (build_modify_expr): Always attempt to build a call to
+ the assignment operator, even if we're using a default one.
+ (convert_for_initialization): Call complete_type.
-Tue Apr 5 17:48:41 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Mon Jul 29 11:25:08 1996 Jason Merrill <jason@yorick.cygnus.com>
- Support for implementing vtables with thunks.
- * tree.def (THUNK_DECL): New TREE_CODE.
- * cp-tree.h (FNADDR_FROM_VTABLE_ENTRY), tree.c
- (fnaddr_from_vtable_entry): Handle flag_vtable_thunks case.
- * cp-tree.h (memptr_type): New variable.
- * class.c (build_vtable_entry): Build thunk if necessary.
- * class.c (build_vfn_ref): If using thunks, don't need
- to add delta field from vtable (there is none!).
- * decl.c: Add memptr_type as well as vtable_entry_type.
- If using thunks, the latter is just ptr_type_node.
- * gc.c, typeck.c: Use memptr_typeChange, not vtable_entry_type.
- * decl2.c (finish_vtable_vardecl): Handle thunks.
- * expr.c (cplus_expand_expr): Support THUNK_DECL.
+ * cvt.c (reference_binding): A REF_BIND gets the reference type.
+ (implicit_conversion): Likewise.
+ (convert_like): Likewise.
+ (compare_ics): Likewise.
+ (compare_qual): Likewise.
+ (print_z_candidates): Handle no candidates.
+ (build_new_op): Don't handle builtin COND_EXPR for now.
- * decl.c (grokdeclarator): Set DECL_THIS_EXTERN if "extern".
- * decl.c (start_function): Set current_extern_inline based on
- DECL_THIS_EXTERN, not TREE_PUBLIC.
- * decl.c (finish_function): Call mark_inline_for_output if needed,
+Sat Jul 27 11:27:47 1996 Stan Shebs <shebs@andros.cygnus.com>
- Improve intelligence about when to emit inlines.
- * cp-tree.h (lang_decl_flags): New field saved_inline.
- * cp-tree.h (DECL_SAVED_INLINE): New macro.
- * class.c (add_virtual_function): Don't set TREE_ADDRESSABLE.
- * decl.h, decl.c (pending_addressable_inlines): Removed.
- * decl2.c (pending_addressable_inlines): Renamed to saved_inlines.
- * decl2.c (mark_inline_for_output): Do nothing if
- DECL_SAVED_INLINE; otherwise set it (and add to saved_inlines list).
- * decl2.c (finish_vtable_vardecl): SET_CLASSTYPE_INTERFACE_KNOWN
- and set CLASSTYPE_INTERFACE_ONLY if there is a non-inline virtual.
- * decl2.c (finish_file): Writing out inlines later, so we can
- also handle the ones needed for vtbales.
- * decl2.c (write_vtable_entries, finish_vtable_typedecl): Removed.
+ * cvt.c (build_builtin_candidate): Init local var in an ANSI way.
- * cp-tree.h, class.c, decl2.c, search.c: Remove -fvtable-hack
- and flag_vtable_hack. Use -fvtable-thunks and flag_vtable_thunks
- instead. (The rationale is that these optimizations both break binary
- compatibility, but should become the default in a future release.)
+Fri Jul 26 01:07:22 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Apr 6 10:53:56 1994 Mike Stump <mrs@cygnus.com>
+ * cvt.c (joust): If the candidates are the same, arbitrarily pick one.
- * class.c (modify_vtable_entries): Never reset the DECL_CONTEXT
- of a fndecl, as we might not be from that vfield.
+ * cvt.c (build_builtin_candidate): Oops.
+ (build_new_op): Oops.
-Tue Apr 5 17:43:35 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * method.c (build_opfncall): Pass COND_EXPR on.
+ * cvt.c (build_builtin_candidate): Reorganize, support COND_EXPR.
+ (add_builtin_candidate{,s}): Likewise.
+ (add_builtin_candidates): Likewise.
+ (print_z_candidates, op_error, build_new_op): Likewise.
+ (type_decays_to): New fn.
+ * lex.c (init_lex): Just say ?: for COND_EXPR.
- * class.c (add_virtual_function): fix bug for pure virtual, so
- that DECL_VINDEX of the dummy decl copied won't be error.
- (see also Apr 4 change)
+Thu Jul 25 09:33:33 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue Apr 5 17:23:45 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * typeck.c (complete_type): Call layout_type rather than building
+ a new array type.
- * typeck.c (c_expand_return): Before checking that we're not
- returning the address of a local, make sure it's a VAR_DECL.
- (And don't worry about it being a TREE_LIST.)
+ * cvt.c (add_builtin_candidate): Pointer arithmetic candidates
+ only use ptrdiff_t.
-Tue Apr 5 13:26:42 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Jul 24 12:45:08 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (YYDEBUG): Always define.
- * lex.c (YYDEBUG): Ditto.
+ * cvt.c: Always compile the new overloading code (but don't use it).
+ (implicit_conversion): Add a BASE_CONV when converting to
+ the same class type.
+ (convert_like): Handle BASE_CONV.
-Mon Apr 4 11:28:17 1994 Kung Hsu (kung@mexican.cygnus.com)
+Tue Jul 23 12:46:30 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): backup out the change below, put the
- new change for the same purpose. The change below breaks code.
+ * cvt.c (build_new_op): Support {MAX,MIN}_EXPR.
+ (add_builtin_candidate): Likewise.
- * class.c (finish_struct): if pure virtual, copy node and make
- RTL point to abort, then put in virtual table.
- * decl2.c (grok_function_iit): reinstate Mar 31 change.
-
-Sat Apr 2 03:12:58 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * init.c (build_new): pedwarn about newing const and volatile
- types.
-
- * tree.c (get_identifier_list): Only do the special handling
- thing if we're dealing with the main variant of the record type.
-
- * cvt.c (convert_to_reference): When converting between
- compatible reference types, use the pointer conversion machinery.
- Don't just blindly overwrite the old type.
-
-Fri Apr 1 17:14:42 1994 Jason Merrill (jason@deneb.cygnus.com)
+ NEW_OVER changes:
+ * typeck.c (build_x_function_call): Try an operator function
+ whenever we call an object of class type.
+ * method.c (build_opfncall): Pass CALL_EXPRs through.
+ * cvt.c (implicit_conversion): Do const-ref case first.
+ (add_conv_candidate, build_object_call, op_error): New fns.
+ (ptr_complete_ob, TYPE_PTROB_P): void is not an object type.
+ ({add,build}_builtin_candidate{,s}, print_z_candidates): Display
+ builtin candidates.
+ (build_new_op): Handle CALL_EXPR. Don't try to decay void.
+ Fall back on preincrement handling. Use op_error.
+ Handle warn_synth.
+ (convert_like): Pass INDIRECT_BIND. Don't try to do anything with
+ an error_mark_node.
+ (build_over_call): Handle PROMOTE_PROTOTYPES and ellipsis promotions
+ properly.
- * call.c (build_method_call): When looking at global functions,
- be sure to use instance_ptr for the first argument, not some version
- of it that has been cast to a base class. Also do this before
- comparing candidates.
+Mon Jul 22 16:21:55 1996 Bob Manson <manson@charmed.cygnus.com>
-Thu Mar 31 19:50:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (tsubst_expr): Handle CONTINUE_STMT.
- * call.c (build_method_call): Constructors can be called for
- const objects.
+Mon Jul 22 15:38:58 1996 Mike Stump <mrs@cygnus.com>
-Thu Mar 31 16:20:16 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * typeck.c (build_component_ref_1): Use build_component_ref
+ instead of open coding it here.
- * decl2.c (grok_func_init): do not abort as rtl for pur virtual
- fucntions. They can be defined somewhere else.
+Mon Jul 22 12:18:54 1996 Jason Merrill <jason@yorick.cygnus.com>
-Sat Jan 23 23:23:26 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de)
+ * g++.c (main): Don't link with -lg++.
- * decl.c (init_decl_processing): Declare __builtin_return_address
- and __builtin_frame_address for C++ as well.
+ NEW_OVER changes:
+ * cvt.c (convert_to_reference): Don't use convert_from_refeence on
+ result of build_type_conversion.
+ (cp_convert): Only call build_method_call for ctors if
+ build_type_conversion failed.
+ (ptr_complete_ob): New function.
+ (TYPE_PTR{,OB,MEM}_P): New macros.
+ ({add,build}_builtin_candidate{,s}): New functions.
+ (print_z_candidates): Handle builtins.
+ (build_user_type_conversion_1): Don't use conversion fns for
+ converting to a base type.
+ (build_user_type_conversion_1): Set ICS_USER_FLAG on AMBIG_CONVs.
+ (build_user_type_conversion): Use convert_from_reference.
+ (build_new_op): New function.
+ (build_over_call): Fix handling of methods.
+ (compare_ics): Handle AMBIG_CONV properly.
+ * typeck2.c: Increment abort count.
+ * method.c (build_opfncall): Forward most requests to build_new_op.
+ * cp-tree.h (IS_OVERLOAD_TYPE): Tweak.
-Thu Mar 31 12:35:49 1994 Mike Stump <mrs@cygnus.com>
+Fri Jul 19 17:59:29 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck2.c (store_init_value): Integral constant variables are
- always constant, even when doing -fpic.
+ * error.c (dump_expr, case CONSTRUCTOR, case CAST_EXPR): Take out
+ invalid second argument to dump_expr_list.
-Sat Jan 23 23:23:26 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de)
+Fri Jul 19 14:04:05 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (redeclaration_error_message): Pass the types to
- comptypes.
+ * decl.c (lookup_name_real): Make sure we do obj->X::i correctly.
-Wed Mar 30 21:29:25 1994 Mike Stump <mrs@cygnus.com>
+Thu Jul 18 14:48:23 1996 Bob Manson <manson@charmed.cygnus.com>
- Cures incorrect errors about pure virtuals in a class, when they
- have been overridden in a derived class.
+ * decl2.c (import_export_vtable): ASM_OUTPUT_EXTERNAL, not
+ ASSEMBLE_EXTERNAL.
- * search.c (get_abstract_virtuals): Reimplement.
- * search.c (get_abstract_virtuals_1): New routine.
+Mon Jul 15 17:48:43 1996 Mike Stump <mrs@cygnus.com>
-Wed Mar 30 14:10:04 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck2.c (process_init_constructor): New pedwarn for using { }
+ to initialize a pointer to member function.
+ * typeck.c (build_ptrmemfunc1): Avoid use of digest_init so that
+ we can avoid the new error.
- * pt.c (push_template_decls): Make the pushed level pseudo
- global.
+Mon Jul 15 15:42:03 1996 Mike Stump <mrs@cygnus.com>
- * parse.y (extdefs): Don't pop everything if the current binding
- level is pseudo_global.
+ * typeck.c (build_ptrmemfunc1): New function to hide details of
+ pointer to member functions better.
- * decl.c (pop_everything): Stop on reaching a pseudo-global
- binding level.
+Mon Jul 15 14:23:02 1996 Mike Stump <mrs@cygnus.com>
- * cp-tree.h (DECL_FUNCTION_MEMBER_P): Change to more reliable test.
+ * init.c (resolve_offset_ref): Resolve OFFSET_REFs that are
+ methods into the actual method, as we know the implied object is
+ not used.
- * decl.c (duplicate_decls): Only copy DECL_SOURCE_{FILE_LINE} if
- the old decl actually had an initializer.
+Mon Jul 15 13:08:29 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * {various}: Clean up gcc -W complaints.
+ * parse.y (maybecomma_warn): Only emit the pedwarn if we're not
+ inside a system header.
- * cp-tree.h (DECL_FUNCTION_MEMBER_P): Currently defined to be
- (DECL_CONTEXT (NODE) != NULL_TREE).
+Fri Jul 12 16:30:05 1996 Bob Manson <manson@charmed.cygnus.com>
- * parse.y (lang_extdef): Call pop_everything if necessary.
+ * call.c (build_method_call): Call complete_type on the
+ instance type.
- * decl.c (pop_everything): New function for popping binding
- levels left over after a syntax error.
- (pushdecl): Use DECL_FUNCTION_MEMBER_P to decide whether or not
- a function is a member.
+Thu Jul 11 17:16:40 1996 Mike Stump <mrs@cygnus.com>
-Wed Mar 30 14:20:50 1994 Mike Stump <mrs@cygnus.com>
+ * typeck.c (build_component_ref): Always build up an OFFSET_REF
+ for obj_ptr->func so that we can know which object to use in a
+ method call.
- Cures calling a more base base class function, when a more derived
- base class member should be called in some MI situations.
+Wed Jul 10 19:36:37 1996 Mike Stump <mrs@cygnus.com>
- * search.c (make_binfo): Use more the more specialized base
- binfos from the binfo given as the second argument to make_binfo,
- instead of the unspecialized ones from the TYPE_BINFO.
- * class.c (finish_base_struct): Ditto, update callers.
- * search.c (dfs_get_vbase_types): Ditto.
- * tree.c (propagate_binfo_offsets, layout_vbasetypes): Ditto.
- * decl.c (xref_tag): Use NULL_TREE instead of 0.
- * lex.c (make_lang_type): Ditto.
+ * typeck.c (build_ptrmemfunc): Remove sorry, now we can cast
+ around things. Also improve maintainability.
-Wed Mar 30 14:10:04 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Jul 10 18:20:11 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (pushdecl): If pushing a C-linkage function, only do a
- push_overloaded_decl.
- (duplicate_decls): Standard overloading does not shadow built-ins.
+ * decl.c (grokdeclarator): Check for overflow when evaluating an
+ array dimension.
-Tue Mar 29 00:54:18 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Jul 10 17:26:19 1996 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (end_template_decl): Don't call push_overloaded_decl.
+ * cvt.c (cp_convert): Don't check for ambiguity with constructor
+ if NEW_OVER.
- * init.c (do_friend): Don't call push_overloaded_decl.
+ * typeck.c (build_x_function_call): Pass function overload
+ questions to new overloading code if NEW_OVER.
+ * init.c (expand_aggr_init_1): Only check for type conversion ops
+ if we're doing copy-initialization (i.e. LOOKUP_ONLYCONVERTING).
+ Don't check for ambiguity with constructor if NEW_OVER.
+ * cvt.c (convert_to_reference): Dereference the result of a type
+ conversion operator.
+ (build_conv): Propagate ICS_USER_FLAG.
+ (implicit_conversion): Call instantiate_type.
+ Pass LOOKUP_ONLYCONVERTING instead of LOOKUP_NORMAL.
+ (add_function_candidate): Fix cv-quals on argtype.
+ (print_z_candidates): New function.
+ (build_new_function_call): Call it.
+ (build_user_type_conversion_1): If LOOKUP_ONLYCONVERTING, don't
+ consider non-converting constructors.
+ Call print_z_candidates.
+ Return an AMBIG_CONV for an ambiguous conversion.
+ (build_user_type_conversion): Handle AMBIG_CONV.
+ (convert_like): Fix test for building TARGET_EXPR.
+ Call instantiate_type.
+ Handle AMBIG_CONV and LVALUE_CONV.
+ (build_over_call): Handle 0 args and ellipsis.
+ * cp-tree.def: Add AMBIG_CONV.
+
+Tue Jul 9 17:48:48 1996 Mike Stump <mrs@cygnus.com>
+
+ * decl.c (lookup_name_real): If we find mem in obj when parsing
+ `obj->mem', make sure we return the right value.
+
+Tue Jul 9 16:11:28 1996 Bob Manson <manson@charmed.cygnus.com>
+
+ * search.c (get_base_distance): Call complete_type.
- * decl.c (pushdecl): Call push_overloaded_decl for functions and
- function templates.
- (duplicate_decls): functions and function templates are not
- duplicates, but don't complain about calling this function to
- compare them.
- (push_overloaded_decl): Don't deal with linkage. Call
- duplicate_decls.
- (redeclaration_error_message): Deal with linkage.
+Tue Jul 9 12:46:34 1996 Mike Stump <mrs@cygnus.com>
+
+ * decl.c (store_bindings): Make static.
- * decl.c (start_function): If push_overloaded_decl returns an
- older version of the function, deal with it.
+Mon Jul 8 16:42:31 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_function): Be sure only to push_overloaded_decl
- for non-members.
+ * init.c (expand_aggr_init_1): Don't check type conversions if
+ NEW_OVER.
- * decl.c (grokfndecl): Put back clearing of DECL_CHAIN for
- methods.
- (start_function): Lose broken and redundant code for checking old
- decl.
+ * cvt.c (z_candidate): Put back template field.
+ (add_function_candidate): Set it.
+ (add_template_candidate): Likewise.
+ (joust): Use it.
+ (compare_qual): Handle references and pointers to members.
+ (compare_ics): Handle reference bindings.
- * init.c (add_friend): Give line numbers of both friend decls
- when warning about re-friending.
+ * decl.c (duplicate_decls): Propagate DECL_ONE_ONLY.
- * pt.c (tsubst): Use comptypes rather than == to compare the
- types of the method as declared and as defined, since default
- parameters may be different.
+Mon Jul 8 16:18:56 1996 Bob Manson <manson@charmed.cygnus.com>
- * call.c (build_method_call): Use brendan's candidate printing
- routine.
+ * call.c (compute_conversion_costs): Call complete_type.
- * decl.c (start_method): Methods defined in the class body are
- inline whether or not it's a template class.
+ * tree.c (vec_binfo_member): Use comptypes instead of comparing
+ pointers, so we can handle template parameters.
-Mon Mar 28 16:39:26 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Jul 5 16:51:53 1996 Bob Manson <manson@charmed.cygnus.com>
- * parse.y (initdcl0): Add "extern" to current_declspecs if
- have_extern_spec && ! used_extern_spcec.
+ * cvt.c (cp_convert_to_pointer): We have to call complete_type
+ here; let's make it explicit instead of a side effect of an
+ error check.
- * tree.c (really_overloaded_fn): A fn with more than one
- overload.
+Wed Jul 3 16:29:51 1996 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (end_template_decl): Use really_overloaded_fn.
+ * cvt.c (z_candidate): Remove template field.
+ (reference_binding): Handle binding to temporary.
+ (implicit_conversion): Likewise.
+ (add_function_candidate): Handle artificial constructor parms.
+ Handle functions with too few parms.
+ (add_template_candidate): New function.
+ (build_user_type_conversion_1): Handle constructors.
+ (convert_like): Likewise.
+ (build_over_call): Likewise.
+ (build_new_function_call): Support templates.
+ (compare_ics): Fix reference, inheritance handling.
- * decl.c (duplicate_decls): When smashing a decl into a previous
- definition, keep the old file and line.
- Don't deal with overloaded functions.
- Lose old code for checking arg types of functions.
- Check for overloaded C functions.
- (pushdecl): Deal with overloaded functions.
- (start_decl): Expect pushdecl to return an appropriate function decl.
- (start_function): Ditto.
- (push_overloaded_decl): Don't check for overloaded C functions.
+Mon Jul 1 22:58:18 1996 Bob Manson <manson@charmed.cygnus.com>
- * *.c: Stop using DECL_OVERLOADED, it being archaic.
- TREE_OVERLOADED should probably go, too.
+ * decl.c: Add signed_size_zero_node.
+ (init_decl_processing): Build it.
+ * class.c (prepare_fresh_vtable): Use it instead of size_zero_node
+ when we're trying to make a negative delta.
-Mon Mar 28 14:00:45 1994 Ron Guilmette (rfg@netcom.com)
+Mon Jul 1 17:56:19 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck.c (comp_target_types): Call comp_target_parms with
- strict == 1.
+ Stop doing this damn index==strchr variable name confusion.
+ * class.c (add_virtual_function): Change local var INDEX to be
+ named IDX.
+ (add_method): Likewise.
+ * lex.c (print_parse_statistics): Likewise.
+ * search.c (make_memoized_table_entry): Likewise.
+ (lookup_fnfields_here): Likewise.
+ (lookup_field): Likewise.
+ (lookup_fnfields): Likewise.
+ (get_baselinks): Likewise.
+ * sig.c (build_signature_table_constructor): Likewise.
+ (build_signature_method_call): Likewise.
+ * typeck.c (build_x_array_ref): Change INDEX parm to be named IDX.
+ (get_member_function_from_ptrfunc): Likewise.
+ (build_ptrmemfunc): Change local var INDEX to be IDX.
+ (c_expand_start_case): Likewise.
-Sun Mar 27 00:07:45 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sat Jun 29 14:05:46 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (empty_parms): Don't parse () as (...) in extern "C"
- sections if we're compiling with -ansi or -pedantic.
+ * cvt.c (cp_convert_to_pointer): Move user-defined type conversion
+ handling to before extraction of TYPE_PTRMEMFUNC_FN_TYPE.
+ (convert_to_reference): Use build_type_conversion to convert to
+ the reference type directly.
+ (standard_conversion): Fix void* case, non-conversions.
+ (reference_binding): Fix expr == 0 case, non-conversions.
+ (convert_like): Support REF_BIND.
+ (compare_qual): Split out from compare_ics.
+ (compare_ics): Use it, handle icses with only a qual_conv.
- * decl.c (decls_match): Don't treat (int) and (int&) as matching.
+ * init.c (expand_vec_init): Don't crash if decl is NULL.
- * decl2.c (grokfield): Don't pedwarn twice about initializing
- field.
+Fri Jun 28 11:52:51 1996 Stan Shebs <shebs@andros.cygnus.com>
- * decl.c (push_overloaded_decl): Warn about shadowing
- constructor.
- (redeclaration_error_message): Don't allow 'int a; int a;'
+ * mpw-config.in: New file, configury for Mac MPW.
+ * mpw-make.sed: New file, makefile editing for MPW.
- * cvt.c (build_up_reference): Only check for valid upcast if
- LOOKUP_PROTECT is set, not just any flag.
+Thu Jun 27 15:18:30 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Mar 25 01:22:31 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (instantiate_class_template): Call repo_template_used.
- * lex.c (check_newline): When we see a #pragma implementation,
- also set it for the main input file.
+ * search.c (lookup_conversions): Only lookup conversions in
+ complete types.
- * init.c (build_new): Convert array size argument to size_t.
+Thu Jun 27 12:59:53 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * parse.y (primary): If we're doing a parenthesized type-id, call
- groktypename before passing it to build_new.
+ * cp-tree.def: Renamed from tree.def, to avoid confusion with
+ gcc's tree.def.
+ * cp-tree.h, lex.c: Include cp-tree.def.
+ * Makefile.in (CXX_TREE_H): Reference cp-tree.def.
- * call.c (build_method_call): Deal properly with const and
- volatile for instances of reference type.
+Wed Jun 26 18:29:47 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (store_return_init): Change 'if (pedantic) error' to 'if
- (pedantic) pedwarn'.
+ * init.c (build_vec_delete_1): Call complete_type.
- * decl.c (grokdeclarator): Don't complain about putting `static'
- and `inline' on template function decls.
+Mon Jun 24 17:17:32 1996 Mike Stump <mrs@cygnus.com>
-Thu Mar 24 23:18:19 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * except.c (start_anon_func): Make sure anonymous functions are
+ never external.
- * call.c (build_method_call): Preserve const & volatile on
- `this'.
+Fri Jun 21 15:10:58 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Mar 24 16:21:52 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (finish_function): If function_depth > 1, set nested.
- * init.c (build_new, build_vec_delete): Use global new and delete
- for arrays.
- * decl2.c (delete_sanity): Ditto.
+ * decl2.c (grokbitfield): Revert Bob's change.
+ * class.c (finish_struct_1): Fix handling of named bitfield widths.
-Thu Mar 24 02:10:46 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Jun 20 23:35:38 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (convert_to_reference): If i is an lvalue,
- (int &)i -> *(int*)&i, as per 5.2.8p9 of the latest WP.
- (convert_force): Call convert_to_reference with LOOKUP_COMPLAIN.
+ * pt.c (add_pending_template): Handle types.
+ (lookup_template_class): With -fexternal-templates, just add the class
+ to pending_templates instead of instantiating it now.
+ * decl2.c (finish_file): Handle types in pending_templates.
-Wed Mar 23 17:45:37 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Jun 20 14:08:40 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (duplicate_decls): Also propagate DECL_TEMPLATE_MEMBERS
- and DECL_TEMPLATE_INSTANTIATIONS.
+ * decl2.c (grokbitfield): Handle constant decls appropriately.
+ Give an appropriate error message now instead of spewing core
+ later.
- * init.c (build_new): Handle array typedefs properly.
+Thu Jun 20 13:01:51 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Mar 23 18:23:33 1994 Mike Stump <mrs@cygnus.com>
+ * decl2.c: Don't turn on thunks by default for now.
- 30th Cygnus<->FSF merge.
+Wed Jun 19 11:37:04 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Mar 23 00:46:24 1994 Mike Stump <mrs@cygnus.com>
+ * typeck.c (complete_type): Handle error_mark_node.
+ (common_type, OFFSET_TYPE): Handle template_type_parms.
- * class.c (modify_vtable_entries): Avoid running off the end of the
- virtuals list when processing a virtual destructor.
- * class.c (get_vtable_entry): Ditto.
+Tue Jun 18 10:02:15 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Mar 23 00:23:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (instantiate_decl): If at_eof, call import_export_decl
+ regardless of DECL_INLINE.
- * decl.c (duplicate_decls): If two template decls don't match,
- just return 0.
+ * typeck.c (mark_addressable): Set TREE_ADDRESSABLE on CONSTRUCTORs.
-Tue Mar 22 23:49:41 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * class.c (finish_struct_bits): Copy TYPE_SIZE.
- * typeck.c (convert_for_assignment): Don't pedwarn about
- converting function pointer to void *.
+ * rtti.c (build_dynamic_cast): Support templates.
+ * tree.def: Support DYNAMIC_CAST_EXPR.
+ * pt.c (tsubst_copy): Likewise.
+ * decl2.c (build_expr_from_tree): Likewise.
-Tue Mar 22 22:23:19 1994 Mike Stump <mrs@cygnus.com>
+Mon Jun 17 15:23:36 1996 Jason Merrill <jason@yorick.cygnus.com>
- Major revamp of pointer to member functions. Cures major
- nonfunctionality when used in casts, and MI situations.
+ * typeck.c (build_static_cast): Support templates.
+ (build_const_cast): Likewise.
+ * tree.def: Support CONST/STATIC_CAST_EXPR.
+ * pt.c (tsubst_copy): Likewise.
+ * decl2.c (build_expr_from_tree): Likewise.
- * cvt.c (convert_force): Update call site of build_ptrmemfunc.
- * typeck.c (convert_for_assignment): Ditto.
- * typeck2.c (digest_init): Ditto.
- * typeck2.c (process_init_constructor): Simplify by moving code into
- digest_init.
- * typeck2.c (digest_init): Do default_conversions on init value, if
- we are processing pointer to member functions.
- * class.c (get_vfield_offset): Now non-static. Convert bit offset
- into byte offset.
- * cp-tree.h (get_vfield_offset): Ditto.
- * typeck.c (get_member_function_from_ptrfunc): Convert down to right
- instance, before fetching vtable pointer.
- * typeck.c (get_delta_difference): New routine.
- * typeck.c (build_ptrmemfunc): Revamp to handle casting better, also
- get vtable pointer out of right subobject.
+Sun Jun 16 12:33:57 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue Mar 22 17:56:48 1994 Mike Stump <mrs@cygnus.com>
+ * decl2.c (finish_vtable_vardecl): Don't trust
+ TREE_SYMBOL_REFERENCED for vtables of local classes.
- * search.c (get_binfo): Return NULL instead of aborting, when
- passed a UNION_TYPE.
+Fri Jun 14 18:13:36 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue Mar 22 12:44:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (tsubst_copy): Handle operator T.
- These patches implement handling of redefinition/redeclaration of
- templates.
+Wed Jun 12 17:52:40 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck.c (comptypes): Simplify. All TEMPLATE_TYPE_PARMs are
- considered compatible.
+ * init.c (build_delete): Move creation of PARMS inside test of
+ TYPE_HAS_DESTRUCTOR, since it's never used outside of that block.
- * parse.y (template_def): Pass defn argument to end_template_decl.
+Tue Jun 11 15:09:18 1996 Bob Manson <manson@charmed.cygnus.com>
- * pt.c (end_template_decl): Add defn argument. Check for
- redefinition. Simplify.
+ * typeck.c (build_conditional_expr): Don't assume that
+ the arguments to ?: are always pointers or records.
- * error.c (OB_UNPUT): New macro, to remove mistakes.
- (aggr_variety): Subroutine of dump_aggr_type.
+Tue Jun 11 13:56:23 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (decls_match): Support templates.
- (duplicate_decls): No longer static. Don't try to lay out template
- decls.
- (pushdecl): Simplify.
+ * decl2.c (import_export_decl): Still emit static/weak/comdat
+ copies of inline template functions with -fno-implicit-templates.
- * cp-tree.h (DECL_TEMPLATE_MEMBERS): Use DECL_SIZE instead of
- DECL_INITIAL.
+Tue Jun 11 11:42:13 1996 Bob Manson <manson@charmed.cygnus.com>
-Mon Mar 21 11:46:55 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * init.c (build_delete): Determine the complete basetype
+ path to the destructor we're calling.
- * error.c (dump_decl): Support class template decls.
- (dump_type): Don't adorn template type parms.
+Fri Jun 7 15:30:10 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (duplicate_decls): Save DECL_TEMPLATE_INFO from old decl
- if it was a definition.
- (redeclaration_error_message): Do the cp_error thang, and reject
- redefinition of templates.
+ * decl.c (build_enumerator): Always copy the INTEGER_CST used to
+ initialize the enum, because we really and truly don't know where
+ it came from.
+ (start_enum): Don't copy integer_zero_node because
+ build_enumerator will do it.
-Mon Mar 21 19:36:06 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Fri Jun 7 11:11:09 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Set TREE_PUBLIC for METHOD_TYPE
- in FIELD context, when appropriate. Also,
- CLASSTYPE_INTERFACE_ONLY is irrelevant to setting TREE_PUBLIC.
- Also, simplify check for bogus return specifiers.
+ * decl.c (finish_function): Do access control on base destructors.
-Mon Mar 21 11:46:55 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (tsubst, case FUNCTION_DECL): Set up
+ IDENTIFIER_GLOBAL_VALUE for member functions so pushdecl doesn't
+ hose us.
- * parse.y (after_type_declarator1): Expand type_quals.
- (notype_declarator1): Ditto.
- (absdcl1): Ditto.
+Fri Jun 7 10:37:33 1996 Mike Stump <mrs@cygnus.com>
-Sat Mar 19 01:05:17 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cvt.c (build_up_reference): If we have already extended the
+ lifetime of the temporary, don't try it again.
+ * typeck.c (c_expand_return): Don't try and convert the return
+ value twice when we want a reference, once is enough.
+
+Tue Jun 4 15:41:45 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Treat class-local typedefs like static
- members; i.e. 'typedef int f();' means that f is a function type,
- not a method type.
+ * pt.c (tsubst_expr, case DECL_STMT): Don't pass
+ LOOKUP_ONLYCONVERTING at all for now.
- * parse.y (decl): Change direct_* back to *.
- (type_id): Change direct_abstract_declarator to absdcl.
- (direct_declarator, direct_initdecls, direct_initdcl0): Remove again.
+ * search.c (add_conversions): Put the conversion function in
+ TREE_VALUE, the basetype in TREE_PURPOSE.
+ * cvt.c (build_type_conversion): Adjust.
+ * cvt.c (build_expr_type_conversion): Adjust.
+ * call.c (user_harshness): Adjust.
-Fri Mar 18 12:47:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Jun 3 15:30:52 1996 Jason Merrill <jason@yorick.cygnus.com>
- These two patches fix crashes on instantiating a template inside a
- function with C linkage or containing labels.
+ * method.c (emit_thunk): Pretend this is a FUNCTION_DECL for the
+ backend's benefit.
- * class.c (current_lang_stacksize): No longer static.
+Mon Jun 10 18:58:19 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (struct saved_scope): Add lang_base, lang_stack,
- lang_name, lang_stacksize, and named_labels.
- (push_to_top_level): Save them.
- (pop_from_top_level): Restore them.
+ * except.c (expand_start_catch_block): Add a dummy region, if we
+ get an error, so that we can avoid core dumping later.
- * gxxint.texi (Parser): Update.
+Fri May 31 14:56:13 1996 Mike Stump <mrs@cygnus.com>
- These two patches finish moving the task of expr/declarator
- ambiguity resolution from the lexer to the parser, and add one more
- r/r conflict. START_DECLARATOR can now be nuked.
+ * cp-tree.h (OFFSET_REF): Remove.
+ * tree.def (CP_OFFSET_REF): Rename to OFFSET_REF.
+ * expr.c (cplus_expand_expr): Cleanup callers of expand_expr.
+ * init.c (expand_aggr_init_1): Likewise.
+ (build_new): Likewise.
+ * typeck.c (expand_target_expr): Likewise.
- * parse.y (decl): Add "direct_" in typespec X rules.
- (direct_declarator): New nonterminal for
- direct_after_type_declarator and direct_notype_declarator.
- (direct_initdecls): Like initdecls, but uses direct_initdcl0.
- (direct_initdcl0): Like initdcl0, but uses direct_declarator.
- (named_parm): Add typespec direct_declarator rule.
+Fri May 31 14:22:08 1996 Jason Merrill <jason@yorick.cygnus.com>
- * spew.c (yylex): #if 0 out START_DECLARATOR insertion.
+ * typeck.c (build_modify_expr): Don't use TREE_VALUE on a
+ TARGET_EXPR.
- These two patches disable some excessive cleverness on the part of
- g++; a non-class declaration always hides a class declaration in the
- same scope, and g++ was trying to unhide it depending on the
- enclosing expression.
+Wed May 29 17:04:33 1996 Mike Stump <mrs@cygnus.com>
- * spew.c (arbitrate_lookup): #if 0 out.
+ * cvt.c (build_up_reference): Redo how and when temporaries are
+ created.
+ * decl.c (grok_reference_init): Don't try and be smart about
+ running cleanups.
- * decl.c (lookup_name): Never call arbitrate_lookup.
+Wed May 29 16:02:08 1996 Mike Stump <mrs@cygnus.com>
- * parse.y (complex_notype_declarator1): Add '*'
- complex_notype_declarator1 and '&' complex_notype_declarator1 rules.
+ * cvt.c (build_up_reference): Add NULL_TREE to all calls to build
+ (TARGET_EXPR...), now that it has 4 arguments.
+ * tree.c (build_cplus_new): Likewise.
- * parse.y (complex_direct_notype_declarator): Restore id_scope
- see_typename TYPENAME rule, remove all other rules beginning with
- those tokens.
- (notype_unqualified_id): Add '~' see_typename IDENTIFIER rule.
+Thu May 23 16:40:30 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Mar 17 17:30:01 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * error.c (dump_expr, case CAST_EXPR): Handle T() properly.
- These changes fix the compiler's handling of the functional cast/
- object declaration ambiguities in section 6.8 of the ARM. They also
- add 11 reduce/reduce conflicts. Sigh.
+ * pt.c (instantiate_decl): Don't call push/pop_cp_function_context.
+ * decl.c (struct saved_scope): Remove named_labels,
+ {base,member}_init_list.
+ (maybe_push_to_top_level): Don't set them. Call
+ push_cp_function_context if appropriate.
+ (pop_from_top_level): Likewise.
- * parse.y: Add precedence decls for OPERATOR and '~'.
- (notype_unqualified_id): New nonterminal, encompasses all of the
- ANSI unqualified-id nonterminal except TYPENAMEs.
- (expr_or_declarator): New nonterminal to delay parsing of code like
- `int (*a)'.
- (primary): Use notype_unqualified_id.
- (decl): Add typespec initdecls ';' and typespec declarator ';'
- rules.
- (initdcl0): Deal with the above.
- (complex_notype_declarator1): A notype_declarator that is not also
- an expr_or_declarator.
- (complex_direct_notype_declarator): A direct_notype_declarator that
- doesn't conflict with expr_or_declarator. Use
- notype_unqualified_id. Remove id_scope see_typename TYPENAME rule.
- (functional_cast): New nonterminal, for the three functional cast
- rules. So that they can be moved after
- complex_direct_notype_declarator.
- (see_typename): Don't accept type_quals any more.
+ * method.c (do_build_assign_ref): Remove obsolete check of
+ TYPE_HAS_ASSIGN_REF (basetype).
- * decl2.c (reparse_decl_as_expr): New function to deal with parse
- nodes for code like `int (*a)++;'.
- (reparse_decl_as_expr1): Recursive subroutine of the above.
- (finish_decl_parsing): New function to deal with parse nodes for
- code like `int (*a);'. See the difference?
+ * decl.c (grokfndecl): Diagnose user definition of
+ implicitly-declared methods.
-Thu Mar 17 12:16:10 1994 Mike Stump <mrs@cygnus.com>
+Thu May 23 12:13:08 1996 Bob Manson <manson@charmed.cygnus.com>
- These changes break binary compatibility in code with classes
- that use virtual bases.
+ * method.c (do_build_copy_constructor): Add code to give
+ meaningful error messages instead of crashing.
+ (do_build_assign_ref): Don't synthesize assignment operators for
+ classes containing reference or const members.
- * search.c (dfs_get_vbase_types): Simplify and correct to make
- sure virtual bases are initialized in dfs ordering.
- * search.c (get_vbase_types): Simplify and make readable.
+ * class.c (struct base_info): Remove cant_synth_copy_ctor
+ and cant_synth_asn_ref.
+ (finish_base_struct): Remove the code that tries to conditionalize
+ synthesis of copy constructors & assignment operators based on
+ access permissions. Instead, let it fail when it tries to
+ synthesize the copy constructor. This will give meaningful error
+ messages instead of silently generating code to perform a bitcopy.
-Thu Mar 17 12:01:10 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed May 22 11:45:19 1996 Bob Manson <manson@charmed.cygnus.com>
- * parse.y: s/ typename / type_id /g
+ * lex.c (real_yylex): Remove old-n-crufty #if 0 code for
+ determining types for constant values.
-Wed Mar 16 17:42:52 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * decl.c (struct named_label_list): Use instead of stuffing
+ random items into a TREE_LIST node.
+ (named_label_uses): Use the new struct.
+ (poplevel): Likewise.
+ (lookup_label): Likewise.
+ (define_label): Add an error message to tell the user the line
+ where the goto is located in addition to the destination of the
+ goto.
+ (init_decl_processing): Use NULL instead of NULL_TREE to initialize
+ named_label_uses.
+ (finish_function): Likewise.
+
+ (start_decl): Complain about defining a static data member
+ in a different type from which it was declared.
- * parse.y (typespec): add SCOPE TYPENAME for global scoped
- type. e.g. ::B x.
+Wed May 22 09:33:23 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (complete_array_type): fix a bug that in -pendantic
- mode even there's no initializer, it will continue to build
- default index.
+ * cvt.c (build_expr_type_conversion): Adjust.
-Wed Mar 16 17:43:07 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue May 21 11:21:56 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (direct_notype_declarator): Add PTYPENAME rule, remove
- all of the scoped PTYPENAME rules.
+ * call.c (build_method_call): Always convert 'this' to the
+ appropriate type.
-Wed Mar 16 16:39:02 1994 Mike Stump <mrs@cygnus.com>
+ * search.c (add_conversions): Put the conversion function in
+ TREE_VALUE, the type in TREE_PURPOSE.
+ * cvt.c (build_type_conversion): Adjust.
+ * call.c (user_harshness): Adjust.
- * init.c (build_offset_ref): The value of A::typedef_name is
- always the TYPE_DECL, and never an error.
+ * method.c (emit_thunk): Call temporary_allocation and
+ permanent_allocation around the ASM_OUTPUT_MI_THUNK case, too.
-Tue Mar 15 20:02:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * tree.c (build_cplus_array_type): Handle tweaking of
+ TYPE_MAIN_VARIANT here.
+ * typeck.c (common_type): Not here.
- * search.c (get_base_distance_recursive): Two binfos can only
- represent the same object if they are both via_virtual.
+ * typeck.c (complete_type): Only try to complete an array type if
+ it has a domain.
- * class.c (finish_base_struct): Check vbases for ambiguity, too.
+Mon May 20 14:55:59 1996 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (get_vbase_types): Accept binfo argument, too.
+ * decl.c (grokvardecl): Call complete_type.
+ (grokdeclarator): Call complete_type for PARM_DECLs.
-Tue Mar 15 19:22:05 1994 Kung Hsu (kung@mexican.cygnus.com)
+Fri May 17 16:41:17 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (complete_array_type): complete TYPE_DOMAIN of the
- initializer also, because back-end requires it.
+ * pt.c (instantiate_class_template): Re-set
+ CLASSTYPE_GOT_SEMICOLON after calling finish_struct_1.
-Tue Mar 15 15:33:31 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri May 17 14:56:55 1996 Mike Stump <mrs@cygnus.com>
- * error.c (dump_expr): Support member functions (which show up as
- OFFSET_REFs).
+ * cp-tree.h (cp_expand_decl_cleanup): Remove, the backend is now
+ smart enough to do it right.
+ * tree.c (cp_expand_decl_cleanup): Likewise.
+ * decl.c (cp_finish_decl): Use expand_decl_cleanup instead of
+ cp_expand_decl_cleanup.
+ (store_parm_decls): Likewise.
+ (hack_incomplete_structures): Likewise.
+ * except.c (push_eh_cleanup): Likewise.
-Mon Mar 14 16:24:36 1994 Mike Stump <mrs@cygnus.com>
+Fri May 17 13:13:51 1996 Mike Stump <mrs@cygnus.com>
- * init.c (build_new): Set the return type of multidimensional
- news correctly.
+ * expr.c (expand_expr, cond UNSAVE_EXPR): Move from the C++
+ frontend to the backend where it belongs.
+ * tree.c (unsave_expr): Likewise.
+ (unsave_expr_now): Likewise.
+ * tree.def (UNSAVE_EXPR): Likewise.
+ * cp-tree.h (unsave_expr): Likewise.
+ (unsave_expr_now): Likewise.
-Fri Mar 11 15:35:39 1994 Kung Hsu (kung@mexican.cygnus.com)
+Fri May 17 11:02:41 1996 Mike Stump <mrs@cygnus.com>
- * call.c (build_method_call): if basetype not equal to type
- of the instance, use the type of the instance in building
- destructor.
+ * init.c (emit_base_init): Make sure the partial EH cleanups live
+ on the function_obstack.
-Thu Mar 10 17:07:10 1994 Kung Hsu (kung@mexican.cygnus.com)
+Thu May 16 15:29:33 1996 Bob Manson <manson@charmed.cygnus.com>
- * parse.y (direct_notype_declarator): add push_nested_type for
- 'template_type SCOPED_NAME' rule.
+ * expr.c (do_case): Don't try to dereference null TREE_TYPEs
+ when checking for pointer types.
-Tue Mar 8 00:19:58 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu May 16 13:38:58 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (parm): Add typed_declspec1 {absdcl, epsilon} rules.
+ * pt.c (instantiate_class_template): Remove obsolete check for
+ access declarations.
-Sat Mar 5 04:47:48 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu May 16 13:34:15 1996 Mike Stump <mrs@cygnus.com>
- * parse.y (regcast_or_absdcl): New nonterminal to implement late
- reduction of constructs like `int ((int)(int)(int))'.
- (cast_expr): Use it.
- (sub_cast_expr): Everything that can come after a cast.
- (typed_declspecs1): typed_declspecs that are not typed_typespecs.
- (direct_after_type_declarator): Lose PAREN_STAR_PAREN rule.
- (direct_abstract_declarator): Replace '(' parmlist ')' rule with
- '(' complex_parmlist ')' and regcast_or_absdcl.
- (parmlist): Split
- (complex_parmlist): Parmlists that are not also typenames.
- (parms_comma): Enabler.
- (named_parm): A parm that is not also a typename. Use declarator
- rather than dont_see_typename abs_or_notype_decl. Expand
- typed_declspecs inline.
- (abs_or_notype_decl): Lose.
- (dont_see_typename): Comment out.
- (bad_parm): Break out abs_or_notype_decl into two rules.
+ * call.c (build_overload_call): Simplify calls to
+ build_overload_call by removing last parameter.
+ (build_method_call): Likewise.
+ * cp-tree.h: Likewise.
+ * method.c (build_opfncall): Likewise.
+ * typeck.c (build_x_function_call): Likewise.
-Fri Mar 4 18:22:39 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu May 16 13:15:43 1996 Mike Stump <mrs@cygnus.com>
- * decl2.c (reparse_decl_as_casts): New function to change parse
- nodes for `(int)(int)(int)' from "function taking int and returning
- function taking int and returning function taking int" to "... cast
- to int, cast to int, cast to int".
+ * call.c (default_parm_conversions): Factor out common code.
+ (build_method_call): Use it.
+ (build_overload_call_real): Use it.
- * decl2.c (reparse_decl_as_expr): Recursive function to change
- parse nodes for `A()()' from "function returning function returning
- A" to "A().operator()".
+Wed May 15 14:46:14 1996 Mike Stump <mrs@cygnus.com>
- * parse.y (primary): Replace `typespec LEFT_RIGHT' rule with
- `typespec fcast_or_absdcl' rule.
- (fcast_or_absdcl): New nonterminal to implement late reduction of
- constructs like `A()()()()'.
- (typename): Replace `typespec absdcl1' rule with
- `typespec direct_abstract_declarator' rule.
- (direct_abstract_declarator): Replace `LEFT_RIGHT type_quals' rule
- with `fcast_or_absdcl type_quals' rule.
+ * call.c (build_method_call): Allow implicit & on METHOD_TYPEs,
+ but pedwarn as the code is bogus.
+ * typeck.c (decay_conversion): Likewise.
+ (build_function_call_real): Use build_addr_func instead of
+ default_conversion. Don't allow pointer-to-method functions down
+ here.
+ (build_unary_op): Use real pointer-to-member functions instead of
+ fake ones.
+ (build_ptrmemfunc): Use build_addr_func instead of build_unary_op.
+ (convert_for_assignment): Removed some obsolete code.
+ * decl2.c (reparse_absdcl_as_expr): Pass current_class_ref to
+ build_x_function_call instead of current_class_ptr. Only call
+ digest_init once on an initializer, we do this just checking
+ TREE_TYPE.
+ (build_expr_from_tree): Pass current_class_ref to
+ build_x_function_call instead of current_class_ptr.
+ * init.c (build_member_call): Likewise.
+ * pase.y: Likewise.
+ * error.c (dump_expr): Handle OFFSET_REFs better.
+ * pt.c (unify): Handle pointer-to-member functions better.
+ * decl.c (finish_function): Clear out current_class_ref just like
+ we do for current_class_ptr.
-Fri Mar 4 16:18:03 1994 Mike Stump <mrs@cygnus.com>
-
- * tree.c (lvalue_p): Improve OFFSET_REF handling, so that it
- matches Section 5.5.
+ * typeck.c (get_delta_difference): Handle virtual bases better.
-Fri Mar 4 14:01:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue May 14 16:37:37 1996 Jason Merrill <jason@yorick.cygnus.com>
- * error.c (dump_type_prefix): Don't print basetype twice for
- pmfs.
+ * sig.c (build_signature_table_constructor): Use the delta for
+ the original basetype for this virtual function with thunks.
+ (build_signature_method_call): We still need to adjust 'this'
+ with thunks.
-Fri Mar 4 13:24:33 1994 Mike Stump <mrs@cygnus.com>
+Tue May 14 16:27:25 1996 Mike Stump <mrs@cygnus.com>
- * typeck.c (convert_arguments): Handle setHandler(A::handlerFn)
- so that it is like setHandler(&A::handlerFn). Cures an `invalid
- lvalue in unary `&''.
+ * call.c (build_addr_func): New routine. Used to get the `real'
+ address of a function or a method. Needed to avoid getting a
+ pointer-to-member function.
+ (build_call): New routine to build CALL_EXPRs.
+ (build_method_call): Use it.
+ * cvt.c (convert_to_aggr): Likewise.
+ * typeck.c (build_function_call_real): Likewise.
+ * sig.c (build_signature_table_constructor): Use build_addr_func.
+ * cp-tree.h (build_call, build_addr_func): Declare them.
-Fri Mar 4 11:15:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue May 14 12:47:47 1996 Mike Stump <mrs@cygnus.com>
- * gxxint.texi (Copying Objects): New section discussing default
- op= problems with virtual inheritance.
+ * cp-tree.h (LOOKUP_AGGR): Remove, unused.
+ * parse.y: Remove uses of LOOKUP_AGGR.
- * decl2.c (grokoptypename): Just does grokdeclarator and
- build_typename_overload, since the parser can't call grokdeclarator
- directly.
+Tue May 14 12:07:51 1996 Mike Stump <mrs@cygnus.com>
- * method.c (build_typename_overload): Set IDENTIFIER_GLOBAL_VALUE
- and TREE_TYPE on generated identifiers.
+ * *.[chy]: Rename current_class_decl to current_class_ptr, and
+ C_C_D to current_class_ref.
- * decl.c (grokdeclarator): Don't deal with TYPE_EXPRs anymore.
+Mon May 13 16:55:23 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (parm): Convert `const char *' to `__opPCc' here.
+ * call.c (convert_harshness): Tighten up pointer conversions.
- * error.c (dump_decl): Say sorry rather than my_friendly_aborting
- if we can't figure out what to do.
- (dump_type*): Ditto.
+Sat May 11 04:33:50 1996 Doug Evans <dje@canuck.cygnus.com>
- * typeck2.c (build_m_component_ref): 'component' is an expr, not
- a decl. Also move the IS_AGGR_TYPE check after the stripping of
- REFERENCE_TYPE.
+ * decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef.
+ (finish_file): Likewise.
-Fri Mar 4 04:46:05 1994 Mike Stump <mrs@cygnus.com>
+Fri May 10 11:09:57 1996 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Handle b->setHandler(A::handlerFn)
- so that it is like b->setHandler(&A::handlerFn). Cures an `invalid
- lvalue in unary `&''.
+ * cvt.c (convert_fn_ptr): We don't use thunks for pmfs.
-Thu Mar 3 12:38:15 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * method.c (emit_thunk): Set flag_omit_frame_pointer in default
+ code.
- * parse.y: Add precedence specification for START_DECLARATOR.
- (type_quals): Move before primary.
- (typename): Move before typed_declspecs, add 'typespec absdcl1' rule.
+Thu May 9 18:18:30 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (grokoptypename): Lose.
+ * decl2.c: Turn on thunks by default where supported.
- * decl.c (grokdeclarator): Parse TYPE_EXPRs in the initial scan,
- rather than waiting until later.
+Tue May 7 20:39:57 1996 Mike Stump <mrs@cygnus.com>
-Wed Mar 2 14:12:23 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cp-tree.h (build_overload_call_maybe): Removed.
+ * call.c (build_overload_call_real): Invert meaning of last arg to
+ be require_complete.
+ (build_overload_call): Likewise.
+ * typeck.c (build_x_function_call): Use build_overload_call_real
+ instead of build_overload_call_maybe.
- * parse.y (unary_expr): Use 'typename' in 'new' rules, rather
- than expanding it inline.
- (typename): Expand empty option of (former) absdcl inline.
- (abs_or_notype_decl): Ditto.
- (absdcl): Lose empty rule.
- (conversion_declarator): New nonterminal for 'typename' of 'operator
- typename'.
- (operator_name): Use it instead of absdcl.
+Mon May 6 01:23:32 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y: Add precedence declarations for SCOPED_TYPENAME,
- TYPEOF, and SIGOF.
- (typed_declspecs): Accept typed_typespecs, rather than typespec
- directly. Add rules with reserved_typespecquals.
- (reserved_declspecs): Don't accept typespecqual_reserved at the
- beginning of the list. The typed_declspecs rule will deal with this
- omission.
- (declmods): Accept nonempty_type_quals, rather than TYPE_QUAL
- directly.
+ * decl2.c (finish_file): Don't try to emit functions that haven't
+ been compiled.
- * parse.y (direct_notype_declarator,
- direct_after_type_declarator, direct_abstract_declarator): Split up
- the declarator1 nonterminals to match the draft standard and avoid
- ambiguities.
- (new_type_id, new_declarator, direct_new_declarator,
- new_member_declarator): New nonterminals to implement the subset of
- 'typename' allowed in new expressions.
- (unary_expr): Use new_type_id instead of typename.
- (after_type_declarator1, absdcl1): Fix semantics of member pointers.
- (abs_member_declarator, after_type_member_declarator): Lose.
+Fri May 3 09:30:13 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (absdcl1): Don't require parens around
- abs_member_declarator.
- (abs_member_declarator): Lose see_typename from rules.
- (after_type_member_declarator): Ditto.
+ * decl2.c (finish_vtable_vardecl): Oops.
- * tree.c (get_identifier_list): New function, containing code
- previously duplicated in get_decl_list and list_hash_lookup_or_cons.
- (get_decl_list): Use it.
- (list_hash_lookup_or_cons): Ditto.
+ * decl.c (maybe_push_to_top_level): Do save previous_class_*.
+ Also store the bindings from previous_class_values.
+ (pop_from_top_level): Restore them.
- * parse.y (typed_declspecs, declmods): It's not necessary to hash
- the declspecs on class_obstack, so don't. This way typed_typespecs
- can reduce to typed_declspecs.
+Thu May 2 21:56:49 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Mar 2 14:29:18 1994 Jason Merrill (jason@cygnus.com)
+ * decl2.c (finish_vtable_vardecl): Only write out vtable if its
+ symbol has been referenced.
+ (finish_file): Re-join synthesis/vtable loop with inline emission
+ loop, disable inlining when an inline is output.
- * cvt.c (build_up_reference): If we aren't checking visibility,
- also allow base->derived conversions.
+Thu May 2 17:20:02 1996 Mike Stump <mrs@cygnus.com>
-Mon Feb 28 15:14:29 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * except.c (init_exception_processing): Setup saved_in_catch.
+ (push_eh_cleanup): Reset __eh_in_catch.
+ (expand_start_catch_block): Set __eh_in_catch.
- * typeck.c (build_c_cast): Remove bogus hack when converting
- to a reference type.
+Thu May 2 16:21:17 1996 Mike Stump <mrs@cygnus.com>
- * cp-tree.h (lang_decl::vbase_init_list, DECL_VBASE_INIT_LIST):
- Removed, not used.
- (lang_stype::methods, lang_decl::next_method): New fields.
- (CLASSTYPE_METHODS, DECL_NEXT_METHOD): New macros.
- * decl.c (duplicate_decls): Preserve DECL_NEXT_METHOD.
+ * except.c (push_eh_cleanup): Add tracking for whether or not we
+ have an active exception object.
+ (expand_builtin_throw): Use it to make sure a rethrow without an
+ exception object is caught.
- * cp-tree.h, decl2.c (flag_vtable_hack): New flag.
- * decl2.c (finish_vtable_vardecl): If flag_vtable_hack,
- and !CLASSTYPE_INTERFACE_KNOWN, try to use the presence of
- a non-inline virtual function to control emitting of vtables.
- * class.c (finish_struct): Build CLASSTYPE_METHODS list.
- * search.c (build_vbase_vtables_init): Don't assemble_external
- (yet) if flag_vtable_hack.
- * class.c (build_vfn_ref): Ditto.
+Thu May 2 11:26:41 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon Feb 28 14:54:13 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (maybe_push_to_top_level): Clear out class-level bindings
+ cache.
- * parse.y (component_decl): Don't include "typed_declspecs
- declarator ';'" speedup, since it breaks enums.
+Wed May 1 11:26:52 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Feb 25 15:43:44 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * decl2.c (finish_file): Also use sentries for vars with
+ DECL_ONE_ONLY or DECL_WEAK set (should any such happen to be
+ created).
- * class.c (finish_struct): Minor optimization for building
- fn_fields list.
+ * lex.c (handle_cp_pragma): Disable #pragma
+ interface/implementation if SUPPORTS_ONE_ONLY > 1.
-Fri Feb 25 15:23:42 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Apr 30 11:25:46 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_function): Fix detection of function overloading.
+ * method.c (emit_thunk): Wrap default case in
+ temporary/permanent_allocation.
-Thu Feb 24 22:26:19 1994 Mike Stump <mrs@cygnus.com>
+ * method.c (make_thunk): Use DECL_ONE_ONLY.
+ (emit_thunk): Call assemble_end_function.
- * lex.c (check_newline): #pragma interface can take a string
- argument, just like #pragma implementation. #pragma implementation
- checks for garbage on the line, line #pragma interface does. Main
- input files do not auto implement like named files, #pragma
- implementation must be used explicitly.
+Mon Apr 29 15:38:29 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Feb 24 17:09:01 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (import_export_vtable): Use DECL_ONE_ONLY.
+ (import_export_decl): Likewise.
+ (finish_prevtable_vardecl): Disable vtable hack if
+ SUPPORTS_ONE_ONLY > 1.
- * parse.y (components): Handle list of one again.
- (notype_components): Ditto.
- (after_type_declarator1): Take maybe_raises out again.
+Mon Apr 29 14:32:47 1996 Mike Stump <mrs@cygnus.com>
- * gxxint.texi (Parser): Document additional r/r conflict.
+ * typeck.c (build_modify_expr): PREINCREMENT_EXPR and
+ PREDECREMENT_EXPRs take two arguments, not one.
-Wed Feb 23 14:42:55 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Apr 29 00:27:53 1996 Jason Merrill <jason@yorick.cygnus.com>
- * gxxint.texi (Parser): Add node.
+ * class.c (build_vtable_entry): Don't build thunks for abstract
+ virtuals.
- * Makefile.in (stamp-parse): Update expected conflict count.
+ * lex.c (real_yylex): Fix handling of __PRETTY_FUNCTION__ like C
+ frontend.
- * parse.y (various): Replace "declmods declarator" with "declmods
- notype_declarator". The comment saying that "declmods declarator ';'"
- corresponds to "int i;" was wrong; it corresponds to "const i;".
- (component_decl): Add "typed_declspecs declarator ';'" rule; this
- *does* correspond to "int i;". Change "declmods components" to
- "declmods notype_components".
- (components): Don't deal with a list of one anymore.
- (notype_components): New nonterminal, corresponds to notype_declarator.
- ({after_,no}type_component_decl{,0}): More new nonterminals.
- ({after_,no}type_declarator): Fold in START_DECLARATOR token.
- Eliminates four reduce/reduce conflicts.
+Sat Apr 27 16:45:35 1996 Jason Merrill <jason@yorick.cygnus.com>
- (expr): Depend on nontrivial_exprlist instead of nonnull_exprlist.
- (nontrivial_exprlist): New nonterminal: A list of at least two
- expr_no_commas's.
- (nonnull_exprlist): Depend on nontrival_exprlist.
- Eliminates four reduce/reduce conflicts.
+ * class.c (set_rtti_entry): Use size_zero_node.
+ (build_vtable): Likewise.
- (named_class_head): Move intermediate code block into separate
- nonterminal so that we can stick %prec EMPTY on it.
+Sat Apr 27 14:48:57 1996 Jason Merrill <jason@phydeaux.cygnus.com>
- Add more %prec EMPTY's to eliminate remaining shift/reduce
- conflicts.
+ * class.c (finish_struct_1): Pass size_zero_node to set_rtti_entry.
+ (prepare_fresh_vtable): Likewise.
- (after_type_declarator): Add maybe_raises to fndecl rules.
- (after_type_declarator_no_typename): Remove.
- For correctness.
+Fri Apr 26 13:14:14 1996 Jason Merrill <jason@yorick.cygnus.com>
- Document remaining reduce/reduce conflicts.
+ * method.c (emit_thunk): Call mark_used on the target function.
-Tue Feb 22 12:10:32 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_method_call): Don't warn about pending templates.
- * search.c (get_base_distance): Only bash BINFO_INHERITANCE_CHAIN
- (TYPE_BINFO (type)) if we care about the path.
+Thu Apr 25 14:55:44 1996 Jason Merrill <jason@yorick.cygnus.com>
- * tree.c (lvalue_p): A COND_EXPR is an lvalue if both of the
- options are.
+ * decl2.c (finish_file): Fix list walking logic.
-Mon Feb 21 19:59:40 1994 Mike Stump <mrs@cygnus.com>
+ * typeck2.c (check_for_new_type): Only warn if -pedantic.
- * Makefile.in (mostlyclean): lex.c is a source file, don't
- remove.
+Wed Apr 24 15:41:15 1996 Bob Manson <manson@charmed.cygnus.com>
-Sat Feb 19 01:27:14 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * class.c (finish_struct_1): Remove old code for
+ dont_allow_type_definitions.
+ * cp-tree.h: Likewise.
+ * spew.c: Make sure cp-tree.h is included before parse.h, so the
+ definition of flagged_type_tree is found before it is used.
+ * lex.c: Likewise.
+ * parse.y: Added the ftype member to the type union, and changed a
+ number of rules to use it instead of ttype. Added calls to
+ check_for_new_type() as appropriate.
+ * typeck2.c (check_for_new_type): New function for checking
+ if a newly defined type appears in the specified tree.
+ * cp-tree.h: Add new type flagged_type_tree. Add a prototype
+ for check_for_new_type().
- * parse.y: Eliminate 20 shift/reduce conflicts.
+Wed Apr 24 00:36:21 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Feb 18 11:49:42 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (finish_file): Only use a sentry if the decl is public.
- * pt.c (type_unification): Add subr argument; if set, it means
- that we are calling ourselves recursively, so a partial match is OK.
- (unify): Support pointers to methods and functions.
- (tsubst): Support method pointers.
- * decl.c (build_ptrmemfunc_type): No longer static, so that
- tsubst can get at it.
+ * pt.c (tsubst_expr, DECL_STMT): If we don't have an initializer,
+ don't pass LOOKUP_ONLYCONVERTING.
- * init.c (is_aggr_typedef): Pretend template type parms are
- aggregates.
- * decl2.c (build_push_scope): If cname refers to a template type
- parm, just grin and nod.
+Tue Apr 23 17:18:47 1996 Bob Manson <manson@charmed.cygnus.com>
- * call.c (build_overload_call_real): Pass subr argument to
- type_unification.
- * pt.c (do_function_instantiation): Ditto.
- * class.c (instantiate_type): Ditto.
+ * typeck.c (common_type): Fix the ARRAY_TYPE case so it
+ properly keeps track of const and volatile type modifiers.
- * search.c (get_base_distance): If BINFO is a binfo, use it and
- don't mess with its BINFO_INHERITANCE_CHAIN.
+Tue Apr 23 10:52:56 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (convert_to_reference): Fix temporary generation.
- If ambiguous, return error_mark_node.
+ * tree.c (cp_tree_equal): C++ version of simple_cst_equal.
+ * pt.c (comp_template_args): Use it.
- * init.c (build_new): Put back some necessary code.
+ * rtti.c (get_tinfo_fn, build_dynamic_cast, expand_*_desc): Call
+ assemble_external for artificial function decls.
-Thu Feb 17 15:39:47 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (cp_finish_decl): Oops.
- * init.c (build_new): Deal with array types properly.
+Mon Apr 22 17:28:27 1996 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (get_binfo): Become a shell for get_base_distance.
- (get_binfo_recursive): Lose.
- (get_base_distance_recursive): Find the path to the via_virtual base
- that provides the most access.
- (get_base_distance): Ditto.
+ * decl2.c (import_export_decl): Put static data member templates
+ into common storage, or make them weak, depending on whether they
+ are dynamically or statically initialized.
+ (get_sentry): New function.
+ (finish_file): Do import_export_decl for static data members before
+ building the init/fini functions. Don't init/fini a variable that's
+ EXTERNAL. Use a sentry for variables in common. Fix mismatching
+ push/pop_temp_slots.
+ * decl.c (cp_finish_decl): If DECL_NOT_REALLY_EXTERN, do the
+ expand_static_init thang.
+ * method.c (get_id_2): New function.
- * parse.y (explicit_instantiation): Syntax is 'template class
- A<int>', not 'template A<int>'.
+Mon Apr 22 15:32:45 1996 Bob Manson <manson@charmed.cygnus.com>
- * typeck.c (convert_for_initialization): Remove bogus warning.
+ * parse.y (empty_parms): Make sure we use C++-style prototypes
+ when we're declaring member functions.
- * parse.y (datadef): Revert patch of Oct 27.
+Sun Apr 21 10:08:22 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Feb 17 15:12:29 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * Makefile.in (CONFLICTS): 16 s/r conflicts.
+ * parse.y (self_template_type): New nonterminal.
- * class.c (build_vfn_ref): Cast delta field to ptrdiff_type_node,
- rather than integer_type_node. Does wonders for the Alpha.
+Thu Apr 18 08:56:54 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Feb 17 13:36:21 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (make_typename_type): Handle getting a TYPE_DECL for a
+ name.
+ * parse.y (base_class.1): Allow 'typename foo::bar'.
- * decl.c (build_ptrmemfunc_type): Make sure that the pmf type
- goes onto the same obstack as its target type.
+ * lex.c (check_newline): Remove #pragma code that plays with the
+ input stream, since we now deal with tokens. Clear nextchar when
+ we're done.
+ (handle_cp_pragma): Use real_yylex.
+ (handle_sysv_pragma): Don't do skipline here. Only call real_yylex
+ in one place.
-Wed Feb 16 00:34:46 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * lex.c (check_for_missing_semicolon): Handle SELFNAME.
- * cvt.c (convert_to_reference): If converting via constructor
- on local level, go back to build_cplus_new approach.
+ * lex.c (handle_cp_pragma): Fix "#pragma implementation".
- * tree.c (build_cplus_new): If with_cleanup_p, set cleanup slot
- to error_mark_node to prevent expand_expr from building a cleanup
- for this variable.
+Wed Apr 17 16:51:33 1996 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (default_assign_ref_body): Return *this from the memcpy
- version, too.
+ * parse.y: New token SELFNAME for potential constructor.
+ * spew.c (yylex): Handle it.
+ * lex.c (identifier_type): Produce it.
- * decl.c (grok_reference_init): Just return if called with
- error_mark_node, don't worry about initializing non-const reference
- with temporary.
+ * parse.y (complete_type_name): In :: case, don't push class binding.
+ (complex_type_name): Likewise.
- * cvt.c (convert_to_reference): Do the right thing for
- non-aggregate reference conversions, pedwarn when generating a
- non-const reference to a temporary.
+Wed Apr 17 15:02:40 1996 Mike Stump <mrs@cygnus.com>
- * class.c (finish_struct): TYPE_HAS_COMPLEX_{INIT,ASSIGN}_REF and
- TYPE_NEEDS_CONSTRUCTING all depend on TYPE_USES_VIRTUAL_BASECLASSES
- again.
+ * typeck.c (build_reinterpret_cast): Handle pointer to member
+ functions.
-Tue Feb 15 19:47:19 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Apr 17 12:28:26 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (grok_reference_init): Pawn off a lot of the work on
- convert_to_reference. Generally do the right thing.
+ * lex.c (handle_cp_pragma): New function, with decl, doing the cc1plus
+ pragmas.
+ (check_newline): Put the vtable/unit/implementation/interface pragma
+ code into handle_cp_pragma, replacing it with a call.
+ (handle_sysv_pragma): Give int return type, and take FINPUT and TOKEN
+ args. Get the next token after handling the pragma token.
- * cvt.c (convert_to_reference): Conform to the initial comment;
- i.e. don't create temps if decl != error_mark_node. Handle
- cleanups better for temps that do get created. Don't pretend
- that we can use an 'A' to initialize a 'const double &' just by
- tacking on a NOP_EXPR. Support LOOKUP_SPECULATIVELY.
+Wed Apr 17 10:28:34 1996 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Set TREE_HAS_CONSTRUCTOR on
- constructor calls.
+ * cvt.c (cp_convert_to_pointer): Avoid doing base analysis on pmfs.
+ (convert_to_pointer_force): Likewise.
-Mon Feb 14 14:50:17 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * init.c (build_new): Fix array new without -fcheck-new.
- * decl.c (grok_reference_init): Make a temporary for initializing
- const reference from constant expression.
+Tue Apr 16 13:44:58 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon Feb 14 11:31:31 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * cp-tree.h, call.c, class.c, decl.c, parse.y, pt.c, rtti.c,
+ tree.c: Lose TYPE_NESTED_NAME.
- * cp-tree.h, decl.c (set_identifier_local_value): Deleted function.
- * decl.c (pushdecl): Define decl in correct binding_level
- (which isn't always the inner_binding_level).
+ * parse.y (nested_name_specifier_1): Don't treat non-identifiers
+ as identifiers.
- * cvt.c (build_up_reference): Don't ever call expand_aggr_init.
- It's ugly, and I don't think it's the right thing to do.
+ * tree.def: Add VEC_INIT_EXPR.
+ * expr.c (cplus_expand_expr): Handle it.
+ * init.c (build_new): Use it instead of the RTL_EXPR nastiness and
+ the extra file-scope symbol nastiness.
- * cp-tree.h, class.c, decl.c, decl2.c, sp/search.c:
- Remove NEW_CLASS_SCOPING, assuming it is always 1.
- * decl.c (pop_decl_level): Removed; manually inlined.
+Mon Apr 15 16:21:29 1996 Jason Merrill <jason@yorick.cygnus.com>
-Sun Feb 13 19:04:56 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * method.c (make_thunk): Thunks are static.
+ (emit_thunk): Use ASM_OUTPUT_MI_THUNK if it's defined.
- * class.h (candidate): Add basetypes field.
+ * decl2.c (mark_vtable_entries): Emit thunks as needed.
+ (finish_file): Don't emit them here.
- * call.c (build_method_call): Do access checking after choosing a
- function, not before.
+Sun Apr 14 11:34:39 1996 Jason Merrill <jason@yorick.cygnus.com>
- * Makefile.in (cvt.o, call.o, method.o): Depend on class.h.
- (mostlyclean): Remove ../cc1plus.
+ * rtti.c (build_dynamic_cast): Handle null pointers.
+ (ifnonnull): New function.
-Fri Feb 11 11:52:26 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Apr 12 09:08:27 1996 Bob Manson <manson@charmed.cygnus.com>
- * class.c (finish_struct): Don't allow adjusting access to a field
- of a base class if a local field has the same name.
+ * call.c (build_method_call): Remember the original basetype we
+ were called with. Give an error message instead of trying
+ (incorrectly) to call a non-static member function through a
+ non-inherited class.
- * error.c (dump_type_prefix): Output basetype for METHOD_TYPEs.
+ * search.c (expand_upcast_fixups): Mark the new fixup as
+ DECL_ARTIFICIAL.
-hu Jan 13 17:55:51 EST 1994 Gnanasekaran Swaminathan (gs4t@virginia.edu)
+Thu Apr 11 03:57:09 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-tree.h (DESTRUCTOR_NAME_P): do not confuse AUTO_TEMP names
- with destructor names when either NO_DOLLAR_IN_LABEL or
- NO_DOT_IN_LABEL are not defined.
+ * init.c (build_new): Use a TARGET_EXPR for alloc_expr.
- Now `template <class T, T f(T&), const T*> class A {...}' works.
+ * class.c (set_rtti_entry): Fix for thunks.
- * pt.c (grok_template_type): substitute template parm types
- with actual types in complex type as well.
- (coerce_template_parms): update the grok_template_type ()
- function call.
+ * decl2.c (import_export_decl): Still emit typeinfo fns for
+ cv-variants of builtin types.
- * pt.c (tsubst): Traverse method list using DECL_CHAIN.
+ * rtti.c (expand_class_desc): Set up base_info_type_node here.
+ (init_rtti_processing): Instead of here.
- * decl.c (grok_op_properties): Allow operator++/-- to have
- default arguments.
+Wed Apr 10 14:17:13 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck2.c (store_init_value): Don't abort when called to
- initialize a type that needs constructing with a CONSTRUCTOR.
+ * rtti.c (init_rtti_processing): Do init regardless of -frtti.
+ (build_typeid): Only complain about taking dynamic typeid without
+ -frtti.
- * init.c (expand_aggr_init_1, CONSTRUCTOR case): If
- store_init_value fails, build and expand an INIT_EXPR. If
- store_init_value succeeds, call expand_decl_init.
+ * decl2.c: flag_rtti defaults to 1.
-Fri Feb 11 02:49:23 1994 Mike Stump <mrs@cygnus.com>
+ * rtti.c (get_tinfo_var): The general class case is now smaller.
+ (init_rtti_processing): Pack the latter three fields of base_info
+ into 32 bits.
- * class.c (build_vbase_path): Use complete_type_p instead of
- resolves_to_fixed_type_p to determine if the virtual bases are in
- their right place for the type of expr. Cures problem of thinking a
- virtual base class is one place, when it is in fact someplace else.
+Wed Apr 10 13:50:14 1996 Mike Stump <mrs@cygnus.com>
-Fri Feb 11 00:26:46 1994 Mike Stump <mrs@cygnus.com>
+ * init.c (expand_member_init): Don't dump if name is NULL_TREE.
- * init.c (resolve_offset_ref): Make sure we first convert to
- intermediate type, if given, when dealing with members off `this'.
- Solves an incorrrect `type `foo' is not a base type for type
- `multiple'' when it is infact, a base type.
+Wed Apr 10 12:56:02 1996 Mike Stump <mrs@cygnus.com>
-Thu Feb 10 21:49:35 1994 Mike Stump <mrs@cygnus.com>
+ * search.c (make_memoized_table_entry): Undefer the pop, if necessary.
+ (push_memoized_context): Split out code to undefer pop_type_level to
+ (clear_memoized_cache): here.
+ (pop_memoized_context): We can only handle one layer of deferral of
+ pop_type_level so clear the cache, if there was a previous level.
- * class.c (modify_other_vtable_entries): Use get_binfo, instead
- of binfo_value. Solves problem with compiler giving a `base class
- `B' ambiguous in binfo_value (compiler error)' on complex MI
- herarchies, when a virtual function is first defied in a virtual
- base class.
+Tue Apr 9 23:06:09 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Feb 10 17:19:32 1994 Mike Stump <mrs@cygnus.com>
+ * rtti.c (init_rtti_processing): Build up base_info_type_node.
+ (expand_class_desc): Use one pointer to an array of base_info
+ structs, passed using a CONSTRUCTOR.
- * class.c (build_vbase_path): Don't complain about ambiguous
- intermediate conversion when converting down to a virtual base
- class, even if they might seem to be ambiguous.
+Tue Apr 9 14:20:57 1996 Mike Stump <mrs@cygnus.com>
-Thu Feb 10 12:18:26 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * class.c (build_vbase_path): Remove block extern for
+ flag_assume_nonnull_objects here.
+ (build_vfn_ref): Split out functionality into build_vtbl_ref.
+ (build_vtbl_ref): New routine.
+ (build_vtable): Set up rtti info here.
+ (add_virtual_function): Note in CLASSTYPE_RTTI the best
+ place where we can get the rtti pointers from to avoid having to
+ search around for a place.
+ (finish_base_struct): Likewise.
+ (finish_struct_1): Likewise. Never create totally new vtables
+ with totally new vtable pointers for rtti. Disable code to layout
+ vtable pointers better until we want to break binary
+ compatibility.
+ * rtti.c (build_headof_sub): New routine to convert down to a
+ sub-object that has an rtti pointer in the vtable.
+ (build_headof): Use it. Also, use build_vtbl_ref now to be more
+ maintainable.
+ (build_dynamic_cast): Make sure we have saved it, if we need to.
+ * search.c (dfs_init_vbase_pointers): Disable code that deals with
+ a more efficient vtable layout, enable later.
+ * call.c (flag_assume_nonnull_objects): Moved declaration to
+ * cp-tree.h: here. Declare build_vtbl_ref.
+ * pt.c (instantiate_class_template): Use NULL_TREE instead of 0 in
+ function calls that want a tree.
- * typeck2.c (build_functional_cast): #if 0 out constructor
- inheritance code, improve error messages.
+Tue Apr 9 12:10:26 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_base_struct): Complain about base with only
- non-default constructors in derived class with no constructors.
+ * rtti.c (build_dynamic_cast): Handle downcasting to X* given
+ other X subobjects in the most derived type. Ack.
- * decl.c (grokdeclarator): Fix detection of virtual new/delete.
+ * rtti.c (build_dynamic_cast): No need to strip cv-quals here,
+ get_typeid will do it for us.
+ (get_typeid_1): Break out call-building for expand_*_desc to use.
+ (get_typeid): Call it.
+ (expand_*_desc): Likewise.
+ * decl.c (init_decl_processing): Don't set TYPE_BUILT_IN on char *
+ and void *.
+ (init_decl_processing): Lose builtin_type_tdescs lossage.
+ * decl2.c (finish_vtable_vardecl): Remove obsolete code.
-Wed Feb 9 22:02:32 1994 Mike Stump <mrs@cygnus.com>
+Mon Apr 8 17:23:23 1996 Bob Manson <manson@charmed.cygnus.com>
- * search.c (build_mi_virtuals, add_mi_virtuals,
- report_ambiguous_mi_virtuals): Removed unneeded code.
- * class.c (finish_struct_bits): Ditto.
+ * pt.c (tsubst): When calling set_nested_typename, use
+ TYPE_NESTED_NAME (current_class_type) instead of
+ current_class_name.
-Wed Feb 9 11:27:17 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (pushdecl): Likewise.
+ (pushdecl_class_level): Likewise.
+ (grokdeclarator): Use NULL_TREE instead of 0 in the call to
+ set_nested_typename.
+
+Sun Apr 7 10:44:31 1996 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (end_template_instantiation): Push decl before
- pop_from_top_level.
+ * rtti.c (synthesize_tinfo_fn): Handle arrays.
+
+ * cp-tree.h (DECL_REALLY_EXTERN): New macro.
+
+Sat Apr 6 13:56:27 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * rtti.c (throw_bad_cast): Use entry point __throw_bad_cast.
+ (init_rtti_processing): Lose bad_cast_type.
+ (build_dynamic_cast): Use throw_bad_cast.
+
+ * rtti.c (synthesize_tinfo_fn): Handle enums and pmfs.
+
+ * decl2.c (finish_file): Don't synthesize artificial functions
+ that are external and not inline.
+
+ * rtti.c (get_tinfo_fn): If at_eof, call import_export_decl.
+
+ * decl2.c (finish_file): Handle having new inlines added to
+ saved_inlines by synthesis.
+
+ * rtti.c (get_bad_cast_node): Don't require <typeinfo>.
+
+Fri Apr 5 17:02:09 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ RTTI rewrite to initialize nodes as needed, not require that
+ users #include <typeinfo>, complete functionality and reduce wasted
+ space.
+ * rtti.c (init_rtti_processing): New fn.
+ (build_typeid): The vtable entry is now a function.
+ (get_tinfo_var): New fn.
+ (get_tinfo_fn): Likewise.
+ (get_typeid): Use it.
+ (build_dynamic_cast): Declare and use entry point __dynamic_cast.
+ (build_*_desc): Rename to expand_*_desc and rewrite to use entry
+ points __rtti_*.
+ (add_uninstantiated_desc, get_def_to_follow, build_t_desc): Lose.
+ (synthesize_tinfo_fn): New fn.
+ * method.c (build_t_desc_overload): Lose.
+ (build_overload_with_type): More generic.
+ * decl.c (init_decl_processing): Call init_rtti_processing.
+ * class.c (set_rtti_entry): Use get_tinfo_fn.
+ * decl2.c (mark_vtable_entries): Mark the rtti function.
+ (finish_prevtable_vardecl): Don't build_t_desc.
+ (import_export_decl): Handle tinfo functions.
+ (finish_file): Likewise.
+ * typeck.c (inline_conversion): New fn.
+ (build_function_call_real): Use it.
+ * cp-tree.h: Add decls.
+
+ * method.c (hack_identifier): Also convert component_refs from
+ references.
- * typeck2.c (build_m_component_ref): Make sure datum is of
- aggregate type.
+ * lex.c (cons_up_default_function): Use the type, not the name, in
+ declspecs.
- * init.c (get_type_value): New function, returns
- IDENTIFIER_TYPE_VALUE or IDENTIFIER_CLASS_TYPE_VALUE or NULL_TREE.
+ * decl2.c (import_export_vtable): Fix weak vtables.
- * call.c (build_method_call): Don't die on call to destructor for
- non-type.
+Fri Apr 5 13:30:17 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (grokdeclarator): Complain about virtual op new and op
- delete, make static virtuals unvirtual instead of unstatic.
+ * search.c (get_base_distance_recursive): Fix access checks for
+ protected bases.
- * typeck.c (build_c_cast): Also call default_conversion on
- methods.
+Fri Apr 5 11:02:06 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (grokdeclarator): Don't complain about anonymous
- bitfields.
+ * call.c (unary_complex_lvalue): Delete unneeded decl, it's in
+ cp-tree.h.
+ (convert_harshness): Add prototypes wrapped by PROTO.
+ * decl2.c (grok_function_init): Likewise.
+ (do_toplevel_using_decl): Change to void return type.
+ * class.c (build_vtable_entry): Remove decl of make_thunk.
+ (merge_overrides): Fix order of arg definitions.
+ (finish_vtbls): Likewise.
+ (fixup_vtable_deltas): Likewise.
+ (modify_all_direct_vtables): Likewise.
+ (modify_all_indirect_vtables): Likewise.
+ * search.c (get_base_distance_recursive): Likewise.
+ (get_abstract_virtuals_1): Likewise.
+ (fixup_virtual_upcast_offsets): Likewise.
+ (lookup_fnfields_1): Add prototypes wrapped by PROTO.
+ * init.c (perform_member_init): Fix order of arg definitions.
+ (expand_aggr_init_1): Add prototypes wrapped by PROTO.
+ * cp-tree.h (make_thunk): Add decl.
+ (overload_template_name, push_template_decl): Add decls.
+ (do_toplevel_using_decl): Change to void return type.
+ (vec_binfo_member): Add decl.
- * parse.y (simple_stmt, for loops): Move the continue point after
- the cleanups.
+Thu Apr 4 13:33:10 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * class.c (finish_struct): Fix setting of
- TYPE_HAS_COMPLEX_INIT_REF.
+ * typeck.c (mark_addressable, convert_for_assignment,
+ convert_for_initialization, pointer_int_sum, pointer_diff,
+ unary_complex_lvalue): Add prototypes wrapped by PROTO.
+ (convert_sequence): #if 0 fn decl, since definition also is.
-Tue Feb 8 13:21:40 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Apr 4 11:00:53 1996 Mike Stump <mrs@cygnus.com>
- * init.c (build_new): Deal with `new double (1)'.
+ * rtti.c (build_dynamic_cast): Make sure we strip qualifiers on
+ cast to pointer types for type searching.
- * class.c (finish_struct): TYPE_HAS_COMPLEX_*_REF are supersets of
- TYPE_HAS_REAL_*_REF, but TYPE_HAS_COMPLEX_INIT_REF is independent of
- TYPE_NEEDS_CONSTRUCTING.
+Wed Apr 3 17:10:57 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (duplicate_decls): Propagate access decls.
+ * typeck.c (get_delta_difference): Use cp_error, not error, in the
+ case where BINFO == 0.
- * typeck2.c (process_init_constructor): Accept empty_init_node
- for initializing unions.
+Wed Apr 3 12:01:02 1996 Mike Stump <mrs@cygnus.com>
- * class.c, lex.c, cp-tree.h: Use
- TYPE_HAS_COMPLEX_ASSIGN_REF where TYPE_HAS_REAL_ASSIGN_REF was used
- before, use TYPE_HAS_COMPLEX_INIT_REF for TYPE_NEEDS_CONSTRUCTING in
- some places.
+ * call.c (build_method_call): Fix wording of error messages so
+ constructors come out right.
- * decl.c (finish_decl): Don't complain about uninitialized const
- if it was initialized before.
+Tue Apr 2 16:06:59 1996 Bob Manson <manson@charmed.cygnus.com>
-Mon Feb 7 18:12:34 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (push_overloaded_decl): Don't warn about hidden
+ constructors when both the type and the function are declared
+ in a system header file.
- * lex.c (default_assign_ref_body): Don't deal with vbases for
- now.
+Mon Apr 1 09:03:13 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (finish_decl): Fix reversed logic for objects and other
- things that need to be constructed but have no initializer.
+ * class.c (finish_struct_1): Propagate the TYPE_PACKED
+ flag for the type to the type's fields.
- * class.c (finish_struct): Don't set TYPE_HAS_* flags that are
- set by grok_op_properties or finish_decl.
+Sat Mar 30 12:14:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c: Don't warn about extern redeclared inline unless
- -Wextern-inline is given.
- * decl2.c (lang_decode_option): Ditto.
- * cp-tree.h: Ditto.
+ * parse.y (complex_parmlist, ELLIPSES): Take out ARM-based warning.
-Mon Feb 7 17:29:24 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Fri Mar 29 15:51:36 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (pushdecl_with_scope): Fix thinko. Add forward
- declaration.
+ * class.c (base_info, finish_base_struct): Replace
+ needs_virtual_dtor with base_has_virtual.
- * decl.c (pushdecl_with_scope): New function.
- * decl.c (pushdecl_top_level): Use new function.
- * decl.c (pushtag): Initialize newdecl.
- * decl.c (pushtag): Push new type decl into correct scope.
+ (finish_struct_1): Remove the old code that tried to make default
+ destructors virtual. Use base_has_virtual when checking if we need
+ to add a vtable entry for the rtti code.
-Mon Feb 7 14:42:03 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Mar 29 14:02:36 1996 Jason Merrill <jason@yorick.cygnus.com>
- * call.c, cvt.c, init.c, search.c, cp-tree.h:
- Eradicate LOOKUP_PROTECTED_OK.
+ * pt.c (push_template_decl): Complain about template decl with
+ inappropriate declaration.
-Mon Feb 7 13:57:19 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Fri Mar 29 12:15:35 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (pushtag, xref_tag), cp-tree.h: Add extra parameter
- 'globalize' to signify implicit declarations.
- * decl.c (globalize_nested_type, maybe_globalize_type): Removed.
- * decl.c (set_identifier_type_value_with_scope): New function.
- * decl.c (set_identifier_local_value): Simplify.
- * spew.c (yylex, do_addr): Modify to return a _DEFN if a
- forward declaration (followed by ';' and not preceded by 'friend').
- * class.c, decl.c, except.c, init.c, parse.y,
- pt.c, search.c: Add new argument to calls to xref_tag and
- pushtag.
+ * typeck.c (build_x_unary_op): Remove bogus check for taking
+ the address of a member function.
-Mon Feb 7 00:22:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Mar 29 11:56:02 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-tree.h (ACCESSIBLY_UNIQUELY_DERIVED_P): New macro, means what
- ACCESSIBLY_DERIVED_FROM_P meant before.
- (ACCESSIBLY_DERIVED_FROM_P): Now disregards ambiguity.
+ * parse.y (constructor_declarator): Only push the class if
+ we are not already in the class.
- * cvt.c (build_up_reference): Call get_binfo with PROTECT == 1.
+Fri Mar 29 09:41:02 1996 Jeffrey A. Law <law@cygnus.com>
- * search.c (get_base_distance_recursive): Members and friends of
- a class X can implicitly convert an X* to a pointer to a private or
- protected immediate base class of X.
- (get_binfo_recursive): Ditto.
- (get_base_distance): Ignore ambiguity if PROTECT < 0.
- (get_binfo): Lose multiple values of PROTECT.
- (compute_access): Protected is OK if the start of the
- search is an accessible base class of current_class_type.
+ * method.c (emit_thunk): Remove current_call_is_indirect nonsense.
+ Add additional argument to INIT_CUMULATIVE_ARGS.
- * method.c (build_opfncall): Do check access on operator new here.
+Thu Mar 28 16:41:39 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (finish_function): Don't check access on operator new
- here.
+ * decl.c (shadow_tag): Fix error about anon union with methods.
-Sun Feb 6 14:06:58 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * parse.y (self_reference): Only generate a self-reference if this
+ is a non-template class.
+ (opt.component_decl_list): Only use it if it was generated.
- * decl.c (xref_tag): The base of a derived struct is NOT always
- public. Duh.
+ * parse.y (component_decl_1): Use constructor_declarator.
+ (fn.def2): Likewise.
+ (notype_component_declarator0): Likewise.
- * pt.c (do_explicit_instantiation): New function, called from
- parser to do explicit function instantiation.
- (type_unification): Allow the args list to be terminated with
- void_list_node.
- (do_pending_expansions): Look at i->interface for non-member
- templates.
+Thu Mar 28 15:11:35 1996 Bob Manson <manson@charmed.cygnus.com>
- * parse.y (datadef): Move explicit_instantiation here.
- (structsp): From here.
- (datadef): Complain about `int;'.
+ * typeck.c (build_x_unary_op): Add checks for taking the address
+ of a TARGET_EXPR or of a member function, and give appropriate
+ warnings.
-Sun Feb 6 12:33:18 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Thu Mar 28 14:49:26 1996 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (end_template_instantiation), cp-tree.h: Remove unused
- second parameter, and simplify first from a TREE_LIST where
- we only care about its TREE_VALUE to just the value (an IDENTIFIER).
- * pt.c (instantiate_member_templates): Simplify argument list
- from a TREE_LIST to just an IDENTIFIER.
- * lex.c (yyprint): PRE_PARSED_CLASS_DECL is now just an IDENTIFIER.
- * parse.y (template_instantiate_once): Simplify accordingly.
- * decl.c (inner_binding_level): New. Use various places to
- simplify.
+ * pt.c (process_template_parm): Allow template type parms to be
+ used as types for template const parms.
-Sun Feb 6 02:49:37 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Mar 27 15:51:19 1996 Mike Stump <mrs@cygnus.com>
- * typeck2.c (build_functional_cast): int() -> int(0).
+ * init.c (expand_vec_init): Ensure the eh cleanups are on the
+ function_obstack.
-Sat Feb 5 00:53:21 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Mar 27 10:14:30 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Don't do a bitwise copy for op= if the
- class has a virtual function table.
+ * decl.c (lookup_name_real): Be even more picky about the
+ ambiguous lookup warning.
+ (grokdeclarator): Tweak SCOPE_REF constructor declarators here.
+ * parse.y (constructor_declarator): Rather than here.
- * typeck.c (convert_for_initialization): Restore warnings about
- not using defined op=. Should really be my_friendly_aborts, I
- s'pose.
+ * parse.y (constructor_declarator): New nonterminal.
+ (fn.def1): Use it.
+ (explicit_instantiation): Likewise.
-Fri Feb 4 14:21:00 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Mar 26 13:41:33 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Tidy up conditions for doing bitwise
- copies of objects.
+ Add implicit declaration of class name at class scope.
+ * decl.c (lookup_name_real): Restrict pedwarn about ambiguous lookup.
+ * parse.y (self_reference): New nonterminal.
+ (opt.component_decl_list): Use it.
+ (fn.def1): Add nested_name_specifier type_name cases.
+ * class.c (build_self_reference): New function.
+ (finish_struct): Handle access_default later, move self-reference
+ decl to the end.
+ * pt.c (lookup_template_class): Handle getting a TYPE_DECL.
+ * cp-tree.h: Adjust.
- * decl.c (build_default_constructor): #if 0 out.
+ * pt.c (do_function_instantiation): Separate handling of member
+ functions and non-member functions properly.
- * *: Eradicate TYPE_GETS_{ASSIGNMENT,ASSIGN_REF,CONST_ASSIGN_REF,
- CONST_INIT_REF}, TYPE_HAS_REAL_CONSTRUCTOR.
+Mon Mar 25 14:23:22 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Don't return void_type_node for
- friends being defined here.
+ * pt.c (process_template_parm): Improve error for 'volatile class K'.
- * init.c (perform_member_init): Only do the init if it's useful.
+ * class.c (finish_struct_1): Check the right slot for destructors.
- * lex.c (default_copy_constructor_body): If we don't need to do
- memberwise init, just call __builtin_memcpy.
- (default_assign_ref_body): Ditto.
+ * decl.c (start_enum): Complain about enum templates.
- * decl.c (grokdeclarator): If friendp && virtualp, friendp = 0.
+Mon Mar 25 13:25:31 1996 Mike Stump <mrs@cygnus.com>
-Fri Feb 4 13:02:56 1994 Mike Stump <mrs@cygnus.com>
+ * init.c (resolve_offset_ref): Offset pointers to member data by one.
+ * typeck.c (unary_complex_lvalue): Likewise.
- * lex.c (reinit_parse_for_method, cons_up_default_function):
- Don't give warn_if_unknown_interface warning when it came from a
- system header file.
- * pt.c (end_template_decl, instantiate_template): Ditto.
- * decl.c (start_decl): Ditto.
+Mon Mar 25 13:30:42 1996 Bob Manson <manson@charmed.cygnus.com>
-Fri Feb 4 00:41:21 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (c_expand_return): Check for a returned local
+ array name, similar to the check for an ADDR_EXPR.
- * decl.c (grokdeclarator): Don't try to set TYPE_WAS_ANONYMOUS on
- enums.
+Mon Mar 25 13:07:19 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (constructor_name_full): Use IS_AGGR_TYPE_CODE instead of
- IS_AGGR_TYPE, since we don't know it's a type.
+ * decl.c (cp_finish_decl): Don't build cleanups for static
+ variables here.
-Thu Feb 3 11:36:46 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Mar 22 17:57:55 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (grokdeclarator): Don't complain about anonymous unions.
+ * typeck.c (build_modify_expr): Fix error messages to be more
+ accurate.
+ * cp-tree.h (assop_as_string): Parallel to op_as_string, but for
+ assignment operators.
+ * error.c (assop_as_string): Likewise. Add support for `%Q' for
+ assignment operators.
- * cp-tree.h (TYPE_WAS_ANONYMOUS): This struct was originally
- anonymous, but had a name given to it by a typedef.
+Fri Mar 22 13:48:29 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): When renaming an anonymous struct, set
- TYPE_WAS_ANONYMOUS.
+ * decl.c (grokdeclarator): Call bad_specifiers for typedefs. Also
+ give an error if initialized. Pedwarn about nested type with the
+ same name as its enclosing class.
- * decl2.c (constructor_name_full): Use TYPE_WAS_ANONYMOUS.
+ * pt.c (tsubst, case TYPE_DECL): Set DECL_CONTEXT.
- * cp-tree.h (DECL_UNDEFINED_FRIENDS): #if 0 out.
+ * typeck.c (require_complete_type): Be sure to instantiate the
+ MAIN_VARIANT of the type.
- * init.c (xref_friend): Don't set up DECL_UNDEFINED_FRIENDS.
- (embrace_waiting_friends): Don't use DECL_UNDEFINED_FRIENDS.
-
- * decl.c (grokdeclarator): Set TYPE_NESTED_NAME properly on nested
- anonymous structs that get typedef'd.
+ * decl2.c (finish_file): Instantiate pending templates before
+ processing static constructors and destructors.
- * decl.c (grokdeclarator): Always return void_type_node for
- friends.
+ * pt.c (instantiate_decl): Don't instantiate functions at toplevel
+ unless at_eof.
- * error.c (dump_function_decl): Don't use DECL_CLASS_CONTEXT for
- friends.
- (dump_function_decl): Don't print out default args for
- a function used in an expression.
+Fri Mar 22 09:30:17 1996 Bob Manson <manson@beauty.cygnus.com>
- * decl.c (grokdeclarator): Give error on abstract declarator used
- in an invalid context (i.e. `void (*)();').
+ * decl2.c (delete_sanity): If error_mark_node is passed
+ in as an expression, quit while we're ahead.
- * error.c (cp_line_of): Support _TYPE nodes.
- (cp_file_of): Ditto.
+ * decl.c (grokdeclarator): Give an error message if `friend'
+ is combined with any storage class specifiers.
- * cvt.c (build_up_reference): Don't abort if passed a SAVE_EXPR;
- it can happen for the RHS of an assignment stmt where the LHS is
- a COND_EXPR.
+Wed Mar 20 14:51:55 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (expand_aggr_init_1): Deal with bracketed initializer
- lists properly.
+ * parse.y (named_complex_class_head_sans_basetype): Don't crash on
+ definition of nonexistent nested type.
- * class.c (finish_struct): Deal with enumerators and typedefs
- again.
+ * error.c (dump_decl, case TYPE_DECL): Fix decision for whether or
+ not to say 'typedef'.
-Wed Feb 2 11:30:22 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Mar 20 00:11:47 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * class.c (finish_struct): Tidy up loop over fields.
+ * cp-tree.h (struct lang_type): Make search_slot a tree, not a char*.
+ * search.c (dfs_walk, dfs_init_vbase_pointers,
+ expand_upcast_fixups): Remove cast of CLASSTYPE_SEARCH_SLOT.
+ (dfs_find_vbases): Remove cast for CLASSTYPE_SEARCH_SLOT init.
- * errfn.c (cp_thing): Don't advance twice after a format.
+Tue Mar 19 17:56:03 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Complain about needing a constructor
- if a member has only non-default constructors, and don't try to
- generate a default constructor.
+ * except.c (build_throw): Support minimal parse.
+ * pt.c (tsubst_copy): Support THROW_EXPR.
+ * decl2.c (build_expr_from_tree): Likewise.
- * decl.c (finish_decl): Also do the constructor thing if
- TYPE_NEEDS_CONSTRUCTING is set (for arrays).
+ * pt.c (mangle_class_name_for_template): Always allocate
+ scratch_firstobj.
- * search.c (unuse_fields): New function: mark all fields in this
- type unused.
- (dfs_unuse_fields): Helper function.
+Tue Mar 19 16:34:31 1996 Bob Manson <manson@beauty.cygnus.com>
- * class.c (pushclass): If the new class is the same as the old
- class, still unuse the fields.
- (unuse_fields): Move to search.c.
+ * cvt.c (cp_convert_to_pointer): Give an appropriate error
+ when trying to cast from an incomplete type.
- * decl.c (grok_op_properties): Add friendp argument.
- (grokfndecl): Pass it.
- (start_method): Ditto.
+Tue Mar 19 16:00:33 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (delete_sanity): Add use_global_delete parameter to catch
- ::delete calls.
+ * pt.c (instantiate_class_template): Don't bother setting up
+ CLASSTYPE_TAGS explicitly, as the nested types will add
+ themselves.
- * parse.y (unary_expr): Pass new parameter to delete_sanity.
+Tue Mar 19 15:48:43 1996 Bob Manson <manson@beauty.cygnus.com>
- * lex.c (default_copy_constructor_body): Don't choke if the union
- has no fields.
- (default_assign_ref_body): Ditto.
+ * decl.c (shadow_tag): Remove old error check for usage of
+ an enum without a previous declaration.
+ (xref_tag): Add error message about usage of enums without a
+ previous declaration.
- * call.c (compute_conversion_costs_ansi): Do the right thing for
- ellipsis matches.
+Tue Mar 19 09:21:35 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (push_to_top_level): Optimize.
+ * lex.c (do_identifier): Only do name consistency check if we're
+ parsing.
- * decl.c (start_function): Look for the lexical scope of a friend
- in DECL_CLASS_CONTEXT.
+ * pt.c (push_template_decl): Don't crash if we get a member defn
+ that doesn't match.
- * init.c (do_friend): Set DECL_CLASS_CONTEXT on global friends.
+ * decl.c (xref_tag_from_type): New function to do an xref without
+ always having to figure out code_type_node.
+ * cp-tree.h: Declare it.
+ * pt.c (instantiate_class_template): Use it for friend classes.
+ (lookup_template_class): Use it.
-Tue Feb 1 15:59:24 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck2.c (build_functional_cast): Pull out a single parm before
+ passing it to build_c_cast.
- * cp-tree.h (TREE_GETS_PLACED_NEW): New macro.
+Tue Mar 19 09:07:15 1996 Bob Manson <manson@beauty.cygnus.com>
- * init.c (init_init_processing): Don't assign BIN/BID to the
- IDENTIFIER_GLOBAL_VALUEs of their respective operators.
- (build_new): Check TREE_GETS_PLACED_NEW.
+ * expr.c (do_case): Give an error message if a pointer is
+ given as a case value.
- * decl.c (grok_op_properties): Don't set TREE_GETS_NEW for a decl of
- op new with placement, set TREE_GETS_PLACED_NEW.
+Mon Mar 18 21:57:54 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-tree.h (ANON_UNION_P): New macro. Applies to decls.
+ * typeck.c (build_c_cast): Don't pull single TEMPLATE_DECL out of
+ an overload list.
- * class.c (finish_struct): Don't treat anonymous unions like
- other aggregate members. Do synthesize methods for unions without
- a name, since they may or may not be "anonymous unions".
+ * lex.c (cons_up_default_function): Really, now, interface hackery
+ does not apply to synthesized methods.
- * decl2.c (grok_x_components): Wipe out memory of synthesized methods
- in anonymous unions.
+Mon Mar 18 18:20:57 1996 Mike Stump <mrs@cygnus.com>
- * lex.c (default_copy_constructor_body): Support unions.
- (default_assign_ref_body): Ditto.
+ * call.c (build_method_call): Ctors and dtors now have special names
+ with respect to lookups.
+ * class.c (add_method): Likewise.
+ (grow_method): Likewise.
+ (finish_struct_methods): Likewise.
+ (warn_hidden): Likewise.
+ (finish_struct_1): Likewise.
+ * cvt.c (convert_to_reference): Likewise.
+ (convert_to_aggr): Likewise.
+ (cp_convert): Likewise.
+ * decl2.c (check_classfn): Likewise.
+ * init.c (expand_member_init): Likewise.
+ (expand_default_init): Likewise.
+ (expand_aggr_init_1): Likewise.
+ (build_offset_ref): Likewise.
+ (build_new): Likewise.
+ (build_delete): Likewise.
+ * lex.c (do_inline_function_hair): Likewise.
+ * search.c (lookup_field_1): Likewise.
+ (lookup_fnfields_here): Likewise.
+ (lookup_field): Likewise.
+ (lookup_fnfields): Likewise.
+ (get_virtual_destructor): Likewise.
+ (dfs_debug_mark): Likewise.
+ (dfs_pushdecls): Likewise.
+ (dfs_compress_decls): Likewise.
+ * tree.c (layout_basetypes): Likewise.
+ * typeck.c (build_component_ref): Likewise.
+ (build_x_function_call): Likewise.
+ (build_modify_expr): Likewise.
+ (convert_for_initialization): Likewise.
+ (build_functional_cast): Likewise.
+ * cp-tree.h (CLASSTYPE_FIRST_CONVERSION): Likewise.
+ (CTOR_NAME): New.
+ (DTOR_NAME): New.
+ * decl.c (ctor_identifier): New.
+ (dtor_identifier): New.
+ (init_decl_processing): Set them.
+
+Mon Mar 18 18:00:51 1996 Mike Stump <mrs@cygnus.com>
+
+ * typeck.c (build_component_ref): Don't get confused by fields whose
+ context has no type name, like pointer to member functions.
+
+Mon Mar 18 13:19:03 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokdeclarator): Handle typedef without declarator.
+
+ * pt.c (tsubst): Handle SCOPE_REF in declarator.
+
+ * parse.y (bad_parm): Catch another case of missing `typename'.
+
+ * lex.c (yyprint): Handle TYPE_DECLs.
+
+ * decl.c (start_function): Don't try to be clever.
+
+ * lex.c: Lose compiler_error_with_decl.
+ * typeck2.c: Lose error_with_aggr_type.
+ (incomplete_type_error): Use cp_* instead of old functions.
+ (readonly_error): Likewise.
+ * typeck.c (convert_arguments): Likewise.
+ * search.c (lookup_nested_field): Likewise.
+ * method.c (make_thunk): Likewise.
+ * decl.c (grokparms): Likewise.
+ * cp-tree.h: Update.
-Mon Jan 31 12:07:30 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * tree.c (min_tree_cons): Call copy_to_permanent for the purpose
+ and value.
- * cp-tree.h: Fix documentation of LOOKUP_GLOBAL, add prototypes.
+Mon Mar 18 11:25:52 1996 Bob Manson <manson@beauty.cygnus.com>
- * error.c (args_as_string): New function (%A), like type_as_string
- except NULL_TREE -> "..."
+ * method.c (build_opfncall): When deleting a pointer to an
+ array, build a new pointer to the tree past any ARRAY_TYPE
+ nodes.
- * call.c (build_overload_call_real): Fix for new overloading.
+Mon Mar 18 10:11:46 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (grok_op_properties): Set all of the TYPE_OVERLOADS_* flags
- here.
+ * decl.c (lookup_name_real): Initialize local var TYPE to NULL_TREE.
- * parse.y (operator_name): Instead of here.
+Fri Mar 15 11:03:57 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck2.c (build_functional_cast): Treat a TREE_LIST as a list
- of functions.
+ * pt.c (instantiate_decl): Only call import_export_decl if at_eof
+ and ! DECL_INLINE.
- * call.c (build_overload_call_real): Support LOOKUP_SPECULATIVELY.
+ * decl.c (finish_function): Don't set nested based on
+ hack_decl_function_context.
+ * parse.y (function_try_block): Check for nested function.
+ (pending_inlines): Likewise.
- * method.c (build_opfncall): Don't need to massage return value
- any more, call build_overload_call with all flags.
+ * decl2.c (build_expr_from_tree): If a unary op already has a
+ type, just return it.
- * typeck.c (build_x_binary_op): Put back speculative call to
- build_opfncall.
- (build_x_unary_op): Ditto.
- (build_x_conditional_expr): Ditto.
+ * decl2.c (finish_prevtable_vardecl): Use ADJUST_VTABLE_LINKAGE.
-Mon Jan 31 10:00:30 1994 Mike Stump <mrs@cygnus.com>
+ * decl2.c (walk_vtables): vardecl_fn returns int; return 1 if it does.
+ (finish_file): Check the return value of walk_vtables.
+ (finish_prevtable_vardecl): Return int.
+ (finish_vtable_vardecl): Likewise.
+ (prune_vtable_vardecl): Likewise.
+ * lex.c (set_vardecl_interface_info): Likewise.
+ * cp-tree.h: Adjust return types.
- * cvt.c (build_type_conversion_1): Change call to pedwarn into
- warning, and conditionalize upon warn_cast_qual.
+ * class.c (delete_duplicate_fields_1): Don't complain about
+ duplicate nested types if they're the same type.
+ (finish_struct): Remove check for duplicate.
+ * decl2.c (grokfield): Don't check for typedef of anonymous type.
-Fri Jan 28 11:48:15 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Mar 14 10:00:19 1996 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (lookup_field): If xbasetype is a binfo, copy it to
- avoid clobbering its inheritance info.
+ * cp-tree.h: Lose SIGNATURE_GROKKING_TYPEDEF.
- * call.c (build_method_call): Don't overwrite basetype_path with
- TYPE_BINFO (inst_ptr_basetype) if they have the same type.
+ * decl.c (grokdeclarator): Lose special handling of class-level
+ typedef. Lose SIGNATURE_GROKKING_TYPEDEF. Set
+ SIGNATURE_HAS_OPAQUE_TYPEDECLS later.
- * search.c (compute_access): Fix handling of protected inheritance
- and friendship with the enclosing class.
+ * cvt.c (convert_pointer_to_real): Retain cv-quals in conversion.
- * typeck2.c (store_init_value): Allow passing of TREE_CHAIN for
- initialization of arbitrary variable.
+ * pt.c (tsubst_copy): Strip cv-quals from destructor name types.
- * typeck2.c (build_functional_cast): Only try calling a method if
- one exists.
+ * search.c (compute_access): Fix handling of anonymous union
+ members.
+ * class.c (finish_struct_anon): Propagate TREE_{PRIVATE,PROTECTED}
+ from anonymous unions to their members.
- * decl.c (grokdeclarator): Move handling of constructor syntax
- initialization into first loop for generality.
- (parmlist_is_random): Lose.
+ * typeck.c (build_x_function_call): For static member functions,
+ hand off to build_member_call.
- * lex.c (cons_up_default_function): Set TREE_PARMLIST on arguments
- to default function.
+Wed Mar 13 14:03:34 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jan 27 19:26:51 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (build_component_ref): Handle OFFSET_REFs.
- * decl.c (grokparms): Abort if we get called with something we don't
- expect.
+ * init.c (expand_vec_init): Fix init == 0 case.
-Thu Jan 27 17:37:25 1994 Mike Stump <mrs@cygnus.com>
+Tue Mar 12 14:36:02 1996 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_overload_call_real): Change argument complain to
- flags to match style of rest of code. Pass it down to
- build_function_call_real as necessary.
- * call.c (build_overload_call, build_overload_call_maybe): Change
- argument complain to flags to match style of rest of code.
- * cp-tree.h (build_function_call_real): Added fourth flags
- argument.
- * cvt.c (convert_to_reference): Only give warning messages, if
- LOOKUP_COMPLAIN is set.
- * typeck.c (build_x_function_call): Change simple complain
- argument to build_overload_call_maybe and build_overload_call, to
- LOOKUP_COMPLAIN to match style of rest of code.
- * typeck2.c (build_functional_cast): Ditto.
- * typeck.c (build_function_call_real): Add flags, so that we can
- not complain, if we don't want to complain. Complain about
- arguments, if we are complaining, otherwise don't.
- * typeck.c (build_function_call, build_function_call_maybe):
- Stick in flags argument.
- * typeck.c (build_x_binary_op, build_x_unary_op,
- build_x_conditional_expr, build_x_compound_expr): Follow style of
- build_x_indirect_ref, as it is more correct and more common.
+ * init.c (build_new): Pedwarn about init and array new.
+ (expand_vec_init): Handle lists, use convert_for_initialization.
-Thu Jan 27 14:36:20 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (convert_for_initialization): Pass LOOKUP_NO_CONVERSION
+ when converting to an aggregate type.
+ * cvt.c (cp_convert): Pass it through.
- * call.c (build_method_call): Don't check for being called with
- a pointer.
+ * typeck.c (build_conditional_expr): Handle user-defined
+ conversions to slightly different types.
- * decl2.c (finish_file): Don't play with DECL_CLASS_CONTEXT for the
- static initializer function.
+ * decl.c (grokdeclarator): Force an array type in a parm to be
+ permanent.
- * init.c (build_member_call): Use convert_force here, too.
+ * decl2.c (do_using_directive): Sorry.
+ (do_namespace_alias): Likewise.
+ * lex.c (real_yylex): Warn about using the `namespace' keyword.
- * search.c (compute_access): Only treat static members specially
- if they are referenced directly.
+Sun Mar 10 22:26:09 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jan 26 18:28:14 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * parse.y (datadef): Move call to note_list_got_semicolon up.
- * gxxint.texi (Access Control): New node.
+Fri Mar 8 11:47:26 1996 Mike Stump <mrs@cygnus.com>
- * search.c (current_scope): New function; returns whichever of
- current_class_type and current_function_decl is the most nested.
- (compute_access): Total overhaul to make it clearer and more
- correct. Don't use the cache for now; in the only situation where
- it was used before, it gained nothing. This frees up three of the
- DECL_LANG_FLAGs for possible other use!
+ * tree.c (unsave_expr): Don't unsave, UNSAVE_EXPRs.
- * cp-tree.h: #if 0 out DECL_PUBLIC & friends.
+Fri Mar 8 11:29:06 1996 Mike Stump <mrs@cygnus.com>
- * typeck.c (build_component_ref_1): Don't check DECL_PUBLIC.
+ * decl.c (cp_finish_decl): The exception regions have to be
+ nested, not overlapping. We start the exception region for a
+ decl, after it has been fully built, and all temporaries for it
+ have been cleaned up.
- * call.c (build_method_call): Use convert_force to cast `this' --
- rely on the access checking for the method itself.
+Thu Mar 7 17:46:06 1996 Mike Stump <mrs@cygnus.com>
- * init.c (is_friend): Do the nesting thing, handle types. I am
- my own friend.
- (is_friend_type): Become a shell for is_friend.
- (add_friend): Never stick in ctype.
- Why are the friendship functions in init.c, anyway?
+ * tree.c (vec_binfo_member): Don't core dump if we have no bases.
-Wed Jan 26 17:50:00 1994 Mike Stump <mrs@cygnus.com>
+Thu Mar 7 14:11:49 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (build_type_conversion_1): Don't conditionalize call to
- pedwarn upon pedantic.
+ * tree.def: Add RETURN_INIT.
+ * pt.c (instantiate_decl): Handle RETURN_INIT.
+ * decl.c (store_return_init): Handle minimal_parse_mode.
-Wed Jan 26 17:20:46 1994 Mike Stump <mrs@cygnus.com>
+ * tree.c (cp_build_type_variant): Just return an error_mark_node.
+ * decl.c (make_typename_type): Don't try to get the file and line
+ of an identifier.
+ * typeck.c (comptypes): Handle TYPENAME_TYPE.
- * cvt.c (convert_to_reference): Add 8.4.3 checking so that one
- gets a warning if one tries to initialize a non-const & from a
- non-lvalue.
- * cvt.c (convert_to_reference): Use %P format for argument
- numbers in warnings.
+Wed Mar 6 18:47:50 1996 Per Bothner <bothner@kalessin.cygnus.com>
-Wed Jan 26 14:35:06 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (poplevel): Make sure we clear out and restore old local
+ non-VAR_DECL values by default when they go out of scope.
- * init.c (build_delete): Follow style in call.c to construct the
- virtual call to the desctructor, as that code is right. Fixes a
- problem of the compiler saying a pointer conversion is ambiguous.
+Wed Mar 6 09:57:36 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jan 26 11:28:14 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * method.c (build_overload_value): Use DECL_ASSEMBLER_NAME in
+ referring to addresses of variables and functions.
- * cp-tree.h (VTABLE_NAME_P): Change other occurrence of
- VTABLE_NAME_FORMAT to VTABLE_NAME.
+ * error.c (dump_expr): Support SIZEOF_EXPR.
- * *: s/visibility/access/g
+ * init.c (do_friend): Use the return value of check_classfn.
-Tue Jan 25 18:39:12 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (convert_arguments): Call complete_type.
- * typeck.c (build_modify_expr): Don't smash references if INIT_EXPR.
+ * method.c (hack_identifier): After giving an error, set value to
+ error_mark_node.
-Tue Jan 25 13:54:29 1994 Mike Stump <mrs@cygnus.com>
+Tue Mar 5 16:00:15 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (hack_decl_function_context): Kludge around DECL_CONTEXT
+ lossage for local classes.
+ * cp-tree.h: Declare it.
+ * decl.c (lookup_name_real): Evil, painful hack for local classes.
+ (grokfndecl): Set DECL_CLASS_CONTEXT and DECL_NO_STATIC_CHAIN here.
+ Use hack_decl_function_context.
+ (grokdeclarator): Don't set DECL_NO_STATIC_CHAIN here.
+ (start_function): Use hack_decl_function_context.
+ (finish_function): Likewise.
+ * method.c (synthesize_method): Likewise.
+ * lex.c (process_next_inline): Likewise.
+ (do_pending_inlines): Likewise.
+ * decl2.c (finish_file): Unset DECL_STATIC_FUNCTION_P when we're
+ done with it.
- * init.c (build_delete): Back out Jan 17th & 18th pacthes, as
- they break libg++.
+Mon Mar 4 22:38:39 1996 Gerald Baumgartner <gb@alexander.cs.purdue.edu>
-Tue Jan 25 13:11:45 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * sig.c (build_signature_pointer_or_reference_type): Align
+ signature pointers/references on 8-byte boundaries so they can be
+ grabbed 2 words at a time on a Sparc.
- * decl.c (duplicate_decls): Fix pointer arithmetic.
+Tue Mar 5 10:21:01 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon Jan 24 15:50:06 1994 Chip Salzenberg (chip@fin.uucp)
+ * method.c (hack_identifier): Requiring a static chain is now a
+ hard error.
+ * decl.c (grokdeclarator): Set DECL_NO_STATIC_CHAIN on nested
+ functions.
- [ cp-* changes propagated from c-* changes in 940114 snapshot ]
- * cp-parse.y (maybe_attribute): Allow multiple __attribute__
- clauses on a declaration.
+Mon Mar 4 20:03:33 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon Jan 24 17:06:23 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * init.c (build_offset_ref): Call complete_type.
- * class.c (finish_struct): Do synthesize methods for anon
- structs, just not unions.
+ * decl.c (pop_from_top_level): Always pop previous_class_type.
-Mon Jan 24 13:50:13 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * parse.y: Handle multiple decls in a for-init-statement.
+ * pt.c (tsubst_expr): Likewise.
- * decl.c (xref_tag): handle anonymous nested type.
- * decl.c (globalize_nested_type): add no globalize bit check.
- * spew.c (hack_more_ids) : templated nested decl not push top
- level.
+ * pt.c (tsubst): Use tsubst_expr for the second operand of an
+ ARRAY_REF.
- * parse.y : get rid of 'goto do_components'. It is much better
- for debugging.
+ * decl.c (maybe_push_to_top_level): Don't save previous_class_type.
+ (poplevel_class): Set it here.
+ (pop_from_top_level): Pop it here if we're returning to class scope.
+ * class.c (pushclass): Don't set it here.
- * decl.c (is_anon_name): get rid of the function and use the
- macro ANON_AGGRNAME_P.
- * pt.c : ditto.
+ * decl.c (maybe_push_to_top_level): Save current_template_parms,
+ and clear it if !pseudo.
+ (pop_from_top_level): Restore it.
-Fri Jan 21 14:06:02 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (finish_file): Push the dummy each time we walk the list
+ of vtables.
- * class.c (finish_struct): Don't synthesize any methods for
- anonymous structs/unions.
+ * error.c (dump_expr): Support LOOKUP_EXPR and actually do
+ something for CAST_EXPR.
+
+Mon Feb 19 14:49:18 1996 Rusty Russell <rusty@adelaide.maptek.com.au>
- * typeck.c (build_modify_expr): Don't treat pmf's as class objects.
+ * cvt.c (cp_convert): Warn about implicit conversion of the
+ address of a function to bool, as it is always true.
-Thu Jan 20 18:56:46 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Feb 23 23:06:01 1996 Rusty Russell <rusty@adelaide.maptek.com.au>
- * method.c (build_opfncall): Call build_indirect_ref on
- synthesized instance for operator delete.
+ * typeck.c (c_expand_return): Fix warning for local externs returned.
- * pt.c (type_unification): Don't abort if called with a list of
- types in ARGS.
+Mon Mar 4 15:03:11 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (instantiate_type): Deal with function templates.
+ * tree.c (mapcar): Propagate const and volatile properly.
-Thu Jan 20 16:55:35 1994 Jim Wilson (wilson@sphagnum.cygnus.com)
+ * typeck.c (complete_type): Be sure to instantiate the
+ MAIN_VARIANT of the type.
- * Makefile.in (CC): Default to cc not gcc.
+ * method.c (synthesize_method): Class interface hackery does not
+ apply to synthesized methods.
-Thu Jan 20 13:47:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Mar 4 14:05:23 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_modify_expr): Call constructor if appropriate.
+ * pt.c (comp_template_args): Use comptypes rather than just
+ checking for TEMPLATE_TYPE_PARM equivalence.
- * decl.c (push_to_top_level): Clear out class-level bindings cache.
+ * typeck.c (build_x_function_call): Call complete_type before
+ checking TYPE_OVERLOADS_CALL_EXPR.
-Wed Jan 19 13:51:22 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Mar 4 18:48:30 1996 Manfred Hollstein <manfred@lts.sel.alcatel.de>
- * call.c (resolve_scope_to_name): Work recursively (previously only
- looked down one level).
+ * g++.c (main): Check also for new define ALT_LIBM.
- * lex.c (do_pending_inlines): If we're still dealing with the last
- batch of inlines, don't start working on a new one.
+Fri Mar 1 13:09:33 1996 Jason Merrill <jason@yorick.cygnus.com>
- * Makefile.in (stamp-parse): Update conflict count.
- (TAGS): Fix.
+ * pt.c (instantiate_class_template): If we don't have a pattern
+ yet, that's OK.
+ (coerce_template_parms): If we see a local class, bail.
- * parse.y (explicit_instantiation): New rule; implements
- 'template A<int>' syntax (though not 'template foo(int)' yet).
- (structsp): Add explicit_instantiation.
+ * decl.c (grok_reference_init): Make sure there's a type before
+ checking its code.
-Tue Jan 18 13:53:05 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (do_function_instantiation): Avoid crashing on invalid decls.
+ (push_template_decl): Likewise.
- * class.c (finish_struct, etc.): Simplify decision to synthesize
- a destructor.
+ * parse.y (named_class_head): Set
+ CLASSTYPE_TEMPLATE_SPECIALIZATION here if we have basetypes.
- * call.c, class.c, cp-tree.h, decl.c, init.c,
- ptree.c, search.c, typeck.c, typeck2.c: Nuke
- TYPE_NEEDS_CONSTRUCTOR (change all calls to TYPE_NEEDS_CONSTRUCTING).
- * init.c (expand_aggr_init_1): Don't try non-constructor methods
- of initializing objects.
- (build_new): Don't try other methods if the constructor lookup fails.
+ * decl.c (xref_tag): Diagnose redeclaration of template
+ type-parameter name.
- * class.c (finish_base_struct): Set cant_have_default_ctor and
- cant_synth_copy_ctor properly.
- (finish_struct): Ditto.
+ * error.c (dump_type): Handle anonymous template type parms.
-Mon Jan 17 13:58:18 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (instantiate_template): Use TYPE_MAIN_DECL instead of
+ TYPE_STUB_DECL.
+ (coerce_template_parms): Likewise.
- * typeck.c (build_modify_expr_1): #if 0 out again.
- (build_modify_expr): #if 0 out memberwise init code again.
+Thu Feb 29 16:26:01 1996 Mike Stump <mrs@cygnus.com>
- * lex.c (default_copy_constructor_body): Be const-correct.
- (default_assign_ref_body): Ditto.
+ * class.c (instantiate_type, case {ARRAY,INDIRECT}_REF,
+ case ADDR_EXPR): Don't modify rhs if a subinstantiation fails.
- * init.c (perform_member_init): Use TYPE_HAS_CONSTRUCTOR to decide
- whether or not to use it, rather than TYPE_NEEDS_CONSTRUCTING.
- (expand_aggr_init): Disable silent conversion from initializer list
- to list of args for a constructor.
+Thu Feb 29 08:20:25 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (base_info): Lose needs_default_ctor.
- (finish_base_struct): Ditto.
- (finish_struct): Ditto.
+ * pt.c (instantiate_template): Take the MAIN_VARIANT of the type
+ before trying to get its STUB_DECL.
+ (coerce_template_parms): Likewise.
- * decl.c (init_decl_processing): Don't turn off flag_default_inline
- just because flag_no_inline is on.
- (finish_decl): Use TYPE_HAS_CONSTRUCTOR to decide to use
- constructor.
+ * parse.y (template_type_parm): If they didn't use 'class',
+ pretend they did after giving an error.
- * class.c (finish_struct): Synthesize default ctor whenever
- allowed.
+ * pt.c (coerce_template_parms): Diagnose use of local class.
- * Makefile.in (TAGS): Don't try to run etags on cp-parse.y.
+ * decl.c (grok_reference_init): Use instantiate_type.
-Sat Jan 15 18:34:33 1994 Mike Stump <mrs@cygnus.com>
+ * error.c (dump_expr): Handle TEMPLATE_DECLs.
- * Makefile.in, configure: Handle the C++ front-end in a
- subdirectory.
- * cp-*: Move C++ front-end to cp/*.
+ * parse.y (named_class_head): Diagnose mismatching types and tags.
-Fri Jan 14 14:09:37 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (pushdecl): Type decls and class templates clash with
+ artificial type decls, not hide them.
- * cp-typeck.c (build_function_call_real): Modify to match other
- instances of taking the address of the function.
+ * decl.c (redeclaration_error_message): Diagnose redefinition of
+ templates properly.
+ (duplicate_decls): Diagnose disallowed overloads for template
+ functions, too.
- * cp-class.c (finish_struct): Set TYPE_HAS_REAL_CONSTRUCTOR to 1 if
- there are non-synthesized constructors.
- Only set TYPE_NEEDS_CONSTRUCTOR if TYPE_HAS_REAL_CONSTRUCTOR.
- Always generate copy constructor if possible.
+ * decl.c (start_decl): Call complete_type before checking for a
+ destructor.
- * cp-tree.h (lang_type): Add has_real_constructor bitfield.
- (TYPE_HAS_REAL_CONSTRUCTOR): Define.
+ * pt.c (tsubst): Use tsubst_expr on the elts of a VEC.
- * cp-lex.c (default_copy_constructor_body): Use init syntax
- for all bases.
+ * decl.c (xref_tag): A TEMPLATE_TYPE_PARM is a match.
- * cp-type2.c (store_init_value): Only give error for initializer list
- if TYPE_HAS_REAL_CONSTRUCTOR.
+Wed Feb 28 09:28:44 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jan 13 15:38:29 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (grok_op_properties): Don't check for operator++(int) in
+ a template.
- * cp-tree.h (DECL_SYNTHESIZED): Add defn.
- (lang_decl): Add synthesized bitfield to decl_flags.
+ * tree.c (perm_manip): Return a copy of variable and function
+ decls with external linkage.
- * cp-lex.c (cons_up_default_function): Use DECL_SYNTHESIZED to mark
- artificial methods, rather than a line # of 0.
+ * tree.def: Change some of the min tree codes to type "1".
+ * pt.c (uses_template_parms): Handle 'e's, return 1 for LOOKUP_EXPRs.
+ * method.c (build_overload_int): Emit something arbitrary for
+ anything but an INTEGER_CST if we're in a template.
-Fri Jan 14 18:25:29 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * decl.c (cp_finish_decl): Call complete_type before deciding
+ whether or not to lay out the decl.
- * cp-decl (xref_tag): fix a bug in conflict type.
- * cp-parse.y : add SCOPED_NAME for uninstantiated template nested
- type reference.
- * cp-spew.c (yylex) : generated SCOPED_NAME token.
- * cp-lex.c (yyprint): handle SCOPED_NAME.
+ * lex.c (do_identifier): Check for DECL_INITIAL before using it.
-Fri Jan 14 17:00:29 1994 Mike Stump <mrs@cygnus.com>
+Tue Feb 27 16:35:32 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-decl.c (pushdecl): Revert patch from Jan 11 19:33:03, as it is
- not right.
+ * typeck2.c (build_x_arrow): Call complete_type.
-Thu Jan 13 14:00:35 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * pt.c (add_pending_template): Broken out.
+ (lookup_template_class): If -fexternal-templates, call it for all
+ the methods of implemented types.
+ (instantiate_class_template): Instead of instantiating them here.
+ (instantiate_decl): Handle -fexternal-templates earlier.
- * cp-decl2.c (grok_x_components): fix a bug that enum type does not
- have type_flags.
+Tue Feb 27 15:51:32 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Thu Jan 13 11:39:34 1994 Mike Stump <mrs@cygnus.com>
+ * search.c, lex.c, decl.c, class.c, cp-tree.h: Don't wrap the
+ memoized lookup stuff inside GATHER_STATISTICS.
- Ensure that all vtable pointers are initialized with all the right
- values.
+Tue Feb 27 10:38:08 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-class.c (is_normal): Changed to reflect new meaning of
- CLASSTYPE_VFIELD_PARENT.
- * cp-class.c (maybe_fixup_vptrs): Use of
- CLASSTYPE_NEEDS_VIRTUAL_REINIT here is misguided. Use
- BINFO_MODIFIED instead.
- * cp-class.c (finish_struct): Changed to reflect new meaning of
- CLASSTYPE_VFIELD_PARENT.
- * cp-decl.c (get_binfo_from_vfield): Removed, unneeded now.
- * cp-decl.c (finish_function): Use init_vtbl_ptrs, instead of open
- coding it here.
- * cp-init.c (init_vfields): Changed name to init_vtbl_ptrs, and
- re-implement.
- * cp-init.c (emit_base_init): Use new name init_vtbl_ptrs.
- * cp-tree.h (vfield_parent): Changed to integer.
- * cp-tree.h (CLASSTYPE_VFIELD_PARENT): Changed docs to reflect new
- meaning.
- * cp-tree.h (init_vtbl_ptrs): Added init_vtbl_ptrs.
+ * decl.c (start_decl): Complain about array of incomplete type
+ here.
+ (grokdeclarator): Not here.
-Wed Jan 12 18:24:16 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * parse.y (template_parm): Expand full_parm inline so we can set
+ the rule's precedence.
- * cp-decl.c (xref_tag): re-implement globalize nested type.
- * cp-decl2.c (grok_x_components): ditto.
- * cp-parse.y: ditto.
- * cp-tree.h (lang_type): add no_globalize bit in type_flags.
+ * pt.c (tsubst_expr): If we're in a template, just do tsubst_copy.
+ (tsubst): tsubst_expr the DECL_INITIAL of FIELD_DECLs.
+ * decl2.c (grokbitfield): Don't check for integer constant here.
+ * class.c (finish_struct_1): Check here.
-Wed Jan 12 14:08:09 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (define_label): Make the min decl go on permanent_obstack.
- * cp-decl.c (grokdeclarator): Don't set TREE_PUBLIC on friend
- decls with a definition attached.
+ * pt.c (unify): Don't handle CONST_DECLs.
+ (uses_template_parms): Don't check DECL_INITIAL on a CONST_DECL.
+ (tsubst_copy): Likewise.
- * cp-typeck.c (build_modify_expr): Undo previous change in the case
- of INIT_EXPRs.
+ * lex.c (do_identifier): Do pull the DECL_INITIAL out of a
+ CONST_DECL for a template parm.
-Tue Jan 11 19:33:03 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Feb 26 12:48:18 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-typeck.c (build_modify_expr): Replace code for generating
- assignment semantics for classes with an error.
- (build_modify_expr_1): #if 0 out.
+ * decl.c (grokdeclarator): Complain about array of incomplete type
+ here.
+ (start_decl_1): Not here.
- * cp-decl.c (pushdecl): Patch bogus design of pushdecl
- behavior for overloaded functions (it doesn't push anything).
+ * pt.c (tsubst): Handle pointer-to-function declarators.
- * cp-class.c (finish_struct): When generating default op=,
- set TYPE_HAS_ASSIGNMENT.
+ * method.c (hack_identifier): If pedantic, diagnose local class
+ methods that require a static chain.
-Mon Jan 10 18:48:06 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (grok_op_properties): No longer static.
+ * cp-tree.h: Declare it.
+ * pt.c (tsubst): Call it for operators.
+ Use tsubst_copy for TREE_VECs.
- * cp-cvt.c (convert): Make {double, clashing enum} -> enum
- invalid.
- * cp-typeck.c (convert_for_assignment): Simplify.
- * cp-decl2.c (warn_enum_clash): Removed.
- * invoke.texi (-Wenum-clash): Removed.
- * toplev.c (-Wenum-clash): Removed.
+ * parse.y (template_arg): The expr has precedence like '>'.
-Mon Jan 10 17:48:37 1994 Kung Hsu (kung@mexican.cygnus.com)
+Fri Feb 23 14:51:52 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-decl.c (finish_decl): fix incorrect popclass call.
+ * pt.c (coerce_template_parms): Don't coerce an expression using
+ template parms.
+ (uses_template_parms): Also check DECL_INITIAL in CONST_DECLs.
+ (tsubst): Don't use build_index_2_type if the max_value uses template
+ parms.
+ * method.c (build_overload_int): Emit something arbitrary for an
+ expression using template parms.
+
+ * parse.y (template_close_bracket): New non-terminal to catch use
+ of '>>' instead of '> >' in template class names.
+ (template_type): Use it.
+ * Makefile.in (CONFLICTS): Causes one more r/r conflict.
+
+ * tree.def: Add CAST_EXPR.
+ * typeck2.c (build_functional_cast): Use CAST_EXPR instead of
+ CONVERT_EXPR for minimal_parse_mode.
+ * typeck.c (build_c_cast): Likewise.
+ * pt.c (tsubst_copy): Likewise.
+ * decl2.c (build_expr_from_tree): Likewise.
+ * error.c (dump_expr): Likewise.
+
+Fri Feb 23 10:36:46 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * except.c (SetTerminate, SetUnexpected): Put back global vars.
+ (init_exception_processing): Put back decl/init of
+ set_unexpected_fndecl and set_terminate_fndecl, needed to get the
+ fns from libstdc++.
+
+ * decl.c (struct binding_level): Delete ACCEPT_ANY bitfield.
+ (declare_uninstantiated_type_level, uninstantiated_type_level_p):
+ Delete unused fns.
+ * cp-tree.h (declare_uninstantiated_type_level,
+ uninstantiated_type_level_p): Delete prototypes.
+
+Thu Feb 22 19:36:15 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst_expr): Add default return.
+
+Thu Feb 22 16:47:24 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * error.c (fndecl_as_string): Delete unused arg CNAME.
+ * sig.c (build_signature_table_constructor,
+ build_signature_method_call): Fix calls.
+
+ * class.c (the_null_vtable_entry): Delete var definition.
+ (init_class_processing): Delete tree the_null_vtable_entry init.
+ * decl.c (no_print_{functions, builtins}): Declare as static.
+ (__tp_desc_type_node): #if 0 var definition.
+ (init_type_desc): #if 0 init of __tp_desc_type_node.
+ (vb_off_identifier): Move var decl into init_decl_processing.
+ (current_function_assigns_this): Declare as static.
+ (int_ftype_ptr_ptr_int, void_ftype_ptr_int_int): Delete var decls.
+ (init_decl_processing): Delete init of void_ftype_ptr_ptr_int.
+ Move decls of string_ftype_ptr_ptr and int_ftype_string_string here.
+ * decl2.c (delete_sanity): Delete definition/mod of local var ELT_SIZE.
+ * init.c (BI_header_type, BI_header_size): Declare as static.
+ * pt.c (template_classes): Delete unused var.
+ (add_pending_template): Delete decl for non-existent fn.
+ (lookup_template_class): Delete vars CODE and TAG_CODE.
+ (instantiate_template): Delete unused var TARGS.
+ * cp-tree.h (vb_off_identifier, current_function_assigns_this):
+ Delete decls.
+ (__tp_desc_type_node): #if 0 var decl.
+ (fndecl_as_string): Fix prototype.
+
+Thu Feb 22 15:56:19 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.def: Add GOTO_STMT.
+ * pt.c (tsubst_expr): Support goto and labels.
+ * decl.c (define_label): Support minimal parsing.
+ * parse.y (simple_stmt): Likewise.
+
+Thu Feb 22 15:30:12 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * xref.c (GNU_xref_member): Only define/set var I if
+ XREF_SHORT_MEMBER_NAMES is defined, to match when it's actually
+ used.
+ (GNU_xref_end_scope): Delete unused fifth arg TRNS.
+ (GNU_xref_end): Fix call.
+ * decl.c (poplevel, poplevel_class, finish_method): Fix calls.
+ * cp-tree.h (GNU_xref_end_scope): Fix prototype.
+
+ * tree.c (build_exception_variant): Delete unused vars I, A, T,
+ T2, and CNAME.
+ (layout_vbasetypes): Delete unused var NONVIRTUAL_VAR_SIZE.
+ (mapcar): Delete unused var CODE.
+ (build_cplus_new): Delete unused arg WITH_CLEANUP_P.
+ (break_out_cleanups): Fix call.
+ (bot_manip): Likewise.
+ * call.c (build_method_call): Likewise.
+ * cvt.c (build_up_reference, convert_to_reference, cp_convert):
+ Likewise.
+ * typeck.c (unary_complex_lvalue, build_modify_expr,
+ convert_for_initialization): Likewise.
+ * typeck2.c (build_functional_cast): Likewise.
+ * cp-tree.h (build_cplus_new): Fix prototype.
+
+ * repo.c (open_repo_file): Delete unused var Q.
+ (repo_compile_flags, repo_template_declared,
+ repo_template_defined, repo_class_defined, repo_inline_used,
+ repo_vtable_used, repo_tinfo_used): #if 0 unused fns.
+ (repo_get_id, repo_vtable_used): Declare as static.
+ * cp-tree.h (mark_{decl,class}_instantiated, finish_repo): Add
+ prototypes.
+
+Thu Feb 22 14:53:35 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * parse.y (pending_inlines): Add function_try_block case.
+
+ * pt.c (unify): Fix for template const parms.
+
+Thu Feb 22 13:24:15 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * lex.c (extract_interface_info): Delete forward decl.
+ (default_copy_constructor_body, default_assign_ref_body): Delete
+ decls for non-existent functions.
+ (synth_firstobj, inline_text_firstobjs): Delete unused vars.
+ (init_lex): Delete setting them.
+ (cons_up_default_function): Delete unused vars FUNC_BUF,
+ FUNC_LEN, and COMPLEX. Delete code setting COMPLEX. Delete old
+ #if 0'd synth code.
+ (toplevel, expression_obstack): Delete unused extern decls.
+ (tree_node_kind): Delete unused enum.
+ (tree_node_counts, tree_node_sizes): Wrap with #ifdef
+ GATHER_STATISTICS.
+ (tree_node_kind_names): Delete unused extern decl.
+ (synth_obstack): Delete unused var.
+ (init_lex): Don't set it.
+ (init_parse): Add decl before use.
+ (reduce_count): Only define #ifdef GATHER_STATISTICS && REDUCE_LENGTH.
+ (current_unit_{name, language}): Delete unused vars.
+ (check_newline): Don't bother setting them, just accept the #pragma.
+ * cp-tree.h (init_repo, peek_yylex): Add prototypes.
+ (current_unit_{name, language}): Delete decls.
+
+ * search.c: Wrap all of the memoized functions, macros, and
+ variables inside #ifdef GATHER_STATISTICS.
+ (lookup_field, lookup_fnfields): Likewise.
+ (init_search_processing): Likewise.
+ (reinit_search_statistics): Wrap whole function.
+ * lex.c (reinit_lang_specific): Wrap call to reinit_search_statistics.
+
+ * decl.c (finish_function): Only call pop_memoized_context if
+ GATHER_STATISTICS is defined.
+ (start_function): Likewise for push_memoized_context.
+ * class.c (pushclass, popclass): Likewise.
+
+ * cp-tree.h (CLASSTYPE_MTABLE_ENTRY): Move definition from here...
+ * search.c (CLASSTYPE_MTABLE_ENTRY): ... to here.
+
+ * cvt.c (cp_convert): Delete unused local var FORM.
+ * cp-tree.h (can_convert, can_convert_arg, real_lvalue_p): Add
+ prototypes.
+
+Thu Feb 22 13:19:44 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (do_poplevel): Oops; really return what we get from
+ poplevel this time.
+
+Thu Feb 22 11:41:44 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * cp-tree.h (is_aggr_type): Add prototype.
+
+ * cp-tree.h ({push,pop}_cp_function_context): Add decls.
+ * method.c ({push,pop}_cp_function_context): Delete decls.
+ * except.c (start_eh_unwinder, end_eh_unwinder): Declare as void.
+ (SetUnexpected, SetTerminate): Delete unused vars.
+ (init_exception_processing): Don't set SetUnexpected or
+ SetTerminate. Don't set SET_UNEXPECTED_FNDECL or SET_TERMINATE_FNDECL.
+ (output_exception_table_entry): Delete unused array LABEL.
+ (expand_internal_throw): Delete unused var PARAMS.
+ (expand_start_catch_block): Delete unused var CLEANUP.
+ (emit_exception_table): Delete unused var EH_NODE_DECL.
+ (expand_builtin_throw): Delete unused vars UNWIND_AND_THROW and
+ GOTO_UNWIND_AND_THROW. Don't set them.
+ (end_eh_unwinder): Add top decl.
+ (pop_rtl_from_perm): Delete unused decl of PERMANENT_OBSTACK.
+ (exception_section, push_rtl_perm, do_function_call,
+ lang_interim_eh, push_eh_cleanup, eh_outer_context,
+ expand_end_eh_spec, end_eh_unwinder): Declare as static.
+ (saved_pc, saved_throw_type, saved_throw_value, saved_cleanup,
+ throw_used): Likewise.
+ * cp-tree.h (expand_end_eh_spec): Delete prototype.
+
+ * search.c (dfs_mark, dfs_mark_vtable_path,
+ dfs_unmark_vtable_path, dfs_mark_new_vtable,
+ dfs_unmark_new_vtable, dfs_clear_search_slot,
+ dfs_search_slot_nonempty_p, bfs_markedp, bfs_unmarkedp,
+ bfs_marked_vtable_pathp, bfs_unmarked_vtable_pathp,
+ bfs_marked_new_vtablep, bfs_unmarked_new_vtablep): #if 0 unused
+ functions.
+ (n_fields_searched, n_calls_lookup_field, n_calls_lookup_field_1,
+ n_calls_lookup_fnfields, n_calls_lookup_fnfields_1,
+ n_calls_get_base_type, n_outer_fields_searched, n_contexts_saved):
+ Only define #ifdef GATHER_STATISTICS.
+ (reinit_search_statistics): Only init some vars if GATHER_STATISTICS
+ is defined.
+ (vbase_decl): Delete var definition.
+ (init_search): Delete old decl.
+ (init_vbase_pointers): Delete building of VBASE_DECL, since it's
+ never actually used.
+ (expand_indirect_vtbls_init): Delete init of VBASE_DECL.
+ (get_base_distance_recursive): Delete unused fourth arg
+ BASETYPE_PATH. Fix call .
+ (get_base_distance): Fix call.
+ (push_class_decls): Delete unused var ID.
+ (make_memoized_table_entry): Declare as static.
+ (breadth_first_search): Declare as static.
+ (tree_has_any_destructor_p): Declare as static.
+ (pop_class_decls): Delete unused arg pop_class_decls.
+ * class.c (popclass): Fix call to pop_class_decls.
+ * cp-tree.h (make_memoized_table_entry, breadth_first_search,
+ tree_has_any_destructor_p): Delete prototypes.
+
+ * rtti.c (build_ptmf_desc): Delete unused arg TYPE.
+ (build_t_desc): Fix call. Delete unused vars ELEMS and TT.
+ (build_dynamic_cast): Delete unused local vars TMP1 and RETVAL.
+ (build_user_desc): Delete unused var T.
+ (build_class_desc): Delete unused vars T and OFF.
+ (build_t_desc): Delete unused var NAME_STRING.
+ (build_headof): Make static.
+ (get_bad_cast_node): Likewise.
+ (get_def_to_follow): Likewise.
+ * cp-tree.h (init_type_desc): Add prototype.
+ (build_headof): Remove prototype.
+
+Thu Feb 22 00:54:22 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst): Only look for matching decls at file scope for
+ non-member functions.
- * cp-decl.c (is_anon_name): new function, check whether the name
- is anonymous name generated by compiler.
- * cp-decl.c (grokdeclarator): allow nested SCOPE_REF
- * cp-spew.c (hack_more_ids): handle nested type in template.
- * cp-parse.y : handle nested type reference in uninstantiated
- template.
- * cp-call.c (build_method_call): handle uninstantiated template
- case.
- * cp-pt.c (search_nested_type_in_tmpl): new function, search nested
- type in template.
- * cp-pt.c (lookup_nested_type_by_name): new function, lookup nested
- type by name.
- * cp-pt.c (tsubst): handle nested type search by name.
+ * call.c (build_scoped_method_call): Handle scoped destructor
+ calls in templates.
-Mon Jan 10 14:32:18 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (*_top_level): Also save previous_class_values.
- * cp-init.c (build_member_call): Propagate qualifiers to new type.
+ * pt.c (tsubst_expr): Support do {} while loops.
+ * parse.y (simple_stmt): Likewise.
+ * tree.def: Likewise.
- * cp-call.c (build_method_call): Count functions the new way.
+ * method.c (build_overload_identifier): For a class nested in a
+ template class, don't mangle in the template parms from our
+ context.
-Fri Jan 7 19:03:26 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * lex.c, cp-tree.h: Remove support for template instantiations in
+ the pending_inlines code.
+ * pt.c: Remove dead functions and unused arguments.
+ (uses_template_parms): TYPENAME_TYPEs always use template parms.
+ * parse.y: Stop passing anything to end_template_decl.
+ * tree.c (print_lang_statistics): Only print tinst info #ifdef
+ GATHER_STATISTICS.
+
+Wed Feb 21 16:57:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * init.c (expand_recursive_init{,_1}): Delete decls.
+ (sort_member_init): Delete unused var INIT.
+ (emit_base_init): Delete unused var X.
+ (build_offset_ref): Delete unused var CNAME.
+ (sort_member_init): Delete unused var FIELDS_TO_UNMARK.
+ (emit_base_init): Delete unused local var BASE. Delete extern
+ decl of IN_CHARGE_IDENTIFIER.
+ (build_delete): Delete unused local var VIRTUAL_SIZE.
+
+ * init.c (build_vec_delete): Delete unused third arg ELT_SIZE.
+ (build_delete): Fix call.
+ * decl2.c (delete_sanity): Likewise.
+ * cp-tree.h (build_vec_delete): Update prototype.
+
+ * typeck.c (common_base_type): Delete unused var TMP.
+ (build_binary_op): Delete local var ARGS_SAVE.
+ (build_array_ref): Delete unused var ITYPE.
+ (c_expand_return): Delete unused var USE_TEMP.
+
+ * typeck.c (compexcepttypes): Delete unused arg STRICT.
+ (comptypes): Fix calls.
+ * decl.c (duplicate_decls): Likewise.
+ * cp-tree.h (compexcepttypes): Delete extra arg.
+
+ * decl2.c (check_classfn): Delete unused second arg CNAME.
+ * decl.c (start_decl, grokfndecl): Fix calls.
+ * init.c (do_friend): Likewise.
+ * cp-tree.h (check_classfn): Update prototype.
+
+ * cp-tree.h (signature_error, import_export_vtable,
+ append_signature_fields, id_in_current_class, mark_used,
+ copy_assignment_arg_p): Add decls.
+ * decl2.c (mark_used): Delete decl.
+
+ * class.c (n_*): Wrap with #ifdef GATHER_STATISTICS.
+
+ * class.c (get_vtable_entry): Diable unused function.
+ (doing_hard_virtuals): Delete unused static global var.
+ (finish_struct_1): Don't init DOING_HARD_VIRTUALS.
+ (prepare_fresh_vtable): Delete unused vars PATH and RESULT.
+ (overrides): Delete unused vars RETTYPE and BASE_RETTYPE.
+ (modify_one_vtable): Delete unused var OLD_RTTI.
+ (finish_struct_anon): Delete unused vars OFFSET and X.
+ (finish_struct_bits): Delete unused var METHOD_VEC.
+ (get_basefndecls): Delete unused var PURPOSE. Delete unused
+ for-scope local variable METHODS.
+
+ * call.c (user_harshness): Delete unused/unneeded arg PARM.
+ (ideal_candidate): Delete unused args BASETYPE and PARMS.
+ (build_method_call): Delete unused args passed into ideal_candidate.
+ (build_overload_call_real): Likewise. Delete unused var OVERLOAD_NAME.
+ * cp-tree.h (synthesize_method): Add decl.
+
+ * decl.c (note_level_for_for): Give void return type.
+ (pushdecl_nonclass_level): Likewise.
+ (finish_function): Delete unused vars VFIELDS and ALLOCATED_THIS.
+ (poplevel): Delete unused var IMPLICIT_TRY_BLOCK.
+ (suspend_binding_level): Delete unused var LEVEL.
+ (duplicate_decls): Delete unused var CTYPE.
+ (duplicate_decls): Delete unused var PREVIOUS_C_DECL.
+ (init_decl_processing): Delete unused vars FLOAT_ENDLINK and
+ PTR_ENDLINK.
+ (grokdeclarator): Delete unused var C.
+ (grokdeclarator): Delete unused var SIZE_VARIES.
+ (grokparms): Delete unused var SAW_VOID.
+ (start_function): Delete unused var OLDDECL.
+ (cplus_expand_expr_stmt): Delete unused var
+ REMOVE_IMPLICIT_IMMEDIATELY.
+
+ * cp-tree.h (pushdecl_nonclass_level): Fix prototype.
+
+ * Makefile.in (CONFLICTS): Update to 12 shift/reduce.
+
+Wed Feb 21 00:06:17 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (build_min): Set TREE_COMPLEXITY to lineno.
+ (build_min_nt): Likewise.
+ * pt.c (do_pushlevel): Emit line note.
+ (do_poplevel): Return what we get from poplevel.
+ (tsubst_expr): Set lineno from TREE_COMPLEXITY in stmt nodes.
+ * parse.y: Use do_pushlevel and do_poplevel.
+ * cp-tree.h: Declare do_poplevel.
+
+ * cp-tree.h: Declare at_eof.
+ * decl.c (cp_finish_decl): Pass it to rest_of_decl_compilation.
+ * decl2.c (import_export_decl): Renamed from import_export_inline.
+ (finish_file): Call it to do interface handling for statics.
+ * pt.c (tsubst_copy): Call mark_used on variables and functions
+ used here.
- * cp-decl.c (pushtag): Set DECL_ASSEMBLER_NAME for nested classes,
- too.
+ * decl2.c (finish_file): Don't emit statics we can't generate.
+ * pt.c (instantiate_decl): Don't set interface on instantiations
+ we can't generate.
-Tue Jan 4 16:45:51 1994 Kung Hsu (kung@cirdan.cygnus.com)
+ * cp-tree.h (struct tinst_level): Change 'classname' to 'decl'.
+ * tree.c (print_lang_statistics): Print max template depth.
+ * pt.c (push_tinst_level): Dump entire instantiation context.
+ (instantiate_class_template): Use it and pop_tinst_level.
+ (instantiate_decl): Likewise.
- * cp-parse.y: change to handle whether to globalize nested class.
- * cp-decl.c(xref_tag, maybe_globalize_type): Ditto.
+ * call.c class.c cp-tree.h decl.c decl2.c error.c lex.c method.c
+ pt.c ptree.c tree.def: Remove all traces of UNINSTANTIATED_P_TYPE.
-Mon Jan 3 22:22:32 1994 Gerald Baumgartner (gb@cygnus.com)
+Tue Feb 20 18:21:51 1996 Jason Merrill <jason@yorick.cygnus.com>
- * Makefile.in cp-call.c cp-class.c cp-cvt.c cp-decl.c cp-decl2.c
- cp-error.c cp-init.c cp-lex.c cp-lex.h cp-method.c cp-parse.y
- cp-spew.c cp-tree.c cp-tree.h cp-type2.c cp-typeck.c cp-xref.c
- gplus.gperf toplev.c: Incorporated C++ signature extension.
- * cp-sig.c: New file, contains most of signature processing.
- * cp-hash.h: Regenerated from gplus.gperf.
+ * call.c class.c cp-tree.h cvt.c decl.c decl2.c error.c expr.c
+ init.c lex.c method.c parse.y pt.c repo.c search.c spew.c tree.c
+ tree.def typeck.c typeck2.c xref.c: Massive, systemic changes for
+ the new template implementation.
- * gcc.1 g++.1: Added explanation for the `-fhandle-signatures'
- and `-fno-handle-signatures' command line flags.
+Tue Feb 20 17:14:29 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * gcc.texi: Changed the last-modification date.
- * invoke.texi: Added `-fhandle-signatures' in the list of
- C++ language options. Added explanation for this option.
+ * decl2.c (check_cp_case_value): Use STRIP_TYPE_NOPS.
-Tue Dec 28 21:10:03 1993 Mike Stump <mrs@cygnus.com>
+Thu Feb 15 18:44:42 1996 Mike Stump <mrs@cygnus.com>
- * cp-init.c (expand_vec_init): Remove comptypes test, as it is too
- harsh here.
+ * decl.c (cp_finish_decl): Delay emitting the debug information for
+ a typedef that has been installed as the canonical typedef, if the
+ type has not yet been defined.
-Tue Dec 28 13:42:22 1993 Mike Stump <mrs@cygnus.com>
+Thu Feb 15 09:39:08 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-pt.c (do_pending_expansions): Decide to expand a template
- member function, based upon it's class type, not the class type of
- the first place it was declared.
+ * decl2.c (grokfield): Still call pop_nested_class for access decls.
-Tue Dec 28 05:42:31 1993 Mike Stump <mrs@cygnus.com>
+Wed Feb 14 17:30:04 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-class.c (is_normal): New routine, use to determine when the
- given binfo is the normal one. (The one that should have the simple
- vtable name.)
- * cp-class.c (modify_other_vtable_entries): Use DECL_ASSEMBLER_NAME
- to check if two fndecls are `the same'. Sometimes this routine can
- modify the main vtable, and normal should be 1, in that case, so use
- is_normal() to determine if this is the main vtable for the class.
- Don't recurse down virtual bases, as they are shared, and we take
- care of them elsewhere.
- * cp-class.c (modify_vtable_entries): If we have already updated the
- vtable with the new virtual, don't do it again.
- * cp-class.c (finish_struct): Set CLASSTYPE_VFIELD_PARENT as
- appropriate. Do virtual function overriding in virtual bases, after
- normal overriding, so that the base function list in DECL_VINDEX is
- not overridden, before we have a chance to run through the list.
- Use DECL_ASSEMBLER_NAME to check if two fndecls are `the same'.
- Make sure we pass the right address into modify_vtable_entries.
- * cp-tree.h (CLASSTYPE_VFIELD_PARENT): New field to indicate which
- binfo is the one that has the vtable that we based our vtable on.
+ * decl.c (lookup_label): Call label_rtx.
-Fri Dec 24 09:40:52 1993 Michael Tiemann (tiemann@blues.cygnus.com)
+ * decl.c (make_binding_level): New function.
+ (pushlevel, pushlevel_class): Call it instead of explicit
+ duplicate calls to xmalloc.
- * cp-typeck.c (c_expand_start_case): Use default_conversion to
- convert expression from reference type if necessary.
+ * decl.c (init_decl_processing): Delete useless build_pointer_type
+ call.
-Wed Dec 22 17:58:43 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (float_ftype_float, ldouble_ftype_ldouble): Add definitions.
+ (sizet_ftype_string): Delete variable.
+ (init_decl_processing): Add built-in functions fabsf, fabsl,
+ sqrtf, sqrtl, sinf, sin, sinl, cosf, cos, cosl. New local
+ variable strlen_ftype, used for strlen.
- * cp-typeck.c (build_unary_op): Make sure that it's a TREE_LIST before
- trying to read its TREE_VALUE.
+Wed Feb 14 16:21:25 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-class.c (finish_struct_methods): Clear DECL_IN_AGGR_P here.
- (finish_struct): Instead of here.
+ * decl.c (push_to_top_level): Start from current_binding_level
+ again for now; the stl hacks depend on g++ being broken in this
+ way, and it'll be fixed in the template rewrite.
-Tue Dec 21 14:34:25 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * tree.def: Add USING_DECL.
+ * decl2.c (do_class_using_decl): Implement.
+ (grokfield): Pass access decls off to do_class_using_decl instead of
+ grokdeclarator.
+ * error.c (dump_decl): Handle USING_DECLs.
+ * decl.c (grokdeclarator): Remove code for handling access decls.
+ * class.c (finish_struct_1): Adjust accordingly, treat using-decls
+ as access decls for now.
+ (finish_struct): Don't check USING_DECLs for other uses of the name.
- * cp-tree.c (list_hash_lookup_or_cons): Make sure the type doesn't
- have TYPE_PTRMEMFUNC_P set before we try to build its
- CLASSTYPE_ID_AS_LIST.
- (get_decl_list): Likewise, when trying to read it.
+ * search.c (get_matching_virtual): Use cp_error_at.
- * cp-tree.h (VTABLE_NAME): No def with NO_{DOLLAR,DOT} defined.
- (VTABLE_NAME_P): Use it instead of VTABLE_NAME_FORMAT.
+Wed Feb 14 10:36:58 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Mon Dec 20 13:35:03 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * typeck.c (comptypes): Default COMP_TYPE_ATTRIBUTES to 1, to
+ match c-typeck.c.
+ (self_promoting_args_p): Move the check that TYPE is non-nil
+ before trying to look at its main variant.
+ (unsigned_type, signed_type): Add checking of DI/SI/HI/QI nodes.
- * cp-typeck.c (rationalize_conditional_expr): New function.
- (unary_complex_lvalue): Use it.
- (build_modify_expr): Use it, since trying to do an ADDR_EXPR of it
- with build_unary_op won't cut it. Don't wrap the COND_EXPR with a
- SAVE_EXPR either.
+ * cp-tree.h (DECL_WAITING_FRIENDS, SET_DECL_WAITING_FRIENDS):
+ Delete macros.
+ * init.c (xref_friend, embrace_waiting_friends): Delete functions.
+ (do_friend): Delete call to xref_friend.
+ * class.c (finish_struct_1): Delete call to embrace_waiting_friends.
- * cp-decl2.c (explicit_warn_return_type): Deleted variable.
- (lang_decode_option): Set warn_return_type, not explicit_*, for
- -Wreturn-type and -Wall. This is what rest_of_compilation uses to
- decide if it should go into jump_optimize or not.
- * cp-tree.h (explicit_warn_return_type): Deleted.
- * cp-decl.c (grokdeclarator): Use warn_return_type, not explicit_*.
- (finish_function): Also complain about no return in a non-void fn if
- we're being pedantic (don't rely on use of -Wreturn-type).
+ * typeck.c (convert_sequence): #if 0 unused function.
-Fri Dec 17 15:45:46 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * cp-tree.h (DECL_IN_MEMORY_P): New macro w/ the check that used to
+ be in decl_in_memory_p.
+ (decl_in_memory_p): Delete decl.
+ * expr.c (decl_in_memory_p): Delete fn.
+ * typeck.c (mark_addressable): Use DECL_IN_MEMORY_P.
- * cp-decl.c (grokdeclarator): Forbid declaration of a function as
- static if it's being done inside another function.
+ * decl.c (cp_finish_decl): Use DECL_IN_MEMORY_P.
- * cp-search.c (compute_visibility): Check for friendship both ways.
+Tue Feb 13 12:51:21 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Dec 17 14:28:25 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * class.c (finish_struct_1): Check for a pure-specifier on a
+ non-virtual function here.
- * cp-cvt.c (build_default_binary_type_conversion): Make error
- messages more helpful.
+ * decl2.c (grok_function_init): Don't check whether the function
+ is virtual here.
+ (grokfield): Don't call check_for_override here.
- * cp-error.c (op_as_string): New function, returns "operator =="
- given EQ_EXPR or suchlike.
+ * decl.c (push_to_top_level): Start from inner_binding_level,
+ check class_shadowed in class levels.
-Fri Dec 17 13:28:11 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+Mon Feb 12 17:46:59 1996 Mike Stump <mrs@cygnus.com>
- * cp-call.c (print_n_candidates): New function.
- (build_overload_call_real): Use it when we complain about a call
- being ambiguous.
+ * decl.c (resume_level): Ignore things that don't have names, instead
+ of core dumping.
-Fri Dec 17 12:41:17 1993 Jason Merrill (jason@deneb.cygnus.com)
+Mon Feb 12 15:47:44 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-call.c (build_method_call): Fix checking for static call
- context.
+ * decl2.c (grokfield): Set DECL_VINDEX properly for FUNCTION_DECLs.
- * cp-method.c (build_opfncall): Call build_indirect_ref on argument
- to operator new.
+Sat Feb 10 17:59:45 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-init.c (build_new): Don't mess with rval when building
- indirect ref.
+ * class.c (finish_struct_1): Set DECL_VINDEX properly on a
+ synthesized dtor.
-Thu Dec 16 16:48:05 1993 Kung Hsu (kung@cirdan.cygnus.com)
+ * parse.y (complete_type_name): Bind global_scope earlier.
+ (complex_type_name): Likewise.
+ (qualified_type_name): Remove.
- * cp-lex.c (default_assign_ref_body): add check when TYPE_NESTED_
- NAME(type) may not be exist. It's not a problem for old compiler.
+Thu Feb 8 15:15:14 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Dec 16 14:46:06 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl.c (grokfndecl): Move code that looks for virtuals in base
+ classes...
+ * class.c (check_for_override): ... to a new function.
+ (finish_struct_1): Call it.
- * cp-tree.h (CLASSTYPE_ALTERS_VISIBILITIES_P): Delete macro, it's
- never used for anything.
- (struct lang_type, member type_flags): Delete field
- `alters_visibility', and up `dummy' by 1.
- * cp-class.c (finish_base_struct): Delete code that copies the
- setting of CLASSTYPE_ALTERS_VISIBILITIES_P.
- (finish_struct): Delete code that sets it.
+ * cp-tree.h: Declare warn_sign_compare.
-Thu Dec 16 14:44:39 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (build_binary_op_nodefault): Check warn_sign_compare
+ rather than extra_warnings to decide whether to warn about
+ comparison of signed and unsigned.
- * cp-decl.c, cp-init.c, cp-typeck.c: Fix arguments to
- build_method_call that I messed up before.
+ * decl2.c (lang_decode_option): Handle warn_sign_compare. -Wall
+ implies -Wsign-compare. -Wall doesn't imply -W.
- * cp-search.c (get_base_distance): If protect > 1, allow immediate
- private base.
+Wed Feb 7 15:27:57 1996 Mike Stump <mrs@cygnus.com>
- * cp-class.c (finish_base_struct): Set cant_synth_* correctly.
- (finish_struct): Ditto. Well, nigh-correctly; it won't deal
- properly with the case where a class contains an object of an
- ambiguous base class which has a protected op=. Should be fixed
- when the access control code gets overhauled.
- (finish_struct_methods): Set TYPE_HAS_NONPUBLIC_* correctly.
+ * typeck.c (build_component_ref): Fix to handle anon unions in base
+ classes as well.
-Thu Dec 16 12:17:06 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+Wed Feb 7 14:29:12 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-lex.c (real_yylex): Turn the code back on that deals with
- __FUNCTION__ and __PRETTY_FUNCTION__. Don't use lookup_name, to
- avoid the ambiguity problems that led to it being turned off in the
- first place.
+ * class.c (resolves_to_fixed_type_p): Delete code dealing with
+ a WITH_CLEANUP_EXPR, since we don't generate them any more.
+ * cvt.c (build_up_reference): Likewise.
+ * decl.c (grok_reference_init): Likewise.
+ (cp_finish_decl): Likewise.
+ * error.c (dump_expr): Likewise.
+ * tree.c (real_lvalue_p): Likewise.
+ (lvalue_p): Likewise.
+ (build_cplus_new): Likewise.
+ (unsave_expr_now): Likewise.
+ * typeck.c (unary_complex_lvalue, build_modify_expr,
+ c_expand_return): Likewise.
- * cp-method.c (hack_identifier): Also check for a TYPE_PTRMEMFUNC_P
- to see if something is a method.
+Tue Feb 6 13:39:22 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Dec 15 18:35:58 1993 Mike Stump <mrs@cygnus.com>
+ Make the C++ front-end pay attention to attributes for structures.
+ * class.c (finish_struct): New argument ATTRIBUTES, passed down into
+ finish_struct_1.
+ (finish_struct_1): New argument ATTRIBUTES; call cplus_decl_attributes.
+ Take out old round_up_size use and setting the DECL_ALIGN possibly
+ using it. Take out setting of TYPE_ALIGN to round_up_size, which
+ can override what the attribute set.
+ * cp-tree.h (finish_struct): Update prototype.
+ * parse.y (template_instantiate_once): Pass a NULL_TREE for the
+ attributes to finish_struct.
+ (structsp): For a CLASS decl, add maybe_attribute to rule and pass that
+ value down into finish_struct.
+ * Makefile.in (CONFLICTS): Switch to 7 shift/reduce conflicts.
- * cp-typeck.c (build_modify_expr): Avoid error messages on small
- enum bit fields.
- * cp-typeck.c (convert_for_assignment): Add missing argument to
- cp_warning and cp_pedwarn calls.
+Tue Feb 6 13:12:15 1996 Per Bothner <bothner@kalessin.cygnus.com>
-Wed Dec 15 18:25:32 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (poplevel): Re-word dead for local handling.
+ (pushdecl): Remove useless DECL_DEAD_FOR_LOCAL test.
+ (cp_finish_decl): If is_for_scope, check for duplicates so
+ we can disable is_for_scope. Otherwise, preserve_temp_slots.
- * cp-parse.y (member_init): ANSI C++ doesn't forbid old-style base
- initializers; it's just anachronistic.
+ * lex.c (do_identifier): Use global binding in preference of
+ dead for local variable.
- * cp-decl.c (finish_decl): Don't require external-linkage arrays
- to have a complete type at declaration time when pedantic.
+Mon Feb 5 17:46:46 1996 Mike Stump <mrs@cygnus.com>
-Tue Dec 14 11:37:23 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * init.c (initializing_context): Handle anon union changes, the
+ context where fields of anon unions can be initialized now has to be
+ found by walking up the TYPE_CONTEXT chain.
- * cp-decl.c (pushdecl): Don't set DECL_CONTEXT if it's already set.
+Fri Feb 2 14:54:04 1996 Doug Evans <dje@charmed.cygnus.com>
- * cp-call.c (build_method_call): Don't dereference pointer given
- as instance.
+ * decl.c (start_decl): #ifdef out code to set DECL_COMMON
+ if ASM_OUTPUT{,_ALIGNED}_BSS is defined.
+ (obscure_complex_init): If bss is supported, always set
+ DECL_INITIAL to error_mark_node.
- * cp-decl.c (finish_function): Don't pass pointer to
- build_method_call.
- (finish_function): Ditto.
+Thu Feb 1 16:19:56 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-typeck.c (build_x_function_call): Ditto.
+ * init.c (is_friend): Make sure there's a context before we see if
+ it's an aggr type.
- * cp-method.c (build_component_type_expr): Ditto.
+Thu Feb 1 15:44:53 1996 Mike Stump <mrs@cygnus.com>
- * cp-init.c (build_member_call): Ditto.
- (build_new): Ditto.
+ * init.c (is_friend): Classes are not friendly with nested classes.
-Mon Dec 13 18:04:33 1993 Kung Hsu (kung@cirdan.cygnus.com)
+Thu Feb 1 15:27:37 1996 Doug Evans <dje@charmed.cygnus.com>
- * cp-decl.c (xref_tag): fix regression created by changes made
- in Dec. 7 1993.
- * cp-decl.c (xref_defn_tag): fix parallel nested class problem.
+ * lex.c (check_newline): Pass last character read to HANDLE_PRAGMA,
+ and record its result.
-Fri Dec 10 12:40:25 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+Thu Feb 1 09:27:01 1996 Mike Stump <mrs@cygnus.com>
- * cp-call.c (compute_conversion_costs_ansi) [DEBUG_MATCHING]: Print
- out the final evaluation of the function, so we can see if ELLIPSIS,
- USER, and EVIL were set at the end.
+ * class.c (finish_struct_anon): Switch around code to not move anon
+ union elements around, nor mess up their contexts, nor offsets,
+ instead we now build up the right number of COMPONENT_REFs for all
+ the anon unions that may be present at build_component_ref time.
+ * typeck.c (lookup_anon_field): New routine to handle field lookup
+ on fields without names. We find them, based upon their unique type
+ instead.
+ * typeck.c (build_component_ref): Allow FIELD_DECL components.
+ Handle finding components in anonymous unions, and ensure that a
+ COMPONENT_REF is built for each level as necessary.
- * cp-call.c (convert_harshness_ansi): When the parm isn't an lvalue,
- only go for setting TRIVIAL_CODE if we are dealing with types that
- are compatible.
+Tue Jan 30 18:18:23 1996 Mike Stump <mrs@cygnus.com>
-Thu Dec 9 18:27:22 1993 Mike Stump <mrs@cygnus.com>
+ * cvt.c (build_up_reference): Make the INDIRECT_BIND case come after
+ code that ensures that copy ctors are used if appropriate.
- * cp-decl.c (flag_huge_objects): New flag to allow large objects.
- * toplev.c (lang_options): Ditto.
- * cp-decl2.c (flag_huge_objects, lang_f_options): Ditto.
- * cp-decl.c (delta_type_node): New type for delta entries.
- * cp-tree.h (delta_type_node): Ditto.
- * cp-decl.c (init_decl_processing): Setup delta_type_node.
- * cp-decl.c (init_decl_processing, build_ptrmemfunc_type): Use
- delta_type_node instead of short_integer_type_node.
- * cp-class.c (build_vtable_entry): Ditto.
+Tue Jan 30 17:35:14 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Thu Dec 9 16:19:05 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * init.c (build_vec_delete): Only give an error if base isn't an
+ error_mark_node.
- * cp-tree.h (OPERATOR_TYPENAME_P): Define outside of
- NO_{DOLLAR,DOT} macro checks, so it always gets defined.
- (VTABLE_NAME_P): Define for NO_DOT && NO_DOLLAR_IN_LABEL.
+Mon Jan 29 17:09:06 1996 Mike Stump <mrs@cygnus.com>
+
+ * spew.c (do_aggr): `new struct S;' isn't a forward declaration.
+ (yylex): If we see `new', keep slurping.
+
+Thu Jan 25 18:31:36 1996 Mike Stump <mrs@cygnus.com>
+
+ * class.c (finish_struct_1): Move code for handling anon unions...
+ (finish_struct_anon): to here. Fixup so that we do the offset
+ calculations right, and so that the fields are physically moved to
+ the containers's chain.
+
+Thu Jan 25 18:27:37 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * decl.c (grokdeclarator): Avoid trying to get an operand off an
+ identifier node.
+
+Wed Jan 24 11:25:30 1996 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * typeck.c (pointer_int_sum): Use TYPE_PRECISION (sizetype) not
+ POINTER_SIZE to agree with expr.c.
+
+Thu Jan 25 13:01:23 1996 Mike Stump <mrs@cygnus.com>
+
+ * search.c (lookup_field): Don't report ambiguities if protect is 0,
+ instead return NULL_TREE.
+
+Wed Jan 24 13:01:26 1996 Mike Stump <mrs@cygnus.com>
+
+ * class.c (finish_struct_1): Call warn_hidden if we want warnings
+ about overloaded virtual functions.
+ (warn_hidden): New routine to warn of virtual functions that are
+ hidden by other virtual functions, that are not overridden.
+ (get_basefndecls): New routine, used by warn_hidden.
+ (mark_overriders): New routine, used by warn_hidden.
+ * search.c (get_matching_virtual): Remove old warning that just
+ isn't very useful.
+
+Tue Jan 23 12:26:10 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * decl.c (output_builtin_tdesc_entries): #if 0 the function definition.
+
+ * typeck.c (null_ptr_cst_p): Delete unused fn.
+ (build_function_call_maybe): Delete unused fn.
+
+ * expr.c (extract_init): #if 0 the code after unconditional return 0
+ for now.
+
+ Delete old cadillac code.
+ * edsel.c: Remove file.
+ * Make-lang.in (CXX_SRCS): Take edsel.c off the list.
+ * Makefile.in (CXX_OBJS): Delete edsel.o.
+ (edsel.o): Delete rule.
+ * cp-tree.h (flag_cadillac): Delete var decl.
+ * lang-options.h: Delete "-fcadillac" and "-fno-cadillac".
+ * decl2.c (flag_cadillac): Delete var definition.
+ (lang_decode_option): Delete handling of -fcadillac and -fno-cadillac.
+ (grokfield): Delete code depending on flag_cadillac.
+ (finish_anon_union): Likewise.
+ * class.c (finish_struct_1): Likewise.
+ (pushclass): Likewise.
+ (popclass): Likewise.
+ (push_lang_context): Likewise.
+ (pop_lang_context): Likewise.
+ * decl.c (init_decl_processing): Likewise.
+ (start_decl): Likewise.
+ (cp_finish_decl): Likewise.
+ (xref_tag): Likewise.
+ (finish_enum): Likewise.
+ (start_function): Likewise.
+ (finish_function): Likewise.
+ (finish_stmt): Likewise.
+ * lex.c (lang_init): Likewise.
+ (check_newline): Likewise.
-Wed Dec 8 17:38:06 1993 Mike Stump <mrs@cygnus.com>
+ * lex.c (do_pending_inlines): Delete synthesized method kludge.
- * cp-decl.c (finish_decl): Make sure things that can go into
- "common", do go into common, if -fcommon is given.
+ Delete defunct, ancient garbage collection implementation.
+ * rtti.c: New file with the RTTI stuff from gc.c.
+ * gc.c: Removed file (moved the remaining stuff into rtti.c).
+ * Makefile.in (CXX_OBJS): Replace gc.o with rtti.o.
+ (rtti.o): New rule, replacing gc.o.
+ * Make-lang.in (CXX_SRCS): Replace gc.c with rtti.c.
+ * cp-tree.h: Delete gc-related fn decls.
+ (DECL_GC_OFFSET): Delete macro.
+ (flag_gc): Delete extern decl.
+ * decl.c (current_function_obstack_index): Delete var decl.
+ (current_function_obstack_usage): Delete var decl.
+ (start_function): Delete clearing of current_function_obstack_index
+ and current_function_obstack_usage.
+ (init_decl_processing): Delete code relying on -fgc.
+ Delete call to init_gc_processing.
+ (cp_finish_decl): Delete calls to build_static_gc_entry and
+ type_needs_gc_entry. Delete gc code setting DECL_GC_OFFSET.
+ (store_parm_decls): Delete -fgc calls to cp_expand_decl_cleanup
+ and to expand_expr of a __gc_main call.
+ (maybe_gc_cleanup): Delete var decl.
+ (finish_function): Delete call to expand_gc_prologue_and_epilogue.
+ * decl2.c (flag_gc): Delete var decl.
+ (lang_f_options): Delete offering of -fgc.
+ (lang_decode_option): Delete -fgc and -fno-gc handling.
+ (get_temp_regvar): Delete gc code.
+ * init.c (build_new): Delete gc code.
+ * lex.c (init_lex): Delete checking of flag_gc.
+
+ * typeck.c (convert_arguments): Delete gc code.
+ (build_component_addr): Delete -fgc warning.
+ (build_modify_expr): Delete gc code.
+
+ * decl2.c (build_push_scope): Delete fn.
+ * cp-tree.h (build_push_scope): Delete decl.
+
+ * search.c (clear_search_slots): Delete fn.
+ * cp-tree.h (clear_search_slots): Delete decl.
+
+ * search.c (tree_needs_constructor_p): Delete fn.
+ * cp-tree.h (tree_needs_constructor_p): Delete decl.
+
+ * tree.c (id_cmp): Delete fn.
+
+ * tree.c (set_fnaddr_from_vtable_entry): Delete fn.
+ * cp-tree.h (set_fnaddr_from_vtable_entry): Delete decl.
+
+ * tree.c (decl_value_member): Delete fn.
+ * cp-tree.h (decl_value_member): Delete decl.
+
+ * tree.c (list_hash_lookup_or_cons): Delete fn.
+ * cp-tree.h (list_hash_lookup_or_cons): Delete decl.
+
+ * method.c (cplus_exception_name): Delete fn.
+ (EXCEPTION_NAME_{PREFIX, LENGTH}): Delete macros.
+
+ * spew.c (shift_tokens): Delete fn.
+
+Mon Jan 22 17:49:33 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * except.c (init_exception_processing): Pass 1 to needs_pop in calls
+ to cp_finish_decl.
+ * parse.y: Likewise.
+
+Mon Jan 22 17:34:29 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * tree.c (build_cplus_staticfn_type): Delete function definition;
+ never used.
+ * cp-tree.h (build_cplus_staticfn_type): Delete decl.
+
+ * tree.c (virtual_member): Delete function definition; never used.
+ * cp-tree.h (virtual_member): Delete decl.
+
+Fri Jan 19 18:03:14 1996 Mike Stump <mrs@cygnus.com>
+
+ * typeck.c (build_component_ref): Handle getting vbase pointers
+ out of complex multiple inheritance better.
+
+Fri Jan 19 16:27:40 1996 Mike Stump <mrs@cygnus.com>
+
+ * typeck.c (build_object_ref): Make sure we use the real type, not
+ any reference type.
+
+Fri Jan 19 16:01:47 1996 Mike Stump <mrs@cygnus.com>
+
+ * tree.c (build_exception_variant): Don't create new types if we
+ don't have to, also build new types on the right obstack.
+
+Fri Jan 19 14:09:44 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Dec 8 13:01:54 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl.c (store_bindings): Split out from push_to_top_level.
+ (push_to_top_level): Call it for b->type_shadowed on class binding
+ levels.
- * cp-call.c (print_harshness) [DEBUG_MATCHING]: New function.
- (compute_conversion_costs_ansi) [DEBUG_MATCHING]: Print out
- argument matching diagnostics to make instantly clear what the
- compiler is doing.
+Fri Jan 19 13:53:14 1996 Mike Stump <mrs@cygnus.com>
- * cp-call.c (convert_harshness_ansi): If the parm isn't an lvalue,
- then check to see if the penalty was increased due to
- signed/unsigned mismatch, and use a TRIVIAL_CODE if it wasn't.
+ * search.c (expand_upcast_fixups): Fix so that offsets stored in
+ vbase_offsets are always right. Fixes a problem where virtual base
+ upcasting and downcasting could be wrong during conversions on this
+ during virtual function dispatch at ctor/dtor time when dynamic
+ vtable fixups for deltas are needed. This only sounds easier than
+ it is. :-)
+ (fixup_virtual_upcast_offsets): Change to reflect new calling
+ convention for expand_upcast_fixups.
-Tue Dec 7 18:29:14 1993 Kung Hsu (kung@cirdan.cygnus.com)
+Fri Jan 19 12:23:08 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-decl.c (xref_tag, pushtag): Fix nested class search/resolution
- problem.
+ * decl2.c (grokbitfield): Strip the NOPs from WIDTH before we
+ check that it's usable as the bitfield width.
-Tue Dec 7 16:09:34 1993 Jason Merrill (jason@deneb.cygnus.com)
+Wed Jan 17 21:22:40 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-class.c (finish_struct): Before synthesizing methods, if no
- methods have yet been declared then set nonprivate_method. Don't
- set non_private method after synthesizing a method.
+ * decl2.c (grokfield): Call cplus_decl_attributes with the attrlist.
+ Pass a null tree to grokdeclarator for its ATTRLIST arg, since it's
+ only ever used for functions in it.
- * cp-lex.c (extract_interface_info): If flag_alt_external_templates
- is set, tie emitted code to the location of template instantiation,
- rather than definition.
+Wed Jan 17 12:10:38 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-tree.h: Declare flag_alt_external_templates.
+ * parse.y (qualified_type_name): Use the TYPE_DECL, not the type.
+ (nested_type): Likewise.
+ (nested_name_specifier): Use lastiddecl.
- * cp-decl2.c (lang_decode_option): Support -falt-external-templates.
+ * decl.c (grokdeclarator): Adjust accordingly.
+ * init.c (expand_member_init): Likewise.
+ * parse.y (base_class): Likewise.
+ * typeck2.c (build_functional_cast): Likewise.
- * toplev.c (lang_options): Ditto.
+ * typeck2.c (build_functional_cast): Fill in name after we've
+ checked for non-aggr type.
- Mon Oct 4 12:50:02 1993 Chip Salzenberg (chip@fin.uucp)
+Wed Jan 17 10:18:01 1996 Mike Stump <mrs@cygnus.com>
- [changes propagated from 930810 snapshot]
- * cp-decl.c (init_decl_processing): Make long long available for use
- as SIZE_TYPE and PTRDIFF_TYPE.
- (finish_decl): Allow file-scope static incomplete array.
- (grokdeclarator): Don't pass on const and volatile fron function
- value type to function type.
- Warn here for volatile fn returning non-void type.
- * cp-parse.y (attrib): Accept attributes `volatile' with alias
- `noreturn', and `const'.
- * cp-typeck.c (default_conversion): Don't lose const and volatile.
- (build_binary_op_nodefault): Generate pedantic warning for comparison
- of complete pointer type with incomplete pointer type.
- (build_c_cast): Be careful that null pointer constant be INTEGER_CST.
+ * decl2.c (warn_pointer_arith): Default to on.
-Tue Dec 7 10:46:48 1993 Jason Merrill (jason@deneb.cygnus.com)
+Tue Jan 16 12:45:38 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-init.c (expand_vec_init): When creating a temporary for copying
- arrays, use the type of the source, not the target.
+ * lex.c (is_rid): New function.
+ * decl.c (grokdeclarator): Diagnose reserved words used as
+ declarator-ids.
- * cp-cvt.c (convert): Pass an argument for errtype to
- convert_to_reference.
+Tue Jan 16 11:39:40 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-error.c (dump_expr, COMPONENT_REF & CALL_EXPR): Deal with
- methods, -> and `this'.
+ * tree.c (get_decl_list): Don't lose cv-quals.
-Mon Dec 6 17:12:33 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (grokdeclarator): Fix SCOPE_REF handling and diagnose
+ typespecs used as declarator-ids.
- * cp-error.c (parm_as_string): New function; returns `this' or arg
- number. Corresponds to %P.
- (dump_expr): Deal with method calls.
+Tue Jan 16 11:09:42 1996 Mike Stump <mrs@cygnus.com>
- * cp-cvt.c (convert_to_reference): Stop using warn_for_assignment.
- * cp-typeck.c (convert_for_assignment): Ditto.
- (warn_for_assignment): Lose.
+ * decl.c (poplevel): When poping a level, don't give a warning for
+ any subblocks that already exist.
-Mon Dec 6 11:33:35 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+Tue Jan 16 00:25:33 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-call.c (ideal_candidate_ansi): Delete code that was never
- doing anything useful. Instead, sort once, and DO NOT wipe
- out any codes with EVIL_CODE, since that's what we use as a
- marker for the end of the list of candidates.
+ * typeck.c (build_object_ref): Finish what I started.
- * cp-cvt.c (convert_to_aggr): Make sure to always set H_LEN.
+ * parse.y (qualified_type_name): Don't check TYPE_BUILT_IN.
-Mon Dec 6 12:49:17 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (constructor_name_full): Handle TEMPLATE_TYPE_PARMs.
- * cp-init.c (get_aggr_from_typedef): New function, like
- is_aggr_typedef but returns the _TYPE.
+ * decl.c (grokdeclarator): Also accept TEMPLATE_TYPE_PARM as a
+ scope.
- * cp-call.c, cp-init.c, cp-method.c: Eradicate err_name.
+Mon Jan 15 16:19:32 1996 Jason Merrill <jason@yorick.cygnus.com>
-Sun Dec 5 18:12:48 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl.c (xref_tag): Handle passing a type in directly.
- * cp-lex.c (readescape): Pedwarn when a hex escape is out of range.
+ * parse.y (qualified_type_name): Pull out the type.
+ (nested_type): Likewise.
+ Take types directly instead of as identifiers.
+ * call.c (build_scoped_method_call): Take types directly instead of
+ as identifiers.
+ * decl.c (xref_basetypes): Likewise.
+ * init.c (expand_member_init): Likewise.
+ (build_member_call): Likewise.
+ (build_offset_ref): Likewise.
+ * typeck2.c (build_scoped_ref): Likewise, remove bogus code.
+ * method.c (do_build_assign_ref): Likewise.
+ * decl.c (grokdeclarator): Handle a type appearing as the
+ declarator-id for constructors.
+ * method.c (do_build_copy_constructor): current_base_init_list now
+ uses the types directly, not their names.
+ * init.c (sort_base_init): Likewise.
+ (expand_member_init): Likewise.
+ * init.c (is_aggr_type): New function, like is_aggr_typedef.
-Thu Nov 25 23:50:19 1993 Chip Salzenberg (chip@fin.uucp)
+Mon Jan 15 08:45:01 1996 Jeffrey A Law <law@cygnus.com>
- Delay language context change until beginning of next decl.
+ * tree.c (layout_basetypes): Call build_lang_field_decl instead
+ of build_lang_decl if first arg is a FIELD_DECL.
- * cp-lex.h (c_header_level): Removed.
- (pending_lang_change): Declared.
- * cp-lex.c (c_header_level): Renamed from in_c_header, made static.
- (pending_lang_change): Defined.
- (check_newline): Rework code that recognizes line number and
- filename changes. Instead of pushing and popping lang context,
- increment and decrement pending_lang_change.
- (do_pending_lang_change): Push and pop lang context according
- to value of pending_lang_change.
- * cp-parse.y (extdefs): Use lang_extdef instead of extdef.
- (extdef): Same as extdef, but call do_pending_lang_change() first.
+Thu Jan 11 14:55:07 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Mon Nov 15 15:39:15 1993 Chip Salzenberg (chip@fin.uucp)
+ * decl.c (cp_finish_decl): Only clear TREE_USED if DECL_NAME is
+ non-empty.
+ * except.c (expand_start_catch_block): Set TREE_USED to avoid
+ warnings about the catch handler.
- * cp-typeck.c (build_binary_op_nodefault): Warn for ordered
- compare of ptr with 0 only if pedantic in both cases.
+Mon Jan 8 17:35:12 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Nov 25 13:31:37 1993 Chip Salzenberg (chip@fin.uucp)
+ * typeck.c (build_modify_expr): Use a COMPOUND_EXPR instead of
+ expand_target_expr.
- Reinstate the below patch, which got lost in the Cygnus merge:
- Tue Nov 23 13:59:24 1993 Hallvard B Furuseth (hbf@durin.uio.no)
- * cp-parse.y (maybe_type_qual): Don't fail to set $$.
+Thu Jan 4 12:30:32 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Nov 17 19:03:30 1993 Chip Salzenberg (chip@fin.uucp)
+ Fix access control to use trees rather than integers.
+ * class.c (access_{default, public, protected, private,
+ default_virtual, public_virtual, private_virtual}_node): Add
+ definitions.
+ (init_class_processing): Do creation of those nodes.
+ * cp-tree.h (access_type): Delete enum decl.
+ (access_{default, public, protected, private, default_virtual,
+ public_virtual, private_virtual}_node): Add decls.
+ (compute_access): Change return type.
+ * search.c (compute_access): Have tree return type, instead of enum.
+ (lookup_field): Declare THIS_V and NEW_V to be tree nodes.
+ * lex.c (real_yylex): Use yylval.ttype for giving the value of the
+ access_* node for each of RID_{PUBLIC, PRIVATE, PROTECTED}.
+ * parse.y (VISSPEC): Make ttype rather than itype.
+ (base_class_access_list): Likewise.
+ * *.[cy]: Change all refs of `access_public' to `access_public_node',
+ etc.
+ * call.c (build_method_call): Make ACCESS be a tree.
+ * class.c (alter_access, finish_struct_1, filter_struct): Likewise.
+ * cvt.c (convert_to_aggr): Likewise.
+ * init.c (build_offset_ref, resolve_offset_ref, build_delete):
+ Likewise.
+ * method.c (hack_identifier): Likewise.
+ * typeck.c (build_component_ref_1, build_component_ref): ): Likewise.
- * cp-parse.y (attrib): Allow "ident(ident)" like the C front end.
+Thu Jan 4 11:02:20 1996 Mike Stump <mrs@cygnus.com>
-Fri Oct 22 20:43:37 1993 Paul Eggert (eggert@twinsun.com)
+ * typeck.c (pointer_int_sum, pointer_diff): Make code agree with C
+ frontend, and make it more consistent with respect to
+ warn_pointer_arith.
- * cp-lex.c (real_yylex): Diagnose floating point constants
- that are too large.
+Tue Jan 2 00:13:38 1996 Rusty Russell <rusty@adelaide.maptek.com.au>
-Wed Nov 17 19:10:37 1993 Chip Salzenberg (chip@fin.uucp)
+ * decl.c (pushdecl): Check for duplicate parameter names.
- * cp-type2.c (build_functional_cast): ARM page 16: When a class
- and an object, function or enumerator are declared in the same
- scope with the same name, the class name is hidden.
+Wed Jan 3 09:25:48 1996 Mike Stump <mrs@cygnus.com>
-Wed Nov 17 19:07:18 1993 Chip Salzenberg (chip@fin.uucp)
+ * decl.c (expand_static_init): Call assemble_external for atexit.
- * cp-call.c (convert_harshness_ansi): Distinguish float, double,
- and long double from each other when overloading.
- (compute_conversion_costs_{ansi,old}, build_method_call,
- build_overlay_call_real, convert_to_aggr): Always set and
- always use H_LEN member of candidate structure.
+Wed Jan 3 07:55:19 1996 Mike Stump <mrs@cygnus.com>
-Mon Oct 11 23:10:53 1993 Chip Salzenberg (chip@fin.uucp)
+ * except.c (do_unwind): Remove some generated dead code.
+ (eh_outer_context): New routine, factor out some common code from
+ expand_builtin_throw and end_eh_unwinder. Add code to do return
+ address masking for the PA.
+ (expand_builtin_throw): Use eh_outer_context instead of open coding
+ it here.
+ (end_eh_unwinder): Likewise.
+
+Tue Jan 2 17:00:56 1996 Mike Stump <mrs@cygnus.com>
+
+ * except.c (expand_throw): Call assemble_external for __empty, if we
+ use it.
- * cp-decl.c (duplicate_decls): Note redeclarations of library
- functions, and generate distinct warnings for them.
+Thu Dec 28 11:13:15 1995 Mike Stump <mrs@cygnus.com>
-Mon Oct 4 12:26:49 1993 Chip Salzenberg (chip@fin.uucp)
+ * except.c (expand_builtin_throw): Use RETURN_ADDR_OFFSET instead of
+ NORMAL_RETURN_ADDR_OFFSET.
+ (end_eh_unwinder): Likewise.
- Support format warnings in G++.
+Wed Dec 27 22:18:16 1995 Mike Stump <mrs@cygnus.com>
- * cp-tree.h: Protect against multiple inclusion.
- Declare all public functions in c-common.c (copy from c-tree.h).
- (STDIO_PROTO): Define.
- (warn_format): Declare.
- (record_format_info): Remove declaration.
- * cp-decl.c (init_decl_processing): Call init_function_format_info.
- * cp-decl2.c (lang_decode_option): Make "-Wall" include warn_format.
- * cp-typeck.c (build_function_call_real): Call check_function_format.
- (record_format_info): Remove -- obsolete stub.
+ * gc.c (build_dynamic_cast): Make sure we don't cast away const
+ when dealing with references, and make sure we handle dynamic
+ casting to a cv qualified reference.
-Sat Jul 24 12:04:29 1993 Chip Salzenberg (chip@fin.uucp)
+Thu Dec 21 23:50:35 1995 Mike Stump <mrs@cygnus.com>
- * cp-decl.c (duplicate_decls): Don't warn for non-extern var decl
- following an extern one (for -Wredundant-decls).
- * cp-parse.y (primary): In statement expression case, if compstmt
- returns something other than a BLOCK, return it unchanged.
+ * except.c (struct eh_context): New structure top hold eh context
+ information.
+ (push_eh_context): New routine.
+ (pop_eh_context): Likewise.
+ * decl.c (push_cp_function_context): Use them.
+ (pop_cp_function_context): Likewise.
-Thu Dec 2 20:44:58 1993 Chip Salzenberg (chip@fin.uucp)
+Wed Dec 20 12:42:51 1995 Jason Merrill <jason@yorick.cygnus.com>
- * cp-decl.c (warn_extern_redeclared_static): New function made
- from code extracted from pushdecl.
- (duplicate_decls, pushdecl): Call new function.
- (lookup_name_current_level): Allow for IDENTIFIER_GLOBAL_VALUE
- to be a TREE_LIST when function is declared in 'extern "C" {}'.
+ * decl2.c (finish_file): Also prune uninteresting functions in the
+ inline emission loop.
-Fri Dec 3 16:01:10 1993 Jason Merrill (jason@deneb.cygnus.com)
+Wed Dec 20 02:32:07 1995 Jeffrey A Law <law@cygnus.com>
- * cp-class.c (duplicate_tag_error): Use cp_error.
- (finish_base_struct): Check for ambiguity with direct base, and don't
- generate op= or copy ctor if it exists.
+ * sig.c (build_signature_table_constructor): Mark functions
+ in the signature as referenced.
-Fri Dec 3 15:32:34 1993 Kung Hsu (kung@cirdan.cygnus.com)
+Tue Dec 19 22:36:56 1995 Jason Merrill <jason@yorick.cygnus.com>
- * cp-init.c (expand_member_init): when initializer name is null,
- don't try to build it now because emit_base_init will handle it.
+ * decl2.c (finish_file): Do all the vtable/synthesis stuff before
+ the inline emission stuff.
-Fri Dec 3 12:28:59 1993 Jason Merrill (jason@deneb.cygnus.com)
+Mon Dec 18 15:51:33 1995 Jason Merrill <jason@yorick.cygnus.com>
- * cp-lex.c (init_lex): Initialize input_filename to "<internal>" for
- code such as ExceptionHandler::operator=.
+ * cp-tree.h, decl2.c (flag_weak): New flag to control the use of
+ weak symbols.
+ * lang-options.h: Add -f{no-,}weak.
+ * decl.c (init_decl_processing): If the target does not support weak
+ symbols, don't use them.
+ * decl2.c, pt.c: s/SUPPORTS_WEAK/flag_weak/.
-Fri Dec 3 10:32:08 1993 Jason Merrill (jason@deneb.cygnus.com)
+Sun Dec 17 21:13:23 1995 Rusty Russell <rusty@adelaide.maptek.com.au>
- * cp-decl.c (grokdeclarator): Don't try to print out dname when
- complaining about arrays of references if decl_context==TYPENAME,
- since it will be null.
+ * init.c (expand_member_init): warning for base init after members.
- * cp-decl2.c: Default to flag_ansi_overloading.
+Fri Dec 15 15:32:18 1995 Jason Merrill <jason@yorick.cygnus.com>
-Thu Dec 2 18:05:56 1993 Kung Hsu (kung@cirdan.cygnus.com)
+ * cvt.c (build_expr_type_conversion): Don't convert to a reference
+ type.
- * cp-call.c (build_method_call): use binfo from instance if it's
- different from binfo (basetype_path) passed from above.
+Thu Dec 14 16:05:58 1995 Mike Stump <mrs@cygnus.com>
+
+ * method.c (report_type_mismatch): Improve wording for volatile
+ mismatches.
+
+Thu Dec 14 14:16:26 1995 Mike Stump <mrs@cygnus.com>
+
+ * init.c (expand_aggr_init_1): Use expand_aggr_init_1 instead of
+ expand_assignment, as the later doesn't handle things that have
+ copy constructors well. The compiler would do bitwise copying,
+ instead of ctor calling in some cases.
+
+Wed Dec 13 17:05:54 PST 1995 Paul Eggert <eggert@twinsun.com>
+
+ * g++.c (my_strerror): Return "cannot access" if errno is 0.
+ (pfatal_with_name, perror_exec): Don't assume that
+ the returned value from my_strerror contains no '%'s.
+ (concat): Remove.
+ (sys_nerror): Declare only if HAVE_STRERROR is not defined.
+
+Wed Dec 13 16:22:38 1995 Jason Merrill <jason@yorick.cygnus.com>
+
+ Lose CLASSTYPE_METHODS/DECL_NEXT_METHOD chain; make
+ TYPE_METHODS/TREE_CHAIN mean what they used to.
+ * decl2.c (constructor_name_full): Refer to CLASSTYPE_METHOD_VEC
+ instead of TYPE_METHODS.
+ * decl.c (duplicate_decls): Lose references to DECL_NEXT_METHOD.
+ * tree.c (tree_copy_lang_decl_for_deferred_output): Likewise.
+ * cp-tree.h (CLASSTYPE_METHODS): Lose.
+ (CLASSTYPE_METHOD_VEC): Point to lang_spec->methods instead of
+ TYPE_METHODS.
+ (struct lang_decl): Lose next_method field.
+ (DECL_NEXT_METHOD): Lose.
+ * class.c (finish_struct_methods): Don't mess with TYPE_METHODS.
+ (finish_struct): Just use TYPE_METHODS; we don't need fn_fields
+ anymore.
+ (finish_struct_methods): Don't mess with the TREE_CHAINs in
+ fn_fields.
-Thu Dec 2 12:48:36 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * search.c (add_conversions): Don't use TREE_CHAIN to traverse method
+ vector.
-Wed Nov 17 19:14:29 1993 Chip Salzenberg (chip@fin.uucp)
+ * call.c (build_method_call): Synthesize here even when not inlining.
+ * typeck.c (build_function_call_real): Likewise.
- cp-error.c (dump_expr): Use unsigned chars to output a
- TREE_REAL_CST in hex.
+Wed Dec 13 15:02:39 1995 Ian Lance Taylor <ian@cygnus.com>
-Thu Dec 2 11:05:48 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * cp/lex.c (check_newline): If DBX_DEBUGGING_INFO and write_symbols
+ == DBX_DEBUG, call dbxout_start_new_source_file and
+ dbxout_resume_previous_source_file when appropriate.
- * cp-class.c (finish_struct): Fix typo in setting
- cant_synth_asn_ref.
+Tue Dec 12 20:38:55 1995 Mike Stump <mrs@cygnus.com>
- * cp-tree.h (TYPE_NESTED_NAME): New macro, does
- DECL_NESTED_TYPENAME (TYPE_NAME (NODE)).
+ * except.c (start_anon_func): Push to the top level.
+ (end_anon_func): Pop from the top level.
- * cp-lex.c (default_copy_constructor_body): Change
- DECL_NAME (TYPE_NAME (btype)) to TYPE_NESTED_NAME (btype).
- (default_assign_ref_body): Ditto.
- (default_copy_constructor_body): Call operator= explicitly for
- base classes that have no constructor.
+Mon Dec 11 18:56:14 1995 Mike Stump <mrs@cygnus.com>
-Thu Dec 2 10:47:15 1993 Michael Tiemann (tiemann@blues.cygnus.com)
+ * cp-tree.h (build_cleanup): New routine to build cleanups.
+ * decl.c (expand_static_init): Use build_cleanup to build a cleanup
+ call at ctor time and use atexit to run it later.
+ * decl2.c (build_cleanup): New routine, taken from finish_file.
+ (finish_file): Use build_cleanup instead, and don't put function
+ local statics in global dtor list.
+
+Wed Dec 6 14:34:29 1995 Mike Stump <mrs@cygnus.com>
+
+ * except.c (expand_throw): Ensure that we have cleanups, if we try
+ and expand cleanups.
+
+Wed Dec 6 11:48:21 1995 Mike Stump <mrs@cygnus.com>
+
+ * except.c (expand_throw): Add logic to manage dynamic cleanups for
+ the EH object.
+ (expand_end_catch_block): Use the magic of expand_goto, instead of
+ emit_jump so that we get the cleanup for any catch clause parameter
+ and the cleanup for the exception object. Update to reflect label
+ changes.
+ (push_eh_cleanup): New routine to register a cleanup for an
+ exception object.
+ (empty_fndecl): Used to default cleanup actions to
+ nothing.
+ (init_exception_processing): Setup empty_fndecl. Setup
+ saved_cleanup.
+ (expand_start_catch_block): Update to reflect label changes. Call
+ push_eh_object to register the cleanup for the EH object.
+ (start_anon_func): New routine to start building lambda expressions
+ from trees.
+ (end_anon_func): New routine to end them.
+ (struct labelNode): Change so that we can use tree labels, or rtx
+ labels.
+ (saved_cleanup): Object to check for dynamic cleanups for the
+ exception handling object.
+ (push_label_entry): Change so that we can use tree labels, or rtx
+ labels.
+ (pop_label_entry): Likewise.
+ (top_label_entry): Likewise.
+ (expand_start_all_catch): Use tree label instead of rtx label, so
+ that we can get the magic of expand_goto.
+ (expand_end_all_catch): Update to reflect label changes.
+
+ * class.c (build_vfn_ref): Remove building_cleanup logic, as we now
+ use UNSAVE_EXPRs.
+ typeck.c (get_member_function_from_ptrfunc): Remove remnants of
+ building_cleanup logic, as we now use UNSAVE_EXPRs.
+ * cp-tree.h (unsave_expr): Declare it.
+ * decl.c (building_cleanup): Remove.
+ (maybe_build_cleanup): Remove building_cleanup logic, and use
+ UNSAVE_EXPR instead.
+
+Sun Dec 3 01:34:58 1995 Mike Stump <mrs@cygnus.com>
+
+ * gc.c (build_t_desc): Update error message to say <typeinfo>.
+
+Thu Nov 30 12:30:05 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * decl.c (pushdecl): Only warn about shadowing a local variable if
+ warn_shadow is true.
+
+Sun Nov 26 16:06:55 1995 Rusty Russell <rusty@adelaide.maptek.com.au>
+
+ * typeck.c (build_binary_op_nodefault): Added warning about
+ comparisons between different enum types with -Wall, unless
+ -fenum-int-equiv set.
+
+Wed Nov 22 15:44:02 1995 Mike Stump <mrs@cygnus.com>
+
+ * class.c (finish_struct_1): Skip down to the inner type in
+ multidimensional arrays. Ensures ctors will be made for types that
+ need constructing.
+
+Wed Nov 22 14:19:22 1995 Mike Stump <mrs@cygnus.com>
+
+ * decl.c (last_dtor_insn): New to track the last compiler generated
+ insn in a dtor.
+ (store_parm_decls): Set it.
+ (finish_function): Use it to see if the dtor is empty. Avoid doing
+ vtable setup all the time, if we can.
+ (struct cp_function): Add last_dtor_insn.
+ (push_cp_function_context): Save it.
+ (pop_cp_function_context): Restore it.
- * cp-call.c (build_method_call): If the instance variable is
- converted to error_mark_node when we're trying to convert it to the
- base type of a method we're looking up, return error_mark_node.
+Wed Nov 22 11:52:19 1995 Paul Russell <Rusty.Russell@adelaide.maptek.com.au>
-Thu Dec 2 10:41:16 1993 Torbjorn Granlund (tege@cygnus.com)
+ * typeck.c (build_unary_op): Set TREE_NO_UNUSED_WARNING to avoid
+ warnings.
- * cp-typeck.c (build_binary_op_nodefault): In *_DIV_EXPR *_MOD_EXPR
- cases, tests for unsigned operands by peeking inside a NOP_EXPR.
+Tue Nov 21 17:15:23 1995 Mike Stump <mrs@cygnus.com>
-Wed Dec 1 13:33:34 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * typeck.c (expand_target_expr): Make sure targets get put into the
+ current temp_slot_level, so that the free_temp_slots call will reuse
+ them.
- * cp-call.c (compute_conversion_costs_ansi): Use the size of struct
- harshness_code, not the size of short, for clearing out the
- ansi_harshness.
+Tue Nov 21 13:32:03 1995 Mike Stump <mrs@cygnus.com>
- * cp-call.c (print_candidates): New function.
- (build_method_call): When we had some candidates, but didn't get a
- usable match, don't report that we got an error with the first
- candidate. Instead, say there were no matches, and list the
- candidates with print_candidates. In the second pass, make sure we
- clear out ever_seen, so we can accurately count the number of
- functions that qualified.
+ * class.c (finish_struct_1): Delay delta fixups for virtual bases
+ until after we have done the hard virtuals, to avoid a bogus `every
+ virtual function must have a unique final overrider' for virtual
+ functions that are only overridden by hard virtuals.
-Wed Dec 1 09:53:59 1993 Torbjorn Granlund (tege@cygnus.com)
+Thu Nov 9 13:35:30 1995 Jason Merrill <jason@yorick.cygnus.com>
- * cp-typeck.c (build_binary_op_nodefault): Shorten for *_MOD_EXPR
- only if op1 is known to be != -1.
- (build_binary_op_nodefault): Handle *_DIV_EXPR likewise.
+ * pt.c (do_function_instantiation): Don't try to find a file-scope
+ template for a member function.
-Tue Nov 30 14:07:26 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+Tue Nov 14 06:20:35 1995 Mike Stump <mrs@cygnus.com>
- * cp-method.c (hack_identifier): If the field itself is private, and
- not from a private base class, say so.
+ * g++.c (main): Add handling of -nodefaultlibs.
-Mon Nov 29 03:00:56 1993 Jason Merrill (jason@deneb.cygnus.com)
+Mon Nov 13 15:45:34 1995 Mike Stump <mrs@cygnus.com>
- * cp-decl.c (grokdeclarator): Always warn on initialization of
- const member.
+ * cp-tree.h (INDIRECT_BIND): Add a way for the frontend to
+ distinguish between direct bindings of reference variables, and
+ indirect bindings of reference variables.
+ * cvt.c (build_up_reference): Use it.
+ * typeck.c (convert_arguments): Use it to indicate this is an
+ indirect binding.
+ * decl.c (cp_finish_decl): Ensure that we reuse stack slots as fast
+ as they are unused.
+ (expand_static_init): Likewise.
+ (cplus_expand_expr_stmt): Likewise.
+ * decl2.c (finish_file): Likewise.
+ * init.c (perform_member_init): Likewise.
+ (emit_base_init): Likewise.
+ (expand_aggr_vbase_init_1): Likewise.
-Wed Nov 24 00:49:35 1993 Jason Merrill (jason@deneb.cygnus.com)
+Fri Nov 10 09:18:09 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-class.c (finish_struct): Set TYPE_GETS_CONST_* properly.
- (finish_base_struct): Set cant_synth_asn_ref properly.
+ * decl.c (push_namespace): Rewrite to use build_lang_decl, so we
+ get a DECL_LANG_SPECIFIC node.
+ * cp-tree.h (lang_decl_flags): Add new member `level'.
+ (NAMESPACE_LEVEL): Don't use decl.arguments, instead use the
+ decl_flags level member.
- * cp-lex.c (cons_up_default_function): Add section for operator=.
- (default_assign_ref_body): New function, mostly cribbed from
- default_copy_constructor_body.
+Mon Nov 6 18:36:13 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-class.c (base_info): Add members cant_synth_copy_ctor,
- cant_synth_asn_ref, no_const_asn_ref.
- (finish_base_struct): Update no_const_asn_ref, note that you should
- update cant_synth_*, propagate TYPE_GETS_ASSIGN_REF.
- (finish_struct): Add decls for cant_synth_*, no_const_asn_ref, and
- initialize them properly. Set no_const_asn_ref properly. Set
- cant_synth_* in some of the situations where they should be set.
- Propagate TYPE_GETS_ASSIGN_REF. Use cant_synth_copy_ctor. Add call
- to cons_up_default_function for operator=.
+ * call.c (build_method_call): Make sure instance has a
+ TYPE_LANG_SPECIFIC node before we dive into it.
-Tue Nov 23 20:24:58 1993 Mike Stump <mrs@cygnus.com>
+Sat Nov 4 20:01:52 1995 Jason Molenda <crash@phydeaux.cygnus.com>
- * cp-cvt.c (convert_force): Add code to perform casting of pointer
- to member function types.
- * cp-typeck.c (build_ptrmemfunc): Add FORCE parameter to indicate
- when the conversion should be done, regardless.
- * cp-tree.h (build_ptrmemfunc): Ditto.
- * cp-type2.c (digest_init): Ditto.
- * cp-typeck.c (convert_for_assignment): Ditto.
+ * method.c (make_thunk): use TREE_SET_CODE to set thunk's tree code.
-Tue Nov 23 18:06:58 1993 Jason Merrill (jason@deneb.cygnus.com)
+Thu Nov 2 17:56:57 1995 Mike Stump <mrs@cygnus.com>
- * cp-error.c (dump_expr): Do the right thing for variables of
- reference type.
+ * decl.c (duplicate_decls): When smashing decls, smash staticness in
+ the usual way.
- * cp-decl.c (grok_op_properties): Set TYPE_HAS_ASSIGN_REF
- and its kin properly.
- (xref_tag): Propagate TYPE_GETS_ASSIGN_REF.
+Thu Nov 2 16:44:02 1995 Mike Stump <mrs@cygnus.com>
-Tue Nov 23 12:26:13 1993 Mike Stump <mrs@cygnus.com>
+ * decl.c (poplevel): Handle the merging of subblocks of cleanups
+ when finishing blocks that have already been created (usually due to
+ the fixup goto code). Fixes bad debugging information.
- * cp-method.c (build_opfncall): Don't count pointer to member
- functions as aggregates here, as we don't want to look up methods in
- them. The compiler would core dump if we did, as they don't have
- normal names.
- * cp-typeck.c (build_indirect_ref): Improve wording on error
- message.
+Wed Nov 1 12:33:53 1995 Jason Merrill <jason@yorick.cygnus.com>
-Mon Nov 22 14:22:23 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * method.c (hack_identifier): Don't abort when we get a TREE_LIST
+ that's not a list of overloaded functions.
- * cp-decl.c (grok_op_properties): Allow operator?: with pedwarn
- (since it's supported in other compiler bits).
+Wed Nov 1 11:38:58 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-method.c (report_type_mismatch): Use cp_error; ignore err_name
- argument.
+ * decl2.c (mark_vtable_entries): Check DECL_LANG_SPECIFIC on fn
+ before trying to use DECL_ABSTRACT_VIRTUAL_P.
- * cp-error.c (dump_function_decl): Don't print return type for
- constructors and destructors.
+Tue Oct 31 11:56:55 1995 Jason Merrill <jason@yorick.cygnus.com>
- * cp-cvt.c (cp_convert_to_pointer): Import code from
- convert_to_pointer so we can return error_mark_node in the case of an
- error, and to allow more meaningful error messages.
- (build_type_conversion): Don't go through void* when trying
- to convert to a pointer type.
+ * decl2.c (mark_used): New function for hooking into setting of
+ TREE_USED on decls.
+ * call.c (build_method_call): Use it.
+ * class.c (instantiate_type): Likewise.
+ * init.c (build_offset_ref): Likewise. Don't call assemble_external
+ for all like-named functions.
+ * method.c (hack_identifier): Likewise.
+ (emit_thunk): Don't call assemble_external.
+ (make_thunk): Create thunk as a FUNCTION_DECL so that it
+ gets the right mode and ENCODE_SECTION_INFO works.
+
+ * parse.y: Use mark_used. Pass operator names to do_identifier.
+ * lex.c (do_identifier): Handle operator names.
- * cp-decl.c (grokfndecl): Move call to grok_op_properties back
- after grokclassfn so that it's dealing with the right decl.
- (grok_op_properties): Don't assert !methodp for op new and op delete.
+ * decl2.c (grokclassfn): Tweak __in_chrg attributes.
- * cp-init.c (build_delete): Don't use TYPE_BUILT_IN (there are now
- no uses of it in the compiler).
+Thu Oct 26 16:45:58 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-call.c (build_scoped_method_call): Fix for destructors of simple
- types.
- (build_method_call): Ditto.
+ * errfn.c: Include stdio.h.
+ (cp_sprintf): Take out decl of sprintf, and cast sprintf to errorfn*.
-Fri Nov 19 12:59:38 1993 Jason Merrill (jason@deneb.cygnus.com)
+Wed Oct 25 18:58:41 1995 Mike Stump <mrs@cygnus.com>
- * cp-tree.c (count_functions): Abstraction function.
+ * typeck2.c (digest_init): Always convert initializers to the
+ right type.
- * cp-call.c (build_overload_call_real): Deal with new overloading
- properly, remove dead code.
+Wed Oct 25 13:25:24 1995 Mike Stump <mrs@cygnus.com>
- * gcc.c (default_compilers): Generate and use .ii files in the
- intermediate stage of compiling C++ source.
+ * init.c (member_init_ok_or_else): Don't allow member initializers
+ for indirect members, as it is invalid.
-Fri Nov 19 11:26:09 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+Wed Oct 25 11:35:28 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-expr.c (cplus_expand_expr): Make call_target a valid memory
- address before using it, so it can be later safely compared.
+ * decl.c (grokdeclarator): Don't allow `friend signed ()'.
-Fri Nov 12 15:30:27 1993 Jason Merrill (jason@deneb.cygnus.com)
+Fri Oct 20 10:30:59 1995 Mike Stump <mrs@cygnus.com>
- * cp-pt.c (tsubst): Deal with new overloading.
+ * parse.y (for.init.statement): Catch compound statements inside for
+ initializations, if we're being pedantic.
- * cp-typeck.c (fntype_p): is the arg function type?
- (comp_target_parms): pedwarn on conversion from (anything) to (...).
- (build_x_function_call): Deal with new overloading.
+Fri Oct 20 10:03:42 1995 Mike Stump <mrs@cygnus.com>
- * cp-tree.c (decl_list_length): Deal with new overloading.
- (decl_value_member): Like value_member, but for DECL_CHAINs.
+ * decl.c (lookup_tag): Return NULL_TREE if we don't find what we are
+ looking for.
- * cp-decl.c (duplicate_decls): Deal with new overloading.
- (start_decl): Ditto.
+Thu Oct 19 14:26:10 1995 Mike Stump <mrs@cygnus.com>
- * cp-class.c (instantiate_type): Deal with new overloading.
+ * error.c (dump_expr): Don't core dump when a boolean expression is
+ used as a default argument.
- * cp-call.c (convert_harshness_ansi): Deal with new overloading.
- (convert_harshness_old): Deal with new overloading.
- (build_overload_call_real): Ditto.
+Thu Oct 19 10:36:30 1995 Jason Merrill <jason@yorick.cygnus.com>
-Mon Nov 8 13:50:49 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * class.c (finish_struct_bits): Check aggregate_value_p instead of
+ RETURN_IN_MEMORY.
- * cp-tree.c (get_unique_fn): New function; returns FUNCTION_DECL
- if unambiguous, NULL_TREE otherwise.
- (get_first_fn): Returns the first appropriate FUNCTION_DECL.
- (is_overloaded_fn): Returns whether or not the passed tree is
- a function or list of functions.
+Wed Oct 18 18:12:32 1995 Jason Merrill <jason@yorick.cygnus.com>
- * cp-init.c (init_init_processing): use `get_first_fn' to find
- the FUNCTION_DEFN for new and delete.
+ * class.c (finish_struct_bits): Also set TREE_ADDRESSABLE on a
+ BLKmode type that would otherwise be returned in registers.
- * cp-decl.c (push_overloaded_decl): Use new overloading strategy, cut
- code size in half (I spit on special cases).
+Mon Oct 16 12:32:19 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue Sep 7 20:03:33 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * g++.c (WITHLIBC): New macro.
+ (main): Declare saw_libc. Use WITHLIBC if `-lc' was used; set
+ saw_libc and pass it at the end if it was set.
- * cp-decl.c: Allow references and template type parameters as well
+Wed Oct 11 16:30:34 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-Local Variables:
-eval: (auto-fill-mode)
-left-margin: 8
-fill-column: 76
-End:
+ * parse.y (fn.def1): Call split_specs_attrs in
+ declmods notype_declarator case.
diff --git a/contrib/gcc/cp/Make-lang.in b/contrib/gcc/cp/Make-lang.in
index c9d0a39..be02cf1 100644
--- a/contrib/gcc/cp/Make-lang.in
+++ b/contrib/gcc/cp/Make-lang.in
@@ -1,5 +1,5 @@
# Top level makefile fragment for GNU C++.
-# Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
#This file is part of GNU CC.
@@ -35,7 +35,7 @@
# - making any compiler driver (eg: g++)
# - the compiler proper (eg: cc1plus)
# - define the names for selecting the language in LANGUAGES.
-
+#
# Extra flags to pass to recursive makes.
CXX_FLAGS_TO_PASS = \
"CXX_FOR_BUILD=$(CXX_FOR_BUILD)" \
@@ -45,39 +45,69 @@ CXX_FLAGS_TO_PASS = \
# Actual names to use when installing a native compiler.
CXX_INSTALL_NAME = `t='$(program_transform_name)'; echo c++ | sed $$t`
GXX_INSTALL_NAME = `t='$(program_transform_name)'; echo g++ | sed $$t`
+DEMANGLER_INSTALL_NAME = `t='$(program_transform_name)'; echo c++filt | sed $$t`
# Actual names to use when installing a cross-compiler.
CXX_CROSS_NAME = `t='$(program_transform_cross_name)'; echo c++ | sed $$t`
GXX_CROSS_NAME = `t='$(program_transform_cross_name)'; echo g++ | sed $$t`
+DEMANGLER_CROSS_NAME = `t='$(program_transform_cross_name)'; echo c++filt | sed $$t`
# The name to use for the demangler program.
-DEMANGLER_PROG = c++filt
-
+DEMANGLER_PROG = c++filt$(exeext)
+
+# Extra headers to install.
+CXX_EXTRA_HEADERS = $(srcdir)/cp/inc/typeinfo $(srcdir)/cp/inc/exception \
+ $(srcdir)/cp/inc/new $(srcdir)/cp/inc/new.h
+
+# Extra code to include in libgcc2.
+CXX_LIB2FUNCS = tinfo.o tinfo2.o new.o opnew.o opnewnt.o opvnew.o opvnewnt.o \
+ opdel.o opdelnt.o opvdel.o opvdelnt.o exception.o
+CXX_LIB2SRCS = $(srcdir)/cp/new.cc $(srcdir)/cp/new1.cc $(srcdir)/cp/new2.cc \
+ $(srcdir)/cp/exception.cc $(srcdir)/cp/tinfo.cc \
+ $(srcdir)/cp/tinfo2.cc $(srcdir)/cp/tinfo.h
+#
# Define the names for selecting c++ in LANGUAGES.
# Note that it would be nice to move the dependency on g++
# into the C++ rule, but that needs a little bit of work
# to do the right thing within all.cross.
-C++ c++: cc1plus
+C++ c++: cc1plus$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: C++ c++
+g++.c: $(srcdir)/gcc.c
+ -rm -f $@
+ $(LN_S) $(srcdir)/gcc.c $@
+
+g++spec.o: $(srcdir)/cp/g++spec.c
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/cp/g++spec.c
+
+# N.B.: This is a copy of the gcc.o rule, with -DLANG_SPECIFIC_DRIVER added.
+# It'd be nice if we could find an easier way to do this---rather than have
+# to track changes to the toplevel gcc Makefile as well.
+# We depend on g++.c last, to make it obvious where it came from.
+g++.o: $(CONFIG_H) multilib.h config.status $(lang_specs_files) g++.c \
+ system.h
+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(DRIVER_DEFINES) \
+ -DLANG_SPECIFIC_DRIVER \
+ -c g++.c
+
# Create the compiler driver for g++.
-g++: $(srcdir)/cp/g++.c $(CONFIG_H) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) -o $@ $(srcdir)/cp/g++.c $(LIBS)
+g++$(exeext): g++.o g++spec.o version.o choose-temp.o pexecute.o prefix.o mkstemp.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ g++.o g++spec.o prefix.o \
+ version.o choose-temp.o pexecute.o mkstemp.o $(EXTRA_GCC_OBJS) $(LIBS)
# Create a version of the g++ driver which calls the cross-compiler.
-g++-cross: $(srcdir)/cp/g++.c version.o $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) -o $@ \
- -DGCC_NAME=\"$(GCC_CROSS_NAME)\" $(srcdir)/cp/g++.c version.o $(LIBS)
+g++-cross$(exeext): g++$(exeext)
+ -rm -f g++-cross$(exeext)
+ cp g++$(exeext) g++-cross$(exeext)
cxxmain.o: cplus-dem.c demangle.h
rm -f cxxmain.c
- ln -s $(srcdir)/cplus-dem.c cxxmain.c > /dev/null 2>&1 \
- || cp $(srcdir)/cplus-dem.c cxxmain.c
+ $(LN_S) $(srcdir)/cplus-dem.c cxxmain.c
$(CC) -c -DMAIN $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DVERSION=\"$(version)\" cxxmain.c
- rm -f cxxmain.c
$(DEMANGLER_PROG): cxxmain.o underscore.o getopt.o getopt1.o $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) $(LIBS) -o $@ \
@@ -86,26 +116,95 @@ $(DEMANGLER_PROG): cxxmain.o underscore.o getopt.o getopt1.o $(LIBDEPS)
CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
$(srcdir)/cp/except.c $(srcdir)/cp/input.c $(srcdir)/cp/pt.c \
$(srcdir)/cp/spew.c $(srcdir)/cp/xref.c $(srcdir)/cp/class.c \
- $(srcdir)/cp/edsel.c $(srcdir)/cp/expr.c $(srcdir)/cp/lex.c \
+ $(srcdir)/cp/expr.c $(srcdir)/cp/lex.c \
$(srcdir)/cp/ptree.c $(srcdir)/cp/tree.c $(srcdir)/cp/cvt.c \
- $(srcdir)/cp/errfn.c $(srcdir)/cp/gc.c $(srcdir)/cp/method.c \
+ $(srcdir)/cp/errfn.c $(srcdir)/cp/rtti.c $(srcdir)/cp/method.c \
$(srcdir)/cp/search.c $(srcdir)/cp/typeck.c $(srcdir)/cp/decl.c \
- $(srcdir)/cp/error.c $(srcdir)/cp/init.c $(srcdir)/cp/parse.y \
- $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c $(srcdir)/cp/repo.c
+ $(srcdir)/cp/error.c $(srcdir)/cp/friend.c $(srcdir)/cp/init.c \
+ $(srcdir)/cp/parse.y $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c \
+ $(srcdir)/cp/repo.c $(srcdir)/cp/semantics.c
-cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o
- cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus
-
+cc1plus$(exeext): $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \
+ $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def
+ cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus$(exeext)
+#
# Build hooks:
-c++.all.build: g++ $(DEMANGLER_PROG)
-c++.all.cross: g++-cross $(DEMANGLER_PROG)
-c++.start.encap: g++
+c++.all.build: g++$(exeext)
+c++.all.cross: g++-cross$(exeext) $(DEMANGLER_PROG)
+c++.start.encap: g++$(exeext)
c++.rest.encap: $(DEMANGLER_PROG)
c++.info:
c++.dvi:
-
+
+# C++ language-support library pieces for libgcc.
+tinfo.o: cc1plus$(exeext) $(srcdir)/cp/tinfo.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/tinfo.cc
+tinfo2.o: cc1plus$(exeext) $(srcdir)/cp/tinfo2.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/tinfo2.cc
+exception.o: cc1plus$(exeext) $(srcdir)/cp/exception.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c -fexceptions $(srcdir)/cp/exception.cc
+new.o: cc1plus$(exeext) $(srcdir)/cp/new.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new.cc
+opnew.o: cc1plus$(exeext) $(srcdir)/cp/new1.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new1.cc -DL_op_new -o opnew.o
+opnewnt.o: cc1plus$(exeext) $(srcdir)/cp/new1.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new1.cc -DL_op_newnt -o opnewnt.o
+opvnew.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new2.cc -DL_op_vnew -o opvnew.o
+opvnewnt.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new2.cc -DL_op_vnewnt -o opvnewnt.o
+opdel.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new2.cc -DL_op_delete -o opdel.o
+opdelnt.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new2.cc -DL_op_delnt -o opdelnt.o
+opvdel.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new2.cc -DL_op_vdel -o opvdel.o
+opvdelnt.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new2.cc -DL_op_vdelnt -o opvdelnt.o
+
+# We want to update cplib2.txt if any of the source files change...
+cplib2.txt: $(CXX_LIB2SRCS) $(CXX_EXTRA_HEADERS) cplib2.ready
+ case " $(LANGUAGES) " in \
+ *" "[cC]"++ "*) \
+ echo $(CXX_LIB2FUNCS) > cplib2.new;; \
+ *) \
+ echo "" > cplib2.new;; \
+ esac
+ mv -f cplib2.new cplib2.txt
+
+# Or if it would be different.
+cplib2.ready: $(GCC_PASSES) $(LANGUAGES) $(LIBGCC2_DEPS) stmp-int-hdrs
+ @if [ -r cplib2.txt ]; then \
+ case " $(LANGUAGES) " in \
+ *" "[cC]"++ "*) \
+ echo $(CXX_LIB2FUNCS) > cplib2.new;; \
+ *) \
+ echo "" > cplib2.new;; \
+ esac; \
+ if cmp -s cplib2.new cplib2.txt; then true; else \
+ touch cplib2.ready; \
+ fi; \
+ rm -f cplib2.new; \
+ else true ; \
+ fi
+ @if [ -f cplib2.ready ]; then true; else \
+ touch cplib2.ready; \
+ fi
+#
# Install hooks:
# cc1plus is installed elsewhere as part of $(COMPILERS).
@@ -121,17 +220,24 @@ c++.install-common:
$(INSTALL_PROGRAM) g++-cross$(exeext) $(bindir)/$(GXX_CROSS_NAME)$(exeext); \
chmod a+x $(bindir)/$(GXX_CROSS_NAME)$(exeext); \
rm -f $(bindir)/$(CXX_CROSS_NAME)$(exeext); \
- ln $(bindir)/$(GXX_CROSS_NAME)$(exeext) $(bindir)/$(CXX_CROSS_NAME)$(exeext) \
- > /dev/null 2>&1 \
- || cp $(bindir)/$(GXX_CROSS_NAME)$(exeext) $(bindir)/$(CXX_CROSS_NAME)$(exeext) ; \
+ $(LN) $(bindir)/$(GXX_CROSS_NAME)$(exeext) $(bindir)/$(CXX_CROSS_NAME)$(exeext); \
else \
rm -f $(bindir)/$(GXX_INSTALL_NAME)$(exeext); \
$(INSTALL_PROGRAM) g++$(exeext) $(bindir)/$(GXX_INSTALL_NAME)$(exeext); \
chmod a+x $(bindir)/$(GXX_INSTALL_NAME)$(exeext); \
rm -f $(bindir)/$(CXX_INSTALL_NAME)$(exeext); \
- ln $(bindir)/$(GXX_INSTALL_NAME)$(exeext) $(bindir)/$(CXX_INSTALL_NAME)$(exeext) \
- > /dev/null 2>&1 \
- || cp $(bindir)/$(GXX_INSTALL_NAME)$(exeext) $(bindir)/$(CXX_INSTALL_NAME)$(exeext) ; \
+ $(LN) $(bindir)/$(GXX_INSTALL_NAME)$(exeext) $(bindir)/$(CXX_INSTALL_NAME)$(exeext); \
+ fi ; \
+ if [ x$(DEMANGLER_PROG) != x ] && [ -x "$(DEMANGLER_PROG)" ]; then \
+ if [ -f g++-cross$(exeext) ] ; then \
+ rm -f $(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \
+ $(INSTALL_PROGRAM) $(DEMANGLER_PROG) $(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \
+ chmod a+x $(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \
+ else \
+ rm -f $(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \
+ $(INSTALL_PROGRAM) $(DEMANGLER_PROG) $(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \
+ chmod a+x $(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \
+ fi ; \
fi ; \
fi
@@ -155,9 +261,11 @@ c++.uninstall:
-rm -rf $(bindir)/$(CXX_CROSS_NAME)$(exeext)
-rm -rf $(bindir)/$(GXX_INSTALL_NAME)$(exeext)
-rm -rf $(bindir)/$(GXX_CROSS_NAME)$(exeext)
+ -rm -rf $(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext)
+ -rm -rf $(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext)
-rm -rf $(mandir)/$(GXX_INSTALL_NAME)$(manext)
-rm -rf $(mandir)/$(GXX_CROSS_NAME)$(manext)
-
+#
# Clean hooks:
# A lot of the ancillary files are deleted by the main makefile.
# We just have to delete files specific to us.
@@ -165,33 +273,41 @@ c++.uninstall:
c++.mostlyclean:
-rm -f cp/*$(objext) $(DEMANGLER_PROG)
c++.clean:
+ -rm -f cplib2.txt cplib2.ready
c++.distclean:
-rm -f cp/config.status cp/Makefile
-rm -f cp/parse.output
+ -rm -f g++.c
c++.extraclean:
c++.maintainer-clean:
-rm -f cp/parse.c cp/parse.h
-
+#
# Stage hooks:
# The main makefile has already created stage?/cp.
-c++.stage1:
+c++.stage1: stage1-start
-mv cp/*$(objext) stage1/cp
-c++.stage2:
+c++.stage2: stage2-start
-mv cp/*$(objext) stage2/cp
-c++.stage3:
+c++.stage3: stage3-start
-mv cp/*$(objext) stage3/cp
-c++.stage4:
+c++.stage4: stage4-start
-mv cp/*$(objext) stage4/cp
-
+#
# Maintenance hooks:
# This target creates the files that can be rebuilt, but go in the
# distribution anyway. It then copies the files to the distdir directory.
c++.distdir:
mkdir tmp/cp
+ mkdir tmp/cp/inc
cd cp ; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) parse.c hash.h
cd cp; \
for file in *[0-9a-zA-Z+]; do \
- ln $$file ../tmp/cp >/dev/null 2>&1 || cp $$file ../tmp/cp; \
+ $(LN) $$file ../tmp/cp; \
+ done
+ cd cp/inc; \
+ for file in *[0-9a-zA-Z+]; do \
+ ln $$file ../../tmp/cp/inc >/dev/null 2>&1 \
+ || cp $$file ../../tmp/cp/inc; \
done
diff --git a/contrib/gcc/cp/Makefile.in b/contrib/gcc/cp/Makefile.in
index 11466b2..8d7098d 100644
--- a/contrib/gcc/cp/Makefile.in
+++ b/contrib/gcc/cp/Makefile.in
@@ -1,5 +1,5 @@
# Makefile for GNU C++ compiler.
-# Copyright (C) 1987, 88, 90-4, 1995 Free Software Foundation, Inc.
+# Copyright (C) 1987, 88, 90-5, 1998 Free Software Foundation, Inc.
#This file is part of GNU CC.
@@ -54,10 +54,10 @@ T_CFLAGS =
X_CPPFLAGS =
T_CPPFLAGS =
-CC = cc
-BISON = bison
+CC = @CC@
+BBISON = `if [ -f ../../bison/bison ] ; then echo ../../bison/bison -L $(srcdir)/../../bison/ ; else echo bison ; fi`
BISONFLAGS =
-LEX = flex
+LEX = `if [ -f ../../flex/flex ] ; then echo ../../flex/flex ; else echo flex ; fi`
LEXFLAGS =
AR = ar
AR_FLAGS = rc
@@ -83,14 +83,21 @@ GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS)
# These are used because `configure' appends `cross-make'
# to the makefile when making a cross-compiler.
-target= ... `configure' substitutes actual target name here.
-xmake_file= ... `configure' substitutes actual x- file name here.
-tmake_file= ... `configure' substitutes actual t- file name here.
+# We don't use cross-make. Instead we use the tools
+# from the build tree, if they are available.
+# program_transform_name and objdir are set by configure.in.
+program_transform_name =
+objdir = .
+
+target=@target@
+xmake_file=@dep_host_xmake_file@
+tmake_file=@dep_tmake_file@
#version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < $(srcdir)/version.c`
#mainversion=`sed -e 's/.*\"\([0-9]*\.[0-9]*\).*/\1/' < $(srcdir)/version.c`
# Directory where sources are, from where we are.
-srcdir = .
+srcdir = @srcdir@
+VPATH = @srcdir@
# Additional system libraries to link with.
CLIB=
@@ -113,16 +120,21 @@ all: all.indirect
# sed inserts variable overrides after the following line.
####target overrides
+@target_overrides@
####host overrides
+@host_overrides@
####cross overrides
+@cross_defines@
+@cross_overrides@
####build overrides
-
+@build_overrides@
+#
# Now figure out from those variables how to compile and link.
-all.indirect: Makefile ../cc1plus
+all.indirect: Makefile ../cc1plus$(exeext)
# IN_GCC tells obstack.h that we are using gcc's <stddef.h> file.
-INTERNAL_CFLAGS = $(CROSS) -DIN_GCC
+INTERNAL_CFLAGS = $(CROSS) -DIN_GCC @extra_c_flags@
# This is the variable actually used when we compile.
ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS)
@@ -150,33 +162,37 @@ INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
.c.o:
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+# The only suffixes we want for implicit rules are .c and .o.
+.SUFFIXES:
+.SUFFIXES: .c .o
+
# This tells GNU make version 3 not to export all the variables
# defined in this file into the environment.
.NOEXPORT:
-
+#
# Lists of files for various purposes.
# Language-specific object files for g++
CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \
- class.o decl2.o error.o gc.o lex.o parse.o ptree.o spew.o typeck.o cvt.o \
- edsel.o except.o init.o method.o search.o tree.o xref.o repo.o
+ class.o decl2.o error.o lex.o parse.o ptree.o rtti.o spew.o typeck.o cvt.o \
+ except.o friend.o init.o method.o search.o semantics.o tree.o xref.o \
+ repo.o @extra_cxx_objs@
# Language-independent object files.
OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o
-compiler: ../cc1plus
-../cc1plus: $(P) $(CXX_OBJS) $(OBJDEPS) $(LIBDEPS)
- rm -f ../cc1plus$(exeext)
+compiler: ../cc1plus$(exeext)
+../cc1plus$(exeext): $(P) $(CXX_OBJS) $(OBJDEPS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
$(CXX_OBJS) $(OBJS) $(LIBS)
Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure
cd ..; $(SHELL) config.status
-native: config.status ../cc1plus
-
+native: config.status ../cc1plus$(exeext)
+#
# Compiling object files from source files.
# Note that dependencies on obstack.h are not written
@@ -188,15 +204,18 @@ RTL_H = $(srcdir)/../rtl.h $(srcdir)/../rtl.def \
$(srcdir)/../machmode.h $(srcdir)/../machmode.def
TREE_H = $(srcdir)/../tree.h $(srcdir)/../real.h $(srcdir)/../tree.def \
$(srcdir)/../machmode.h $(srcdir)/../machmode.def
-CXX_TREE_H = $(TREE_H) cp-tree.h tree.def
+CXX_TREE_H = $(TREE_H) cp-tree.h cp-tree.def
PARSE_H = $(srcdir)/parse.h
PARSE_C = $(srcdir)/parse.c
+EXPR_H = $(srcdir)/../expr.h ../insn-codes.h
-parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h
+parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h \
+ $(srcdir)/../except.h $(srcdir)/../output.h $(srcdir)/../system.h \
+ $(srcdir)/../toplev.h
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(PARSE_C) | sed 's,^\./,,'`
-CONFLICTS = expect 5 shift/reduce conflicts and 38 reduce/reduce conflicts.
+CONFLICTS = expect 26 shift/reduce conflicts and 42 reduce/reduce conflicts.
$(PARSE_H) : $(PARSE_C)
$(PARSE_C) : $(srcdir)/parse.y
@echo $(CONFLICTS)
@@ -221,35 +240,61 @@ $(srcdir)/hash.h:
$(srcdir)/gxx.gperf >$(srcdir)/hash.h
spew.o : spew.c $(CONFIG_H) $(CXX_TREE_H) \
- $(PARSE_H) $(srcdir)/../flags.h lex.h
+ $(PARSE_H) $(srcdir)/../flags.h lex.h $(srcdir)/../system.h
lex.o : lex.c $(CONFIG_H) $(CXX_TREE_H) \
- $(PARSE_H) input.c $(srcdir)/../flags.h hash.h lex.h $(srcdir)/../c-pragma.h
+ $(PARSE_H) input.c $(srcdir)/../flags.h hash.h lex.h \
+ $(srcdir)/../c-pragma.h $(srcdir)/../system.h $(srcdir)/../toplev.h \
+ $(srcdir)/../output.h
decl.o : decl.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
- lex.h decl.h $(srcdir)/../stack.h
+ lex.h decl.h $(srcdir)/../stack.h $(srcdir)/../output.h \
+ $(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h
decl2.o : decl2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
- lex.h decl.h
-typeck2.o : typeck2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
-typeck.o : typeck.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H)
-class.o : class.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
-call.o : call.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h class.h
-init.o : init.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H)
-method.o : method.c $(CONFIG_H) $(CXX_TREE_H) class.h
-cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) class.h
-search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h $(srcdir)/../flags.h
-tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
-ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H)
-gc.o : gc.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
-except.o : except.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H)
+ lex.h decl.h $(EXPR_H) $(srcdir)/../except.h \
+ $(srcdir)/../output.h $(srcdir)/../except.h $(srcdir)/../system.h \
+ $(srcdir)/../toplev.h $(srcdir)/../dwarf2out.h $(srcdir)/../dwarfout.h
+typeck2.o : typeck2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
+ $(srcdir)/../system.h $(srcdir)/../toplev.h
+typeck.o : typeck.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
+ $(EXPR_H) $(srcdir)/../system.h $(srcdir)/../toplev.h
+class.o : class.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
+ $(srcdir)/../system.h $(srcdir)/../toplev.h
+call.o : call.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
+ $(srcdir)/../system.h $(srcdir)/../toplev.h
+friend.o : friend.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
+ $(srcdir)/../system.h $(srcdir)/../toplev.h
+init.o : init.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
+ $(EXPR_H) $(srcdir)/../system.h $(srcdir)/../toplev.h
+method.o : method.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \
+ $(srcdir)/../toplev.h
+cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h
+search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h \
+ $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h
+tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
+ $(srcdir)/../system.h $(srcdir)/../toplev.h
+ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h
+rtti.o : rtti.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
+ $(srcdir)/../system.h $(srcdir)/../toplev.h
+except.o : except.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
+ $(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h
expr.o : expr.c $(CONFIG_H) $(CXX_TREE_H) $(RTL_H) $(srcdir)/../flags.h \
- $(srcdir)/../expr.h ../insn-codes.h
-edsel.o : edsel.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h $(srcdir)/../flags.h
-xref.o : xref.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../input.h
-pt.o : pt.c $(CONFIG_H) $(CXX_TREE_H) decl.h $(PARSE_H)
-error.o : error.c $(CONFIG_H) $(CXX_TREE_H)
-errfn.o : errfn.c $(CONFIG_H) $(CXX_TREE_H)
-sig.o : sig.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
-repo.o : repo.c $(CONFIG_H) $(CXX_TREE_H)
-
+ $(EXPR_H) $(srcdir)/../system.h $(srcdir)/../toplev.h
+xref.o : xref.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../input.h \
+ $(srcdir)/../system.h $(srcdir)/../toplev.h
+pt.o : pt.c $(CONFIG_H) $(CXX_TREE_H) decl.h $(PARSE_H) lex.h \
+ $(srcdir)/../system.h $(srcdir)/../toplev.h
+error.o : error.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \
+ $(srcdir)/../toplev.h
+errfn.o : errfn.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \
+ $(srcdir)/../toplev.h
+sig.o : sig.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
+ $(srcdir)/../system.h $(srcdir)/../toplev.h
+repo.o : repo.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \
+ $(srcdir)/../toplev.h
+semantics.o: semantics.c $(CONFIG_H) $(CXX_TREE_H) lex.h \
+ $(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h
+
+
+#
# These exist for maintenance purposes.
# Update the tags table.
@@ -263,3 +308,32 @@ TAGS: force
.PHONY: TAGS
force:
+
+g++FAQ.info: $(srcdir)/g++FAQ.texi
+ $(MAKEINFO) --no-split -o ./g++FAQ.info $(srcdir)/g++FAQ.texi
+
+# Preprocess the texi file so that the final document will have
+# hyperlinks.
+# It would be nice if texi2html could do something like this itself.
+
+# Assumption 1: the FAQ puts all http: and ftp: links in a @file{...}.
+# Assumption 2: newsgroups are like @file{comp.foo}
+# Assumption 3: email addresses match the regexp shown.
+
+g++FAQ.html: $(srcdir)/g++FAQ.texi
+ mkdir work
+ sed -e 's?@file{\([fth]*p://[^}]*\)}?@strong{<A HREF="\1">\1</A>}?' \
+ -e 's?@file{\(comp\.[-a-z+.]*\)}?<A HREF="news:\1">\1</A>?' \
+ -e 's?@file{\(gnu\.[-a-z+.]*\)}?<A HREF="news:\1">\1</A>?' \
+ -e 's?\([.+a-zA-Z0-9-]*@@[.a-zA-Z0-9-]*[a-zA-Z0-9]\)?<A HREF="mailto:\1">\1</A>?' \
+ $(srcdir)/g++FAQ.texi > work/g++FAQ.texi
+ cd work; texi2html g++FAQ.texi
+ mv work/*.html .
+ rm -r work
+
+# Make plain-text form.
+
+g++FAQ.txt: $(srcdir)/g++FAQ.texi
+ $(MAKEINFO) --no-split --no-headers -o - $(srcdir)/g++FAQ.texi |\
+ sed '/^Concept Index/,$$d' > g++FAQ.txt
+
diff --git a/contrib/gcc/cp/NEWS b/contrib/gcc/cp/NEWS
new file mode 100644
index 0000000..9cb7d5b
--- /dev/null
+++ b/contrib/gcc/cp/NEWS
@@ -0,0 +1,226 @@
+*** Changes in EGCS 1.1:
+
+* Namespaces are fully supported. The library has not yet been converted
+ to use namespace std, however, and the old std-faking code is still on by
+ default. To turn it off, you can use -fhonor-std.
+
+* Massive template improvements:
+ + member template classes are supported.
+ + template friends are supported.
+ + template template parameters are supported.
+ + local classes in templates are supported.
+ + lots of bugs fixed.
+
+* operator new now throws bad_alloc where appropriate.
+
+* Exception handling is now thread safe, and supports nested exceptions and
+ placement delete. Exception handling overhead on x86 is much lower with
+ GNU as 2.9.
+
+* protected virtual inheritance is now supported.
+
+* Loops are optimized better; we now move the test to the end in most
+ cases, like the C frontend does.
+
+* For class D derived from B which has a member 'int i', &D::i is now of
+ type 'int B::*' instead of 'int D::*'.
+
+* An _experimental_ new ABI for g++ can be turned on with -fnew-abi. The
+ current features of this are more efficient allocation of base classes
+ (including the empty base optimization), and more compact mangling of C++
+ symbol names (which can be turned on separately with -fsquangle). This
+ ABI is subject to change without notice, so don't use it for anything
+ that you don't want to rebuild with every release of the compiler.
+
+ As with all ABI-changing flags, this flag is for experts only, as all
+ code (including the library code in libgcc and libstdc++) must be
+ compiled with the same ABI.
+
+*** Changes in EGCS 1.0:
+
+* A public review copy of the December 1996 Draft of the ISO/ANSI C++
+ standard is now available. See
+
+ http://www.cygnus.com/misc/wp/
+
+ for more information.
+
+* g++ now uses a new implementation of templates. The basic idea is that
+ now templates are minimally parsed when seen and then expanded later.
+ This allows conformant early name binding and instantiation controls,
+ since instantiations no longer have to go through the parser.
+
+ What you get:
+
+ + Inlining of template functions works without any extra effort or
+ modifications.
+ + Instantiations of class templates and methods defined in the class
+ body are deferred until they are actually needed (unless
+ -fexternal-templates is specified).
+ + Nested types in class templates work.
+ + Static data member templates work.
+ + Member function templates are now supported.
+ + Partial specialization of class templates is now supported.
+ + Explicit specification of template parameters to function templates
+ is now supported.
+
+ Things you may need to fix in your code:
+
+ + Syntax errors in templates that are never instantiated will now be
+ diagnosed.
+ + Types and class templates used in templates must be declared
+ first, or the compiler will assume they are not types, and fail.
+ + Similarly, nested types of template type parameters must be tagged
+ with the 'typename' keyword, except in base lists. In many cases,
+ but not all, the compiler will tell you where you need to add
+ 'typename'. For more information, see
+
+ http://www.cygnus.com/misc/wp/dec96pub/template.html#temp.res
+
+ + Guiding declarations are no longer supported. Function declarations,
+ including friend declarations, do not refer to template instantiations.
+ You can restore the old behavior with -fguiding-decls until you fix
+ your code.
+
+ Other features:
+
+ + Default function arguments in templates will not be evaluated (or
+ checked for semantic validity) unless they are needed. Default
+ arguments in class bodies will not be parsed until the class
+ definition is complete.
+ + The -ftemplate-depth-NN flag can be used to increase the maximum
+ recursive template instantiation depth, which defaults to 17. If you
+ need to use this flag, the compiler will tell you.
+ + Explicit instantiation of template constructors and destructors is
+ now supported. For instance:
+
+ template A<int>::A(const A&);
+
+ Still not supported:
+
+ + Member class templates.
+ + Template friends.
+
+* Exception handling support has been significantly improved and is on by
+ default. The compiler supports two mechanisms for walking back up the
+ call stack; one relies on static information about how registers are
+ saved, and causes no runtime overhead for code that does not throw
+ exceptions. The other mechanism uses setjmp and longjmp equivalents, and
+ can result in quite a bit of runtime overhead. You can determine which
+ mechanism is the default for your target by compiling a testcase that
+ uses exceptions and doing an 'nm' on the object file; if it uses __throw,
+ it's using the first mechanism. If it uses __sjthrow, it's using the
+ second.
+
+ You can turn EH support off with -fno-exceptions.
+
+* RTTI support has been rewritten to work properly and is now on by default.
+ This means code that uses virtual functions will have a modest space
+ overhead. You can use the -fno-rtti flag to disable RTTI support.
+
+* On ELF systems, duplicate copies of symbols with 'initialized common'
+ linkage (such as template instantiations, vtables, and extern inlines)
+ will now be discarded by the GNU linker, so you don't need to use -frepo.
+ This support requires GNU ld from binutils 2.8 or later.
+
+* The overload resolution code has been rewritten to conform to the latest
+ C++ Working Paper. Built-in operators are now considered as candidates
+ in operator overload resolution. Function template overloading chooses
+ the more specialized template, and handles base classes in type deduction
+ and guiding declarations properly. In this release the old code can
+ still be selected with -fno-ansi-overloading, although this is not
+ supported and will be removed in a future release.
+
+* Standard usage syntax for the std namespace is supported; std is treated
+ as an alias for global scope. General namespaces are still not supported.
+
+* New flags:
+
+ + New warning -Wno-pmf-conversion (don't warn about
+ converting from a bound member function pointer to function
+ pointer).
+
+ + A flag -Weffc++ has been added for violations of some of the style
+ guidelines in Scott Meyers' _Effective C++_ books.
+
+ + -Woverloaded-virtual now warns if a virtual function in a base
+ class is hidden in a derived class, rather than warning about
+ virtual functions being overloaded (even if all of the inherited
+ signatures are overridden) as it did before.
+
+ + -Wall no longer implies -W. The new warning flag, -Wsign-compare,
+ included in -Wall, warns about dangerous comparisons of signed and
+ unsigned values. Only the flag is new; it was previously part of
+ -W.
+
+ + The new flag, -fno-weak, disables the use of weak symbols.
+
+* Synthesized methods are now emitted in any translation units that need
+ an out-of-line copy. They are no longer affected by #pragma interface
+ or #pragma implementation.
+
+* __FUNCTION__ and __PRETTY_FUNCTION__ are now treated as variables by the
+ parser; previously they were treated as string constants. So code like
+ `printf (__FUNCTION__ ": foo")' must be rewritten to
+ `printf ("%s: foo", __FUNCTION__)'. This is necessary for templates.
+
+* local static variables in extern inline functions will be shared between
+ translation units.
+
+* -fvtable-thunks is supported for all targets, and is the default for
+ Linux with glibc 2.x (also called libc 6.x).
+
+* bool is now always the same size as another built-in type. Previously,
+ a 64-bit RISC target using a 32-bit ABI would have 32-bit pointers and a
+ 64-bit bool. This should only affect Irix 6, which was not supported in
+ 2.7.2.
+
+* new (nothrow) is now supported.
+
+* Synthesized destructors are no longer made virtual just because the class
+ already has virtual functions, only if they override a virtual destructor
+ in a base class. The compiler will warn if this affects your code.
+
+* The g++ driver now only links against libstdc++, not libg++; it is
+ functionally identical to the c++ driver.
+
+* (void *)0 is no longer considered a null pointer constant; NULL in
+ <stddef.h> is now defined as __null, a magic constant of type (void *)
+ normally, or (size_t) with -ansi.
+
+* The name of a class is now implicitly declared in its own scope; A::A
+ refers to A.
+
+* Local classes are now supported.
+
+* __attribute__ can now be attached to types as well as declarations.
+
+* The compiler no longer emits a warning if an ellipsis is used as a
+ function's argument list.
+
+* Definition of nested types outside of their containing class is now
+ supported. For instance:
+
+ struct A {
+ struct B;
+ B* bp;
+ };
+
+ struct A::B {
+ int member;
+ };
+
+* On the HPPA, some classes that do not define a copy constructor
+ will be passed and returned in memory again so that functions
+ returning those types can be inlined.
+
+*** The g++ team thanks everyone that contributed to this release,
+ but especially:
+
+* Joe Buck <jbuck@synopsys.com>, the maintainer of the g++ FAQ.
+* Brendan Kehoe <brendan@cygnus.com>, who coordinates testing of g++.
+* Jason Merrill <jason@cygnus.com>, the g++ maintainer.
+* Mark Mitchell <mmitchell@usa.net>, who implemented member function
+ templates and explicit qualification of function templates.
+* Mike Stump <mrs@wrs.com>, the previous g++ maintainer, who did most of
+ the exception handling work.
diff --git a/contrib/gcc/cp/call.c b/contrib/gcc/cp/call.c
index 3f293ac..e65898e 100644
--- a/contrib/gcc/cp/call.c
+++ b/contrib/gcc/cp/call.c
@@ -1,7 +1,7 @@
/* Functions related to invoking methods and overloaded functions.
- Copyright (C) 1987, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92-97, 1998 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
- hacked by Brendan Kehoe (brendan@cygnus.com).
+ modified by Brendan Kehoe (brendan@cygnus.com).
This file is part of GNU CC.
@@ -21,1188 +21,75 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* High-level class interface. */
+/* High-level class interface. */
#include "config.h"
+#include "system.h"
#include "tree.h"
-#include <stdio.h>
#include "cp-tree.h"
-#include "class.h"
#include "output.h"
#include "flags.h"
+#include "rtl.h"
+#include "toplev.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-extern void sorry ();
-
extern int inhibit_warnings;
-extern int flag_assume_nonnull_objects;
extern tree ctor_label, dtor_label;
-/* From typeck.c: */
-extern tree unary_complex_lvalue ();
-
-/* Compute the ease with which a conversion can be performed
- between an expected and the given type. */
-static struct harshness_code convert_harshness ();
-
-#define EVIL_RETURN(ARG) ((ARG).code = EVIL_CODE, (ARG))
-#define STD_RETURN(ARG) ((ARG).code = STD_CODE, (ARG))
-#define QUAL_RETURN(ARG) ((ARG).code = QUAL_CODE, (ARG))
-#define TRIVIAL_RETURN(ARG) ((ARG).code = TRIVIAL_CODE, (ARG))
-#define ZERO_RETURN(ARG) ((ARG).code = 0, (ARG))
-
-/* Ordering function for overload resolution. Compare two candidates
- by gross quality. */
-int
-rank_for_overload (x, y)
- struct candidate *x, *y;
-{
- if (y->h.code & (EVIL_CODE|ELLIPSIS_CODE|USER_CODE))
- return y->h.code - x->h.code;
- if (x->h.code & (EVIL_CODE|ELLIPSIS_CODE|USER_CODE))
- return -1;
-
- /* This is set by compute_conversion_costs, for calling a non-const
- member function from a const member function. */
- if ((y->harshness[0].code & CONST_CODE) ^ (x->harshness[0].code & CONST_CODE))
- return y->harshness[0].code - x->harshness[0].code;
-
- if (y->h.code & STD_CODE)
- {
- if (x->h.code & STD_CODE)
- return y->h.distance - x->h.distance;
- return 1;
- }
- if (x->h.code & STD_CODE)
- return -1;
-
- return y->h.code - x->h.code;
-}
-
-/* Compare two candidates, argument by argument. */
-int
-rank_for_ideal (x, y)
- struct candidate *x, *y;
-{
- int i;
-
- if (x->h_len != y->h_len)
- abort ();
-
- for (i = 0; i < x->h_len; i++)
- {
- if (y->harshness[i].code - x->harshness[i].code)
- return y->harshness[i].code - x->harshness[i].code;
- if ((y->harshness[i].code & STD_CODE)
- && (y->harshness[i].distance - x->harshness[i].distance))
- return y->harshness[i].distance - x->harshness[i].distance;
-
- /* They're both the same code. Now see if we're dealing with an
- integral promotion that needs a finer grain of accuracy. */
- if (y->harshness[0].code & PROMO_CODE
- && (y->harshness[i].int_penalty ^ x->harshness[i].int_penalty))
- return y->harshness[i].int_penalty - x->harshness[i].int_penalty;
- }
- return 0;
-}
-
-/* TYPE is the type we wish to convert to. PARM is the parameter
- we have to work with. We use a somewhat arbitrary cost function
- to measure this conversion. */
-static struct harshness_code
-convert_harshness (type, parmtype, parm)
- register tree type, parmtype;
- tree parm;
-{
- struct harshness_code h;
- register enum tree_code codel;
- register enum tree_code coder;
- int lvalue;
-
- h.code = 0;
- h.distance = 0;
- h.int_penalty = 0;
-
-#ifdef GATHER_STATISTICS
- n_convert_harshness++;
-#endif
-
- if (TREE_CODE (parmtype) == REFERENCE_TYPE)
- {
- if (parm)
- parm = convert_from_reference (parm);
- parmtype = TREE_TYPE (parmtype);
- lvalue = 1;
- }
- else if (parm)
- lvalue = lvalue_p (parm);
- else
- lvalue = 0;
-
- if (TYPE_PTRMEMFUNC_P (type))
- type = TYPE_PTRMEMFUNC_FN_TYPE (type);
- if (TYPE_PTRMEMFUNC_P (parmtype))
- parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype);
-
- codel = TREE_CODE (type);
- coder = TREE_CODE (parmtype);
-
- if (TYPE_MAIN_VARIANT (parmtype) == TYPE_MAIN_VARIANT (type))
- return ZERO_RETURN (h);
-
- 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;
-
- if (TREE_CODE (ttl) == ARRAY_TYPE && TREE_CODE (ttr) == ARRAY_TYPE)
- {
- if (comptypes (ttl, ttr, 1))
- return ZERO_RETURN (h);
- return EVIL_RETURN (h);
- }
-
- 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;
- struct harshness_code h1, h2;
-
- /* Get to the METHOD_TYPE or FUNCTION_TYPE that this might be. */
- type = TREE_TYPE (type);
-
- if (coder == POINTER_TYPE)
- {
- parmtype = TREE_TYPE (parmtype);
- coder = TREE_CODE (parmtype);
- }
-
- if (coder != TREE_CODE (type))
- return EVIL_RETURN (h);
-
- if (type != parmtype && coder == METHOD_TYPE)
- {
- tree ttl = TYPE_METHOD_BASETYPE (type);
- tree ttr = TYPE_METHOD_BASETYPE (parmtype);
-
- int b_or_d = get_base_distance (ttr, ttl, 0, 0);
- if (b_or_d < 0)
- {
- b_or_d = get_base_distance (ttl, ttr, 0, 0);
- if (b_or_d < 0)
- return EVIL_RETURN (h);
- h.distance = -b_or_d;
- }
- else
- h.distance = b_or_d;
- h.code = STD_CODE;
-
- type = build_function_type
- (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type)));
- parmtype = build_function_type
- (TREE_TYPE (parmtype), TREE_CHAIN (TYPE_ARG_TYPES (parmtype)));
- }
-
- /* We allow the default conversion between function type
- and pointer-to-function type for free. */
- if (comptypes (type, parmtype, 1))
- return h;
-
- if (pedantic)
- return EVIL_RETURN (h);
-
- /* Compare return types. */
- p1 = TREE_TYPE (type);
- p2 = TREE_TYPE (parmtype);
- h2 = convert_harshness (p1, p2, NULL_TREE);
- if (h2.code & EVIL_CODE)
- return h2;
-
- h1.code = TRIVIAL_CODE;
- h1.distance = 0;
-
- if (h2.distance != 0)
- {
- tree binfo;
-
- /* This only works for pointers. */
- if (TREE_CODE (p1) != POINTER_TYPE
- && TREE_CODE (p1) != REFERENCE_TYPE)
- return EVIL_RETURN (h);
-
- p1 = TREE_TYPE (p1);
- p2 = TREE_TYPE (p2);
- /* Don't die if we happen to be dealing with void*. */
- if (!IS_AGGR_TYPE (p1) || !IS_AGGR_TYPE (p2))
- return EVIL_RETURN (h);
- if (h2.distance < 0)
- binfo = get_binfo (p2, p1, 0);
- else
- binfo = get_binfo (p1, p2, 0);
-
- if (! BINFO_OFFSET_ZEROP (binfo))
- {
-#if 0
- static int explained = 0;
- if (h2.distance < 0)
- message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p2, p1);
- else
- message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p1, p2);
-
- if (! explained++)
- sorry ("(because pointer values change during conversion)");
-#endif
- return EVIL_RETURN (h);
- }
- }
-
- h1.code |= h2.code;
- if (h2.distance > h1.distance)
- h1.distance = h2.distance;
-
- p1 = TYPE_ARG_TYPES (type);
- p2 = TYPE_ARG_TYPES (parmtype);
- while (p1 && TREE_VALUE (p1) != void_type_node
- && p2 && TREE_VALUE (p2) != void_type_node)
- {
- h2 = convert_harshness (TREE_VALUE (p1), TREE_VALUE (p2),
- NULL_TREE);
- if (h2.code & EVIL_CODE)
- return h2;
-
- if (h2.distance)
- {
- /* This only works for pointers and references. */
- if (TREE_CODE (TREE_VALUE (p1)) != POINTER_TYPE
- && TREE_CODE (TREE_VALUE (p1)) != REFERENCE_TYPE)
- return EVIL_RETURN (h);
- h2.distance = - h2.distance;
- }
-
- h1.code |= h2.code;
- if (h2.distance > h1.distance)
- h1.distance = h2.distance;
- p1 = TREE_CHAIN (p1);
- p2 = TREE_CHAIN (p2);
- }
- if (p1 == p2)
- return h1;
- if (p2)
- {
- if (p1)
- return EVIL_RETURN (h);
- h1.code |= ELLIPSIS_CODE;
- return h1;
- }
- if (p1)
- {
- if (TREE_PURPOSE (p1) == NULL_TREE)
- h1.code |= EVIL_CODE;
- return h1;
- }
- }
- else if (codel == POINTER_TYPE && coder == OFFSET_TYPE)
- {
- tree ttl, ttr;
-
- /* Get to the OFFSET_TYPE that this might be. */
- type = TREE_TYPE (type);
-
- if (coder != TREE_CODE (type))
- return EVIL_RETURN (h);
-
- ttl = TYPE_OFFSET_BASETYPE (type);
- ttr = TYPE_OFFSET_BASETYPE (parmtype);
-
- if (ttl == ttr)
- h.code = 0;
- else
- {
- int b_or_d = get_base_distance (ttr, ttl, 0, 0);
- if (b_or_d < 0)
- {
- b_or_d = get_base_distance (ttl, ttr, 0, 0);
- if (b_or_d < 0)
- return EVIL_RETURN (h);
- h.distance = -b_or_d;
- }
- else
- h.distance = b_or_d;
- h.code = STD_CODE;
- }
-
- /* Now test the OFFSET_TYPE's target compatibility. */
- type = TREE_TYPE (type);
- parmtype = TREE_TYPE (parmtype);
- }
-
- if (coder == UNKNOWN_TYPE)
- {
- if (codel == FUNCTION_TYPE
- || codel == METHOD_TYPE
- || (codel == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)))
- return TRIVIAL_RETURN (h);
- return EVIL_RETURN (h);
- }
-
- if (coder == VOID_TYPE)
- return EVIL_RETURN (h);
-
- if (codel == BOOLEAN_TYPE)
- {
- if (INTEGRAL_CODE_P (coder) || coder == REAL_TYPE)
- return STD_RETURN (h);
- else if (coder == POINTER_TYPE || coder == OFFSET_TYPE)
- {
- /* Make this worse than any conversion to another pointer.
- FIXME this is how I think the language should work, but it may not
- end up being how the language is standardized (jason 1/30/95). */
- h.distance = 32767;
- return STD_RETURN (h);
- }
- return EVIL_RETURN (h);
- }
-
- if (INTEGRAL_CODE_P (codel))
- {
- /* Control equivalence of ints an enums. */
-
- if (codel == ENUMERAL_TYPE
- && flag_int_enum_equivalence == 0)
- {
- /* Enums can be converted to ints, but not vice-versa. */
- if (coder != ENUMERAL_TYPE
- || TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (parmtype))
- return EVIL_RETURN (h);
- }
-
- /* else enums and ints (almost) freely interconvert. */
-
- if (INTEGRAL_CODE_P (coder))
- {
- if (TYPE_MAIN_VARIANT (type)
- == TYPE_MAIN_VARIANT (type_promotes_to (parmtype)))
- {
- h.code = PROMO_CODE;
-#if 0 /* What purpose does this serve? -jason */
- /* A char, short, wchar_t, etc., should promote to an int if
- it can handle it, otherwise to an unsigned. So we'll make
- an unsigned. */
- if (type != integer_type_node)
- h.int_penalty = 1;
-#endif
- }
- else
- h.code = STD_CODE;
-
- return h;
- }
- else if (coder == REAL_TYPE)
- {
- h.code = STD_CODE;
- h.distance = 0;
- return h;
- }
- }
-
- if (codel == REAL_TYPE)
- {
- if (coder == REAL_TYPE)
- {
- if (TYPE_MAIN_VARIANT (type)
- == TYPE_MAIN_VARIANT (type_promotes_to (parmtype)))
- h.code = PROMO_CODE;
- else
- h.code = STD_CODE;
-
- return h;
- }
- else if (INTEGRAL_CODE_P (coder))
- {
- h.code = STD_CODE;
- h.distance = 0;
- return h;
- }
- }
-
- /* 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;
- 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)
- {
- register tree ttl = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- register tree ttr = TYPE_MAIN_VARIANT (TREE_TYPE (parmtype));
- int penalty = 4 * (ttl != ttr);
-
- /* Anything converts to void *. Since this may be `const void *'
- (etc.) use VOID_TYPE instead of void_type_node. Otherwise, the
- targets must be the same, except that we do allow (at some cost)
- conversion between signed and unsigned pointer types. */
-
- if ((TREE_CODE (ttl) == METHOD_TYPE
- || TREE_CODE (ttl) == FUNCTION_TYPE)
- && TREE_CODE (ttl) == TREE_CODE (ttr))
- {
- if (comptypes (ttl, ttr, -1))
- {
- h.code = penalty ? STD_CODE : 0;
- h.distance = 0;
- }
- else
- h.code = EVIL_CODE;
- return h;
- }
-
-#if 1
- if (TREE_CODE (ttl) != VOID_TYPE
- && (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm)))
- {
- if (TREE_UNSIGNED (ttl) != TREE_UNSIGNED (ttr))
- {
- ttl = unsigned_type (ttl);
- ttr = unsigned_type (ttr);
- penalty = 10;
- }
- if (comp_target_types (type, parmtype, 1) <= 0)
- return EVIL_RETURN (h);
- }
-#else
- if (!(TREE_CODE (ttl) == VOID_TYPE
- || TREE_CODE (ttr) == VOID_TYPE
- || (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (ttr)
- && (ttl = unsigned_type (ttl),
- ttr = unsigned_type (ttr),
- penalty = 10, 0))
- || (comp_target_types (ttl, ttr, 0) > 0)))
- return EVIL_RETURN (h);
-#endif
-
- if (penalty == 10 || ttr == ttl)
- {
- tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
-
- /* If one was unsigned but the other wasn't, then we need to
- do a standard conversion from T to unsigned T. */
- if (penalty == 10)
- h.code = PROMO_CODE; /* was STD_CODE */
- else
- h.code = 0;
-
- /* Note conversion from `T*' to `const T*',
- or `T*' to `volatile T*'. */
- if (ttl == ttr
- && ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
- || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2))))
- h.code |= QUAL_CODE;
-
- h.distance = 0;
- return h;
- }
-
-
- if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
- {
- int b_or_d = get_base_distance (ttl, ttr, 0, 0);
- if (b_or_d < 0)
- {
- b_or_d = get_base_distance (ttr, ttl, 0, 0);
- if (b_or_d < 0)
- return EVIL_RETURN (h);
- h.distance = -b_or_d;
- }
- else
- h.distance = b_or_d;
- h.code = STD_CODE;
- return h;
- }
-
- /* If converting from a `class*' to a `void*', make it
- less favorable than any inheritance relationship. */
- if (TREE_CODE (ttl) == VOID_TYPE && IS_AGGR_TYPE (ttr))
- {
- h.code = STD_CODE;
- h.distance = CLASSTYPE_MAX_DEPTH (ttr)+1;
- return h;
- }
-
- h.code = penalty ? STD_CODE : PROMO_CODE;
- /* Catch things like `const char *' -> `const void *'
- vs `const char *' -> `void *'. */
- if (ttl != ttr)
- {
- tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
- if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
- || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))
- h.code |= QUAL_CODE;
- }
- return h;
- }
-
- if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
- {
- /* This is not a bad match, but don't let it beat
- integer-enum combinations. */
- if (parm && integer_zerop (parm))
- {
- h.code = STD_CODE;
- h.distance = 0;
- return h;
- }
- }
-
- /* C++: Since the `this' parameter of a signature member function
- is represented as a signature pointer to handle default implementations
- correctly, we can have the case that `type' is a signature pointer
- while `parmtype' is a pointer to a signature table. We don't really
- do any conversions in this case, so just return 0. */
-
- if (codel == RECORD_TYPE && coder == POINTER_TYPE
- && IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype)))
- return ZERO_RETURN (h);
-
- if (codel == RECORD_TYPE && coder == RECORD_TYPE)
- {
- int b_or_d = get_base_distance (type, parmtype, 0, 0);
- if (b_or_d < 0)
- {
- b_or_d = get_base_distance (parmtype, type, 0, 0);
- if (b_or_d < 0)
- return EVIL_RETURN (h);
- h.distance = -b_or_d;
- }
- else
- h.distance = b_or_d;
- h.code = STD_CODE;
- return h;
- }
- 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;
- tree parm;
-{
- tree conv;
- tree winner = NULL_TREE;
- int code;
-
- {
- tree typename = build_typename_overload (type);
- if (lookup_fnfields (TYPE_BINFO (parmtype), typename, 0))
- return 0;
- }
-
- for (conv = lookup_conversions (parmtype); conv; conv = TREE_CHAIN (conv))
- {
- struct harshness_code tmp;
-
- if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
- continue;
-
- if (tmp = convert_harshness (type, TREE_VALUE (conv), NULL_TREE),
- tmp.code < USER_CODE && tmp.distance >= 0)
- {
- if (winner)
- return EVIL_CODE;
- else
- {
- winner = conv;
- code = tmp.code;
- }
- }
- }
-
- if (winner)
- return code;
-
- return -1;
-}
-
-int
-can_convert (to, from)
- tree to, from;
-{
- struct harshness_code h;
- h = convert_harshness (to, from, NULL_TREE);
- return h.code < USER_CODE && h.distance >= 0;
-}
-
-int
-can_convert_arg (to, from, arg)
- tree to, from, arg;
-{
- struct harshness_code h;
- h = convert_harshness (to, from, arg);
- return h.code < USER_CODE && h.distance >= 0;
-}
-
-#ifdef DEBUG_MATCHING
-static char *
-print_harshness (h)
- struct harshness_code *h;
-{
- static char buf[1024];
- char tmp[1024];
-
- bzero (buf, 1024 * sizeof (char));
- strcat (buf, "codes=[");
- if (h->code & EVIL_CODE)
- strcat (buf, "EVIL");
- if (h->code & CONST_CODE)
- strcat (buf, " CONST");
- if (h->code & ELLIPSIS_CODE)
- strcat (buf, " ELLIPSIS");
- if (h->code & USER_CODE)
- strcat (buf, " USER");
- if (h->code & STD_CODE)
- strcat (buf, " STD");
- if (h->code & PROMO_CODE)
- strcat (buf, " PROMO");
- if (h->code & QUAL_CODE)
- strcat (buf, " QUAL");
- if (h->code & TRIVIAL_CODE)
- strcat (buf, " TRIVIAL");
- if (buf[0] == '\0')
- strcat (buf, "0");
-
- sprintf (tmp, "] distance=%d int_penalty=%d", h->distance, h->int_penalty);
-
- strcat (buf, tmp);
-
- return buf;
-}
-#endif
-
-/* Algorithm: For each argument, calculate how difficult it is to
- make FUNCTION accept that argument. If we can easily tell that
- FUNCTION won't be acceptable to one of the arguments, then we
- don't need to compute the ease of converting the other arguments,
- since it will never show up in the intersection of all arguments'
- favorite functions.
-
- Conversions between builtin and user-defined types are allowed, but
- no function involving such a conversion is preferred to one which
- does not require such a conversion. Furthermore, such conversions
- must be unique. */
-
-void
-compute_conversion_costs (function, tta_in, cp, arglen)
- tree function;
- tree tta_in;
- struct candidate *cp;
- int arglen;
-{
- tree ttf_in = TYPE_ARG_TYPES (TREE_TYPE (function));
- tree ttf = ttf_in;
- tree tta = tta_in;
-
- /* Start out with no strikes against. */
- int evil_strikes = 0;
- int ellipsis_strikes = 0;
- int user_strikes = 0;
- int b_or_d_strikes = 0;
- int easy_strikes = 0;
-
- int strike_index = 0, win;
- struct harshness_code lose;
- extern int cp_silent;
-
-#ifdef GATHER_STATISTICS
- n_compute_conversion_costs++;
-#endif
-
-#ifndef DEBUG_MATCHING
- /* We don't emit any warnings or errors while trying out each candidate. */
- cp_silent = 1;
-#endif
-
- cp->function = function;
- cp->arg = tta ? TREE_VALUE (tta) : NULL_TREE;
- cp->u.bad_arg = 0; /* optimistic! */
-
- cp->h.code = 0;
- cp->h.distance = 0;
- cp->h.int_penalty = 0;
- bzero ((char *) cp->harshness,
- (cp->h_len + 1) * sizeof (struct harshness_code));
-
- while (ttf && tta)
- {
- struct harshness_code h;
-
- if (ttf == void_list_node)
- break;
-
- if (type_unknown_p (TREE_VALUE (tta)))
- {
- /* Must perform some instantiation here. */
- tree rhs = TREE_VALUE (tta);
- tree lhstype = TREE_VALUE (ttf);
-
- /* Keep quiet about possible contravariance violations. */
- int old_inhibit_warnings = inhibit_warnings;
- inhibit_warnings = 1;
-
- /* @@ This is to undo what `grokdeclarator' does to
- parameter types. It really should go through
- something more general. */
-
- TREE_TYPE (tta) = unknown_type_node;
- rhs = instantiate_type (lhstype, rhs, 0);
- inhibit_warnings = old_inhibit_warnings;
-
- if (TREE_CODE (rhs) == ERROR_MARK)
- h.code = EVIL_CODE;
- else
- h = convert_harshness (lhstype, TREE_TYPE (rhs), rhs);
- }
- else
- {
-#ifdef DEBUG_MATCHING
- static tree old_function = NULL_TREE;
-
- if (!old_function || function != old_function)
- {
- cp_error ("trying %D", function);
- old_function = function;
- }
-
- cp_error (" doing (%T) %E against arg %T",
- TREE_TYPE (TREE_VALUE (tta)), TREE_VALUE (tta),
- TREE_VALUE (ttf));
-#endif
-
- h = convert_harshness (TREE_VALUE (ttf),
- TREE_TYPE (TREE_VALUE (tta)),
- TREE_VALUE (tta));
-
-#ifdef DEBUG_MATCHING
- cp_error (" evaluated %s", print_harshness (&h));
-#endif
- }
-
- cp->harshness[strike_index] = h;
- if ((h.code & EVIL_CODE)
- || ((h.code & STD_CODE) && h.distance < 0))
- {
- cp->u.bad_arg = strike_index;
- evil_strikes = 1;
- }
- else if (h.code & ELLIPSIS_CODE)
- ellipsis_strikes += 1;
-#if 0
- /* This is never set by `convert_harshness'. */
- else if (h.code & USER_CODE)
- {
- user_strikes += 1;
- }
-#endif
- else
- {
- if ((h.code & STD_CODE) && h.distance)
- {
- if (h.distance > b_or_d_strikes)
- b_or_d_strikes = h.distance;
- }
- else
- easy_strikes += (h.code & (STD_CODE|PROMO_CODE|TRIVIAL_CODE));
- cp->h.code |= h.code;
- /* Make sure we communicate this. */
- cp->h.int_penalty += h.int_penalty;
- }
-
- ttf = TREE_CHAIN (ttf);
- tta = TREE_CHAIN (tta);
- strike_index += 1;
- }
-
- if (tta)
- {
- /* ran out of formals, and parmlist is fixed size. */
- if (ttf /* == void_type_node */)
- {
- cp->h.code = EVIL_CODE;
- cp->u.bad_arg = -1;
- cp_silent = 0;
- return;
- }
- else
- {
- struct harshness_code h;
- int l = list_length (tta);
- ellipsis_strikes += l;
- h.code = ELLIPSIS_CODE;
- h.distance = 0;
- h.int_penalty = 0;
- for (; l; --l)
- cp->harshness[strike_index++] = h;
- }
- }
- else if (ttf && ttf != void_list_node)
- {
- /* ran out of actuals, and no defaults. */
- if (TREE_PURPOSE (ttf) == NULL_TREE)
- {
- cp->h.code = EVIL_CODE;
- cp->u.bad_arg = -2;
- cp_silent = 0;
- return;
- }
- /* Store index of first default. */
- cp->harshness[arglen].distance = strike_index+1;
- }
- else
- cp->harshness[arglen].distance = 0;
-
- /* Argument list lengths work out, so don't need to check them again. */
- if (evil_strikes)
- {
- /* We do not check for derived->base conversions here, since in
- no case would they give evil strike counts, unless such conversions
- are somehow ambiguous. */
-
- /* See if any user-defined conversions apply.
- But make sure that we do not loop. */
- static int dont_convert_types = 0;
-
- if (dont_convert_types)
- {
- cp->h.code = EVIL_CODE;
- cp_silent = 0;
- return;
- }
-
- win = 0; /* Only get one chance to win. */
- ttf = TYPE_ARG_TYPES (TREE_TYPE (function));
- tta = tta_in;
- strike_index = 0;
- evil_strikes = 0;
-
- while (ttf && tta)
- {
- if (ttf == void_list_node)
- break;
-
- lose = cp->harshness[strike_index];
- if ((lose.code & EVIL_CODE)
- || ((lose.code & STD_CODE) && lose.distance < 0))
- {
- tree actual_type = TREE_TYPE (TREE_VALUE (tta));
- tree formal_type = TREE_VALUE (ttf);
- int extra_conversions = 0;
-
- dont_convert_types = 1;
-
- if (TREE_CODE (formal_type) == REFERENCE_TYPE)
- formal_type = TREE_TYPE (formal_type);
- if (TREE_CODE (actual_type) == REFERENCE_TYPE)
- actual_type = TREE_TYPE (actual_type);
-
- if (formal_type != error_mark_node
- && actual_type != error_mark_node)
- {
- formal_type = TYPE_MAIN_VARIANT (formal_type);
- actual_type = TYPE_MAIN_VARIANT (actual_type);
-
- if (TYPE_HAS_CONSTRUCTOR (formal_type))
- {
- /* If it has a constructor for this type,
- try to use it. */
- /* @@ There is no way to save this result yet, so
- success is a NULL_TREE for now. */
- if (convert_to_aggr (formal_type, TREE_VALUE (tta), 0, 1)
- != error_mark_node)
- win++;
- }
- if (TYPE_LANG_SPECIFIC (actual_type)
- && TYPE_HAS_CONVERSION (actual_type))
- {
- int extra = user_harshness (formal_type, actual_type);
-
- if (extra == EVIL_CODE)
- win += 2;
- else if (extra >= 0)
- {
- win++;
- extra_conversions = extra;
- }
- }
- }
- dont_convert_types = 0;
-
- if (win == 1)
- {
- user_strikes += 1;
- cp->harshness[strike_index].code
- = USER_CODE | (extra_conversions ? STD_CODE : 0);
- win = 0;
- }
- else
- {
- if (cp->u.bad_arg > strike_index)
- cp->u.bad_arg = strike_index;
-
- evil_strikes = win ? 2 : 1;
- break;
- }
- }
-
- ttf = TREE_CHAIN (ttf);
- tta = TREE_CHAIN (tta);
- strike_index += 1;
- }
- }
-
- /* Const member functions get a small penalty because defaulting
- to const is less useful than defaulting to non-const. */
- /* This is bogus, it does not correspond to anything in the ARM.
- This code will be fixed when this entire section is rewritten
- to conform to the ARM. (mrs) */
- if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
- {
- tree this_parm = TREE_VALUE (ttf_in);
-
- if (TREE_CODE (this_parm) == RECORD_TYPE /* Is `this' a sig ptr? */
- ? TYPE_READONLY (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (this_parm))))
- : TYPE_READONLY (TREE_TYPE (this_parm)))
- {
- cp->harshness[0].code |= TRIVIAL_CODE;
- ++easy_strikes;
- }
- else
- {
- /* Calling a non-const member function from a const member function
- is probably invalid, but for now we let it only draw a warning.
- We indicate that such a mismatch has occurred by setting the
- harshness to a maximum value. */
- if (TREE_CODE (TREE_TYPE (TREE_VALUE (tta_in))) == POINTER_TYPE
- && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (TREE_VALUE (tta_in))))))
- cp->harshness[0].code |= CONST_CODE;
- }
- }
-
- if (evil_strikes)
- cp->h.code = EVIL_CODE;
- if (ellipsis_strikes)
- cp->h.code |= ELLIPSIS_CODE;
- if (user_strikes)
- cp->h.code |= USER_CODE;
- cp_silent = 0;
-#ifdef DEBUG_MATCHING
- cp_error ("final eval %s", print_harshness (&cp->h));
-#endif
-}
-
-/* Subroutine of ideal_candidate. See if X or Y is a better match
- than the other. */
-static int
-strictly_better (x, y)
- unsigned short x, y;
-{
- unsigned short xor;
-
- if (x == y)
- return 0;
-
- xor = x ^ y;
- if (xor >= x || xor >= y)
- return 1;
- return 0;
-}
-
-/* When one of several possible overloaded functions and/or methods
- can be called, choose the best candidate for overloading.
-
- BASETYPE is the context from which we start method resolution
- or NULL if we are comparing overloaded functions.
- CANDIDATES is the array of candidates we have to choose from.
- N_CANDIDATES is the length of CANDIDATES.
- PARMS is a TREE_LIST of parameters to the function we'll ultimately
- choose. It is modified in place when resolving methods. It is not
- modified in place when resolving overloaded functions.
- LEN is the length of the parameter list. */
-
-static struct candidate *
-ideal_candidate (basetype, candidates, n_candidates, parms, len)
- tree basetype;
- struct candidate *candidates;
- int n_candidates;
- tree parms;
- int len;
-{
- struct candidate *cp = candidates+n_candidates;
- int i, j = -1, best_code;
-
- /* For each argument, sort the functions from best to worst for the arg.
- For each function that's not best for this arg, set its overall
- harshness to EVIL so that other args won't like it. The candidate
- list for the last argument is the intersection of all the best-liked
- functions. */
-
-#if 0
- for (i = 0; i < len; i++)
- {
- qsort (candidates, n_candidates, sizeof (struct candidate),
- rank_for_overload);
- best_code = cp[-1].h.code;
-
- /* To find out functions that are worse than that represented
- by BEST_CODE, we can't just do a comparison like h.code>best_code.
- The total harshness for the "best" fn may be 8|8 for two args, and
- the harshness for the next-best may be 8|2. If we just compared,
- that would be checking 8>10, which would lead to the next-best
- being disqualified. What we actually want to do is get rid
- of functions that are definitely worse than that represented
- by best_code, i.e. those which have bits set higher than the
- highest in best_code. Sooooo, what we do is clear out everything
- represented by best_code, and see if we still come up with something
- higher. If so (e.g., 8|8 vs 8|16), it'll disqualify it properly. */
- for (j = n_candidates-2; j >= 0; j--)
- if ((candidates[j].h.code & ~best_code) > best_code)
- candidates[j].h.code = EVIL_CODE;
- }
-
- if (cp[-1].h.code & EVIL_CODE)
- return NULL;
-#else
- qsort (candidates, n_candidates, sizeof (struct candidate),
- rank_for_overload);
- best_code = cp[-1].h.code;
-#endif
-
- /* If they're at least as good as each other, do an arg-by-arg check. */
- if (! strictly_better (cp[-1].h.code, cp[-2].h.code))
- {
- int better = 0;
- int worse = 0;
-
- for (j = 0; j < n_candidates; j++)
- if (! strictly_better (candidates[j].h.code, best_code))
- break;
-
- qsort (candidates+j, n_candidates-j, sizeof (struct candidate),
- rank_for_ideal);
- for (i = 0; i < len; i++)
- {
- if (cp[-1].harshness[i].code < cp[-2].harshness[i].code)
- better = 1;
- else if (cp[-1].harshness[i].code > cp[-2].harshness[i].code)
- worse = 1;
- else if (cp[-1].harshness[i].code & STD_CODE)
- {
- /* If it involves a standard conversion, let the
- inheritance lattice be the final arbiter. */
- if (cp[-1].harshness[i].distance > cp[-2].harshness[i].distance)
- worse = 1;
- else if (cp[-1].harshness[i].distance < cp[-2].harshness[i].distance)
- better = 1;
- }
- else if (cp[-1].harshness[i].code & PROMO_CODE)
- {
- /* For integral promotions, take into account a finer
- granularity for determining which types should be favored
- over others in such promotions. */
- if (cp[-1].harshness[i].int_penalty > cp[-2].harshness[i].int_penalty)
- worse = 1;
- else if (cp[-1].harshness[i].int_penalty < cp[-2].harshness[i].int_penalty)
- better = 1;
- }
- }
-
- if (! better || worse)
- return NULL;
- }
- return cp-1;
-}
-
-/* Assume that if the class referred to is not in the
- current class hierarchy, that it may be remote.
- PARENT is assumed to be of aggregate type here. */
-static int
-may_be_remote (parent)
- tree parent;
-{
- if (TYPE_OVERLOADS_METHOD_CALL_EXPR (parent) == 0)
- return 0;
-
- if (current_class_type == NULL_TREE)
- return 0;
-
- if (parent == current_class_type)
- return 0;
-
- if (UNIQUELY_DERIVED_FROM_P (parent, current_class_type))
- return 0;
- return 1;
-}
+static tree build_new_method_call PROTO((tree, tree, tree, tree, int));
+
+static tree build_field_call PROTO((tree, tree, tree, tree));
+static tree find_scoped_type PROTO((tree, tree, tree));
+static struct z_candidate * tourney PROTO((struct z_candidate *));
+static int joust PROTO((struct z_candidate *, struct z_candidate *, int));
+static int compare_ics PROTO((tree, tree));
+static tree build_over_call PROTO((struct z_candidate *, tree, int));
+static tree convert_like PROTO((tree, tree));
+static void op_error PROTO((enum tree_code, enum tree_code, tree, tree,
+ tree, char *));
+static tree build_object_call PROTO((tree, tree));
+static tree resolve_args PROTO((tree));
+static struct z_candidate * build_user_type_conversion_1
+ PROTO ((tree, tree, int));
+static void print_z_candidates PROTO((struct z_candidate *));
+static tree build_this PROTO((tree));
+static struct z_candidate * splice_viable PROTO((struct z_candidate *));
+static int any_viable PROTO((struct z_candidate *));
+static struct z_candidate * add_template_candidate
+ PROTO((struct z_candidate *, tree, tree, tree, tree, int,
+ unification_kind_t));
+static struct z_candidate * add_template_candidate_real
+ PROTO((struct z_candidate *, tree, tree, tree, tree, int,
+ tree, unification_kind_t));
+static struct z_candidate * add_template_conv_candidate
+ PROTO((struct z_candidate *, tree, tree, tree, tree));
+static struct z_candidate * add_builtin_candidates
+ PROTO((struct z_candidate *, enum tree_code, enum tree_code,
+ tree, tree *, int));
+static struct z_candidate * add_builtin_candidate
+ PROTO((struct z_candidate *, enum tree_code, enum tree_code,
+ tree, tree, tree, tree *, tree *, int));
+static int is_complete PROTO((tree));
+static struct z_candidate * build_builtin_candidate
+ PROTO((struct z_candidate *, tree, tree, tree, tree *, tree *,
+ int));
+static struct z_candidate * add_conv_candidate
+ PROTO((struct z_candidate *, tree, tree, tree));
+static struct z_candidate * add_function_candidate
+ PROTO((struct z_candidate *, tree, tree, int));
+static tree implicit_conversion PROTO((tree, tree, tree, int));
+static tree standard_conversion PROTO((tree, tree, tree));
+static tree reference_binding PROTO((tree, tree, tree, int));
+static tree strip_top_quals PROTO((tree));
+static tree non_reference PROTO((tree));
+static tree build_conv PROTO((enum tree_code, tree, tree));
+static int is_subseq PROTO((tree, tree));
+static int is_properly_derived_from PROTO((tree, tree));
+static int maybe_handle_ref_bind PROTO((tree*, tree*));
+static void maybe_handle_implicit_object PROTO((tree*));
tree
build_vfield_ref (datum, type)
@@ -1223,7 +110,7 @@ build_vfield_ref (datum, type)
rval = build (COMPONENT_REF, TREE_TYPE (CLASSTYPE_VFIELD (type)),
datum, CLASSTYPE_VFIELD (type));
else
- rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), 0, 0);
+ rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), NULL_TREE, 0);
flag_assume_nonnull_objects = old_assume_nonnull_objects;
return rval;
@@ -1231,13 +118,17 @@ build_vfield_ref (datum, type)
/* Build a call to a member of an object. I.e., one that overloads
operator ()(), or is a pointer-to-function or pointer-to-method. */
+
static tree
build_field_call (basetype_path, instance_ptr, name, parms)
tree basetype_path, instance_ptr, name, parms;
{
tree field, instance;
- if (instance_ptr == current_class_decl)
+ if (name == ctor_identifier || name == dtor_identifier)
+ return NULL_TREE;
+
+ if (instance_ptr == current_class_ptr)
{
/* Check to see if we really have a reference to an instance variable
with `operator()()' overloaded. */
@@ -1253,12 +144,11 @@ build_field_call (basetype_path, instance_ptr, name, parms)
{
/* If it's a field, try overloading operator (),
or calling if the field is a pointer-to-function. */
- instance = build_component_ref_1 (C_C_D, field, 0);
+ instance = build_component_ref_1 (current_class_ref, field, 0);
if (instance == error_mark_node)
return error_mark_node;
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (instance))
- && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (instance)))
+ if (TYPE_LANG_SPECIFIC (TREE_TYPE (instance)))
return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms, NULL_TREE);
if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
@@ -1266,7 +156,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
return build_function_call (instance, parms);
else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == METHOD_TYPE)
- return build_function_call (instance, tree_cons (NULL_TREE, current_class_decl, parms));
+ return build_function_call (instance, expr_tree_cons (NULL_TREE, current_class_ptr, parms));
}
}
return NULL_TREE;
@@ -1281,7 +171,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
if (field == error_mark_node)
return error_mark_node;
- if (field)
+ if (field && TREE_CODE (field) == FIELD_DECL)
{
tree basetype;
tree ftype = TREE_TYPE (field);
@@ -1289,7 +179,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
if (TREE_CODE (ftype) == REFERENCE_TYPE)
ftype = TREE_TYPE (ftype);
- if (TYPE_LANG_SPECIFIC (ftype) && TYPE_OVERLOADS_CALL_EXPR (ftype))
+ if (TYPE_LANG_SPECIFIC (ftype))
{
/* Make the next search for this field very short. */
basetype = DECL_FIELD_CONTEXT (field);
@@ -1326,7 +216,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
return NULL_TREE;
}
-tree
+static tree
find_scoped_type (type, inner_name, inner_types)
tree type, inner_name, inner_types;
{
@@ -1341,28 +231,19 @@ find_scoped_type (type, inner_name, inner_types)
if (TREE_PURPOSE (tags) == inner_name)
{
if (inner_types == NULL_TREE)
- return DECL_NESTED_TYPENAME (TYPE_NAME (TREE_VALUE (tags)));
+ return TYPE_MAIN_DECL (TREE_VALUE (tags));
return resolve_scope_to_name (TREE_VALUE (tags), inner_types);
}
tags = TREE_CHAIN (tags);
}
-#if 0
- /* XXX This needs to be fixed better. */
- if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
- {
- sorry ("nested class lookup in template type");
- return NULL_TREE;
- }
-#endif
-
/* Look for a TYPE_DECL. */
for (tags = TYPE_FIELDS (type); tags; tags = TREE_CHAIN (tags))
if (TREE_CODE (tags) == TYPE_DECL && DECL_NAME (tags) == inner_name)
{
/* Code by raeburn. */
if (inner_types == NULL_TREE)
- return DECL_NESTED_TYPENAME (tags);
+ return tags;
return resolve_scope_to_name (TREE_TYPE (tags), inner_types);
}
@@ -1374,6 +255,7 @@ find_scoped_type (type, inner_name, inner_types)
is a chain of nested type names (held together by SCOPE_REFs);
OUTER_TYPE is the type we know to enclose INNER_TYPES.
Returns NULL_TREE if there is an error. */
+
tree
resolve_scope_to_name (outer_type, inner_stuff)
tree outer_type, inner_stuff;
@@ -1394,7 +276,7 @@ resolve_scope_to_name (outer_type, inner_stuff)
if (rval != NULL_TREE)
return rval;
- type = DECL_CONTEXT (TYPE_NAME (type));
+ type = DECL_CONTEXT (TYPE_MAIN_DECL (type));
}
}
@@ -1458,11 +340,43 @@ resolve_scope_to_name (outer_type, inner_stuff)
return tmp;
}
+/* Returns nonzero iff the destructor name specified in NAME
+ (a BIT_NOT_EXPR) matches BASETYPE. The operand of NAME can take many
+ forms... */
+
+int
+check_dtor_name (basetype, name)
+ tree basetype, name;
+{
+ name = TREE_OPERAND (name, 0);
+
+ if (TREE_CODE (name) == TYPE_DECL)
+ name = TREE_TYPE (name);
+ else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
+ /* OK */;
+ else if (TREE_CODE (name) == IDENTIFIER_NODE)
+ {
+ if ((IS_AGGR_TYPE (basetype) && name == constructor_name (basetype))
+ || (TREE_CODE (basetype) == ENUMERAL_TYPE
+ && name == TYPE_IDENTIFIER (basetype)))
+ name = basetype;
+ else
+ name = get_type_value (name);
+ }
+ else
+ my_friendly_abort (980605);
+
+ if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name))
+ return 1;
+ return 0;
+}
+
/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'.
This is how virtual function calls are avoided. */
+
tree
-build_scoped_method_call (exp, scopes, name, parms)
- tree exp, scopes, name, parms;
+build_scoped_method_call (exp, basetype, name, parms)
+ tree exp, basetype, name, parms;
{
/* Because this syntactic form does not allow
a pointer to a base class to be `stolen',
@@ -1470,35 +384,64 @@ build_scoped_method_call (exp, scopes, name, parms)
that happens here.
@@ But we do have to check access privileges later. */
- tree basename = resolve_scope_to_name (NULL_TREE, scopes);
- tree basetype, binfo, decl;
+ tree binfo, decl;
tree type = TREE_TYPE (exp);
if (type == error_mark_node
- || basename == NULL_TREE)
+ || basetype == error_mark_node)
return error_mark_node;
- basetype = IDENTIFIER_TYPE_VALUE (basename);
+ if (processing_template_decl)
+ {
+ if (TREE_CODE (name) == BIT_NOT_EXPR
+ && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
+ {
+ tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
+ if (type)
+ name = build_min_nt (BIT_NOT_EXPR, type);
+ }
+ name = build_min_nt (SCOPE_REF, basetype, name);
+ return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, NULL_TREE);
+ }
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
- /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
- that explicit ~int is caught in the parser; this deals with typedefs
- and template parms. */
- if (TREE_CODE (name) == BIT_NOT_EXPR && ! is_aggr_typedef (basename, 0))
+ if (TREE_CODE (basetype) == TREE_VEC)
{
- if (type != basetype)
- cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')",
- exp, basetype, type);
- name = TREE_OPERAND (name, 0);
- if (basetype != get_type_value (name))
+ binfo = basetype;
+ basetype = BINFO_TYPE (binfo);
+ }
+ else
+ binfo = NULL_TREE;
+
+ /* Check the destructor call syntax. */
+ if (TREE_CODE (name) == BIT_NOT_EXPR)
+ {
+ /* We can get here if someone writes their destructor call like
+ `obj.NS::~T()'; this isn't really a scoped method call, so hand
+ it off. */
+ if (TREE_CODE (basetype) == NAMESPACE_DECL)
+ return build_method_call (exp, name, parms, NULL_TREE, LOOKUP_NORMAL);
+
+ if (! check_dtor_name (basetype, name))
cp_error ("qualified type `%T' does not match destructor name `~%T'",
- basetype, name);
- return convert (void_type_node, exp);
+ basetype, TREE_OPERAND (name, 0));
+
+ /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
+ that explicit ~int is caught in the parser; this deals with typedefs
+ and template parms. */
+ if (! IS_AGGR_TYPE (basetype))
+ {
+ if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (basetype))
+ cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')",
+ exp, basetype, type);
+
+ return cp_convert (void_type_node, exp);
+ }
}
- if (! is_aggr_typedef (basename, 1))
+ if (! is_aggr_type (basetype, 1))
return error_mark_node;
if (! IS_AGGR_TYPE (type))
@@ -1508,31 +451,29 @@ build_scoped_method_call (exp, scopes, name, parms)
return error_mark_node;
}
- if ((binfo = binfo_or_else (basetype, type)))
+ if (! binfo)
{
+ binfo = get_binfo (basetype, type, 1);
if (binfo == error_mark_node)
return error_mark_node;
+ if (! binfo)
+ error_not_base_type (basetype, type);
+ }
+
+ if (binfo)
+ {
if (TREE_CODE (exp) == INDIRECT_REF)
- decl = build_indirect_ref (convert_pointer_to (binfo,
- build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR);
+ decl = build_indirect_ref
+ (convert_pointer_to_real
+ (binfo, build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR);
else
- decl = build_scoped_ref (exp, scopes);
+ decl = build_scoped_ref (exp, basetype);
/* Call to a destructor. */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
- /* Explicit call to destructor. */
- name = TREE_OPERAND (name, 0);
- if (! (name == constructor_name (TREE_TYPE (decl))
- || TREE_TYPE (decl) == get_type_value (name)))
- {
- cp_error
- ("qualified type `%T' does not match destructor name `~%T'",
- TREE_TYPE (decl), name);
- return error_mark_node;
- }
if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
- return convert (void_type_node, exp);
+ return cp_convert (void_type_node, exp);
return build_delete (TREE_TYPE (decl), decl, integer_two_node,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,
@@ -1546,30 +487,92 @@ build_scoped_method_call (exp, scopes, name, parms)
return error_mark_node;
}
-static void
-print_candidates (candidates)
- tree candidates;
+/* We want the address of a function or method. We avoid creating a
+ pointer-to-member function. */
+
+tree
+build_addr_func (function)
+ tree function;
{
- cp_error_at ("candidates are: %D", TREE_VALUE (candidates));
- candidates = TREE_CHAIN (candidates);
+ tree type = TREE_TYPE (function);
- while (candidates)
+ /* We have to do these by hand to avoid real pointer to member
+ functions. */
+ if (TREE_CODE (type) == METHOD_TYPE)
{
- cp_error_at (" %D", TREE_VALUE (candidates));
- candidates = TREE_CHAIN (candidates);
+ tree addr;
+
+ type = build_pointer_type (type);
+
+ if (mark_addressable (function) == 0)
+ return error_mark_node;
+
+ addr = build1 (ADDR_EXPR, type, function);
+
+ /* Address of a static or external variable or function counts
+ as a constant */
+ if (staticp (function))
+ TREE_CONSTANT (addr) = 1;
+
+ function = addr;
}
+ else
+ function = default_conversion (function);
+
+ return function;
}
-static void
-print_n_candidates (candidates, n)
- struct candidate *candidates;
- int n;
+/* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or
+ POINTER_TYPE to those. Note, pointer to member function types
+ (TYPE_PTRMEMFUNC_P) must be handled by our callers. */
+
+tree
+build_call (function, result_type, parms)
+ tree function, result_type, parms;
{
- int i;
+ int is_constructor = 0;
+ tree tmp;
+ tree decl;
- cp_error_at ("candidates are: %D", candidates[0].function);
- for (i = 1; i < n; i++)
- cp_error_at (" %D", candidates[i].function);
+ function = build_addr_func (function);
+
+ if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
+ {
+ sorry ("unable to call pointer to member function here");
+ return error_mark_node;
+ }
+
+ if (TREE_CODE (function) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
+ decl = TREE_OPERAND (function, 0);
+ else
+ decl = NULL_TREE;
+
+ if (decl && DECL_CONSTRUCTOR_P (decl))
+ is_constructor = 1;
+
+ /* Don't pass empty class objects by value. This is useful
+ for tags in STL, which are used to control overload resolution.
+ We don't need to handle other cases of copying empty classes. */
+ if (! decl || ! DECL_BUILT_IN (decl))
+ for (tmp = parms; tmp; tmp = TREE_CHAIN (tmp))
+ if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp)))
+ && ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp))))
+ {
+ tree t = make_node (RTL_EXPR);
+ TREE_TYPE (t) = TREE_TYPE (TREE_VALUE (tmp));
+ RTL_EXPR_RTL (t) = const0_rtx;
+ RTL_EXPR_SEQUENCE (t) = NULL_RTX;
+ TREE_VALUE (tmp) = build (COMPOUND_EXPR, TREE_TYPE (t),
+ TREE_VALUE (tmp), t);
+ }
+
+ function = build_nt (CALL_EXPR, function, parms, NULL_TREE);
+ TREE_HAS_CONSTRUCTOR (function) = is_constructor;
+ TREE_TYPE (function) = result_type;
+ TREE_SIDE_EFFECTS (function) = 1;
+
+ return function;
}
/* Build something of the form ptr->method (args)
@@ -1603,31 +606,13 @@ print_n_candidates (candidates, n)
Note that NAME may refer to an instance variable name. If
`operator()()' is defined for the type of that field, then we return
that result. */
+
tree
build_method_call (instance, name, parms, basetype_path, flags)
tree instance, name, parms, basetype_path;
int flags;
{
- register tree function, fntype, value_type;
- register tree basetype, save_basetype;
- register tree baselink, result, method_name, parmtypes, parm;
- tree last;
- int pass;
- enum access_type access = access_public;
-
- /* Range of cases for vtable optimization. */
- enum vtable_needs { not_needed, maybe_needed, unneeded, needed };
- enum vtable_needs need_vtbl = not_needed;
-
- char *name_kind;
- int ever_seen = 0;
- tree instance_ptr = NULL_TREE;
- int all_virtual = flag_all_virtual;
- int static_call_context = 0;
- tree found_fns = NULL_TREE;
-
- /* Keep track of `const' and `volatile' objects. */
- int constp, volatilep;
+ tree basetype, instance_ptr;
#ifdef GATHER_STATISTICS
n_build_method_call++;
@@ -1639,48 +624,59 @@ build_method_call (instance, name, parms, basetype_path, flags)
|| (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
return error_mark_node;
+ if (processing_template_decl)
+ {
+ /* We need to process template parm names here so that tsubst catches
+ them properly. Other type names can wait. */
+ if (TREE_CODE (name) == BIT_NOT_EXPR
+ && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
+ {
+ tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
+ if (type && TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ name = build_min_nt (BIT_NOT_EXPR, type);
+ }
+
+ return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
+ }
+
/* This is the logic that magically deletes the second argument to
- operator delete, if it is not needed. */
+ operator delete, if it is not needed. */
if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2)
{
tree save_last = TREE_CHAIN (parms);
- tree result;
+
/* get rid of unneeded argument */
TREE_CHAIN (parms) = NULL_TREE;
- result = build_method_call (instance, name, parms, basetype_path,
- (LOOKUP_SPECULATIVELY|flags)
- &~LOOKUP_COMPLAIN);
- /* If it finds a match, return it. */
- if (result)
- return build_method_call (instance, name, parms, basetype_path, flags);
+ if (build_method_call (instance, name, parms, basetype_path,
+ (LOOKUP_SPECULATIVELY|flags) & ~LOOKUP_COMPLAIN))
+ {
+ /* If it finds a match, return it. */
+ return build_method_call (instance, name, parms, basetype_path, flags);
+ }
/* If it doesn't work, two argument delete must work */
TREE_CHAIN (parms) = save_last;
}
/* We already know whether it's needed or not for vec delete. */
else if (name == ansi_opname[(int) VEC_DELETE_EXPR]
+ && TYPE_LANG_SPECIFIC (TREE_TYPE (instance))
&& ! TYPE_VEC_DELETE_TAKES_SIZE (TREE_TYPE (instance)))
TREE_CHAIN (parms) = NULL_TREE;
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
- flags |= LOOKUP_DESTRUCTOR;
- name = TREE_OPERAND (name, 0);
if (parms)
error ("destructors take no parameters");
basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
- if (! ((IS_AGGR_TYPE (basetype)
- && name == constructor_name (basetype))
- || basetype == get_type_value (name)))
- {
- cp_error ("destructor name `~%D' does not match type `%T' of expression",
- name, basetype);
- return convert (void_type_node, instance);
- }
- if (! TYPE_HAS_DESTRUCTOR (basetype))
- return convert (void_type_node, instance);
+ if (! check_dtor_name (basetype, name))
+ cp_error
+ ("destructor name `~%T' does not match type `%T' of expression",
+ TREE_OPERAND (name, 0), basetype);
+
+ if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype)))
+ return cp_convert (void_type_node, instance);
instance = default_conversion (instance);
instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
return build_delete (build_pointer_type (basetype),
@@ -1688,1306 +684,3833 @@ build_method_call (instance, name, parms, basetype_path, flags)
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
}
- {
- char *xref_name;
-
- /* Initialize name for error reporting. */
- if (IDENTIFIER_OPNAME_P (name) && ! IDENTIFIER_TYPENAME_P (name))
- {
- char *p = operator_name_string (name);
- xref_name = (char *)alloca (strlen (p) + 10);
- sprintf (xref_name, "operator %s", p);
- }
- else if (TREE_CODE (name) == SCOPE_REF)
- xref_name = IDENTIFIER_POINTER (TREE_OPERAND (name, 1));
- else
- xref_name = IDENTIFIER_POINTER (name);
+ return build_new_method_call (instance, name, parms, basetype_path, flags);
+}
- GNU_xref_call (current_function_decl, xref_name);
- }
+/* New overloading code. */
+
+struct z_candidate {
+ tree fn;
+ tree convs;
+ tree second_conv;
+ int viable;
+ tree basetype_path;
+ tree template;
+ tree warnings;
+ struct z_candidate *next;
+};
+
+#define IDENTITY_RANK 0
+#define EXACT_RANK 1
+#define PROMO_RANK 2
+#define STD_RANK 3
+#define PBOOL_RANK 4
+#define USER_RANK 5
+#define ELLIPSIS_RANK 6
+#define BAD_RANK 7
+
+#define ICS_RANK(NODE) \
+ (ICS_BAD_FLAG (NODE) ? BAD_RANK \
+ : ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK \
+ : ICS_USER_FLAG (NODE) ? USER_RANK \
+ : ICS_STD_RANK (NODE))
+
+#define ICS_STD_RANK(NODE) TREE_COMPLEXITY (NODE)
+
+#define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE)
+#define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
+#define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)
+#define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)
+
+#define USER_CONV_CAND(NODE) \
+ ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
+#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
- if (instance == NULL_TREE)
+int
+null_ptr_cst_p (t)
+ tree t;
+{
+ if (t == null_node
+ || (integer_zerop (t) && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE))
+ return 1;
+ return 0;
+}
+
+static tree
+build_conv (code, type, from)
+ enum tree_code code;
+ tree type, from;
+{
+ tree t = build1 (code, type, from);
+ int rank = ICS_STD_RANK (from);
+ switch (code)
+ {
+ case PTR_CONV:
+ case PMEM_CONV:
+ case BASE_CONV:
+ case STD_CONV:
+ if (rank < STD_RANK)
+ rank = STD_RANK;
+ break;
+
+ case QUAL_CONV:
+ if (rank < EXACT_RANK)
+ rank = EXACT_RANK;
+
+ default:
+ break;
+ }
+ ICS_STD_RANK (t) = rank;
+ ICS_USER_FLAG (t) = ICS_USER_FLAG (from);
+ ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from);
+ return t;
+}
+
+static tree
+non_reference (t)
+ tree t;
+{
+ if (TREE_CODE (t) == REFERENCE_TYPE)
+ t = TREE_TYPE (t);
+ return t;
+}
+
+static tree
+strip_top_quals (t)
+ tree t;
+{
+ if (TREE_CODE (t) == ARRAY_TYPE)
+ return t;
+ return TYPE_MAIN_VARIANT (t);
+}
+
+/* Returns the standard conversion path (see [conv]) from type FROM to type
+ TO, if any. For proper handling of null pointer constants, you must
+ also pass the expression EXPR to convert from. */
+
+static tree
+standard_conversion (to, from, expr)
+ tree to, from, expr;
+{
+ enum tree_code fcode, tcode;
+ tree conv;
+ int fromref = 0;
+
+ if (TREE_CODE (to) == REFERENCE_TYPE)
+ to = TREE_TYPE (to);
+ if (TREE_CODE (from) == REFERENCE_TYPE)
+ {
+ fromref = 1;
+ from = TREE_TYPE (from);
+ }
+ to = strip_top_quals (to);
+ from = strip_top_quals (from);
+
+ fcode = TREE_CODE (from);
+ tcode = TREE_CODE (to);
+
+ conv = build1 (IDENTITY_CONV, from, expr);
+
+ if (fcode == FUNCTION_TYPE)
{
- basetype = NULL_TREE;
- /* Check cases where this is really a call to raise
- an exception. */
- if (current_class_type && TREE_CODE (name) == IDENTIFIER_NODE)
+ from = build_pointer_type (from);
+ fcode = TREE_CODE (from);
+ conv = build_conv (LVALUE_CONV, from, conv);
+ }
+ else if (fcode == ARRAY_TYPE)
+ {
+ from = build_pointer_type (TREE_TYPE (from));
+ fcode = TREE_CODE (from);
+ conv = build_conv (LVALUE_CONV, from, conv);
+ }
+ else if (fromref || (expr && real_lvalue_p (expr)))
+ conv = build_conv (RVALUE_CONV, from, conv);
+
+ if (from == to)
+ return conv;
+
+ if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to))
+ && expr && null_ptr_cst_p (expr))
+ {
+ conv = build_conv (STD_CONV, to, conv);
+ }
+ else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE)
+ {
+ enum tree_code ufcode = TREE_CODE (TREE_TYPE (from));
+ enum tree_code utcode = TREE_CODE (TREE_TYPE (to));
+
+ if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (from)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (to)), 1))
+ ;
+ else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE
+ && ufcode != FUNCTION_TYPE)
{
- basetype = purpose_member (name, CLASSTYPE_TAGS (current_class_type));
- if (basetype)
- basetype = TREE_VALUE (basetype);
+ from = build_pointer_type
+ (cp_build_type_variant (void_type_node,
+ TYPE_READONLY (TREE_TYPE (from)),
+ TYPE_VOLATILE (TREE_TYPE (from))));
+ conv = build_conv (PTR_CONV, from, conv);
}
- else if (TREE_CODE (name) == SCOPE_REF
- && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
+ else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
{
- if (! is_aggr_typedef (TREE_OPERAND (name, 0), 1))
- return error_mark_node;
- basetype = purpose_member (TREE_OPERAND (name, 1),
- CLASSTYPE_TAGS (IDENTIFIER_TYPE_VALUE (TREE_OPERAND (name, 0))));
- if (basetype)
- basetype = TREE_VALUE (basetype);
+ tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from));
+ tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to));
+
+ if (DERIVED_FROM_P (fbase, tbase)
+ && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))),
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to))),
+ 1)))
+ {
+ from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
+ from = build_pointer_type (from);
+ conv = build_conv (PMEM_CONV, from, conv);
+ }
+ }
+ else if (IS_AGGR_TYPE (TREE_TYPE (from))
+ && IS_AGGR_TYPE (TREE_TYPE (to)))
+ {
+ if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
+ {
+ from = cp_build_type_variant (TREE_TYPE (to),
+ TYPE_READONLY (TREE_TYPE (from)),
+ TYPE_VOLATILE (TREE_TYPE (from)));
+ from = build_pointer_type (from);
+ conv = build_conv (PTR_CONV, from, conv);
+ }
}
- if (basetype != NULL_TREE)
- ;
- /* call to a constructor... */
- else if (basetype_path)
- basetype = BINFO_TYPE (basetype_path);
- else if (IDENTIFIER_HAS_TYPE_VALUE (name))
+ if (comptypes (from, to, 1))
+ /* OK */;
+ else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from)))
+ conv = build_conv (QUAL_CONV, to, conv);
+ else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from)))
{
- basetype = IDENTIFIER_TYPE_VALUE (name);
- name = constructor_name_full (basetype);
+ conv = build_conv (PTR_CONV, to, conv);
+ ICS_BAD_FLAG (conv) = 1;
}
else
+ return 0;
+
+ from = to;
+ }
+ else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from))
+ {
+ tree fromfn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from));
+ tree tofn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to));
+ tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn)));
+ tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn)));
+
+ if (! DERIVED_FROM_P (fbase, tbase)
+ || ! comptypes (TREE_TYPE (fromfn), TREE_TYPE (tofn), 1)
+ || ! compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)),
+ TREE_CHAIN (TYPE_ARG_TYPES (tofn)), 1)
+ || TYPE_READONLY (fbase) != TYPE_READONLY (tbase)
+ || TYPE_VOLATILE (fbase) != TYPE_VOLATILE (tbase))
+ return 0;
+
+ from = cp_build_type_variant (tbase, TYPE_READONLY (fbase),
+ TYPE_VOLATILE (fbase));
+ from = build_cplus_method_type (from, TREE_TYPE (fromfn),
+ TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
+ from = build_ptrmemfunc_type (build_pointer_type (from));
+ conv = build_conv (PMEM_CONV, from, conv);
+ }
+ else if (tcode == BOOLEAN_TYPE)
+ {
+ if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
+ || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from)))
+ return 0;
+
+ conv = build_conv (STD_CONV, to, conv);
+ if (fcode == POINTER_TYPE
+ || (TYPE_PTRMEMFUNC_P (from) && ICS_STD_RANK (conv) < PBOOL_RANK))
+ ICS_STD_RANK (conv) = PBOOL_RANK;
+ }
+ /* We don't check for ENUMERAL_TYPE here because there are no standard
+ conversions to enum type. */
+ else if (tcode == INTEGER_TYPE || tcode == BOOLEAN_TYPE
+ || tcode == REAL_TYPE)
+ {
+ if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
+ return 0;
+ conv = build_conv (STD_CONV, to, conv);
+
+ /* Give this a better rank if it's a promotion. */
+ if (to == type_promotes_to (from)
+ && ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK)
+ ICS_STD_RANK (conv) = PROMO_RANK;
+ }
+ else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
+ && DERIVED_FROM_P (to, from))
+ {
+ if (TREE_CODE (conv) == RVALUE_CONV)
+ conv = TREE_OPERAND (conv, 0);
+ conv = build_conv (BASE_CONV, to, conv);
+ }
+ else
+ return 0;
+
+ return conv;
+}
+
+/* Returns the conversion path from type FROM to reference type TO for
+ purposes of reference binding. For lvalue binding, either pass a
+ reference type to FROM or an lvalue expression to EXPR.
+
+ Currently does not distinguish in the generated trees between binding to
+ an lvalue and a temporary. Should it? */
+
+static tree
+reference_binding (rto, rfrom, expr, flags)
+ tree rto, rfrom, expr;
+ int flags;
+{
+ tree conv;
+ int lvalue = 1;
+ tree to = TREE_TYPE (rto);
+ tree from = rfrom;
+ int related;
+
+ if (TREE_CODE (from) == REFERENCE_TYPE)
+ from = TREE_TYPE (from);
+ else if (! expr || ! real_lvalue_p (expr))
+ lvalue = 0;
+
+ related = (comptypes (TYPE_MAIN_VARIANT (to),
+ TYPE_MAIN_VARIANT (from), 1)
+ || (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
+ && DERIVED_FROM_P (to, from)));
+
+ if (lvalue && related
+ && TYPE_READONLY (to) >= TYPE_READONLY (from)
+ && TYPE_VOLATILE (to) >= TYPE_VOLATILE (from))
+ {
+ conv = build1 (IDENTITY_CONV, from, expr);
+
+ if (comptypes (TYPE_MAIN_VARIANT (to),
+ TYPE_MAIN_VARIANT (from), 1))
+ conv = build_conv (REF_BIND, rto, conv);
+ else
{
- tree typedef_name = lookup_name (name, 1);
- if (typedef_name && TREE_CODE (typedef_name) == TYPE_DECL)
- {
- /* Canonicalize the typedef name. */
- basetype = TREE_TYPE (typedef_name);
- name = TYPE_IDENTIFIER (basetype);
- }
- else
+ conv = build_conv (REF_BIND, rto, conv);
+ ICS_STD_RANK (conv) = STD_RANK;
+ }
+ }
+ else
+ conv = NULL_TREE;
+
+ if (! conv)
+ {
+ conv = standard_conversion (to, rfrom, expr);
+ if (conv)
+ {
+ conv = build_conv (REF_BIND, rto, conv);
+
+ /* Bind directly to a base subobject of a class rvalue. Do it
+ after building the conversion for proper handling of ICS_RANK. */
+ if (TREE_CODE (TREE_OPERAND (conv, 0)) == BASE_CONV)
+ TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0);
+ }
+ if (conv
+ && ((! (TYPE_READONLY (to) && ! TYPE_VOLATILE (to)
+ && (flags & LOOKUP_NO_TEMP_BIND) == 0))
+ /* If T1 is reference-related to T2, cv1 must be the same
+ cv-qualification as, or greater cv-qualification than,
+ cv2; otherwise, the program is ill-formed. */
+ || (related
+ && (TYPE_READONLY (to) < TYPE_READONLY (from)
+ || TYPE_VOLATILE (to) < TYPE_VOLATILE (from)))))
+ ICS_BAD_FLAG (conv) = 1;
+ }
+
+ return conv;
+}
+
+/* Returns the implicit conversion sequence (see [over.ics]) from type FROM
+ to type TO. The optional expression EXPR may affect the conversion.
+ FLAGS are the usual overloading flags. Only LOOKUP_NO_CONVERSION is
+ significant. */
+
+static tree
+implicit_conversion (to, from, expr, flags)
+ tree to, from, expr;
+ int flags;
+{
+ tree conv;
+ struct z_candidate *cand;
+
+ if (expr && type_unknown_p (expr))
+ {
+ expr = instantiate_type (to, expr, 0);
+ if (expr == error_mark_node)
+ return 0;
+ from = TREE_TYPE (expr);
+ }
+
+ if (TREE_CODE (to) == REFERENCE_TYPE)
+ conv = reference_binding (to, from, expr, flags);
+ else
+ conv = standard_conversion (to, from, expr);
+
+ if (conv)
+ ;
+ else if (expr != NULL_TREE
+ && (IS_AGGR_TYPE (non_reference (from))
+ || IS_AGGR_TYPE (non_reference (to)))
+ && (flags & LOOKUP_NO_CONVERSION) == 0)
+ {
+ cand = build_user_type_conversion_1
+ (to, expr, LOOKUP_ONLYCONVERTING);
+ if (cand)
+ conv = cand->second_conv;
+ if ((! conv || ICS_BAD_FLAG (conv))
+ && TREE_CODE (to) == REFERENCE_TYPE
+ && (flags & LOOKUP_NO_TEMP_BIND) == 0)
+ {
+ cand = build_user_type_conversion_1
+ (TYPE_MAIN_VARIANT (TREE_TYPE (to)), expr, LOOKUP_ONLYCONVERTING);
+ if (cand)
{
- cp_error ("no constructor named `%T' in scope",
- name);
- return error_mark_node;
+ if (! TYPE_READONLY (TREE_TYPE (to))
+ || TYPE_VOLATILE (TREE_TYPE (to)))
+ ICS_BAD_FLAG (cand->second_conv) = 1;
+ if (!conv || (ICS_BAD_FLAG (conv)
+ > ICS_BAD_FLAG (cand->second_conv)))
+ conv = build_conv (REF_BIND, to, cand->second_conv);
}
}
+ }
- if (! IS_AGGR_TYPE (basetype))
- {
- non_aggr_error:
- if ((flags & LOOKUP_COMPLAIN) && TREE_CODE (basetype) != ERROR_MARK)
- cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
- name, instance, basetype);
+ return conv;
+}
- return error_mark_node;
+/* Add a new entry to the list of candidates. Used by the add_*_candidate
+ functions. */
+
+static struct z_candidate *
+add_candidate (candidates, fn, convs, viable)
+ struct z_candidate *candidates;
+ tree fn, convs;
+ int viable;
+{
+ struct z_candidate *cand
+ = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate));
+
+ cand->fn = fn;
+ cand->convs = convs;
+ cand->second_conv = NULL_TREE;
+ cand->viable = viable;
+ cand->basetype_path = NULL_TREE;
+ cand->template = NULL_TREE;
+ cand->warnings = NULL_TREE;
+ cand->next = candidates;
+
+ return cand;
+}
+
+/* Create an overload candidate for the function or method FN called with
+ the argument list ARGLIST and add it to CANDIDATES. FLAGS is passed on
+ to implicit_conversion. */
+
+static struct z_candidate *
+add_function_candidate (candidates, fn, arglist, flags)
+ struct z_candidate *candidates;
+ tree fn, arglist;
+ int flags;
+{
+ tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ int i, len;
+ tree convs;
+ tree parmnode = parmlist;
+ tree argnode = arglist;
+ int viable = 1;
+
+ /* The `this' and `in_chrg' arguments to constructors are not considered
+ in overload resolution. */
+ if (DECL_CONSTRUCTOR_P (fn))
+ {
+ parmnode = TREE_CHAIN (parmnode);
+ argnode = TREE_CHAIN (argnode);
+ if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+ {
+ parmnode = TREE_CHAIN (parmnode);
+ argnode = TREE_CHAIN (argnode);
}
}
- else if (instance == C_C_D || instance == current_class_decl)
+
+ len = list_length (argnode);
+ convs = make_scratch_vec (len);
+
+ for (i = 0; i < len; ++i)
{
- /* When doing initialization, we side-effect the TREE_TYPE of
- C_C_D, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */
- basetype = TREE_TYPE (C_C_D);
+ tree arg = TREE_VALUE (argnode);
+ tree argtype = TREE_TYPE (arg);
+ tree t;
- /* Anything manifestly `this' in constructors and destructors
- has a known type, so virtual function tables are not needed. */
- if (TYPE_VIRTUAL_P (basetype)
- && !(flags & LOOKUP_NONVIRTUAL))
- need_vtbl = (dtor_label || ctor_label)
- ? unneeded : maybe_needed;
+ /* An overloaded function does not have an argument type */
+ if (TREE_CODE (arg) == OVERLOAD)
+ argtype = unknown_type_node;
+ argtype = cp_build_type_variant
+ (argtype, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg));
- /* If `this' is a signature pointer and `name' is not a constructor,
- we are calling a signature member function. In that case, set the
- `basetype' to the signature type and dereference the `optr' field. */
- if (IS_SIGNATURE_POINTER (basetype)
- && TYPE_IDENTIFIER (basetype) != name)
+ if (parmnode == void_list_node)
+ break;
+ else if (parmnode)
+ t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags);
+ else
{
- basetype = SIGNATURE_TYPE (basetype);
- instance_ptr = build_optr_ref (instance);
- instance_ptr = convert (build_pointer_type (basetype), instance_ptr);
- basetype_path = TYPE_BINFO (basetype);
+ t = build1 (IDENTITY_CONV, argtype, arg);
+ ICS_ELLIPSIS_FLAG (t) = 1;
}
+
+ if (i == 0 && t && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
+ && ! DECL_CONSTRUCTOR_P (fn))
+ ICS_THIS_FLAG (t) = 1;
+
+ TREE_VEC_ELT (convs, i) = t;
+ if (! t)
+ break;
+
+ if (ICS_BAD_FLAG (t))
+ viable = -1;
+
+ if (parmnode)
+ parmnode = TREE_CHAIN (parmnode);
+ argnode = TREE_CHAIN (argnode);
+ }
+
+ if (i < len)
+ viable = 0;
+
+ /* Make sure there are default args for the rest of the parms. */
+ for (; parmnode && parmnode != void_list_node;
+ parmnode = TREE_CHAIN (parmnode))
+ if (! TREE_PURPOSE (parmnode))
+ {
+ viable = 0;
+ break;
+ }
+
+ return add_candidate (candidates, fn, convs, viable);
+}
+
+/* Create an overload candidate for the conversion function FN which will
+ be invoked for expression OBJ, producing a pointer-to-function which
+ will in turn be called with the argument list ARGLIST, and add it to
+ CANDIDATES. FLAGS is passed on to implicit_conversion. */
+
+static struct z_candidate *
+add_conv_candidate (candidates, fn, obj, arglist)
+ struct z_candidate *candidates;
+ tree fn, obj, arglist;
+{
+ tree totype = TREE_TYPE (TREE_TYPE (fn));
+ tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (totype));
+ int i, len = list_length (arglist) + 1;
+ tree convs = make_scratch_vec (len);
+ tree parmnode = parmlist;
+ tree argnode = arglist;
+ int viable = 1;
+ int flags = LOOKUP_NORMAL;
+
+ for (i = 0; i < len; ++i)
+ {
+ tree arg = i == 0 ? obj : TREE_VALUE (argnode);
+ tree argtype = lvalue_type (arg);
+ tree t;
+
+ if (i == 0)
+ t = implicit_conversion (totype, argtype, arg, flags);
+ else if (parmnode == void_list_node)
+ break;
+ else if (parmnode)
+ t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags);
else
{
- instance = C_C_D;
- instance_ptr = current_class_decl;
- basetype_path = TYPE_BINFO (current_class_type);
+ t = build1 (IDENTITY_CONV, argtype, arg);
+ ICS_ELLIPSIS_FLAG (t) = 1;
}
- result = build_field_call (basetype_path, instance_ptr, name, parms);
- if (result)
- return result;
+ TREE_VEC_ELT (convs, i) = t;
+ if (! t)
+ break;
+
+ if (ICS_BAD_FLAG (t))
+ viable = -1;
+
+ if (i == 0)
+ continue;
+
+ if (parmnode)
+ parmnode = TREE_CHAIN (parmnode);
+ argnode = TREE_CHAIN (argnode);
}
- else if (TREE_CODE (instance) == RESULT_DECL)
+
+ if (i < len)
+ viable = 0;
+
+ for (; parmnode && parmnode != void_list_node;
+ parmnode = TREE_CHAIN (parmnode))
+ if (! TREE_PURPOSE (parmnode))
+ {
+ viable = 0;
+ break;
+ }
+
+ return add_candidate (candidates, fn, convs, viable);
+}
+
+static struct z_candidate *
+build_builtin_candidate (candidates, fnname, type1, type2,
+ args, argtypes, flags)
+ struct z_candidate *candidates;
+ tree fnname, type1, type2, *args, *argtypes;
+ int flags;
+
+{
+ tree t, convs;
+ int viable = 1, i;
+ tree types[2];
+
+ types[0] = type1;
+ types[1] = type2;
+
+ convs = make_scratch_vec (args[2] ? 3 : (args[1] ? 2 : 1));
+
+ for (i = 0; i < 2; ++i)
{
- basetype = TREE_TYPE (instance);
- /* Should we ever have to make a virtual function reference
- from a RESULT_DECL, know that it must be of fixed type
- within the scope of this function. */
- if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))
- need_vtbl = maybe_needed;
- instance_ptr = build1 (ADDR_EXPR, build_pointer_type (basetype), instance);
+ if (! args[i])
+ break;
+
+ t = implicit_conversion (types[i], argtypes[i], args[i], flags);
+ if (! t)
+ {
+ viable = 0;
+ /* We need something for printing the candidate. */
+ t = build1 (IDENTITY_CONV, types[i], NULL_TREE);
+ }
+ else if (ICS_BAD_FLAG (t))
+ viable = 0;
+ TREE_VEC_ELT (convs, i) = t;
}
- else
+
+ /* For COND_EXPR we rearranged the arguments; undo that now. */
+ if (args[2])
{
- /* The MAIN_VARIANT of the type that `instance_ptr' winds up being. */
- tree inst_ptr_basetype;
+ TREE_VEC_ELT (convs, 2) = TREE_VEC_ELT (convs, 1);
+ TREE_VEC_ELT (convs, 1) = TREE_VEC_ELT (convs, 0);
+ t = implicit_conversion (boolean_type_node, argtypes[2], args[2], flags);
+ if (t)
+ TREE_VEC_ELT (convs, 0) = t;
+ else
+ viable = 0;
+ }
- static_call_context =
- (TREE_CODE (instance) == INDIRECT_REF
- && TREE_CODE (TREE_OPERAND (instance, 0)) == NOP_EXPR
- && TREE_OPERAND (TREE_OPERAND (instance, 0), 0) == error_mark_node);
+ return add_candidate (candidates, fnname, convs, viable);
+}
- if (TREE_CODE (instance) == OFFSET_REF)
- instance = resolve_offset_ref (instance);
+static int
+is_complete (t)
+ tree t;
+{
+ return TYPE_SIZE (complete_type (t)) != NULL_TREE;
+}
- /* the base type of an instance variable is pointer to class */
- basetype = TREE_TYPE (instance);
+/* Create any builtin operator overload candidates for the operator in
+ question given the converted operand types TYPE1 and TYPE2. The other
+ args are passed through from add_builtin_candidates to
+ build_builtin_candidate. */
+
+static struct z_candidate *
+add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
+ args, argtypes, flags)
+ struct z_candidate *candidates;
+ enum tree_code code, code2;
+ tree fnname, type1, type2, *args, *argtypes;
+ int flags;
+{
+ switch (code)
+ {
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ args[1] = integer_zero_node;
+ type2 = integer_type_node;
+ break;
+ default:
+ break;
+ }
- if (TREE_CODE (basetype) == REFERENCE_TYPE)
+ switch (code)
+ {
+
+/* 4 For every pair T, VQ), where T is an arithmetic or enumeration type,
+ and VQ is either volatile or empty, there exist candidate operator
+ functions of the form
+ VQ T& operator++(VQ T&);
+ T operator++(VQ T&, int);
+ 5 For every pair T, VQ), where T is an enumeration type or an arithmetic
+ type other than bool, and VQ is either volatile or empty, there exist
+ candidate operator functions of the form
+ VQ T& operator--(VQ T&);
+ T operator--(VQ T&, int);
+ 6 For every pair T, VQ), where T is a cv-qualified or cv-unqualified
+ complete object type, and VQ is either volatile or empty, there exist
+ candidate operator functions of the form
+ T*VQ& operator++(T*VQ&);
+ T*VQ& operator--(T*VQ&);
+ T* operator++(T*VQ&, int);
+ T* operator--(T*VQ&, int); */
+
+ case POSTDECREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ if (TREE_CODE (type1) == BOOLEAN_TYPE)
+ return candidates;
+ case POSTINCREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ if ((ARITHMETIC_TYPE_P (type1) && TREE_CODE (type1) != ENUMERAL_TYPE)
+ || TYPE_PTROB_P (type1))
{
- basetype = TREE_TYPE (basetype);
- if (! IS_AGGR_TYPE (basetype))
- goto non_aggr_error;
- /* Call to convert not needed because we are remaining
- within the same type. */
- instance_ptr = build1 (NOP_EXPR, build_pointer_type (basetype),
- instance);
- inst_ptr_basetype = TYPE_MAIN_VARIANT (basetype);
+ type1 = build_reference_type (type1);
+ break;
}
- else
+ return candidates;
+
+/* 7 For every cv-qualified or cv-unqualified complete object type T, there
+ exist candidate operator functions of the form
+
+ T& operator*(T*);
+
+ 8 For every function type T, there exist candidate operator functions of
+ the form
+ T& operator*(T*); */
+
+ case INDIRECT_REF:
+ if (TREE_CODE (type1) == POINTER_TYPE
+ && (TYPE_PTROB_P (type1)
+ || TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE))
+ break;
+ return candidates;
+
+/* 9 For every type T, there exist candidate operator functions of the form
+ T* operator+(T*);
+
+ 10For every promoted arithmetic type T, there exist candidate operator
+ functions of the form
+ T operator+(T);
+ T operator-(T); */
+
+ case CONVERT_EXPR: /* unary + */
+ if (TREE_CODE (type1) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) != OFFSET_TYPE)
+ break;
+ case NEGATE_EXPR:
+ if (ARITHMETIC_TYPE_P (type1))
+ break;
+ return candidates;
+
+/* 11For every promoted integral type T, there exist candidate operator
+ functions of the form
+ T operator~(T); */
+
+ case BIT_NOT_EXPR:
+ if (INTEGRAL_TYPE_P (type1))
+ break;
+ return candidates;
+
+/* 12For every quintuple C1, C2, T, CV1, CV2), where C2 is a class type, C1
+ is the same type as C2 or is a derived class of C2, T is a complete
+ object type or a function type, and CV1 and CV2 are cv-qualifier-seqs,
+ there exist candidate operator functions of the form
+ CV12 T& operator->*(CV1 C1*, CV2 T C2::*);
+ where CV12 is the union of CV1 and CV2. */
+
+ case MEMBER_REF:
+ if (TREE_CODE (type1) == POINTER_TYPE
+ && (TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2)))
{
- if (! IS_AGGR_TYPE (basetype)
- && ! (TYPE_LANG_SPECIFIC (basetype)
- && (IS_SIGNATURE_POINTER (basetype)
- || IS_SIGNATURE_REFERENCE (basetype))))
- goto non_aggr_error;
-
- /* If `instance' is a signature pointer/reference and `name' is
- not a constructor, we are calling a signature member function.
- In that case set the `basetype' to the signature type. */
- if ((IS_SIGNATURE_POINTER (basetype)
- || IS_SIGNATURE_REFERENCE (basetype))
- && TYPE_IDENTIFIER (basetype) != name)
- basetype = SIGNATURE_TYPE (basetype);
-
- if ((IS_SIGNATURE (basetype)
- && (instance_ptr = instance))
- || (lvalue_p (instance)
- && (instance_ptr = build_unary_op (ADDR_EXPR, instance, 0)))
- || (instance_ptr = unary_complex_lvalue (ADDR_EXPR, instance)))
- {
- if (instance_ptr == error_mark_node)
- return error_mark_node;
- }
- else if (TREE_CODE (instance) == NOP_EXPR
- || TREE_CODE (instance) == CONSTRUCTOR)
- {
- /* A cast is not an lvalue. Initialize a fresh temp
- with the value we are casting from, and proceed with
- that temporary. We can't cast to a reference type,
- so that simplifies the initialization to something
- we can manage. */
- tree temp = get_temp_name (TREE_TYPE (instance), 0);
- if (IS_AGGR_TYPE (TREE_TYPE (instance)))
- expand_aggr_init (temp, instance, 0, flags);
- else
- {
- store_init_value (temp, instance);
- expand_decl_init (temp);
- }
- instance = temp;
- instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
- }
- else
+ tree c1 = TREE_TYPE (type1);
+ tree c2 = (TYPE_PTRMEMFUNC_P (type2)
+ ? TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type2)))
+ : TYPE_OFFSET_BASETYPE (TREE_TYPE (type2)));
+
+ if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1)
+ && (TYPE_PTRMEMFUNC_P (type2)
+ || is_complete (TREE_TYPE (TREE_TYPE (type2)))))
+ break;
+ }
+ return candidates;
+
+/* 13For every pair of promoted arithmetic types L and R, there exist can-
+ didate operator functions of the form
+ LR operator*(L, R);
+ LR operator/(L, R);
+ LR operator+(L, R);
+ LR operator-(L, R);
+ bool operator<(L, R);
+ bool operator>(L, R);
+ bool operator<=(L, R);
+ bool operator>=(L, R);
+ bool operator==(L, R);
+ bool operator!=(L, R);
+ where LR is the result of the usual arithmetic conversions between
+ types L and R.
+
+ 14For every pair of types T and I, where T is a cv-qualified or cv-
+ unqualified complete object type and I is a promoted integral type,
+ there exist candidate operator functions of the form
+ T* operator+(T*, I);
+ T& operator[](T*, I);
+ T* operator-(T*, I);
+ T* operator+(I, T*);
+ T& operator[](I, T*);
+
+ 15For every T, where T is a pointer to complete object type, there exist
+ candidate operator functions of the form112)
+ ptrdiff_t operator-(T, T);
+
+ 16For every pointer type T, there exist candidate operator functions of
+ the form
+ bool operator<(T, T);
+ bool operator>(T, T);
+ bool operator<=(T, T);
+ bool operator>=(T, T);
+ bool operator==(T, T);
+ bool operator!=(T, T);
+
+ 17For every pointer to member type T, there exist candidate operator
+ functions of the form
+ bool operator==(T, T);
+ bool operator!=(T, T); */
+
+ case MINUS_EXPR:
+ if (TYPE_PTROB_P (type1) && TYPE_PTROB_P (type2))
+ break;
+ if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ {
+ type2 = ptrdiff_type_node;
+ break;
+ }
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
+ break;
+ return candidates;
+
+ case EQ_EXPR:
+ case NE_EXPR:
+ if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2))
+ || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)))
+ break;
+ if ((TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEM_P (type1))
+ && null_ptr_cst_p (args[1]))
+ {
+ type2 = type1;
+ break;
+ }
+ if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2))
+ && null_ptr_cst_p (args[0]))
+ {
+ type1 = type2;
+ break;
+ }
+ case LT_EXPR:
+ case GT_EXPR:
+ case LE_EXPR:
+ case GE_EXPR:
+ case MAX_EXPR:
+ case MIN_EXPR:
+ if ((ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
+ || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2)))
+ break;
+ if (TYPE_PTR_P (type1) && null_ptr_cst_p (args[1]))
+ {
+ type2 = type1;
+ break;
+ }
+ if (null_ptr_cst_p (args[0]) && TYPE_PTR_P (type2))
+ {
+ type1 = type2;
+ break;
+ }
+ return candidates;
+
+ case PLUS_EXPR:
+ if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
+ break;
+ case ARRAY_REF:
+ if (INTEGRAL_TYPE_P (type1) && TYPE_PTROB_P (type2))
+ {
+ type1 = ptrdiff_type_node;
+ break;
+ }
+ if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ {
+ type2 = ptrdiff_type_node;
+ break;
+ }
+ return candidates;
+
+/* 18For every pair of promoted integral types L and R, there exist candi-
+ date operator functions of the form
+ LR operator%(L, R);
+ LR operator&(L, R);
+ LR operator^(L, R);
+ LR operator|(L, R);
+ L operator<<(L, R);
+ L operator>>(L, R);
+ where LR is the result of the usual arithmetic conversions between
+ types L and R. */
+
+ case TRUNC_MOD_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
+ break;
+ return candidates;
+
+/* 19For every triple L, VQ, R), where L is an arithmetic or enumeration
+ type, VQ is either volatile or empty, and R is a promoted arithmetic
+ type, there exist candidate operator functions of the form
+ VQ L& operator=(VQ L&, R);
+ VQ L& operator*=(VQ L&, R);
+ VQ L& operator/=(VQ L&, R);
+ VQ L& operator+=(VQ L&, R);
+ VQ L& operator-=(VQ L&, R);
+
+ 20For every pair T, VQ), where T is any type and VQ is either volatile
+ or empty, there exist candidate operator functions of the form
+ T*VQ& operator=(T*VQ&, T*);
+
+ 21For every pair T, VQ), where T is a pointer to member type and VQ is
+ either volatile or empty, there exist candidate operator functions of
+ the form
+ VQ T& operator=(VQ T&, T);
+
+ 22For every triple T, VQ, I), where T is a cv-qualified or cv-
+ unqualified complete object type, VQ is either volatile or empty, and
+ I is a promoted integral type, there exist candidate operator func-
+ tions of the form
+ T*VQ& operator+=(T*VQ&, I);
+ T*VQ& operator-=(T*VQ&, I);
+
+ 23For every triple L, VQ, R), where L is an integral or enumeration
+ type, VQ is either volatile or empty, and R is a promoted integral
+ type, there exist candidate operator functions of the form
+
+ VQ L& operator%=(VQ L&, R);
+ VQ L& operator<<=(VQ L&, R);
+ VQ L& operator>>=(VQ L&, R);
+ VQ L& operator&=(VQ L&, R);
+ VQ L& operator^=(VQ L&, R);
+ VQ L& operator|=(VQ L&, R); */
+
+ case MODIFY_EXPR:
+ switch (code2)
+ {
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
{
- if (TREE_CODE (instance) != CALL_EXPR)
- my_friendly_abort (125);
- if (TYPE_NEEDS_CONSTRUCTING (basetype))
- instance = build_cplus_new (basetype, instance, 0);
- else
- {
- instance = get_temp_name (basetype, 0);
- TREE_ADDRESSABLE (instance) = 1;
- }
- instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
+ type2 = ptrdiff_type_node;
+ break;
}
- /* @@ Should we call comp_target_types here? */
- if (IS_SIGNATURE (basetype))
- inst_ptr_basetype = basetype;
- else
- inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr));
- if (TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (inst_ptr_basetype))
- basetype = inst_ptr_basetype;
- else
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
+ break;
+ return candidates;
+
+ case TRUNC_MOD_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
+ break;
+ return candidates;
+
+ case NOP_EXPR:
+ if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
+ break;
+ if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2))
+ || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
+ || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))
+ || ((TYPE_PTRMEMFUNC_P (type1)
+ || TREE_CODE (type1) == POINTER_TYPE)
+ && null_ptr_cst_p (args[1])))
{
- instance_ptr = convert (build_pointer_type (basetype), instance_ptr);
- if (instance_ptr == error_mark_node)
- return error_mark_node;
+ type2 = type1;
+ break;
}
+ return candidates;
+
+ default:
+ my_friendly_abort (367);
}
+ type1 = build_reference_type (type1);
+ break;
+
+ case COND_EXPR:
+ /* Kludge around broken overloading rules whereby
+ bool ? const char& : enum is ambiguous
+ (between int and const char&). */
+ flags |= LOOKUP_NO_TEMP_BIND;
+
+ /* Extension: Support ?: of enumeral type. Hopefully this will not
+ be an extension for long. */
+ if (TREE_CODE (type1) == ENUMERAL_TYPE && type1 == type2)
+ break;
+ else if (TREE_CODE (type1) == ENUMERAL_TYPE
+ || TREE_CODE (type2) == ENUMERAL_TYPE)
+ return candidates;
+ if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
+ break;
+ if (TREE_CODE (type1) == TREE_CODE (type2)
+ && (TREE_CODE (type1) == REFERENCE_TYPE
+ || TREE_CODE (type1) == POINTER_TYPE
+ || TYPE_PTRMEMFUNC_P (type1)
+ || IS_AGGR_TYPE (type1)))
+ break;
+ if (TREE_CODE (type1) == REFERENCE_TYPE
+ || TREE_CODE (type2) == REFERENCE_TYPE)
+ return candidates;
+ if (((TYPE_PTRMEMFUNC_P (type1) || TREE_CODE (type1) == POINTER_TYPE)
+ && null_ptr_cst_p (args[1]))
+ || IS_AGGR_TYPE (type1))
+ {
+ type2 = type1;
+ break;
+ }
+ if (((TYPE_PTRMEMFUNC_P (type2) || TREE_CODE (type2) == POINTER_TYPE)
+ && null_ptr_cst_p (args[0]))
+ || IS_AGGR_TYPE (type2))
+ {
+ type1 = type2;
+ break;
+ }
+ return candidates;
- /* After converting `instance_ptr' above, `inst_ptr_basetype' was
- not updated, so we use `basetype' instead. */
- if (basetype_path == NULL_TREE
- && IS_SIGNATURE (basetype))
- basetype_path = TYPE_BINFO (basetype);
- else if (basetype_path == NULL_TREE ||
- BINFO_TYPE (basetype_path) != TYPE_MAIN_VARIANT (inst_ptr_basetype))
- basetype_path = TYPE_BINFO (inst_ptr_basetype);
+ default:
+ my_friendly_abort (367);
+ }
- result = build_field_call (basetype_path, instance_ptr, name, parms);
- if (result)
- return result;
+ /* If we're dealing with two pointer types, we need candidates
+ for both of them. */
+ if (type2 && type1 != type2
+ && TREE_CODE (type1) == TREE_CODE (type2)
+ && (TREE_CODE (type1) == REFERENCE_TYPE
+ || (TREE_CODE (type1) == POINTER_TYPE
+ && TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2))
+ || TYPE_PTRMEMFUNC_P (type1)
+ || IS_AGGR_TYPE (type1)))
+ {
+ candidates = build_builtin_candidate
+ (candidates, fnname, type1, type1, args, argtypes, flags);
+ return build_builtin_candidate
+ (candidates, fnname, type2, type2, args, argtypes, flags);
+ }
+
+ return build_builtin_candidate
+ (candidates, fnname, type1, type2, args, argtypes, flags);
+}
+
+tree
+type_decays_to (type)
+ tree type;
+{
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ return build_pointer_type (TREE_TYPE (type));
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ return build_pointer_type (type);
+ return type;
+}
+
+/* There are three conditions of builtin candidates:
+
+ 1) bool-taking candidates. These are the same regardless of the input.
+ 2) pointer-pair taking candidates. These are generated for each type
+ one of the input types converts to.
+ 3) arithmetic candidates. According to the WP, we should generate
+ all of these, but I'm trying not to... */
+
+static struct z_candidate *
+add_builtin_candidates (candidates, code, code2, fnname, args, flags)
+ struct z_candidate *candidates;
+ enum tree_code code, code2;
+ tree fnname, *args;
+ int flags;
+{
+ int ref1, i;
+ tree type, argtypes[3], types[2];
- if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))
+ for (i = 0; i < 3; ++i)
+ {
+ if (args[i])
+ argtypes[i] = lvalue_type (args[i]);
+ else
+ argtypes[i] = NULL_TREE;
+ }
+
+ switch (code)
+ {
+/* 4 For every pair T, VQ), where T is an arithmetic or enumeration type,
+ and VQ is either volatile or empty, there exist candidate operator
+ functions of the form
+ VQ T& operator++(VQ T&); */
+
+ case POSTINCREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case MODIFY_EXPR:
+ ref1 = 1;
+ break;
+
+/* 24There also exist candidate operator functions of the form
+ bool operator!(bool);
+ bool operator&&(bool, bool);
+ bool operator||(bool, bool); */
+
+ case TRUTH_NOT_EXPR:
+ return build_builtin_candidate
+ (candidates, fnname, boolean_type_node,
+ NULL_TREE, args, argtypes, flags);
+
+ case TRUTH_ORIF_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ return build_builtin_candidate
+ (candidates, fnname, boolean_type_node,
+ boolean_type_node, args, argtypes, flags);
+
+ case ADDR_EXPR:
+ case COMPOUND_EXPR:
+ case COMPONENT_REF:
+ return candidates;
+
+ default:
+ ref1 = 0;
+ }
+
+ types[0] = types[1] = NULL_TREE;
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (! args[i])
+ ;
+ else if (IS_AGGR_TYPE (argtypes[i]))
{
- if (TREE_SIDE_EFFECTS (instance_ptr))
+ tree convs = lookup_conversions (argtypes[i]);
+
+ if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
+ return candidates;
+
+ convs = lookup_conversions (argtypes[i]);
+
+ if (code == COND_EXPR)
{
- /* This action is needed because the instance is needed
- for providing the base of the virtual function table.
- Without using a SAVE_EXPR, the function we are building
- may be called twice, or side effects on the instance
- variable (such as a post-increment), may happen twice. */
- instance_ptr = save_expr (instance_ptr);
- instance = build_indirect_ref (instance_ptr, NULL_PTR);
+ if (real_lvalue_p (args[i]))
+ types[i] = scratch_tree_cons
+ (NULL_TREE, build_reference_type (argtypes[i]), types[i]);
+
+ types[i] = scratch_tree_cons
+ (NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]);
}
- else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
+
+ else if (! convs)
+ return candidates;
+
+ for (; convs; convs = TREE_CHAIN (convs))
{
- /* This happens when called for operator new (). */
- instance = build_indirect_ref (instance, NULL_PTR);
- }
+ type = TREE_TYPE (TREE_TYPE (TREE_VALUE (convs)));
+
+ if (i == 0 && ref1
+ && (TREE_CODE (type) != REFERENCE_TYPE
+ || TYPE_READONLY (TREE_TYPE (type))))
+ continue;
+
+ if (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE)
+ types[i] = scratch_tree_cons (NULL_TREE, type, types[i]);
+
+ type = non_reference (type);
+ if (i != 0 || ! ref1)
+ {
+ type = TYPE_MAIN_VARIANT (type_decays_to (type));
+ if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE)
+ types[i] = scratch_tree_cons (NULL_TREE, type, types[i]);
+ if (INTEGRAL_TYPE_P (type))
+ type = type_promotes_to (type);
+ }
- need_vtbl = maybe_needed;
+ if (! value_member (type, types[i]))
+ types[i] = scratch_tree_cons (NULL_TREE, type, types[i]);
+ }
+ }
+ else
+ {
+ if (code == COND_EXPR && real_lvalue_p (args[i]))
+ types[i] = scratch_tree_cons
+ (NULL_TREE, build_reference_type (argtypes[i]), types[i]);
+ type = non_reference (argtypes[i]);
+ if (i != 0 || ! ref1)
+ {
+ type = TYPE_MAIN_VARIANT (type_decays_to (type));
+ if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE)
+ types[i] = scratch_tree_cons (NULL_TREE, type, types[i]);
+ if (INTEGRAL_TYPE_P (type))
+ type = type_promotes_to (type);
+ }
+ types[i] = scratch_tree_cons (NULL_TREE, type, types[i]);
}
}
- if (TYPE_SIZE (basetype) == 0)
+ for (; types[0]; types[0] = TREE_CHAIN (types[0]))
{
- /* This is worth complaining about, I think. */
- cp_error ("cannot lookup method in incomplete type `%T'", basetype);
- return error_mark_node;
+ if (types[1])
+ for (type = types[1]; type; type = TREE_CHAIN (type))
+ candidates = add_builtin_candidate
+ (candidates, code, code2, fnname, TREE_VALUE (types[0]),
+ TREE_VALUE (type), args, argtypes, flags);
+ else
+ candidates = add_builtin_candidate
+ (candidates, code, code2, fnname, TREE_VALUE (types[0]),
+ NULL_TREE, args, argtypes, flags);
}
- save_basetype = TYPE_MAIN_VARIANT (basetype);
+ return candidates;
+}
-#if 0
- if (all_virtual == 1
- && (! strncmp (IDENTIFIER_POINTER (name), OPERATOR_METHOD_FORMAT,
- OPERATOR_METHOD_LENGTH)
- || instance_ptr == NULL_TREE
- || (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype) == 0)))
- all_virtual = 0;
-#endif
- last = NULL_TREE;
- for (parmtypes = NULL_TREE, parm = parms; parm; parm = TREE_CHAIN (parm))
+/* If TMPL can be successfully instantiated as indicated by
+ EXPLICIT_TARGS and ARGLIST, adds the instantiation to CANDIDATES.
+
+ TMPL is the template. EXPLICIT_TARGS are any explicit template
+ arguments. ARGLIST is the arguments provided at the call-site.
+ The RETURN_TYPE is the desired type for conversion operators. If
+ OBJ is NULL_TREE, FLAGS are as for add_function_candidate. If an
+ OBJ is supplied, FLAGS are ignored, and OBJ is as for
+ add_conv_candidate. */
+
+static struct z_candidate*
+add_template_candidate_real (candidates, tmpl, explicit_targs,
+ arglist, return_type, flags,
+ obj, strict)
+ struct z_candidate *candidates;
+ tree tmpl, explicit_targs, arglist, return_type;
+ int flags;
+ tree obj;
+ unification_kind_t strict;
+{
+ int ntparms = DECL_NTPARMS (tmpl);
+ tree targs = make_scratch_vec (ntparms);
+ struct z_candidate *cand;
+ int i;
+ tree fn;
+
+ i = fn_type_unification (tmpl, explicit_targs, targs, arglist,
+ return_type, strict, NULL_TREE);
+
+ if (i != 0)
+ return candidates;
+
+ fn = instantiate_template (tmpl, targs);
+ if (fn == error_mark_node)
+ return candidates;
+
+ if (obj != NULL_TREE)
+ /* Aha, this is a conversion function. */
+ cand = add_conv_candidate (candidates, fn, obj, arglist);
+ else
+ cand = add_function_candidate (candidates, fn, arglist, flags);
+ if (DECL_TI_TEMPLATE (fn) != tmpl)
+ /* This situation can occur if a member template of a template
+ class is specialized. Then, instantiate_template might return
+ an instantiation of the specialization, in which case the
+ DECL_TI_TEMPLATE field will point at the original
+ specialization. For example:
+
+ template <class T> struct S { template <class U> void f(U);
+ template <> void f(int) {}; };
+ S<double> sd;
+ sd.f(3);
+
+ Here, TMPL will be template <class U> S<double>::f(U).
+ And, instantiate template will give us the specialization
+ template <> S<double>::f(int). But, the DECL_TI_TEMPLATE field
+ for this will point at template <class T> template <> S<T>::f(int),
+ so that we can find the definition. For the purposes of
+ overload resolution, however, we want the original TMPL. */
+ cand->template = tree_cons (tmpl, targs, NULL_TREE);
+ else
+ cand->template = DECL_TEMPLATE_INFO (fn);
+
+ return cand;
+}
+
+
+static struct z_candidate *
+add_template_candidate (candidates, tmpl, explicit_targs,
+ arglist, return_type, flags, strict)
+ struct z_candidate *candidates;
+ tree tmpl, explicit_targs, arglist, return_type;
+ int flags;
+ unification_kind_t strict;
+{
+ return
+ add_template_candidate_real (candidates, tmpl, explicit_targs,
+ arglist, return_type, flags,
+ NULL_TREE, strict);
+}
+
+
+static struct z_candidate *
+add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
+ struct z_candidate *candidates;
+ tree tmpl, obj, arglist, return_type;
+{
+ return
+ add_template_candidate_real (candidates, tmpl, NULL_TREE, arglist,
+ return_type, 0, obj, DEDUCE_CONV);
+}
+
+
+static int
+any_viable (cands)
+ struct z_candidate *cands;
+{
+ for (; cands; cands = cands->next)
+ if (pedantic ? cands->viable == 1 : cands->viable)
+ return 1;
+ return 0;
+}
+
+static struct z_candidate *
+splice_viable (cands)
+ struct z_candidate *cands;
+{
+ struct z_candidate **p = &cands;
+
+ for (; *p; )
{
- tree t = TREE_TYPE (TREE_VALUE (parm));
- if (TREE_CODE (t) == OFFSET_TYPE)
+ if (pedantic ? (*p)->viable == 1 : (*p)->viable)
+ p = &((*p)->next);
+ else
+ *p = (*p)->next;
+ }
+
+ return cands;
+}
+
+static tree
+build_this (obj)
+ tree obj;
+{
+ /* Fix this to work on non-lvalues. */
+ if (IS_SIGNATURE_POINTER (TREE_TYPE (obj))
+ || IS_SIGNATURE_REFERENCE (TREE_TYPE (obj)))
+ return obj;
+ else
+ return build_unary_op (ADDR_EXPR, obj, 0);
+}
+
+static void
+print_z_candidates (candidates)
+ struct z_candidate *candidates;
+{
+ char *str = "candidates are:";
+ for (; candidates; candidates = candidates->next)
+ {
+ if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
{
- /* Convert OFFSET_TYPE entities to their normal selves. */
- TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
+ if (candidates->fn == ansi_opname [COND_EXPR])
+ cp_error ("%s %D(%T, %T, %T) <builtin>", str, candidates->fn,
+ TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
+ TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)),
+ TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2)));
+ else if (TREE_VEC_LENGTH (candidates->convs) == 2)
+ cp_error ("%s %D(%T, %T) <builtin>", str, candidates->fn,
+ TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
+ TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)));
+ else
+ cp_error ("%s %D(%T) <builtin>", str, candidates->fn,
+ TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
}
- if (TREE_CODE (TREE_VALUE (parm)) == OFFSET_REF
- && TREE_CODE (t) == METHOD_TYPE)
+ else
+ cp_error_at ("%s %+D%s", str, candidates->fn,
+ candidates->viable == -1 ? " <near match>" : "");
+ str = " ";
+ }
+}
+
+/* Returns the best overload candidate to perform the requested
+ conversion. This function is used for three the overloading situations
+ described in [over.match.copy], [over.match.conv], and [over.match.ref].
+ If TOTYPE is a REFERENCE_TYPE, we're trying to find an lvalue binding as
+ per [dcl.init.ref], so we ignore temporary bindings. */
+
+static struct z_candidate *
+build_user_type_conversion_1 (totype, expr, flags)
+ tree totype, expr;
+ int flags;
+{
+ struct z_candidate *candidates, *cand;
+ tree fromtype = TREE_TYPE (expr);
+ tree ctors = NULL_TREE, convs = NULL_TREE, *p;
+ tree args = NULL_TREE;
+ tree templates = NULL_TREE;
+
+ if (IS_AGGR_TYPE (totype))
+ ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
+ if (IS_AGGR_TYPE (fromtype)
+ && (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype)))
+ convs = lookup_conversions (fromtype);
+
+ candidates = 0;
+ flags |= LOOKUP_NO_CONVERSION;
+
+ if (ctors)
+ {
+ tree t = build_int_2 (0, 0);
+ TREE_TYPE (t) = build_pointer_type (totype);
+ args = build_scratch_list (NULL_TREE, expr);
+ if (TYPE_USES_VIRTUAL_BASECLASSES (totype))
+ args = scratch_tree_cons (NULL_TREE, integer_one_node, args);
+ args = scratch_tree_cons (NULL_TREE, t, args);
+
+ ctors = TREE_VALUE (ctors);
+ }
+ for (; ctors; ctors = OVL_NEXT (ctors))
+ {
+ tree ctor = OVL_CURRENT (ctors);
+ if (DECL_NONCONVERTING_P (ctor))
+ continue;
+
+ if (TREE_CODE (ctor) == TEMPLATE_DECL)
{
- TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0);
- }
+ templates = scratch_tree_cons (NULL_TREE, ctor, templates);
+ candidates =
+ add_template_candidate (candidates, ctor,
+ NULL_TREE, args, NULL_TREE, flags,
+ DEDUCE_CALL);
+ }
+ else
+ candidates = add_function_candidate (candidates, ctor,
+ args, flags);
+
+ if (candidates)
+ {
+ candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
+ candidates->basetype_path = TYPE_BINFO (totype);
+ }
+ }
+
+ if (convs)
+ args = build_scratch_list (NULL_TREE, build_this (expr));
+
+ for (; convs; convs = TREE_CHAIN (convs))
+ {
+ tree fns = TREE_VALUE (convs);
+ int convflags = LOOKUP_NO_CONVERSION;
+ tree ics;
+
+ /* If we are called to convert to a reference type, we are trying to
+ find an lvalue binding, so don't even consider temporaries. If
+ we don't find an lvalue binding, the caller will try again to
+ look for a temporary binding. */
+ if (TREE_CODE (totype) == REFERENCE_TYPE)
+ convflags |= LOOKUP_NO_TEMP_BIND;
+
+ if (TREE_CODE (fns) != TEMPLATE_DECL)
+ ics = implicit_conversion
+ (totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags);
+ else
+ /* We can't compute this yet. */
+ ics = error_mark_node;
+
+ if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics))
+ /* ignore the near match. */;
+ else if (ics)
+ for (; fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ struct z_candidate *old_candidates = candidates;
+
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ {
+ templates = scratch_tree_cons (NULL_TREE, fn, templates);
+ candidates =
+ add_template_candidate (candidates, fn, NULL_TREE,
+ args, totype, flags,
+ DEDUCE_CONV);
+ }
+ else
+ candidates = add_function_candidate (candidates, fn,
+ args, flags);
+
+ if (candidates != old_candidates)
+ {
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ ics = implicit_conversion
+ (totype, TREE_TYPE (TREE_TYPE (candidates->fn)),
+ 0, convflags);
+
+ candidates->second_conv = ics;
+ candidates->basetype_path = TREE_PURPOSE (convs);
+
+ if (ics == NULL_TREE)
+ candidates->viable = 0;
+ else if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
+ candidates->viable = -1;
+ }
+ }
+ }
+
+ if (! any_viable (candidates))
+ {
#if 0
- /* This breaks reference-to-array parameters. */
- if (TREE_CODE (t) == ARRAY_TYPE)
+ if (flags & LOOKUP_COMPLAIN)
{
- /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
- This eliminates needless calls to `compute_conversion_costs'. */
- TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
+ if (candidates && ! candidates->next)
+ /* say why this one won't work or try to be loose */;
+ else
+ cp_error ("no viable candidates");
}
#endif
- if (t == error_mark_node)
- return error_mark_node;
- last = build_tree_list (NULL_TREE, t);
- parmtypes = chainon (parmtypes, last);
+
+ return 0;
}
- if (instance && IS_SIGNATURE (basetype))
+ candidates = splice_viable (candidates);
+ cand = tourney (candidates);
+
+ if (cand == 0)
{
- /* @@ Should this be the constp/volatilep flags for the optr field
- of the signature pointer? */
- constp = TYPE_READONLY (basetype);
- volatilep = TYPE_VOLATILE (basetype);
- parms = tree_cons (NULL_TREE, instance_ptr, parms);
+ if (flags & LOOKUP_COMPLAIN)
+ {
+ cp_error ("conversion from `%T' to `%T' is ambiguous",
+ fromtype, totype);
+ print_z_candidates (candidates);
+ }
+
+ cand = candidates; /* any one will do */
+ cand->second_conv = build1 (AMBIG_CONV, totype, expr);
+ ICS_USER_FLAG (cand->second_conv) = 1;
+ ICS_BAD_FLAG (cand->second_conv) = 1;
+
+ return cand;
}
- else if (instance)
+
+ for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; )
+ p = &(TREE_OPERAND (*p, 0));
+
+ /* Pedantically, normal function declarations are never considered
+ to refer to template instantiations, so we only do this with
+ -fguiding-decls. */
+ if (flag_guiding_decls && templates && ! cand->template
+ && !DECL_INITIAL (cand->fn)
+ && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE)
+ add_maybe_template (cand->fn, templates);
+
+ *p = build
+ (USER_CONV,
+ (DECL_CONSTRUCTOR_P (cand->fn)
+ ? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
+ expr, build_expr_ptr_wrapper (cand));
+ ICS_USER_FLAG (cand->second_conv) = 1;
+ if (cand->viable == -1)
+ ICS_BAD_FLAG (cand->second_conv) = 1;
+
+ return cand;
+}
+
+tree
+build_user_type_conversion (totype, expr, flags)
+ tree totype, expr;
+ int flags;
+{
+ struct z_candidate *cand
+ = build_user_type_conversion_1 (totype, expr, flags);
+
+ if (cand)
{
- /* TREE_READONLY (instance) fails for references. */
- constp = TYPE_READONLY (TREE_TYPE (TREE_TYPE (instance_ptr)));
- volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (instance_ptr)));
- parms = tree_cons (NULL_TREE, instance_ptr, parms);
+ if (TREE_CODE (cand->second_conv) == AMBIG_CONV)
+ return error_mark_node;
+ return convert_from_reference (convert_like (cand->second_conv, expr));
}
- else
+ return NULL_TREE;
+}
+
+/* Do any initial processing on the arguments to a function call. */
+
+static tree
+resolve_args (args)
+ tree args;
+{
+ tree t;
+ for (t = args; t; t = TREE_CHAIN (t))
{
- /* Raw constructors are always in charge. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)
- && ! (flags & LOOKUP_HAS_IN_CHARGE))
+ if (TREE_VALUE (t) == error_mark_node)
+ return error_mark_node;
+ else if (TREE_CODE (TREE_TYPE (TREE_VALUE (t))) == VOID_TYPE)
{
- flags |= LOOKUP_HAS_IN_CHARGE;
- parms = tree_cons (NULL_TREE, integer_one_node, parms);
- parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);
+ error ("invalid use of void expression");
+ return error_mark_node;
}
+ else if (TREE_CODE (TREE_VALUE (t)) == OFFSET_REF)
+ TREE_VALUE (t) = resolve_offset_ref (TREE_VALUE (t));
+ }
+ return args;
+}
+
+tree
+build_new_function_call (fn, args)
+ tree fn, args;
+{
+ struct z_candidate *candidates = 0, *cand;
+ tree explicit_targs = NULL_TREE;
+ int template_only = 0;
- 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);
+ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+ {
+ explicit_targs = TREE_OPERAND (fn, 1);
+ fn = TREE_OPERAND (fn, 0);
+ template_only = 1;
}
- parmtypes = tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes);
+ if (really_overloaded_fn (fn))
+ {
+ tree t1;
+ tree templates = NULL_TREE;
- if (last == NULL_TREE)
- last = parmtypes;
+ args = resolve_args (args);
- /* Look up function name in the structure type definition. */
+ if (args == error_mark_node)
+ return error_mark_node;
- if ((IDENTIFIER_HAS_TYPE_VALUE (name)
- && ! IDENTIFIER_OPNAME_P (name)
- && IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name))
- && TREE_CODE (IDENTIFIER_TYPE_VALUE (name)) != UNINSTANTIATED_P_TYPE)
- || name == constructor_name (basetype))
- {
- tree tmp = NULL_TREE;
- if (IDENTIFIER_TYPE_VALUE (name) == basetype
- || name == constructor_name (basetype))
- tmp = TYPE_BINFO (basetype);
- else
- tmp = get_binfo (IDENTIFIER_TYPE_VALUE (name), basetype, 0);
-
- if (tmp != NULL_TREE)
+ for (t1 = fn; t1; t1 = OVL_CHAIN (t1))
{
- name_kind = "constructor";
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)
- && ! (flags & LOOKUP_HAS_IN_CHARGE))
+ tree t = OVL_FUNCTION (t1);
+ if (TREE_CODE (t) == TEMPLATE_DECL)
{
- /* Constructors called for initialization
- only are never in charge. */
- tree tmplist;
-
- flags |= LOOKUP_HAS_IN_CHARGE;
- tmplist = tree_cons (NULL_TREE, integer_zero_node,
- TREE_CHAIN (parms));
- TREE_CHAIN (parms) = tmplist;
- tmplist = tree_cons (NULL_TREE, integer_type_node, TREE_CHAIN (parmtypes));
- TREE_CHAIN (parmtypes) = tmplist;
+ templates = scratch_tree_cons (NULL_TREE, t, templates);
+ candidates = add_template_candidate
+ (candidates, t, explicit_targs, args, NULL_TREE,
+ LOOKUP_NORMAL, DEDUCE_CALL);
}
- basetype = BINFO_TYPE (tmp);
+ else if (! template_only)
+ candidates = add_function_candidate
+ (candidates, t, args, LOOKUP_NORMAL);
}
- else
- name_kind = "method";
+
+ if (! any_viable (candidates))
+ {
+ if (candidates && ! candidates->next)
+ return build_function_call (candidates->fn, args);
+ cp_error ("no matching function for call to `%D (%A)'",
+ DECL_NAME (OVL_FUNCTION (fn)), args);
+ if (candidates)
+ print_z_candidates (candidates);
+ return error_mark_node;
+ }
+ candidates = splice_viable (candidates);
+ cand = tourney (candidates);
+
+ if (cand == 0)
+ {
+ cp_error ("call of overloaded `%D (%A)' is ambiguous",
+ DECL_NAME (OVL_FUNCTION (fn)), args);
+ print_z_candidates (candidates);
+ return error_mark_node;
+ }
+
+ /* Pedantically, normal function declarations are never considered
+ to refer to template instantiations, so we only do this with
+ -fguiding-decls. */
+ if (flag_guiding_decls && templates && ! cand->template
+ && ! DECL_INITIAL (cand->fn))
+ add_maybe_template (cand->fn, templates);
+
+ return build_over_call (cand, args, LOOKUP_NORMAL);
}
- else
- name_kind = "method";
-
- if (basetype_path == NULL_TREE
- || BINFO_TYPE (basetype_path) != TYPE_MAIN_VARIANT (basetype))
- basetype_path = TYPE_BINFO (basetype);
- result = lookup_fnfields (basetype_path, name,
- (flags & LOOKUP_COMPLAIN));
- if (result == error_mark_node)
- return error_mark_node;
+ /* This is not really overloaded. */
+ fn = OVL_CURRENT (fn);
-#if 0
- /* Now, go look for this method name. We do not find destructors here.
-
- Putting `void_list_node' on the end of the parmtypes
- fakes out `build_decl_overload' into doing the right thing. */
- TREE_CHAIN (last) = void_list_node;
- method_name = build_decl_overload (name, parmtypes,
- 1 + (name == constructor_name (save_basetype)
- || name == constructor_name_full (save_basetype)));
- TREE_CHAIN (last) = NULL_TREE;
-#endif
+ return build_function_call (fn, args);
+}
- for (pass = 0; pass < 2; pass++)
+static tree
+build_object_call (obj, args)
+ tree obj, args;
+{
+ struct z_candidate *candidates = 0, *cand;
+ tree fns, convs, mem_args = NULL_TREE;
+ tree type = TREE_TYPE (obj);
+ tree templates = NULL_TREE;
+
+ if (TYPE_PTRMEMFUNC_P (type))
{
- struct candidate *candidates;
- struct candidate *cp;
- int len;
- unsigned best = 1;
+ /* It's no good looking for an overloaded operator() on a
+ pointer-to-member-function. */
+ cp_error ("pointer-to-member function %E cannot be called", obj);
+ cp_error ("without an object; consider using .* or ->*");
+ return error_mark_node;
+ }
- /* This increments every time we go up the type hierarchy.
- The idea is to prefer a function of the derived class if possible. */
- int b_or_d = 0;
+ fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname [CALL_EXPR], 1);
+ if (fns == error_mark_node)
+ return error_mark_node;
- baselink = result;
+ args = resolve_args (args);
- if (pass > 0)
- {
- candidates
- = (struct candidate *) alloca ((ever_seen+1)
- * sizeof (struct candidate));
- bzero ((char *) candidates, (ever_seen + 1) * sizeof (struct candidate));
- cp = candidates;
- len = list_length (parms);
- ever_seen = 0;
+ if (args == error_mark_node)
+ return error_mark_node;
- /* First see if a global function has a shot at it. */
- if (flags & LOOKUP_GLOBAL)
+ if (fns)
+ {
+ tree base = TREE_PURPOSE (fns);
+ mem_args = scratch_tree_cons (NULL_TREE, build_this (obj), args);
+
+ for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
{
- tree friend_parms;
- tree parm = instance_ptr;
+ templates = scratch_tree_cons (NULL_TREE, fn, templates);
+ candidates
+ = add_template_candidate (candidates, fn, NULL_TREE,
+ mem_args, NULL_TREE,
+ LOOKUP_NORMAL, DEDUCE_CALL);
+ }
+ else
+ candidates = add_function_candidate
+ (candidates, fn, mem_args, LOOKUP_NORMAL);
- if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE)
- parm = convert_from_reference (parm);
- else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
- parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
- else
- my_friendly_abort (167);
+ if (candidates)
+ candidates->basetype_path = base;
+ }
+ }
- friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
+ convs = lookup_conversions (type);
- cp->h_len = len;
- cp->harshness = (struct harshness_code *)
- alloca ((len + 1) * sizeof (struct harshness_code));
+ for (; convs; convs = TREE_CHAIN (convs))
+ {
+ tree fns = TREE_VALUE (convs);
+ tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
+ tree fn;
+
+ if (TREE_CODE (totype) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
+ for (; fns; fns = OVL_NEXT (fn))
+ {
+ fn = OVL_CURRENT (fn);
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ {
+ templates = scratch_tree_cons (NULL_TREE, fn, templates);
+ candidates = add_template_conv_candidate (candidates,
+ fn,
+ obj,
+ args,
+ totype);
+ }
+ else
+ candidates = add_conv_candidate (candidates, fn, obj, args);
- result = build_overload_call (name, friend_parms, 0, cp);
- /* If it turns out to be the one we were actually looking for
- (it was probably a friend function), the return the
- good result. */
- if (TREE_CODE (result) == CALL_EXPR)
- return result;
+ if (candidates)
+ candidates->basetype_path = TREE_PURPOSE (convs);
+ }
+ }
- while ((cp->h.code & EVIL_CODE) == 0)
- {
- /* non-standard uses: set the field to 0 to indicate
- we are using a non-member function. */
- cp->u.field = 0;
- if (cp->harshness[len].distance == 0
- && cp->h.code < best)
- best = cp->h.code;
- cp += 1;
- }
- }
- }
+ if (! any_viable (candidates))
+ {
+ cp_error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args);
+ print_z_candidates (candidates);
+ return error_mark_node;
+ }
- while (baselink)
- {
- /* We have a hit (of sorts). If the parameter list is
- "error_mark_node", or some variant thereof, it won't
- match any methods. Since we have verified that the is
- some method vaguely matching this one (in name at least),
- silently return.
-
- Don't stop for friends, however. */
- basetype_path = TREE_PURPOSE (baselink);
+ candidates = splice_viable (candidates);
+ cand = tourney (candidates);
- function = TREE_VALUE (baselink);
- if (TREE_CODE (basetype_path) == TREE_LIST)
- basetype_path = TREE_VALUE (basetype_path);
- basetype = BINFO_TYPE (basetype_path);
+ if (cand == 0)
+ {
+ cp_error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args);
+ print_z_candidates (candidates);
+ return error_mark_node;
+ }
-#if 0
- /* Cast the instance variable if necessary. */
- if (basetype != TYPE_MAIN_VARIANT
- (TREE_TYPE (TREE_TYPE (TREE_VALUE (parms)))))
- {
- if (basetype == save_basetype)
- TREE_VALUE (parms) = instance_ptr;
- else
- {
- tree type = build_pointer_type
- (build_type_variant (basetype, constp, volatilep));
- TREE_VALUE (parms) = convert_force (type, instance_ptr, 0);
- }
- }
+ if (DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR])
+ return build_over_call (cand, mem_args, LOOKUP_NORMAL);
- /* FIXME: this is the wrong place to get an error. Hopefully
- the access-control rewrite will make this change more cleanly. */
- if (TREE_VALUE (parms) == error_mark_node)
- return error_mark_node;
-#endif
+ obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj);
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
- function = DECL_CHAIN (function);
+ /* FIXME */
+ return build_function_call (obj, args);
+}
- for (; function; function = DECL_CHAIN (function))
- {
-#ifdef GATHER_STATISTICS
- n_inner_fields_searched++;
-#endif
- ever_seen++;
- if (pass > 0)
- found_fns = tree_cons (NULL_TREE, function, found_fns);
+static void
+op_error (code, code2, arg1, arg2, arg3, problem)
+ enum tree_code code, code2;
+ tree arg1, arg2, arg3;
+ char *problem;
+{
+ char * opname
+ = (code == MODIFY_EXPR ? assignop_tab [code2] : opname_tab [code]);
- /* Not looking for friends here. */
- if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE
- && ! DECL_STATIC_FUNCTION_P (function))
- continue;
+ switch (code)
+ {
+ case COND_EXPR:
+ cp_error ("%s for `%T ? %T : %T'", problem,
+ error_type (arg1), error_type (arg2), error_type (arg3));
+ break;
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ cp_error ("%s for `%T%s'", problem, error_type (arg1), opname);
+ break;
+ case ARRAY_REF:
+ cp_error ("%s for `%T[%T]'", problem,
+ error_type (arg1), error_type (arg2));
+ break;
+ default:
+ if (arg2)
+ cp_error ("%s for `%T %s %T'", problem,
+ error_type (arg1), opname, error_type (arg2));
+ else
+ cp_error ("%s for `%s%T'", problem, opname, error_type (arg1));
+ }
+}
+
+tree
+build_new_op (code, flags, arg1, arg2, arg3)
+ enum tree_code code;
+ int flags;
+ tree arg1, arg2, arg3;
+{
+ struct z_candidate *candidates = 0, *cand;
+ tree fns, mem_arglist = NULL_TREE, arglist, fnname;
+ enum tree_code code2 = NOP_EXPR;
+ tree templates = NULL_TREE;
+ tree conv;
+
+ if (arg1 == error_mark_node
+ || arg2 == error_mark_node
+ || arg3 == error_mark_node)
+ return error_mark_node;
+
+ /* This can happen if a template takes all non-type parameters, e.g.
+ undeclared_template<1, 5, 72>a; */
+ if (code == LT_EXPR && TREE_CODE (arg1) == TEMPLATE_DECL)
+ {
+ cp_error ("`%D' must be declared before use", arg1);
+ return error_mark_node;
+ }
+
+ if (code == MODIFY_EXPR)
+ {
+ code2 = TREE_CODE (arg3);
+ arg3 = NULL_TREE;
+ fnname = ansi_assopname[code2];
+ }
+ else
+ fnname = ansi_opname[code];
+
+ switch (code)
+ {
+ case NEW_EXPR:
+ case VEC_NEW_EXPR:
+ {
+ tree rval;
+
+ arglist = scratch_tree_cons (NULL_TREE, arg2, arg3);
+ if (flags & LOOKUP_GLOBAL)
+ return build_new_function_call
+ (lookup_function_nonclass (fnname, arglist), arglist);
+
+ /* FIXME */
+ rval = build_method_call
+ (build_indirect_ref (build1 (NOP_EXPR, arg1, error_mark_node),
+ "new"),
+ fnname, arglist, NULL_TREE, flags);
+ if (rval == error_mark_node)
+ /* User might declare fancy operator new, but invoke it
+ like standard one. */
+ return rval;
+
+ TREE_TYPE (rval) = arg1;
+ return rval;
+ }
+ case VEC_DELETE_EXPR:
+ case DELETE_EXPR:
+ {
+ tree rval;
+
+ if (flags & LOOKUP_GLOBAL)
+ {
+ arglist = build_scratch_list (NULL_TREE, arg1);
+ return build_new_function_call
+ (lookup_function_nonclass (fnname, arglist), arglist);
+ }
+
+ arglist = scratch_tree_cons (NULL_TREE, arg1, build_scratch_list (NULL_TREE, arg2));
+
+ arg1 = TREE_TYPE (arg1);
+
+ /* This handles the case where we're trying to delete
+ X (*a)[10];
+ a=new X[5][10];
+ delete[] a; */
+
+ if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
+ {
+ /* Strip off the pointer and the array. */
+ arg1 = TREE_TYPE (TREE_TYPE (arg1));
+
+ while (TREE_CODE (arg1) == ARRAY_TYPE)
+ arg1 = (TREE_TYPE (arg1));
+
+ arg1 = build_pointer_type (arg1);
+ }
+
+ /* FIXME */
+ rval = build_method_call
+ (build_indirect_ref (build1 (NOP_EXPR, arg1,
+ error_mark_node),
+ NULL_PTR),
+ fnname, arglist, NULL_TREE, flags);
#if 0
- if (pass == 0
- && DECL_ASSEMBLER_NAME (function) == method_name)
- goto found;
+ /* This can happen when operator delete is protected. */
+ my_friendly_assert (rval != error_mark_node, 250);
+ TREE_TYPE (rval) = void_type_node;
#endif
+ return rval;
+ }
- if (pass > 0)
- {
- tree these_parms = parms;
+ case CALL_EXPR:
+ return build_object_call (arg1, arg2);
-#ifdef GATHER_STATISTICS
- n_inner_fields_searched++;
-#endif
- cp->h_len = len;
- cp->harshness = (struct harshness_code *)
- alloca ((len + 1) * sizeof (struct harshness_code));
-
- if (DECL_STATIC_FUNCTION_P (function))
- these_parms = TREE_CHAIN (these_parms);
- compute_conversion_costs (function, these_parms, cp, len);
-
- if ((cp->h.code & EVIL_CODE) == 0)
- {
- cp->u.field = function;
- cp->function = function;
- cp->basetypes = basetype_path;
-
- /* Don't allow non-converting constructors to convert. */
- if (flags & LOOKUP_ONLYCONVERTING
- && DECL_LANG_SPECIFIC (function)
- && DECL_NONCONVERTING_P (function))
- continue;
-
- /* No "two-level" conversions. */
- if (flags & LOOKUP_NO_CONVERSION
- && (cp->h.code & USER_CODE))
- continue;
-
- cp++;
- }
- }
- }
- /* Now we have run through one link's member functions.
- arrange to head-insert this link's links. */
- baselink = next_baselink (baselink);
- b_or_d += 1;
- /* Don't grab functions from base classes. lookup_fnfield will
- do the work to get us down into the right place. */
- baselink = NULL_TREE;
- }
- if (pass == 0)
- {
- tree igv = lookup_name_nonclass (name);
+ default:
+ break;
+ }
- /* No exact match could be found. Now try to find match
- using default conversions. */
- if ((flags & LOOKUP_GLOBAL) && igv)
- {
- if (TREE_CODE (igv) == FUNCTION_DECL)
- ever_seen += 1;
- else if (TREE_CODE (igv) == TREE_LIST)
- ever_seen += count_functions (igv);
- }
+ /* The comma operator can have void args. */
+ if (TREE_CODE (arg1) == OFFSET_REF)
+ arg1 = resolve_offset_ref (arg1);
+ if (arg2 && TREE_CODE (arg2) == OFFSET_REF)
+ arg2 = resolve_offset_ref (arg2);
+ if (arg3 && TREE_CODE (arg3) == OFFSET_REF)
+ arg3 = resolve_offset_ref (arg3);
- if (ever_seen == 0)
- {
- if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
- == LOOKUP_SPECULATIVELY)
- return NULL_TREE;
-
- TREE_CHAIN (last) = void_list_node;
- if (flags & LOOKUP_GLOBAL)
- cp_error ("no global or member function `%D(%A)' defined",
- name, parmtypes);
- else
- cp_error ("no member function `%T::%D(%A)' defined",
- save_basetype, name, TREE_CHAIN (parmtypes));
- return error_mark_node;
- }
- continue;
+ if (code == COND_EXPR)
+ {
+ if (arg2 == NULL_TREE
+ || TREE_CODE (TREE_TYPE (arg2)) == VOID_TYPE
+ || TREE_CODE (TREE_TYPE (arg3)) == VOID_TYPE
+ || (! IS_OVERLOAD_TYPE (TREE_TYPE (arg2))
+ && ! IS_OVERLOAD_TYPE (TREE_TYPE (arg3))))
+ goto builtin;
+ }
+ else if (! IS_OVERLOAD_TYPE (TREE_TYPE (arg1))
+ && (! arg2 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg2))))
+ goto builtin;
+
+ if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
+ arg2 = integer_zero_node;
+
+ if (arg2 && arg3)
+ arglist = scratch_tree_cons (NULL_TREE, arg1, scratch_tree_cons
+ (NULL_TREE, arg2, build_scratch_list (NULL_TREE, arg3)));
+ else if (arg2)
+ arglist = scratch_tree_cons (NULL_TREE, arg1, build_scratch_list (NULL_TREE, arg2));
+ else
+ arglist = build_scratch_list (NULL_TREE, arg1);
+
+ fns = lookup_function_nonclass (fnname, arglist);
+
+ if (fns && TREE_CODE (fns) == TREE_LIST)
+ fns = TREE_VALUE (fns);
+ for (; fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ {
+ templates = scratch_tree_cons (NULL_TREE, fn, templates);
+ candidates
+ = add_template_candidate (candidates, fn, NULL_TREE,
+ arglist, TREE_TYPE (fnname),
+ flags, DEDUCE_CALL);
}
+ else
+ candidates = add_function_candidate (candidates, fn, arglist, flags);
+ }
+
+ if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
+ {
+ fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 1);
+ if (fns == error_mark_node)
+ return fns;
+ }
+ else
+ fns = NULL_TREE;
- if (cp - candidates != 0)
+ if (fns)
+ {
+ tree basetype = TREE_PURPOSE (fns);
+ mem_arglist = scratch_tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
+ for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
{
- /* Rank from worst to best. Then cp will point to best one.
- Private fields have their bits flipped. For unsigned
- numbers, this should make them look very large.
- If the best alternate has a (signed) negative value,
- then all we ever saw were private members. */
- if (cp - candidates > 1)
- {
- int n_candidates = cp - candidates;
- extern int warn_synth;
- TREE_VALUE (parms) = instance_ptr;
- cp = ideal_candidate (save_basetype, candidates,
- n_candidates, parms, len);
- if (cp == (struct candidate *)0)
- {
- if (flags & LOOKUP_COMPLAIN)
- {
- TREE_CHAIN (last) = void_list_node;
- cp_error ("call of overloaded %s `%D(%A)' is ambiguous",
- name_kind, name, TREE_CHAIN (parmtypes));
- print_n_candidates (candidates, n_candidates);
- }
- return error_mark_node;
- }
- if (cp->h.code & EVIL_CODE)
- return error_mark_node;
- if (warn_synth
- && DECL_NAME (cp->function) == ansi_opname[MODIFY_EXPR]
- && DECL_ARTIFICIAL (cp->function)
- && n_candidates == 2)
- {
- cp_warning ("using synthesized `%#D' for copy assignment",
- cp->function);
- cp_warning_at (" where cfront would use `%#D'",
- candidates->function);
- }
- }
- else if (cp[-1].h.code & EVIL_CODE)
- {
- if (flags & LOOKUP_COMPLAIN)
- cp_error ("ambiguous type conversion requested for %s `%D'",
- name_kind, name);
- return error_mark_node;
- }
+ tree fn = OVL_CURRENT (fns);
+ tree this_arglist;
+
+ if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+ this_arglist = mem_arglist;
else
- cp--;
+ this_arglist = arglist;
- /* The global function was the best, so use it. */
- if (cp->u.field == 0)
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
{
- /* We must convert the instance pointer into a reference type.
- Global overloaded functions can only either take
- aggregate objects (which come for free from references)
- or reference data types anyway. */
- TREE_VALUE (parms) = copy_node (instance_ptr);
- TREE_TYPE (TREE_VALUE (parms)) = build_reference_type (TREE_TYPE (TREE_TYPE (instance_ptr)));
- return build_function_call (cp->function, parms);
+ /* A member template. */
+ templates = scratch_tree_cons (NULL_TREE, fn, templates);
+ candidates
+ = add_template_candidate (candidates, fn, NULL_TREE,
+ this_arglist, TREE_TYPE (fnname),
+ flags, DEDUCE_CALL);
}
+ else
+ candidates = add_function_candidate
+ (candidates, fn, this_arglist, flags);
- function = cp->function;
- basetype_path = cp->basetypes;
- if (! DECL_STATIC_FUNCTION_P (function))
- TREE_VALUE (parms) = cp->arg;
- goto found_and_maybe_warn;
+ if (candidates)
+ candidates->basetype_path = basetype;
}
+ }
- if (flags & (LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY))
- {
- if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
- == LOOKUP_SPECULATIVELY)
- return NULL_TREE;
+ {
+ tree args[3];
- if (DECL_STATIC_FUNCTION_P (cp->function))
- parms = TREE_CHAIN (parms);
- if (ever_seen)
- {
- if (flags & LOOKUP_SPECULATIVELY)
- return NULL_TREE;
- if (static_call_context
- && TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE)
- cp_error ("object missing in call to `%D'", cp->function);
- else if (ever_seen > 1)
- {
- TREE_CHAIN (last) = void_list_node;
- 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);
- }
- else
- report_type_mismatch (cp, parms, name_kind);
- return error_mark_node;
- }
+ /* Rearrange the arguments for ?: so that add_builtin_candidate only has
+ to know about two args; a builtin candidate will always have a first
+ parameter of type bool. We'll handle that in
+ build_builtin_candidate. */
+ if (code == COND_EXPR)
+ {
+ args[0] = arg2;
+ args[1] = arg3;
+ args[2] = arg1;
+ }
+ else
+ {
+ args[0] = arg1;
+ args[1] = arg2;
+ args[2] = NULL_TREE;
+ }
- if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
- == LOOKUP_COMPLAIN)
- {
- cp_error ("%T has no method named %D", save_basetype, name);
- return error_mark_node;
- }
- return NULL_TREE;
- }
- continue;
+ candidates = add_builtin_candidates
+ (candidates, code, code2, fnname, args, flags);
+ }
- found_and_maybe_warn:
- if ((cp->harshness[0].code & CONST_CODE)
- /* 12.1p2: Constructors can be called for const objects. */
- && ! DECL_CONSTRUCTOR_P (cp->function))
+ if (! any_viable (candidates))
+ {
+ switch (code)
{
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ /* Look for an `operator++ (int)'. If they didn't have
+ one, then we fall back to the old way of doing things. */
if (flags & LOOKUP_COMPLAIN)
- {
- cp_error_at ("non-const member function `%D'", cp->function);
- error ("called for const object at this point in file");
- }
- /* Not good enough for a match. */
+ cp_pedwarn ("no `%D (int)' declared for postfix `%s', trying prefix operator instead",
+ fnname, opname_tab [code]);
+ if (code == POSTINCREMENT_EXPR)
+ code = PREINCREMENT_EXPR;
else
- return error_mark_node;
- }
- goto found;
- }
- /* Silently return error_mark_node. */
- return error_mark_node;
-
- found:
- if (flags & LOOKUP_PROTECT)
- access = compute_access (basetype_path, function);
+ code = PREDECREMENT_EXPR;
+ return build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE);
+
+ /* The caller will deal with these. */
+ case ADDR_EXPR:
+ case COMPOUND_EXPR:
+ case COMPONENT_REF:
+ return NULL_TREE;
- if (access == access_private)
- {
+ default:
+ break;
+ }
if (flags & LOOKUP_COMPLAIN)
{
- cp_error_at ("%s `%+#D' is %s", name_kind, function,
- TREE_PRIVATE (function) ? "private"
- : "from private base class");
- error ("within this context");
+ op_error (code, code2, arg1, arg2, arg3, "no match");
+ print_z_candidates (candidates);
}
return error_mark_node;
}
- else if (access == access_protected)
+ candidates = splice_viable (candidates);
+ cand = tourney (candidates);
+
+ if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
{
- cp_error_at ("%s `%+#D' %s", name_kind, function,
- TREE_PROTECTED (function) ? "is protected"
- : "has protected accessibility");
- error ("within this context");
+ op_error (code, code2, arg1, arg2, arg3, "ambiguous overload");
+ print_z_candidates (candidates);
}
return error_mark_node;
}
- /* From here on down, BASETYPE is the type that INSTANCE_PTR's
- type (if it exists) is a pointer to. */
+ if (TREE_CODE (cand->fn) == FUNCTION_DECL)
+ {
+ extern int warn_synth;
+ if (warn_synth
+ && fnname == ansi_opname[MODIFY_EXPR]
+ && DECL_ARTIFICIAL (cand->fn)
+ && candidates->next
+ && ! candidates->next->next)
+ {
+ cp_warning ("using synthesized `%#D' for copy assignment",
+ cand->fn);
+ cp_warning_at (" where cfront would use `%#D'",
+ cand == candidates
+ ? candidates->next->fn
+ : candidates->fn);
+ }
- if (DECL_ABSTRACT_VIRTUAL_P (function)
- && instance == C_C_D
- && DECL_CONSTRUCTOR_P (current_function_decl)
- && ! (flags & LOOKUP_NONVIRTUAL)
- && value_member (function, get_abstract_virtuals (basetype)))
- cp_error ("abstract virtual `%#D' called from constructor", function);
+ /* Pedantically, normal function declarations are never considered
+ to refer to template instantiations, so we only do this with
+ -fguiding-decls. */
+ if (flag_guiding_decls && templates && ! cand->template
+ && ! DECL_INITIAL (cand->fn)
+ && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE)
+ add_maybe_template (cand->fn, templates);
+
+ return build_over_call
+ (cand,
+ TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
+ ? mem_arglist : arglist,
+ LOOKUP_NORMAL);
+ }
- if (IS_SIGNATURE (basetype) && static_call_context)
+ /* Check for comparison of different enum types. */
+ switch (code)
{
- cp_error ("cannot call signature member function `%T::%D' without signature pointer/reference",
- basetype, name);
- return error_mark_node;
+ case GT_EXPR:
+ case LT_EXPR:
+ case GE_EXPR:
+ case LE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ if (flag_int_enum_equivalence == 0
+ && TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE
+ && TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (arg1))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (arg2))))
+ {
+ cp_warning ("comparison between `%#T' and `%#T'",
+ TREE_TYPE (arg1), TREE_TYPE (arg2));
}
- else if (IS_SIGNATURE (basetype))
- return build_signature_method_call (basetype, instance, function, parms);
+ break;
+ default:
+ break;
+ }
- function = DECL_MAIN_VARIANT (function);
- /* Declare external function if necessary. */
- assemble_external (function);
+ /* We need to strip any leading REF_BIND so that bitfields don't cause
+ errors. This should not remove any important conversions, because
+ builtins don't apply to class objects directly. */
+ conv = TREE_VEC_ELT (cand->convs, 0);
+ if (TREE_CODE (conv) == REF_BIND)
+ conv = TREE_OPERAND (conv, 0);
+ arg1 = convert_like (conv, arg1);
+ if (arg2)
+ arg2 = convert_like (TREE_VEC_ELT (cand->convs, 1), arg2);
+ if (arg3)
+ arg3 = convert_like (TREE_VEC_ELT (cand->convs, 2), arg3);
+
+builtin:
+ switch (code)
+ {
+ case MODIFY_EXPR:
+ return build_modify_expr (arg1, code2, arg2);
+
+ case INDIRECT_REF:
+ return build_indirect_ref (arg1, "unary *");
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case GT_EXPR:
+ case LT_EXPR:
+ case GE_EXPR:
+ case LE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ case MAX_EXPR:
+ case MIN_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case TRUNC_MOD_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ return build_binary_op_nodefault (code, arg1, arg2, code);
+
+ case CONVERT_EXPR:
+ case NEGATE_EXPR:
+ case BIT_NOT_EXPR:
+ case TRUTH_NOT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ return build_unary_op (code, arg1, candidates != 0);
+
+ case ARRAY_REF:
+ return build_array_ref (arg1, arg2);
+
+ case COND_EXPR:
+ return build_conditional_expr (arg1, arg2, arg3);
+
+ case MEMBER_REF:
+ return build_m_component_ref
+ (build_indirect_ref (arg1, NULL_PTR), arg2);
+
+ /* The caller will deal with these. */
+ case ADDR_EXPR:
+ case COMPONENT_REF:
+ case COMPOUND_EXPR:
+ return NULL_TREE;
-#if 1
- /* Is it a synthesized method that needs to be synthesized? */
- if (DECL_ARTIFICIAL (function) && ! flag_no_inline
- && ! DECL_INITIAL (function)
- /* Kludge: don't synthesize for default args. */
- && current_function_decl)
- synthesize_method (function);
-#endif
+ default:
+ my_friendly_abort (367);
+ return NULL_TREE;
+ }
+}
- if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function)
- && ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function))
- cp_warning ("inline function `%#D' called before definition", function);
+/* Build up a call to operator new. This has to be handled differently
+ from other operators in the way lookup is handled; first members are
+ considered, then globals. CODE is either NEW_EXPR or VEC_NEW_EXPR.
+ TYPE is the type to be created. ARGS are any new-placement args.
+ FLAGS are the usual overloading flags. */
- fntype = TREE_TYPE (function);
- if (TREE_CODE (fntype) == POINTER_TYPE)
- fntype = TREE_TYPE (fntype);
- basetype = DECL_CLASS_CONTEXT (function);
+tree
+build_op_new_call (code, type, args, flags)
+ enum tree_code code;
+ tree type, args;
+ int flags;
+{
+ tree fnname = ansi_opname[code];
- /* If we are referencing a virtual function from an object
- of effectively static type, then there is no need
- to go through the virtual function table. */
- if (need_vtbl == maybe_needed)
+ if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)
+ && (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR))))
{
- int fixed_type = resolves_to_fixed_type_p (instance, 0);
+ tree dummy = build1 (NOP_EXPR, build_pointer_type (type),
+ error_mark_node);
+ dummy = build_indirect_ref (dummy, "new");
+ return build_method_call (dummy, fnname, args, NULL_TREE, flags);
+ }
+ else
+ return build_new_function_call
+ (lookup_function_nonclass (fnname, args), args);
+}
- if (all_virtual == 1
- && DECL_VINDEX (function)
- && may_be_remote (basetype))
- need_vtbl = needed;
- else if (DECL_VINDEX (function))
- need_vtbl = fixed_type ? unneeded : needed;
- else
- need_vtbl = not_needed;
+/* Build a call to operator delete. This has to be handled very specially,
+ because the restrictions on what signatures match are different from all
+ other call instances. For a normal delete, only a delete taking (void *)
+ or (void *, size_t) is accepted. For a placement delete, only an exact
+ match with the placement new is accepted.
+
+ CODE is either DELETE_EXPR or VEC_DELETE_EXPR.
+ ADDR is the pointer to be deleted. For placement delete, it is also
+ used to determine what the corresponding new looked like.
+ SIZE is the size of the memory block to be deleted.
+ FLAGS are the usual overloading flags.
+ PLACEMENT is the corresponding placement new call, or 0. */
+
+tree
+build_op_delete_call (code, addr, size, flags, placement)
+ enum tree_code code;
+ tree addr, size, placement;
+ int flags;
+{
+ tree fn, fns, fnname, fntype, argtypes, args, type;
+
+ if (addr == error_mark_node)
+ return error_mark_node;
+
+ type = TREE_TYPE (TREE_TYPE (addr));
+ fnname = ansi_opname[code];
+
+ if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL))
+ /* In [class.free]
+
+ If the result of the lookup is ambiguous or inaccessible, or if
+ the lookup selects a placement deallocation function, the
+ program is ill-formed.
+
+ Therefore, we ask lookup_fnfields to complain ambout ambiguity. */
+ {
+ fns = lookup_fnfields (TYPE_BINFO (type), fnname, 1);
+ if (fns == error_mark_node)
+ return error_mark_node;
}
+ else
+ fns = NULL_TREE;
+
+ if (fns == NULL_TREE)
+ fns = lookup_name_nonclass (fnname);
+
+ if (placement)
+ {
+ /* placement is a CALL_EXPR around an ADDR_EXPR around a function. */
+
+ /* Extract the function. */
+ argtypes = TREE_OPERAND (TREE_OPERAND (placement, 0), 0);
+ /* Then the second parm type. */
+ argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (argtypes)));
- if (TREE_CODE (fntype) == METHOD_TYPE && static_call_context
- && !DECL_CONSTRUCTOR_P (function))
+ /* Also the second argument. */
+ args = TREE_CHAIN (TREE_OPERAND (placement, 1));
+ }
+ else
{
- /* Let's be nice to the user for now, and give reasonable
- default behavior. */
- instance_ptr = current_class_decl;
- if (instance_ptr)
+ /* First try it without the size argument. */
+ argtypes = void_list_node;
+ args = NULL_TREE;
+ }
+
+ argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
+ fntype = build_function_type (void_type_node, argtypes);
+
+ /* Strip const and volatile from addr. */
+ if (type != TYPE_MAIN_VARIANT (type))
+ addr = cp_convert (build_pointer_type (TYPE_MAIN_VARIANT (type)), addr);
+
+ /* instantiate_type will always return a plain function; pretend it's
+ overloaded. */
+ if (TREE_CODE (fns) == FUNCTION_DECL)
+ fns = scratch_ovl_cons (fns, NULL_TREE);
+
+ fn = instantiate_type (fntype, fns, 0);
+
+ if (fn != error_mark_node)
+ {
+ if (TREE_CODE (fns) == TREE_LIST)
+ /* Member functions. */
+ enforce_access (TREE_PURPOSE (fns), fn);
+ return build_function_call (fn, expr_tree_cons (NULL_TREE, addr, args));
+ }
+
+ /* If we are doing placement delete we do nothing if we don't find a
+ matching op delete. */
+ if (placement)
+ return NULL_TREE;
+
+ /* Normal delete; now try to find a match including the size argument. */
+ argtypes = tree_cons (NULL_TREE, ptr_type_node,
+ tree_cons (NULL_TREE, sizetype, void_list_node));
+ fntype = build_function_type (void_type_node, argtypes);
+
+ fn = instantiate_type (fntype, fns, 0);
+
+ if (fn != error_mark_node)
+ {
+ if (TREE_CODE (fns) == TREE_LIST)
+ /* Member functions. */
+ enforce_access (TREE_PURPOSE (fns), fn);
+ return build_function_call
+ (fn, expr_tree_cons (NULL_TREE, addr,
+ build_expr_list (NULL_TREE, size)));
+ }
+
+ /* finish_function passes LOOKUP_SPECULATIVELY if we're in a
+ destructor, in which case the error should be deferred
+ until someone actually tries to delete one of these. */
+ if (flags & LOOKUP_SPECULATIVELY)
+ return NULL_TREE;
+
+ cp_error ("no suitable operator delete for `%T'", type);
+ return error_mark_node;
+}
+
+/* If the current scope isn't allowed to access DECL along
+ BASETYPE_PATH, give an error. */
+
+void
+enforce_access (basetype_path, decl)
+ tree basetype_path, decl;
+{
+ tree access = compute_access (basetype_path, decl);
+
+ if (access == access_private_node)
+ {
+ cp_error_at ("`%+#D' is %s", decl,
+ TREE_PRIVATE (decl) ? "private"
+ : "from private base class");
+ error ("within this context");
+ }
+ else if (access == access_protected_node)
+ {
+ cp_error_at ("`%+#D' %s", decl,
+ TREE_PROTECTED (decl) ? "is protected"
+ : "has protected accessibility");
+ error ("within this context");
+ }
+}
+
+/* Perform the conversions in CONVS on the expression EXPR. */
+
+static tree
+convert_like (convs, expr)
+ tree convs, expr;
+{
+ if (ICS_BAD_FLAG (convs)
+ && TREE_CODE (convs) != USER_CONV
+ && TREE_CODE (convs) != AMBIG_CONV)
+ {
+ tree t = convs;
+ for (; t; t = TREE_OPERAND (t, 0))
{
- if (basetype != current_class_type)
+ if (TREE_CODE (t) == USER_CONV)
{
- tree binfo = get_binfo (basetype, current_class_type, 1);
- if (binfo == NULL_TREE)
- {
- error_not_base_type (function, current_class_type);
- return error_mark_node;
- }
- else if (basetype == error_mark_node)
- return error_mark_node;
+ expr = convert_like (t, expr);
+ break;
}
+ else if (TREE_CODE (t) == AMBIG_CONV)
+ return convert_like (t, expr);
+ else if (TREE_CODE (t) == IDENTITY_CONV)
+ break;
}
- /* Only allow a static member function to call another static member
- function. */
- else if (DECL_LANG_SPECIFIC (function)
- && !DECL_STATIC_FUNCTION_P (function))
- {
- cp_error ("cannot call member function `%D' without object",
- function);
- return error_mark_node;
- }
+ return convert_for_initialization
+ (NULL_TREE, TREE_TYPE (convs), expr, LOOKUP_NORMAL,
+ "conversion", NULL_TREE, 0);
}
- value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
+ switch (TREE_CODE (convs))
+ {
+ case USER_CONV:
+ {
+ struct z_candidate *cand
+ = WRAPPER_PTR (TREE_OPERAND (convs, 1));
+ tree fn = cand->fn;
+ tree args;
+
+ if (DECL_CONSTRUCTOR_P (fn))
+ {
+ tree t = build_int_2 (0, 0);
+ TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn));
+
+ args = build_scratch_list (NULL_TREE, expr);
+ if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+ args = scratch_tree_cons (NULL_TREE, integer_one_node, args);
+ args = scratch_tree_cons (NULL_TREE, t, args);
+ }
+ else
+ args = build_this (expr);
+ expr = build_over_call (cand, args, LOOKUP_NORMAL);
+
+ /* If this is a constructor or a function returning an aggr type,
+ we need to build up a TARGET_EXPR. */
+ if (DECL_CONSTRUCTOR_P (fn))
+ expr = build_cplus_new (TREE_TYPE (convs), expr);
+
+ return expr;
+ }
+ case IDENTITY_CONV:
+ if (type_unknown_p (expr))
+ expr = instantiate_type (TREE_TYPE (convs), expr, 1);
+ if (TREE_READONLY_DECL_P (expr))
+ expr = decl_constant_value (expr);
+ return expr;
+ case AMBIG_CONV:
+ /* Call build_user_type_conversion again for the error. */
+ return build_user_type_conversion
+ (TREE_TYPE (convs), TREE_OPERAND (convs, 0), LOOKUP_NORMAL);
+
+ default:
+ break;
+ };
+
+ expr = convert_like (TREE_OPERAND (convs, 0), expr);
+ if (expr == error_mark_node)
+ return error_mark_node;
- if (TYPE_SIZE (value_type) == 0)
+ switch (TREE_CODE (convs))
{
- if (flags & LOOKUP_COMPLAIN)
- incomplete_type_error (0, value_type);
- return error_mark_node;
+ case RVALUE_CONV:
+ if (! IS_AGGR_TYPE (TREE_TYPE (convs)))
+ return expr;
+ /* else fall through */
+ case BASE_CONV:
+ {
+ tree cvt_expr = build_user_type_conversion
+ (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
+ if (!cvt_expr)
+ {
+ /* This can occur if, for example, the EXPR has incomplete
+ type. We can't check for that before attempting the
+ conversion because the type might be an incomplete
+ array type, which is OK if some constructor for the
+ destination type takes a pointer argument. */
+ if (TYPE_SIZE (TREE_TYPE (expr)) == 0)
+ {
+ if (comptypes (TREE_TYPE (expr), TREE_TYPE (convs), 1))
+ incomplete_type_error (expr, TREE_TYPE (expr));
+ else
+ cp_error ("could not convert `%E' (with incomplete type `%T') to `%T'",
+ expr, TREE_TYPE (expr), TREE_TYPE (convs));
+ }
+ else
+ cp_error ("could not convert `%E' to `%T'",
+ expr, TREE_TYPE (convs));
+ return error_mark_node;
+ }
+ return cvt_expr;
+ }
+
+ case REF_BIND:
+ return convert_to_reference
+ (TREE_TYPE (convs), expr,
+ CONV_IMPLICIT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION,
+ error_mark_node);
+ case LVALUE_CONV:
+ return decay_conversion (expr);
+
+ default:
+ break;
+ }
+ return ocp_convert (TREE_TYPE (convs), expr, CONV_IMPLICIT,
+ LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
+}
+
+/* ARG is being passed to a varargs function. Perform any conversions
+ required. Return the converted value. */
+
+tree
+convert_arg_to_ellipsis (arg)
+ tree arg;
+{
+ if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
+ && (TYPE_PRECISION (TREE_TYPE (arg))
+ < TYPE_PRECISION (double_type_node)))
+ /* Convert `float' to `double'. */
+ arg = cp_convert (double_type_node, arg);
+ else if (IS_AGGR_TYPE (TREE_TYPE (arg))
+ && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (arg)))
+ cp_warning ("cannot pass objects of type `%T' through `...'",
+ TREE_TYPE (arg));
+ else
+ /* Convert `short' and `char' to full-size `int'. */
+ arg = default_conversion (arg);
+
+ return arg;
+}
+
+/* ARG is a default argument expression being passed to a parameter of
+ the indicated TYPE. Do any required conversions. Return the
+ converted value. */
+
+tree
+convert_default_arg (type, arg)
+ tree type, arg;
+{
+ arg = break_out_target_exprs (arg);
+
+ if (TREE_CODE (arg) == CONSTRUCTOR)
+ {
+ arg = digest_init (type, arg, 0);
+ arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
+ "default argument", 0, 0);
+ }
+ else
+ {
+ /* This could get clobbered by the following call. */
+ if (TREE_HAS_CONSTRUCTOR (arg))
+ arg = copy_node (arg);
+
+ arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
+ "default argument", 0, 0);
+#ifdef PROMOTE_PROTOTYPES
+ if ((TREE_CODE (type) == INTEGER_TYPE
+ || TREE_CODE (type) == ENUMERAL_TYPE)
+ && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
+ arg = default_conversion (arg);
+#endif
}
- if (DECL_STATIC_FUNCTION_P (function))
- parms = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
- TREE_CHAIN (parms), function, LOOKUP_NORMAL);
- else if (need_vtbl == unneeded)
+ return arg;
+}
+
+static tree
+build_over_call (cand, args, flags)
+ struct z_candidate *cand;
+ tree args;
+ int flags;
+{
+ tree fn = cand->fn;
+ tree convs = cand->convs;
+ tree converted_args = NULL_TREE;
+ tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ tree conv, arg, val;
+ int i = 0;
+ int is_method = 0;
+
+ /* Give any warnings we noticed during overload resolution. */
+ if (cand->warnings)
+ for (val = cand->warnings; val; val = TREE_CHAIN (val))
+ joust (cand, WRAPPER_PTR (TREE_VALUE (val)), 1);
+
+ if (DECL_FUNCTION_MEMBER_P (fn))
+ enforce_access (cand->basetype_path, fn);
+
+ if (args && TREE_CODE (args) != TREE_LIST)
+ args = build_scratch_list (NULL_TREE, args);
+ arg = args;
+
+ /* The implicit parameters to a constructor are not considered by overload
+ resolution, and must be of the proper type. */
+ if (DECL_CONSTRUCTOR_P (fn))
{
- int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL;
- basetype = TREE_TYPE (instance);
- if (TYPE_METHOD_BASETYPE (TREE_TYPE (function)) != TYPE_MAIN_VARIANT (basetype)
- && TYPE_USES_COMPLEX_INHERITANCE (basetype))
+ converted_args = expr_tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args);
+ arg = TREE_CHAIN (arg);
+ parm = TREE_CHAIN (parm);
+ if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
{
- basetype = DECL_CLASS_CONTEXT (function);
- instance_ptr = convert_pointer_to (basetype, instance_ptr);
- instance = build_indirect_ref (instance_ptr, NULL_PTR);
+ converted_args = expr_tree_cons
+ (NULL_TREE, TREE_VALUE (arg), converted_args);
+ arg = TREE_CHAIN (arg);
+ parm = TREE_CHAIN (parm);
}
- parms = tree_cons (NULL_TREE, instance_ptr,
- convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, sub_flags));
+ }
+ /* Bypass access control for 'this' parameter. */
+ else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+ {
+ tree parmtype = TREE_VALUE (parm);
+ tree argtype = TREE_TYPE (TREE_VALUE (arg));
+ if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
+ {
+ int dv = (TYPE_VOLATILE (TREE_TYPE (parmtype))
+ < TYPE_VOLATILE (TREE_TYPE (argtype)));
+ int dc = (TYPE_READONLY (TREE_TYPE (parmtype))
+ < TYPE_READONLY (TREE_TYPE (argtype)));
+ char *p = (dv && dc ? "const and volatile"
+ : dc ? "const" : dv ? "volatile" : "");
+
+ cp_pedwarn ("passing `%T' as `this' argument of `%#D' discards %s",
+ TREE_TYPE (argtype), fn, p);
+ }
+ converted_args = expr_tree_cons
+ (NULL_TREE, convert_force (TREE_VALUE (parm), TREE_VALUE (arg), CONV_C_CAST),
+ converted_args);
+ parm = TREE_CHAIN (parm);
+ arg = TREE_CHAIN (arg);
+ ++i;
+ is_method = 1;
}
- else
+
+ for (; arg && parm;
+ parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i)
{
- if ((flags & LOOKUP_NONVIRTUAL) == 0)
- basetype = DECL_CONTEXT (function);
+ tree type = TREE_VALUE (parm);
- /* First parm could be integer_zerop with casts like
- ((Object*)0)->Object::IsA() */
- if (!integer_zerop (TREE_VALUE (parms)))
+ conv = TREE_VEC_ELT (convs, i);
+ if (ICS_BAD_FLAG (conv))
{
- /* Since we can't have inheritance with a union, doing get_binfo
- on it won't work. We do all the convert_pointer_to_real
- stuff to handle MI correctly...for unions, that's not
- an issue, so we must short-circuit that extra work here. */
- tree tmp = TREE_TYPE (TREE_TYPE (TREE_VALUE (parms)));
- if (tmp != NULL_TREE && TREE_CODE (tmp) == UNION_TYPE)
- instance_ptr = TREE_VALUE (parms);
- else
- {
- tree binfo = get_binfo (basetype,
- TREE_TYPE (TREE_TYPE (TREE_VALUE (parms))),
- 0);
- instance_ptr = convert_pointer_to_real (binfo, TREE_VALUE (parms));
- }
- instance_ptr
- = convert_pointer_to (build_type_variant (basetype,
- constp, volatilep),
- instance_ptr);
+ tree t = conv;
+ val = TREE_VALUE (arg);
- if (TREE_CODE (instance_ptr) == COND_EXPR)
+ for (; t; t = TREE_OPERAND (t, 0))
{
- instance_ptr = save_expr (instance_ptr);
- instance = build_indirect_ref (instance_ptr, NULL_PTR);
+ if (TREE_CODE (t) == USER_CONV
+ || TREE_CODE (t) == AMBIG_CONV)
+ {
+ val = convert_like (t, val);
+ break;
+ }
+ else if (TREE_CODE (t) == IDENTITY_CONV)
+ break;
}
- else if (TREE_CODE (instance_ptr) == NOP_EXPR
- && TREE_CODE (TREE_OPERAND (instance_ptr, 0)) == ADDR_EXPR
- && TREE_OPERAND (TREE_OPERAND (instance_ptr, 0), 0) == instance)
- ;
- /* The call to `convert_pointer_to' may return error_mark_node. */
- else if (TREE_CODE (instance_ptr) == ERROR_MARK)
- return instance_ptr;
- else if (instance == NULL_TREE
- || TREE_CODE (instance) != INDIRECT_REF
- || TREE_OPERAND (instance, 0) != instance_ptr)
- instance = build_indirect_ref (instance_ptr, NULL_PTR);
- }
- parms = tree_cons (NULL_TREE, instance_ptr,
- convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, LOOKUP_NORMAL));
+ val = convert_for_initialization
+ (NULL_TREE, type, val, LOOKUP_NORMAL,
+ "argument passing", fn, i - is_method);
+ }
+ else
+ val = convert_like (conv, TREE_VALUE (arg));
+
+#ifdef PROMOTE_PROTOTYPES
+ if ((TREE_CODE (type) == INTEGER_TYPE
+ || TREE_CODE (type) == ENUMERAL_TYPE)
+ && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
+ val = default_conversion (val);
+#endif
+ converted_args = expr_tree_cons (NULL_TREE, val, converted_args);
}
-#if 0
- /* Constructors do not overload method calls. */
- else if (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype)
- && name != TYPE_IDENTIFIER (basetype)
- && (TREE_CODE (function) != FUNCTION_DECL
- || strncmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)),
- OPERATOR_METHOD_FORMAT,
- OPERATOR_METHOD_LENGTH))
- && (may_be_remote (basetype) || instance != C_C_D))
+ /* Default arguments */
+ for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm))
{
- tree fn_as_int;
+ tree arg = TREE_PURPOSE (parm);
- parms = TREE_CHAIN (parms);
+ if (DECL_TEMPLATE_INFO (fn))
+ {
+ /* This came from a template. Instantiate the default arg here,
+ not in tsubst. In the case of something like:
- if (!all_virtual && TREE_CODE (function) == FUNCTION_DECL)
- fn_as_int = build_unary_op (ADDR_EXPR, function, 0);
- else
- fn_as_int = convert (TREE_TYPE (default_conversion (function)), DECL_VINDEX (function));
- if (all_virtual == 1)
- fn_as_int = convert (integer_type_node, fn_as_int);
+ template <class T>
+ struct S {
+ static T t();
+ void f(T = t());
+ };
+
+ we must be careful to do name lookup in the scope of
+ S<T>, rather than in the current class. */
+ if (DECL_CLASS_SCOPE_P (fn))
+ pushclass (DECL_REAL_CONTEXT (fn), 2);
+
+ arg = tsubst_expr (arg, DECL_TI_ARGS (fn), NULL_TREE);
+
+ if (DECL_CLASS_SCOPE_P (fn))
+ popclass (1);
+ }
+ converted_args = expr_tree_cons
+ (NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
+ converted_args);
+ }
+
+ /* Ellipsis */
+ for (; arg; arg = TREE_CHAIN (arg))
+ converted_args
+ = expr_tree_cons (NULL_TREE,
+ convert_arg_to_ellipsis (TREE_VALUE (arg)),
+ converted_args);
- result = build_opfncall (METHOD_CALL_EXPR, LOOKUP_NORMAL, instance, fn_as_int, parms);
+ converted_args = nreverse (converted_args);
- if (result == NULL_TREE)
+ /* Avoid actually calling copy constructors and copy assignment operators,
+ if possible. */
+ if (DECL_CONSTRUCTOR_P (fn)
+ && TREE_VEC_LENGTH (convs) == 1
+ && copy_args_p (fn))
+ {
+ tree targ;
+ arg = TREE_CHAIN (converted_args);
+ if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+ arg = TREE_CHAIN (arg);
+ arg = TREE_VALUE (arg);
+
+ /* Pull out the real argument, disregarding const-correctness. */
+ targ = arg;
+ while (TREE_CODE (targ) == NOP_EXPR
+ || TREE_CODE (targ) == NON_LVALUE_EXPR
+ || TREE_CODE (targ) == CONVERT_EXPR)
+ targ = TREE_OPERAND (targ, 0);
+ if (TREE_CODE (targ) == ADDR_EXPR)
{
- compiler_error ("could not overload `operator->()(...)'");
- return error_mark_node;
+ targ = TREE_OPERAND (targ, 0);
+ if (! comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg))),
+ TYPE_MAIN_VARIANT (TREE_TYPE (targ)), 1))
+ targ = NULL_TREE;
}
- else if (result == error_mark_node)
- return error_mark_node;
+ else
+ targ = NULL_TREE;
-#if 0
- /* Do this if we want the result of operator->() to inherit
- the type of the function it is subbing for. */
- TREE_TYPE (result) = value_type;
-#endif
+ if (targ)
+ arg = targ;
+ else
+ arg = build_indirect_ref (arg, 0);
+
+ /* [class.copy]: the copy constructor is implicitly defined even if
+ the implementation elided its use. */
+ if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn)))
+ mark_used (fn);
+
+ /* If we're creating a temp and we already have one, don't create a
+ new one. If we're not creating a temp but we get one, use
+ INIT_EXPR to collapse the temp into our target. Otherwise, if the
+ ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a
+ temp or an INIT_EXPR otherwise. */
+ if (integer_zerop (TREE_VALUE (args)))
+ {
+ if (! real_lvalue_p (arg))
+ return arg;
+ else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
+ {
+ val = build (VAR_DECL, DECL_CONTEXT (fn));
+ layout_decl (val, 0);
+ val = build (TARGET_EXPR, DECL_CONTEXT (fn), val, arg, 0, 0);
+ TREE_SIDE_EFFECTS (val) = 1;
+ return val;
+ }
+ }
+ else if (! real_lvalue_p (arg)
+ || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
+ {
+ tree to = stabilize_reference
+ (build_indirect_ref (TREE_VALUE (args), 0));
+
+ /* Don't copy the padding byte; it might not have been allocated
+ if to is a base subobject. */
+ if (is_empty_class (DECL_CLASS_CONTEXT (fn)))
+ return build_unary_op
+ (ADDR_EXPR, build (COMPOUND_EXPR, TREE_TYPE (to),
+ cp_convert (void_type_node, arg), to),
+ 0);
+
+ val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
+ TREE_SIDE_EFFECTS (val) = 1;
+ return build_unary_op (ADDR_EXPR, val, 0);
+ }
+ }
+ else if (DECL_NAME (fn) == ansi_opname[MODIFY_EXPR]
+ && copy_args_p (fn)
+ && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CLASS_CONTEXT (fn)))
+ {
+ tree to = stabilize_reference
+ (build_indirect_ref (TREE_VALUE (converted_args), 0));
- return result;
+ arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
+
+ /* Don't copy the padding byte; it might not have been allocated
+ if to is a base subobject. */
+ if (is_empty_class (DECL_CLASS_CONTEXT (fn)))
+ return build (COMPOUND_EXPR, TREE_TYPE (to),
+ cp_convert (void_type_node, arg), to);
+
+ val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
+ TREE_SIDE_EFFECTS (val) = 1;
+ return val;
}
-#endif
- if (parms == error_mark_node
- || (parms && TREE_CHAIN (parms) == error_mark_node))
- return error_mark_node;
+ mark_used (fn);
- if (need_vtbl == needed)
+ if (DECL_CLASS_SCOPE_P (fn) && IS_SIGNATURE (DECL_CONTEXT (fn)))
+ return build_signature_method_call (fn, converted_args);
+ else if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
{
- function = build_vfn_ref (&TREE_VALUE (parms), instance,
- DECL_VINDEX (function));
- TREE_TYPE (function) = build_pointer_type (fntype);
+ tree t, *p = &TREE_VALUE (converted_args);
+ tree binfo = get_binfo
+ (DECL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0);
+ *p = convert_pointer_to_real (binfo, *p);
+ if (TREE_SIDE_EFFECTS (*p))
+ *p = save_expr (*p);
+ t = build_pointer_type (TREE_TYPE (fn));
+ fn = build_vfn_ref (p, build_indirect_ref (*p, 0), DECL_VINDEX (fn));
+ TREE_TYPE (fn) = t;
}
+ else if (DECL_INLINE (fn))
+ fn = inline_conversion (fn);
+ else
+ fn = build_addr_func (fn);
- if (TREE_CODE (function) == FUNCTION_DECL)
- GNU_xref_call (current_function_decl,
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)));
+ /* Recognize certain built-in functions so we can make tree-codes
+ other than CALL_EXPR. We do this when it enables fold-const.c
+ to do something useful. */
- {
- int is_constructor;
-
- if (TREE_CODE (function) == FUNCTION_DECL)
- {
- is_constructor = DECL_CONSTRUCTOR_P (function);
- TREE_USED (function) = 1;
- function = default_conversion (function);
- }
- else
+ if (TREE_CODE (fn) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
+ && DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
+ switch (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 0)))
{
- is_constructor = 0;
- function = default_conversion (function);
+ case BUILT_IN_ABS:
+ case BUILT_IN_LABS:
+ case BUILT_IN_FABS:
+ if (converted_args == 0)
+ return integer_zero_node;
+ return build_unary_op (ABS_EXPR, TREE_VALUE (converted_args), 0);
+ default:
+ break;
}
- result = build_nt (CALL_EXPR, function, parms, NULL_TREE);
-
- TREE_TYPE (result) = value_type;
- TREE_SIDE_EFFECTS (result) = 1;
- TREE_HAS_CONSTRUCTOR (result) = is_constructor;
- result = convert_from_reference (result);
- return result;
- }
+ fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args);
+ if (TREE_TYPE (fn) == void_type_node)
+ return fn;
+ fn = require_complete_type (fn);
+ if (IS_AGGR_TYPE (TREE_TYPE (fn)))
+ fn = build_cplus_new (TREE_TYPE (fn), fn);
+ return convert_from_reference (fn);
}
-/* Similar to `build_method_call', but for overloaded non-member functions.
- The name of this function comes through NAME. The name depends
- on PARMS.
+static tree
+build_new_method_call (instance, name, args, basetype_path, flags)
+ tree instance, name, args, basetype_path;
+ int flags;
+{
+ struct z_candidate *candidates = 0, *cand;
+ tree explicit_targs = NULL_TREE;
+ tree basetype, mem_args = NULL_TREE, fns, instance_ptr;
+ tree pretty_name;
+ tree user_args = args;
+ tree templates = NULL_TREE;
+ int template_only = 0;
+
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ explicit_targs = TREE_OPERAND (name, 1);
+ name = TREE_OPERAND (name, 0);
+ if (TREE_CODE (name) == TEMPLATE_DECL)
+ name = DECL_NAME (name);
+ template_only = 1;
+ }
- Note that this function must handle simple `C' promotions,
- as well as variable numbers of arguments (...), and
- default arguments to boot.
+ /* If there is an extra argument for controlling virtual bases,
+ remove it for error reporting. */
+ if (flags & LOOKUP_HAS_IN_CHARGE)
+ user_args = TREE_CHAIN (args);
- If the overloading is successful, we return a tree node which
- contains the call to the function.
+ args = resolve_args (args);
- If overloading produces candidates which are probable, but not definite,
- we hold these candidates. If FINAL_CP is non-zero, then we are free
- to assume that final_cp points to enough storage for all candidates that
- this function might generate. The `harshness' array is preallocated for
- the first candidate, but not for subsequent ones.
+ if (args == error_mark_node)
+ return error_mark_node;
- Note that the DECL_RTL of FUNCTION must be made to agree with this
- function's new name. */
+ if (instance == NULL_TREE)
+ basetype = BINFO_TYPE (basetype_path);
+ else
+ {
+ if (TREE_CODE (instance) == OFFSET_REF)
+ instance = resolve_offset_ref (instance);
+ if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
+ instance = convert_from_reference (instance);
+ basetype = TREE_TYPE (instance);
-tree
-build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
- tree fnname, parms;
- int flags;
- struct candidate *final_cp;
- int buildxxx;
-{
- /* must check for overloading here */
- tree overload_name, functions, function, parm;
- tree parmtypes = NULL_TREE, last = NULL_TREE;
- register tree outer;
- int length;
- int parmlength = list_length (parms);
+ /* XXX this should be handled before we get here. */
+ if (! IS_AGGR_TYPE (basetype)
+ && ! (TYPE_LANG_SPECIFIC (basetype)
+ && (IS_SIGNATURE_POINTER (basetype)
+ || IS_SIGNATURE_REFERENCE (basetype))))
+ {
+ if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node)
+ cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
+ name, instance, basetype);
- struct candidate *candidates, *cp;
+ return error_mark_node;
+ }
- if (final_cp)
- {
- final_cp[0].h.code = 0;
- final_cp[0].h.distance = 0;
- final_cp[0].function = 0;
- /* end marker. */
- final_cp[1].h.code = EVIL_CODE;
+ /* If `instance' is a signature pointer/reference and `name' is
+ not a constructor, we are calling a signature member function.
+ In that case set the `basetype' to the signature type. */
+ if ((IS_SIGNATURE_POINTER (basetype)
+ || IS_SIGNATURE_REFERENCE (basetype))
+ && TYPE_IDENTIFIER (basetype) != name)
+ basetype = SIGNATURE_TYPE (basetype);
}
- for (parm = parms; parm; parm = TREE_CHAIN (parm))
+ if (basetype_path == NULL_TREE)
+ basetype_path = TYPE_BINFO (basetype);
+
+ if (instance)
{
- register tree t = TREE_TYPE (TREE_VALUE (parm));
+ instance_ptr = build_this (instance);
- if (t == error_mark_node)
- {
- if (final_cp)
- final_cp->h.code = EVIL_CODE;
- return error_mark_node;
- }
- if (TREE_CODE (t) == OFFSET_TYPE)
-#if 0
- /* This breaks reference-to-array parameters. */
- || TREE_CODE (t) == ARRAY_TYPE
-#endif
+ if (! template_only)
{
- /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
- Also convert OFFSET_TYPE entities to their normal selves.
- This eliminates needless calls to `compute_conversion_costs'. */
- TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
+ /* XXX this should be handled before we get here. */
+ fns = build_field_call (basetype_path, instance_ptr, name, args);
+ if (fns)
+ return fns;
}
- last = build_tree_list (NULL_TREE, t);
- parmtypes = chainon (parmtypes, last);
}
- if (last)
- TREE_CHAIN (last) = void_list_node;
else
- parmtypes = void_list_node;
+ {
+ instance_ptr = build_int_2 (0, 0);
+ TREE_TYPE (instance_ptr) = build_pointer_type (basetype);
+ }
+
+ pretty_name
+ = (name == ctor_identifier ? constructor_name (basetype) : name);
+
+ fns = lookup_fnfields (basetype_path, name, 1);
- if (is_overloaded_fn (fnname))
+ if (fns == error_mark_node)
+ return error_mark_node;
+ if (fns)
{
- functions = fnname;
- if (TREE_CODE (fnname) == TREE_LIST)
- fnname = TREE_PURPOSE (functions);
- else if (TREE_CODE (fnname) == FUNCTION_DECL)
- fnname = DECL_NAME (functions);
+ tree fn = TREE_VALUE (fns);
+ if (name == ctor_identifier && TYPE_USES_VIRTUAL_BASECLASSES (basetype)
+ && ! (flags & LOOKUP_HAS_IN_CHARGE))
+ {
+ flags |= LOOKUP_HAS_IN_CHARGE;
+ args = scratch_tree_cons (NULL_TREE, integer_one_node, args);
+ }
+ mem_args = scratch_tree_cons (NULL_TREE, instance_ptr, args);
+ for (; fn; fn = OVL_NEXT (fn))
+ {
+ tree t = OVL_CURRENT (fn);
+ tree this_arglist;
+
+ /* We can end up here for copy-init of same or base class. */
+ if (name == ctor_identifier
+ && (flags & LOOKUP_ONLYCONVERTING)
+ && DECL_NONCONVERTING_P (t))
+ continue;
+ if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)
+ this_arglist = mem_args;
+ else
+ this_arglist = args;
+
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ {
+ /* A member template. */
+ templates = scratch_tree_cons (NULL_TREE, t, templates);
+ candidates =
+ add_template_candidate (candidates, t, explicit_targs,
+ this_arglist,
+ TREE_TYPE (name), flags, DEDUCE_CALL);
+ }
+ else if (! template_only)
+ candidates = add_function_candidate (candidates, t,
+ this_arglist, flags);
+
+ if (candidates)
+ candidates->basetype_path = TREE_PURPOSE (fns);
+ }
}
- else
- functions = lookup_name_nonclass (fnname);
- if (functions == NULL_TREE)
+ if (! any_viable (candidates))
{
+ /* XXX will LOOKUP_SPECULATIVELY be needed when this is done? */
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
- if (flags & LOOKUP_COMPLAIN)
- error ("only member functions apply");
- if (final_cp)
- final_cp->h.code = EVIL_CODE;
+ cp_error ("no matching function for call to `%T::%D (%A)%V'", basetype,
+ pretty_name, user_args, TREE_TYPE (TREE_TYPE (instance_ptr)));
+ print_z_candidates (candidates);
return error_mark_node;
}
+ candidates = splice_viable (candidates);
+ cand = tourney (candidates);
- if (TREE_CODE (functions) == FUNCTION_DECL && ! IDENTIFIER_OPNAME_P (fnname))
+ if (cand == 0)
{
- functions = DECL_MAIN_VARIANT (functions);
- if (final_cp)
- {
- /* We are just curious whether this is a viable alternative or
- not. */
- compute_conversion_costs (functions, parms, final_cp, parmlength);
- return functions;
- }
- else
- return build_function_call_real (functions, parms, 1, flags);
+ cp_error ("call of overloaded `%D(%A)' is ambiguous", pretty_name,
+ user_args);
+ print_z_candidates (candidates);
+ return error_mark_node;
}
- if (TREE_CODE (functions) == TREE_LIST
- && TREE_VALUE (functions) == NULL_TREE)
+ if (DECL_ABSTRACT_VIRTUAL_P (cand->fn)
+ && instance == current_class_ref
+ && DECL_CONSTRUCTOR_P (current_function_decl)
+ && ! (flags & LOOKUP_NONVIRTUAL)
+ && value_member (cand->fn, get_abstract_virtuals (basetype)))
+ cp_error ("abstract virtual `%#D' called from constructor", cand->fn);
+ if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
+ && TREE_CODE (instance_ptr) == NOP_EXPR
+ && TREE_OPERAND (instance_ptr, 0) == error_mark_node)
+ cp_error ("cannot call member function `%D' without object", cand->fn);
+
+ if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
+ && ((instance == current_class_ref && (dtor_label || ctor_label))
+ || resolves_to_fixed_type_p (instance, 0)))
+ flags |= LOOKUP_NONVIRTUAL;
+
+ /* Pedantically, normal function declarations are never considered
+ to refer to template instantiations, so we only do this with
+ -fguiding-decls. */
+ if (flag_guiding_decls && templates && ! cand->template
+ && ! DECL_INITIAL (cand->fn))
+ add_maybe_template (cand->fn, templates);
+
+ return build_over_call
+ (cand,
+ TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args,
+ flags);
+}
+
+/* Returns non-zero iff standard conversion sequence ICS1 is a proper
+ subsequence of ICS2. */
+
+static int
+is_subseq (ics1, ics2)
+ tree ics1, ics2;
+{
+ /* We can assume that a conversion of the same code
+ between the same types indicates a subsequence since we only get
+ here if the types we are converting from are the same. */
+
+ while (TREE_CODE (ics1) == RVALUE_CONV
+ || TREE_CODE (ics1) == LVALUE_CONV)
+ ics1 = TREE_OPERAND (ics1, 0);
+
+ while (1)
{
- if (flags & LOOKUP_SPECULATIVELY)
- return NULL_TREE;
-
- if (flags & LOOKUP_COMPLAIN)
- cp_error ("function `%D' declared overloaded, but no instances of that function declared",
- TREE_PURPOSE (functions));
- if (final_cp)
- final_cp->h.code = EVIL_CODE;
- return error_mark_node;
+ while (TREE_CODE (ics2) == RVALUE_CONV
+ || TREE_CODE (ics2) == LVALUE_CONV)
+ ics2 = TREE_OPERAND (ics2, 0);
+
+ if (TREE_CODE (ics2) == USER_CONV
+ || TREE_CODE (ics2) == AMBIG_CONV
+ || TREE_CODE (ics2) == IDENTITY_CONV)
+ /* At this point, ICS1 cannot be a proper subsequence of
+ ICS2. We can get a USER_CONV when we are comparing the
+ second standard conversion sequence of two user conversion
+ sequences. */
+ return 0;
+
+ ics2 = TREE_OPERAND (ics2, 0);
+
+ if (TREE_CODE (ics2) == TREE_CODE (ics1)
+ && comptypes (TREE_TYPE (ics2), TREE_TYPE (ics1), 1)
+ && comptypes (TREE_TYPE (TREE_OPERAND (ics2, 0)),
+ TREE_TYPE (TREE_OPERAND (ics1, 0)), 1))
+ return 1;
+ }
+}
+
+/* Returns non-zero iff DERIVED is derived from BASE. The inputs may
+ be any _TYPE nodes. */
+
+static int
+is_properly_derived_from (derived, base)
+ tree derived;
+ tree base;
+{
+ if (!IS_AGGR_TYPE_CODE (TREE_CODE (derived))
+ || !IS_AGGR_TYPE_CODE (TREE_CODE (base)))
+ return 0;
+
+ /* We only allow proper derivation here. The DERIVED_FROM_P macro
+ considers every class derived from itself. */
+ return (!comptypes (TYPE_MAIN_VARIANT (derived),
+ TYPE_MAIN_VARIANT (base), 1)
+ && DERIVED_FROM_P (base, derived));
+}
+
+/* We build the ICS for an implicit object parameter as a pointer
+ conversion sequence. However, such a sequence should be compared
+ as if it were a reference conversion sequence. If ICS is the
+ implicit conversion sequence for an implicit object parameter,
+ modify it accordingly. */
+
+static void
+maybe_handle_implicit_object (ics)
+ tree* ics;
+{
+ if (ICS_THIS_FLAG (*ics))
+ {
+ /* [over.match.funcs]
+
+ For non-static member functions, the type of the
+ implicit object parameter is "reference to cv X"
+ where X is the class of which the function is a
+ member and cv is the cv-qualification on the member
+ function declaration. */
+ tree t = *ics;
+ if (TREE_CODE (t) == QUAL_CONV)
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == PTR_CONV)
+ t = TREE_OPERAND (t, 0);
+ t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE);
+ t = build_conv (REF_BIND,
+ build_reference_type (TREE_TYPE (TREE_TYPE (*ics))),
+ t);
+ ICS_STD_RANK (t) = ICS_STD_RANK (*ics);
+ *ics = t;
}
+}
+
+/* If ICS is a REF_BIND, modify it appropriately, set TARGET_TYPE
+ to the type the reference originally referred to, and return 1.
+ Otherwise, return 0. */
- length = count_functions (functions);
+static int
+maybe_handle_ref_bind (ics, target_type)
+ tree* ics;
+ tree* target_type;
+{
+ if (TREE_CODE (*ics) == REF_BIND)
+ {
+ /* [over.ics.rank]
+
+ When a parameter of reference type binds directly
+ (_dcl.init.ref_) to an argument expression, the implicit
+ conversion sequence is the identity conversion, unless the
+ argument expression has a type that is a derived class of the
+ parameter type, in which case the implicit conversion
+ sequence is a derived-to-base Conversion.
+
+ If the parameter binds directly to the result of applying a
+ conversion function to the argument expression, the implicit
+ conversion sequence is a user-defined conversion sequence
+ (_over.ics.user_), with the second standard conversion
+ sequence either an identity conversion or, if the conversion
+ function returns an entity of a type that is a derived class
+ of the parameter type, a derived-to-base Conversion.
+
+ When a parameter of reference type is not bound directly to
+ an argument expression, the conversion sequence is the one
+ required to convert the argument expression to the underlying
+ type of the reference according to _over.best.ics_.
+ Conceptually, this conversion sequence corresponds to
+ copy-initializing a temporary of the underlying type with the
+ argument expression. Any difference in top-level
+ cv-qualification is subsumed by the initialization itself and
+ does not constitute a conversion. */
+
+ tree old_ics = *ics;
+
+ *target_type = TREE_TYPE (TREE_TYPE (*ics));
+ *ics = TREE_OPERAND (*ics, 0);
+ if (TREE_CODE (*ics) == IDENTITY_CONV
+ && is_properly_derived_from (TREE_TYPE (*ics), *target_type))
+ *ics = build_conv (BASE_CONV, *target_type, *ics);
+ ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics);
+ ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics);
+
+ return 1;
+ }
- if (final_cp)
- candidates = final_cp;
+ return 0;
+}
+
+/* Compare two implicit conversion sequences according to the rules set out in
+ [over.ics.rank]. Return values:
+
+ 1: ics1 is better than ics2
+ -1: ics2 is better than ics1
+ 0: ics1 and ics2 are indistinguishable */
+
+static int
+compare_ics (ics1, ics2)
+ tree ics1, ics2;
+{
+ tree from_type1;
+ tree from_type2;
+ tree to_type1;
+ tree to_type2;
+ tree deref_from_type1 = NULL_TREE;
+ tree deref_from_type2;
+ tree deref_to_type1;
+ tree deref_to_type2;
+
+ /* REF_BINDING is non-zero if the result of the conversion sequence
+ is a reference type. In that case TARGET_TYPE is the
+ type referred to by the reference. */
+ int ref_binding1;
+ int ref_binding2;
+ tree target_type1;
+ tree target_type2;
+
+ /* Handle implicit object parameters. */
+ maybe_handle_implicit_object (&ics1);
+ maybe_handle_implicit_object (&ics2);
+
+ /* Handle reference parameters. */
+ ref_binding1 = maybe_handle_ref_bind (&ics1, &target_type1);
+ ref_binding2 = maybe_handle_ref_bind (&ics2, &target_type2);
+
+ /* [over.ics.rank]
+
+ When comparing the basic forms of implicit conversion sequences (as
+ defined in _over.best.ics_)
+
+ --a standard conversion sequence (_over.ics.scs_) is a better
+ conversion sequence than a user-defined conversion sequence
+ or an ellipsis conversion sequence, and
+
+ --a user-defined conversion sequence (_over.ics.user_) is a
+ better conversion sequence than an ellipsis conversion sequence
+ (_over.ics.ellipsis_). */
+ if (ICS_RANK (ics1) > ICS_RANK (ics2))
+ return -1;
+ else if (ICS_RANK (ics1) < ICS_RANK (ics2))
+ return 1;
+
+ if (ICS_RANK (ics1) == BAD_RANK)
+ {
+ /* Both ICS are bad. We try to make a decision based on what
+ would have happenned if they'd been good. */
+ if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2)
+ || ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
+ return -1;
+ else if (ICS_USER_FLAG (ics1) < ICS_USER_FLAG (ics2)
+ || ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
+ return 1;
+
+ /* We couldn't make up our minds; try to figure it out below. */
+ }
+
+ if (ICS_ELLIPSIS_FLAG (ics1))
+ /* Both conversions are ellipsis conversions. */
+ return 0;
+
+ /* User-defined conversion sequence U1 is a better conversion sequence
+ than another user-defined conversion sequence U2 if they contain the
+ same user-defined conversion operator or constructor and if the sec-
+ ond standard conversion sequence of U1 is better than the second
+ standard conversion sequence of U2. */
+
+ if (ICS_USER_FLAG (ics1))
+ {
+ tree t1, t2;
+
+ for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0))
+ if (TREE_CODE (t1) == AMBIG_CONV)
+ return 0;
+ for (t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0))
+ if (TREE_CODE (t2) == AMBIG_CONV)
+ return 0;
+
+ if (USER_CONV_FN (t1) != USER_CONV_FN (t2))
+ return 0;
+
+ /* We can just fall through here, after setting up
+ FROM_TYPE1 and FROM_TYPE2. */
+ from_type1 = TREE_TYPE (t1);
+ from_type2 = TREE_TYPE (t2);
+ }
else
{
- candidates
- = (struct candidate *)alloca ((length+1) * sizeof (struct candidate));
- bzero ((char *) candidates, (length + 1) * sizeof (struct candidate));
+ /* We're dealing with two standard conversion sequences.
+
+ [over.ics.rank]
+
+ Standard conversion sequence S1 is a better conversion
+ sequence than standard conversion sequence S2 if
+
+ --S1 is a proper subsequence of S2 (comparing the conversion
+ sequences in the canonical form defined by _over.ics.scs_,
+ excluding any Lvalue Transformation; the identity
+ conversion sequence is considered to be a subsequence of
+ any non-identity conversion sequence */
+
+ from_type1 = ics1;
+ while (TREE_CODE (from_type1) != IDENTITY_CONV)
+ from_type1 = TREE_OPERAND (from_type1, 0);
+ from_type1 = TREE_TYPE (from_type1);
+
+ from_type2 = ics2;
+ while (TREE_CODE (from_type2) != IDENTITY_CONV)
+ from_type2 = TREE_OPERAND (from_type2, 0);
+ from_type2 = TREE_TYPE (from_type2);
+ }
+
+ if (comptypes (from_type1, from_type2, 1))
+ {
+ if (is_subseq (ics1, ics2))
+ return 1;
+ if (is_subseq (ics2, ics1))
+ return -1;
}
+ /* Otherwise, one sequence cannot be a subsequence of the other; they
+ don't start with the same type. This can happen when comparing the
+ second standard conversion sequence in two user-defined conversion
+ sequences. */
+
+ /* [over.ics.rank]
+
+ Or, if not that,
+
+ --the rank of S1 is better than the rank of S2 (by the rules
+ defined below):
- cp = candidates;
+ Standard conversion sequences are ordered by their ranks: an Exact
+ Match is a better conversion than a Promotion, which is a better
+ conversion than a Conversion.
- my_friendly_assert (is_overloaded_fn (functions), 169);
+ Two conversion sequences with the same rank are indistinguishable
+ unless one of the following rules applies:
- functions = get_first_fn (functions);
+ --A conversion that is not a conversion of a pointer, or pointer
+ to member, to bool is better than another conversion that is such
+ a conversion.
+
+ The ICS_STD_RANK automatically handles the pointer-to-bool rule,
+ so that we do not have to check it explicitly. */
+ if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
+ return 1;
+ else if (ICS_STD_RANK (ics2) < ICS_STD_RANK (ics1))
+ return -1;
+
+ to_type1 = TREE_TYPE (ics1);
+ to_type2 = TREE_TYPE (ics2);
+
+ if (TYPE_PTR_P (from_type1)
+ && TYPE_PTR_P (from_type2)
+ && TYPE_PTR_P (to_type1)
+ && TYPE_PTR_P (to_type2))
+ {
+ deref_from_type1 = TREE_TYPE (from_type1);
+ deref_from_type2 = TREE_TYPE (from_type2);
+ deref_to_type1 = TREE_TYPE (to_type1);
+ deref_to_type2 = TREE_TYPE (to_type2);
+ }
+ /* The rules for pointers to members A::* are just like the rules
+ for pointers A*, except opposite: if B is derived from A then
+ A::* converts to B::*, not vice versa. For that reason, we
+ switch the from_ and to_ variables here. */
+ else if (TYPE_PTRMEM_P (from_type1)
+ && TYPE_PTRMEM_P (from_type2)
+ && TYPE_PTRMEM_P (to_type1)
+ && TYPE_PTRMEM_P (to_type2))
+ {
+ deref_to_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type1));
+ deref_to_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type2));
+ deref_from_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type1));
+ deref_from_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type2));
+ }
+ else if (TYPE_PTRMEMFUNC_P (from_type1)
+ && TYPE_PTRMEMFUNC_P (from_type2)
+ && TYPE_PTRMEMFUNC_P (to_type1)
+ && TYPE_PTRMEMFUNC_P (to_type2))
+ {
+ deref_to_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type1);
+ deref_to_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type2);
+ deref_from_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type1);
+ deref_from_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type2);
+ }
- /* OUTER is the list of FUNCTION_DECLS, in a TREE_LIST. */
- for (outer = functions; outer; outer = DECL_CHAIN (outer))
+ if (deref_from_type1 != NULL_TREE
+ && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type1))
+ && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type2)))
{
- int template_cost = 0;
- function = outer;
- if (TREE_CODE (function) != FUNCTION_DECL
- && ! (TREE_CODE (function) == TEMPLATE_DECL
- && ! DECL_TEMPLATE_IS_CLASS (function)
- && TREE_CODE (DECL_TEMPLATE_RESULT (function)) == FUNCTION_DECL))
+ /* This was one of the pointer or pointer-like conversions.
+
+ [over.ics.rank]
+
+ --If class B is derived directly or indirectly from class A,
+ conversion of B* to A* is better than conversion of B* to
+ void*, and conversion of A* to void* is better than
+ conversion of B* to void*. */
+ if (TREE_CODE (deref_to_type1) == VOID_TYPE
+ && TREE_CODE (deref_to_type2) == VOID_TYPE)
+ {
+ if (is_properly_derived_from (deref_from_type1,
+ deref_from_type2))
+ return -1;
+ else if (is_properly_derived_from (deref_from_type2,
+ deref_from_type1))
+ return 1;
+ }
+ else if (TREE_CODE (deref_to_type1) == VOID_TYPE
+ || TREE_CODE (deref_to_type2) == VOID_TYPE)
{
- enum tree_code code = TREE_CODE (function);
- if (code == TEMPLATE_DECL)
- code = TREE_CODE (DECL_TEMPLATE_RESULT (function));
- if (code == CONST_DECL)
- cp_error_at
- ("enumeral value `%D' conflicts with function of same name",
- function);
- else if (code == VAR_DECL)
+ if (comptypes (deref_from_type1, deref_from_type2, 1))
{
- if (TREE_STATIC (function))
- cp_error_at
- ("variable `%D' conflicts with function of same name",
- function);
- else
- cp_error_at
- ("constant field `%D' conflicts with function of same name",
- function);
+ if (TREE_CODE (deref_to_type2) == VOID_TYPE)
+ {
+ if (is_properly_derived_from (deref_from_type1,
+ deref_to_type1))
+ return 1;
+ }
+ /* We know that DEREF_TO_TYPE1 is `void' here. */
+ else if (is_properly_derived_from (deref_from_type1,
+ deref_to_type2))
+ return -1;
}
- else if (code == TYPE_DECL)
- continue;
- else
- my_friendly_abort (2);
- error ("at this point in file");
- continue;
}
- if (TREE_CODE (function) == TEMPLATE_DECL)
+ else if (IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type1))
+ && IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type2)))
{
- int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (function));
- tree *targs = (tree *) alloca (sizeof (tree) * ntparms);
- int i;
+ /* [over.ics.rank]
- i = type_unification (DECL_TEMPLATE_PARMS (function), targs,
- TYPE_ARG_TYPES (TREE_TYPE (function)),
- parms, &template_cost, 0);
- if (i == 0)
- function = instantiate_template (function, targs);
+ --If class B is derived directly or indirectly from class A
+ and class C is derived directly or indirectly from B,
+
+ --conversion of C* to B* is better than conversion of C* to
+ A*,
+
+ --conversion of B* to A* is better than conversion of C* to
+ A* */
+ if (comptypes (deref_from_type1, deref_from_type2, 1))
+ {
+ if (is_properly_derived_from (deref_to_type1,
+ deref_to_type2))
+ return 1;
+ else if (is_properly_derived_from (deref_to_type2,
+ deref_to_type1))
+ return -1;
+ }
+ else if (comptypes (deref_to_type1, deref_to_type2, 1))
+ {
+ if (is_properly_derived_from (deref_from_type2,
+ deref_from_type1))
+ return 1;
+ else if (is_properly_derived_from (deref_from_type1,
+ deref_from_type2))
+ return -1;
+ }
}
-
- if (TREE_CODE (function) == TEMPLATE_DECL)
+ }
+ else if (IS_AGGR_TYPE_CODE (TREE_CODE (from_type1))
+ && comptypes (from_type1, from_type2, 1))
+ {
+ /* [over.ics.rank]
+
+ --binding of an expression of type C to a reference of type
+ B& is better than binding an expression of type C to a
+ reference of type A&
+
+ --conversion of C to B is better than conversion of C to A, */
+ if (is_properly_derived_from (from_type1, to_type1)
+ && is_properly_derived_from (from_type1, to_type2))
{
- /* Unconverted template -- failed match. */
- cp->function = function;
- cp->u.bad_arg = -4;
- cp->h.code = EVIL_CODE;
+ if (is_properly_derived_from (to_type1, to_type2))
+ return 1;
+ else if (is_properly_derived_from (to_type2, to_type1))
+ return -1;
}
- else
+ }
+ else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1))
+ && comptypes (to_type1, to_type2, 1))
+ {
+ /* [over.ics.rank]
+
+ --binding of an expression of type B to a reference of type
+ A& is better than binding an expression of type C to a
+ reference of type A&,
+
+ --onversion of B to A is better than conversion of C to A */
+ if (is_properly_derived_from (from_type1, to_type1)
+ && is_properly_derived_from (from_type2, to_type1))
{
- struct candidate *cp2;
+ if (is_properly_derived_from (from_type2, from_type1))
+ return 1;
+ else if (is_properly_derived_from (from_type1, from_type2))
+ return -1;
+ }
+ }
- /* Check that this decl is not the same as a function that's in
- the list due to some template instantiation. */
- cp2 = candidates;
- while (cp2 != cp)
- if (cp2->function == function)
- break;
- else
- cp2 += 1;
- if (cp2->function == function)
- continue;
+ /* [over.ics.rank]
- function = DECL_MAIN_VARIANT (function);
+ --S1 and S2 differ only in their qualification conversion and yield
+ similar types T1 and T2 (_conv.qual_), respectively, and the cv-
+ qualification signature of type T1 is a proper subset of the cv-
+ qualification signature of type T2 */
+ if (TREE_CODE (ics1) == QUAL_CONV
+ && TREE_CODE (ics2) == QUAL_CONV
+ && comptypes (from_type1, from_type2, 1))
+ return comp_cv_qual_signature (to_type1, to_type2);
- /* Can't use alloca here, since result might be
- passed to calling function. */
- cp->h_len = parmlength;
- cp->harshness = (struct harshness_code *)
- oballoc ((parmlength + 1) * sizeof (struct harshness_code));
+ /* [over.ics.rank]
+
+ --S1 and S2 are reference bindings (_dcl.init.ref_), and the
+ types to which the references refer are the same type except for
+ top-level cv-qualifiers, and the type to which the reference
+ initialized by S2 refers is more cv-qualified than the type to
+ which the reference initialized by S1 refers */
+
+ if (ref_binding1 && ref_binding2
+ && comptypes (TYPE_MAIN_VARIANT (to_type1),
+ TYPE_MAIN_VARIANT (to_type2), 1))
+ return comp_cv_qualification (target_type2, target_type1);
- compute_conversion_costs (function, parms, cp, parmlength);
+ /* Neither conversion sequence is better than the other. */
+ return 0;
+}
- /* Make sure this is clear as well. */
- cp->h.int_penalty += template_cost;
+/* The source type for this standard conversion sequence. */
- if ((cp[0].h.code & EVIL_CODE) == 0)
- {
- cp[1].h.code = EVIL_CODE;
- cp++;
- }
+static tree
+source_type (t)
+ tree t;
+{
+ for (;; t = TREE_OPERAND (t, 0))
+ {
+ if (TREE_CODE (t) == USER_CONV
+ || TREE_CODE (t) == AMBIG_CONV
+ || TREE_CODE (t) == IDENTITY_CONV)
+ return TREE_TYPE (t);
+ }
+ my_friendly_abort (1823);
+}
+
+/* Note a warning about preferring WINNER to LOSER. We do this by storing
+ a pointer to LOSER and re-running joust to produce the warning if WINNER
+ is actually used. */
+
+static void
+add_warning (winner, loser)
+ struct z_candidate *winner, *loser;
+{
+ winner->warnings = expr_tree_cons (NULL_PTR,
+ build_expr_ptr_wrapper (loser),
+ winner->warnings);
+}
+
+/* Compare two candidates for overloading as described in
+ [over.match.best]. Return values:
+
+ 1: cand1 is better than cand2
+ -1: cand2 is better than cand1
+ 0: cand1 and cand2 are indistinguishable */
+
+static int
+joust (cand1, cand2, warn)
+ struct z_candidate *cand1, *cand2;
+ int warn;
+{
+ int winner = 0;
+ int i, off1 = 0, off2 = 0, len;
+
+ /* Candidates that involve bad conversions are always worse than those
+ that don't. */
+ if (cand1->viable > cand2->viable)
+ return 1;
+ if (cand1->viable < cand2->viable)
+ return -1;
+
+ /* a viable function F1
+ is defined to be a better function than another viable function F2 if
+ for all arguments i, ICSi(F1) is not a worse conversion sequence than
+ ICSi(F2), and then */
+
+ /* for some argument j, ICSj(F1) is a better conversion sequence than
+ ICSj(F2) */
+
+ /* For comparing static and non-static member functions, we ignore the
+ implicit object parameter of the non-static function. The WP says to
+ pretend that the static function has an object parm, but that won't
+ work with operator overloading. */
+ len = TREE_VEC_LENGTH (cand1->convs);
+ if (len != TREE_VEC_LENGTH (cand2->convs))
+ {
+ if (DECL_STATIC_FUNCTION_P (cand1->fn)
+ && ! DECL_STATIC_FUNCTION_P (cand2->fn))
+ off2 = 1;
+ else if (! DECL_STATIC_FUNCTION_P (cand1->fn)
+ && DECL_STATIC_FUNCTION_P (cand2->fn))
+ {
+ off1 = 1;
+ --len;
}
+ else
+ my_friendly_abort (42);
}
- if (cp - candidates)
+ for (i = 0; i < len; ++i)
{
- tree rval = error_mark_node;
+ tree t1 = TREE_VEC_ELT (cand1->convs, i+off1);
+ tree t2 = TREE_VEC_ELT (cand2->convs, i+off2);
+ int comp = compare_ics (t1, t2);
- /* Leave marker. */
- cp[0].h.code = EVIL_CODE;
- if (cp - candidates > 1)
+ if (comp != 0)
{
- struct candidate *best_cp
- = ideal_candidate (NULL_TREE, candidates,
- cp - candidates, parms, parmlength);
- if (best_cp == (struct candidate *)0)
+ if (warn_sign_promo
+ && ICS_RANK (t1) + ICS_RANK (t2) == STD_RANK + PROMO_RANK
+ && TREE_CODE (t1) == STD_CONV
+ && TREE_CODE (t2) == STD_CONV
+ && TREE_CODE (TREE_TYPE (t1)) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (t2)) == INTEGER_TYPE
+ && (TYPE_PRECISION (TREE_TYPE (t1))
+ == TYPE_PRECISION (TREE_TYPE (t2)))
+ && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (t1, 0)))
+ || (TREE_CODE (TREE_TYPE (TREE_OPERAND (t1, 0)))
+ == ENUMERAL_TYPE)))
{
- if (flags & LOOKUP_COMPLAIN)
+ tree type = TREE_TYPE (TREE_OPERAND (t1, 0));
+ tree type1, type2;
+ struct z_candidate *w, *l;
+ if (comp > 0)
+ type1 = TREE_TYPE (t1), type2 = TREE_TYPE (t2),
+ w = cand1, l = cand2;
+ else
+ type1 = TREE_TYPE (t2), type2 = TREE_TYPE (t1),
+ w = cand2, l = cand1;
+
+ if (warn)
{
- cp_error ("call of overloaded `%D' is ambiguous", fnname);
- print_n_candidates (candidates, cp - candidates);
+ cp_warning ("passing `%T' chooses `%T' over `%T'",
+ type, type1, type2);
+ cp_warning (" in call to `%D'", w->fn);
}
- return error_mark_node;
+ else
+ add_warning (w, l);
+ }
+
+ if (winner && comp != winner)
+ {
+ winner = 0;
+ goto tweak;
+ }
+ winner = comp;
+ }
+ }
+
+ /* warn about confusing overload resolution for user-defined conversions,
+ either between a constructor and a conversion op, or between two
+ conversion ops. */
+ if (winner && cand1->second_conv
+ && ((DECL_CONSTRUCTOR_P (cand1->fn)
+ != DECL_CONSTRUCTOR_P (cand2->fn))
+ /* Don't warn if the two conv ops convert to the same type... */
+ || (! DECL_CONSTRUCTOR_P (cand1->fn)
+ && ! comptypes (TREE_TYPE (cand1->second_conv),
+ TREE_TYPE (cand2->second_conv), 1))))
+ {
+ int comp = compare_ics (cand1->second_conv, cand2->second_conv);
+ if (comp != winner)
+ {
+ struct z_candidate *w, *l;
+ if (winner == 1)
+ w = cand1, l = cand2;
+ else
+ w = cand2, l = cand1;
+ if (warn)
+ {
+ tree source = source_type (TREE_VEC_ELT (w->convs, 0));
+ if (! DECL_CONSTRUCTOR_P (w->fn))
+ source = TREE_TYPE (source);
+ cp_warning ("choosing `%D' over `%D'", w->fn, l->fn);
+ cp_warning (" for conversion from `%T' to `%T'",
+ source, TREE_TYPE (w->second_conv));
+ cp_warning (" because conversion sequence for the argument is better");
}
else
- rval = best_cp->function;
+ add_warning (w, l);
}
+ }
+
+ if (winner)
+ return winner;
+
+ /* or, if not that,
+ F1 is a non-template function and F2 is a template function */
+
+ if (! cand1->template && cand2->template)
+ return 1;
+ else if (cand1->template && ! cand2->template)
+ return -1;
+ else if (cand1->template && cand2->template)
+ winner = more_specialized
+ (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template),
+ NULL_TREE);
+
+ /* or, if not that,
+ the context is an initialization by user-defined conversion (see
+ _dcl.init_ and _over.match.user_) and the standard conversion
+ sequence from the return type of F1 to the destination type (i.e.,
+ the type of the entity being initialized) is a better conversion
+ sequence than the standard conversion sequence from the return type
+ of F2 to the destination type. */
+
+ if (! winner && cand1->second_conv)
+ winner = compare_ics (cand1->second_conv, cand2->second_conv);
+
+ /* If the built-in candidates are the same, arbitrarily pick one. */
+ if (! winner && cand1->fn == cand2->fn
+ && TREE_CODE (cand1->fn) == IDENTIFIER_NODE)
+ {
+ for (i = 0; i < len; ++i)
+ if (! comptypes (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)),
+ TREE_TYPE (TREE_VEC_ELT (cand2->convs, i)), 1))
+ break;
+ if (i == TREE_VEC_LENGTH (cand1->convs))
+ return 1;
+
+ /* Kludge around broken overloading rules whereby
+ Integer a, b; test ? a : b; is ambiguous, since there's a builtin
+ that takes references and another that takes values. */
+ if (cand1->fn == ansi_opname[COND_EXPR])
+ {
+ tree c1 = TREE_VEC_ELT (cand1->convs, 1);
+ tree c2 = TREE_VEC_ELT (cand2->convs, 1);
+ tree t1 = strip_top_quals (non_reference (TREE_TYPE (c1)));
+ tree t2 = strip_top_quals (non_reference (TREE_TYPE (c2)));
+
+ if (comptypes (t1, t2, 1))
+ {
+ if (TREE_CODE (c1) == REF_BIND && TREE_CODE (c2) != REF_BIND)
+ return 1;
+ if (TREE_CODE (c1) != REF_BIND && TREE_CODE (c2) == REF_BIND)
+ return -1;
+ }
+ }
+ }
+
+tweak:
+
+ /* Extension: If the worst conversion for one candidate is worse than the
+ worst conversion for the other, take the first. */
+ if (! winner && ! pedantic)
+ {
+ int rank1 = IDENTITY_RANK, rank2 = IDENTITY_RANK;
+
+ for (i = 0; i < len; ++i)
+ {
+ if (ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1)) > rank1)
+ rank1 = ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1));
+ if (ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2)) > rank2)
+ rank2 = ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2));
+ }
+
+ if (rank1 < rank2)
+ return 1;
+ if (rank1 > rank2)
+ return -1;
+ }
+
+ return winner;
+}
+
+/* Given a list of candidates for overloading, find the best one, if any.
+ This algorithm has a worst case of O(2n) (winner is last), and a best
+ case of O(n/2) (totally ambiguous); much better than a sorting
+ algorithm. */
+
+static struct z_candidate *
+tourney (candidates)
+ struct z_candidate *candidates;
+{
+ struct z_candidate *champ = candidates, *challenger;
+ int fate;
+ int champ_compared_to_predecessor = 0;
+
+ /* Walk through the list once, comparing each current champ to the next
+ candidate, knocking out a candidate or two with each comparison. */
+
+ for (challenger = champ->next; challenger; )
+ {
+ fate = joust (champ, challenger, 0);
+ if (fate == 1)
+ challenger = challenger->next;
else
{
- cp -= 1;
- if (cp->h.code & EVIL_CODE)
+ if (fate == 0)
{
- if (flags & LOOKUP_COMPLAIN)
- error ("type conversion ambiguous");
+ champ = challenger->next;
+ if (champ == 0)
+ return 0;
+ champ_compared_to_predecessor = 0;
}
else
- rval = cp->function;
+ {
+ champ = challenger;
+ champ_compared_to_predecessor = 1;
+ }
+
+ challenger = champ->next;
}
+ }
- if (final_cp)
- return rval;
+ /* Make sure the champ is better than all the candidates it hasn't yet
+ been compared to. */
- return buildxxx ? build_function_call_real (rval, parms, 0, flags)
- : build_function_call_real (rval, parms, 1, flags);
+ for (challenger = candidates;
+ challenger != champ
+ && !(champ_compared_to_predecessor && challenger->next == champ);
+ challenger = challenger->next)
+ {
+ fate = joust (champ, challenger, 0);
+ if (fate != 1)
+ return 0;
}
- if (flags & LOOKUP_SPECULATIVELY)
- return NULL_TREE;
-
- if (flags & LOOKUP_COMPLAIN)
- report_type_mismatch (cp, parms, "function",
- decl_as_string (cp->function, 1));
-
- return error_mark_node;
+ return champ;
}
-tree
-build_overload_call (fnname, parms, flags, final_cp)
- tree fnname, parms;
- int flags;
- struct candidate *final_cp;
+int
+can_convert (to, from)
+ tree to, from;
{
- return build_overload_call_real (fnname, parms, flags, final_cp, 0);
+ tree t = implicit_conversion (to, from, NULL_TREE, LOOKUP_NORMAL);
+ return (t && ! ICS_BAD_FLAG (t));
}
-tree
-build_overload_call_maybe (fnname, parms, flags, final_cp)
- tree fnname, parms;
- int flags;
- struct candidate *final_cp;
+int
+can_convert_arg (to, from, arg)
+ tree to, from, arg;
{
- return build_overload_call_real (fnname, parms, flags, final_cp, 1);
+ tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
+ return (t && ! ICS_BAD_FLAG (t));
}
diff --git a/contrib/gcc/cp/class.c b/contrib/gcc/cp/class.c
index e289304..8a61bf8 100644
--- a/contrib/gcc/cp/class.c
+++ b/contrib/gcc/cp/class.c
@@ -1,5 +1,5 @@
/* Functions related to building classes and their related objects.
- Copyright (C) 1987, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -20,15 +20,16 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* High-level class interface. */
+/* High-level class interface. */
#include "config.h"
+#include "system.h"
#include "tree.h"
-#include <stdio.h>
#include "cp-tree.h"
#include "flags.h"
#include "rtl.h"
#include "output.h"
+#include "toplev.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
@@ -37,7 +38,7 @@ Boston, MA 02111-1307, USA. */
extern struct obstack permanent_obstack;
/* This is how we tell when two virtual member functions are really the
- same. */
+ same. */
#define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL))
extern void set_class_shadows PROTO ((tree));
@@ -72,7 +73,9 @@ struct class_level
int unused;
};
-tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */
+/* The current_class_ptr is the pointer to the current class.
+ current_class_ref is the actual current class. */
+tree current_class_ptr, current_class_ref;
/* The following two can be derived from the previous one */
tree current_class_name; /* IDENTIFIER_NODE: name of current class */
@@ -80,26 +83,76 @@ tree current_class_type; /* _TYPE: the type of the current class */
tree previous_class_type; /* _TYPE: the previous type that was a class */
tree previous_class_values; /* TREE_LIST: copy of the class_shadowed list
when leaving an outermost class scope. */
+
+struct base_info;
+
static tree get_vfield_name PROTO((tree));
-tree the_null_vtable_entry;
+static void finish_struct_anon PROTO((tree));
+static tree build_vbase_pointer PROTO((tree, tree));
+static int complete_type_p PROTO((tree));
+static tree build_vtable_entry PROTO((tree, tree));
+static tree get_vtable_name PROTO((tree));
+static tree get_derived_offset PROTO((tree, tree));
+static tree get_basefndecls PROTO((tree, tree));
+static void set_rtti_entry PROTO((tree, tree, tree));
+static tree build_vtable PROTO((tree, tree));
+static void prepare_fresh_vtable PROTO((tree, tree));
+static void fixup_vtable_deltas1 PROTO((tree, tree));
+static void fixup_vtable_deltas PROTO((tree, int, tree));
+static void grow_method PROTO((tree, tree *));
+static void finish_vtbls PROTO((tree, int, tree));
+static void modify_vtable_entry PROTO((tree, tree, tree));
+static tree get_vtable_entry_n PROTO((tree, unsigned HOST_WIDE_INT));
+static void add_virtual_function PROTO((tree *, tree *, int *, tree, tree));
+static tree delete_duplicate_fields_1 PROTO((tree, tree));
+static void delete_duplicate_fields PROTO((tree));
+static void finish_struct_bits PROTO((tree, int));
+static int alter_access PROTO((tree, tree, tree, tree));
+static void handle_using_decl PROTO((tree, tree, tree, tree));
+static int overrides PROTO((tree, tree));
+static int strictly_overrides PROTO((tree, tree));
+static void merge_overrides PROTO((tree, tree, int, tree));
+static void override_one_vtable PROTO((tree, tree, tree));
+static void mark_overriders PROTO((tree, tree));
+static void check_for_override PROTO((tree, tree));
+static tree maybe_fixup_vptrs PROTO((tree, tree, tree));
+static tree get_class_offset_1 PROTO((tree, tree, tree, tree, tree));
+static tree get_class_offset PROTO((tree, tree, tree, tree));
+static void modify_one_vtable PROTO((tree, tree, tree, tree));
+static void modify_all_vtables PROTO((tree, tree, tree));
+static void modify_all_direct_vtables PROTO((tree, int, tree, tree,
+ tree));
+static void modify_all_indirect_vtables PROTO((tree, int, int, tree,
+ tree, tree));
+static void build_class_init_list PROTO((tree));
+static int finish_base_struct PROTO((tree, struct base_info *));
/* Way of stacking language names. */
tree *current_lang_base, *current_lang_stack;
int current_lang_stacksize;
/* Names of languages we recognize. */
-tree lang_name_c, lang_name_cplusplus;
+tree lang_name_c, lang_name_cplusplus, lang_name_java;
tree current_lang_name;
-char *dont_allow_type_definitions;
-
/* When layout out an aggregate type, the size of the
basetypes (virtual and non-virtual) is passed to layout_record
via this node. */
static tree base_layout_decl;
+/* Constants used for access control. */
+tree access_default_node; /* 0 */
+tree access_public_node; /* 1 */
+tree access_protected_node; /* 2 */
+tree access_private_node; /* 3 */
+tree access_default_virtual_node; /* 4 */
+tree access_public_virtual_node; /* 5 */
+tree access_protected_virtual_node; /* 6 */
+tree access_private_virtual_node; /* 7 */
+
/* Variables shared between class.c and call.c. */
+#ifdef GATHER_STATISTICS
int n_vtables = 0;
int n_vtable_entries = 0;
int n_vtable_searches = 0;
@@ -108,9 +161,11 @@ int n_convert_harshness = 0;
int n_compute_conversion_costs = 0;
int n_build_method_call = 0;
int n_inner_fields_searched = 0;
+#endif
/* Virtual baseclass things. */
-tree
+
+static tree
build_vbase_pointer (exp, type)
tree exp, type;
{
@@ -118,12 +173,13 @@ build_vbase_pointer (exp, type)
name = (char *) alloca (TYPE_NAME_LENGTH (type) + sizeof (VBASE_NAME) + 1);
sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (type));
- return build_component_ref (exp, get_identifier (name), 0, 0);
+ return build_component_ref (exp, get_identifier (name), NULL_TREE, 0);
}
/* Is the type of the EXPR, the complete type of the object?
- If we are going to be wrong, we must be conservative, and return 0. */
-int
+ If we are going to be wrong, we must be conservative, and return 0. */
+
+static int
complete_type_p (expr)
tree expr;
{
@@ -143,20 +199,20 @@ complete_type_p (expr)
case CALL_EXPR:
if (! TREE_HAS_CONSTRUCTOR (expr))
break;
- /* fall through... */
+ /* fall through... */
case VAR_DECL:
case FIELD_DECL:
if (TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
&& IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (expr)))
&& TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type)
return 1;
- /* fall through... */
+ /* fall through... */
case TARGET_EXPR:
case PARM_DECL:
if (IS_AGGR_TYPE (TREE_TYPE (expr))
&& TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type)
return 1;
- /* fall through... */
+ /* fall through... */
case PLUS_EXPR:
default:
break;
@@ -174,6 +230,7 @@ complete_type_p (expr)
TYPE is the type we want this path to have on exit.
ALIAS_THIS is non-zero if EXPR in an expression involving `this'. */
+
tree
build_vbase_path (code, type, expr, path, alias_this)
enum tree_code code;
@@ -183,21 +240,28 @@ build_vbase_path (code, type, expr, path, alias_this)
register int changed = 0;
tree last = NULL_TREE, last_virtual = NULL_TREE;
int nonnull = 0;
- int fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
+ int fixed_type_p;
tree null_expr = 0, nonnull_expr;
tree basetype;
tree offset = integer_zero_node;
+ if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE)
+ return build1 (NOP_EXPR, type, expr);
+
if (nonnull == 0 && (alias_this && flag_this_is_variable <= 0))
nonnull = 1;
+#if 0
/* 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
recognize when that is, we cannot do the short cut logic. (mrs) */
+ fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
+#else
/* Do this, until we can undo any previous conversions. See net35.C
- for a testcase. */
+ for a testcase. */
fixed_type_p = complete_type_p (expr);
+#endif
if (!fixed_type_p && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
@@ -207,6 +271,7 @@ build_vbase_path (code, type, expr, path, alias_this)
{
tree reverse_path = NULL_TREE;
+ push_expression_obstack ();
while (path)
{
tree r = copy_node (path);
@@ -215,6 +280,7 @@ build_vbase_path (code, type, expr, path, alias_this)
path = BINFO_INHERITANCE_CHAIN (path);
}
path = reverse_path;
+ pop_obstacks ();
}
basetype = BINFO_TYPE (path);
@@ -230,11 +296,10 @@ build_vbase_path (code, type, expr, path, alias_this)
if (changed)
{
- extern int flag_assume_nonnull_objects;
tree ind;
/* We already check for ambiguous things in the caller, just
- find a path. */
+ find a path. */
if (last)
{
tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (nonnull_expr))), 0);
@@ -278,7 +343,8 @@ build_vbase_path (code, type, expr, path, alias_this)
if (null_expr)
{
TREE_OPERAND (expr, 2) = nonnull_expr;
- TREE_TYPE (TREE_OPERAND (expr, 1)) = TREE_TYPE (nonnull_expr);
+ TREE_TYPE (expr) = TREE_TYPE (TREE_OPERAND (expr, 1))
+ = TREE_TYPE (nonnull_expr);
}
else
expr = nonnull_expr;
@@ -310,8 +376,11 @@ build_vbase_path (code, type, expr, path, alias_this)
if (TREE_INT_CST_LOW (offset))
{
/* Bash types to make the backend happy. */
- offset = convert (type, offset);
+ offset = cp_convert (type, offset);
+#if 0
+ /* This shouldn't be necessary. (mrs) */
expr = build1 (NOP_EXPR, type, expr);
+#endif
/* For multiple inheritance: if `this' can be set by any
function, then it could be 0 on entry to any function.
@@ -349,27 +418,20 @@ build_vbase_path (code, type, expr, path, alias_this)
/* Virtual function things. */
-/* Virtual functions to be dealt with after laying out our base
- classes. We do all overrides after we layout virtual base classes.
- */
-static tree pending_hard_virtuals;
-static int doing_hard_virtuals;
-
/* Build an entry in the virtual function table.
DELTA is the offset for the `this' pointer.
PFN is an ADDR_EXPR containing a pointer to the virtual function.
Note that the index (DELTA2) in the virtual function table
is always 0. */
-tree
+
+static tree
build_vtable_entry (delta, pfn)
tree delta, pfn;
{
-
if (flag_vtable_thunks)
{
HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta);
- extern tree make_thunk ();
- if (idelta)
+ if (idelta && ! DECL_ABSTRACT_VIRTUAL_P (TREE_OPERAND (pfn, 0)))
{
pfn = build1 (ADDR_EXPR, vtable_entry_type,
make_thunk (pfn, idelta));
@@ -384,25 +446,23 @@ build_vtable_entry (delta, pfn)
else
{
extern int flag_huge_objects;
- tree elems = tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, integer_zero_node,
- build_tree_list (NULL_TREE, pfn)));
+ tree elems = expr_tree_cons (NULL_TREE, delta,
+ expr_tree_cons (NULL_TREE, integer_zero_node,
+ build_expr_list (NULL_TREE, pfn)));
tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
- /* DELTA is constructed by `size_int', which means it may be an
- unsigned quantity on some platforms. Therefore, we cannot use
- `int_fits_type_p', because when DELTA is really negative,
- `force_fit_type' will make it look like a very large number. */
-
- if ((TREE_INT_CST_LOW (TYPE_MAX_VALUE (delta_type_node))
- < TREE_INT_CST_LOW (delta))
- || (TREE_INT_CST_LOW (delta)
- < TREE_INT_CST_LOW (TYPE_MIN_VALUE (delta_type_node))))
- if (flag_huge_objects)
- sorry ("object size exceeds built-in limit for virtual function table implementation");
- else
- sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");
+ /* DELTA used to be constructed by `size_int' and/or size_binop,
+ which caused overflow problems when it was negative. That should
+ be fixed now. */
+ if (! int_fits_type_p (delta, delta_type_node))
+ {
+ if (flag_huge_objects)
+ sorry ("object size exceeds built-in limit for virtual function table implementation");
+ else
+ sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");
+ }
+
TREE_CONSTANT (entry) = 1;
TREE_STATIC (entry) = 1;
TREE_READONLY (entry) = 1;
@@ -416,22 +476,21 @@ build_vtable_entry (delta, pfn)
}
/* Given an object INSTANCE, return an expression which yields the
- virtual function corresponding to INDEX. There are many special
- cases for INSTANCE which we take care of here, mainly to avoid
- creating extra tree nodes when we don't have to. */
+ virtual function vtable element corresponding to INDEX. There are
+ many special cases for INSTANCE which we take care of here, mainly
+ to avoid creating extra tree nodes when we don't have to. */
+
tree
-build_vfn_ref (ptr_to_instptr, instance, idx)
- tree *ptr_to_instptr, instance;
- tree idx;
+build_vtbl_ref (instance, idx)
+ tree instance, idx;
{
- extern int building_cleanup;
tree vtbl, aref;
tree basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
- if (instance == C_C_D)
+ if (instance == current_class_ref)
vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
NULL_PTR);
else
@@ -479,34 +538,53 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
- /* Save the intermediate result in a SAVE_EXPR so we don't have to
- compute each component of the virtual function pointer twice. */
- if (!building_cleanup && TREE_CODE (aref) == INDIRECT_REF)
- TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
+ return aref;
+}
+/* Given an object INSTANCE, return an expression which yields the
+ virtual function corresponding to INDEX. There are many special
+ cases for INSTANCE which we take care of here, mainly to avoid
+ creating extra tree nodes when we don't have to. */
+
+tree
+build_vfn_ref (ptr_to_instptr, instance, idx)
+ tree *ptr_to_instptr, instance;
+ tree idx;
+{
+ tree aref = build_vtbl_ref (instance, idx);
+
+ /* When using thunks, there is no extra delta, and we get the pfn
+ directly. */
if (flag_vtable_thunks)
return aref;
- else
+
+ if (ptr_to_instptr)
{
- if (ptr_to_instptr)
- *ptr_to_instptr
- = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
- *ptr_to_instptr,
- convert (ptrdiff_type_node,
- build_component_ref (aref, delta_identifier, 0, 0)));
- return build_component_ref (aref, pfn_identifier, 0, 0);
+ /* Save the intermediate result in a SAVE_EXPR so we don't have to
+ compute each component of the virtual function pointer twice. */
+ if (TREE_CODE (aref) == INDIRECT_REF)
+ TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
+
+ *ptr_to_instptr
+ = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
+ *ptr_to_instptr,
+ cp_convert (ptrdiff_type_node,
+ build_component_ref (aref, delta_identifier, NULL_TREE, 0)));
}
+
+ return build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
}
/* Return the name of the virtual function table (as an IDENTIFIER_NODE)
for the given TYPE. */
+
static tree
get_vtable_name (type)
tree type;
{
tree type_id = build_typename_overload (type);
- char *buf = (char *)alloca (strlen (VTABLE_NAME_FORMAT)
- + IDENTIFIER_LENGTH (type_id) + 2);
+ char *buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT)
+ + IDENTIFIER_LENGTH (type_id) + 2);
char *ptr = IDENTIFIER_POINTER (type_id);
int i;
for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ;
@@ -522,10 +600,79 @@ get_vtable_name (type)
return get_identifier (buf);
}
+/* Return the offset to the main vtable for a given base BINFO. */
+
+tree
+get_vfield_offset (binfo)
+ tree binfo;
+{
+ tree tmp
+ = size_binop (FLOOR_DIV_EXPR,
+ DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),
+ size_int (BITS_PER_UNIT));
+ tmp = convert (sizetype, tmp);
+ return size_binop (PLUS_EXPR, tmp, BINFO_OFFSET (binfo));
+}
+
+/* Get the offset to the start of the original binfo that we derived
+ this binfo from. If we find TYPE first, return the offset only
+ that far. The shortened search is useful because the this pointer
+ on method calling is expected to point to a DECL_CONTEXT (fndecl)
+ object, and not a baseclass of it. */
+
+static tree
+get_derived_offset (binfo, type)
+ tree binfo, type;
+{
+ tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
+ tree offset2;
+ int i;
+ while (BINFO_BASETYPES (binfo)
+ && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
+ {
+ tree binfos = BINFO_BASETYPES (binfo);
+ if (BINFO_TYPE (binfo) == type)
+ break;
+ binfo = TREE_VEC_ELT (binfos, i);
+ }
+ offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
+ return size_binop (MINUS_EXPR, offset1, offset2);
+}
+
+/* Update the rtti info for this class. */
+
+static void
+set_rtti_entry (virtuals, offset, type)
+ tree virtuals, offset, type;
+{
+ tree vfn;
+
+ if (flag_rtti)
+ vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type));
+ else
+ vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, size_zero_node);
+ TREE_CONSTANT (vfn) = 1;
+
+ if (! flag_vtable_thunks)
+ TREE_VALUE (virtuals) = build_vtable_entry (offset, vfn);
+ else
+ {
+ tree voff = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
+ TREE_CONSTANT (voff) = 1;
+
+ TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, voff);
+
+ /* The second slot is for the tdesc pointer when thunks are used. */
+ TREE_VALUE (TREE_CHAIN (virtuals))
+ = build_vtable_entry (integer_zero_node, vfn);
+ }
+}
+
/* Build a virtual function for type TYPE.
If BINFO is non-NULL, build the vtable starting with the initial
approximation that it is the same as the one which is the head of
the association list. */
+
static tree
build_vtable (binfo, type)
tree binfo, type;
@@ -535,8 +682,15 @@ build_vtable (binfo, type)
if (binfo)
{
+ tree offset;
+
virtuals = copy_list (BINFO_VIRTUALS (binfo));
decl = build_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo)));
+
+ /* Now do rtti stuff. */
+ offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);
+ offset = ssize_binop (MINUS_EXPR, integer_zero_node, offset);
+ set_rtti_entry (virtuals, offset, type);
}
else
{
@@ -552,12 +706,14 @@ build_vtable (binfo, type)
/* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */
import_export_vtable (decl, type, 0);
- IDENTIFIER_GLOBAL_VALUE (name) = decl = pushdecl_top_level (decl);
+ decl = pushdecl_top_level (decl);
+ SET_IDENTIFIER_GLOBAL_VALUE (name, decl);
/* Initialize the association list for this type, based
on our first approximation. */
TYPE_BINFO_VTABLE (type) = decl;
TYPE_BINFO_VIRTUALS (type) = virtuals;
+ DECL_ARTIFICIAL (decl) = 1;
TREE_STATIC (decl) = 1;
#ifndef WRITABLE_VTABLES
/* Make them READONLY by default. (mrs) */
@@ -578,124 +734,124 @@ build_vtable (binfo, type)
return decl;
}
-/* Given a base type PARENT, and a derived type TYPE, build
- a name which distinguishes exactly the PARENT member of TYPE's type.
-
- FORMAT is a string which controls how sprintf formats the name
- we have generated.
+extern tree signed_size_zero_node;
- For example, given
-
- class A; class B; class C : A, B;
+/* 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
+ share a lot of structure.
- it is possible to distinguish "A" from "C's A". And given
+ FOR_TYPE is the derived type which caused this table to
+ be needed.
- class L;
- class A : L; class B : L; class C : A, B;
+ BINFO is the type association which provided TYPE for FOR_TYPE.
- it is possible to distinguish "L" from "A's L", and also from
- "C's L from A".
+ The order in which vtables are built (by calling this function) for
+ an object must remain the same, otherwise a binary incompatibility
+ can result. */
- Make sure to use the DECL_ASSEMBLER_NAME of the TYPE_NAME of the
- type, as template have DECL_NAMEs like: X<int>, whereas the
- DECL_ASSEMBLER_NAME is set to be something the assembler can handle.
- */
-static tree
-build_type_pathname (format, parent, type)
- char *format;
- tree parent, type;
+static void
+prepare_fresh_vtable (binfo, for_type)
+ tree binfo, for_type;
{
- extern struct obstack temporary_obstack;
- char *first, *base, *name;
+ tree basetype;
+ tree orig_decl = BINFO_VTABLE (binfo);
+ tree name;
+ tree new_decl;
+ tree offset;
+ tree path = binfo;
+ char *buf, *buf2;
+ char joiner = '_';
int i;
- tree id;
-
- parent = TYPE_MAIN_VARIANT (parent);
- /* Remember where to cut the obstack to. */
- first = obstack_base (&temporary_obstack);
-
- /* Put on TYPE+PARENT. */
- obstack_grow (&temporary_obstack,
- TYPE_ASSEMBLER_NAME_STRING (type),
- TYPE_ASSEMBLER_NAME_LENGTH (type));
#ifdef JOINER
- obstack_1grow (&temporary_obstack, JOINER);
-#else
- obstack_1grow (&temporary_obstack, '_');
+ joiner = JOINER;
#endif
- obstack_grow0 (&temporary_obstack,
- TYPE_ASSEMBLER_NAME_STRING (parent),
- TYPE_ASSEMBLER_NAME_LENGTH (parent));
- i = obstack_object_size (&temporary_obstack);
- base = obstack_base (&temporary_obstack);
- obstack_finish (&temporary_obstack);
-
- /* Put on FORMAT+TYPE+PARENT. */
- obstack_blank (&temporary_obstack, strlen (format) + i + 1);
- name = obstack_base (&temporary_obstack);
- sprintf (name, format, base);
- id = get_identifier (name);
- obstack_free (&temporary_obstack, first);
-
- 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
+ basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (binfo));
+
+ buf2 = TYPE_ASSEMBLER_NAME_STRING (basetype);
+ i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1;
+
+ /* We know that the vtable that we are going to create doesn't exist
+ yet in the global namespace, and when we finish, it will be
+ pushed into the global namespace. In complex MI hierarchies, we
+ have to loop while the name we are thinking of adding is globally
+ defined, adding more name components to the vtable name as we
+ loop, until the name is unique. This is because in complex MI
+ cases, we might have the same base more than once. This means
+ that the order in which this function is called for vtables must
+ remain the same, otherwise binary compatibility can be
+ compromised. */
+
+ while (1)
{
- tree vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
- TREE_CONSTANT (vfn) = 1;
+ char *buf1 = (char *) alloca (TYPE_ASSEMBLER_NAME_LENGTH (for_type)
+ + 1 + i);
+ char *new_buf2;
- 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;
+ sprintf (buf1, "%s%c%s", TYPE_ASSEMBLER_NAME_STRING (for_type), joiner,
+ buf2);
+ buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT) + strlen (buf1) + 1);
+ sprintf (buf, VTABLE_NAME_FORMAT, buf1);
+ name = get_identifier (buf);
- TREE_VALUE (TREE_CHAIN (virtuals))
- = build_vtable_entry (integer_zero_node, vfn);
- }
-}
+ /* If this name doesn't clash, then we can use it, otherwise
+ we add more to the name until it is unique. */
-/* 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
- share a lot of structure.
+ if (! IDENTIFIER_GLOBAL_VALUE (name))
+ break;
- FOR_TYPE is the derived type which caused this table to
- be needed.
+ /* Set values for next loop through, if the name isn't unique. */
- BINFO is the type association which provided TYPE for FOR_TYPE. */
-static void
-prepare_fresh_vtable (binfo, for_type)
- tree binfo, for_type;
-{
- tree basetype = BINFO_TYPE (binfo);
- tree orig_decl = BINFO_VTABLE (binfo);
- /* This name is too simplistic. We can have multiple basetypes for
- for_type, and we really want different names. (mrs) */
- tree name = build_type_pathname (VTABLE_NAME_FORMAT, basetype, for_type);
- tree new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
- tree path, offset;
- int result;
+ path = BINFO_INHERITANCE_CHAIN (path);
+
+ /* We better not run out of stuff to make it unique. */
+ my_friendly_assert (path != NULL_TREE, 368);
+
+ basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (path));
+
+ if (for_type == basetype)
+ {
+ /* If we run out of basetypes in the path, we have already
+ found created a vtable with that name before, we now
+ resort to tacking on _%d to distinguish them. */
+ int j = 2;
+ i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1 + i + 1 + 3;
+ buf1 = (char *) alloca (i);
+ do {
+ sprintf (buf1, "%s%c%s%c%d",
+ TYPE_ASSEMBLER_NAME_STRING (basetype), joiner,
+ buf2, joiner, j);
+ buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT)
+ + strlen (buf1) + 1);
+ sprintf (buf, VTABLE_NAME_FORMAT, buf1);
+ name = get_identifier (buf);
+
+ /* If this name doesn't clash, then we can use it,
+ otherwise we add something different to the name until
+ it is unique. */
+ } while (++j <= 999 && IDENTIFIER_GLOBAL_VALUE (name));
+
+ /* Hey, they really like MI don't they? Increase the 3
+ above to 6, and the 999 to 999999. :-) */
+ my_friendly_assert (j <= 999, 369);
+ break;
+ }
+
+ i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1 + i;
+ new_buf2 = (char *) alloca (i);
+ sprintf (new_buf2, "%s%c%s",
+ TYPE_ASSEMBLER_NAME_STRING (basetype), joiner, buf2);
+ buf2 = new_buf2;
+ }
+
+ new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
/* Remember which class this vtable is really for. */
DECL_CONTEXT (new_decl) = for_type;
+ DECL_ARTIFICIAL (new_decl) = 1;
TREE_STATIC (new_decl) = 1;
BINFO_VTABLE (binfo) = pushdecl_top_level (new_decl);
DECL_VIRTUAL_P (new_decl) = 1;
@@ -709,13 +865,23 @@ prepare_fresh_vtable (binfo, for_type)
BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
if (TREE_VIA_VIRTUAL (binfo))
- offset = BINFO_OFFSET (binfo_member (BINFO_TYPE (binfo),
- CLASSTYPE_VBASECLASSES (for_type)));
+ {
+ tree binfo1 = binfo_member (BINFO_TYPE (binfo),
+ CLASSTYPE_VBASECLASSES (for_type));
+
+ /* XXX - This should never happen, if it does, the caller should
+ ensure that the binfo is from for_type's binfos, not from any
+ base type's. We can remove all this code after a while. */
+ if (binfo1 != binfo)
+ warning ("internal inconsistency: binfo offset error for rtti");
+
+ offset = BINFO_OFFSET (binfo1);
+ }
else
offset = BINFO_OFFSET (binfo);
set_rtti_entry (BINFO_VIRTUALS (binfo),
- size_binop (MINUS_EXPR, integer_zero_node, offset),
+ ssize_binop (MINUS_EXPR, integer_zero_node, offset),
for_type);
#ifdef GATHER_STATISTICS
@@ -733,10 +899,12 @@ prepare_fresh_vtable (binfo, for_type)
SET_BINFO_NEW_VTABLE_MARKED (binfo);
}
+#if 0
/* Access the virtual function table entry that logically
contains BASE_FNDECL. VIRTUALS is the virtual function table's
initializer. We can run off the end, when dealing with virtual
destructors in MI situations, return NULL_TREE in that case. */
+
static tree
get_vtable_entry (virtuals, base_fndecl)
tree virtuals, base_fndecl;
@@ -757,6 +925,7 @@ get_vtable_entry (virtuals, base_fndecl)
}
return virtuals;
}
+#endif
/* Put new entry ENTRY into virtual function table initializer
VIRTUALS.
@@ -776,7 +945,7 @@ modify_vtable_entry (old_entry_in_list, new_entry, fndecl)
TREE_VALUE (old_entry_in_list) = new_entry;
/* Now assign virtual dispatch information, if unset. */
- /* We can dispatch this, through any overridden base function. */
+ /* We can dispatch this, through any overridden base function. */
if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
{
DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
@@ -784,8 +953,9 @@ modify_vtable_entry (old_entry_in_list, new_entry, fndecl)
}
}
-/* Access the virtual function table entry i. VIRTUALS is the virtual
+/* Access the virtual function table entry N. VIRTUALS is the virtual
function table's initializer. */
+
static tree
get_vtable_entry_n (virtuals, n)
tree virtuals;
@@ -806,13 +976,17 @@ get_vtable_entry_n (virtuals, n)
HAS_VIRTUAL keeps track of how many virtuals there are in our main
vtable for the type, and we build upon the PENDING_VIRTUALS list
and return it. */
-static tree
-add_virtual_function (pending_virtuals, has_virtual, fndecl, t)
- tree pending_virtuals;
+
+static void
+add_virtual_function (pv, phv, has_virtual, fndecl, t)
+ tree *pv, *phv;
int *has_virtual;
tree fndecl;
- tree t; /* Structure type. */
+ tree t; /* Structure type. */
{
+ tree pending_virtuals = *pv;
+ tree pending_hard_virtuals = *phv;
+
/* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely
convert to void *. Make such a conversion here. */
tree vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
@@ -835,11 +1009,8 @@ add_virtual_function (pending_virtuals, has_virtual, fndecl, t)
{
tree entry;
- if (flag_rtti && *has_virtual == 0)
- {
- /* CLASSTYPE_RTTI is only used as a Boolean (NULL or not). */
- CLASSTYPE_RTTI (t) = integer_one_node;
- }
+ /* We remember that this was the base sub-object for rtti. */
+ CLASSTYPE_RTTI (t) = t;
/* If we are using thunks, use two slots at the front, one
for the offset pointer, one for the tdesc pointer. */
@@ -851,21 +1022,21 @@ add_virtual_function (pending_virtuals, has_virtual, fndecl, t)
/* Build a new INT_CST for this DECL_VINDEX. */
{
static tree index_table[256];
- tree index;
+ tree idx;
/* We skip a slot for the offset/tdesc entry. */
int i = ++(*has_virtual);
if (i >= 256 || index_table[i] == 0)
{
- index = build_int_2 (i, 0);
+ idx = build_int_2 (i, 0);
if (i < 256)
- index_table[i] = index;
+ index_table[i] = idx;
}
else
- index = index_table[i];
+ idx = index_table[i];
- /* Now assign virtual dispatch information. */
- DECL_VINDEX (fndecl) = index;
+ /* Now assign virtual dispatch information. */
+ DECL_VINDEX (fndecl) = idx;
DECL_CONTEXT (fndecl) = t;
}
entry = build_vtable_entry (integer_zero_node, vfn);
@@ -879,7 +1050,8 @@ add_virtual_function (pending_virtuals, has_virtual, fndecl, t)
Deal with this after we have laid out our virtual base classes. */
pending_hard_virtuals = temp_tree_cons (fndecl, vfn, pending_hard_virtuals);
}
- return pending_virtuals;
+ *pv = pending_virtuals;
+ *phv = pending_hard_virtuals;
}
/* Obstack on which to build the vector of class methods. */
@@ -892,39 +1064,30 @@ extern struct obstack *current_obstack;
FIELDS is the entry in the METHOD_VEC vector entry of the class type where
the method should be added. */
+
void
add_method (type, fields, method)
tree type, *fields, method;
{
- /* We must make a copy of METHOD here, since we must be sure that
- we have exclusive title to this method's DECL_CHAIN. */
- tree decl;
-
push_obstacks (&permanent_obstack, &permanent_obstack);
- {
- decl = copy_node (method);
- if (DECL_RTL (decl) == 0
- && (!processing_template_decl
- || !uses_template_parms (decl)))
- {
- make_function_rtl (decl);
- DECL_RTL (method) = DECL_RTL (decl);
- }
- }
if (fields && *fields)
- {
- /* Take care not to hide destructor. */
- DECL_CHAIN (decl) = DECL_CHAIN (*fields);
- DECL_CHAIN (*fields) = decl;
- }
+ *fields = build_overload (method, *fields);
else if (CLASSTYPE_METHOD_VEC (type) == 0)
{
tree method_vec = make_node (TREE_VEC);
- if (TYPE_IDENTIFIER (type) == DECL_NAME (decl))
+ if (TYPE_IDENTIFIER (type) == DECL_NAME (method))
{
- TREE_VEC_ELT (method_vec, 0) = decl;
- TREE_VEC_LENGTH (method_vec) = 1;
+ /* ??? Is it possible for there to have been enough room in the
+ current chunk for the tree_vec structure but not a tree_vec
+ plus a tree*? Will this work in that case? */
+ obstack_free (current_obstack, method_vec);
+ obstack_blank (current_obstack, sizeof (struct tree_vec) + sizeof (tree *));
+ if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)))
+ TREE_VEC_ELT (method_vec, 1) = method;
+ else
+ TREE_VEC_ELT (method_vec, 0) = method;
+ TREE_VEC_LENGTH (method_vec) = 2;
}
else
{
@@ -932,9 +1095,9 @@ add_method (type, fields, method)
current chunk for the tree_vec structure but not a tree_vec
plus a tree*? Will this work in that case? */
obstack_free (current_obstack, method_vec);
- obstack_blank (current_obstack, sizeof (struct tree_vec) + sizeof (tree *));
- TREE_VEC_ELT (method_vec, 1) = decl;
- TREE_VEC_LENGTH (method_vec) = 2;
+ obstack_blank (current_obstack, sizeof (struct tree_vec) + 2*sizeof (tree *));
+ TREE_VEC_ELT (method_vec, 2) = method;
+ TREE_VEC_LENGTH (method_vec) = 3;
obstack_finish (current_obstack);
}
CLASSTYPE_METHOD_VEC (type) = method_vec;
@@ -946,14 +1109,13 @@ add_method (type, fields, method)
/* Adding a new ctor or dtor. This is easy because our
METHOD_VEC always has a slot for such entries. */
- if (TYPE_IDENTIFIER (type) == DECL_NAME (decl))
+ if (TYPE_IDENTIFIER (type) == DECL_NAME (method))
{
- /* TREE_VEC_ELT (method_vec, 0) = decl; */
- if (decl != TREE_VEC_ELT (method_vec, 0))
- {
- DECL_CHAIN (decl) = TREE_VEC_ELT (method_vec, 0);
- TREE_VEC_ELT (method_vec, 0) = decl;
- }
+ int idx = !!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method));
+ /* TREE_VEC_ELT (method_vec, idx) = method; */
+ if (method != TREE_VEC_ELT (method_vec, idx))
+ TREE_VEC_ELT (method_vec, idx) =
+ build_overload (method, TREE_VEC_ELT (method_vec, idx));
}
else
{
@@ -992,7 +1154,7 @@ add_method (type, fields, method)
}
obstack_finish (ob);
- TREE_VEC_ELT (method_vec, len) = decl;
+ TREE_VEC_ELT (method_vec, len) = method;
TREE_VEC_LENGTH (method_vec) = len + 1;
CLASSTYPE_METHOD_VEC (type) = method_vec;
@@ -1009,8 +1171,8 @@ add_method (type, fields, method)
}
}
}
- DECL_CONTEXT (decl) = type;
- DECL_CLASS_CONTEXT (decl) = type;
+ DECL_CONTEXT (method) = type;
+ DECL_CLASS_CONTEXT (method) = type;
pop_obstacks ();
}
@@ -1030,6 +1192,7 @@ add_method (type, fields, method)
Note that anonymous fields which are not of UNION_TYPE are
not duplicates, they are just anonymous fields. This happens
when we have unnamed bitfields, for example. */
+
static tree
delete_duplicate_fields_1 (field, fields)
tree field, fields;
@@ -1074,13 +1237,25 @@ delete_duplicate_fields_1 (field, fields)
|| TREE_CODE (x) == CONST_DECL)
cp_error_at ("duplicate field `%D' (as enum and non-enum)",
x);
- else if (TREE_CODE (field) == TYPE_DECL
- && TREE_CODE (x) == TYPE_DECL)
- cp_error_at ("duplicate nested type `%D'", x);
- else if (TREE_CODE (field) == TYPE_DECL
- || TREE_CODE (x) == TYPE_DECL)
- cp_error_at ("duplicate field `%D' (as type and non-type)",
- x);
+ else if (DECL_DECLARES_TYPE_P (field)
+ && DECL_DECLARES_TYPE_P (x))
+ {
+ if (comptypes (TREE_TYPE (field), TREE_TYPE (x), 1))
+ continue;
+ cp_error_at ("duplicate nested type `%D'", x);
+ }
+ else if (DECL_DECLARES_TYPE_P (field)
+ || DECL_DECLARES_TYPE_P (x))
+ {
+ /* Hide tag decls. */
+ if ((TREE_CODE (field) == TYPE_DECL
+ && DECL_ARTIFICIAL (field))
+ || (TREE_CODE (x) == TYPE_DECL
+ && DECL_ARTIFICIAL (x)))
+ continue;
+ cp_error_at ("duplicate field `%D' (as type and non-type)",
+ x);
+ }
else
cp_error_at ("duplicate member `%D'", x);
if (prev == 0)
@@ -1103,85 +1278,135 @@ delete_duplicate_fields (fields)
TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x));
}
-/* Change the access of FDECL to ACCESS in T.
- Return 1 if change was legit, otherwise return 0. */
+/* Change the access of FDECL to ACCESS in T. The access to FDECL is
+ along the path given by BINFO. Return 1 if change was legit,
+ otherwise return 0. */
+
static int
-alter_access (t, fdecl, access)
+alter_access (t, binfo, fdecl, access)
tree t;
+ tree binfo;
tree fdecl;
- enum access_type access;
+ tree access;
{
tree elem = purpose_member (t, DECL_ACCESS (fdecl));
- if (elem && TREE_VALUE (elem) != (tree)access)
+ if (elem)
{
- if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL)
+ if (TREE_VALUE (elem) != access)
{
- cp_error_at ("conflicting access specifications for method `%D', ignored", TREE_TYPE (fdecl));
+ if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL)
+ cp_error_at ("conflicting access specifications for method `%D', ignored", TREE_TYPE (fdecl));
+ else
+ error ("conflicting access specifications for field `%s', ignored",
+ IDENTIFIER_POINTER (DECL_NAME (fdecl)));
}
else
- error ("conflicting access specifications for field `%s', ignored",
- IDENTIFIER_POINTER (DECL_NAME (fdecl)));
- }
- else if (TREE_PRIVATE (fdecl))
- {
- if (access != access_private)
- cp_error_at ("cannot make private `%D' non-private", fdecl);
- goto alter;
- }
- else if (TREE_PROTECTED (fdecl))
- {
- if (access != access_protected)
- cp_error_at ("cannot make protected `%D' non-protected", fdecl);
- goto alter;
+ {
+ /* They're changing the access to the same thing they changed
+ it to before. That's OK. */
+ ;
+ }
}
- /* ARM 11.3: an access declaration may not be used to restrict access
- to a member that is accessible in the base class. */
- else if (access != access_public)
- cp_error_at ("cannot reduce access of public member `%D'", fdecl);
- else if (elem == NULL_TREE)
+ else
{
- alter:
- DECL_ACCESS (fdecl) = tree_cons (t, (tree)access,
- DECL_ACCESS (fdecl));
+ enforce_access (binfo, fdecl);
+
+ DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
}
return 0;
}
-/* Return the offset to the main vtable for a given base BINFO. */
-tree
-get_vfield_offset (binfo)
- tree binfo;
-{
- return size_binop (PLUS_EXPR,
- size_binop (FLOOR_DIV_EXPR,
- DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),
- size_int (BITS_PER_UNIT)),
- BINFO_OFFSET (binfo));
-}
+/* Process the USING_DECL, which is a member of T. The METHOD_VEC, if
+ non-NULL, is the methods of T. The FIELDS are the fields of T.
+ Returns 1 if the USING_DECL was valid, 0 otherwise. */
-/* Get the offset to the start of the original binfo that we derived
- this binfo from. If we find TYPE first, return the offset only
- that far. The shortened search is useful because the this pointer
- on method calling is expected to point to a DECL_CONTEXT (fndecl)
- object, and not a baseclass of it. */
-static tree
-get_derived_offset (binfo, type)
- tree binfo, type;
+void
+handle_using_decl (using_decl, t, method_vec, fields)
+ tree using_decl;
+ tree t;
+ tree method_vec;
+ tree fields;
{
- tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
- tree offset2;
+ tree ctype = DECL_INITIAL (using_decl);
+ tree name = DECL_NAME (using_decl);
+ tree access
+ = TREE_PRIVATE (using_decl) ? access_private_node
+ : TREE_PROTECTED (using_decl) ? access_protected_node
+ : access_public_node;
+ tree fdecl, binfo;
+ tree flist = NULL_TREE;
+ tree tmp;
int i;
- while (BINFO_BASETYPES (binfo)
- && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
+ int n_methods;
+
+ binfo = binfo_or_else (ctype, t);
+ if (! binfo)
+ return;
+
+ if (name == constructor_name (ctype)
+ || name == constructor_name_full (ctype))
+ cp_error_at ("using-declaration for constructor", using_decl);
+
+ fdecl = lookup_member (binfo, name, 0, 0);
+
+ if (!fdecl)
{
- tree binfos = BINFO_BASETYPES (binfo);
- if (BINFO_TYPE (binfo) == type)
- break;
- binfo = TREE_VEC_ELT (binfos, i);
+ cp_error_at ("no members matching `%D' in `%#T'", using_decl, ctype);
+ return;
}
- offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
- return size_binop (MINUS_EXPR, offset1, offset2);
+
+ /* Functions are represented as TREE_LIST, with the purpose
+ being the type and the value the functions. Other members
+ come as themselves. */
+ if (TREE_CODE (fdecl) == TREE_LIST)
+ /* Ignore base type this came from. */
+ fdecl = TREE_VALUE (fdecl);
+
+ if (TREE_CODE (fdecl) == OVERLOAD)
+ {
+ /* We later iterate over all functions. */
+ flist = fdecl;
+ fdecl = OVL_FUNCTION (flist);
+ }
+
+ name = DECL_NAME (fdecl);
+ n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
+ for (i = 2; i < n_methods; i++)
+ if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)))
+ == name)
+ {
+ cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
+ cp_error_at (" because of local method `%#D' with same name",
+ OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
+ return;
+ }
+
+ if (! DECL_LANG_SPECIFIC (fdecl))
+ /* We don't currently handle DECL_ACCESS for TYPE_DECLs; just return. */
+ return;
+
+ for (tmp = fields; tmp; tmp = TREE_CHAIN (tmp))
+ if (DECL_NAME (tmp) == name)
+ {
+ cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
+ cp_error_at (" because of local field `%#D' with same name", tmp);
+ return;
+ }
+
+ /* Make type T see field decl FDECL with access ACCESS.*/
+ if (flist)
+ {
+ while (flist)
+ {
+ if (alter_access (t, binfo, OVL_FUNCTION (flist),
+ access) == 0)
+ return;
+ flist = OVL_CHAIN (flist);
+ }
+ }
+ else
+ alter_access (t, binfo, fdecl, access);
}
/* If FOR_TYPE needs to reinitialize virtual function table pointers
@@ -1202,7 +1427,7 @@ maybe_fixup_vptrs (for_type, binfo, base_init_list)
: VF_BASETYPE_VALUE (vfields);
tree base_binfo = get_binfo (basetype, for_type, 0);
- /* Punt until this is implemented. */
+ /* Punt until this is implemented. */
if (1 /* BINFO_MODIFIED (base_binfo) */)
{
tree base_offset = get_vfield_offset (base_binfo);
@@ -1335,10 +1560,13 @@ build_class_init_list (type)
}
if (base_init_list)
- if (member_init_list)
- CLASSTYPE_BASE_INIT_LIST (type) = build_tree_list (base_init_list, member_init_list);
- else
- CLASSTYPE_BASE_INIT_LIST (type) = base_init_list;
+ {
+ if (member_init_list)
+ CLASSTYPE_BASE_INIT_LIST (type) =
+ build_tree_list (base_init_list, member_init_list);
+ else
+ CLASSTYPE_BASE_INIT_LIST (type) = base_init_list;
+ }
else if (member_init_list)
CLASSTYPE_BASE_INIT_LIST (type) = member_init_list;
}
@@ -1350,12 +1578,10 @@ struct base_info
int n_ancestors;
tree vfield;
tree vfields;
+ tree rtti;
char cant_have_default_ctor;
char cant_have_const_ctor;
- char cant_synth_copy_ctor;
- char cant_synth_asn_ref;
char no_const_asn_ref;
- char needs_virtual_dtor;
};
/* Record information about type T derived from its base classes.
@@ -1372,17 +1598,14 @@ struct base_info
offsets include that offset in theirs.
Returns the index of the first base class to have virtual functions,
- or -1 if no such base class.
-
- Note that at this point TYPE_BINFO (t) != t_binfo. */
+ or -1 if no such base class. */
static int
-finish_base_struct (t, b, t_binfo)
+finish_base_struct (t, b)
tree t;
struct base_info *b;
- tree t_binfo;
{
- tree binfos = BINFO_BASETYPES (t_binfo);
+ tree binfos = TYPE_BINFO_BASETYPES (t);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
int first_vfn_base_index = -1;
bzero ((char *) b, sizeof (struct base_info));
@@ -1392,6 +1615,13 @@ finish_base_struct (t, b, t_binfo)
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree basetype = BINFO_TYPE (base_binfo);
+ /* Effective C++ rule 14. We only need to check TYPE_VIRTUAL_P
+ here because the case of virtual functions but non-virtual
+ dtor is handled in finish_struct_1. */
+ if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype)
+ && TYPE_HAS_DESTRUCTOR (basetype))
+ cp_warning ("base class `%#T' has a non-virtual destructor", basetype);
+
/* If the type of basetype is incomplete, then
we already complained about that fact
(and we should have fixed it up as well). */
@@ -1409,13 +1639,8 @@ finish_base_struct (t, b, t_binfo)
TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);
}
- if (TYPE_HAS_INIT_REF (basetype)
- && !TYPE_HAS_CONST_INIT_REF (basetype))
+ if (! TYPE_HAS_CONST_INIT_REF (basetype))
b->cant_have_const_ctor = 1;
- if (! TYPE_HAS_INIT_REF (basetype)
- || (TYPE_HAS_NONPUBLIC_CTOR (basetype) == 2
- && ! is_friend_type (t, basetype)))
- b->cant_synth_copy_ctor = 1;
if (TYPE_HAS_CONSTRUCTOR (basetype)
&& ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype))
@@ -1432,11 +1657,6 @@ finish_base_struct (t, b, t_binfo)
if (TYPE_HAS_ASSIGN_REF (basetype)
&& !TYPE_HAS_CONST_ASSIGN_REF (basetype))
b->no_const_asn_ref = 1;
- if (! TYPE_HAS_ASSIGN_REF (basetype)
- || TYPE_HAS_ABSTRACT_ASSIGN_REF (basetype)
- || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (basetype) == 2
- && ! is_friend_type (t, basetype)))
- b->cant_synth_asn_ref = 1;
b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype);
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
@@ -1448,52 +1668,15 @@ finish_base_struct (t, b, t_binfo)
TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
- if (! TREE_VIA_VIRTUAL (base_binfo)
-#if 0
- /* This cannot be done, as prepare_fresh_vtable wants to modify
- binfos associated with vfields anywhere in the hierarchy, not
- just immediate base classes. Due to unsharing, the compiler
- might consume 3% more memory on a real program.
- */
- && ! BINFO_OFFSET_ZEROP (base_binfo)
-#endif
- && BINFO_BASETYPES (base_binfo))
- {
- tree base_binfos = BINFO_BASETYPES (base_binfo);
- tree chain = NULL_TREE;
- int j;
-
- /* Now unshare the structure beneath BASE_BINFO. */
- for (j = TREE_VEC_LENGTH (base_binfos)-1;
- j >= 0; j--)
- {
- tree base_base_binfo = TREE_VEC_ELT (base_binfos, j);
- if (! TREE_VIA_VIRTUAL (base_base_binfo))
- TREE_VEC_ELT (base_binfos, j)
- = make_binfo (BINFO_OFFSET (base_base_binfo),
- base_base_binfo,
- BINFO_VTABLE (base_base_binfo),
- BINFO_VIRTUALS (base_base_binfo),
- chain);
- chain = TREE_VEC_ELT (base_binfos, j);
- TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
- TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
- BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
- }
-
- /* Completely unshare potentially shared data, and
- update what is ours. */
- propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
- }
-
if (! TREE_VIA_VIRTUAL (base_binfo))
CLASSTYPE_N_SUPERCLASSES (t) += 1;
if (TYPE_VIRTUAL_P (basetype))
{
- /* If there's going to be a destructor needed, make
- sure it will be virtual. */
- b->needs_virtual_dtor = 1;
+ /* Ensure that this is set from at least a virtual base
+ class. */
+ if (b->rtti == NULL_TREE)
+ b->rtti = CLASSTYPE_RTTI (basetype);
/* Don't borrow virtuals from virtual baseclasses. */
if (TREE_VIA_VIRTUAL (base_binfo))
@@ -1507,8 +1690,8 @@ finish_base_struct (t, b, t_binfo)
/* Update these two, now that we know what vtable we are
going to extend. This is so that we can add virtual
functions, and override them properly. */
- BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype);
- BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype);
+ TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
+ TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
b->has_virtual = CLASSTYPE_VSIZE (basetype);
b->vfield = CLASSTYPE_VFIELD (basetype);
b->vfields = copy_list (CLASSTYPE_VFIELDS (basetype));
@@ -1556,8 +1739,8 @@ finish_base_struct (t, b, t_binfo)
/* Update these two, now that we know what vtable we are
going to extend. This is so that we can add virtual
functions, and override them properly. */
- BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype);
- BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype);
+ TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
+ TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
b->has_virtual = CLASSTYPE_VSIZE (basetype);
b->vfield = CLASSTYPE_VFIELD (basetype);
CLASSTYPE_VFIELD (t) = b->vfield;
@@ -1583,33 +1766,31 @@ finish_base_struct (t, b, t_binfo)
}
}
- /* Must come after offsets are fixed for all bases. */
+ /* This comment said "Must come after offsets are fixed for all bases."
+ Well, now this happens before the offsets are fixed, but it seems to
+ work fine. Guess we'll see... */
for (i = 0; i < n_baseclasses; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree basetype = BINFO_TYPE (base_binfo);
- if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2)
+ if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
{
cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
- b->cant_synth_asn_ref = 1;
- b->cant_synth_copy_ctor = 1;
}
}
{
- tree v = get_vbase_types (t_binfo);
+ tree v = get_vbase_types (t);
for (; v; v = TREE_CHAIN (v))
{
tree basetype = BINFO_TYPE (v);
- if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2)
+ if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
{
if (extra_warnings)
cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
- b->cant_synth_asn_ref = 1;
- b->cant_synth_copy_ctor = 1;
}
}
}
@@ -1630,28 +1811,23 @@ finish_base_struct (t, b, t_binfo)
if (b->vfield == 0)
/* If all virtual functions come only from virtual baseclasses. */
return -1;
- return first_vfn_base_index;
-}
-static int
-typecode_p (type, code)
- tree type;
- enum tree_code code;
-{
- return (TREE_CODE (type) == code
- || (TREE_CODE (type) == REFERENCE_TYPE
- && TREE_CODE (TREE_TYPE (type)) == code));
+ /* Update the rtti base if we have a non-virtual base class version
+ of it. */
+ b->rtti = CLASSTYPE_RTTI (BINFO_TYPE (TREE_VEC_ELT (binfos, first_vfn_base_index)));
+
+ return first_vfn_base_index;
}
/* Set memoizing fields and bits of T (and its variants) for later use.
MAX_HAS_VIRTUAL is the largest size of any T's virtual function tables. */
+
static void
finish_struct_bits (t, max_has_virtual)
tree t;
int max_has_virtual;
{
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
- tree method_vec = CLASSTYPE_METHOD_VEC (t);
/* Fix up variants (if any). */
tree variants = TYPE_NEXT_VARIANT (t);
@@ -1670,6 +1846,9 @@ finish_struct_bits (t, max_has_virtual)
/* Copy whatever these are holding today. */
TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t);
TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t);
+ TYPE_FIELDS (variants) = TYPE_FIELDS (t);
+ TYPE_SIZE (variants) = TYPE_SIZE (t);
+ TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (t);
variants = TYPE_NEXT_VARIANT (variants);
}
@@ -1688,7 +1867,7 @@ finish_struct_bits (t, max_has_virtual)
if (might_have_abstract_virtuals)
{
/* We use error_mark_node from override_one_vtable to signal
- an artificial abstract. */
+ an artificial abstract. */
if (CLASSTYPE_ABSTRACT_VIRTUALS (t) == error_mark_node)
CLASSTYPE_ABSTRACT_VIRTUALS (t) = NULL_TREE;
CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t);
@@ -1706,12 +1885,7 @@ finish_struct_bits (t, max_has_virtual)
{
basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
- if (TYPE_HAS_CONVERSION (basetype))
- {
- TYPE_HAS_CONVERSION (t) = 1;
- TYPE_HAS_INT_CONVERSION (t) |= TYPE_HAS_INT_CONVERSION (basetype);
- TYPE_HAS_REAL_CONVERSION (t) |= TYPE_HAS_REAL_CONVERSION (basetype);
- }
+ TYPE_HAS_CONVERSION (t) |= TYPE_HAS_CONVERSION (basetype);
if (CLASSTYPE_MAX_DEPTH (basetype) >= CLASSTYPE_MAX_DEPTH (t))
CLASSTYPE_MAX_DEPTH (t) = CLASSTYPE_MAX_DEPTH (basetype) + 1;
}
@@ -1720,12 +1894,17 @@ finish_struct_bits (t, max_has_virtual)
/* If this type has a copy constructor, force its mode to be BLKmode, and
force its TREE_ADDRESSABLE bit to be nonzero. This will cause it to
be passed by invisible reference and prevent it from being returned in
- a register. */
- if (! TYPE_HAS_TRIVIAL_INIT_REF (t))
+ a register.
+
+ Also do this if the class has BLKmode but can still be returned in
+ registers, since function_cannot_inline_p won't let us inline
+ functions returning such a type. This affects the HP-PA. */
+ if (! TYPE_HAS_TRIVIAL_INIT_REF (t)
+ || (TYPE_MODE (t) == BLKmode && ! aggregate_value_p (t)
+ && CLASSTYPE_NON_AGGREGATE (t)))
{
tree variants;
- if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
- DECL_MODE (TYPE_NAME (t)) = BLKmode;
+ DECL_MODE (TYPE_MAIN_DECL (t)) = BLKmode;
for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants))
{
TYPE_MODE (variants) = BLKmode;
@@ -1734,57 +1913,29 @@ finish_struct_bits (t, max_has_virtual)
}
}
-/* Add FN to the method_vec growing on the class_obstack. Used by
- finish_struct_methods. */
+/* Add FNDECL to the method_vec growing on the class_obstack. Used by
+ finish_struct_methods. Note, FNDECL cannot be a constructor or
+ destructor, those cases are handled by the caller. */
+
static void
-grow_method (fn, method_vec_ptr)
- tree fn;
+grow_method (fndecl, method_vec_ptr)
+ tree fndecl;
tree *method_vec_ptr;
{
tree method_vec = (tree)obstack_base (&class_obstack);
- tree *testp = &TREE_VEC_ELT (method_vec, 0);
- if (*testp == NULL_TREE)
- testp++;
- while (((HOST_WIDE_INT) testp
- < (HOST_WIDE_INT) obstack_next_free (&class_obstack))
- && DECL_NAME (*testp) != DECL_NAME (fn))
+
+ /* Start off past the constructors and destructor. */
+ tree *testp = &TREE_VEC_ELT (method_vec, 2);
+
+ while (testp < (tree *) obstack_next_free (&class_obstack)
+ && (*testp == NULL_TREE || DECL_NAME (OVL_CURRENT (*testp)) != DECL_NAME (fndecl)))
testp++;
- if ((HOST_WIDE_INT) testp
- < (HOST_WIDE_INT) obstack_next_free (&class_obstack))
- {
- tree x, prev_x;
- for (x = *testp; x; x = DECL_CHAIN (x))
- {
- if (DECL_NAME (fn) == ansi_opname[(int) DELETE_EXPR]
- || DECL_NAME (fn) == ansi_opname[(int) VEC_DELETE_EXPR])
- {
- /* ANSI C++ June 5 1992 WP 12.5.5.1 */
- cp_error_at ("`%D' overloaded", fn);
- cp_error_at ("previous declaration as `%D' here", x);
- }
- if (DECL_ASSEMBLER_NAME (fn)==DECL_ASSEMBLER_NAME (x))
- {
- /* We complain about multiple destructors on sight,
- so we do not repeat the warning here. Friend-friend
- ambiguities are warned about outside this loop. */
- if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn)))
- cp_error_at ("ambiguous method `%#D' in structure", fn);
- break;
- }
- prev_x = x;
- }
- if (x == 0)
- {
- if (*testp)
- DECL_CHAIN (prev_x) = fn;
- else
- *testp = fn;
- }
- }
+ if (testp < (tree *) obstack_next_free (&class_obstack))
+ *testp = build_overload (fndecl, *testp);
else
{
- obstack_ptr_grow (&class_obstack, fn);
+ obstack_ptr_grow (&class_obstack, fndecl);
*method_vec_ptr = (tree)obstack_base (&class_obstack);
}
}
@@ -1812,36 +1963,35 @@ grow_method (fn, method_vec_ptr)
us to reduce search time in places like `build_method_call' to
consider only reasonably likely functions. */
-static tree
+tree
finish_struct_methods (t, fn_fields, nonprivate_method)
tree t;
tree fn_fields;
int nonprivate_method;
{
tree method_vec;
- tree save_fn_fields = tree_cons (NULL_TREE, NULL_TREE, fn_fields);
- tree lastp;
- tree name = constructor_name (t);
+ tree save_fn_fields = fn_fields;
+ tree ctor_name = constructor_name (t);
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
/* Now prepare to gather fn_fields into vector. */
struct obstack *ambient_obstack = current_obstack;
current_obstack = &class_obstack;
- method_vec = make_node (TREE_VEC);
- /* Room has been saved for constructors and destructors. */
+ method_vec = make_tree_vec (2);
current_obstack = ambient_obstack;
+
/* Now make this a live vector. */
obstack_free (&class_obstack, method_vec);
- obstack_blank (&class_obstack, sizeof (struct tree_vec));
- /* First fill in entry 0 with the constructors, and the next few with
- type conversion operators (if any). */
+ /* Save room for constructors and destructors. */
+ obstack_blank (&class_obstack, sizeof (struct tree_vec) + sizeof (struct tree *));
+
+ /* First fill in entry 0 with the constructors, entry 1 with destructors,
+ and the next few with type conversion operators (if any). */
- for (lastp = save_fn_fields; fn_fields; fn_fields = TREE_CHAIN (lastp))
+ for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields))
{
tree fn_name = DECL_NAME (fn_fields);
- if (fn_name == NULL_TREE)
- fn_name = name;
/* Clear out this flag.
@@ -1852,7 +2002,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
/* Note here that a copy ctor is private, so we don't dare generate
a default copy constructor for a class that has a member
of this type without making sure they have access to it. */
- if (fn_name == name)
+ if (fn_name == ctor_name)
{
tree parmtypes = FUNCTION_ARG_CHAIN (fn_fields);
tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node;
@@ -1870,43 +2020,30 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
TYPE_HAS_NONPUBLIC_CTOR (t) = 2;
}
}
- /* Constructors are handled easily in search routines. */
- DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0);
- TREE_VEC_ELT (method_vec, 0) = fn_fields;
+ if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn_fields)))
+ {
+ /* Destructors go in slot 1. */
+ TREE_VEC_ELT (method_vec, 1) =
+ build_overload (fn_fields, TREE_VEC_ELT (method_vec, 1));
+ }
+ else
+ {
+ /* Constructors go in slot 0. */
+ TREE_VEC_ELT (method_vec, 0) =
+ build_overload (fn_fields, TREE_VEC_ELT (method_vec, 0));
+ }
}
else if (IDENTIFIER_TYPENAME_P (fn_name))
- {
- tree return_type = TREE_TYPE (TREE_TYPE (fn_fields));
-
- if (typecode_p (return_type, INTEGER_TYPE)
- || typecode_p (return_type, BOOLEAN_TYPE)
- || typecode_p (return_type, ENUMERAL_TYPE))
- TYPE_HAS_INT_CONVERSION (t) = 1;
- else if (typecode_p (return_type, REAL_TYPE))
- TYPE_HAS_REAL_CONVERSION (t) = 1;
-
- grow_method (fn_fields, &method_vec);
- }
- else
- {
- lastp = fn_fields;
- continue;
- }
-
- TREE_CHAIN (lastp) = TREE_CHAIN (fn_fields);
- TREE_CHAIN (fn_fields) = NULL_TREE;
+ grow_method (fn_fields, &method_vec);
}
- fn_fields = TREE_CHAIN (save_fn_fields);
- while (fn_fields)
+ fn_fields = save_fn_fields;
+ for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields))
{
- tree nextp;
tree fn_name = DECL_NAME (fn_fields);
- if (fn_name == NULL_TREE)
- fn_name = name;
- nextp = TREE_CHAIN (fn_fields);
- TREE_CHAIN (fn_fields) = NULL_TREE;
+ if (fn_name == ctor_name || IDENTIFIER_TYPENAME_P (fn_name))
+ continue;
if (fn_name == ansi_opname[(int) MODIFY_EXPR])
{
@@ -1922,7 +2059,6 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
}
grow_method (fn_fields, &method_vec);
- fn_fields = nextp;
}
TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack)
@@ -1932,7 +2068,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
if (nonprivate_method == 0
&& CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
- && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE)
+ && DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE)
{
tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
for (i = 0; i < n_baseclasses; i++)
@@ -1942,60 +2078,44 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
nonprivate_method = 1;
break;
}
- if (nonprivate_method == 0)
+ if (nonprivate_method == 0
+ && warn_ctor_dtor_privacy)
cp_warning ("all member functions in class `%T' are private", t);
}
- /* If there are constructors (and destructors), they are at the
- front. Place destructors at very front. Also warn if all
- constructors and/or destructors are private (in which case this
- class is effectively unusable. */
+ /* Warn if all destructors are private (in which case this class is
+ effectively unusable. */
if (TYPE_HAS_DESTRUCTOR (t))
{
- tree dtor, prev;
-
- for (dtor = TREE_VEC_ELT (method_vec, 0);
- dtor;
- prev = dtor, dtor = DECL_CHAIN (dtor))
- {
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (dtor)))
- {
- if (TREE_PRIVATE (dtor)
- && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
- && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE
- && warn_ctor_dtor_privacy)
- cp_warning ("`%#T' only defines a private destructor and has no friends",
- t);
- break;
- }
- }
+ tree dtor = TREE_VEC_ELT (method_vec, 1);
/* Wild parse errors can cause this to happen. */
if (dtor == NULL_TREE)
TYPE_HAS_DESTRUCTOR (t) = 0;
- else if (dtor != TREE_VEC_ELT (method_vec, 0))
- {
- DECL_CHAIN (prev) = DECL_CHAIN (dtor);
- DECL_CHAIN (dtor) = TREE_VEC_ELT (method_vec, 0);
- TREE_VEC_ELT (method_vec, 0) = dtor;
- }
+ else if (TREE_PRIVATE (dtor)
+ && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
+ && DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE
+ && warn_ctor_dtor_privacy)
+ cp_warning ("`%#T' only defines a private destructor and has no friends",
+ t);
}
/* Now for each member function (except for constructors and
destructors), compute where member functions of the same
name reside in base classes. */
if (n_baseclasses != 0
- && TREE_VEC_LENGTH (method_vec) > 1)
+ && TREE_VEC_LENGTH (method_vec) > 2)
{
int len = TREE_VEC_LENGTH (method_vec);
tree baselink_vec = make_tree_vec (len);
int any_links = 0;
tree baselink_binfo = build_tree_list (NULL_TREE, TYPE_BINFO (t));
- for (i = 1; i < len; i++)
+ for (i = 2; i < len; i++)
{
TREE_VEC_ELT (baselink_vec, i)
- = get_baselinks (baselink_binfo, t, DECL_NAME (TREE_VEC_ELT (method_vec, i)));
+ = get_baselinks (baselink_binfo, t,
+ DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i))));
if (TREE_VEC_ELT (baselink_vec, i) != 0)
any_links = 1;
}
@@ -2005,46 +2125,10 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
obstack_free (current_obstack, baselink_vec);
}
- /* Now add the methods to the TYPE_METHODS of T, arranged in a chain. */
- {
- tree x, last_x = NULL_TREE;
- int limit = TREE_VEC_LENGTH (method_vec);
-
- for (i = 1; i < limit; i++)
- {
- for (x = TREE_VEC_ELT (method_vec, i); x; x = DECL_CHAIN (x))
- {
- if (last_x != NULL_TREE)
- TREE_CHAIN (last_x) = x;
- last_x = x;
- }
- }
-
- /* Put ctors and dtors at the front of the list. */
- x = TREE_VEC_ELT (method_vec, 0);
- if (x)
- {
- while (DECL_CHAIN (x))
- {
- /* Let's avoid being circular about this. */
- if (x == DECL_CHAIN (x))
- break;
- TREE_CHAIN (x) = DECL_CHAIN (x);
- x = DECL_CHAIN (x);
- }
- if (TREE_VEC_LENGTH (method_vec) > 1)
- TREE_CHAIN (x) = TREE_VEC_ELT (method_vec, 1);
- else
- TREE_CHAIN (x) = NULL_TREE;
- }
- }
-
- TYPE_METHODS (t) = method_vec;
-
return method_vec;
}
-/* Emit error when a duplicate definition of a type is seen. Patch up. */
+/* Emit error when a duplicate definition of a type is seen. Patch up. */
void
duplicate_tag_error (t)
@@ -2058,23 +2142,22 @@ duplicate_tag_error (t)
/* All of the component_decl's were TREE_CHAINed together in the parser.
finish_struct_methods walks these chains and assembles all methods with
the same base name into DECL_CHAINs. Now we don't need the parser chains
- anymore, so we unravel them.
- */
- /*
- * This used to be in finish_struct, but it turns out that the
- * TREE_CHAIN is used by dbxout_type_methods and perhaps some other things...
- */
- if (CLASSTYPE_METHOD_VEC(t))
- {
- tree tv = CLASSTYPE_METHOD_VEC(t);
- int i, len = TREE_VEC_LENGTH (tv);
+ anymore, so we unravel them. */
+
+ /* This used to be in finish_struct, but it turns out that the
+ TREE_CHAIN is used by dbxout_type_methods and perhaps some other
+ things... */
+ if (CLASSTYPE_METHOD_VEC (t))
+ {
+ tree method_vec = CLASSTYPE_METHOD_VEC (t);
+ int i, len = TREE_VEC_LENGTH (method_vec);
for (i = 0; i < len; i++)
{
- tree unchain = TREE_VEC_ELT (tv, i);
+ tree unchain = TREE_VEC_ELT (method_vec, i);
while (unchain != NULL_TREE)
{
- TREE_CHAIN (unchain) = NULL_TREE;
- unchain = DECL_CHAIN(unchain);
+ TREE_CHAIN (OVL_CURRENT (unchain)) = NULL_TREE;
+ unchain = OVL_NEXT (unchain);
}
}
}
@@ -2095,7 +2178,6 @@ duplicate_tag_error (t)
CLASSTYPE_BINFO_AS_LIST (t) = binfo_as_list;
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
- CLASSTYPE_VBASE_SIZE (t) = integer_zero_node;
TYPE_REDEFINED (t) = 1;
}
TYPE_SIZE (t) = NULL_TREE;
@@ -2106,11 +2188,13 @@ duplicate_tag_error (t)
TYPE_CONTEXT (t) = NULL_TREE;
}
-/* finish up all new vtables. */
+/* finish up all new vtables. */
+
static void
finish_vtbls (binfo, do_self, t)
- tree binfo, t;
+ tree binfo;
int do_self;
+ tree t;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2138,8 +2222,8 @@ finish_vtbls (binfo, do_self, t)
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable =
- i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+ int is_not_base_vtable
+ = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (TREE_VIA_VIRTUAL (base_binfo))
{
base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t));
@@ -2150,20 +2234,21 @@ finish_vtbls (binfo, do_self, t)
/* True if we should override the given BASE_FNDECL with the given
FNDECL. */
+
static int
overrides (fndecl, base_fndecl)
tree fndecl, base_fndecl;
{
- /* Destructors have special names. */
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)) &&
- DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
+ /* Destructors have special names. */
+ if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl))
+ && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
return 1;
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)) ||
- DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
+ if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl))
+ || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
return 0;
if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl))
{
- tree rettype, base_rettype, types, base_types;
+ tree types, base_types;
#if 0
retypes = TREE_TYPE (TREE_TYPE (fndecl));
base_retypes = TREE_TYPE (TREE_TYPE (base_fndecl));
@@ -2226,6 +2311,7 @@ get_class_offset_1 (parent, binfo, context, t, fndecl)
/* Get the offset to the CONTEXT subobject that is related to the
given BINFO. */
+
static tree
get_class_offset (context, t, binfo, fndecl)
tree context, t, binfo, fndecl;
@@ -2251,7 +2337,7 @@ get_class_offset (context, t, binfo, fndecl)
}
/* Ok, not found in the less derived binfos, now check the more
- derived binfos. */
+ derived binfos. */
offset = get_class_offset_1 (first_binfo, TYPE_BINFO (t), context, t, fndecl);
if (offset==0 || TREE_CODE (offset) != INTEGER_CST)
my_friendly_abort (999); /* we have to find it. */
@@ -2259,6 +2345,7 @@ get_class_offset (context, t, binfo, fndecl)
}
/* Skip RTTI information at the front of the virtual list. */
+
unsigned HOST_WIDE_INT
skip_rtti_stuff (virtuals)
tree *virtuals;
@@ -2287,7 +2374,6 @@ modify_one_vtable (binfo, t, fndecl, pfn)
tree binfo, t, fndecl, pfn;
{
tree virtuals = BINFO_VIRTUALS (binfo);
- tree old_rtti;
unsigned HOST_WIDE_INT n;
/* update rtti entry */
@@ -2333,7 +2419,7 @@ modify_one_vtable (binfo, t, fndecl, pfn)
base_offset = size_binop (PLUS_EXPR,
get_derived_offset (binfo, DECL_CONTEXT (current_fndecl)),
BINFO_OFFSET (binfo));
- this_offset = size_binop (MINUS_EXPR, offset, base_offset);
+ this_offset = ssize_binop (MINUS_EXPR, offset, base_offset);
/* Make sure we can modify the derived association with immunity. */
if (TREE_USED (binfo))
@@ -2369,11 +2455,13 @@ modify_one_vtable (binfo, t, fndecl, pfn)
}
}
-/* These are the ones that are not through virtual base classes. */
+/* These are the ones that are not through virtual base classes. */
+
static void
modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn)
- tree binfo, t, fndecl, pfn;
+ tree binfo;
int do_self;
+ tree t, fndecl, pfn;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2387,14 +2475,15 @@ modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn)
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable =
- i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+ int is_not_base_vtable
+ = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (! TREE_VIA_VIRTUAL (base_binfo))
modify_all_direct_vtables (base_binfo, is_not_base_vtable, t, fndecl, pfn);
}
}
/* Fixup all the delta entries in this one vtable that need updating. */
+
static void
fixup_vtable_deltas1 (binfo, t)
tree binfo, t;
@@ -2427,9 +2516,10 @@ fixup_vtable_deltas1 (binfo, t)
Also, we want just the delta between the most base class
that we derived this vfield from and us. */
base_offset = size_binop (PLUS_EXPR,
- get_derived_offset (binfo, DECL_CONTEXT (fndecl)),
+ get_derived_offset (binfo,
+ DECL_CONTEXT (fndecl)),
BINFO_OFFSET (binfo));
- this_offset = size_binop (MINUS_EXPR, offset, base_offset);
+ this_offset = ssize_binop (MINUS_EXPR, offset, base_offset);
if (! tree_int_cst_equal (this_offset, delta))
{
@@ -2469,10 +2559,12 @@ fixup_vtable_deltas1 (binfo, t)
This happens when we have non-overridden virtual functions from a
virtual base class, that are at a different offset, in the new
hierarchy, because the layout of the virtual bases has changed. */
+
static void
fixup_vtable_deltas (binfo, init_self, t)
- tree binfo, t;
+ tree binfo;
int init_self;
+ tree t;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2480,8 +2572,8 @@ fixup_vtable_deltas (binfo, init_self, t)
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable =
- i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+ int is_not_base_vtable
+ = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (! TREE_VIA_VIRTUAL (base_binfo))
fixup_vtable_deltas (base_binfo, is_not_base_vtable, t);
}
@@ -2492,11 +2584,13 @@ fixup_vtable_deltas (binfo, init_self, t)
}
}
-/* These are the ones that are through virtual base classes. */
+/* These are the ones that are through virtual base classes. */
+
static void
modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn)
- tree binfo, t, fndecl, pfn;
+ tree binfo;
int do_self, via_virtual;
+ tree t, fndecl, pfn;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2510,8 +2604,8 @@ modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn)
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable =
- i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+ int is_not_base_vtable
+ = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (TREE_VIA_VIRTUAL (base_binfo))
{
via_virtual = 1;
@@ -2526,7 +2620,7 @@ modify_all_vtables (t, fndecl, vfn)
tree t, fndecl, vfn;
{
/* Do these first, so that we will make use of any non-virtual class's
- vtable, over a virtual classes vtable. */
+ vtable, over a virtual classes vtable. */
modify_all_direct_vtables (TYPE_BINFO (t), 1, t, fndecl, vfn);
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
modify_all_indirect_vtables (TYPE_BINFO (t), 1, 0, t, fndecl, vfn);
@@ -2534,6 +2628,7 @@ modify_all_vtables (t, fndecl, vfn)
/* Here, we already know that they match in every respect.
All we have to check is where they had their declarations. */
+
static int
strictly_overrides (fndecl1, fndecl2)
tree fndecl1, fndecl2;
@@ -2558,6 +2653,7 @@ strictly_overrides (fndecl1, fndecl2)
then it is ill-formed. (mrs)
We take special care to reuse a vtable, if we can. */
+
static void
override_one_vtable (binfo, old, t)
tree binfo, old, t;
@@ -2567,7 +2663,7 @@ override_one_vtable (binfo, old, t)
enum { REUSE_NEW, REUSE_OLD, UNDECIDED, NEITHER } choose = UNDECIDED;
/* If we have already committed to modifying it, then don't try and
- reuse another vtable. */
+ reuse another vtable. */
if (BINFO_NEW_VTABLE_MARKED (binfo))
choose = NEITHER;
@@ -2582,10 +2678,10 @@ override_one_vtable (binfo, old, t)
old_fndecl = FNADDR_FROM_VTABLE_ENTRY (old_fndecl);
fndecl = TREE_OPERAND (fndecl, 0);
old_fndecl = TREE_OPERAND (old_fndecl, 0);
- /* First check to see if they are the same. */
+ /* First check to see if they are the same. */
if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl))
{
- /* No need to do anything. */
+ /* No need to do anything. */
}
else if (strictly_overrides (fndecl, old_fndecl))
{
@@ -2640,15 +2736,16 @@ override_one_vtable (binfo, old, t)
fndecl = copy_node (fndecl);
copy_lang_decl (fndecl);
DECL_ABSTRACT_VIRTUAL_P (fndecl) = 1;
- /* Make sure we search for it later. */
+ DECL_NEEDS_FINAL_OVERRIDER_P (fndecl) = 1;
+ /* Make sure we search for it later. */
if (! CLASSTYPE_ABSTRACT_VIRTUALS (t))
CLASSTYPE_ABSTRACT_VIRTUALS (t) = error_mark_node;
vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
TREE_CONSTANT (vfn) = 1;
- /* We can use integer_zero_node, as we will will core dump
- if this is used anyway. */
+ /* We can use integer_zero_node, as we will core dump
+ if this is used anyway. */
TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, vfn);
}
}
@@ -2656,7 +2753,7 @@ override_one_vtable (binfo, old, t)
old_virtuals = TREE_CHAIN (old_virtuals);
}
- /* Let's reuse the old vtable. */
+ /* Let's reuse the old vtable. */
if (choose == REUSE_OLD)
{
BINFO_VTABLE (binfo) = BINFO_VTABLE (old);
@@ -2667,10 +2764,12 @@ override_one_vtable (binfo, old, t)
/* Merge in overrides for virtual bases.
BINFO is the hierarchy we want to modify, and OLD has the potential
overrides. */
+
static void
merge_overrides (binfo, old, do_self, t)
- tree binfo, old, t;
+ tree binfo, old;
int do_self;
+ tree t;
{
tree binfos = BINFO_BASETYPES (binfo);
tree old_binfos = BINFO_BASETYPES (old);
@@ -2686,13 +2785,252 @@ merge_overrides (binfo, old, do_self, t)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree old_base_binfo = TREE_VEC_ELT (old_binfos, i);
- int is_not_base_vtable =
- i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+ int is_not_base_vtable
+ = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (! TREE_VIA_VIRTUAL (base_binfo))
merge_overrides (base_binfo, old_base_binfo, is_not_base_vtable, t);
}
}
+/* Get the base virtual function declarations in T that are either
+ overridden or hidden by FNDECL as a list. We set TREE_PURPOSE with
+ the overrider/hider. */
+
+static tree
+get_basefndecls (fndecl, t)
+ tree fndecl, t;
+{
+ tree methods = TYPE_METHODS (t);
+ tree base_fndecls = NULL_TREE;
+ tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
+ int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+
+ while (methods)
+ {
+ if (TREE_CODE (methods) == FUNCTION_DECL
+ && DECL_VINDEX (methods) != NULL_TREE
+ && DECL_NAME (fndecl) == DECL_NAME (methods))
+ base_fndecls = temp_tree_cons (fndecl, methods, base_fndecls);
+
+ methods = TREE_CHAIN (methods);
+ }
+
+ if (base_fndecls)
+ return base_fndecls;
+
+ for (i = 0; i < n_baseclasses; i++)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ tree basetype = BINFO_TYPE (base_binfo);
+
+ base_fndecls = chainon (get_basefndecls (fndecl, basetype),
+ base_fndecls);
+ }
+
+ return base_fndecls;
+}
+
+/* Mark the functions that have been hidden with their overriders.
+ Since we start out with all functions already marked with a hider,
+ no need to mark functions that are just hidden. */
+
+static void
+mark_overriders (fndecl, base_fndecls)
+ tree fndecl, base_fndecls;
+{
+ while (base_fndecls)
+ {
+ if (overrides (TREE_VALUE (base_fndecls), fndecl))
+ TREE_PURPOSE (base_fndecls) = fndecl;
+
+ base_fndecls = TREE_CHAIN (base_fndecls);
+ }
+}
+
+/* If this declaration supersedes the declaration of
+ a method declared virtual in the base class, then
+ mark this field as being virtual as well. */
+
+static void
+check_for_override (decl, ctype)
+ tree decl, ctype;
+{
+ tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype));
+ int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ int virtualp = DECL_VIRTUAL_P (decl);
+
+ for (i = 0; i < n_baselinks; i++)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo))
+ || flag_all_virtual == 1)
+ {
+ tree tmp = get_matching_virtual
+ (base_binfo, decl,
+ DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
+ if (tmp)
+ {
+ /* If this function overrides some virtual in some base
+ class, then the function itself is also necessarily
+ virtual, even if the user didn't explicitly say so. */
+ DECL_VIRTUAL_P (decl) = 1;
+
+ /* The TMP we really want is the one from the deepest
+ baseclass on this path, taking care not to
+ duplicate if we have already found it (via another
+ path to its virtual baseclass. */
+ if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
+ {
+ cp_error_at ("method `%D' may not be declared static",
+ decl);
+ cp_error_at ("(since `%D' declared virtual in base class.)",
+ tmp);
+ break;
+ }
+ virtualp = 1;
+
+#if 0 /* The signature of an overriding function is not changed. */
+ {
+ /* The argument types may have changed... */
+ tree type = TREE_TYPE (decl);
+ tree argtypes = TYPE_ARG_TYPES (type);
+ tree base_variant = TREE_TYPE (TREE_VALUE (argtypes));
+ tree raises = TYPE_RAISES_EXCEPTIONS (type);
+
+ argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))),
+ TREE_CHAIN (argtypes));
+ /* But the return type has not. */
+ type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
+ if (raises)
+ type = build_exception_variant (type, raises);
+ TREE_TYPE (decl) = type;
+ }
+#endif
+ DECL_VINDEX (decl)
+ = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
+ break;
+ }
+ }
+ }
+ if (virtualp)
+ {
+ if (DECL_VINDEX (decl) == NULL_TREE)
+ DECL_VINDEX (decl) = error_mark_node;
+ IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
+ }
+}
+
+/* Warn about hidden virtual functions that are not overridden in t.
+ We know that constructors and destructors don't apply. */
+
+void
+warn_hidden (t)
+ tree t;
+{
+ tree method_vec = CLASSTYPE_METHOD_VEC (t);
+ int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
+ int i;
+
+ /* We go through each separately named virtual function. */
+ for (i = 2; i < n_methods; ++i)
+ {
+ tree fns = TREE_VEC_ELT (method_vec, i);
+ tree fndecl;
+
+ tree base_fndecls = NULL_TREE;
+ tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
+ int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+
+ fndecl = OVL_CURRENT (fns);
+ if (DECL_VINDEX (fndecl) == NULL_TREE)
+ continue;
+
+ /* First we get a list of all possible functions that might be
+ hidden from each base class. */
+ for (i = 0; i < n_baseclasses; i++)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ tree basetype = BINFO_TYPE (base_binfo);
+
+ base_fndecls = chainon (get_basefndecls (fndecl, basetype),
+ base_fndecls);
+ }
+
+ fns = OVL_NEXT (fns);
+ if (fns)
+ fndecl = OVL_CURRENT (fns);
+ else
+ fndecl = NULL_TREE;
+
+ /* ...then mark up all the base functions with overriders, preferring
+ overriders to hiders. */
+ if (base_fndecls)
+ while (fndecl)
+ {
+ mark_overriders (fndecl, base_fndecls);
+
+ fns = OVL_NEXT (fns);
+ if (fns)
+ fndecl = OVL_CURRENT (fns);
+ else
+ fndecl = NULL_TREE;
+ }
+
+ /* Now give a warning for all base functions without overriders,
+ as they are hidden. */
+ while (base_fndecls)
+ {
+ if (! overrides (TREE_VALUE (base_fndecls),
+ TREE_PURPOSE (base_fndecls)))
+ {
+ /* Here we know it is a hider, and no overrider exists. */
+ cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls));
+ cp_warning_at (" by `%D'", TREE_PURPOSE (base_fndecls));
+ }
+
+ base_fndecls = TREE_CHAIN (base_fndecls);
+ }
+ }
+}
+
+/* Check for things that are invalid. There are probably plenty of other
+ things we should check for also. */
+
+static void
+finish_struct_anon (t)
+ tree t;
+{
+ tree field;
+ for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_STATIC (field))
+ continue;
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ if (DECL_NAME (field) == NULL_TREE
+ && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+ {
+ tree* uelt = &TYPE_FIELDS (TREE_TYPE (field));
+ for (; *uelt; uelt = &TREE_CHAIN (*uelt))
+ {
+ 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);
+
+ TREE_PRIVATE (*uelt) = TREE_PRIVATE (field);
+ TREE_PROTECTED (*uelt) = TREE_PROTECTED (field);
+ }
+ }
+ }
+}
+
extern int interface_only, interface_unknown;
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
@@ -2724,6 +3062,8 @@ extern int interface_only, interface_unknown;
TREE_LIST elements, whose TREE_PURPOSE field tells what access
the list has, and the TREE_VALUE slot gives the actual fields.
+ ATTRIBUTES is the set of decl attributes to be applied, if any.
+
If flag_all_virtual == 1, then we lay all functions into
the virtual function table, as though they were declared
virtual. Constructors do not lay down in the virtual function table.
@@ -2760,25 +3100,21 @@ finish_struct_1 (t, warn_anon)
int warn_anon;
{
int old;
- int round_up_size = 1;
-
tree name = TYPE_IDENTIFIER (t);
enum tree_code code = TREE_CODE (t);
tree fields = TYPE_FIELDS (t);
- tree fn_fields = CLASSTYPE_METHODS (t);
+ tree fn_fields = TYPE_METHODS (t);
tree x, last_x, method_vec;
- int needs_virtual_dtor;
int all_virtual;
int has_virtual;
int max_has_virtual;
tree pending_virtuals = NULL_TREE;
+ tree pending_hard_virtuals = NULL_TREE;
tree abstract_virtuals = NULL_TREE;
tree vfield;
tree vfields;
int cant_have_default_ctor;
int cant_have_const_ctor;
- int cant_synth_copy_ctor;
- int cant_synth_asn_ref;
int no_const_asn_ref;
/* The index of the first base class which has virtual
@@ -2790,9 +3126,10 @@ finish_struct_1 (t, warn_anon)
int const_sans_init = 0;
int ref_sans_init = 0;
int nonprivate_method = 0;
- tree t_binfo = TYPE_BINFO (t);
tree access_decls = NULL_TREE;
int aggregate = 1;
+ int empty = 1;
+ int has_pointers = 0;
if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
pedwarn ("anonymous class type not used to declare any objects");
@@ -2807,12 +3144,6 @@ finish_struct_1 (t, warn_anon)
return t;
}
- if (dont_allow_type_definitions)
- {
- pedwarn ("types cannot be defined %s",
- dont_allow_type_definitions);
- }
-
GNU_xref_decl (current_function_decl, t);
/* If this type was previously laid out as a forward reference,
@@ -2831,13 +3162,6 @@ finish_struct_1 (t, warn_anon)
}
#endif
-#if 0
- if (flag_rtti)
- build_t_desc (t, 0);
-#endif
-
- TYPE_BINFO (t) = NULL_TREE;
-
old = suspend_momentary ();
/* Install struct as DECL_FIELD_CONTEXT of each field decl.
@@ -2847,8 +3171,8 @@ finish_struct_1 (t, warn_anon)
Store 0 there, except for ": 0" fields (so we can find them
and delete them, below). */
- if (t_binfo && BINFO_BASETYPES (t_binfo))
- n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo));
+ if (TYPE_BINFO_BASETYPES (t))
+ n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t));
else
n_baseclasses = 0;
@@ -2856,27 +3180,18 @@ finish_struct_1 (t, warn_anon)
{
struct base_info base_info;
- /* If using multiple inheritance, this may cause variants of our
- basetypes to be used (instead of their canonical forms). */
- 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 */
+ first_vfn_base_index = finish_base_struct (t, &base_info);
+ /* Remember where we got our vfield from. */
CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index;
has_virtual = base_info.has_virtual;
max_has_virtual = base_info.max_has_virtual;
CLASSTYPE_N_SUPERCLASSES (t) += base_info.n_ancestors;
vfield = base_info.vfield;
vfields = base_info.vfields;
+ CLASSTYPE_RTTI (t) = base_info.rtti;
cant_have_default_ctor = base_info.cant_have_default_ctor;
cant_have_const_ctor = base_info.cant_have_const_ctor;
- cant_synth_copy_ctor = base_info.cant_synth_copy_ctor;
- cant_synth_asn_ref = base_info.cant_synth_asn_ref;
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
@@ -2886,13 +3201,10 @@ finish_struct_1 (t, warn_anon)
max_has_virtual = has_virtual;
vfield = NULL_TREE;
vfields = NULL_TREE;
- last_x = NULL_TREE;
+ CLASSTYPE_RTTI (t) = NULL_TREE;
cant_have_default_ctor = 0;
cant_have_const_ctor = 0;
- cant_synth_copy_ctor = 0;
- cant_synth_asn_ref = 0;
no_const_asn_ref = 0;
- needs_virtual_dtor = 0;
}
#if 0
@@ -2908,19 +3220,17 @@ finish_struct_1 (t, warn_anon)
/* The three of these are approximations which may later be
modified. Needed at this point to make add_virtual_function
and modify_vtable_entries work. */
- TREE_CHAIN (t_binfo) = TYPE_BINFO (t);
- TYPE_BINFO (t) = t_binfo;
CLASSTYPE_VFIELDS (t) = vfields;
CLASSTYPE_VFIELD (t) = vfield;
if (IS_SIGNATURE (t))
all_virtual = 0;
- else if (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (t))
+ else if (flag_all_virtual == 1)
all_virtual = 1;
else
all_virtual = 0;
- for (x = CLASSTYPE_METHODS (t); x; x = TREE_CHAIN (x))
+ for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
GNU_xref_member (current_class_name, x);
@@ -2939,48 +3249,61 @@ finish_struct_1 (t, warn_anon)
DECL_SAVED_INSNS (x) = NULL_RTX;
DECL_FIELD_SIZE (x) = 0;
+ check_for_override (x, t);
+ if (DECL_ABSTRACT_VIRTUAL_P (x) && ! DECL_VINDEX (x))
+ cp_error_at ("initializer specified for non-virtual method `%D'", 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);
+ add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
+ &has_virtual, x, t);
if (DECL_ABSTRACT_VIRTUAL_P (x))
abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
+#if 0
+ /* XXX Why did I comment this out? (jason) */
else
TREE_USED (x) = 1;
+#endif
}
}
- for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x))
+ if (n_baseclasses)
+ fields = chainon (build_vbase_pointer_fields (t), fields);
+
+ last_x = NULL_TREE;
+ for (x = fields; x; x = TREE_CHAIN (x))
{
GNU_xref_member (current_class_name, x);
- /* Handle access declarations. */
- if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF)
+ if (TREE_CODE (x) == FIELD_DECL)
{
- tree fdecl = TREE_OPERAND (DECL_NAME (x), 1);
- enum access_type access
- = TREE_PRIVATE (x) ? access_private :
- TREE_PROTECTED (x) ? access_protected : access_public;
+ DECL_PACKED (x) |= TYPE_PACKED (t);
+ empty = 0;
+ }
+ if (TREE_CODE (x) == USING_DECL)
+ {
+ /* Save access declarations for later. */
if (last_x)
TREE_CHAIN (last_x) = TREE_CHAIN (x);
else
fields = TREE_CHAIN (x);
-
- access_decls = tree_cons ((tree) access, fdecl, access_decls);
+
+ access_decls = scratch_tree_cons (NULL_TREE, x, access_decls);
continue;
}
last_x = x;
- if (TREE_CODE (x) == TYPE_DECL)
+ if (TREE_CODE (x) == TYPE_DECL
+ || TREE_CODE (x) == TEMPLATE_DECL)
continue;
/* If we've gotten this far, it's a data member, possibly static,
- or an enumerator. */
+ or an enumerator. */
DECL_FIELD_CONTEXT (x) = t;
@@ -3009,7 +3332,7 @@ finish_struct_1 (t, warn_anon)
#if 0
if (DECL_NAME (x) == constructor_name (t))
- cant_have_default_ctor = cant_synth_copy_ctor = 1;
+ cant_have_default_ctor = 1;
#endif
if (TREE_TYPE (x) == error_mark_node)
@@ -3049,8 +3372,8 @@ finish_struct_1 (t, warn_anon)
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;
+ TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
{
@@ -3061,6 +3384,9 @@ finish_struct_1 (t, warn_anon)
}
}
+ if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE)
+ has_pointers = 1;
+
/* If any field is const, the structure type is pseudo-const. */
if (TREE_READONLY (x))
{
@@ -3072,8 +3398,8 @@ finish_struct_1 (t, warn_anon)
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;
+ TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t)
&& extra_warnings)
@@ -3118,9 +3444,26 @@ finish_struct_1 (t, warn_anon)
/* Detect and ignore out of range field width. */
if (DECL_INITIAL (x))
{
- register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
+ tree w = DECL_INITIAL (x);
+ register int width = 0;
+
+ /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
+ STRIP_NOPS (w);
- if (width < 0)
+ /* detect invalid field size. */
+ if (TREE_CODE (w) == CONST_DECL)
+ w = DECL_INITIAL (w);
+ else if (TREE_READONLY_DECL_P (w))
+ w = decl_constant_value (w);
+
+ if (TREE_CODE (w) != INTEGER_CST)
+ {
+ cp_error_at ("bit-field `%D' width not an integer constant",
+ x);
+ DECL_INITIAL (x) = NULL_TREE;
+ }
+ else if (width = TREE_INT_CST_LOW (w),
+ width < 0)
{
DECL_INITIAL (x) = NULL;
cp_error_at ("negative width in bit-field `%D'", x);
@@ -3141,7 +3484,8 @@ finish_struct_1 (t, warn_anon)
cp_error_at (" in declaration of `%D'", x);
}
else if (width > TYPE_PRECISION (TREE_TYPE (x))
- && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
+ && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE
+ && TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE)
{
cp_warning_at ("width of `%D' exceeds its type", x);
}
@@ -3154,23 +3498,13 @@ finish_struct_1 (t, warn_anon)
cp_warning_at ("`%D' is too small to hold all values of `%#T'",
x, TREE_TYPE (x));
}
- }
- /* Process valid field width. */
- if (DECL_INITIAL (x))
- {
- register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
- if (width == 0)
+ if (DECL_INITIAL (x) == NULL_TREE)
+ ;
+ else 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;
+ DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
#endif
#ifdef PCC_BITFIELD_TYPE_MATTERS
DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
@@ -3182,11 +3516,6 @@ finish_struct_1 (t, warn_anon)
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
@@ -3197,7 +3526,7 @@ finish_struct_1 (t, warn_anon)
{
tree type = TREE_TYPE (x);
- if (TREE_CODE (type) == ARRAY_TYPE)
+ while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x)
@@ -3219,8 +3548,8 @@ finish_struct_1 (t, warn_anon)
fie = "constructor";
else if (TYPE_NEEDS_DESTRUCTOR (type))
fie = "destructor";
- else if (TYPE_HAS_REAL_ASSIGNMENT (type))
- fie = "assignment operator";
+ else if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
+ fie = "copy assignment operator";
if (fie)
cp_error_at ("member `%#D' with %s not allowed in union", x,
fie);
@@ -3233,18 +3562,10 @@ finish_struct_1 (t, warn_anon)
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))
+ 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))
+ if (!TYPE_HAS_CONST_ASSIGN_REF (type))
no_const_asn_ref = 1;
if (TYPE_HAS_CONSTRUCTOR (type)
@@ -3294,41 +3615,50 @@ finish_struct_1 (t, warn_anon)
&& !IS_SIGNATURE (t))
{
/* Here we must cons up a destructor on the fly. */
- tree dtor = cons_up_default_function (t, name, needs_virtual_dtor != 0);
+ tree dtor = cons_up_default_function (t, name, 0);
+ check_for_override (dtor, t);
/* If we couldn't make it work, then pretend we didn't need it. */
if (dtor == void_type_node)
TYPE_NEEDS_DESTRUCTOR (t) = 0;
else
{
- /* Link dtor onto end of fn_fields. */
+ /* Link dtor onto end of fn_fields. */
TREE_CHAIN (dtor) = fn_fields;
fn_fields = dtor;
- if (DECL_VINDEX (dtor) == NULL_TREE
- && (needs_virtual_dtor
- || pending_virtuals != NULL_TREE
- || pending_hard_virtuals != NULL_TREE))
- DECL_VINDEX (dtor) = error_mark_node;
if (DECL_VINDEX (dtor))
- pending_virtuals = add_virtual_function (pending_virtuals,
- &has_virtual, dtor, t);
+ add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
+ &has_virtual, dtor, t);
nonprivate_method = 1;
}
}
+ /* Effective C++ rule 11. */
+ if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t)
+ && ! (TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
+ {
+ cp_warning ("`%#T' has pointer data members", t);
+
+ if (! TYPE_HAS_INIT_REF (t))
+ {
+ cp_warning (" but does not override `%T(const %T&)'", t, t);
+ if (! TYPE_HAS_ASSIGN_REF (t))
+ cp_warning (" or `operator=(const %T&)'", t);
+ }
+ else if (! TYPE_HAS_ASSIGN_REF (t))
+ cp_warning (" but does not override `operator=(const %T&)'", t);
+ }
+
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
- if (flag_rtti && (max_has_virtual > 0 || needs_virtual_dtor) &&
- has_virtual == 0)
- has_virtual = 1;
TYPE_HAS_COMPLEX_INIT_REF (t)
|= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
- || any_default_members);
+ || has_virtual || 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);
+ || has_virtual || any_default_members);
if (! IS_SIGNATURE (t))
CLASSTYPE_NON_AGGREGATE (t)
= ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t);
@@ -3346,8 +3676,7 @@ finish_struct_1 (t, warn_anon)
}
/* Create default copy constructor, if needed. */
- if (! TYPE_HAS_INIT_REF (t) && ! cant_synth_copy_ctor
- && ! IS_SIGNATURE (t))
+ if (! TYPE_HAS_INIT_REF (t) && ! IS_SIGNATURE (t) && ! TYPE_FOR_JAVA (t))
{
/* ARM 12.18: You get either X(X&) or X(const X&), but
not both. --Chip */
@@ -3362,8 +3691,7 @@ finish_struct_1 (t, warn_anon)
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
- if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref
- && ! IS_SIGNATURE (t))
+ if (! TYPE_HAS_ASSIGN_REF (t) && ! IS_SIGNATURE (t) && ! TYPE_FOR_JAVA (t))
{
tree default_fn = cons_up_default_function (t, name,
5 + no_const_asn_ref);
@@ -3373,19 +3701,20 @@ finish_struct_1 (t, warn_anon)
if (fn_fields)
{
+ TYPE_METHODS (t) = fn_fields;
method_vec = finish_struct_methods (t, fn_fields, nonprivate_method);
if (TYPE_HAS_CONSTRUCTOR (t)
&& CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
- && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE)
+ && DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE)
{
int nonprivate_ctor = 0;
tree ctor;
for (ctor = TREE_VEC_ELT (method_vec, 0);
ctor;
- ctor = DECL_CHAIN (ctor))
- if (! TREE_PRIVATE (ctor))
+ ctor = OVL_NEXT (ctor))
+ if (! TREE_PRIVATE (OVL_CURRENT (ctor)))
{
nonprivate_ctor = 1;
break;
@@ -3406,68 +3735,9 @@ finish_struct_1 (t, warn_anon)
TYPE_HAS_DESTRUCTOR (t) = 0;
}
- {
- int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
-
- for (access_decls = nreverse (access_decls); access_decls;
- access_decls = TREE_CHAIN (access_decls))
- {
- tree fdecl = TREE_VALUE (access_decls);
- tree flist = NULL_TREE;
- tree name;
- enum access_type access = (enum access_type)TREE_PURPOSE(access_decls);
- int i = TREE_VEC_ELT (method_vec, 0) ? 0 : 1;
- tree tmp;
-
- if (TREE_CODE (fdecl) == TREE_LIST)
- {
- flist = fdecl;
- fdecl = TREE_VALUE (flist);
- }
-
- name = DECL_NAME (fdecl);
-
- for (; i < n_methods; i++)
- if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name)
- {
- cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
- cp_error_at (" because of local method `%#D' with same name",
- TREE_VEC_ELT (method_vec, i));
- fdecl = NULL_TREE;
- break;
- }
-
- if (! fdecl)
- continue;
-
- for (tmp = fields; tmp; tmp = TREE_CHAIN (tmp))
- if (DECL_NAME (tmp) == name)
- {
- cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
- cp_error_at (" because of local field `%#D' with same name", tmp);
- fdecl = NULL_TREE;
- break;
- }
-
- if (!fdecl)
- continue;
-
- /* Make type T see field decl FDECL with access ACCESS.*/
- if (flist)
- {
- fdecl = TREE_VALUE (flist);
- while (fdecl)
- {
- if (alter_access (t, fdecl, access) == 0)
- break;
- fdecl = DECL_CHAIN (fdecl);
- }
- }
- else
- alter_access (t, fdecl, access);
- }
-
- }
+ for (access_decls = nreverse (access_decls); access_decls;
+ access_decls = TREE_CHAIN (access_decls))
+ handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields);
if (vfield == NULL_TREE && has_virtual)
{
@@ -3477,23 +3747,26 @@ finish_struct_1 (t, warn_anon)
ptr_type_node);
/* If you change any of the below, take a look at all the
other VFIELD_BASEs and VTABLE_BASEs in the code, and change
- them too. */
+ them too. */
DECL_ASSEMBLER_NAME (vfield) = get_identifier (VFIELD_BASE);
CLASSTYPE_VFIELD (t) = vfield;
DECL_VIRTUAL_P (vfield) = 1;
+ DECL_ARTIFICIAL (vfield) = 1;
DECL_FIELD_CONTEXT (vfield) = t;
DECL_CLASS_CONTEXT (vfield) = t;
DECL_FCONTEXT (vfield) = t;
DECL_SAVED_INSNS (vfield) = NULL_RTX;
DECL_FIELD_SIZE (vfield) = 0;
DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node);
- if (CLASSTYPE_RTTI (t))
- {
- /* vfield is always first entry in structure. */
- TREE_CHAIN (vfield) = fields;
- fields = vfield;
- }
- else if (last_x)
+#if 0
+ /* This is more efficient, but breaks binary compatibility, turn
+ it on sometime when we don't care. If we turn it on, we also
+ have to enable the code in dfs_init_vbase_pointers. */
+ /* vfield is always first entry in structure. */
+ TREE_CHAIN (vfield) = fields;
+ fields = vfield;
+#else
+ if (last_x)
{
my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175);
TREE_CHAIN (last_x) = vfield;
@@ -3501,6 +3774,8 @@ finish_struct_1 (t, warn_anon)
}
else
fields = vfield;
+#endif
+ empty = 0;
vfields = chainon (vfields, CLASSTYPE_AS_LIST (t));
}
@@ -3534,13 +3809,18 @@ finish_struct_1 (t, warn_anon)
for (x = fields; x; x = TREE_CHAIN (x))
{
tree name = DECL_NAME (x);
- int i = /*TREE_VEC_ELT (method_vec, 0) ? 0 : */ 1;
+ int i = 2;
+
+ if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))
+ continue;
+
for (; i < n_methods; ++i)
- if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name)
+ if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)))
+ == name)
{
cp_error_at ("data member `%#D' conflicts with", x);
cp_error_at ("function member `%#D'",
- TREE_VEC_ELT (method_vec, i));
+ OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
break;
}
}
@@ -3551,114 +3831,65 @@ finish_struct_1 (t, warn_anon)
TYPE_FIELDS (t) = fields;
- /* If there's a :0 field at the end, round the size to the
- EMPTY_FIELD_BOUNDARY. */
- TYPE_ALIGN (t) = round_up_size;
-
- /* Pass layout information about base classes to layout_type, if any. */
if (n_baseclasses)
{
- tree pseudo_basetype = TREE_TYPE (base_layout_decl);
-
- TREE_CHAIN (base_layout_decl) = TYPE_FIELDS (t);
- TYPE_FIELDS (t) = base_layout_decl;
+ last_x = build_base_fields (t);
- TYPE_SIZE (pseudo_basetype) = CLASSTYPE_SIZE (t);
- TYPE_MODE (pseudo_basetype) = TYPE_MODE (t);
- TYPE_ALIGN (pseudo_basetype) = CLASSTYPE_ALIGN (t);
- DECL_ALIGN (base_layout_decl) = TYPE_ALIGN (pseudo_basetype);
- /* Don't re-use old size. */
- DECL_SIZE (base_layout_decl) = NULL_TREE;
+ /* If all our bases are empty, we can be empty too. */
+ for (x = last_x; empty && x; x = TREE_CHAIN (x))
+ if (DECL_SIZE (x) != integer_zero_node)
+ empty = 0;
}
+ if (empty)
+ {
+ /* C++: do not let empty structures exist. */
+ tree decl = build_lang_field_decl
+ (FIELD_DECL, NULL_TREE, char_type_node);
+ TREE_CHAIN (decl) = fields;
+ TYPE_FIELDS (t) = decl;
+ }
+ if (n_baseclasses)
+ TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t));
layout_type (t);
- {
- tree field;
- for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
- {
- if (TREE_STATIC (field))
- continue;
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- /* If this field is an anonymous union,
- give each union-member the same position as the union has.
-
- ??? This is a real kludge because it makes the structure
- of the types look strange. This feature is only used by
- C++, which should have build_component_ref build two
- COMPONENT_REF operations, one for the union and one for
- the inner field. We set the offset of this field to zero
- so that either the old or the correct method will work.
- Setting DECL_FIELD_CONTEXT is wrong unless the inner fields are
- moved into the type of this field, but nothing seems to break
- by doing this. */
-
- if (DECL_NAME (field) == NULL_TREE
- && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
- {
- tree uelt = TYPE_FIELDS (TREE_TYPE (field));
- for (; uelt; uelt = TREE_CHAIN (uelt))
- {
- 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);
- }
-
- DECL_FIELD_BITPOS (field) = integer_zero_node;
- }
- }
- }
-
- if (n_baseclasses)
- TYPE_FIELDS (t) = TREE_CHAIN (TYPE_FIELDS (t));
+ /* Remember the size and alignment of the class before adding
+ the virtual bases. */
+ if (empty && flag_new_abi)
+ CLASSTYPE_SIZE (t) = integer_zero_node;
+ else if (flag_new_abi && TYPE_HAS_COMPLEX_INIT_REF (t)
+ && TYPE_HAS_COMPLEX_ASSIGN_REF (t))
+ CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
+ else
+ CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
+ CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
- /* C++: do not let empty structures exist. */
- if (integer_zerop (TYPE_SIZE (t)))
- TYPE_SIZE (t) = TYPE_SIZE (char_type_node);
+ finish_struct_anon (t);
/* Set the TYPE_DECL for this type to contain the right
value for DECL_OFFSET, so that we can use it as part
of a COMPONENT_REF for multiple inheritance. */
- if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
- layout_decl (TYPE_NAME (t), 0);
+ layout_decl (TYPE_MAIN_DECL (t), 0);
/* Now fix up any virtual base class types that we left lying
around. We must get these done before we try to lay out the
virtual function table. */
- doing_hard_virtuals = 1;
pending_hard_virtuals = nreverse (pending_hard_virtuals);
+ if (n_baseclasses)
+ /* layout_basetypes will remove the base subobject fields. */
+ max_has_virtual = layout_basetypes (t, max_has_virtual);
+ else if (empty)
+ TYPE_FIELDS (t) = fields;
+
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{
tree vbases;
- max_has_virtual = layout_vbasetypes (t, max_has_virtual);
vbases = CLASSTYPE_VBASECLASSES (t);
CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases);
- /* The rtti code should do this. (mrs) */
-#if 0
- while (vbases)
- {
- /* Update rtti info with offsets for virtual baseclasses. */
- if (flag_rtti && ! BINFO_NEW_VTABLE_MARKED (vbases))
- prepare_fresh_vtable (vbases, t);
- vbases = TREE_CHAIN (vbases);
- }
-#endif
-
{
/* Now fixup overrides of all functions in vtables from all
direct or indirect virtual base classes. */
@@ -3681,19 +3912,6 @@ finish_struct_1 (t, warn_anon)
}
}
}
-
- /* Now fixup any virtual function entries from virtual bases
- that have different deltas. */
- vbases = CLASSTYPE_VBASECLASSES (t);
- while (vbases)
- {
- /* We might be able to shorten the amount of work we do by
- only doing this for vtables that come from virtual bases
- that have differing offsets, but don't want to miss any
- entries. */
- fixup_vtable_deltas (vbases, 1, t);
- vbases = TREE_CHAIN (vbases);
- }
}
/* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
@@ -3736,38 +3954,53 @@ finish_struct_1 (t, warn_anon)
TREE_VALUE (pending_hard_virtuals));
pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals);
}
- doing_hard_virtuals = 0;
+
+ if (TYPE_USES_VIRTUAL_BASECLASSES (t))
+ {
+ tree vbases;
+ /* Now fixup any virtual function entries from virtual bases
+ that have different deltas. This has to come after we do the
+ pending hard virtuals, as we might have a function that comes
+ from multiple virtual base instances that is only overridden
+ by a hard virtual above. */
+ vbases = CLASSTYPE_VBASECLASSES (t);
+ while (vbases)
+ {
+ /* We might be able to shorten the amount of work we do by
+ only doing this for vtables that come from virtual bases
+ that have differing offsets, but don't want to miss any
+ entries. */
+ fixup_vtable_deltas (vbases, 1, t);
+ vbases = TREE_CHAIN (vbases);
+ }
+ }
/* Under our model of GC, every C++ class gets its own virtual
function table, at least virtually. */
- if (pending_virtuals || (flag_rtti && TYPE_VIRTUAL_P (t)))
+ if (pending_virtuals)
{
pending_virtuals = nreverse (pending_virtuals);
/* We must enter these virtuals into the table. */
if (first_vfn_base_index < 0)
{
- /* The first slot is for the rtti offset. */
- pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
-
/* 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);
+ /* The first slot is for the rtti offset. */
+ pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
+
+ set_rtti_entry (pending_virtuals,
+ convert (ssizetype, 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);
-
- 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
@@ -3877,42 +4110,6 @@ finish_struct_1 (t, warn_anon)
}
}
- /* Now add the tags, if any, to the list of TYPE_DECLs
- defined for this type. */
- if (CLASSTYPE_TAGS (t))
- {
- x = CLASSTYPE_TAGS (t);
- last_x = tree_last (TYPE_FIELDS (t));
- while (x)
- {
- tree tag = TYPE_NAME (TREE_VALUE (x));
-
- /* Check to see if it is already there. This will be the case if
- was do enum { red; } color; */
- if (chain_member (tag, TYPE_FIELDS (t)))
- {
- x = TREE_CHAIN (x);
- continue;
- }
-
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG)
- {
- /* Notify dwarfout.c that this TYPE_DECL node represent a
- gratuitous typedef. */
- DECL_IGNORED_P (tag) = 1;
- }
-#endif /* DWARF_DEBUGGING_INFO */
-
- TREE_NONLOCAL_FLAG (TREE_VALUE (x)) = 0;
- x = TREE_CHAIN (x);
- last_x = chainon (last_x, tag);
- }
- if (TYPE_FIELDS (t) == NULL_TREE)
- TYPE_FIELDS (t) = last_x;
- CLASSTYPE_LOCAL_TYPEDECLS (t) = 1;
- }
-
if (TYPE_HAS_CONSTRUCTOR (t))
{
tree vfields = CLASSTYPE_VFIELDS (t);
@@ -3932,9 +4129,6 @@ finish_struct_1 (t, warn_anon)
else if (TYPE_NEEDS_CONSTRUCTING (t))
build_class_init_list (t);
- if (! IS_SIGNATURE (t))
- embrace_waiting_friends (t);
-
/* Write out inline function definitions. */
do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t));
CLASSTYPE_INLINE_FRIENDS (t) = 0;
@@ -3942,7 +4136,7 @@ finish_struct_1 (t, warn_anon)
if (CLASSTYPE_VSIZE (t) != 0)
{
#if 0
- /* This is now done above. */
+ /* This is now done above. */
if (DECL_FIELD_CONTEXT (vfield) != t)
{
tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0);
@@ -3961,13 +4155,13 @@ finish_struct_1 (t, warn_anon)
}
#endif
- /* In addition to this one, all the other vfields should be listed. */
+ /* In addition to this one, all the other vfields should be listed. */
/* Before that can be done, we have to have FIELD_DECLs for them, and
a place to find them. */
TYPE_NONCOPIED_PARTS (t) = build_tree_list (default_conversion (TYPE_BINFO_VTABLE (t)), vfield);
if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
- && DECL_VINDEX (TREE_VEC_ELT (method_vec, 0)) == NULL_TREE)
+ && DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE)
cp_warning ("`%#T' has virtual functions but non-virtual destructor",
t);
}
@@ -3975,22 +4169,17 @@ finish_struct_1 (t, warn_anon)
/* Make the rtl for any new vtables we have created, and unmark
the base types we marked. */
finish_vtbls (TYPE_BINFO (t), 1, t);
- TYPE_BEING_DEFINED (t) = 0;
hack_incomplete_structures (t);
#if 0
if (TYPE_NAME (t) && TYPE_IDENTIFIER (t))
undo_template_name_overload (TYPE_IDENTIFIER (t), 1);
#endif
- if (current_class_type)
- popclass (0);
- else
- error ("trying to finish struct, but kicked out due to previous parse errors.");
resume_momentary (old);
- if (flag_cadillac)
- cadillac_finish_struct (t);
+ if (warn_overloaded_virtual)
+ warn_hidden (t);
#if 0
/* This has to be done after we have sorted out what to do with
@@ -3999,13 +4188,12 @@ finish_struct_1 (t, warn_anon)
{
/* Be smarter about nested classes here. If a type is nested,
only output it if we would output the enclosing type. */
- if (DECL_CONTEXT (TYPE_NAME (t))
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (TYPE_NAME (t)))) == 't')
- DECL_IGNORED_P (TYPE_NAME (t)) = TREE_ASM_WRITTEN (TYPE_NAME (t));
+ if (DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (t)))
+ DECL_IGNORED_P (TYPE_MAIN_DECL (t)) = TREE_ASM_WRITTEN (TYPE_MAIN_DECL (t));
}
#endif
- if (write_symbols != DWARF_DEBUG)
+ if (write_symbols != DWARF_DEBUG && write_symbols != DWARF2_DEBUG)
{
/* If the type has methods, we want to think about cutting down
the amount of symbol table stuff we output. The value stored in
@@ -4013,7 +4201,10 @@ finish_struct_1 (t, warn_anon)
For example, if a member function is seen and we decide to
write out that member function, then we can change the value
of the DECL_IGNORED_P slot, and the type will be output when
- that member function's debug info is written out. */
+ that member function's debug info is written out.
+
+ We can't do this with DWARF, which does not support name
+ references between translation units. */
if (CLASSTYPE_METHOD_VEC (t))
{
extern tree pending_vtables;
@@ -4021,16 +4212,19 @@ finish_struct_1 (t, warn_anon)
/* Don't output full info about any type
which does not have its implementation defined here. */
if (TYPE_VIRTUAL_P (t) && write_virtuals == 2)
- TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t))
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t))
= (value_member (TYPE_IDENTIFIER (t), pending_vtables) == 0);
else if (CLASSTYPE_INTERFACE_ONLY (t))
- TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1;
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
+#if 0
+ /* XXX do something about this. */
else if (CLASSTYPE_INTERFACE_UNKNOWN (t))
/* Only a first approximation! */
- TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1;
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
+#endif
}
else if (CLASSTYPE_INTERFACE_ONLY (t))
- TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1;
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
}
/* Finish debugging output for this type. */
@@ -4040,16 +4234,19 @@ finish_struct_1 (t, warn_anon)
}
tree
-finish_struct (t, list_of_fieldlists, warn_anon)
- tree t;
- tree list_of_fieldlists;
+finish_struct (t, list_of_fieldlists, attributes, warn_anon)
+ tree t, list_of_fieldlists, attributes;
int warn_anon;
{
- tree fields = NULL_TREE, fn_fields, *tail;
- tree *tail_user_methods = &CLASSTYPE_METHODS (t);
+ tree fields = NULL_TREE;
+ tree *tail = &TYPE_METHODS (t);
+ tree specializations = NULL_TREE;
+ tree *specialization_tail = &specializations;
tree name = TYPE_NAME (t);
tree x, last_x = NULL_TREE;
- enum access_type access;
+ tree access;
+ tree dummy = NULL_TREE;
+ tree next_x = NULL_TREE;
if (TREE_CODE (name) == TYPE_DECL)
{
@@ -4071,34 +4268,53 @@ finish_struct (t, list_of_fieldlists, warn_anon)
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)
+ /* Move our self-reference declaration to the end of the field list so
+ any real field with the same name takes precedence. */
+ if (list_of_fieldlists
+ && TREE_VALUE (list_of_fieldlists)
+ && DECL_ARTIFICIAL (TREE_VALUE (list_of_fieldlists)))
{
- if (list_of_fieldlists
- && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default)
- TREE_PURPOSE (list_of_fieldlists) = (tree)access_public;
+ dummy = TREE_VALUE (list_of_fieldlists);
+ list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
}
- else if (list_of_fieldlists
- && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default)
- TREE_PURPOSE (list_of_fieldlists) = (tree)access_private;
+
+ if (last_x && list_of_fieldlists)
+ TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
while (list_of_fieldlists)
{
- access = (enum access_type)TREE_PURPOSE (list_of_fieldlists);
+ access = TREE_PURPOSE (list_of_fieldlists);
+
+ /* For signatures, we made all methods `public' in the parser and
+ reported an error if a access specifier was used. */
+ if (access == access_default_node)
+ {
+ if (CLASSTYPE_DECLARED_CLASS (t) == 0)
+ access = access_public_node;
+ else
+ access = access_private_node;
+ }
- for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x))
+ for (x = TREE_VALUE (list_of_fieldlists); x; x = next_x)
{
- TREE_PRIVATE (x) = access == access_private;
- TREE_PROTECTED (x) = access == access_protected;
+ next_x = TREE_CHAIN (x);
+
+ TREE_PRIVATE (x) = access == access_private_node;
+ TREE_PROTECTED (x) = access == access_protected_node;
+
+ if (TREE_CODE (x) == TEMPLATE_DECL)
+ {
+ TREE_PRIVATE (DECL_RESULT (x)) = TREE_PRIVATE (x);
+ TREE_PROTECTED (DECL_RESULT (x)) = TREE_PROTECTED (x);
+ }
+
+ /* A name N used in a class S shall refer to the same declaration
+ in its context and when re-evaluated in the completed scope of S.
- /* 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
+ if (TREE_CODE (x) != TYPE_DECL && TREE_CODE (x) != USING_DECL
+ && ! (TREE_CODE (x) == TEMPLATE_DECL
+ && TREE_CODE (DECL_RESULT (x)) == TYPE_DECL)
&& TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL)
{
tree name = DECL_NAME (x);
@@ -4111,6 +4327,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
icv = NULL_TREE;
if (icv
+ && flag_optional_diags
/* Don't complain about constructors. */
&& name != constructor_name (current_class_type)
/* Or inherited names. */
@@ -4119,35 +4336,42 @@ finish_struct (t, list_of_fieldlists, warn_anon)
&& !(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);
+ cp_pedwarn_at ("declaration of identifier `%D' as `%+#D'",
+ name, x);
+ cp_pedwarn_at ("conflicts with other use in class as `%#D'",
+ icv);
}
}
- if (TREE_CODE (x) == FUNCTION_DECL)
+ if (TREE_CODE (x) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (x))
{
+ DECL_CLASS_CONTEXT (x) = t;
+
if (last_x)
- TREE_CHAIN (last_x) = TREE_CHAIN (x);
- /* Link x onto end of fn_fields and CLASSTYPE_METHODS. */
+ TREE_CHAIN (last_x) = next_x;
+
+ if (DECL_TEMPLATE_SPECIALIZATION (x))
+ /* We don't enter the specialization into the class
+ method vector since specializations don't affect
+ overloading. Instead we keep track of the
+ specializations, and process them after the method
+ vector is complete. */
+ {
+ *specialization_tail = x;
+ specialization_tail = &TREE_CHAIN (x);
+ TREE_CHAIN (x) = NULL_TREE;
+ continue;
+ }
+
+ /* Link x onto end of TYPE_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 (TREE_CODE (x) != TYPE_DECL)
+ DECL_FIELD_CONTEXT (x) = t;
if (! fields)
fields = x;
@@ -4166,17 +4390,122 @@ finish_struct (t, list_of_fieldlists, warn_anon)
}
}
+ /* Now add the tags, if any, to the list of TYPE_DECLs
+ defined for this type. */
+ if (CLASSTYPE_TAGS (t) || dummy)
+ {
+ /* The list of tags was built up in pushtag in reverse order; we need
+ to fix that so that enumerators will be processed in forward order
+ in template instantiation. */
+ CLASSTYPE_TAGS (t) = x = nreverse (CLASSTYPE_TAGS (t));
+ while (x)
+ {
+ tree tag_type = TREE_VALUE (x);
+ tree tag = TYPE_MAIN_DECL (TREE_VALUE (x));
+
+ if (IS_AGGR_TYPE_CODE (TREE_CODE (tag_type))
+ && CLASSTYPE_IS_TEMPLATE (tag_type))
+ tag = CLASSTYPE_TI_TEMPLATE (tag_type);
+
+ TREE_NONLOCAL_FLAG (tag_type) = 0;
+ x = TREE_CHAIN (x);
+ last_x = chainon (last_x, tag);
+ }
+ if (dummy)
+ last_x = chainon (last_x, dummy);
+ if (fields == NULL_TREE)
+ fields = last_x;
+ CLASSTYPE_LOCAL_TYPEDECLS (t) = 1;
+ }
+
*tail = NULL_TREE;
- *tail_user_methods = NULL_TREE;
TYPE_FIELDS (t) = fields;
- if (0 && processing_template_defn)
+ cplus_decl_attributes (t, attributes, NULL_TREE);
+
+ if (processing_template_decl)
{
- CLASSTYPE_METHOD_VEC (t) = finish_struct_methods (t, fn_fields, 1);
- return t;
+ tree d = getdecls ();
+ for (; d; d = TREE_CHAIN (d))
+ {
+ /* If this is the decl for the class or one of the template
+ parms, we've seen all the injected decls. */
+ if ((TREE_CODE (d) == TYPE_DECL
+ && (TREE_TYPE (d) == t
+ || TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TEMPLATE_PARM))
+ || TREE_CODE (d) == CONST_DECL)
+ break;
+ /* Don't inject cache decls. */
+ else if (IDENTIFIER_TEMPLATE (DECL_NAME (d)))
+ continue;
+ DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t))
+ = tree_cons (NULL_TREE, d,
+ DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t)));
+ }
+ CLASSTYPE_METHOD_VEC (t)
+ = finish_struct_methods (t, TYPE_METHODS (t), 1);
+ TYPE_SIZE (t) = integer_zero_node;
+ }
+ else
+ t = finish_struct_1 (t, warn_anon);
+
+ TYPE_BEING_DEFINED (t) = 0;
+
+ /* Now, figure out which member templates we're specializing. */
+ for (x = specializations; x != NULL_TREE; x = TREE_CHAIN (x))
+ {
+ tree spec_args;
+ tree fn;
+ int pending_specialization;
+
+ if (uses_template_parms (t))
+ /* If t is a template class, and x is a specialization, then x
+ is itself really a template. Due to the vagaries of the
+ parser, however, we will have a handle to a function
+ declaration, rather than the template declaration, at this
+ point. */
+ {
+ my_friendly_assert (DECL_TEMPLATE_INFO (x) != NULL_TREE, 0);
+ my_friendly_assert (DECL_TI_TEMPLATE (x) != NULL_TREE, 0);
+ fn = DECL_TI_TEMPLATE (x);
+ }
+ else
+ fn = x;
+
+ /* We want the specialization arguments, which will be the
+ innermost ones. */
+ if (DECL_TI_ARGS (fn) && TREE_CODE (DECL_TI_ARGS (fn)) == TREE_VEC)
+ spec_args
+ = TREE_VEC_ELT (DECL_TI_ARGS (fn), 0);
+ else
+ spec_args = DECL_TI_ARGS (fn);
+
+ pending_specialization
+ = TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn));
+ check_explicit_specialization
+ (lookup_template_function (DECL_NAME (fn), spec_args),
+ fn, 0, 1 | (8 * pending_specialization));
+ TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn)) = 0;
+
+ /* Now, the assembler name will be correct for fn, so we
+ make its RTL. */
+ DECL_RTL (fn) = 0;
+ make_decl_rtl (fn, NULL_PTR, 1);
+
+ if (x != fn)
+ {
+ DECL_RTL (x) = 0;
+ make_decl_rtl (x, NULL_PTR, 1);
+ }
}
+
+ if (current_class_type)
+ popclass (0);
else
- return finish_struct_1 (t, warn_anon);
+ error ("trying to finish struct, but kicked out due to previous parse errors.");
+
+ return t;
}
/* Return non-zero if the effective type of INSTANCE is static.
@@ -4185,6 +4514,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
*NONNULL is set iff INSTANCE can be known to be nonnull, regardless
of our knowledge of its type. */
+
int
resolves_to_fixed_type_p (instance, nonnull)
tree instance;
@@ -4219,13 +4549,6 @@ resolves_to_fixed_type_p (instance, nonnull)
return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
case RTL_EXPR:
- /* This is a call to `new', hence it's never zero. */
- if (TREE_CALLS_NEW (instance))
- {
- if (nonnull)
- *nonnull = 1;
- return 1;
- }
return 0;
case PLUS_EXPR:
@@ -4249,10 +4572,6 @@ resolves_to_fixed_type_p (instance, nonnull)
case COMPONENT_REF:
return resolves_to_fixed_type_p (TREE_OPERAND (instance, 1), nonnull);
- case WITH_CLEANUP_EXPR:
- if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
- /* fall through... */
case VAR_DECL:
case FIELD_DECL:
if (TREE_CODE (TREE_TYPE (instance)) == ARRAY_TYPE
@@ -4262,7 +4581,7 @@ resolves_to_fixed_type_p (instance, nonnull)
*nonnull = 1;
return 1;
}
- /* fall through... */
+ /* fall through... */
case TARGET_EXPR:
case PARM_DECL:
if (IS_AGGR_TYPE (TREE_TYPE (instance)))
@@ -4273,7 +4592,7 @@ resolves_to_fixed_type_p (instance, nonnull)
}
else if (nonnull)
{
- if (instance == current_class_decl
+ if (instance == current_class_ptr
&& flag_this_is_variable <= 0)
{
/* Some people still use `this = 0' inside destructors. */
@@ -4305,8 +4624,16 @@ init_class_processing ()
current_lang_base = (tree *)xmalloc(current_lang_stacksize * sizeof (tree));
current_lang_stack = current_lang_base;
+ access_default_node = build_int_2 (0, 0);
+ access_public_node = build_int_2 (1, 0);
+ access_protected_node = build_int_2 (2, 0);
+ access_private_node = build_int_2 (3, 0);
+ access_default_virtual_node = build_int_2 (4, 0);
+ access_public_virtual_node = build_int_2 (5, 0);
+ access_protected_virtual_node = build_int_2 (6, 0);
+ access_private_virtual_node = build_int_2 (7, 0);
+
/* Keep these values lying around. */
- the_null_vtable_entry = build_vtable_entry (integer_zero_node, integer_zero_node);
base_layout_decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, error_mark_node);
TREE_TYPE (base_layout_decl) = make_node (RECORD_TYPE);
@@ -4352,6 +4679,7 @@ pushclass (type, modify)
tree type;
int modify;
{
+ type = TYPE_MAIN_VARIANT (type);
push_memoized_context (type, modify);
current_class_depth++;
@@ -4359,9 +4687,9 @@ pushclass (type, modify)
*current_class_stack++ = current_class_type;
if (current_class_stack >= current_class_base + current_class_stacksize)
{
- current_class_base =
- (tree *)xrealloc (current_class_base,
- sizeof (tree) * (current_class_stacksize + 10));
+ current_class_base
+ = (tree *)xrealloc (current_class_base,
+ sizeof (tree) * (current_class_stacksize + 10));
current_class_stack = current_class_base + current_class_stacksize;
current_class_stacksize += 10;
}
@@ -4382,6 +4710,11 @@ pushclass (type, modify)
pushlevel_class ();
+#if 0
+ if (CLASSTYPE_TEMPLATE_INFO (type))
+ overload_template_name (type);
+#endif
+
if (modify)
{
tree tags;
@@ -4394,15 +4727,15 @@ pushclass (type, modify)
else
current_function_decl = NULL_TREE;
- if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
- declare_uninstantiated_type_level ();
- else if (type != previous_class_type || current_class_depth > 1)
+ if (type != previous_class_type || current_class_depth > 1)
{
+#ifdef MI_MATRIX
build_mi_matrix (type);
push_class_decls (type);
free_mi_matrix ();
- if (current_class_depth == 1)
- previous_class_type = type;
+#else
+ push_class_decls (type);
+#endif
}
else
{
@@ -4423,35 +4756,33 @@ pushclass (type, modify)
unuse_fields (type);
}
- if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (type)))
- overload_template_name (current_class_name, 0);
-
for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags))
{
- TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 1;
+ tree tag_type = TREE_VALUE (tags);
+
+ TREE_NONLOCAL_FLAG (tag_type) = 1;
if (! TREE_PURPOSE (tags))
continue;
- pushtag (TREE_PURPOSE (tags), TREE_VALUE (tags), 0);
+ if (! (IS_AGGR_TYPE_CODE (TREE_CODE (tag_type))
+ && CLASSTYPE_IS_TEMPLATE (tag_type)))
+ pushtag (TREE_PURPOSE (tags), tag_type, 0);
+ else
+ pushdecl_class_level (CLASSTYPE_TI_TEMPLATE (tag_type));
}
current_function_decl = this_fndecl;
}
-
- if (flag_cadillac)
- cadillac_push_class (type);
}
/* Get out of the current class scope. If we were in a class scope
previously, that is the one popped to. The flag MODIFY tells whether
the current scope declarations needs to be modified as a result of
popping to the previous scope. 0 is used for class definitions. */
+
void
popclass (modify)
int modify;
{
- if (flag_cadillac)
- cadillac_pop_class ();
-
if (modify < 0)
{
/* Back this old class out completely. */
@@ -4482,8 +4813,6 @@ popclass (modify)
TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
tags = TREE_CHAIN (tags);
}
- if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type)))
- undo_template_name_overload (current_class_name, 0);
}
/* Force clearing of IDENTIFIER_CLASS_VALUEs after a class definition,
@@ -4494,7 +4823,7 @@ popclass (modify)
this really only frees the obstack used for these decls.
That's why it had to be moved down here. */
if (modify)
- pop_class_decls (current_class_type);
+ pop_class_decls ();
current_class_depth--;
current_class_type = *--current_class_stack;
@@ -4506,6 +4835,21 @@ popclass (modify)
;
}
+/* Returns 1 if current_class_type is either T or a nested type of T. */
+
+int
+currently_open_class (t)
+ tree t;
+{
+ int i;
+ if (t == current_class_type)
+ return 1;
+ for (i = 0; i < current_class_depth; ++i)
+ if (current_class_stack [-i*2 - 1] == t)
+ return 1;
+ return 0;
+}
+
/* When entering a class scope, all enclosing class scopes' names with
static meaning (static variables, static functions, types and enumerators)
have to be visible. This recursive function calls pushclass for all
@@ -4520,10 +4864,14 @@ push_nested_class (type, modify)
{
tree context;
- if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type))
+ my_friendly_assert (!type || TREE_CODE (type) != NAMESPACE_DECL, 980711);
+
+ if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type)
+ || TREE_CODE (type) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
return;
- context = DECL_CONTEXT (TYPE_NAME (type));
+ context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
if (context && TREE_CODE (context) == RECORD_TYPE)
push_nested_class (context, 2);
@@ -4536,7 +4884,7 @@ void
pop_nested_class (modify)
int modify;
{
- tree context = DECL_CONTEXT (TYPE_NAME (current_class_type));
+ tree context = DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type));
popclass (modify);
if (context && TREE_CODE (context) == RECORD_TYPE)
@@ -4553,14 +4901,14 @@ push_lang_context (name)
*current_lang_stack++ = current_lang_name;
if (current_lang_stack >= current_lang_base + current_lang_stacksize)
{
- current_lang_base =
- (tree *)xrealloc (current_lang_base,
- sizeof (tree) * (current_lang_stacksize + 10));
+ current_lang_base
+ = (tree *)xrealloc (current_lang_base,
+ sizeof (tree) * (current_lang_stacksize + 10));
current_lang_stack = current_lang_base + current_lang_stacksize;
current_lang_stacksize += 10;
}
- if (name == lang_name_cplusplus)
+ if (name == lang_name_cplusplus || name == lang_name_java)
{
strict_prototype = strict_prototypes_lang_cplusplus;
current_lang_name = name;
@@ -4572,44 +4920,64 @@ push_lang_context (name)
}
else
error ("language string `\"%s\"' not recognized", IDENTIFIER_POINTER (name));
-
- if (flag_cadillac)
- cadillac_push_lang (name);
}
/* Get out of the current language scope. */
+
void
pop_lang_context ()
{
- if (flag_cadillac)
- cadillac_pop_lang ();
-
current_lang_name = *--current_lang_stack;
- if (current_lang_name == lang_name_cplusplus)
+ if (current_lang_name == lang_name_cplusplus
+ || current_lang_name == lang_name_java)
strict_prototype = strict_prototypes_lang_cplusplus;
else if (current_lang_name == lang_name_c)
strict_prototype = strict_prototypes_lang_c;
}
+
+/* Type instantiation routines. */
-int
-root_lang_context_p ()
+static tree
+validate_lhs (lhstype, complain)
+ tree lhstype;
+ int complain;
{
- return current_lang_stack == current_lang_base;
+ if (TYPE_PTRMEMFUNC_P (lhstype))
+ lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
+
+ if (TREE_CODE (lhstype) == POINTER_TYPE)
+ {
+ if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
+ lhstype = TREE_TYPE (lhstype);
+ else
+ {
+ if (complain)
+ error ("invalid type combination for overload");
+ return error_mark_node;
+ }
+ }
+ return lhstype;
}
-
-/* Type instantiation routines. */
-/* This function will instantiate the type of the expression given
- in RHS to match the type of LHSTYPE. If LHSTYPE is NULL_TREE,
- or other errors exist, the TREE_TYPE of RHS will be ERROR_MARK_NODE.
+/* This function will instantiate the type of the expression given in
+ RHS to match the type of LHSTYPE. If errors exist, then return
+ error_mark_node. If only complain is COMPLAIN is set. If we are
+ not complaining, never modify rhs, as overload resolution wants to
+ try many possible instantiations, in hopes that at least one will
+ work.
This function is used in build_modify_expr, convert_arguments,
build_c_cast, and compute_conversion_costs. */
+
tree
instantiate_type (lhstype, rhs, complain)
tree lhstype, rhs;
int complain;
{
+ tree explicit_targs = NULL_TREE;
+ int template_only = 0;
+
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
if (complain)
@@ -4618,7 +4986,19 @@ instantiate_type (lhstype, rhs, complain)
}
if (TREE_TYPE (rhs) != NULL_TREE && ! (type_unknown_p (rhs)))
- return rhs;
+ {
+ if (comptypes (lhstype, TREE_TYPE (rhs), 1))
+ return rhs;
+ if (complain)
+ cp_error ("argument of type `%T' does not match `%T'",
+ TREE_TYPE (rhs), lhstype);
+ return error_mark_node;
+ }
+
+ /* We don't overwrite rhs if it is an overloaded function.
+ Copying it would destroy the tree link. */
+ if (TREE_CODE (rhs) != OVERLOAD)
+ rhs = copy_node (rhs);
/* This should really only be used when attempting to distinguish
what sort of a pointer to function we have. For now, any
@@ -4637,14 +5017,18 @@ instantiate_type (lhstype, rhs, complain)
case INDIRECT_REF:
case ARRAY_REF:
- TREE_TYPE (rhs) = lhstype;
- lhstype = build_pointer_type (lhstype);
- TREE_OPERAND (rhs, 0)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
- if (TREE_OPERAND (rhs, 0) == error_mark_node)
- return error_mark_node;
+ {
+ tree new_rhs;
- return rhs;
+ new_rhs = instantiate_type (build_pointer_type (lhstype),
+ TREE_OPERAND (rhs, 0), complain);
+ if (new_rhs == error_mark_node)
+ return error_mark_node;
+
+ TREE_TYPE (rhs) = lhstype;
+ TREE_OPERAND (rhs, 0) = new_rhs;
+ return rhs;
+ }
case NOP_EXPR:
rhs = copy_node (TREE_OPERAND (rhs, 0));
@@ -4671,9 +5055,13 @@ instantiate_type (lhstype, rhs, complain)
return error_mark_node;
return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function));
}
+ mark_used (function);
return function;
}
+ /* I could not trigger this code. MvL */
+ my_friendly_abort (980326);
+#if 0
my_friendly_assert (TREE_CODE (field) == FIELD_DECL, 178);
my_friendly_assert (!(TREE_CODE (TREE_TYPE (field)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (field)) == METHOD_TYPE),
@@ -4687,6 +5075,7 @@ instantiate_type (lhstype, rhs, complain)
if (field)
{
TREE_OPERAND (rhs, 1) = field;
+ mark_used (field);
return rhs;
}
@@ -4713,144 +5102,194 @@ instantiate_type (lhstype, rhs, complain)
error ("no appropriate overload exists for COMPONENT_REF");
return error_mark_node;
}
+#endif
return rhs;
}
- case TREE_LIST:
- {
- tree elem, baselink, name;
- int globals = overloaded_globals_p (rhs);
+ case OFFSET_REF:
+ /* This can happen if we are forming a pointer-to-member for a
+ member template. */
+ rhs = TREE_OPERAND (rhs, 1);
+ my_friendly_assert (TREE_CODE (rhs) == TEMPLATE_ID_EXPR, 0);
+
+ /* Fall through. */
-#if 0 /* obsolete */
- /* If there's only one function we know about, return that. */
- if (globals > 0 && TREE_CHAIN (rhs) == NULL_TREE)
- return TREE_VALUE (rhs);
-#endif
+ case TEMPLATE_ID_EXPR:
+ {
+ explicit_targs = TREE_OPERAND (rhs, 1);
+ template_only = 1;
+ rhs = TREE_OPERAND (rhs, 0);
+ }
+ /* fall through */
+ my_friendly_assert (TREE_CODE (rhs) == OVERLOAD, 980401);
- /* First look for an exact match. Search either overloaded
- functions or member functions. May have to undo what
- `default_conversion' might do to lhstype. */
+ case OVERLOAD:
+ {
+ tree elem, elems;
- if (TYPE_PTRMEMFUNC_P (lhstype))
- lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
+ /* Check that the LHSTYPE and the RHS are reasonable. */
+ lhstype = validate_lhs (lhstype, complain);
+ if (lhstype == error_mark_node)
+ return lhstype;
- if (TREE_CODE (lhstype) == POINTER_TYPE)
- if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
- lhstype = TREE_TYPE (lhstype);
- else
- {
- if (complain)
- error ("invalid type combination for overload");
- return error_mark_node;
- }
-
- if (TREE_CODE (lhstype) != FUNCTION_TYPE && globals > 0)
+ if (TREE_CODE (lhstype) != FUNCTION_TYPE
+ && TREE_CODE (lhstype) != METHOD_TYPE)
{
if (complain)
- cp_error ("cannot resolve overloaded function `%D' based on non-function type",
- TREE_PURPOSE (rhs));
+ cp_error("cannot resolve overloaded function `%D' "
+ "based on non-function type",
+ DECL_NAME (OVL_FUNCTION (rhs)));
return error_mark_node;
}
-
- if (globals > 0)
+
+ /* Look for an exact match, by searching through the
+ overloaded functions. */
+ if (template_only)
+ /* If we're processing a template-id, only a template
+ function can match, so we don't look through the
+ overloaded functions. */
+ ;
+ else for (elems = rhs; elems; elems = OVL_CHAIN (elems))
{
- elem = get_first_fn (rhs);
- while (elem)
- if (! comptypes (lhstype, TREE_TYPE (elem), 1))
- elem = DECL_CHAIN (elem);
- else
+ elem = OVL_FUNCTION (elems);
+ if (comptypes (lhstype, TREE_TYPE (elem), 1))
+ {
+ mark_used (elem);
return elem;
+ }
+ }
- /* No exact match found, look for a compatible template. */
- {
- tree save_elem = 0;
- for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem))
- if (TREE_CODE (elem) == TEMPLATE_DECL)
+ /* No overloaded function was an exact match. See if we can
+ instantiate some template to match. */
+ {
+ tree save_elem = 0;
+ elems = rhs;
+ if (TREE_CODE (elems) == TREE_LIST)
+ elems = TREE_VALUE (rhs);
+ for (; elems; elems = OVL_NEXT (elems))
+ if (TREE_CODE (elem = OVL_CURRENT (elems)) == TEMPLATE_DECL)
+ {
+ int n = DECL_NTPARMS (elem);
+ tree t = make_scratch_vec (n);
+ int i;
+ i = type_unification
+ (DECL_INNERMOST_TEMPLATE_PARMS (elem), t,
+ TYPE_ARG_TYPES (TREE_TYPE (elem)),
+ TYPE_ARG_TYPES (lhstype), explicit_targs, DEDUCE_EXACT, 1);
+ if (i == 0)
{
- int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem));
- tree *t = (tree *) alloca (sizeof (tree) * n);
- int i, d = 0;
- i = type_unification (DECL_TEMPLATE_PARMS (elem), t,
- TYPE_ARG_TYPES (TREE_TYPE (elem)),
- TYPE_ARG_TYPES (lhstype), &d, 0);
- if (i == 0)
+ if (save_elem)
{
- if (save_elem)
- {
- cp_error ("ambiguous template instantiation converting to `%#T'", lhstype);
- return error_mark_node;
- }
- save_elem = instantiate_template (elem, t);
- /* Check the return type. */
- if (! comptypes (TREE_TYPE (lhstype),
- TREE_TYPE (TREE_TYPE (save_elem)), 1))
- save_elem = 0;
+ cp_error ("ambiguous template instantiation converting to `%#T'", lhstype);
+ return error_mark_node;
}
+ save_elem = instantiate_template (elem, t);
+ /* Check the return type. */
+ if (! comptypes (TREE_TYPE (lhstype),
+ TREE_TYPE (TREE_TYPE (save_elem)), 1))
+ save_elem = 0;
}
- if (save_elem)
- return save_elem;
+ }
+ if (save_elem)
+ {
+ mark_used (save_elem);
+ return save_elem;
}
+ }
- /* No match found, look for a compatible function. */
- elem = get_first_fn (rhs);
- while (elem && comp_target_types (lhstype,
- TREE_TYPE (elem), 1) <= 0)
- elem = DECL_CHAIN (elem);
- if (elem)
+ /* There's no exact match, and no templates can be
+ instantiated to match. The last thing we try is to see if
+ some ordinary overloaded function is close enough. If
+ we're only looking for template functions, we don't do
+ this. */
+ if (!template_only)
+ {
+ for (elems = rhs; elems; elems = OVL_NEXT (elems))
+ {
+ elem = OVL_CURRENT (elems);
+ if (comp_target_types (lhstype, TREE_TYPE (elem), 1) > 0)
+ break;
+ }
+ if (elems)
{
tree save_elem = elem;
- elem = DECL_CHAIN (elem);
- while (elem && comp_target_types (lhstype,
- TREE_TYPE (elem), 0) <= 0)
- elem = DECL_CHAIN (elem);
- if (elem)
+ for (elems = OVL_CHAIN (elems); elems;
+ elems = OVL_CHAIN (elems))
+ {
+ elem = OVL_FUNCTION (elems);
+ if (comp_target_types (lhstype, TREE_TYPE (elem), 0) > 0)
+ break;
+ }
+ if (elems)
{
if (complain)
{
- cp_error ("cannot resolve overload to target type `%#T'",
- lhstype);
- cp_error_at (" ambiguity between `%#D'", save_elem);
+ cp_error
+ ("cannot resolve overload to target type `%#T'",
+ lhstype);
+ cp_error_at (" ambiguity between `%#D'", save_elem);
cp_error_at (" and `%#D', at least", elem);
}
return error_mark_node;
}
+ mark_used (save_elem);
return save_elem;
}
- if (complain)
- {
- cp_error ("cannot resolve overload to target type `%#T'",
- lhstype);
- cp_error (" because no suitable overload of function `%D' exists",
- TREE_PURPOSE (rhs));
- }
- return error_mark_node;
}
- if (TREE_NONLOCAL_FLAG (rhs))
+ /* We failed to find a match. */
+ if (complain)
{
- /* Got to get it as a baselink. */
- rhs = lookup_fnfields (TYPE_BINFO (current_class_type),
- TREE_PURPOSE (rhs), 0);
+ cp_error ("cannot resolve overload to target type `%#T'", lhstype);
+ cp_error
+ (" because no suitable overload of function `%D' exists",
+ DECL_NAME (OVL_FUNCTION (rhs)));
}
- else
+ return error_mark_node;
+ }
+
+ case TREE_LIST:
+ {
+ tree elem, baselink, name = NULL_TREE;
+
+ if (TREE_PURPOSE (rhs) == error_mark_node)
{
- my_friendly_assert (TREE_CHAIN (rhs) == NULL_TREE, 181);
- if (TREE_CODE (TREE_VALUE (rhs)) == TREE_LIST)
- rhs = TREE_VALUE (rhs);
- my_friendly_assert (TREE_CODE (TREE_VALUE (rhs)) == FUNCTION_DECL,
- 182);
+ /* Make sure we don't drop the non-local flag, as the old code
+ would rely on it. */
+ int nl = TREE_NONLOCAL_FLAG (rhs);
+ /* We don't need the type of this node. */
+ rhs = TREE_VALUE (rhs);
+ my_friendly_assert (TREE_NONLOCAL_FLAG (rhs) == nl, 980331);
}
+ /* Now we should have a baselink. */
+ my_friendly_assert (TREE_CODE (TREE_PURPOSE (rhs)) == TREE_VEC,
+ 980331);
+ /* First look for an exact match. Search member functions.
+ May have to undo what `default_conversion' might do to
+ lhstype. */
+
+ lhstype = validate_lhs (lhstype, complain);
+ if (lhstype == error_mark_node)
+ return lhstype;
+
+ my_friendly_assert (TREE_CHAIN (rhs) == NULL_TREE, 181);
+ my_friendly_assert (TREE_CODE (TREE_VALUE (rhs)) == FUNCTION_DECL
+ || TREE_CODE (TREE_VALUE (rhs)) == OVERLOAD,
+ 182);
+
for (baselink = rhs; baselink;
baselink = next_baselink (baselink))
{
elem = TREE_VALUE (baselink);
while (elem)
- if (comptypes (lhstype, TREE_TYPE (elem), 1))
- return elem;
+ if (comptypes (lhstype, TREE_TYPE (OVL_CURRENT (elem)), 1))
+ {
+ mark_used (OVL_CURRENT (elem));
+ return OVL_CURRENT (elem);
+ }
else
- elem = DECL_CHAIN (elem);
+ elem = OVL_NEXT (elem);
}
/* No exact match found, look for a compatible method. */
@@ -4858,25 +5297,30 @@ instantiate_type (lhstype, rhs, complain)
baselink = next_baselink (baselink))
{
elem = TREE_VALUE (baselink);
- while (elem && comp_target_types (lhstype,
- TREE_TYPE (elem), 1) <= 0)
- elem = DECL_CHAIN (elem);
+ for (; elem; elem = OVL_NEXT (elem))
+ if (comp_target_types (lhstype,
+ TREE_TYPE (OVL_CURRENT (elem)), 1) > 0)
+ break;
if (elem)
{
- tree save_elem = elem;
- elem = DECL_CHAIN (elem);
- while (elem && comp_target_types (lhstype,
- TREE_TYPE (elem), 0) <= 0)
- elem = DECL_CHAIN (elem);
+ tree save_elem = OVL_CURRENT (elem);
+ for (elem = OVL_NEXT (elem); elem; elem = OVL_NEXT (elem))
+ if (comp_target_types (lhstype,
+ TREE_TYPE (OVL_CURRENT (elem)), 0) > 0)
+ break;
if (elem)
{
if (complain)
error ("ambiguous overload for overloaded method requested");
return error_mark_node;
}
+ mark_used (save_elem);
return save_elem;
}
- name = DECL_NAME (TREE_VALUE (rhs));
+ name = rhs;
+ while (TREE_CODE (name) == TREE_LIST)
+ name = TREE_VALUE (name);
+ name = DECL_NAME (OVL_CURRENT (name));
#if 0
if (TREE_CODE (lhstype) == FUNCTION_TYPE && globals < 0)
{
@@ -5006,15 +5450,20 @@ instantiate_type (lhstype, rhs, complain)
error ("type for resolving address of overloaded function must be pointer type");
return error_mark_node;
}
- TREE_TYPE (rhs) = lhstype;
- lhstype = TREE_TYPE (lhstype);
{
- tree fn = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
+ tree fn = instantiate_type (TREE_TYPE (lhstype), TREE_OPERAND (rhs, 0), complain);
if (fn == error_mark_node)
return error_mark_node;
mark_addressable (fn);
+ TREE_TYPE (rhs) = lhstype;
TREE_OPERAND (rhs, 0) = fn;
TREE_CONSTANT (rhs) = staticp (fn);
+ if (TREE_CODE (lhstype) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
+ {
+ build_ptrmemfunc_type (lhstype);
+ rhs = build_ptrmemfunc (lhstype, rhs, 0);
+ }
}
return rhs;
@@ -5036,6 +5485,7 @@ instantiate_type (lhstype, rhs, complain)
this may have to look back through base types to find the
ultimate field name. (For single inheritance, these could
all be the same name. Who knows for multiple inheritance). */
+
static tree
get_vfield_name (type)
tree type;
@@ -5049,8 +5499,8 @@ get_vfield_name (type)
binfo = BINFO_BASETYPE (binfo, 0);
type = BINFO_TYPE (binfo);
- buf = (char *)alloca (sizeof (VFIELD_NAME_FORMAT)
- + TYPE_NAME_LENGTH (type) + 2);
+ buf = (char *) alloca (sizeof (VFIELD_NAME_FORMAT)
+ + TYPE_NAME_LENGTH (type) + 2);
sprintf (buf, VFIELD_NAME_FORMAT, TYPE_NAME_STRING (type));
return get_identifier (buf);
}
@@ -5077,6 +5527,7 @@ print_class_statistics ()
decls that may be cached in the previous_class_values list. For now, let's
use the permanent obstack, later we may create a dedicated obstack just
for this purpose. The effect is undone by pop_obstacks. */
+
void
maybe_push_cache_obstack ()
{
@@ -5084,3 +5535,49 @@ maybe_push_cache_obstack ()
if (current_class_depth == 1)
current_obstack = &permanent_obstack;
}
+
+/* Build a dummy reference to ourselves so Derived::Base (and A::A) works,
+ according to [class]:
+ The class-name is also inserted
+ into the scope of the class itself. For purposes of access checking,
+ the inserted class name is treated as if it were a public member name. */
+
+tree
+build_self_reference ()
+{
+ tree name = constructor_name (current_class_type);
+ tree value = build_lang_decl (TYPE_DECL, name, current_class_type);
+ DECL_NONLOCAL (value) = 1;
+ DECL_CONTEXT (value) = current_class_type;
+ DECL_CLASS_CONTEXT (value) = current_class_type;
+ CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
+ DECL_ARTIFICIAL (value) = 1;
+
+ pushdecl_class_level (value);
+ return value;
+}
+
+/* Returns 1 if TYPE contains only padding bytes. */
+
+int
+is_empty_class (type)
+ tree type;
+{
+ tree t;
+
+ if (type == error_mark_node)
+ return 0;
+
+ if (! IS_AGGR_TYPE (type))
+ return 0;
+
+ if (flag_new_abi)
+ return CLASSTYPE_SIZE (type) == integer_zero_node;
+
+ if (TYPE_BINFO_BASETYPES (type))
+ return 0;
+ t = TYPE_FIELDS (type);
+ while (t && TREE_CODE (t) != FIELD_DECL)
+ t = TREE_CHAIN (t);
+ return (t == NULL_TREE);
+}
diff --git a/contrib/gcc/cp/config-lang.in b/contrib/gcc/cp/config-lang.in
index 7a9a5c5..9b39d51 100644
--- a/contrib/gcc/cp/config-lang.in
+++ b/contrib/gcc/cp/config-lang.in
@@ -32,4 +32,10 @@ compilers="cc1plus\$(exeext)"
stagestuff="g++\$(exeext) g++-cross\$(exeext) cc1plus\$(exeext)"
-diff_excludes="-x cp/parse.c -x cp/parse.h"
+diff_excludes="-x parse.c -x parse.h"
+
+headers='$(CXX_EXTRA_HEADERS)'
+
+lib2funcs=cplib2.txt
+
+outputs=cp/Makefile
diff --git a/contrib/gcc/cp/cp-tree.def b/contrib/gcc/cp/cp-tree.def
new file mode 100644
index 0000000..dbbdb66
--- /dev/null
+++ b/contrib/gcc/cp/cp-tree.def
@@ -0,0 +1,240 @@
+/* This file contains the definitions and documentation for the
+ additional tree codes used in the GNU C++ compiler (see tree.def
+ for the standard codes).
+ Copyright (C) 1987, 1988, 1990, 1993 Free Software Foundation, Inc.
+ Hacked by Michael Tiemann (tiemann@cygnus.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/* Reference to the contents of an offset
+ (a value whose type is an OFFSET_TYPE).
+ Operand 0 is the object within which the offset is taken.
+ Operand 1 is the offset. The language independent OFFSET_REF
+ just won't work for us. */
+DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
+
+/* For NEW_EXPR, operand 0 is the placement list.
+ Operand 1 is the new-declarator.
+ Operand 2 is the initializer. */
+DEFTREECODE (NEW_EXPR, "nw_expr", 'e', 3)
+DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", 'e', 3)
+
+/* For DELETE_EXPR, operand 0 is the store to be destroyed.
+ Operand 1 is the value to pass to the destroying function
+ saying whether the store should be deallocated as well. */
+DEFTREECODE (DELETE_EXPR, "dl_expr", 'e', 2)
+DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", 'e', 2)
+
+/* 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).
+ The COMPLEXITY field holds the class level (usually 0). */
+DEFTREECODE (SCOPE_REF, "scope_ref", 'r', 2)
+
+/* When composing an object with a member, this is the result.
+ Operand 0 is the object. Operand 1 is the member (usually
+ a dereferenced pointer to member). */
+DEFTREECODE (MEMBER_REF, "member_ref", 'r', 2)
+
+/* Type conversion operator in C++. TREE_TYPE is type that this
+ operator converts to. Operand is expression to be converted. */
+DEFTREECODE (TYPE_EXPR, "type_expr", 'e', 1)
+
+/* For AGGR_INIT_EXPR, operand 0 is function which performs initialization,
+ operand 1 is argument list to initialization function,
+ and operand 2 is the slot which was allocated for this expression. */
+DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", 'e', 3)
+
+/* A throw expression. operand 0 is the expression, if there was one,
+ else it is NULL_TREE. */
+DEFTREECODE (THROW_EXPR, "throw_expr", 'e', 1)
+
+/* Initialization of a vector, used in build_new. Operand 0 is the target
+ of the initialization, operand 1 is the initializer, and operand 2 is
+ the number of elements. */
+DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", 'e', 3)
+
+/* Template definition. The following fields have the specified uses,
+ although there are other macros in cp-tree.h that should be used for
+ accessing this data.
+ DECL_ARGUMENTS template parm vector
+ DECL_TEMPLATE_INFO template text &c
+ DECL_VINDEX list of instantiations already produced;
+ only done for functions so far
+ For class template:
+ DECL_INITIAL associated templates (methods &c)
+ DECL_RESULT null
+ For non-class templates:
+ TREE_TYPE type of object to be constructed
+ DECL_RESULT decl for object to be created
+ (e.g., FUNCTION_DECL with tmpl parms used)
+ */
+DEFTREECODE (TEMPLATE_DECL, "template_decl", 'd', 0)
+
+/* Index into a template parameter list. The TEMPLATE_PARM_IDX gives
+ the index (from 0) of the parameter, while the TEMPLATE_PARM_LEVEL
+ gives the level (from 1) of the parameter.
+
+ Here's an example:
+
+ template <class T> // Index 0, Level 1.
+ struct S
+ {
+ template <class U, // Index 0, Level 2.
+ class V> // Index 1, Level 2.
+ void f();
+ };
+
+ The DESCENDANTS will be a chain of TEMPLATE_PARM_INDEXs descended
+ from this one. The first descendant will have the same IDX, but
+ its LEVEL will be one less. The TREE_CHAIN field is used to chain
+ together the descendants. The TEMPLATE_PARM_DECL is the
+ declaration of this parameter, either a TYPE_DECL or CONST_DECL.
+ The TEMPLATE_PARM_ORIG_LEVEL is the LEVEL of the most distant
+ parent, i.e., the LEVEL that the parameter originally had when it
+ was declared. For example, if we instantiate S<int>, we will have:
+
+ struct S<int>
+ {
+ template <class U, // Index 0, Level 1, Orig Level 2
+ class V> // Index 1, Level 1, Orig Level 2
+ void f();
+ };
+
+ The LEVEL is the level of the parameter when we are worrying about
+ the types of things; the ORIG_LEVEL is the level when we are
+ worrying about instantiating things. */
+DEFTREECODE (TEMPLATE_PARM_INDEX, "template_parm_index", 'x',
+ /* The addition of (sizeof(char*) - 1) in the next
+ expression is to ensure against the case where
+ sizeof(char*) does not evenly divide
+ sizeof(HOST_WIDE_INT). */
+ 2 + ((3 * sizeof (HOST_WIDE_INT) + sizeof(char*) - 1)
+ / sizeof (char*)))
+
+/* Index into a template parameter list. This parameter must be a type.
+ The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX. */
+DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", 't', 0)
+
+/* Index into a template parameter list. This parameter must be a type.
+ If it is used in signature of a template, TEMPLATE_INFO is NULL_TREE.
+ Otherwise it is used to declare a type like TT<int>.
+ The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX. */
+DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", 't', 0)
+
+/* A type designated by 'typename T::t'. */
+DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
+
+/* A thunk is a stub function.
+
+ Thunks are used to implement multiple inheritance:
+ At run-time, such a thunk subtracts THUNK_DELTA (an int, not a tree)
+ from the this pointer, and then jumps to DECL_INITIAL
+ (which is an ADDR_EXPR whose operand is a FUNCTION_DECL).
+
+ Other kinds of thunks may be defined later. */
+DEFTREECODE (THUNK_DECL, "thunk_decl", 'd', 0)
+
+/* A using declaration. DECL_INITIAL contains the specified scope.
+ This is not an alias, but is later expanded into multiple aliases. */
+DEFTREECODE (USING_DECL, "using_decl", 'd', 0)
+
+/* An un-parsed default argument. Looks like an IDENTIFIER_NODE. */
+DEFTREECODE (DEFAULT_ARG, "default_arg", 'c', 2)
+
+/* A template-id, like foo<int>. The first operand is the template.
+ The second is the list of explicitly specified arguments. The
+ template will be a FUNCTION_DECL, TEMPLATE_DECL, or a list of
+ overloaded functions and templates if the template-id refers to
+ a global template. If the template-id refers to a member template,
+ the template may be an IDENTIFIER_NODE. */
+DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
+
+/* An association between namespace and entity. Parameters are the
+ scope and the (non-type) value.
+ TREE_TYPE indicates the type bound to the name. */
+DEFTREECODE (CPLUS_BINDING, "binding", 'x', 2)
+
+/* A list-like node for chaining overloading candidates. TREE_TYPE is
+ the original name, and the parameter is the FUNCTION_DECL. */
+DEFTREECODE (OVERLOAD, "overload", 'x', 1)
+
+/* A generic wrapper for something not tree that we want to include in
+ tree structure. */
+DEFTREECODE (WRAPPER, "wrapper", 'x', 1)
+
+/* A node to remember a source position. */
+DEFTREECODE (SRCLOC, "srcloc", 'x', 2)
+
+/* A whole bunch of tree codes for the initial, superficial parsing of
+ templates. */
+DEFTREECODE (LOOKUP_EXPR, "lookup_expr", 'e', 2)
+DEFTREECODE (MODOP_EXPR, "modop_expr", 'e', 3)
+DEFTREECODE (CAST_EXPR, "cast_expr", '1', 1)
+DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", '1', 1)
+DEFTREECODE (CONST_CAST_EXPR, "const_cast_expr", '1', 1)
+DEFTREECODE (STATIC_CAST_EXPR, "static_cast_expr", '1', 1)
+DEFTREECODE (DYNAMIC_CAST_EXPR, "dynamic_cast_expr", '1', 1)
+DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", '1', 1)
+DEFTREECODE (ALIGNOF_EXPR, "alignof_expr", '1', 1)
+DEFTREECODE (ARROW_EXPR, "arrow_expr", 'e', 1)
+DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", 'e', 2)
+DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1)
+
+DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
+DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1)
+DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 3)
+DEFTREECODE (IF_STMT, "if_stmt", 'e', 3)
+DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4)
+DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2)
+DEFTREECODE (DO_STMT, "do_stmt", 'e', 2)
+DEFTREECODE (RETURN_STMT, "return_stmt", 'e', 1)
+DEFTREECODE (BREAK_STMT, "break_stmt", 'e', 0)
+DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0)
+DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2)
+DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1)
+DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
+
+DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
+DEFTREECODE (CASE_LABEL, "case_label", 'e', 2)
+DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
+DEFTREECODE (TRY_BLOCK, "try_stmt", 'e', 2)
+DEFTREECODE (HANDLER, "catch_stmt", 'e', 2)
+
+DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
+
+/* And some codes for expressing conversions for overload resolution. */
+
+DEFTREECODE (IDENTITY_CONV, "identity_conv", 'e', 1)
+DEFTREECODE (LVALUE_CONV, "lvalue_conv", 'e', 1)
+DEFTREECODE (QUAL_CONV, "qual_conv", 'e', 1)
+DEFTREECODE (STD_CONV, "std_conv", 'e', 1)
+DEFTREECODE (PTR_CONV, "ptr_conv", 'e', 1)
+DEFTREECODE (PMEM_CONV, "pmem_conv", 'e', 1)
+DEFTREECODE (BASE_CONV, "base_conv", 'e', 1)
+DEFTREECODE (REF_BIND, "ref_bind", 'e', 1)
+DEFTREECODE (USER_CONV, "user_conv", 'e', 2)
+DEFTREECODE (AMBIG_CONV, "ambig_conv", 'e', 1)
+DEFTREECODE (RVALUE_CONV, "rvalue_conv", 'e', 1)
+
+/*
+Local variables:
+mode:c
+End:
+*/
diff --git a/contrib/gcc/cp/cp-tree.h b/contrib/gcc/cp/cp-tree.h
index fe9855d..7572921 100644
--- a/contrib/gcc/cp/cp-tree.h
+++ b/contrib/gcc/cp/cp-tree.h
@@ -1,5 +1,5 @@
/* Definitions for C++ parsing and type checking.
- Copyright (C) 1987, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 93, 94, 95, 1996 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -22,24 +22,66 @@ Boston, MA 02111-1307, USA. */
#ifndef _CP_TREE_H
#define _CP_TREE_H
-/* Borrow everything that is C from c-tree.h,
- but do so by copy, not by inclusion, since c-tree.h defines
- lang_identifier. */
-
-#ifndef STDIO_PROTO
-#ifdef BUFSIZ
-#define STDIO_PROTO(ARGS) PROTO(ARGS)
-#else
-#define STDIO_PROTO(ARGS) ()
-#endif
-#endif
+#include "gansidecl.h"
+
+/* Usage of TREE_LANG_FLAG_?:
+ 0: TREE_NONLOCAL_FLAG (in TREE_LIST or _TYPE).
+ BINFO_MARKED (BINFO nodes).
+ TI_USES_TEMPLATE_PARMS.
+ COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT).
+ NEW_EXPR_USE_GLOBAL (in NEW_EXPR).
+ DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
+ LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR).
+ TREE_NEGATED_INT (in INTEGER_CST).
+ (TREE_MANGLED) (in IDENTIFIER_NODE) (commented-out).
+ 1: IDENTIFIER_VIRTUAL_P.
+ TI_PENDING_TEMPLATE_FLAG.
+ TI_PENDING_SPECIALIZATION_FLAG.
+ TEMPLATE_PARMS_FOR_INLINE.
+ DELETE_EXPR_USE_VEC (in DELETE_EXPR).
+ (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
+ TYPE_USES_COMPLEX_INHERITANCE (in _TYPE).
+ C_DECLARED_LABEL_FLAG.
+ 2: IDENTIFIER_OPNAME_P.
+ BINFO_FIELDS_MARKED.
+ TYPE_VIRTUAL_P.
+ PARM_DECL_EXPR (in SAVE_EXPR).
+ 3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
+ BINFO_VTABLE_PATH_MARKED.
+ (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
+ 4: BINFO_NEW_VTABLE_MARKED.
+ TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
+ or FIELD_DECL).
+ 5: BINFO_VIA_PUBLIC.
+ BINFO_VBASE_INIT_MARKED.
+ 6: Not used.
+
+ Usage of TYPE_LANG_FLAG_?:
+ 0: C_TYPE_FIELDS_READONLY (in RECORD_TYPE or UNION_TYPE).
+ 1: TYPE_HAS_CONSTRUCTOR.
+ 2: TYPE_HAS_DESTRUCTOR.
+ 3: TYPE_FOR_JAVA.
+ 4: TYPE_NEEDS_DESTRUCTOR.
+ 5: IS_AGGR_TYPE.
+ 6: TYPE_BUILT_IN.
+
+ Usage of DECL_LANG_FLAG_?:
+ 0: DECL_ERROR_REPORTED (in VAR_DECL).
+ 1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
+ 2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
+ 3: DECL_IN_AGGR_P.
+ 4: DECL_MAYBE_TEMPLATE.
+ 5: DECL_INTERFACE_KNOWN.
+ 6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL).
+ 7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
+*/
/* Language-dependent contents of an identifier. */
struct lang_identifier
{
struct tree_identifier ignore;
- tree global_value, local_value;
+ tree namespace_bindings, local_value;
tree class_value;
tree class_template_info;
struct lang_id2 *x;
@@ -51,14 +93,96 @@ struct lang_id2
tree type_desc, as_list, error_locus;
};
+typedef struct
+{
+ tree t;
+ int new_type_flag;
+} flagged_type_tree;
+
+typedef struct
+{
+ char common[sizeof (struct tree_common)];
+ struct rtx_def *rtl; /* Unused, but required to match up with what
+ the middle-end expects. */
+ HOST_WIDE_INT index;
+ HOST_WIDE_INT level;
+ HOST_WIDE_INT orig_level;
+ tree decl;
+} template_parm_index;
+
+/* For a binding between a name and an entity, defines the scope
+ where the binding is declared. Currently always points to a
+ namespace declaration. */
+#define BINDING_SCOPE(NODE) (((struct tree_binding*)NODE)->scope)
+/* This is the declaration bound to the name. Possible values:
+ variable, overloaded function, namespace, template, enumerator. */
+#define BINDING_VALUE(NODE) (((struct tree_binding*)NODE)->value)
+/* If name is bound to a type, this is the type (struct, union, enum). */
+#define BINDING_TYPE(NODE) TREE_TYPE(NODE)
+#define IDENTIFIER_GLOBAL_VALUE(NODE) \
+ namespace_binding (NODE, global_namespace)
+#define SET_IDENTIFIER_GLOBAL_VALUE(NODE, VAL) \
+ set_namespace_binding (NODE, global_namespace, VAL)
+#define IDENTIFIER_NAMESPACE_VALUE(NODE) \
+ namespace_binding (NODE, current_namespace)
+#define SET_IDENTIFIER_NAMESPACE_VALUE(NODE, VAL) \
+ set_namespace_binding (NODE, current_namespace, VAL)
+
+struct tree_binding
+{
+ char common[sizeof (struct tree_common)];
+ tree scope;
+ tree value;
+};
+
+/* The overloaded FUNCTION_DECL. */
+#define OVL_FUNCTION(NODE) (((struct tree_overload*)NODE)->function)
+#define OVL_CHAIN(NODE) TREE_CHAIN(NODE)
+/* Polymorphic access to FUNCTION and CHAIN. */
+#define OVL_CURRENT(NODE) \
+ ((TREE_CODE(NODE)==OVERLOAD) ? OVL_FUNCTION(NODE) : NODE)
+#define OVL_NEXT(NODE) \
+ ((TREE_CODE(NODE)==OVERLOAD) ? TREE_CHAIN(NODE) : NULL_TREE)
+/* If set, this was imported in a using declaration.
+ This is not to confuse with being used somewhere, which
+ is not important for this node. */
+#define OVL_USED(NODE) TREE_USED(NODE)
+
+struct tree_overload
+{
+ char common[sizeof (struct tree_common)];
+ tree function;
+};
+
+#define WRAPPER_PTR(NODE) (((struct tree_wrapper*)NODE)->u.ptr)
+#define WRAPPER_INT(NODE) (((struct tree_wrapper*)NODE)->u.i)
+
+struct tree_wrapper
+{
+ char common[sizeof (struct tree_common)];
+ union {
+ void *ptr;
+ int i;
+ } u;
+};
+
+#define SRCLOC_FILE(NODE) (((struct tree_srcloc*)NODE)->filename)
+#define SRCLOC_LINE(NODE) (((struct tree_srcloc*)NODE)->linenum)
+struct tree_srcloc
+{
+ char common[sizeof (struct tree_common)];
+ char *filename;
+ int linenum;
+};
+
/* To identify to the debug emitters if it should pay attention to the
flag `-Wtemplate-debugging'. */
#define HAVE_TEMPLATES 1
/* Macros for access to language-specific slots in an identifier. */
-#define IDENTIFIER_GLOBAL_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->global_value)
+#define IDENTIFIER_NAMESPACE_BINDINGS(NODE) \
+ (((struct lang_identifier *)(NODE))->namespace_bindings)
#define IDENTIFIER_CLASS_VALUE(NODE) \
(((struct lang_identifier *)(NODE))->class_value)
#define IDENTIFIER_LOCAL_VALUE(NODE) \
@@ -66,9 +190,14 @@ struct lang_id2
#define IDENTIFIER_TEMPLATE(NODE) \
(((struct lang_identifier *)(NODE))->class_template_info)
-#define IDENTIFIER_TYPE_VALUE(NODE) (TREE_TYPE (NODE))
+/* TREE_TYPE only indicates on local and class scope the current
+ type. For namespace scope, the presence of a type in any namespace
+ is indicated with global_type_node, and the real type behind must
+ be found through lookup. */
+#define IDENTIFIER_TYPE_VALUE(NODE) (identifier_type_value(NODE))
+#define REAL_IDENTIFIER_TYPE_VALUE(NODE) (TREE_TYPE (NODE))
#define SET_IDENTIFIER_TYPE_VALUE(NODE,TYPE) (TREE_TYPE (NODE) = TYPE)
-#define IDENTIFIER_HAS_TYPE_VALUE(NODE) (TREE_TYPE (NODE) ? 1 : 0)
+#define IDENTIFIER_HAS_TYPE_VALUE(NODE) (IDENTIFIER_TYPE_VALUE (NODE) ? 1 : 0)
#define LANG_ID_FIELD(NAME,NODE) \
(((struct lang_identifier *)(NODE))->x \
@@ -139,15 +268,34 @@ extern tree unsigned_type_node;
extern tree string_type_node, char_array_type_node, int_array_type_node;
extern tree wchar_array_type_node;
extern tree wchar_type_node, signed_wchar_type_node, unsigned_wchar_type_node;
+
+extern tree complex_integer_type_node;
+extern tree complex_float_type_node;
+extern tree complex_double_type_node;
+extern tree complex_long_double_type_node;
+
extern tree intQI_type_node, unsigned_intQI_type_node;
extern tree intHI_type_node, unsigned_intHI_type_node;
extern tree intSI_type_node, unsigned_intSI_type_node;
extern tree intDI_type_node, unsigned_intDI_type_node;
+extern tree intTI_type_node, unsigned_intTI_type_node;
+
+extern tree java_byte_type_node;
+extern tree java_short_type_node;
+extern tree java_int_type_node;
+extern tree java_long_type_node;
+extern tree java_float_type_node;
+extern tree java_double_type_node;
+extern tree java_char_type_node;
+extern tree java_boolean_type_node;
extern int current_function_returns_value;
extern int current_function_returns_null;
extern tree current_function_return_value;
+extern tree current_namespace;
+extern tree global_namespace;
+
extern tree ridpointers[];
extern tree ansi_opname[];
extern tree ansi_assopname[];
@@ -181,6 +329,10 @@ extern int flag_no_ident;
extern int warn_implicit;
+/* Nonzero means warn about usage of long long when `-pedantic'. */
+
+extern int warn_long_long;
+
/* Nonzero means warn when all ctors or dtors are private, and the class
has no friends. */
@@ -202,10 +354,6 @@ extern int warn_write_strings;
extern int warn_pointer_arith;
-/* Nonzero means warn for all old-style non-prototype function decls. */
-
-extern int warn_strict_prototypes;
-
/* Nonzero means warn about suggesting putting in ()'s. */
extern int warn_parentheses;
@@ -219,6 +367,10 @@ extern int warn_redundant_decls;
extern int warn_missing_braces;
+/* Warn about comparison of signed and unsigned values. */
+
+extern int warn_sign_compare;
+
/* Warn about a subscript that has type char. */
extern int warn_char_subscripts;
@@ -228,25 +380,36 @@ extern int warn_char_subscripts;
extern int warn_cast_qual;
-/* Warn about traditional constructs whose meanings changed in ANSI C. */
-
-extern int warn_traditional;
-
-/* Warn about *printf or *scanf format/argument anomalies. */
+/* Warn about *printf or *scanf format/argument anomalies. */
extern int warn_format;
/* Nonzero means warn about non virtual destructors in classes that have
- virtual functions. */
+ virtual functions. */
extern int warn_nonvdtor;
+/* Non-zero means warn when we convert a pointer to member function
+ into a pointer to (void or function). */
+
+extern int warn_pmf2ptr;
+
+/* Nonzero means warn about violation of some Effective C++ style rules. */
+
+extern int warn_ecpp;
+
+/* Nonzero means warn where overload resolution chooses a promotion from
+ unsigned to signed over a conversion to an unsigned of the same size. */
+
+extern int warn_sign_promo;
+
/* Non-zero means warn when a function is declared extern and later inline. */
+
extern int warn_extern_inline;
-/* Nonzero means do some things the same way PCC does. */
+/* Non-zero means warn when an old-style cast is used. */
-extern int flag_traditional;
+extern int warn_old_style_cast;
/* Nonzero means to treat bitfields as unsigned unless they say `signed'. */
@@ -264,9 +427,9 @@ extern int flag_signed_bitfields;
extern int write_virtuals;
-/* True for more efficient but incompatible (not not fully tested)
+/* True for more efficient but incompatible (not fully tested)
vtable implementation (using thunks).
- 0 is old behavior; 1 is new behavior. */
+ 0 is old behavior; 1 is new behavior. */
extern int flag_vtable_thunks;
/* INTERFACE_ONLY nonzero means that we are in an "interface"
@@ -285,11 +448,6 @@ extern int flag_elide_constructors;
extern int flag_ansi;
-/* Nonzero means recognize and handle ansi-style exception handling
- constructs. */
-
-extern int flag_handle_exceptions;
-
/* Nonzero means recognize and handle signature language constructs. */
extern int flag_handle_signatures;
@@ -299,24 +457,32 @@ extern int flag_handle_signatures;
extern int flag_default_inline;
-/* Nonzero means emit cadillac protocol. */
+/* The name-mangling scheme to use. Versions of gcc before 2.8 use
+ version 0. */
+extern int name_mangling_version;
+
+/* Nonzero means that guiding declarations are allowed. */
+extern int flag_guiding_decls;
+
+/* Nonzero if squashed mangling is to be performed.
+ This uses the B and K codes to reference previously seen class types
+ and class qualifiers. */
+extern int flag_do_squangling;
-extern int flag_cadillac;
+/* Nonzero if we want to issue diagnostics that the standard says are not
+ required. */
+extern int flag_optional_diags;
/* C++ language-specific tree codes. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
enum cplus_tree_code {
__DUMMY = LAST_AND_UNUSED_TREE_CODE,
-#include "tree.def"
+#include "cp-tree.def"
LAST_CPLUS_TREE_CODE
};
#undef DEFTREECODE
-/* Override OFFSET_REFs from the back-end, as we want our very own. */
-/* Allow complex pointer to members to work correctly. */
-#define OFFSET_REF CP_OFFSET_REF
-
-enum languages { lang_c, lang_cplusplus };
+enum languages { lang_c, lang_cplusplus, lang_java };
/* Macros to make error reporting functions' lives easier. */
#define TYPE_IDENTIFIER(NODE) (DECL_NAME (TYPE_NAME (NODE)))
@@ -327,27 +493,28 @@ enum languages { lang_c, lang_cplusplus };
#define TYPE_ASSEMBLER_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE))))
/* The _DECL for this _TYPE. */
-#define TYPE_MAIN_DECL(NODE) (TYPE_NAME (NODE))
+#define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE)))
#define IS_AGGR_TYPE(t) (TYPE_LANG_FLAG_5 (t))
-#define IS_AGGR_TYPE_CODE(t) (t == RECORD_TYPE || t == UNION_TYPE || t == UNINSTANTIATED_P_TYPE)
+#define IS_AGGR_TYPE_CODE(t) (t == RECORD_TYPE || t == UNION_TYPE)
#define IS_AGGR_TYPE_2(TYPE1,TYPE2) \
(TREE_CODE (TYPE1) == TREE_CODE (TYPE2) \
&& IS_AGGR_TYPE (TYPE1)&IS_AGGR_TYPE (TYPE2))
-#define IS_OVERLOAD_TYPE_CODE(t) (IS_AGGR_TYPE_CODE (t) || t == ENUMERAL_TYPE)
-#define IS_OVERLOAD_TYPE(t) (IS_OVERLOAD_TYPE_CODE (TREE_CODE (t)))
+#define IS_OVERLOAD_TYPE(t) \
+ (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE)
/* In a *_TYPE, nonzero means a built-in type. */
#define TYPE_BUILT_IN(NODE) TYPE_LANG_FLAG_6(NODE)
-/* Macros which might want to be replaced by function calls. */
+/* True if this a "Java" type, defined in 'extern "Java"'. */
+#define TYPE_FOR_JAVA(NODE) TYPE_LANG_FLAG_3(NODE)
#define DELTA_FROM_VTABLE_ENTRY(ENTRY) \
(!flag_vtable_thunks ? \
TREE_VALUE (CONSTRUCTOR_ELTS (ENTRY)) \
: TREE_CODE (TREE_OPERAND ((ENTRY), 0)) != THUNK_DECL ? integer_zero_node \
: build_int_2 (THUNK_DELTA (TREE_OPERAND ((ENTRY), 0)), 0))
-#if 1
+
/* Virtual function addresses can be gotten from a virtual function
table entry using this macro. */
#define FNADDR_FROM_VTABLE_ENTRY(ENTRY) \
@@ -363,15 +530,6 @@ enum languages { lang_c, lang_cplusplus };
&& IS_AGGR_TYPE (TREE_TYPE (NODE))) \
|| IS_AGGR_TYPE (NODE))
-#else
-#define FNADDR_FROM_VTABLE_ENTRY(ENTRY) (fnaddr_from_vtable_entry (ENTRY))
-#define SET_FNADDR_FROM_VTABLE_ENTRY(ENTRY,VALUE) \
- (set_fnaddr_from_vtable_entry (ENTRY, VALUE))
-/* #define TYPE_NAME_STRING(NODE) (type_name_string (NODE)) */
-#define FUNCTION_ARG_CHAIN(NODE) (function_arg_chain (NODE))
-#define PROMOTES_TO_AGGR_TYPE(NODE,CODE) (promotes_to_aggr_type (NODE, CODE))
-/* #define IS_AGGR_TYPE_2(TYPE1, TYPE2) (is_aggr_type_2 (TYPE1, TYPE2)) */
-#endif
/* Nonzero iff TYPE is uniquely derived from PARENT. Under MI, PARENT can
be an ambiguous base class of TYPE, and this macro will be false. */
#define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) >= 0)
@@ -389,57 +547,48 @@ struct lang_type
struct
{
unsigned has_type_conversion : 1;
- unsigned has_int_conversion : 1;
- unsigned has_float_conversion : 1;
unsigned has_init_ref : 1;
- unsigned gets_init_aggr : 1;
unsigned has_assignment : 1;
unsigned has_default_ctor : 1;
unsigned uses_multiple_inheritance : 1;
-
- unsigned has_nonpublic_ctor : 2;
- unsigned has_nonpublic_assign_ref : 2;
unsigned const_needs_init : 1;
unsigned ref_needs_init : 1;
unsigned has_const_assign_ref : 1;
- unsigned vtable_needs_writing : 1;
+ unsigned has_nonpublic_ctor : 2;
+ unsigned has_nonpublic_assign_ref : 2;
+ unsigned vtable_needs_writing : 1;
unsigned has_assign_ref : 1;
unsigned gets_new : 2;
+
unsigned gets_delete : 2;
unsigned has_call_overloaded : 1;
unsigned has_array_ref_overloaded : 1;
unsigned has_arrow_overloaded : 1;
-
unsigned local_typedecls : 1;
unsigned interface_only : 1;
unsigned interface_unknown : 1;
+
unsigned needs_virtual_reinit : 1;
unsigned vec_delete_takes_size : 1;
unsigned declared_class : 1;
unsigned being_defined : 1;
unsigned redefined : 1;
-
- unsigned no_globalize : 1;
unsigned marked : 1;
unsigned marked2 : 1;
unsigned marked3 : 1;
+
unsigned marked4 : 1;
unsigned marked5 : 1;
unsigned marked6 : 1;
-
- unsigned use_template : 2;
unsigned debug_requested : 1;
- unsigned has_method_call_overloaded : 1;
- unsigned private_attr : 1;
+ unsigned use_template : 2;
unsigned got_semicolon : 1;
unsigned ptrmemfunc_flag : 1;
+
unsigned is_signature : 1;
unsigned is_signature_pointer : 1;
-
unsigned is_signature_reference : 1;
- unsigned has_default_implementation : 1;
- unsigned grokking_typedef : 1;
unsigned has_opaque_typedecls : 1;
unsigned sigtable_has_been_generated : 1;
unsigned was_anonymous : 1;
@@ -455,39 +604,30 @@ struct lang_type
/* 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 : 19;
-
- unsigned n_vancestors : 16;
+ unsigned dummy : 11;
} type_flags;
+#ifdef MI_MATRIX
int cid;
+#endif
int n_ancestors;
+ int n_vancestors;
int vsize;
int max_depth;
int vfield_parent;
- union tree_node *vbinfo[2];
union tree_node *baselink_vec;
union tree_node *vfields;
union tree_node *vbases;
- union tree_node *vbase_size;
union tree_node *tags;
char *memoized_table_entry;
- char *search_slot;
-
-#ifdef ONLY_INT_FIELDS
- unsigned int mode : 8;
-#else
- enum machine_mode mode : 8;
-#endif
+ union tree_node *search_slot;
- unsigned char size_unit;
unsigned char align;
- unsigned char sep_unit;
+ /* Room for another three unsigned chars. */
- union tree_node *sep;
union tree_node *size;
union tree_node *base_init_list;
@@ -497,7 +637,9 @@ struct lang_type
union tree_node *binfo_as_list;
union tree_node *friend_classes;
+#ifdef MI_MATRIX
char *mi_matrix;
+#endif
union tree_node *rtti;
@@ -507,6 +649,8 @@ struct lang_type
union tree_node *signature_pointer_to;
union tree_node *signature_reference_to;
+ union tree_node *template_info;
+
int linenum;
};
@@ -549,21 +693,10 @@ struct lang_type
/* Nonzero for TREE_LIST or _TYPE node means that this node is class-local. */
#define TREE_NONLOCAL_FLAG(NODE) (TREE_LANG_FLAG_0 (NODE))
-/* Nonzero for a _CLASSTYPE node which we know to be private. */
-#define TYPE_PRIVATE_P(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.private_attr)
-
/* Nonzero means that this _CLASSTYPE node defines ways of converting
itself to other types. */
#define TYPE_HAS_CONVERSION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_type_conversion)
-/* Nonzero means that this _CLASSTYPE node can convert itself to an
- INTEGER_TYPE. */
-#define TYPE_HAS_INT_CONVERSION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_int_conversion)
-
-/* Nonzero means that this _CLASSTYPE node can convert itself to an
- REAL_TYPE. */
-#define TYPE_HAS_REAL_CONVERSION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_float_conversion)
-
/* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */
#define TYPE_HAS_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_assign_ref)
#define TYPE_HAS_CONST_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_const_assign_ref)
@@ -572,11 +705,6 @@ struct lang_type
#define TYPE_HAS_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_init_ref)
#define TYPE_HAS_CONST_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_const_init_ref)
-/* Nonzero means that this _CLASSTYPE node has an X(X ...) constructor.
- Note that there must be other arguments, or this constructor is flagged
- as being erroneous. */
-#define TYPE_GETS_INIT_AGGR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_init_aggr)
-
/* Nonzero means that this type is being defined. I.e., the left brace
starting the definition of this type has been seen. */
#define TYPE_BEING_DEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.being_defined)
@@ -584,10 +712,6 @@ struct lang_type
convenient, don't reprocess any methods that appear in its redefinition. */
#define TYPE_REDEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.redefined)
-/* Nonzero means that this _CLASSTYPE node overloads the method call
- operator. In this case, all method calls go through `operator->()(...). */
-#define TYPE_OVERLOADS_METHOD_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_method_call_overloaded)
-
/* Nonzero means that this type is a signature. */
# define IS_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)?TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature:0)
# define SET_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature=1)
@@ -599,12 +723,6 @@ struct lang_type
/* Nonzero means that this type is a signature reference type. */
# define IS_SIGNATURE_REFERENCE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature_reference)
-/* Nonzero means that this signature type has a default implementation. */
-# define HAS_DEFAULT_IMPLEMENTATION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_default_implementation)
-
-/* Nonzero means that grokdeclarator works on a signature-local typedef. */
-#define SIGNATURE_GROKKING_TYPEDEF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.grokking_typedef)
-
/* Nonzero means that this signature contains opaque type declarations. */
#define SIGNATURE_HAS_OPAQUE_TYPEDECLS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_opaque_typedecls)
@@ -636,10 +754,6 @@ struct lang_type
/* The is the VAR_DECL that contains NODE's rtti. */
#define CLASSTYPE_RTTI(NODE) (TYPE_LANG_SPECIFIC(NODE)->rtti)
-/* List of all explicit methods (chained using DECL_NEXT_METHOD),
- in order they were parsed. */
-#define CLASSTYPE_METHODS(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
-
/* Nonzero means that this _CLASSTYPE node overloads operator(). */
#define TYPE_OVERLOADS_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_call_overloaded)
@@ -660,14 +774,14 @@ struct lang_type
#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE))
/* List of lists of member functions defined in this class. */
-#define CLASSTYPE_METHOD_VEC(NODE) TYPE_METHODS(NODE)
+#define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
/* The first type conversion operator in the class (the others can be
searched with TREE_CHAIN), or the first non-constructor function if
there are no type conversion operators. */
#define CLASSTYPE_FIRST_CONVERSION(NODE) \
- TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 1 \
- ? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1) \
+ TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 2 \
+ ? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 2) \
: NULL_TREE;
/* Pointer from any member function to the head of the list of
@@ -695,13 +809,17 @@ struct lang_type
#define SET_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 1)
#define CLEAR_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 0)
+/* A list of the nested tag-types (class, struct, union, or enum)
+ found within this class. The TREE_PURPOSE of each node is the name
+ of the type; the TREE_VALUE is the type itself. This list includes
+ nested member class templates. */
#define CLASSTYPE_TAGS(NODE) (TYPE_LANG_SPECIFIC(NODE)->tags)
/* If this class has any bases, this is the number of the base class from
which our VFIELD is based, -1 otherwise. If this class has no base
classes, this is not used.
In D : B1, B2, PARENT would be 0, if D's vtable came from B1,
- 1, if D's vtable came from B2. */
+ 1, if D's vtable came from B2. */
#define CLASSTYPE_VFIELD_PARENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfield_parent)
/* Remove when done merging. */
@@ -725,7 +843,7 @@ struct lang_type
large a multiple-inheritance matrix we need to build to find
derivation information. */
#define CLASSTYPE_N_SUPERCLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->n_ancestors)
-#define CLASSTYPE_N_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.n_vancestors)
+#define CLASSTYPE_N_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->n_vancestors)
/* Record how deep the inheritance is for this class so `void*' conversions
are less favorable than a conversion to the most base type. */
@@ -740,20 +858,11 @@ struct lang_type
it can mean almost anything. */
#define CLASSTYPE_MTABLE_ENTRY(NODE) (TYPE_LANG_SPECIFIC(NODE)->memoized_table_entry)
-/* This is the total size of the baseclasses defined for this type.
- Needed because it is desirable to layout such information
- before beginning to process the class itself, and we
- don't want to compute it second time when actually laying
- out the type for real. */
+/* These are the size, mode and alignment of the type without its
+ virtual base classes, for when we use this type as a base itself. */
#define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->size)
-#define CLASSTYPE_SIZE_UNIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->size_unit)
-#define CLASSTYPE_MODE(NODE) (TYPE_LANG_SPECIFIC(NODE)->mode)
#define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align)
-/* This is the space needed for virtual base classes. NULL if
- there are no virtual basetypes. */
-#define CLASSTYPE_VBASE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbase_size)
-
/* A cons list of structure elements which either have constructors
to be called, or virtual function table pointers which
need initializing. Depending on what is being initialized,
@@ -807,17 +916,19 @@ struct lang_type
/* Same, but cache a list whose value is the binfo of this type. */
#define CLASSTYPE_BINFO_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->binfo_as_list)
-/* A list of class types with which this type is a friend. */
+/* A list of class types with which this type is a friend. The
+ TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the
+ case of a template friend. */
#define CLASSTYPE_FRIEND_CLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->friend_classes)
+#ifdef MI_MATRIX
/* Keep an inheritance lattice around so we can quickly tell whether
a type is derived from another or not. */
#define CLASSTYPE_MI_MATRIX(NODE) (TYPE_LANG_SPECIFIC(NODE)->mi_matrix)
+#endif
/* Say whether this node was declared as a "class" or a "struct". */
#define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class)
-/* whether this can be globalized. */
-#define CLASSTYPE_NO_GLOBALIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.no_globalize)
/* Nonzero if this class has const members which have no specified initialization. */
#define CLASSTYPE_READONLY_FIELDS_NEED_INIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.const_needs_init)
@@ -838,24 +949,20 @@ struct lang_type
/* Nonzero if a _DECL node requires us to output debug info for this class. */
#define CLASSTYPE_DEBUG_REQUESTED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.debug_requested)
-
-#define TYPE_INCOMPLETE(NODE) \
- (TYPE_SIZE (NODE) == NULL_TREE && TREE_CODE (NODE) != TEMPLATE_TYPE_PARM)
/* Additional macros for inheritance information. */
-#define CLASSTYPE_VBINFO(NODE,VIA_PUBLIC) \
- (TYPE_LANG_SPECIFIC (NODE)->vbinfo[VIA_PUBLIC])
-
/* When following an binfo-specific chain, this is the cumulative
via-public flag. */
#define BINFO_VIA_PUBLIC(NODE) TREE_LANG_FLAG_5 (NODE)
+#ifdef MI_MATRIX
/* When building a matrix to determine by a single lookup
whether one class is derived from another or not,
this field is the index of the class in the table. */
#define CLASSTYPE_CID(NODE) (TYPE_LANG_SPECIFIC(NODE)->cid)
#define BINFO_CID(NODE) CLASSTYPE_CID(BINFO_TYPE(NODE))
+#endif
/* Nonzero means marked by DFS or BFS search, including searches
by `get_binfo' and `get_base_distance'. */
@@ -923,8 +1030,8 @@ struct lang_type
this type can raise. */
#define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE)
-/* The binding level associated with the namespace. */
-#define NAMESPACE_LEVEL(NODE) ((NODE)->decl.arguments)
+/* The binding level associated with the namespace. */
+#define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level)
struct lang_decl_flags
{
@@ -951,38 +1058,48 @@ struct lang_decl_flags
unsigned saved_inline : 1;
unsigned use_template : 2;
- unsigned c_static : 1;
unsigned nonconverting : 1;
unsigned declared_inline : 1;
unsigned not_really_extern : 1;
- unsigned dummy : 4;
+ unsigned comdat : 1;
+ unsigned needs_final_overrider : 1;
+ unsigned dummy : 3;
tree access;
tree context;
tree memfunc_pointer_to;
+ tree template_info;
+ struct binding_level *level;
};
struct lang_decl
{
struct lang_decl_flags decl_flags;
- struct template_info *template_info;
tree main_decl_variant;
struct pending_inline *pending_inline_info;
- tree next_method;
- tree chain;
};
/* Non-zero if NODE is a _DECL with TREE_READONLY set. */
#define TREE_READONLY_DECL_P(NODE) \
(TREE_READONLY (NODE) && TREE_CODE_CLASS (TREE_CODE (NODE)) == 'd')
+/* Non-zero iff DECL is memory-based. The DECL_RTL of
+ certain const variables might be a CONST_INT, or a REG
+ in some cases. We cannot use `memory_operand' as a test
+ here because on most RISC machines, a variable's address
+ is not, by itself, a legitimate address. */
+#define DECL_IN_MEMORY_P(NODE) \
+ (DECL_RTL (NODE) != NULL_RTX && GET_CODE (DECL_RTL (NODE)) == MEM)
+
/* For FUNCTION_DECLs: return the language in which this decl
was declared. */
#define DECL_LANGUAGE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.language)
/* For FUNCTION_DECLs: nonzero means that this function is a constructor. */
#define DECL_CONSTRUCTOR_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_attr)
+#define DECL_DESTRUCTOR_P(NODE) (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME(NODE)))
+
/* For FUNCTION_DECLs: nonzero means that this function is a constructor
for an object with virtual baseclasses. */
#define DECL_CONSTRUCTOR_FOR_VBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr)
@@ -997,7 +1114,7 @@ struct lang_decl
/* Nonzero for FUNCTION_DECL means that this constructor is known to
not make any assignment to `this', and therefore can be trusted
- to return it unchanged. Otherwise, we must re-assign `current_class_decl'
+ to return it unchanged. Otherwise, we must re-assign `current_class_ptr'
after performing base initializations. */
#define DECL_PRESERVES_THIS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.preserves_first_arg)
@@ -1023,10 +1140,15 @@ struct lang_decl
(TREE_CODE (NODE) == VAR_DECL || TREE_CODE (NODE) == TYPE_DECL \
|| TREE_CODE (NODE) == CONST_DECL)
+/* Nonzero for FUNCTION_DECL means that this decl is a non-static
+ member function. */
+#define DECL_NONSTATIC_MEMBER_FUNCTION_P(NODE) \
+ (TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE)
+
/* Nonzero for FUNCTION_DECL means that this decl is a member function
(static or non-static). */
#define DECL_FUNCTION_MEMBER_P(NODE) \
- (TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE || DECL_STATIC_FUNCTION_P (NODE))
+ (DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE) || DECL_STATIC_FUNCTION_P (NODE))
/* Nonzero for FUNCTION_DECL means that this member function
has `this' as const X *const. */
@@ -1048,31 +1170,57 @@ struct lang_decl
exists as part of an abstract class's interface. */
#define DECL_ABSTRACT_VIRTUAL_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.abstract_virtual)
+/* Nonzero for FUNCTION_DECL means that this member function
+ must be overridden by derived classes. */
+#define DECL_NEEDS_FINAL_OVERRIDER_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.needs_final_overrider)
+
/* Nonzero if allocated on permanent_obstack. */
#define LANG_DECL_PERMANENT(LANGDECL) ((LANGDECL)->decl_flags.permanent_attr)
/* The _TYPE context in which this _DECL appears. This field holds the
class where a virtual function instance is actually defined, and the
- lexical scope of a friend function defined in a class body. */
+ 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
- link into the FIELD_DECL chain. */
-#if 1
-#define DECL_CHAIN(NODE) (DECL_LANG_SPECIFIC(NODE)->chain)
-#else
-#define DECL_CHAIN(NODE) (TREE_CHAIN (NODE))
-#endif
-
-/* Next method in CLASSTYPE_METHODS list. */
-#define DECL_NEXT_METHOD(NODE) (DECL_LANG_SPECIFIC(NODE)->next_method)
+ ? DECL_CLASS_CONTEXT (NODE) : CP_DECL_CONTEXT (NODE))
+
+/* NULL_TREE in DECL_CONTEXT represents the global namespace. */
+#define CP_DECL_CONTEXT(NODE) \
+ (DECL_CONTEXT (NODE) ? DECL_CONTEXT (NODE) : global_namespace)
+#define FROB_CONTEXT(NODE) ((NODE) == global_namespace ? NULL_TREE : (NODE))
+
+/* 1 iff NODE has namespace scope, including the global namespace. */
+#define DECL_NAMESPACE_SCOPE_P(NODE) \
+ (DECL_CONTEXT (NODE) == NULL_TREE \
+ || TREE_CODE (DECL_CONTEXT (NODE)) == NAMESPACE_DECL)
+
+/* 1 iff NODE is a class member. */
+#define DECL_CLASS_SCOPE_P(NODE) \
+ (DECL_CONTEXT (NODE) \
+ && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (NODE))) == 't')
+
+/* For a NAMESPACE_DECL: the list of using namespace directives
+ The PURPOSE is the used namespace, the value is the namespace
+ that is the common ancestor. */
+#define DECL_NAMESPACE_USING(NODE) DECL_VINDEX(NODE)
+
+/* In a NAMESPACE_DECL, the DECL_INITIAL is used to record all users
+ of a namespace, to record the transitive closure of using namespace. */
+#define DECL_NAMESPACE_USERS(NODE) DECL_INITIAL (NODE)
+
+/* In a NAMESPACE_DECL, points to the original namespace if this is
+ a namespace alias. */
+#define DECL_NAMESPACE_ALIAS(NODE) DECL_ABSTRACT_ORIGIN (NODE)
+#define ORIGINAL_NAMESPACE(NODE) \
+ (DECL_NAMESPACE_ALIAS (NODE) ? DECL_NAMESPACE_ALIAS (NODE) : (NODE))
+
+/* In a TREE_LIST concatenating using directives, indicate indirekt
+ directives */
+#define TREE_INDIRECT_USING(NODE) ((NODE)->common.lang_flag_0)
/* In a VAR_DECL for a variable declared in a for statement,
- this is the shadowed variable. */
+ this is the shadowed (local) variable. */
#define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT(NODE)
/* Points back to the decl which caused this lang_decl to be allocated. */
@@ -1083,7 +1231,7 @@ struct lang_decl
squirreled away. */
#define DECL_PENDING_INLINE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->pending_inline_info)
-/* True if on the saved_inlines (see decl2.c) list. */
+/* True if on the saved_inlines (see decl2.c) list. */
#define DECL_SAVED_INLINE(DECL) \
(DECL_LANG_SPECIFIC(DECL)->decl_flags.saved_inline)
@@ -1096,31 +1244,71 @@ struct lang_decl
which this signature member function pointer was created. */
#define DECL_MEMFUNC_POINTING_TO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.memfunc_pointer_to)
-/* For a TEMPLATE_DECL: template-specific information. */
-#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->template_info)
-
-/* Nonzero in INT_CST means that this int is negative by dint of
+/* For a VAR_DECL or FUNCTION_DECL: template-specific information. */
+#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.template_info)
+#define CLASSTYPE_TEMPLATE_INFO(NODE) (TYPE_LANG_SPECIFIC(NODE)->template_info)
+#define TI_TEMPLATE(NODE) (TREE_PURPOSE (NODE))
+#define TI_ARGS(NODE) (TREE_VALUE (NODE))
+#define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE))
+#define TI_USES_TEMPLATE_PARMS(NODE) TREE_LANG_FLAG_0 (NODE)
+#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
+/* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates
+ that the template is a specialization of a member template, but
+ that we don't yet know which one. */
+#define TI_PENDING_SPECIALIZATION_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
+#define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE))
+#define DECL_TI_ARGS(NODE) TI_ARGS (DECL_TEMPLATE_INFO (NODE))
+#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE))
+#define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE))
+#define CLASSTYPE_TI_SPEC_INFO(NODE) TI_SPEC_INFO (CLASSTYPE_TEMPLATE_INFO (NODE))
+#define INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE(NODE)
+
+#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
+
+#define DECL_SAVED_TREE(NODE) DECL_MEMFUNC_POINTER_TO (NODE)
+#define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE)
+#define NEW_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
+#define DELETE_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
+#define DELETE_EXPR_USE_VEC(NODE) TREE_LANG_FLAG_1 (NODE)
+#define LOOKUP_EXPR_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
+
+/* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a
+ TEMPLATE_DECL. This macro determines whether or not a given class
+ type is really a template type, as opposed to an instantiation or
+ specialization of one. */
+#define CLASSTYPE_IS_TEMPLATE(NODE) \
+ (CLASSTYPE_TEMPLATE_INFO (NODE) \
+ && !CLASSTYPE_USE_TEMPLATE (NODE) \
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))
+
+#define TYPENAME_TYPE_FULLNAME(NODE) CLASSTYPE_SIZE (NODE)
+
+/* Nonzero in INTEGER_CST means that this int is negative by dint of
using a twos-complement negated operand. */
#define TREE_NEGATED_INT(NODE) (TREE_LANG_FLAG_0 (NODE))
+#if 0 /* UNUSED */
/* Nonzero in any kind of _EXPR or _REF node means that it is a call
to a storage allocation routine. If, later, alternate storage
is found to hold the object, this call can be ignored. */
#define TREE_CALLS_NEW(NODE) (TREE_LANG_FLAG_1 (NODE))
+#endif
/* Nonzero in any kind of _TYPE that uses multiple inheritance
or virtual baseclasses. */
#define TYPE_USES_COMPLEX_INHERITANCE(NODE) (TREE_LANG_FLAG_1 (NODE))
+#if 0 /* UNUSED */
/* Nonzero in IDENTIFIER_NODE means that this name is not the name the user
gave; it's a DECL_NESTED_TYPENAME. Someone may want to set this on
mangled function names, too, but it isn't currently. */
#define TREE_MANGLED(NODE) (TREE_LANG_FLAG_0 (NODE))
+#endif
#if 0 /* UNUSED */
/* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
should be looked up in a non-standard way. */
-#define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE))
+#define DECL_OVERLOADED(NODE) (FOO)
#endif
/* Nonzero if this (non-TYPE)_DECL has its virtual attribute set.
@@ -1134,20 +1322,10 @@ struct lang_decl
one that does). */
#define TYPE_VIRTUAL_P(NODE) (TREE_LANG_FLAG_2 (NODE))
-#if 0
-/* Same, but tells if this field is private in current context. */
-#define DECL_PRIVATE(NODE) (FOO)
-
-/* Same, but tells if this field is private in current context. */
-#define DECL_PROTECTED(NODE) (DECL_LANG_FLAG_6 (NODE))
-
-#define DECL_PUBLIC(NODE) (DECL_LANG_FLAG_7 (NODE))
-#endif
-
extern int flag_new_for_scope;
/* This flag is true of a local VAR_DECL if it was declared in a for
- statement, but we are no longer in the scope of the for. */
+ statement, but we are no longer in the scope of the for. */
#define DECL_DEAD_FOR_LOCAL(NODE) DECL_LANG_FLAG_7 (NODE)
/* This flag is set on a VAR_DECL that is a DECL_DEAD_FOR_LOCAL
@@ -1179,11 +1357,6 @@ extern int flag_new_for_scope;
These may be shadowed, and may be referenced from nested functions. */
#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
-/* Record whether a type or decl was written with nonconstant size.
- Note that TYPE_SIZE may have simplified to a constant. */
-#define C_TYPE_VARIABLE_SIZE(type) TREE_LANG_FLAG_4 (type)
-#define C_DECL_VARIABLE_SIZE(type) DECL_LANG_FLAG_8 (type)
-
/* Nonzero for _TYPE means that the _TYPE defines
at least one constructor. */
#define TYPE_HAS_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1(NODE))
@@ -1207,10 +1380,12 @@ extern int flag_new_for_scope;
#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \
&& CONSTRUCTOR_ELTS (NODE) == NULL_TREE)
+#if 0
/* Indicates that a NON_LVALUE_EXPR came from a C++ reference.
Used to generate more helpful error message in case somebody
tries to take its address. */
#define TREE_REFERENCE_EXPR(NODE) (TREE_LANG_FLAG_3(NODE))
+#endif
/* Nonzero for _TYPE means that the _TYPE defines a destructor. */
#define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2(NODE))
@@ -1219,7 +1394,7 @@ extern int flag_new_for_scope;
/* Nonzero for _TYPE node means that creating an object of this type
will involve a call to a constructor. This can apply to objects
of ARRAY_TYPE if the type of the elements needs a constructor. */
-#define TYPE_NEEDS_CONSTRUCTING(NODE) (TYPE_LANG_FLAG_3(NODE))
+#define TYPE_NEEDS_CONSTRUCTING(NODE) ... defined in ../tree.h ...
#endif
/* Nonzero means that an object of this type can not be initialized using
@@ -1250,21 +1425,41 @@ extern int flag_new_for_scope;
#define TYPE_HAS_TRIVIAL_ASSIGN_REF(NODE) \
(TYPE_HAS_ASSIGN_REF (NODE) && ! TYPE_HAS_COMPLEX_ASSIGN_REF (NODE))
+#define TYPE_PTRMEM_P(NODE) \
+ (TREE_CODE (NODE) == POINTER_TYPE \
+ && TREE_CODE (TREE_TYPE (NODE)) == OFFSET_TYPE)
+#define TYPE_PTR_P(NODE) \
+ (TREE_CODE (NODE) == POINTER_TYPE \
+ && TREE_CODE (TREE_TYPE (NODE)) != OFFSET_TYPE)
+#define TYPE_PTROB_P(NODE) \
+ (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE \
+ && TREE_CODE (TREE_TYPE (NODE)) != VOID_TYPE)
+#define TYPE_PTROBV_P(NODE) \
+ (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE)
+#define TYPE_PTRFN_P(NODE) \
+ (TREE_CODE (NODE) == POINTER_TYPE \
+ && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE)
+
/* Nonzero for _TYPE node means that this type is a pointer to member
- function type. */
+ function type. */
#define TYPE_PTRMEMFUNC_P(NODE) (TREE_CODE(NODE) == RECORD_TYPE && TYPE_LANG_SPECIFIC(NODE)->type_flags.ptrmemfunc_flag)
#define TYPE_PTRMEMFUNC_FLAG(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.ptrmemfunc_flag)
/* Get the POINTER_TYPE to the METHOD_TYPE associated with this
pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true,
- before using this macro. */
+ before using this macro. */
#define TYPE_PTRMEMFUNC_FN_TYPE(NODE) (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (NODE)))))))
-/* These are use to manipulate the the canonical RECORD_TYPE from the
- hashed POINTER_TYPE, and can only be used on the POINTER_TYPE. */
+
+/* Returns `A' for a type like `int (A::*)(double)' */
+#define TYPE_PTRMEMFUNC_OBJECT_TYPE(NODE) \
+ TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (NODE)))
+
+/* These are use to manipulate the canonical RECORD_TYPE from the
+ hashed POINTER_TYPE, and can only be used on the POINTER_TYPE. */
#define TYPE_GET_PTRMEMFUNC_TYPE(NODE) ((tree)TYPE_LANG_SPECIFIC(NODE))
#define TYPE_SET_PTRMEMFUNC_TYPE(NODE, VALUE) (TYPE_LANG_SPECIFIC(NODE) = ((struct lang_type *)(void*)(VALUE)))
-/* These are to get the delta2 and pfn fields from a TYPE_PTRMEMFUNC_P. */
-#define DELTA2_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), delta2_identifier, 0, 0))
-#define PFN_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), pfn_identifier, 0, 0))
+/* These are to get the delta2 and pfn fields from a TYPE_PTRMEMFUNC_P. */
+#define DELTA2_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, NULL_TREE, 0), delta2_identifier, NULL_TREE, 0))
+#define PFN_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, NULL_TREE, 0), pfn_identifier, NULL_TREE, 0))
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
specified in its declaration. */
@@ -1283,6 +1478,11 @@ extern int flag_new_for_scope;
#define ANON_UNION_P(NODE) (DECL_NAME (NODE) == 0)
+/* Nonzero if TYPE is an anonymous union type. */
+#define ANON_UNION_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == UNION_TYPE \
+ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TYPE)))
+
#define UNKNOWN_TYPE LANG_TYPE
/* Define fields and accessors for nodes representing declared names. */
@@ -1299,22 +1499,22 @@ extern int flag_new_for_scope;
#define DECL_VPARENT(NODE) ((NODE)->decl.arguments)
#endif
-/* Make a slot so we can implement nested types. This slot holds
- the IDENTIFIER_NODE that uniquely names the nested type. This
- is for TYPE_DECLs only. */
-#define DECL_NESTED_TYPENAME(NODE) ((NODE)->decl.arguments)
-#define TYPE_NESTED_NAME(NODE) (DECL_NESTED_TYPENAME (TYPE_NAME (NODE)))
-
#define TYPE_WAS_ANONYMOUS(NODE) (TYPE_LANG_SPECIFIC (NODE)->type_flags.was_anonymous)
/* C++: all of these are overloaded! These apply only to TYPE_DECLs. */
+
+/* The format of each node in the DECL_FRIENDLIST is as follows:
+
+ The TREE_PURPOSE will be the name of a function, i.e., an
+ IDENTIFIER_NODE. The TREE_VALUE will be itself a TREE_LIST, the
+ list of functions with that name which are friends. The
+ TREE_PURPOSE of each node in this sublist will be error_mark_node,
+ if the function was declared a friend individually, in which case
+ the TREE_VALUE will be the function_decl. If, however, all
+ functions with a given name in a class were declared to be friends,
+ the TREE_PUROSE will be the class type, and the TREE_VALUE will be
+ NULL_TREE. */
#define DECL_FRIENDLIST(NODE) (DECL_INITIAL (NODE))
-#if 0
-#define DECL_UNDEFINED_FRIENDS(NODE) ((NODE)->decl.result)
-#endif
-#define DECL_WAITING_FRIENDS(NODE) ((tree)(NODE)->decl.rtl)
-#define SET_DECL_WAITING_FRIENDS(NODE,VALUE) \
- ((NODE)->decl.rtl=(struct rtx_def*)VALUE)
/* The DECL_ACCESS is used to record under which context
special access rules apply. */
@@ -1325,25 +1525,70 @@ extern int flag_new_for_scope;
#define DECL_REFERENCE_SLOT(NODE) ((tree)(NODE)->decl.arguments)
#define SET_DECL_REFERENCE_SLOT(NODE,VAL) ((NODE)->decl.arguments=VAL)
-/* For local VAR_DECLs, holds index into gc-protected obstack. */
-#define DECL_GC_OFFSET(NODE) ((NODE)->decl.result)
-
/* Accessor macros for C++ template decl nodes. */
-#define DECL_TEMPLATE_IS_CLASS(NODE) (DECL_RESULT(NODE) == NULL_TREE)
+
+/* The DECL_TEMPLATE_PARMS are a list. The TREE_PURPOSE of each node
+ indicates the level of the template parameters, with 1 being the
+ outermost set of template parameters. The TREE_VALUE is a vector,
+ whose elements are the template parameters at each level. Each
+ element in the vector is a TREE_LIST, whose TREE_VALUE is a
+ PARM_DECL (if the parameter is a non-type parameter), or a
+ TYPE_DECL (if the parameter is a type parameter). The TREE_PURPOSE
+ is the default value, if any. The TEMPLATE_PARM_INDEX for the
+ parameter is avilable as the DECL_INITIAL (for a PARM_DECL) or as
+ the TREE_TYPE (for a TYPE_DECL). */
#define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE)
+#define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \
+ INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE))
+#define DECL_NTPARMS(NODE) \
+ TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (NODE))
/* For class templates. */
-#define DECL_TEMPLATE_MEMBERS(NODE) DECL_SIZE(NODE)
+#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
/* For function, method, class-data templates. */
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE)
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
+#define DECL_TEMPLATE_INJECT(NODE) DECL_INITIAL(NODE)
+
+/* Nonzero for TEMPLATE_DECL nodes that represents template template
+ parameters */
+#define DECL_TEMPLATE_TEMPLATE_PARM_P(NODE) \
+ (TREE_CODE (NODE) == TEMPLATE_DECL && TREE_TYPE (NODE) \
+ && TREE_CODE (TREE_TYPE (NODE)) == TEMPLATE_TEMPLATE_PARM)
+
+#define DECL_FUNCTION_TEMPLATE_P(NODE) \
+ (TREE_CODE (NODE) == TEMPLATE_DECL \
+ && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
+
+/* Nonzero for a DECL that represents a template class. */
+#define DECL_CLASS_TEMPLATE_P(NODE) \
+ (TREE_CODE (NODE) == TEMPLATE_DECL \
+ && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == TYPE_DECL \
+ && !DECL_TEMPLATE_TEMPLATE_PARM_P (NODE))
+
+/* Nonzero if NODE which declares a type. */
+#define DECL_DECLARES_TYPE_P(NODE) \
+ (TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
+
+/* A `primary' template is one that has its own template header. A
+ member function of a class template is a template, but not primary.
+ A member template is primary. Friend templates are primary, too. */
+
+/* Returns the primary template corresponding to these parameters. */
+#define DECL_PRIMARY_TEMPLATE(NODE) \
+ (TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE)))
+
+/* Returns non-zero if NODE is a primary template. */
+#define PRIMARY_TEMPLATE_P(NODE) (DECL_PRIMARY_TEMPLATE (NODE) == NODE)
+
+#define CLASSTYPE_TEMPLATE_LEVEL(NODE) \
+ (TREE_INT_CST_HIGH (TREE_PURPOSE (CLASSTYPE_TI_TEMPLATE (NODE))))
/* Indicates whether or not (and how) a template was expanded for this
FUNCTION_DECL or VAR_DECL.
0=normal declaration, e.g. int min (int, int);
1=implicit template instantiation
2=explicit template specialization, e.g. int min<int> (int, int);
- 3=explicit template instantiation, e.g. template int min<int> (int, int);
- */
+ 3=explicit template instantiation, e.g. template int min<int> (int, int); */
#define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.use_template)
#define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1)
@@ -1371,14 +1616,11 @@ extern int flag_new_for_scope;
#define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) = 3)
+/* This function may be a guiding decl for a template. */
+#define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE)
/* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
-/* This decl was declared or deduced to have internal linkage. This is
- only meaningful if TREE_PUBLIC is set. */
-#define DECL_C_STATIC(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->decl_flags.c_static)
-
/* This function was declared inline. This flag controls the linkage
semantics of 'inline'; whether or not the function is inlined is
controlled by DECL_INLINE. */
@@ -1391,9 +1633,12 @@ extern int flag_new_for_scope;
#define DECL_NOT_REALLY_EXTERN(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.not_really_extern)
-#define DECL_PUBLIC(NODE) \
- (TREE_CODE (NODE) == FUNCTION_DECL \
- ? ! DECL_C_STATIC (NODE) : TREE_PUBLIC (NODE))
+#define DECL_REALLY_EXTERN(NODE) \
+ (DECL_EXTERNAL (NODE) && ! DECL_NOT_REALLY_EXTERN (NODE))
+
+/* Used to tell cp_finish_decl that it should approximate comdat linkage
+ as best it can for this decl. */
+#define DECL_COMDAT(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.comdat)
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
@@ -1401,6 +1646,45 @@ extern int flag_new_for_scope;
#define UPT_TEMPLATE(NODE) TREE_PURPOSE(TYPE_VALUES(NODE))
#define UPT_PARMS(NODE) TREE_VALUE(TYPE_VALUES(NODE))
+/* An un-parsed default argument looks like an identifier. */
+#define DEFARG_NODE_CHECK(t) TREE_CHECK(t, DEFAULT_ARG)
+#define DEFARG_LENGTH(NODE) (DEFARG_NODE_CHECK(NODE)->identifier.length)
+#define DEFARG_POINTER(NODE) (DEFARG_NODE_CHECK(NODE)->identifier.pointer)
+
+#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
+ define_function (NAME, TYPE, CODE, (void (*) PROTO((tree)))pushdecl, LIBNAME)
+
+/* These macros provide convenient access to the various _STMT nodes
+ created when parsing template declarations. */
+#define IF_COND(NODE) TREE_OPERAND (NODE, 0)
+#define THEN_CLAUSE(NODE) TREE_OPERAND (NODE, 1)
+#define ELSE_CLAUSE(NODE) TREE_OPERAND (NODE, 2)
+#define WHILE_COND(NODE) TREE_OPERAND (NODE, 0)
+#define WHILE_BODY(NODE) TREE_OPERAND (NODE, 1)
+#define DO_COND(NODE) TREE_OPERAND (NODE, 0)
+#define DO_BODY(NODE) TREE_OPERAND (NODE, 1)
+#define RETURN_EXPR(NODE) TREE_OPERAND (NODE, 0)
+#define EXPR_STMT_EXPR(NODE) TREE_OPERAND (NODE, 0)
+#define FOR_INIT_STMT(NODE) TREE_OPERAND (NODE, 0)
+#define FOR_COND(NODE) TREE_OPERAND (NODE, 1)
+#define FOR_EXPR(NODE) TREE_OPERAND (NODE, 2)
+#define FOR_BODY(NODE) TREE_OPERAND (NODE, 3)
+#define SWITCH_COND(NODE) TREE_OPERAND (NODE, 0)
+#define SWITCH_BODY(NODE) TREE_OPERAND (NODE, 1)
+#define CASE_LOW(NODE) TREE_OPERAND (NODE, 0)
+#define CASE_HIGH(NODE) TREE_OPERAND (NODE, 1)
+#define GOTO_DESTINATION(NODE) TREE_OPERAND (NODE, 0)
+#define TRY_STMTS(NODE) TREE_OPERAND (NODE, 0)
+#define TRY_HANDLERS(NODE) TREE_OPERAND (NODE, 1)
+#define HANDLER_PARMS(NODE) TREE_OPERAND (NODE, 0)
+#define HANDLER_BODY(NODE) TREE_OPERAND (NODE, 1)
+#define COMPOUND_BODY(NODE) TREE_OPERAND (NODE, 0)
+#define ASM_CV_QUAL(NODE) TREE_OPERAND (NODE, 0)
+#define ASM_STRING(NODE) TREE_OPERAND (NODE, 1)
+#define ASM_OUTPUTS(NODE) TREE_OPERAND (NODE, 2)
+#define ASM_INPUTS(NODE) TREE_OPERAND (NODE, 3)
+#define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4)
+
/* An enumeration of the kind of tags that C++ accepts. */
enum tag_types { record_type, class_type, union_type, enum_type,
signature_type };
@@ -1423,6 +1707,9 @@ extern int flag_detailed_statistics;
type signature of any virtual function in the base class. */
extern int warn_overloaded_virtual;
+/* Nonzero means warn about use of multicharacter literals. */
+extern int warn_multichar;
+
/* in c-common.c */
extern void declare_function_name PROTO((void));
extern void decl_attributes PROTO((tree, tree, tree));
@@ -1433,6 +1720,7 @@ extern void check_function_format PROTO((tree, tree, tree));
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code));
extern tree cp_build_type_variant PROTO((tree, int, int));
+extern tree canonical_type_variant PROTO((tree));
extern void c_expand_expr_stmt PROTO((tree));
/* Validate the expression after `case' and apply default promotions. */
extern tree check_case_value PROTO((tree));
@@ -1443,16 +1731,23 @@ extern tree convert_and_check PROTO((tree, tree));
extern void overflow_warning PROTO((tree));
extern void unsigned_conversion_warning PROTO((tree, tree));
/* Read the rest of the current #-directive line. */
-extern char *get_directive_line STDIO_PROTO((FILE *));
+#if USE_CPPLIB
+extern char *get_directive_line PROTO((void));
+#define GET_DIRECTIVE_LINE() get_directive_line ()
+#else
+extern char *get_directive_line PROTO((FILE *));
+#define GET_DIRECTIVE_LINE() get_directive_line (finput)
+#endif
/* Subroutine of build_binary_op, used for comparison operations.
See if the operands have both been converted from subword integer types
and, if so, perhaps change them both back to their original type. */
extern tree shorten_compare PROTO((tree *, tree *, tree *, enum tree_code *));
/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
- or validate its data type for an `if' or `while' statement or ?..: exp. */
+ or validate its data type for an `if' or `while' statement or ?..: exp. */
extern tree truthvalue_conversion PROTO((tree));
extern tree type_for_mode PROTO((enum machine_mode, int));
extern tree type_for_size PROTO((unsigned, int));
+extern int c_get_alias_set PROTO((tree));
/* in decl{2}.c */
extern tree void_list_node;
@@ -1461,7 +1756,9 @@ extern tree default_function_type;
extern tree vtable_entry_type;
extern tree sigtable_entry_type;
extern tree __t_desc_type_node;
+#if 0
extern tree __tp_desc_type_node;
+#endif
extern tree __access_mode_type_node;
extern tree __bltn_desc_type_node, __user_desc_type_node;
extern tree __class_desc_type_node, __attr_desc_type_node;
@@ -1470,87 +1767,89 @@ extern tree __ptmf_desc_type_node, __ptmd_desc_type_node;
extern tree type_info_type_node;
extern tree class_star_type_node;
extern tree this_identifier;
+extern tree ctor_identifier, dtor_identifier;
extern tree pfn_identifier;
extern tree index_identifier;
extern tree delta_identifier;
extern tree delta2_identifier;
extern tree pfn_or_delta2_identifier;
extern tree tag_identifier;
-extern tree vb_off_identifier;
extern tree vt_off_identifier;
/* A node that is a list (length 1) of error_mark_nodes. */
extern tree error_mark_list;
-extern tree ptr_type_node, const_ptr_type_node;
+extern tree ptr_type_node;
extern tree class_type_node, record_type_node, union_type_node, enum_type_node;
extern tree unknown_type_node;
extern tree opaque_type_node, signature_type_node;
/* Node for "pointer to (virtual) function".
- This may be distinct from ptr_type_node so gdb can distinguish them. */
+ This may be distinct from ptr_type_node so gdb can distinguish them. */
#define vfunc_ptr_type_node \
(flag_vtable_thunks ? vtable_entry_type : ptr_type_node)
/* Array type `(void *)[]' */
extern tree vtbl_type_node;
extern tree delta_type_node;
+extern tree std_node;
extern tree long_long_integer_type_node, long_long_unsigned_type_node;
/* For building calls to `delete'. */
extern tree integer_two_node, integer_three_node;
extern tree boolean_type_node, boolean_true_node, boolean_false_node;
+extern tree null_node;
+
/* in pt.c */
-/* PARM_VEC is a vector of template parameters, either IDENTIFIER_NODEs or
- PARM_DECLs. BINDINGS, if non-null, is a vector of bindings for those
- parameters. */
-struct template_info {
- /* Vector of template parameters, either PARM_DECLs or IDENTIFIER_NODEs. */
- tree parm_vec;
- /* If non-null, a vector of bindings for the template parms. */
- tree bindings;
-
- /* Text of template, and length. */
- char *text;
- int length;
- /* Where it came from. */
- char *filename;
- int lineno;
- /* What kind of aggregate -- struct, class, or null. */
- tree aggr;
-};
-extern int processing_template_decl, processing_template_defn;
+/* These values are used for the `STRICT' parameter to type_unfication and
+ fn_type_unification. Their meanings are described with the
+ documentation for fn_type_unification. */
+
+typedef enum unification_kind_t {
+ DEDUCE_CALL,
+ DEDUCE_CONV,
+ DEDUCE_EXACT
+} unification_kind_t;
+
+extern tree current_template_parms;
+extern HOST_WIDE_INT processing_template_decl;
+extern tree last_tree;
/* The template currently being instantiated, and where the instantiation
was triggered. */
struct tinst_level
{
- tree classname;
+ tree decl;
int line;
char *file;
struct tinst_level *next;
};
+extern int minimal_parse_mode;
+
+extern void maybe_print_template_context PROTO ((void));
+
/* in class.c */
extern tree current_class_name;
extern tree current_class_type;
+extern tree current_class_ptr;
extern tree previous_class_type;
+extern tree current_class_ref;
+extern int current_class_depth;
-extern tree current_lang_name, lang_name_cplusplus, lang_name_c;
+extern tree current_lang_name;
+extern tree lang_name_cplusplus, lang_name_c, lang_name_java;
/* Points to the name of that function. May not be the DECL_NAME
of CURRENT_FUNCTION_DECL due to overloading */
extern tree original_function_name;
-extern tree current_class_name, current_class_type, current_class_decl, C_C_D;
-
/* in init.c */
extern tree global_base_init_list;
extern tree current_base_init_list, current_member_init_list;
-extern int current_function_assigns_this;
extern int current_function_just_assigned_this;
extern int current_function_parms_stored;
@@ -1671,6 +1970,8 @@ extern int current_function_parms_stored;
#define THIS_NAME "this"
#define DESTRUCTOR_NAME_FORMAT "~%s"
#define FILE_FUNCTION_PREFIX_LEN 9
+#define CTOR_NAME "__ct"
+#define DTOR_NAME "__dt"
#define IN_CHARGE_NAME "__in_chrg"
@@ -1726,23 +2027,34 @@ extern int current_function_parms_stored;
#define ANON_PARMNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == '_' \
&& IDENTIFIER_POINTER (ID_NODE)[1] <= '9')
#endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */
+
+/* Returns non-zero iff ID_NODE is an IDENTIFIER_NODE whose name is
+ `main'. */
+#define MAIN_NAME_P(ID_NODE) \
+ (strcmp (IDENTIFIER_POINTER (ID_NODE), "main") == 0)
+
+/* Returns non-zero iff NODE is a declaration for the global function
+ `main'. */
+#define DECL_MAIN_P(NODE) \
+ (TREE_CODE (NODE) == FUNCTION_DECL \
+ && DECL_CONTEXT (NODE) == NULL_TREE \
+ && DECL_NAME (NODE) != NULL_TREE \
+ && MAIN_NAME_P (DECL_NAME (NODE)))
+
/* Define the sets of attributes that member functions and baseclasses
can have. These are sensible combinations of {public,private,protected}
cross {virtual,non-virtual}. */
-enum access_type {
- access_default,
- access_public,
- access_protected,
- access_private,
- access_default_virtual,
- access_public_virtual,
- access_private_virtual
-};
-
-/* in lex.c */
-extern tree current_unit_name, current_unit_language;
+/* in class.c. */
+extern tree access_default_node; /* 0 */
+extern tree access_public_node; /* 1 */
+extern tree access_protected_node; /* 2 */
+extern tree access_private_node; /* 3 */
+extern tree access_default_virtual_node; /* 4 */
+extern tree access_public_virtual_node; /* 5 */
+extern tree access_protected_virtual_node; /* 6 */
+extern tree access_private_virtual_node; /* 7 */
/* Things for handling inline functions. */
@@ -1757,7 +2069,6 @@ struct pending_inline
char *buf; /* pointer to character stream */
int len; /* length of stream */
- tree parm_vec, bindings; /* in case this is derived from a template */
unsigned int can_free : 1; /* free this after we're done with it? */
unsigned int deja_vu : 1; /* set iff we don't want to see it again. */
unsigned int interface : 2; /* 0=interface 1=unknown 2=implementation */
@@ -1784,10 +2095,6 @@ extern int flag_this_is_variable;
extern int flag_int_enum_equivalence;
-/* Nonzero means layout structures so that we can do garbage collection. */
-
-extern int flag_gc;
-
/* Nonzero means generate 'rtti' that give run-time type information. */
extern int flag_rtti;
@@ -1809,17 +2116,25 @@ extern int flag_alt_external_templates;
extern int flag_implicit_templates;
-/* Current end of entries in the gc obstack for stack pointer variables. */
+/* Nonzero if we want to emit defined symbols with common-like linkage as
+ weak symbols where possible, in order to conform to C++ semantics.
+ Otherwise, emit them as local symbols. */
-extern int current_function_obstack_index;
+extern int flag_weak;
-/* Flag saying whether we have used the obstack in this function or not. */
+/* Nonzero to enable experimental ABI changes. */
-extern int current_function_obstack_usage;
+extern int flag_new_abi;
-enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
+/* Nonzero to not ignore namespace std. */
-extern tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */
+extern int flag_honor_std;
+
+/* Nonzero if we're done parsing and into end-of-file activities. */
+
+extern int at_eof;
+
+enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
/* The following two can be derived from the previous one */
extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */
@@ -1837,32 +2152,56 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
LOOKUP_COMPLAIN mean complain if no suitable member function
matching the arguments is found.
LOOKUP_NORMAL is just a combination of these two.
- LOOKUP_AGGR requires the instance to be of aggregate type.
LOOKUP_NONVIRTUAL means make a direct call to the member function found
LOOKUP_GLOBAL means search through the space of overloaded functions,
as well as the space of member functions.
LOOKUP_HAS_IN_CHARGE means that the "in charge" variable is already
in the parameter list.
LOOKUP_ONLYCONVERTING means that non-conversion constructors are not tried.
+ DIRECT_BIND means that if a temporary is created, it should be created so
+ that it lives as long as the current variable bindings; otherwise it
+ only lives until the end of the complete-expression.
LOOKUP_SPECULATIVELY means return NULL_TREE if we cannot find what we are
after. Note, LOOKUP_COMPLAIN is checked and error messages printed
before LOOKUP_SPECULATIVELY is checked.
LOOKUP_NO_CONVERSION means that user-defined conversions are not
permitted. Built-in conversions are permitted.
- LOOKUP_DESTRUCTOR means explicit call to destructor. */
+ LOOKUP_DESTRUCTOR means explicit call to destructor.
+ LOOKUP_NO_TEMP_BIND means temporaries will not be bound to references.
+
+ These are used in global lookup to support elaborated types and
+ qualifiers.
+
+ LOOKUP_PREFER_TYPES means not to accept objects, and possibly namespaces.
+ LOOKUP_PREFER_NAMESPACES means not to accept objects, and possibly types.
+ LOOKUP_PREFER_BOTH means class-or-namespace-name.
+ LOOKUP_TEMPLATES_EXPECTED means that class templates also count
+ as types. */
#define LOOKUP_PROTECT (1)
#define LOOKUP_COMPLAIN (2)
#define LOOKUP_NORMAL (3)
-#define LOOKUP_AGGR (4)
+/* #define LOOKUP_UNUSED (4) */
#define LOOKUP_NONVIRTUAL (8)
#define LOOKUP_GLOBAL (16)
#define LOOKUP_HAS_IN_CHARGE (32)
#define LOOKUP_SPECULATIVELY (64)
#define LOOKUP_ONLYCONVERTING (128)
-/* 256 is free */
+#define DIRECT_BIND (256)
#define LOOKUP_NO_CONVERSION (512)
#define LOOKUP_DESTRUCTOR (512)
+#define LOOKUP_NO_TEMP_BIND (1024)
+#define LOOKUP_PREFER_TYPES (2048)
+#define LOOKUP_PREFER_NAMESPACES (4096)
+#define LOOKUP_PREFER_BOTH (6144)
+#define LOOKUP_TEMPLATES_EXPECTED (8192)
+
+#define LOOKUP_NAMESPACES_ONLY(f) \
+ (((f) & LOOKUP_PREFER_NAMESPACES) && !((f) & LOOKUP_PREFER_TYPES))
+#define LOOKUP_TYPES_ONLY(f) \
+ (!((f) & LOOKUP_PREFER_NAMESPACES) && ((f) & LOOKUP_PREFER_TYPES))
+#define LOOKUP_QUALIFIERS_ONLY(f) ((f) & LOOKUP_PREFER_BOTH)
+
/* These flags are used by the conversion code.
CONV_IMPLICIT : Perform implicit conversions (standard and user-defined).
@@ -1870,7 +2209,6 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
CONV_CONST : Perform the explicit conversions for const_cast.
CONV_REINTERPRET: Perform the explicit conversions for reinterpret_cast.
CONV_PRIVATE : Perform upcasts to private bases.
- CONV_NONCONVERTING : Allow non-converting constructors to be used.
CONV_FORCE_TEMP : Require a new temporary when converting to the same
aggregate type. */
@@ -1879,7 +2217,7 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define CONV_CONST 4
#define CONV_REINTERPRET 8
#define CONV_PRIVATE 16
-#define CONV_NONCONVERTING 32
+/* #define CONV_NONCONVERTING 32 */
#define CONV_FORCE_TEMP 64
#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_FORCE_TEMP)
#define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
@@ -1898,23 +2236,27 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define WANT_ARITH (WANT_INT | WANT_FLOAT)
-/* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST):
- purpose = friend name (IDENTIFIER_NODE);
- value = TREE_LIST of FUNCTION_DECLS;
- chain, type = EMPTY; */
#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
-/* These macros are for accessing the fields of TEMPLATE...PARM nodes. */
-#define TEMPLATE_TYPE_TPARMLIST(NODE) TREE_PURPOSE (TYPE_FIELDS (NODE))
-#define TEMPLATE_TYPE_IDX(NODE) TREE_INT_CST_LOW (TREE_VALUE (TYPE_FIELDS (NODE)))
-#define TEMPLATE_TYPE_SET_INFO(NODE,P,I) \
- (TYPE_FIELDS (NODE) = build_tree_list (P, build_int_2 (I, 0)))
-#define TEMPLATE_CONST_TPARMLIST(NODE) (*(tree*)&TREE_INT_CST_LOW(NODE))
-#define TEMPLATE_CONST_IDX(NODE) (TREE_INT_CST_HIGH(NODE))
-#define TEMPLATE_CONST_SET_INFO(NODE,P,I) \
- (TEMPLATE_CONST_TPARMLIST (NODE) = saved_parmlist, \
- TEMPLATE_CONST_IDX (NODE) = I)
+/* These macros are used to access a TEMPLATE_PARM_INDEX. */
+#define TEMPLATE_PARM_IDX(NODE) (((template_parm_index*) NODE)->index)
+#define TEMPLATE_PARM_LEVEL(NODE) (((template_parm_index*) NODE)->level)
+#define TEMPLATE_PARM_DESCENDANTS(NODE) (TREE_CHAIN (NODE))
+#define TEMPLATE_PARM_ORIG_LEVEL(NODE) (((template_parm_index*) NODE)->orig_level)
+#define TEMPLATE_PARM_DECL(NODE) (((template_parm_index*) NODE)->decl)
+
+/* These macros are for accessing the fields of TEMPLATE_TYPE_PARM
+ and TEMPLATE_TEMPLATE_PARM nodes. */
+#define TEMPLATE_TYPE_PARM_INDEX(NODE) (TYPE_FIELDS (NODE))
+#define TEMPLATE_TYPE_IDX(NODE) \
+ (TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE)))
+#define TEMPLATE_TYPE_LEVEL(NODE) \
+ (TEMPLATE_PARM_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
+#define TEMPLATE_TYPE_ORIG_LEVEL(NODE) \
+ (TEMPLATE_PARM_ORIG_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
+#define TEMPLATE_TYPE_DECL(NODE) \
+ (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
/* in lex.c */
/* Indexed by TREE_CODE, these tables give C-looking names to
@@ -1922,163 +2264,214 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
opname_tab[(int) MINUS_EXPR] == "-". */
extern char **opname_tab, **assignop_tab;
-/* in c-common.c */
-extern tree convert_and_check PROTO((tree, tree));
-extern void overflow_warning PROTO((tree));
-extern void unsigned_conversion_warning PROTO((tree, tree));
-
/* in call.c */
-extern struct candidate *ansi_c_bullshit;
-
-extern int rank_for_overload PROTO((struct candidate *, struct candidate *));
-extern void compute_conversion_costs PROTO((tree, tree, struct candidate *, int));
+extern int check_dtor_name PROTO((tree, tree));
extern int get_arglist_len_in_bytes PROTO((tree));
+
extern tree build_vfield_ref PROTO((tree, tree));
-extern tree find_scoped_type PROTO((tree, tree, tree));
extern tree resolve_scope_to_name PROTO((tree, tree));
extern tree build_scoped_method_call PROTO((tree, tree, tree, tree));
+extern tree build_addr_func PROTO((tree));
+extern tree build_call PROTO((tree, tree, tree));
extern tree build_method_call PROTO((tree, tree, tree, tree, int));
-extern tree build_overload_call_real PROTO((tree, tree, int, struct candidate *, int));
-extern tree build_overload_call PROTO((tree, tree, int, struct candidate *));
-extern tree build_overload_call_maybe PROTO((tree, tree, int, struct candidate *));
+extern int null_ptr_cst_p PROTO((tree));
+extern tree type_decays_to PROTO((tree));
+extern tree build_user_type_conversion PROTO((tree, tree, int));
+extern tree build_new_function_call PROTO((tree, tree));
+extern tree build_new_op PROTO((enum tree_code, int, tree, tree, tree));
+extern tree build_op_new_call PROTO((enum tree_code, tree, tree, int));
+extern tree build_op_delete_call PROTO((enum tree_code, tree, tree, int, tree));
+extern int can_convert PROTO((tree, tree));
+extern int can_convert_arg PROTO((tree, tree, tree));
+extern void enforce_access PROTO((tree, tree));
+extern tree convert_default_arg PROTO((tree, tree));
+extern tree convert_arg_to_ellipsis PROTO((tree));
/* in class.c */
-extern char *dont_allow_type_definitions;
-extern tree build_vbase_pointer PROTO((tree, tree));
extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int));
-extern tree build_vtable_entry PROTO((tree, tree));
+extern tree build_vtbl_ref PROTO((tree, tree));
extern tree build_vfn_ref PROTO((tree *, tree, tree));
extern void add_method PROTO((tree, tree *, tree));
+extern int currently_open_class PROTO((tree));
extern tree get_vfield_offset PROTO((tree));
extern void duplicate_tag_error PROTO((tree));
-extern tree finish_struct PROTO((tree, tree, int));
+extern tree finish_struct PROTO((tree, tree, tree, int));
+extern tree finish_struct_1 PROTO((tree, int));
+extern tree finish_struct_methods PROTO((tree, tree, int));
extern int resolves_to_fixed_type_p PROTO((tree, int *));
extern void init_class_processing PROTO((void));
+extern int is_empty_class PROTO((tree));
extern void pushclass PROTO((tree, int));
extern void popclass PROTO((int));
extern void push_nested_class PROTO((tree, int));
extern void pop_nested_class PROTO((int));
extern void push_lang_context PROTO((tree));
extern void pop_lang_context PROTO((void));
-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 *));
+extern tree build_self_reference PROTO((void));
+extern void warn_hidden PROTO((tree));
/* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
extern tree convert_from_reference PROTO((tree));
-extern tree convert_to_aggr PROTO((tree, tree, char **, int));
-extern tree convert_pointer_to PROTO((tree, tree));
extern tree convert_pointer_to_real PROTO((tree, tree));
-extern tree convert_pointer_to_vbase PROTO((tree, tree));
+extern tree convert_pointer_to PROTO((tree, tree));
+extern tree ocp_convert PROTO((tree, tree, int, int));
+extern tree cp_convert PROTO((tree, tree));
extern tree convert PROTO((tree, tree));
-extern tree cp_convert PROTO((tree, tree, int, int));
extern tree convert_force PROTO((tree, tree, int));
extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int));
extern tree build_expr_type_conversion PROTO((int, tree, int));
-extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *));
extern tree type_promotes_to PROTO((tree));
+extern tree perform_qualification_conversions PROTO((tree, tree));
/* decl.c */
+/* resume_binding_level */
extern int global_bindings_p PROTO((void));
extern int toplevel_bindings_p PROTO((void));
extern void keep_next_level PROTO((void));
extern int kept_level_p PROTO((void));
extern void declare_parm_level PROTO((void));
-extern void declare_implicit_exception PROTO((void));
-extern int have_exceptions_p PROTO((void));
-extern void declare_uninstantiated_type_level PROTO((void));
-extern int uninstantiated_type_level_p PROTO((void));
extern void declare_pseudo_global_level PROTO((void));
extern int pseudo_global_level_p PROTO((void));
+extern void set_class_shadows PROTO((tree));
extern void pushlevel PROTO((int));
+extern void note_level_for_for PROTO((void));
extern void pushlevel_temporary PROTO((int));
extern tree poplevel PROTO((int, int, int));
+extern void resume_level PROTO((struct binding_level *));
extern void delete_block PROTO((tree));
extern void insert_block PROTO((tree));
extern void add_block_current_level PROTO((tree));
extern void set_block PROTO((tree));
extern void pushlevel_class PROTO((void));
extern tree poplevel_class PROTO((int));
-/* skip print_other_binding_stack and print_binding_level */
extern void print_binding_stack PROTO((void));
+extern void print_binding_level PROTO((struct binding_level *));
+extern void push_namespace PROTO((tree));
+extern void pop_namespace PROTO((void));
+extern void maybe_push_to_top_level PROTO((int));
extern void push_to_top_level PROTO((void));
extern void pop_from_top_level PROTO((void));
+extern tree identifier_type_value PROTO((tree));
extern void set_identifier_type_value PROTO((tree, tree));
+extern void set_identifier_local_value PROTO((tree, tree));
extern void pop_everything PROTO((void));
-extern tree make_type_decl PROTO((tree, tree));
extern void pushtag PROTO((tree, tree, int));
extern tree make_anon_name PROTO((void));
extern void clear_anon_tags PROTO((void));
+extern int decls_match PROTO((tree, tree));
+extern int duplicate_decls PROTO((tree, tree));
extern tree pushdecl PROTO((tree));
extern tree pushdecl_top_level PROTO((tree));
-extern void push_class_level_binding PROTO((tree, tree));
-extern void push_overloaded_decl_top_level PROTO((tree, int));
extern tree pushdecl_class_level PROTO((tree));
-extern tree pushdecl_nonclass_level PROTO((tree));
-extern int overloaded_globals_p PROTO((tree));
-extern tree push_overloaded_decl PROTO((tree, int));
+#if 0
+extern void pushdecl_nonclass_level PROTO((tree));
+#endif
+extern tree pushdecl_namespace_level PROTO((tree));
+extern tree push_using_decl PROTO((tree, tree));
+extern tree push_using_directive PROTO((tree));
+extern void push_class_level_binding PROTO((tree, tree));
+extern tree push_using_decl PROTO((tree, tree));
extern tree implicitly_declare PROTO((tree));
extern tree lookup_label PROTO((tree));
extern tree shadow_label PROTO((tree));
extern tree define_label PROTO((char *, int, tree));
+extern void push_switch PROTO((void));
+extern void pop_switch PROTO((void));
extern void define_case_label PROTO((tree));
extern tree getdecls PROTO((void));
extern tree gettags PROTO((void));
+#if 0
extern void set_current_level_tags_transparency PROTO((int));
-extern tree typedecl_for_tag PROTO((tree));
-extern tree lookup_name PROTO((tree, int));
+#endif
+extern tree binding_for_name PROTO((tree, tree));
+extern tree namespace_binding PROTO((tree, tree));
+extern void set_namespace_binding PROTO((tree, tree, tree));
extern tree lookup_namespace_name PROTO((tree, tree));
+extern tree make_typename_type PROTO((tree, tree));
+extern tree lookup_name_nonclass PROTO((tree));
+extern tree lookup_function_nonclass PROTO((tree, tree));
+extern tree lookup_name PROTO((tree, int));
extern tree lookup_name_current_level PROTO((tree));
+extern tree lookup_type_current_level PROTO((tree));
+extern tree lookup_name_namespace_only PROTO((tree));
+extern void begin_only_namespace_names PROTO((void));
+extern void end_only_namespace_names PROTO((void));
+extern tree namespace_ancestor PROTO((tree, tree));
+extern int lookup_using_namespace PROTO((tree,tree,tree,tree,int));
+extern int qualified_lookup_using_namespace PROTO((tree,tree,tree,int));
+extern tree auto_function PROTO((tree, tree, enum built_in_function));
extern void init_decl_processing PROTO((void));
-/* skipped define_function */
+extern int init_type_desc PROTO((void));
+extern tree define_function
+ PROTO((char *, tree, enum built_in_function,
+ void (*) (tree), char *));
extern void shadow_tag PROTO((tree));
-extern int grok_ctor_properties PROTO((tree, tree));
extern tree groktypename PROTO((tree));
-extern tree start_decl PROTO((tree, tree, int, tree));
+extern tree start_decl PROTO((tree, tree, int, tree, tree));
+extern void start_decl_1 PROTO((tree));
extern void cp_finish_decl PROTO((tree, tree, tree, int, int));
+extern void finish_decl PROTO((tree, tree, tree));
extern void expand_static_init PROTO((tree, tree));
extern int complete_array_type PROTO((tree, tree, int));
extern tree build_ptrmemfunc_type PROTO((tree));
/* the grokdeclarator prototype is in decl.h */
extern int parmlist_is_exprlist PROTO((tree));
+extern int copy_args_p PROTO((tree));
+extern int grok_ctor_properties PROTO((tree, tree));
+extern void grok_op_properties PROTO((tree, int, int));
extern tree xref_tag PROTO((tree, tree, tree, int));
+extern tree xref_tag_from_type PROTO((tree, tree, int));
extern void xref_basetypes PROTO((tree, tree, tree, tree));
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, tree, int));
-extern void store_parm_decls PROTO((void));
+extern tree grok_enum_decls PROTO((tree));
+extern int start_function PROTO((tree, tree, tree, int));
extern void expand_start_early_try_stmts PROTO((void));
-extern void store_in_parms PROTO((struct rtx_def *));
+extern void store_parm_decls PROTO((void));
extern void store_return_init PROTO((tree, tree));
extern void finish_function PROTO((int, int, int));
-extern tree start_method PROTO((tree, tree, tree));
+extern tree start_method PROTO((tree, tree));
extern tree finish_method PROTO((tree));
extern void hack_incomplete_structures PROTO((tree));
+extern tree maybe_build_cleanup_and_delete PROTO((tree));
extern tree maybe_build_cleanup PROTO((tree));
extern void cplus_expand_expr_stmt PROTO((tree));
extern void finish_stmt PROTO((void));
-extern void pop_implicit_try_blocks PROTO((tree));
-extern void push_exception_cleanup PROTO((tree));
-extern void revert_static_member_fn PROTO((tree *, tree *, tree *));
+extern int id_in_current_class PROTO((tree));
+extern void push_cp_function_context PROTO((tree));
+extern void pop_cp_function_context PROTO((tree));
+extern int in_function_p PROTO((void));
+extern void replace_defarg PROTO((tree, tree));
+extern void print_other_binding_stack PROTO((struct binding_level *));
+extern void revert_static_member_fn PROTO((tree*, tree*, tree*));
+extern void cat_namespace_levels PROTO((void));
/* in decl2.c */
-extern int lang_decode_option PROTO((char *));
+extern int check_java_method PROTO((tree, tree));
+extern int flag_assume_nonnull_objects;
+extern int lang_decode_option PROTO((int, char **));
extern tree grok_method_quals PROTO((tree, tree, tree));
+extern void warn_if_unknown_interface PROTO((tree));
+extern tree grok_x_components PROTO((tree, tree));
+extern void maybe_retrofit_in_chrg PROTO((tree));
+extern void maybe_make_one_only PROTO((tree));
extern void grokclassfn PROTO((tree, tree, tree, enum overload_flags, tree));
extern tree grok_alignof PROTO((tree));
extern tree grok_array_decl PROTO((tree, tree));
extern tree delete_sanity PROTO((tree, tree, int, int));
-extern tree check_classfn PROTO((tree, tree, tree));
-extern tree grokfield PROTO((tree, tree, tree, tree, tree, tree));
+extern tree check_classfn PROTO((tree, tree));
+extern void check_member_template PROTO((tree));
+extern tree grokfield PROTO((tree, tree, tree, tree, tree));
extern tree grokbitfield PROTO((tree, tree, tree));
extern tree groktypefield PROTO((tree, tree));
extern tree grokoptypename PROTO((tree, tree));
-extern tree build_push_scope PROTO((tree, tree));
+extern int copy_assignment_arg_p PROTO((tree, int));
extern void cplus_decl_attributes PROTO((tree, tree, tree));
extern tree constructor_name_full PROTO((tree));
extern tree constructor_name PROTO((tree));
@@ -2092,232 +2485,278 @@ extern tree finish_table PROTO((tree, tree, tree, int));
extern void finish_builtin_type PROTO((tree, char *, tree *, int, tree));
extern tree coerce_new_type PROTO((tree));
extern tree coerce_delete_type PROTO((tree));
-extern void walk_vtables PROTO((void (*)(), void (*)()));
-extern void walk_sigtables PROTO((void (*)(), void (*)()));
+extern void comdat_linkage PROTO((tree));
+extern void import_export_class PROTO((tree));
+extern void import_export_vtable PROTO((tree, tree, int));
+extern int finish_prevtable_vardecl PROTO((tree, tree));
+extern int walk_vtables PROTO((void (*)(tree, tree),
+ int (*)(tree, tree)));
+extern void walk_sigtables PROTO((void (*)(tree, tree),
+ void (*)(tree, tree)));
+extern void import_export_decl PROTO((tree));
+extern tree build_cleanup PROTO((tree));
extern void finish_file PROTO((void));
-extern void warn_if_unknown_interface PROTO((tree));
-extern tree grok_x_components PROTO((tree, tree));
extern tree reparse_absdcl_as_expr PROTO((tree, tree));
extern tree reparse_absdcl_as_casts PROTO((tree, tree));
+extern tree build_expr_from_tree PROTO((tree));
extern tree reparse_decl_as_expr PROTO((tree, tree));
extern tree finish_decl_parsing PROTO((tree));
-extern tree lookup_name_nonclass PROTO((tree));
extern tree check_cp_case_value PROTO((tree));
-extern tree do_toplevel_using_decl PROTO((tree));
+extern void set_decl_namespace PROTO((tree, tree));
+extern tree current_decl_namespace PROTO((void));
+extern void push_decl_namespace PROTO((tree));
+extern void pop_decl_namespace PROTO((void));
+extern void do_namespace_alias PROTO((tree, tree));
+extern void do_toplevel_using_decl PROTO((tree));
+extern void do_local_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 do_using_directive PROTO((tree));
extern void check_default_args PROTO((tree));
+extern void mark_used PROTO((tree));
+extern tree handle_class_head PROTO((tree, tree, tree));
+extern tree lookup_arg_dependent PROTO((tree, tree, tree));
-/* in edsel.c */
+/* in errfn.c */
+extern void cp_error ();
+extern void cp_error_at ();
+extern void cp_warning ();
+extern void cp_warning_at ();
+extern void cp_pedwarn ();
+extern void cp_pedwarn_at ();
+extern void cp_compiler_error ();
+extern void cp_sprintf ();
+
+/* in error.c */
+extern void init_error PROTO((void));
+extern char *fndecl_as_string PROTO((tree, int));
+extern char *type_as_string PROTO((tree, int));
+extern char *type_as_string_real PROTO((tree, int, int));
+extern char *args_as_string PROTO((tree, int));
+extern char *decl_as_string PROTO((tree, int));
+extern char *expr_as_string PROTO((tree, int));
+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 *assop_as_string PROTO((enum tree_code, int));
+extern char *cv_as_string PROTO((tree, int));
+extern char *lang_decl_name PROTO((tree, int));
+extern char *cp_file_of PROTO((tree));
+extern int cp_line_of PROTO((tree));
/* in except.c */
-extern tree protect_list;
-extern void start_protect PROTO((void));
-extern void end_protect PROTO((tree));
-extern void end_protect_partials ();
-extern void expand_exception_blocks PROTO((void));
-extern void expand_start_try_stmts PROTO((void));
-extern void expand_end_try_stmts PROTO((void));
-extern void expand_start_all_catch PROTO((void));
-extern void expand_end_all_catch PROTO((void));
-extern void start_catch_block PROTO((tree, tree));
-extern void end_catch_block PROTO((void));
-extern void expand_throw PROTO((tree));
-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_start_catch_block PROTO((tree, tree));
+extern void expand_end_catch_block PROTO((void));
extern void expand_builtin_throw PROTO((void));
extern void expand_start_eh_spec PROTO((void));
-extern void expand_end_eh_spec PROTO((tree));
+extern void expand_exception_blocks PROTO((void));
+extern tree start_anon_func PROTO((void));
+extern void end_anon_func PROTO((void));
+extern void expand_throw PROTO((tree));
+extern tree build_throw PROTO((tree));
+extern void mark_all_runtime_matches PROTO((void));
/* 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));
-extern int value_safe_from_gc PROTO((tree, tree));
-extern void build_static_gc_entry PROTO((tree, tree));
-extern tree protect_value_from_gc PROTO((tree, tree));
-extern tree build_headof PROTO((tree));
-extern tree build_classof PROTO((tree));
-extern tree build_t_desc PROTO((tree, int));
-extern tree build_i_desc PROTO((tree));
-extern tree build_m_desc PROTO((tree));
-extern void expand_gc_prologue_and_epilogue PROTO((void));
-extern void lang_expand_end_bindings PROTO((struct rtx_def *, struct rtx_def *));
-extern void init_gc_processing PROTO((void));
-extern tree build_typeid PROTO((tree));
-extern tree get_typeid PROTO((tree));
-extern tree build_dynamic_cast PROTO((tree, tree));
+extern int extract_init PROTO((tree, tree));
+extern void do_case PROTO((tree, tree));
+
+/* friend.c */
+extern int is_friend PROTO((tree, tree));
+extern void make_friend_class PROTO((tree, tree));
+extern tree do_friend PROTO((tree, tree, tree, tree, enum overload_flags, tree, int));
/* in init.c */
+extern void init_init_processing PROTO((void));
+extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree));
extern void emit_base_init PROTO((tree, int));
extern void check_base_init PROTO((tree));
-extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree));
-extern void do_member_init PROTO((tree, tree, tree));
extern void expand_member_init PROTO((tree, tree, tree));
extern void expand_aggr_init PROTO((tree, tree, int, int));
extern int is_aggr_typedef PROTO((tree, int));
+extern int is_aggr_type PROTO((tree, int));
extern tree get_aggr_from_typedef PROTO((tree, int));
extern tree get_type_value PROTO((tree));
extern tree build_member_call PROTO((tree, tree, tree));
extern tree build_offset_ref PROTO((tree, tree));
-extern tree get_member_function PROTO((tree *, tree, tree));
-extern tree get_member_function_from_ptrfunc PROTO((tree *, tree));
extern tree resolve_offset_ref PROTO((tree));
extern tree decl_constant_value PROTO((tree));
-extern int is_friend_type PROTO((tree, tree));
-extern int is_friend PROTO((tree, tree));
-extern void make_friend_class PROTO((tree, tree));
-extern tree do_friend PROTO((tree, tree, tree, tree, enum overload_flags, tree));
-extern void embrace_waiting_friends PROTO((tree));
-extern tree build_builtin_call PROTO((tree, tree, tree));
extern tree build_new PROTO((tree, tree, tree, int));
+extern tree build_new_1 PROTO((tree));
extern tree expand_vec_init PROTO((tree, tree, tree, tree, int));
extern tree build_x_delete PROTO((tree, tree, int, tree));
extern tree build_delete PROTO((tree, tree, tree, int, int));
extern tree build_vbase_delete PROTO((tree, tree));
-extern tree build_vec_delete PROTO((tree, tree, tree, tree, tree, int));
+extern tree build_vec_delete PROTO((tree, tree, tree, tree, int));
/* in input.c */
/* in lex.c */
+extern char *file_name_nondirectory PROTO((char *));
extern tree make_pointer_declarator PROTO((tree, tree));
extern tree make_reference_declarator PROTO((tree, tree));
+extern tree make_call_declarator PROTO((tree, tree, tree, tree));
+extern void set_quals_and_spec PROTO((tree, tree, tree));
extern char *operator_name_string PROTO((tree));
extern void lang_init PROTO((void));
extern void lang_finish PROTO((void));
extern void init_filename_times PROTO((void));
+#if 0
extern void reinit_lang_specific PROTO((void));
-extern void init_lex PROTO((void));
+#endif
extern void reinit_parse_for_function PROTO((void));
-extern int *init_parse PROTO((void));
extern void print_parse_statistics PROTO((void));
extern void extract_interface_info PROTO((void));
-extern void set_vardecl_interface_info PROTO((tree, tree));
extern void do_pending_inlines PROTO((void));
extern void process_next_inline PROTO((tree));
-/* skip restore_pending_input */
+extern struct pending_input *save_pending_input PROTO((void));
+extern void restore_pending_input PROTO((struct pending_input *));
extern void yyungetc PROTO((int, int));
extern void reinit_parse_for_method PROTO((int, tree));
-#if 0
-extern void reinit_parse_for_block PROTO((int, struct obstack *, int));
-#endif
+extern void reinit_parse_for_block PROTO((int, struct obstack *));
extern tree cons_up_default_function PROTO((tree, tree, int));
extern void check_for_missing_semicolon PROTO((tree));
extern void note_got_semicolon PROTO((tree));
extern void note_list_got_semicolon PROTO((tree));
-extern int check_newline PROTO((void));
-extern void dont_see_typename PROTO((void));
+extern void do_pending_lang_change PROTO((void));
extern int identifier_type PROTO((tree));
extern void see_typename PROTO((void));
-extern tree do_identifier PROTO((tree));
+extern tree do_identifier PROTO((tree, int, tree));
+extern tree do_scoped_id PROTO((tree, int));
extern tree identifier_typedecl_value PROTO((tree));
extern int real_yylex PROTO((void));
+extern int is_rid PROTO((tree));
extern tree build_lang_decl PROTO((enum tree_code, tree, tree));
extern tree build_lang_field_decl PROTO((enum tree_code, tree, tree));
extern void copy_lang_decl PROTO((tree));
extern tree make_lang_type PROTO((enum tree_code));
-extern void copy_decl_lang_specific PROTO((tree));
extern void dump_time_statistics PROTO((void));
/* extern void compiler_error PROTO((char *, HOST_WIDE_INT, HOST_WIDE_INT)); */
-extern void compiler_error_with_decl PROTO((tree, char *));
extern void yyerror PROTO((char *));
-
-/* in errfn.c */
-extern void cp_error ();
-extern void cp_error_at ();
-extern void cp_warning ();
-extern void cp_warning_at ();
-extern void cp_pedwarn ();
-extern void cp_pedwarn_at ();
-extern void cp_compiler_error ();
-extern void cp_sprintf ();
-
-/* in error.c */
-extern void init_error PROTO((void));
-extern char *fndecl_as_string PROTO((tree, tree, int));
-extern char *type_as_string PROTO((tree, int));
-extern char *args_as_string PROTO((tree, int));
-extern char *decl_as_string PROTO((tree, int));
-extern char *expr_as_string PROTO((tree, int));
-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));
+extern void clear_inline_text_obstack PROTO((void));
+extern void maybe_snarf_defarg PROTO((void));
+extern tree snarf_defarg PROTO((void));
+extern void add_defarg_fn PROTO((tree));
+extern void do_pending_defargs PROTO((void));
+extern int identifier_type PROTO((tree));
+extern void yyhook PROTO((int));
/* in method.c */
extern void init_method PROTO((void));
-extern tree make_anon_parm_name PROTO((void));
-extern void clear_anon_parm_name PROTO((void));
extern void do_inline_function_hair PROTO((tree, tree));
-/* skip report_type_mismatch */
extern char *build_overload_name PROTO((tree, int, int));
extern tree build_static_name PROTO((tree, tree));
-extern tree cplus_exception_name PROTO((tree));
extern tree build_decl_overload PROTO((tree, tree, int));
+extern tree build_template_decl_overload PROTO((tree, tree, tree, tree, tree, int));
extern tree build_typename_overload PROTO((tree));
-extern tree build_t_desc_overload PROTO((tree));
-extern void declare_overloaded PROTO((tree));
-#ifdef NO_AUTO_OVERLOAD
-extern int is_overloaded PROTO((tree));
-#endif
+extern tree build_overload_with_type PROTO((tree, tree));
+extern tree build_destructor_name PROTO((tree));
extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree));
-extern tree hack_identifier PROTO((tree, tree, int));
-extern tree build_component_type_expr PROTO((tree, tree, tree, int));
+extern tree hack_identifier PROTO((tree, tree));
+extern tree make_thunk PROTO((tree, int));
+extern void emit_thunk PROTO((tree));
+extern void synthesize_method PROTO((tree));
+extern tree get_id_2 PROTO((char *, tree));
/* in pt.c */
-extern tree tsubst PROTO ((tree, tree*, int, tree));
+extern tree innermost_args PROTO ((tree, int));
+extern tree tsubst PROTO ((tree, tree, tree));
+extern tree tsubst_expr PROTO ((tree, tree, tree));
+extern tree tsubst_copy PROTO ((tree, tree, tree));
+extern tree tsubst_chain PROTO((tree, tree));
+extern void maybe_begin_member_template_processing PROTO((tree));
+extern void maybe_end_member_template_processing PROTO((tree));
+extern tree finish_member_template_decl PROTO((tree, tree));
extern void begin_template_parm_list PROTO((void));
+extern void begin_specialization PROTO((void));
+extern void reset_specialization PROTO((void));
+extern void end_specialization PROTO((void));
+extern void begin_explicit_instantiation PROTO((void));
+extern void end_explicit_instantiation PROTO((void));
+extern tree determine_specialization PROTO((tree, tree, tree *, int, int));
+extern tree check_explicit_specialization PROTO((tree, tree, int, int));
extern tree process_template_parm PROTO((tree, tree));
extern tree end_template_parm_list PROTO((tree));
-extern void end_template_decl PROTO((tree, tree, tree, int));
-extern tree lookup_template_class PROTO((tree, tree, tree));
-extern void push_template_decls PROTO((tree, tree, int));
-extern void pop_template_decls PROTO((tree, tree, int));
+extern void end_template_decl PROTO((void));
+extern tree current_template_args PROTO((void));
+extern tree push_template_decl PROTO((tree));
+extern tree push_template_decl_real PROTO((tree, int));
+extern void redeclare_class_template PROTO((tree, tree));
+extern tree lookup_template_class PROTO((tree, tree, tree, tree));
+extern tree lookup_template_function PROTO((tree, tree));
extern int uses_template_parms PROTO((tree));
-extern void instantiate_member_templates PROTO((tree));
-extern tree instantiate_class_template PROTO((tree, int));
-extern tree instantiate_template PROTO((tree, tree *));
-extern void undo_template_name_overload PROTO((tree, int));
-extern void overload_template_name PROTO((tree, int));
-extern void end_template_instantiation PROTO((tree));
-extern void reinit_parse_for_template PROTO((int, tree, tree));
-extern int type_unification PROTO((tree, tree *, tree, tree, int *, int));
-extern int do_pending_expansions PROTO((void));
-extern void do_pending_templates PROTO((void));
+extern tree instantiate_class_template PROTO((tree));
+extern tree instantiate_template PROTO((tree, tree));
+extern void overload_template_name PROTO((tree));
+extern int fn_type_unification PROTO((tree, tree, tree, tree, tree, unification_kind_t, tree));
+extern int type_unification PROTO((tree, tree, tree, tree, tree, unification_kind_t, int));
struct tinst_level *tinst_for_decl PROTO((void));
-extern void do_function_instantiation PROTO((tree, tree, tree));
+extern void mark_decl_instantiated PROTO((tree, int));
+extern int more_specialized PROTO((tree, tree, tree));
+extern void mark_class_instantiated PROTO((tree, int));
+extern void do_decl_instantiation PROTO((tree, tree, tree));
extern void do_type_instantiation PROTO((tree, tree));
-extern tree create_nested_upt PROTO((tree, tree));
+extern tree instantiate_decl PROTO((tree));
+extern tree lookup_nested_type_by_name PROTO((tree, tree));
+extern tree do_poplevel PROTO((void));
+extern tree get_bindings PROTO((tree, tree, tree));
+/* CONT ... */
+extern void add_tree PROTO((tree));
+extern void begin_tree PROTO((void));
+extern void end_tree PROTO((void));
+extern void add_maybe_template PROTO((tree, tree));
+extern void pop_tinst_level PROTO((void));
+extern tree most_specialized PROTO((tree, tree, tree));
+extern tree most_specialized_class PROTO((tree, tree, tree));
+extern int more_specialized_class PROTO((tree, tree));
+extern void do_pushlevel PROTO((void));
+extern int is_member_template PROTO((tree));
+extern int comp_template_parms PROTO((tree, tree));
+extern int template_class_depth PROTO((tree));
+extern int is_specialization_of PROTO((tree, tree));
+extern int comp_template_args PROTO((tree, tree));
+
+extern int processing_specialization;
+extern int processing_explicit_instantiation;
+extern int processing_template_parmlist;
+
+/* in repo.c */
+extern void repo_template_used PROTO((tree));
+extern void repo_template_instantiated PROTO((tree, int));
+extern void init_repo PROTO((char*));
+extern void finish_repo PROTO((void));
+
+/* in rtti.c */
+extern void init_rtti_processing PROTO((void));
+extern tree get_tinfo_fn_dynamic PROTO((tree));
+extern tree build_typeid PROTO((tree));
+extern tree build_x_typeid PROTO((tree));
+extern tree get_tinfo_fn PROTO((tree));
+extern tree get_typeid PROTO((tree));
+extern tree build_dynamic_cast PROTO((tree, tree));
+extern void synthesize_tinfo_fn PROTO((tree));
/* in search.c */
-extern tree make_memoized_table_entry PROTO((tree, tree, int));
+extern int types_overlap_p PROTO((tree, tree));
extern void push_memoized_context PROTO((tree, int));
extern void pop_memoized_context PROTO((int));
+extern tree get_vbase PROTO((tree, tree));
extern tree get_binfo PROTO((tree, tree, int));
extern int get_base_distance PROTO((tree, tree, int, tree *));
-extern enum access_type compute_access PROTO((tree, tree));
+extern tree compute_access PROTO((tree, tree));
extern tree lookup_field PROTO((tree, tree, int, int));
extern tree lookup_nested_field PROTO((tree, int));
extern tree lookup_fnfields PROTO((tree, tree, int));
+extern tree lookup_member PROTO((tree, tree, int, int));
extern tree lookup_nested_tag PROTO((tree, tree));
-extern HOST_WIDE_INT breadth_first_search PROTO((tree, int (*)(), int (*)()));
-extern int tree_needs_constructor_p PROTO((tree, int));
-extern int tree_has_any_destructor_p PROTO((tree, int));
extern tree get_matching_virtual PROTO((tree, tree, int));
extern tree get_abstract_virtuals PROTO((tree));
extern tree get_baselinks PROTO((tree, tree, tree));
extern tree next_baselink PROTO((tree));
extern tree init_vbase_pointers PROTO((tree, tree));
-extern void expand_indirect_vtbls_init PROTO((tree, tree, tree, int));
+extern void expand_indirect_vtbls_init PROTO((tree, tree, tree));
extern void clear_search_slots PROTO((tree));
extern tree get_vbase_types PROTO((tree));
extern void build_mi_matrix PROTO((tree));
@@ -2327,7 +2766,7 @@ extern void add_mi_virtuals PROTO((int, tree));
extern void report_ambiguous_mi_virtuals PROTO((int, tree));
extern void note_debug_info_needed PROTO((tree));
extern void push_class_decls PROTO((tree));
-extern void pop_class_decls PROTO((tree));
+extern void pop_class_decls PROTO((void));
extern void unuse_fields PROTO((tree));
extern void unmark_finished_struct PROTO((tree));
extern void print_search_statistics PROTO((void));
@@ -2335,100 +2774,196 @@ extern void init_search_processing PROTO((void));
extern void reinit_search_statistics PROTO((void));
extern tree current_scope PROTO((void));
extern tree lookup_conversions PROTO((tree));
+extern tree get_template_base PROTO((tree, tree));
+
+/* in semantics.c */
+extern void finish_expr_stmt PROTO((tree));
+extern tree begin_if_stmt PROTO((void));
+extern void finish_if_stmt_cond PROTO((tree, tree));
+extern tree finish_then_clause PROTO((tree));
+extern void begin_else_clause PROTO((void));
+extern void finish_else_clause PROTO((tree));
+extern void finish_if_stmt PROTO((void));
+extern tree begin_while_stmt PROTO((void));
+extern void finish_while_stmt_cond PROTO((tree, tree));
+extern void finish_while_stmt PROTO((tree));
+extern tree begin_do_stmt PROTO((void));
+extern void finish_do_body PROTO((tree));
+extern void finish_do_stmt PROTO((tree, tree));
+extern void finish_return_stmt PROTO((tree));
+extern tree begin_for_stmt PROTO((void));
+extern void finish_for_init_stmt PROTO((tree));
+extern void finish_for_cond PROTO((tree, tree));
+extern void finish_for_expr PROTO((tree, tree));
+extern void finish_for_stmt PROTO((tree, tree));
+extern void finish_break_stmt PROTO((void));
+extern void finish_continue_stmt PROTO((void));
+extern void begin_switch_stmt PROTO((void));
+extern tree finish_switch_cond PROTO((tree));
+extern void finish_switch_stmt PROTO((tree, tree));
+extern void finish_case_label PROTO((tree, tree));
+extern void finish_goto_stmt PROTO((tree));
+extern tree begin_try_block PROTO((void));
+extern void finish_try_block PROTO((tree));
+extern void finish_handler_sequence PROTO((tree));
+extern tree begin_handler PROTO((void));
+extern void finish_handler_parms PROTO((tree));
+extern void finish_handler PROTO((tree));
+extern tree begin_compound_stmt PROTO((int));
+extern tree finish_compound_stmt PROTO((int, tree));
+extern void finish_asm_stmt PROTO((tree, tree, tree, tree, tree));
+extern tree finish_parenthesized_expr PROTO((tree));
+extern tree begin_stmt_expr PROTO((void));
+extern tree finish_stmt_expr PROTO((tree, tree));
+extern tree finish_call_expr PROTO((tree, tree, int));
+extern tree finish_increment_expr PROTO((tree, enum tree_code));
+extern tree finish_this_expr PROTO((void));
+extern tree finish_object_call_expr PROTO((tree, tree, tree));
+extern tree finish_qualified_object_call_expr PROTO((tree, tree, tree));
+extern tree finish_pseudo_destructor_call_expr PROTO((tree, tree, tree));
+extern tree finish_globally_qualified_member_call_expr PROTO ((tree, tree));
+extern tree finish_label_address_expr PROTO((tree));
+extern tree finish_unary_op_expr PROTO((enum tree_code, tree));
+extern tree finish_id_expr PROTO((tree));
+extern int begin_new_placement PROTO((void));
+extern tree finish_new_placement PROTO((tree, int));
+extern int begin_function_definition PROTO((tree, tree));
+extern tree begin_constructor_declarator PROTO((tree, tree));
+extern tree finish_declarator PROTO((tree, tree, tree, tree, int));
+extern void finish_translation_unit PROTO((void));
+extern tree finish_template_type_parm PROTO((tree, tree));
+extern tree finish_template_template_parm PROTO((tree, tree));
+extern tree finish_parmlist PROTO((tree, int));
+extern tree begin_class_definition PROTO((tree));
+extern tree finish_class_definition PROTO((tree, tree, tree, int));
+extern void finish_default_args PROTO((void));
+extern void begin_inline_definitions PROTO((void));
+extern tree finish_member_class_template PROTO((tree, tree));
/* in sig.c */
extern tree build_signature_pointer_type PROTO((tree, int, int));
extern tree build_signature_reference_type PROTO((tree, int, int));
extern tree build_signature_pointer_constructor PROTO((tree, tree));
-extern tree build_signature_method_call PROTO((tree, tree, tree, tree));
+extern tree build_signature_method_call PROTO((tree, tree));
extern tree build_optr_ref PROTO((tree));
-extern tree build_sptr_ref PROTO((tree));
+extern void append_signature_fields PROTO((tree));
/* in spew.c */
extern void init_spew PROTO((void));
+extern int peekyylex PROTO((void));
extern int yylex PROTO((void));
extern tree arbitrate_lookup PROTO((tree, tree, tree));
/* in tree.c */
+extern int member_p PROTO((tree));
+extern int real_lvalue_p PROTO((tree));
+extern tree build_min PVPROTO((enum tree_code, tree, ...));
+extern tree build_min_nt PVPROTO((enum tree_code, ...));
+extern tree min_tree_cons PROTO((tree, tree, tree));
extern int lvalue_p PROTO((tree));
extern int lvalue_or_else PROTO((tree, char *));
-extern tree build_cplus_new PROTO((tree, tree, int));
+extern tree build_cplus_new PROTO((tree, tree));
+extern tree get_target_expr PROTO((tree));
extern tree break_out_cleanups PROTO((tree));
extern tree break_out_calls PROTO((tree));
extern tree build_cplus_method_type PROTO((tree, tree, tree));
extern tree build_cplus_staticfn_type PROTO((tree, tree, tree));
extern tree build_cplus_array_type PROTO((tree, tree));
-extern void propagate_binfo_offsets PROTO((tree, tree));
-extern int layout_vbasetypes PROTO((tree, int));
-extern tree layout_basetypes PROTO((tree, tree));
-extern int list_hash PROTO((tree));
-extern tree list_hash_lookup PROTO((int, tree));
-extern void list_hash_add PROTO((int, tree));
-extern tree list_hash_canon PROTO((int, tree));
+extern int layout_basetypes PROTO((tree, int));
+extern tree build_vbase_pointer_fields PROTO((tree));
+extern tree build_base_fields PROTO((tree));
extern tree hash_tree_cons PROTO((int, int, int, tree, tree, tree));
extern tree hash_tree_chain PROTO((tree, tree));
extern tree hash_chainon PROTO((tree, tree));
extern tree get_decl_list PROTO((tree));
-extern tree list_hash_lookup_or_cons PROTO((tree));
extern tree make_binfo PROTO((tree, tree, tree, tree, tree));
extern tree binfo_value PROTO((tree, tree));
extern tree reverse_path PROTO((tree));
-extern tree virtual_member PROTO((tree, tree));
-extern void debug_binfo PROTO((tree));
-extern int decl_list_length PROTO((tree));
extern int count_functions PROTO((tree));
-extern tree decl_value_member PROTO((tree, tree));
extern int is_overloaded_fn PROTO((tree));
extern tree get_first_fn PROTO((tree));
+extern tree binding_init PROTO((struct tree_binding*));
+extern tree ovl_cons PROTO((tree, tree));
+extern tree scratch_ovl_cons PROTO((tree, tree));
+extern int ovl_member PROTO((tree, tree));
+extern tree build_overload PROTO((tree, tree));
extern tree fnaddr_from_vtable_entry PROTO((tree));
-extern void set_fnaddr_from_vtable_entry PROTO((tree, tree));
extern tree function_arg_chain PROTO((tree));
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 char *lang_printable_name PROTO((tree, int));
extern tree build_exception_variant PROTO((tree, tree));
+extern tree copy_template_template_parm PROTO((tree));
extern tree copy_to_permanent PROTO((tree));
extern void print_lang_statistics PROTO((void));
-/* skip __eprintf */
+extern void __eprintf
+ PROTO((const char *, const char *, unsigned, const char *));
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));
+extern tree get_type_decl PROTO((tree));
+extern tree vec_binfo_member PROTO((tree, tree));
+extern tree hack_decl_function_context PROTO((tree));
+extern tree lvalue_type PROTO((tree));
+extern tree error_type PROTO((tree));
+extern tree make_temp_vec PROTO((int));
+extern tree build_ptr_wrapper PROTO((void *));
+extern tree build_expr_ptr_wrapper PROTO((void *));
+extern tree build_int_wrapper PROTO((int));
+extern tree build_srcloc PROTO((char *, int));
+extern tree build_srcloc_here PROTO((void));
+extern int varargs_function_p PROTO((tree));
+extern int really_overloaded_fn PROTO((tree));
+extern int cp_tree_equal PROTO((tree, tree));
+extern int can_free PROTO((struct obstack *, tree));
+extern tree mapcar PROTO((tree, tree (*) (tree)));
+extern void debug_binfo PROTO((tree));
+extern void push_expression_obstack PROTO((void));
+#define scratchalloc expralloc
+#define scratch_tree_cons expr_tree_cons
+#define build_scratch_list build_expr_list
+#define make_scratch_vec make_temp_vec
+#define push_scratch_obstack push_expression_obstack
/* in typeck.c */
extern tree condition_conversion PROTO((tree));
extern tree target_type PROTO((tree));
extern tree require_complete_type PROTO((tree));
+extern tree complete_type PROTO((tree));
+extern tree complete_type_or_else PROTO((tree));
extern int type_unknown_p PROTO((tree));
extern int fntype_p PROTO((tree));
extern tree require_instantiated_type PROTO((tree, tree, tree));
extern tree commonparms PROTO((tree, tree));
+extern tree original_type PROTO((tree));
extern tree common_type PROTO((tree, tree));
-extern int compexcepttypes PROTO((tree, tree, int));
+extern int compexcepttypes PROTO((tree, tree));
extern int comptypes PROTO((tree, tree, int));
extern int comp_target_types PROTO((tree, tree, int));
-extern tree common_base_types PROTO((tree, tree));
extern int compparms PROTO((tree, tree, int));
extern int comp_target_types PROTO((tree, tree, int));
+extern int comp_cv_qualification PROTO((tree, tree));
+extern int comp_cv_qual_signature PROTO((tree, tree));
extern int self_promoting_args_p PROTO((tree));
extern tree unsigned_type PROTO((tree));
extern tree signed_type PROTO((tree));
extern tree signed_or_unsigned_type PROTO((int, tree));
+extern tree expr_sizeof PROTO((tree));
extern tree c_sizeof PROTO((tree));
extern tree c_sizeof_nowarn PROTO((tree));
extern tree c_alignof PROTO((tree));
+extern tree inline_conversion 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));
extern tree build_component_ref PROTO((tree, tree, tree, int));
+extern tree build_x_component_ref PROTO((tree, tree, tree, int));
extern tree build_x_indirect_ref PROTO((tree, char *));
extern tree build_indirect_ref PROTO((tree, char *));
-extern tree build_x_array_ref PROTO((tree, tree));
extern tree build_array_ref PROTO((tree, tree));
extern tree build_x_function_call PROTO((tree, tree, tree));
+extern tree get_member_function_from_ptrfunc PROTO((tree *, tree));
extern tree build_function_call_real PROTO((tree, tree, int, int));
extern tree build_function_call PROTO((tree, tree));
extern tree build_function_call_maybe PROTO((tree, tree));
@@ -2448,7 +2983,8 @@ extern tree build_compound_expr PROTO((tree));
extern tree build_static_cast PROTO((tree, tree));
extern tree build_reinterpret_cast PROTO((tree, tree));
extern tree build_const_cast PROTO((tree, tree));
-extern tree build_c_cast PROTO((tree, tree, int));
+extern tree build_c_cast PROTO((tree, tree));
+extern tree build_x_modify_expr PROTO((tree, enum tree_code, tree));
extern tree build_modify_expr PROTO((tree, enum tree_code, tree));
extern int language_lvalue_valid PROTO((tree));
extern void warn_for_assignment PROTO((char *, char *, char *, tree, int, int));
@@ -2456,15 +2992,16 @@ extern tree convert_for_initialization PROTO((tree, tree, tree, int, char *, tr
extern void c_expand_asm_operands PROTO((tree, tree, tree, tree, int, char *, int));
extern void c_expand_return PROTO((tree));
extern tree c_expand_start_case PROTO((tree));
-extern tree build_component_ref PROTO((tree, tree, tree, int));
+extern int comp_ptr_ttypes PROTO((tree, tree));
+extern int ptr_reasonably_similar PROTO((tree, tree));
extern tree build_ptrmemfunc PROTO((tree, tree, int));
/* in typeck2.c */
extern tree error_not_base_type PROTO((tree, tree));
extern tree binfo_or_else PROTO((tree, tree));
-extern void error_with_aggr_type (); /* PROTO((tree, char *, HOST_WIDE_INT)); */
extern void readonly_error PROTO((tree, char *, int));
extern void abstract_virtuals_error PROTO((tree, tree));
+extern void signature_error PROTO((tree, tree));
extern void incomplete_type_error PROTO((tree, tree));
extern void my_friendly_abort PROTO((int));
extern void my_friendly_assert PROTO((int, int));
@@ -2476,19 +3013,21 @@ extern tree build_m_component_ref PROTO((tree, tree));
extern tree build_functional_cast PROTO((tree, tree));
extern char *enum_name_string PROTO((tree, tree));
extern void report_case_error PROTO((int, tree, tree, tree));
+extern void check_for_new_type PROTO((char *,flagged_type_tree));
+extern tree initializer_constant_valid_p PROTO((tree, tree));
/* in xref.c */
extern void GNU_xref_begin PROTO((char *));
extern void GNU_xref_end PROTO((int));
extern void GNU_xref_file PROTO((char *));
extern void GNU_xref_start_scope PROTO((HOST_WIDE_INT));
-extern void GNU_xref_end_scope PROTO((HOST_WIDE_INT, HOST_WIDE_INT, int, int, int));
+extern void GNU_xref_end_scope PROTO((HOST_WIDE_INT, HOST_WIDE_INT, int, int));
extern void GNU_xref_ref PROTO((tree, char *));
extern void GNU_xref_decl PROTO((tree, tree));
extern void GNU_xref_call PROTO((tree, char *));
extern void GNU_xref_function PROTO((tree, tree));
extern void GNU_xref_assign PROTO((tree));
-extern void GNU_xref_hier PROTO((char *, char *, int, int, int));
+extern void GNU_xref_hier PROTO((tree, tree, int, int, int));
extern void GNU_xref_member PROTO((tree, tree));
/* -- end of C++ */
diff --git a/contrib/gcc/cp/cvt.c b/contrib/gcc/cp/cvt.c
index 56508c1..18b7d8b 100644
--- a/contrib/gcc/cp/cvt.c
+++ b/contrib/gcc/cp/cvt.c
@@ -1,5 +1,5 @@
/* Language-level data type conversion for GNU C++.
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-96, 1998 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -26,14 +26,17 @@ Boston, MA 02111-1307, USA. */
but what kind of conversions it does will depend on the language. */
#include "config.h"
+#include "system.h"
#include "tree.h"
#include "flags.h"
#include "cp-tree.h"
-#include "class.h"
#include "convert.h"
-#undef NULL
-#define NULL (char *)0
+extern tree static_aggregates;
+
+static tree cp_convert_to_pointer PROTO((tree, tree));
+static tree convert_to_pointer_force PROTO((tree, tree));
+static tree build_up_reference PROTO((tree, tree, int, int));
/* Change of width--truncation and extension of integers or reals--
is represented with NOP_EXPR. Proper functioning of many things
@@ -57,71 +60,87 @@ Boston, MA 02111-1307, USA. */
/* Subroutines of `convert'. */
-/* Build a thunk. What it is, is an entry point that when called will
- adjust the this pointer (the first argument) by offset, and then
- goto the real address of the function given by REAL_ADDR that we
- would like called. What we return is the address of the thunk. */
-static tree
-build_thunk (offset, real_addr)
- tree offset, real_addr;
-{
- if (TREE_CODE (real_addr) != ADDR_EXPR
- || TREE_CODE (TREE_OPERAND (real_addr, 0)) != FUNCTION_DECL)
- {
- sorry ("MI pointer to member conversion too complex");
- return error_mark_node;
- }
- sorry ("MI pointer to member conversion too complex");
- return error_mark_node;
-}
-
-/* Convert a `pointer to member' (POINTER_TYPE to METHOD_TYPE) into
- another `pointer to method'. This may involved the creation of
- a thunk to handle the this offset calculation. */
-static tree
-convert_fn_ptr (type, expr)
- tree type, expr;
-{
- if (flag_vtable_thunks)
- {
- tree intype = TREE_TYPE (expr);
- tree binfo = get_binfo (TYPE_METHOD_BASETYPE (TREE_TYPE (intype)),
- TYPE_METHOD_BASETYPE (TREE_TYPE (type)), 1);
- if (binfo == error_mark_node)
- {
- error (" in pointer to member conversion");
- return error_mark_node;
- }
- if (binfo == NULL_TREE)
- {
- /* ARM 4.8 restriction. */
- error ("invalid pointer to member conversion");
- return error_mark_node;
- }
-
- if (BINFO_OFFSET_ZEROP (binfo))
- return build1 (NOP_EXPR, type, expr);
- return build1 (NOP_EXPR, type, build_thunk (BINFO_OFFSET (binfo), expr));
- }
- else
- return build_ptrmemfunc (type, expr, 1);
-}
-
/* if converting pointer to pointer
if dealing with classes, check for derived->base or vice versa
else if dealing with method pointers, delegate
else convert blindly
else if converting class, pass off to build_type_conversion
else try C-style pointer conversion */
+
static tree
cp_convert_to_pointer (type, expr)
tree type, expr;
{
register tree intype = TREE_TYPE (expr);
register enum tree_code form;
+ tree rval;
+
+ if (IS_AGGR_TYPE (intype))
+ {
+ intype = complete_type (intype);
+ if (TYPE_SIZE (intype) == NULL_TREE)
+ {
+ cp_error ("can't convert from incomplete type `%T' to `%T'",
+ intype, type);
+ return error_mark_node;
+ }
+
+ rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);
+ if (rval)
+ {
+ if (rval == error_mark_node)
+ cp_error ("conversion of `%E' from `%T' to `%T' is ambiguous",
+ expr, intype, type);
+ return rval;
+ }
+ }
if (TYPE_PTRMEMFUNC_P (type))
type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+
+ /* Handle anachronistic conversions from (::*)() to cv void* or (*)(). */
+ if (TREE_CODE (type) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+ || TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node))
+ {
+ /* Allow an implicit this pointer for pointer to member
+ functions. */
+ if (TYPE_PTRMEMFUNC_P (intype))
+ {
+ tree decl, basebinfo;
+ tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
+ tree t = TYPE_METHOD_BASETYPE (fntype);
+
+ if (current_class_type == 0
+ || get_base_distance (t, current_class_type, 0, &basebinfo)
+ == -1)
+ {
+ decl = build1 (NOP_EXPR, t, error_mark_node);
+ }
+ else if (current_class_ptr == 0)
+ decl = build1 (NOP_EXPR, t, error_mark_node);
+ else
+ decl = current_class_ref;
+
+ expr = build (OFFSET_REF, fntype, decl, expr);
+ }
+
+ if (TREE_CODE (expr) == OFFSET_REF
+ && TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
+ expr = resolve_offset_ref (expr);
+ if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
+ expr = build_addr_func (expr);
+ if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
+ {
+ if (TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == METHOD_TYPE)
+ if (pedantic || warn_pmf2ptr)
+ cp_pedwarn ("converting from `%T' to `%T'", TREE_TYPE (expr),
+ type);
+ return build1 (NOP_EXPR, type, expr);
+ }
+ intype = TREE_TYPE (expr);
+ }
+
if (TYPE_PTRMEMFUNC_P (intype))
intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
@@ -133,6 +152,8 @@ cp_convert_to_pointer (type, expr)
if (TYPE_MAIN_VARIANT (type) != intype
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
+ && IS_AGGR_TYPE (TREE_TYPE (type))
+ && IS_AGGR_TYPE (TREE_TYPE (intype))
&& TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
{
enum tree_code code = PLUS_EXPR;
@@ -156,9 +177,11 @@ cp_convert_to_pointer (type, expr)
tree path;
if (code == PLUS_EXPR)
- get_base_distance (TREE_TYPE (type), TREE_TYPE (intype), 0, &path);
+ get_base_distance (TREE_TYPE (type), TREE_TYPE (intype),
+ 0, &path);
else
- get_base_distance (TREE_TYPE (intype), TREE_TYPE (type), 0, &path);
+ get_base_distance (TREE_TYPE (intype), TREE_TYPE (type),
+ 0, &path);
return build_vbase_path (code, type, expr, path, 0);
}
}
@@ -166,18 +189,26 @@ cp_convert_to_pointer (type, expr)
if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
- return convert_fn_ptr (type, expr);
+ return build_ptrmemfunc (type, expr, 1);
if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
&& TREE_CODE (TREE_TYPE (intype)) == OFFSET_TYPE)
{
tree b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
tree b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype));
- tree binfo = get_binfo (b1, b2, 1);
+ tree binfo = get_binfo (b2, b1, 1);
+ enum tree_code code = PLUS_EXPR;
+
if (binfo == NULL_TREE)
- binfo = get_binfo (b2, b1, 1);
+ {
+ binfo = get_binfo (b1, b2, 1);
+ code = MINUS_EXPR;
+ }
+
if (binfo == error_mark_node)
return error_mark_node;
+ if (binfo && ! TREE_VIA_VIRTUAL (binfo))
+ expr = size_binop (code, expr, BINFO_OFFSET (binfo));
}
if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
@@ -189,7 +220,9 @@ cp_convert_to_pointer (type, expr)
return error_mark_node;
}
- return build1 (NOP_EXPR, type, expr);
+ rval = build1 (NOP_EXPR, type, expr);
+ TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
+ return rval;
}
my_friendly_assert (form != OFFSET_TYPE, 186);
@@ -198,23 +231,10 @@ cp_convert_to_pointer (type, expr)
&& (IS_SIGNATURE_POINTER (intype) || IS_SIGNATURE_REFERENCE (intype)))
return convert_to_pointer (type, build_optr_ref (expr));
- if (IS_AGGR_TYPE (intype))
- {
- tree rval;
- rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);
- if (rval)
- {
- if (rval == error_mark_node)
- cp_error ("conversion of `%E' from `%T' to `%T' is ambiguous",
- expr, intype, type);
- return rval;
- }
- }
-
if (integer_zerop (expr))
{
- if (type == TREE_TYPE (null_pointer_node))
- return null_pointer_node;
+ if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
+ return build_ptrmemfunc (type, expr, 0);
expr = build_int_2 (0, 0);
TREE_TYPE (expr) = type;
return expr;
@@ -222,9 +242,9 @@ cp_convert_to_pointer (type, expr)
if (INTEGRAL_CODE_P (form))
{
- if (type_precision (intype) == POINTER_SIZE)
+ if (TYPE_PRECISION (intype) == POINTER_SIZE)
return build1 (CONVERT_EXPR, type, expr);
- expr = convert (type_for_size (POINTER_SIZE, 0), expr);
+ expr = cp_convert (type_for_size (POINTER_SIZE, 0), expr);
/* Modes may be different but sizes should be the same. */
if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
!= GET_MODE_SIZE (TYPE_MODE (type)))
@@ -242,6 +262,7 @@ cp_convert_to_pointer (type, expr)
/* Like convert, except permit conversions to take place which
are not normally allowed due to access restrictions
(such as conversion from sub-type to private super-type). */
+
static tree
convert_to_pointer_force (type, expr)
tree type, expr;
@@ -251,8 +272,6 @@ convert_to_pointer_force (type, expr)
if (integer_zerop (expr))
{
- if (type == TREE_TYPE (null_pointer_node))
- return null_pointer_node;
expr = build_int_2 (0, 0);
TREE_TYPE (expr) = type;
return expr;
@@ -273,6 +292,8 @@ convert_to_pointer_force (type, expr)
if (TYPE_MAIN_VARIANT (type) != intype
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
+ && IS_AGGR_TYPE (TREE_TYPE (type))
+ && IS_AGGR_TYPE (TREE_TYPE (intype))
&& TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
{
enum tree_code code = PLUS_EXPR;
@@ -282,8 +303,9 @@ convert_to_pointer_force (type, expr)
if (distance == -2)
{
ambig:
- cp_error ("type `%T' is ambiguous baseclass of `%s'", TREE_TYPE (type),
- TYPE_NAME_STRING (TREE_TYPE (intype)));
+ cp_error ("type `%T' is ambiguous baseclass of `%s'",
+ TREE_TYPE (type),
+ TYPE_NAME_STRING (TREE_TYPE (intype)));
return error_mark_node;
}
if (distance == -1)
@@ -300,7 +322,6 @@ convert_to_pointer_force (type, expr)
}
return build_vbase_path (code, type, expr, path, 0);
}
- return build1 (NOP_EXPR, type, expr);
}
return cp_convert_to_pointer (type, expr);
@@ -311,343 +332,61 @@ convert_to_pointer_force (type, expr)
value we have to begin with is in ARG.
FLAGS controls how we manage access checking.
- CHECKCONST controls if we report error messages on const subversion. */
+ DIRECT_BIND in FLAGS controls how any temporaries are generated. */
+
static tree
build_up_reference (type, arg, flags, checkconst)
tree type, arg;
int flags, checkconst;
{
- tree rval, targ;
- int literal_flag = 0;
+ tree rval;
tree argtype = TREE_TYPE (arg);
tree target_type = TREE_TYPE (type);
- tree binfo = NULL_TREE;
my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);
+
+ if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg))
+ {
+ tree targ = arg;
+ if (toplevel_bindings_p ())
+ arg = get_temp_name (argtype, 1);
+ else
+ {
+ arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));
+ DECL_ARTIFICIAL (arg) = 1;
+ }
+ DECL_INITIAL (arg) = targ;
+ cp_finish_decl (arg, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
+ }
+ else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
+ {
+ tree slot = build_decl (VAR_DECL, NULL_TREE, argtype);
+ arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE);
+ TREE_SIDE_EFFECTS (arg) = 1;
+ }
+
+ /* If we had a way to wrap this up, and say, if we ever needed it's
+ address, transform all occurrences of the register, into a memory
+ reference we could win better. */
+ rval = build_unary_op (ADDR_EXPR, arg, 1);
if ((flags & LOOKUP_PROTECT)
&& TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
&& IS_AGGR_TYPE (argtype)
&& IS_AGGR_TYPE (target_type))
{
- binfo = get_binfo (target_type, argtype, 1);
+ /* We go through get_binfo for the access control. */
+ tree binfo = get_binfo (target_type, argtype, 1);
if (binfo == error_mark_node)
return error_mark_node;
if (binfo == NULL_TREE)
return error_not_base_type (target_type, argtype);
- }
-
- /* Pass along const and volatile down into the type. */
- if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
- target_type = cp_build_type_variant (target_type, TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- targ = arg;
- if (TREE_CODE (targ) == SAVE_EXPR)
- targ = TREE_OPERAND (targ, 0);
- while (TREE_CODE (targ) == NOP_EXPR
- && (TYPE_MAIN_VARIANT (argtype)
- == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (targ, 0)))))
- targ = TREE_OPERAND (targ, 0);
-
- switch (TREE_CODE (targ))
- {
- case INDIRECT_REF:
- /* This is a call to a constructor which did not know what it was
- initializing until now: it needs to initialize a temporary. */
- if (TREE_HAS_CONSTRUCTOR (targ))
- {
- tree temp = build_cplus_new (argtype, TREE_OPERAND (targ, 0), 1);
- TREE_HAS_CONSTRUCTOR (targ) = 0;
- return build_up_reference (type, temp, flags, 1);
- }
- /* Let &* cancel out to simplify resulting code.
- Also, throw away intervening NOP_EXPRs. */
- arg = TREE_OPERAND (targ, 0);
- if (TREE_CODE (arg) == NOP_EXPR || TREE_CODE (arg) == NON_LVALUE_EXPR
- || (TREE_CODE (arg) == CONVERT_EXPR && TREE_REFERENCE_EXPR (arg)))
- arg = TREE_OPERAND (arg, 0);
-
- /* in doing a &*, we have to get rid of the const'ness on the pointer
- value. Haven't thought about volatile here. Pointers come to mind
- here. */
- if (TREE_READONLY (arg))
- {
- arg = copy_node (arg);
- TREE_READONLY (arg) = 0;
- }
-
- rval = build1 (CONVERT_EXPR, type, arg);
- TREE_REFERENCE_EXPR (rval) = 1;
-
- /* propagate the const flag on something like:
-
- class Base {
- public:
- int foo;
- };
-
- class Derived : public Base {
- public:
- int bar;
- };
-
- void func(Base&);
-
- void func2(const Derived& d) {
- func(d);
- }
-
- on the d parameter. The below could have been avoided, if the flags
- were down in the tree, not sure why they are not. (mrs) */
- /* The below code may have to be propagated to other parts of this
- switch. */
- if (TREE_READONLY (targ) && !TREE_READONLY (arg)
- && (TREE_CODE (arg) == PARM_DECL || TREE_CODE (arg) == VAR_DECL)
- && TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE
- && (TYPE_READONLY (target_type) && checkconst))
- {
- arg = copy_node (arg);
- TREE_READONLY (arg) = TREE_READONLY (targ);
- }
- literal_flag = TREE_CONSTANT (arg);
-
- goto done;
-
- /* Get this out of a register if we happened to be in one by accident.
- Also, build up references to non-lvalues it we must. */
- /* For &x[y], return (&) x+y */
- case ARRAY_REF:
- if (mark_addressable (TREE_OPERAND (targ, 0)) == 0)
- return error_mark_node;
- rval = build_binary_op (PLUS_EXPR, TREE_OPERAND (targ, 0),
- TREE_OPERAND (targ, 1), 1);
- TREE_TYPE (rval) = type;
- if (TREE_CONSTANT (TREE_OPERAND (targ, 1))
- && staticp (TREE_OPERAND (targ, 0)))
- TREE_CONSTANT (rval) = 1;
- goto done;
-
- case SCOPE_REF:
- /* Could be a reference to a static member. */
- {
- tree field = TREE_OPERAND (targ, 1);
- if (TREE_STATIC (field))
- {
- rval = build1 (ADDR_EXPR, type, field);
- literal_flag = 1;
- goto done;
- }
- }
-
- /* We should have farmed out member pointers above. */
- my_friendly_abort (188);
-
- case COMPONENT_REF:
- rval = build_component_addr (targ, build_pointer_type (argtype),
- "attempt to make a reference to bit-field structure member `%s'");
- TREE_TYPE (rval) = type;
- literal_flag = staticp (TREE_OPERAND (targ, 0));
-
- goto done;
-
- /* Anything not already handled and not a true memory reference
- needs to have a reference built up. Do so silently for
- things like integers and return values from function,
- but complain if we need a reference to something declared
- as `register'. */
-
- case RESULT_DECL:
- if (staticp (targ))
- literal_flag = 1;
- TREE_ADDRESSABLE (targ) = 1;
- put_var_into_stack (targ);
- break;
-
- case PARM_DECL:
-#if 0
- if (targ == current_class_decl)
- {
- error ("address of `this' not available");
-/* #if 0 */
- /* This code makes the following core dump the compiler on a sun4,
- if the code below is used.
-
- class e_decl;
- class a_decl;
- typedef a_decl* a_ref;
-
- class a_s {
- public:
- a_s();
- void* append(a_ref& item);
- };
- class a_decl {
- public:
- a_decl (e_decl *parent);
- a_s generic_s;
- a_s decls;
- e_decl* parent;
- };
-
- class e_decl {
- public:
- e_decl();
- a_s implementations;
- };
-
- void foobar(void *);
-
- a_decl::a_decl(e_decl *parent) {
- parent->implementations.append(this);
- }
- */
-
- TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */
- put_var_into_stack (targ);
- break;
-/* #else */
- return error_mark_node;
-/* #endif */
- }
-#endif
- /* Fall through. */
- case VAR_DECL:
- case CONST_DECL:
- if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ)
- && !DECL_ARTIFICIAL (targ))
- cp_warning ("address needed to build reference for `%D', which is declared `register'",
- targ);
- else if (staticp (targ))
- literal_flag = 1;
-
- TREE_ADDRESSABLE (targ) = 1;
- put_var_into_stack (targ);
- break;
-
- case COMPOUND_EXPR:
- {
- tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 1),
- LOOKUP_PROTECT, checkconst);
- rval = build (COMPOUND_EXPR, type, TREE_OPERAND (targ, 0), real_reference);
- TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 1));
- return rval;
- }
-
- case PREINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case MODIFY_EXPR:
- case INIT_EXPR:
- {
- tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 0),
- LOOKUP_PROTECT, checkconst);
- rval = build (COMPOUND_EXPR, type, arg, real_reference);
- TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 0));
- return rval;
- }
-
- case COND_EXPR:
- return build (COND_EXPR, type,
- TREE_OPERAND (targ, 0),
- build_up_reference (type, TREE_OPERAND (targ, 1),
- LOOKUP_PROTECT, checkconst),
- build_up_reference (type, TREE_OPERAND (targ, 2),
- LOOKUP_PROTECT, checkconst));
-
- /* Undo the folding... */
- case MIN_EXPR:
- case MAX_EXPR:
- return build (COND_EXPR, type,
- build (TREE_CODE (targ) == MIN_EXPR ? LT_EXPR : GT_EXPR,
- boolean_type_node, TREE_OPERAND (targ, 0),
- TREE_OPERAND (targ, 1)),
- build_up_reference (type, TREE_OPERAND (targ, 0),
- LOOKUP_PROTECT, checkconst),
- build_up_reference (type, TREE_OPERAND (targ, 1),
- LOOKUP_PROTECT, checkconst));
-
- case WITH_CLEANUP_EXPR:
- return build (WITH_CLEANUP_EXPR, type,
- build_up_reference (type, TREE_OPERAND (targ, 0),
- LOOKUP_PROTECT, checkconst),
- 0, TREE_OPERAND (targ, 2));
-
- case BIND_EXPR:
- arg = TREE_OPERAND (targ, 1);
- if (arg == NULL_TREE)
- {
- compiler_error ("({ ... }) expression not expanded when needed for reference");
- return error_mark_node;
- }
- rval = build1 (ADDR_EXPR, type, arg);
- TREE_REFERENCE_EXPR (rval) = 1;
- return rval;
-
- default:
- break;
- }
-
- if (TREE_ADDRESSABLE (targ) == 0)
- {
- tree temp;
-
- if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype))
- {
- temp = build_cplus_new (argtype, targ, 1);
- if (TREE_CODE (temp) == WITH_CLEANUP_EXPR)
- rval = build (WITH_CLEANUP_EXPR, type,
- build1 (ADDR_EXPR, type, TREE_OPERAND (temp, 0)),
- 0, TREE_OPERAND (temp, 2));
- else
- rval = build1 (ADDR_EXPR, type, temp);
- goto done;
- }
- else
- {
- temp = get_temp_name (argtype, 0);
- if (toplevel_bindings_p ())
- {
- /* Give this new temp some rtl and initialize it. */
- DECL_INITIAL (temp) = targ;
- TREE_STATIC (temp) = 1;
- cp_finish_decl (temp, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
- /* Do this after declaring it static. */
- rval = build_unary_op (ADDR_EXPR, temp, 0);
- TREE_TYPE (rval) = type;
- literal_flag = TREE_CONSTANT (rval);
- goto done;
- }
- else
- {
- rval = build_unary_op (ADDR_EXPR, temp, 0);
- if (binfo && !BINFO_OFFSET_ZEROP (binfo))
- rval = convert_pointer_to (target_type, rval);
- else
- TREE_TYPE (rval) = type;
-
- temp = build (MODIFY_EXPR, argtype, temp, arg);
- TREE_SIDE_EFFECTS (temp) = 1;
- return build (COMPOUND_EXPR, type, temp, rval);
- }
- }
+ rval = convert_pointer_to_real (binfo, rval);
}
else
- rval = build1 (ADDR_EXPR, type, arg);
-
- done:
- if (TYPE_USES_COMPLEX_INHERITANCE (argtype)
- || TYPE_USES_COMPLEX_INHERITANCE (target_type))
- {
- TREE_TYPE (rval) = build_pointer_type (argtype);
- if (flags & LOOKUP_PROTECT)
- rval = convert_pointer_to (target_type, rval);
- else
- rval
- = convert_to_pointer_force (build_pointer_type (target_type), rval);
- TREE_TYPE (rval) = type;
- if (TREE_CODE (rval) == PLUS_EXPR || TREE_CODE (rval) == MINUS_EXPR)
- TREE_TYPE (TREE_OPERAND (rval, 0))
- = TREE_TYPE (TREE_OPERAND (rval, 1)) = type;
- }
- TREE_CONSTANT (rval) = literal_flag;
+ rval
+ = convert_to_pointer_force (build_pointer_type (target_type), rval);
+ rval = build1 (NOP_EXPR, type, rval);
+ TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
return rval;
}
@@ -682,7 +421,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
{
/* Look for a user-defined conversion to lvalue that we can use. */
- rval_as_conversion = build_type_conversion (CONVERT_EXPR, type, expr, 1);
+ rval_as_conversion
+ = build_type_conversion (CONVERT_EXPR, reftype, expr, 1);
if (rval_as_conversion && rval_as_conversion != error_mark_node
&& real_lvalue_p (rval_as_conversion))
@@ -708,15 +448,14 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
ttr = cp_build_type_variant (TREE_TYPE (expr), r, v);
}
- if (! real_lvalue_p (expr) &&
- (decl == NULL_TREE || ! TYPE_READONLY (ttl)))
+ if (! real_lvalue_p (expr) && ! TYPE_READONLY (ttl))
{
if (decl)
/* Ensure semantics of [dcl.init.ref] */
- cp_pedwarn ("initialization of non-const `%T' from rvalue `%T'",
+ cp_pedwarn ("initialization of non-const reference `%#T' from rvalue `%T'",
reftype, intype);
else
- cp_pedwarn ("conversion to `%T' from rvalue `%T'",
+ cp_pedwarn ("conversion to non-const `%T' from rvalue `%T'",
reftype, intype);
}
else if (! (convtype & CONV_CONST))
@@ -749,89 +488,18 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
rval = build_unary_op (ADDR_EXPR, expr, 0);
if (rval != error_mark_node)
- rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval, 0);
+ rval = convert_force (build_pointer_type (TREE_TYPE (reftype)),
+ rval, 0);
if (rval != error_mark_node)
rval = build1 (NOP_EXPR, reftype, rval);
}
- else if (decl)
+ else
{
- tree rval_as_ctor = NULL_TREE;
-
- if (rval_as_conversion)
- {
- if (rval_as_conversion == error_mark_node)
- {
- cp_error ("conversion from `%T' to `%T' is ambiguous",
- intype, reftype);
- return error_mark_node;
- }
- rval_as_conversion = build_up_reference (reftype, rval_as_conversion,
- flags, 1);
- }
-
- /* Definitely need to go through a constructor here. */
- if (TYPE_HAS_CONSTRUCTOR (type)
- && ! CLASSTYPE_ABSTRACT_VIRTUALS (type)
- && (rval = build_method_call
- (NULL_TREE, constructor_name_full (type),
- build_tree_list (NULL_TREE, expr), TYPE_BINFO (type),
- LOOKUP_NO_CONVERSION|LOOKUP_SPECULATIVELY
- | LOOKUP_ONLYCONVERTING)))
- {
- tree init;
-
- if (toplevel_bindings_p ())
- {
- extern tree static_aggregates;
- tree t = get_temp_name (type, toplevel_bindings_p ());
- init = build_method_call (t, constructor_name_full (type),
- build_tree_list (NULL_TREE, expr),
- TYPE_BINFO (type),
- LOOKUP_NORMAL|LOOKUP_NO_CONVERSION
- | LOOKUP_ONLYCONVERTING);
-
- if (init == error_mark_node)
- return error_mark_node;
-
- make_decl_rtl (t, NULL_PTR, 1);
- static_aggregates = perm_tree_cons (expr, t, static_aggregates);
- rval = build_unary_op (ADDR_EXPR, t, 0);
- }
- else
- {
- init = build_method_call (NULL_TREE, constructor_name_full (type),
- build_tree_list (NULL_TREE, expr),
- TYPE_BINFO (type),
- LOOKUP_NORMAL|LOOKUP_NO_CONVERSION
- |LOOKUP_ONLYCONVERTING);
-
- if (init == error_mark_node)
- return error_mark_node;
-
- rval = build_cplus_new (type, init, 1);
- rval = build_up_reference (reftype, rval, flags, 1);
- }
- rval_as_ctor = rval;
- }
-
- if (rval_as_ctor && rval_as_conversion)
- {
- cp_error ("ambiguous conversion from `%T' to `%T'; both user-defined conversion and constructor apply",
- intype, reftype);
- return error_mark_node;
- }
- else if (rval_as_ctor)
- rval = rval_as_ctor;
- else if (rval_as_conversion)
- rval = rval_as_conversion;
- else if (! IS_AGGR_TYPE (type) && ! IS_AGGR_TYPE (intype))
- {
- rval = convert (type, expr);
- if (rval == error_mark_node)
- return error_mark_node;
-
- rval = build_up_reference (reftype, rval, flags, 1);
- }
+ rval = convert_for_initialization (NULL_TREE, type, expr, flags,
+ "converting", 0, 0);
+ if (rval == error_mark_node)
+ return error_mark_node;
+ rval = build_up_reference (reftype, rval, flags, 1);
if (rval && ! TYPE_READONLY (TREE_TYPE (reftype)))
cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary",
@@ -840,7 +508,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
if (rval)
{
- /* If we found a way to convert earlier, then use it. */
+ /* If we found a way to convert earlier, then use it. */
return rval;
}
@@ -856,7 +524,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
}
/* We are using a reference VAL for its value. Bash that reference all the
- way down to its lowest form. */
+ way down to its lowest form. */
+
tree
convert_from_reference (val)
tree val;
@@ -870,231 +539,13 @@ convert_from_reference (val)
return val;
}
-/* See if there is a constructor of type TYPE which will convert
- EXPR. The reference manual seems to suggest (8.5.6) that we need
- not worry about finding constructors for base classes, then converting
- to the derived class.
-
- MSGP is a pointer to a message that would be an appropriate error
- string. If MSGP is NULL, then we are not interested in reporting
- errors. */
-tree
-convert_to_aggr (type, expr, msgp, protect)
- tree type, expr;
- char **msgp;
- int protect;
-{
- tree basetype = type;
- tree name = TYPE_IDENTIFIER (basetype);
- tree function, fndecl, fntype, parmtypes, parmlist, result;
- tree method_name;
- enum access_type access;
- int can_be_private, can_be_protected;
-
- if (! TYPE_HAS_CONSTRUCTOR (basetype))
- {
- if (msgp)
- *msgp = "type `%s' does not have a constructor";
- return error_mark_node;
- }
-
- access = access_public;
- can_be_private = 0;
- can_be_protected = IDENTIFIER_CLASS_VALUE (name) || name == current_class_name;
-
- parmlist = build_tree_list (NULL_TREE, expr);
- parmtypes = tree_cons (NULL_TREE, TREE_TYPE (expr), void_list_node);
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
- {
- parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);
- parmlist = tree_cons (NULL_TREE, integer_one_node, parmlist);
- }
-
- /* 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, build_pointer_type (basetype), parmtypes);
-
-#if 0
- method_name = build_decl_overload (name, parmtypes, 1);
-
- /* constructors are up front. */
- fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);
- if (TYPE_HAS_DESTRUCTOR (basetype))
- fndecl = DECL_CHAIN (fndecl);
-
- while (fndecl)
- {
- if (DECL_ASSEMBLER_NAME (fndecl) == method_name)
- {
- function = fndecl;
- if (protect)
- {
- if (TREE_PRIVATE (fndecl))
- {
- can_be_private =
- (basetype == current_class_type
- || is_friend (basetype, current_function_decl)
- || purpose_member (basetype, DECL_ACCESS (fndecl)));
- if (! can_be_private)
- goto found;
- }
- else if (TREE_PROTECTED (fndecl))
- {
- if (! can_be_protected)
- goto found;
- }
- }
- goto found_and_ok;
- }
- fndecl = DECL_CHAIN (fndecl);
- }
-#endif
-
- /* No exact conversion was found. See if an approximate
- one will do. */
- fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);
- if (TYPE_HAS_DESTRUCTOR (basetype))
- fndecl = DECL_CHAIN (fndecl);
-
- {
- int saw_private = 0;
- int saw_protected = 0;
- struct candidate *candidates =
- (struct candidate *) alloca ((decl_list_length (fndecl)+1) * sizeof (struct candidate));
- struct candidate *cp = candidates;
-
- while (fndecl)
- {
- function = fndecl;
- cp->h_len = 2;
- cp->harshness = (struct harshness_code *)
- alloca (3 * sizeof (struct harshness_code));
-
- compute_conversion_costs (fndecl, parmlist, cp, 2);
- if ((cp->h.code & EVIL_CODE) == 0)
- {
- cp->u.field = fndecl;
- if (protect)
- {
- if (TREE_PRIVATE (fndecl))
- access = access_private;
- else if (TREE_PROTECTED (fndecl))
- access = access_protected;
- else
- access = access_public;
- }
- else
- access = access_public;
-
- if (access == access_private
- ? (basetype == current_class_type
- || is_friend (basetype, cp->function)
- || purpose_member (basetype, DECL_ACCESS (fndecl)))
- : access == access_protected
- ? (can_be_protected
- || purpose_member (basetype, DECL_ACCESS (fndecl)))
- : 1)
- {
- if (cp->h.code <= TRIVIAL_CODE)
- goto found_and_ok;
- cp++;
- }
- else
- {
- if (access == access_private)
- saw_private = 1;
- else
- saw_protected = 1;
- }
- }
- fndecl = DECL_CHAIN (fndecl);
- }
- if (cp - candidates)
- {
- /* Rank from worst to best. Then cp will point to best one.
- Private fields have their bits flipped. For unsigned
- numbers, this should make them look very large.
- If the best alternate has a (signed) negative value,
- then all we ever saw were private members. */
- if (cp - candidates > 1)
- qsort (candidates, /* char *base */
- cp - candidates, /* int nel */
- sizeof (struct candidate), /* int width */
- rank_for_overload); /* int (*compar)() */
-
- --cp;
- if (cp->h.code & EVIL_CODE)
- {
- if (msgp)
- *msgp = "ambiguous type conversion possible for `%s'";
- return error_mark_node;
- }
-
- function = cp->function;
- fndecl = cp->u.field;
- goto found_and_ok;
- }
- else if (msgp)
- {
- if (saw_private)
- if (saw_protected)
- *msgp = "only private and protected conversions apply";
- else
- *msgp = "only private conversions apply";
- else if (saw_protected)
- *msgp = "only protected conversions apply";
- else
- *msgp = "no appropriate conversion to type `%s'";
- }
- return error_mark_node;
- }
- /* NOTREACHED */
-
- found:
- if (access == access_private)
- if (! can_be_private)
- {
- if (msgp)
- *msgp = TREE_PRIVATE (fndecl)
- ? "conversion to type `%s' is private"
- : "conversion to type `%s' is from private base class";
- return error_mark_node;
- }
- if (access == access_protected)
- if (! can_be_protected)
- {
- if (msgp)
- *msgp = TREE_PRIVATE (fndecl)
- ? "conversion to type `%s' is protected"
- : "conversion to type `%s' is from protected base class";
- return error_mark_node;
- }
- function = fndecl;
- found_and_ok:
-
- /* It will convert, but we don't do anything about it yet. */
- if (msgp == 0)
- return NULL_TREE;
-
- fntype = TREE_TYPE (function);
- function = default_conversion (function);
-
- result = build_nt (CALL_EXPR, function,
- convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
- parmlist, NULL_TREE, LOOKUP_NORMAL),
- NULL_TREE);
- TREE_TYPE (result) = TREE_TYPE (fntype);
- TREE_SIDE_EFFECTS (result) = 1;
- return result;
-}
-
/* Call this when we know (for any reason) that expr is not, in fact,
zero. This routine is like convert_pointer_to, but it pays
attention to which specific instance of what type we want to
convert to. This routine should eventually become
convert_to_pointer after all references to convert_to_pointer
are removed. */
+
tree
convert_pointer_to_real (binfo, expr)
tree binfo, expr;
@@ -1103,6 +554,9 @@ convert_pointer_to_real (binfo, expr)
tree ptr_type;
tree type, rval;
+ if (intype == error_mark_node)
+ return error_mark_node;
+
if (TREE_CODE (binfo) == TREE_VEC)
type = BINFO_TYPE (binfo);
else if (IS_AGGR_TYPE (binfo))
@@ -1115,13 +569,12 @@ convert_pointer_to_real (binfo, expr)
binfo = NULL_TREE;
}
- ptr_type = build_pointer_type (type);
+ ptr_type = cp_build_type_variant (type, TYPE_READONLY (TREE_TYPE (intype)),
+ TYPE_VOLATILE (TREE_TYPE (intype)));
+ ptr_type = build_pointer_type (ptr_type);
if (ptr_type == TYPE_MAIN_VARIANT (intype))
return expr;
- if (intype == error_mark_node)
- return error_mark_node;
-
my_friendly_assert (!integer_zerop (expr), 191);
if (TREE_CODE (type) == RECORD_TYPE
@@ -1159,6 +612,7 @@ convert_pointer_to_real (binfo, expr)
is more than one instance of that type in the expr, the conversion is
ambiguous. This routine should eventually go away, and all
callers should use convert_to_pointer_real. */
+
tree
convert_pointer_to (binfo, expr)
tree binfo, expr;
@@ -1174,23 +628,39 @@ convert_pointer_to (binfo, expr)
return convert_pointer_to_real (type, expr);
}
+/* C++ conversions, preference to static cast conversions. */
+
+tree
+cp_convert (type, expr)
+ tree type, expr;
+{
+ return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL);
+}
+
/* Conversion...
FLAGS indicates how we should behave. */
tree
-cp_convert (type, expr, convtype, flags)
+ocp_convert (type, expr, convtype, flags)
tree type, expr;
int convtype, flags;
{
register tree e = expr;
register enum tree_code code = TREE_CODE (type);
- if (TREE_CODE (e) == ERROR_MARK
- || TREE_CODE (TREE_TYPE (e)) == ERROR_MARK)
+ if (e == error_mark_node
+ || TREE_TYPE (e) == error_mark_node)
return error_mark_node;
- if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP))
+ if (TREE_READONLY_DECL_P (e))
+ e = decl_constant_value (e);
+
+ if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
+ /* Some internal structures (vtable_entry_type, sigtbl_ptr_type)
+ don't go through finish_struct, so they don't have the synthesized
+ constructors. So don't force a temporary. */
+ && TYPE_HAS_CONSTRUCTOR (type))
/* We need a new temporary; don't take this shortcut. */;
else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
/* Trivial conversion: cv-qualifiers do not matter on rvalues. */
@@ -1203,7 +673,7 @@ cp_convert (type, expr, convtype, flags)
/* This is incorrect. A truncation can't be stripped this way.
Extensions will be stripped by the use of get_unwidened. */
if (TREE_CODE (e) == NOP_EXPR)
- return convert (type, TREE_OPERAND (e, 0));
+ return cp_convert (type, TREE_OPERAND (e, 0));
#endif
/* Just convert to the type of the member. */
@@ -1223,18 +693,15 @@ cp_convert (type, expr, convtype, flags)
if (TREE_CODE (e) == OFFSET_REF)
e = resolve_offset_ref (e);
- if (TREE_READONLY_DECL_P (e))
- e = decl_constant_value (e);
-
if (INTEGRAL_CODE_P (code))
{
tree intype = TREE_TYPE (e);
- enum tree_code form = TREE_CODE (intype);
- /* enum = enum, enum = int, enum = float are all errors. */
+ /* enum = enum, enum = int, enum = float, (enum)pointer are all
+ errors. */
if (flag_int_enum_equivalence == 0
&& TREE_CODE (type) == ENUMERAL_TYPE
- && ARITHMETIC_TYPE_P (intype)
- && ! (convtype & CONV_STATIC))
+ && ((ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC))
+ || (TREE_CODE (intype) == POINTER_TYPE)))
{
cp_pedwarn ("conversion from `%#T' to `%#T'", intype, type);
@@ -1254,13 +721,19 @@ cp_convert (type, expr, convtype, flags)
return error_mark_node;
}
if (code == BOOLEAN_TYPE)
- return truthvalue_conversion (e);
+ {
+ /* Common Ada/Pascal programmer's mistake. We always warn
+ about this since it is so bad. */
+ if (TREE_CODE (expr) == FUNCTION_DECL)
+ cp_warning ("the address of `%D', will always be `true'", expr);
+ return truthvalue_conversion (e);
+ }
return fold (convert_to_integer (type, e));
}
if (code == POINTER_TYPE || code == REFERENCE_TYPE
|| TYPE_PTRMEMFUNC_P (type))
return fold (cp_convert_to_pointer (type, e));
- if (code == REAL_TYPE)
+ if (code == REAL_TYPE || code == COMPLEX_TYPE)
{
if (IS_AGGR_TYPE (TREE_TYPE (e)))
{
@@ -1273,7 +746,10 @@ cp_convert (type, expr, convtype, flags)
cp_error ("`%#T' used where a floating point value was expected",
TREE_TYPE (e));
}
- return fold (convert_to_real (type, e));
+ if (code == REAL_TYPE)
+ return fold (convert_to_real (type, e));
+ else if (code == COMPLEX_TYPE)
+ return fold (convert_to_complex (type, e));
}
/* New C++ semantics: since assignment is now based on
@@ -1283,7 +759,6 @@ cp_convert (type, expr, convtype, flags)
{
tree dtype = TREE_TYPE (e);
tree ctor = NULL_TREE;
- tree conversion = NULL_TREE;
dtype = TYPE_MAIN_VARIANT (dtype);
@@ -1317,53 +792,24 @@ cp_convert (type, expr, convtype, flags)
There may be some ambiguity between using a constructor
vs. using a type conversion operator when both apply. */
- if (IS_AGGR_TYPE (dtype) && ! DERIVED_FROM_P (type, dtype)
- && TYPE_HAS_CONVERSION (dtype))
- conversion = build_type_conversion (CONVERT_EXPR, type, e, 1);
-
- if (conversion == error_mark_node)
- {
- if (flags & LOOKUP_COMPLAIN)
- error ("ambiguous pointer conversion");
- return conversion;
- }
-
- if (TYPE_HAS_CONSTRUCTOR (type))
- ctor = build_method_call (NULL_TREE, constructor_name_full (type),
- build_tree_list (NULL_TREE, e),
- TYPE_BINFO (type),
- (flags & LOOKUP_NORMAL) | LOOKUP_SPECULATIVELY
- | (convtype&CONV_NONCONVERTING ? 0 : LOOKUP_ONLYCONVERTING)
- | (conversion ? LOOKUP_NO_CONVERSION : 0));
-
- if (ctor == error_mark_node)
- {
- if (flags & LOOKUP_COMPLAIN)
- cp_error ("in conversion to type `%T'", type);
- if (flags & LOOKUP_SPECULATIVELY)
- return NULL_TREE;
- return error_mark_node;
- }
-
- if (conversion && ctor)
- {
- if (flags & LOOKUP_COMPLAIN)
- error ("both constructor and type conversion operator apply");
- if (flags & LOOKUP_SPECULATIVELY)
- return NULL_TREE;
- return error_mark_node;
- }
- else if (conversion)
- return conversion;
- else if (ctor)
- {
- ctor = build_cplus_new (type, ctor, 0);
- return ctor;
- }
+ ctor = e;
+
+ if ((flags & LOOKUP_ONLYCONVERTING)
+ && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
+ /* For copy-initialization, first we create a temp of the proper type
+ with a user-defined conversion sequence, then we direct-initialize
+ the target with the temp (see [dcl.init]). */
+ ctor = build_user_type_conversion (type, ctor, flags);
+ if (ctor)
+ ctor = build_method_call (NULL_TREE, ctor_identifier,
+ build_expr_list (NULL_TREE, ctor),
+ TYPE_BINFO (type), flags);
+ if (ctor)
+ return build_cplus_new (type, ctor);
}
/* If TYPE or TREE_TYPE (E) is not on the permanent_obstack,
- then the it won't be hashed and hence compare as not equal,
+ then it won't be hashed and hence compare as not equal,
even when it is. */
if (code == ARRAY_TYPE
&& TREE_TYPE (TREE_TYPE (e)) == TREE_TYPE (type)
@@ -1382,18 +828,45 @@ cp_convert (type, expr, convtype, flags)
converted to type TYPE. The TREE_TYPE of the value
is always TYPE. This function implements all reasonable
conversions; callers should filter out those that are
- not permitted by the language being compiled. */
+ not permitted by the language being compiled.
+
+ Most of this routine is from build_reinterpret_cast.
+
+ The backend cannot call cp_convert (what was convert) because
+ conversions to/from basetypes may involve memory references
+ (vbases) and adding or subtracting small values (multiple
+ inheritance), but it calls convert from the constant folding code
+ on subtrees of already build trees after it has ripped them apart.
+
+ Also, if we ever support range variables, we'll probably also have to
+ do a little bit more work. */
tree
convert (type, expr)
tree type, expr;
{
- return cp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL);
+ tree intype;
+
+ if (type == error_mark_node || expr == error_mark_node)
+ return error_mark_node;
+
+ intype = TREE_TYPE (expr);
+
+ if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
+ {
+ if (TREE_READONLY_DECL_P (expr))
+ expr = decl_constant_value (expr);
+ return fold (build1 (NOP_EXPR, type, expr));
+ }
+
+ return ocp_convert (type, expr, CONV_OLD_CONVERT,
+ LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
}
-/* Like convert, except permit conversions to take place which
+/* Like cp_convert, except permit conversions to take place which
are not normally allowed due to access restrictions
(such as conversion from sub-type to private super-type). */
+
tree
convert_force (type, expr, convtype)
tree type;
@@ -1420,46 +893,11 @@ convert_force (type, expr, convtype)
|| TYPE_PTRMEMFUNC_P (TREE_TYPE (e)))
&& TYPE_PTRMEMFUNC_P (type))
{
- /* compatible pointer to member functions. */
+ /* compatible pointer to member functions. */
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
}
- return cp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL);
-}
-
-/* Subroutine of build_type_conversion. */
-static tree
-build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
- tree xtype, basetype;
- tree expr;
- tree typename;
- int for_sure;
-{
- tree rval;
- int flags;
-
- if (for_sure == 0)
- flags = LOOKUP_PROTECT|LOOKUP_ONLYCONVERTING;
- else
- flags = LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING;
-
- rval = build_method_call (expr, typename, NULL_TREE, NULL_TREE, flags);
- if (rval == error_mark_node)
- {
- if (for_sure == 0)
- return NULL_TREE;
- return error_mark_node;
- }
-
- if (IS_AGGR_TYPE (TREE_TYPE (rval)))
- return rval;
-
- if (warn_cast_qual
- && TREE_TYPE (xtype)
- && (TREE_READONLY (TREE_TYPE (TREE_TYPE (rval)))
- > TREE_READONLY (TREE_TYPE (xtype))))
- warning ("user-defined conversion casting away `const'");
- return convert (xtype, rval);
+ return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL);
}
/* Convert an aggregate EXPR to type XTYPE. If a conversion
@@ -1487,58 +925,8 @@ build_type_conversion (code, xtype, expr, for_sure)
{
/* C++: check to see if we can convert this aggregate type
into the required type. */
- tree basetype;
- tree conv;
- tree winner = NULL_TREE;
-
- if (expr == error_mark_node)
- return error_mark_node;
-
- basetype = TREE_TYPE (expr);
- if (TREE_CODE (basetype) == REFERENCE_TYPE)
- basetype = TREE_TYPE (basetype);
-
- basetype = TYPE_MAIN_VARIANT (basetype);
- if (! TYPE_LANG_SPECIFIC (basetype) || ! TYPE_HAS_CONVERSION (basetype))
- return NULL_TREE;
-
- /* Do we have an exact match? */
- {
- tree typename = build_typename_overload (xtype);
- if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
- return build_type_conversion_1 (xtype, basetype, expr, typename,
- for_sure);
- }
-
- /* Nope; try looking for others. */
- for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
- {
- if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
- continue;
-
- if (can_convert (xtype, TREE_VALUE (conv)))
- {
- if (winner)
- {
- if (for_sure)
- {
- cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
- xtype);
- cp_error (" candidate conversions include `%T' and `%T'",
- TREE_VALUE (winner), TREE_VALUE (conv));
- }
- return NULL_TREE;
- }
- else
- winner = conv;
- }
- }
-
- if (winner)
- return build_type_conversion_1 (xtype, basetype, expr,
- TREE_PURPOSE (winner), for_sure);
-
- return NULL_TREE;
+ return build_user_type_conversion
+ (xtype, expr, for_sure ? LOOKUP_NORMAL : 0);
}
/* Convert the given EXPR to one of a group of types suitable for use in an
@@ -1568,7 +956,7 @@ build_expr_type_conversion (desires, expr, complain)
if ((desires & WANT_NULL) && TREE_CODE (expr) == INTEGER_CST
&& integer_zerop (expr))
return expr;
- /* else fall through... */
+ /* else fall through... */
case BOOLEAN_TYPE:
return (desires & WANT_INT) ? expr : NULL_TREE;
@@ -1587,6 +975,9 @@ build_expr_type_conversion (desires, expr, complain)
return NULL_TREE;
}
+ /* The code for conversions from class type is currently only used for
+ delete expressions. Other expressions are handled by build_new_op. */
+
if (! TYPE_HAS_CONVERSION (basetype))
return NULL_TREE;
@@ -1594,11 +985,12 @@ build_expr_type_conversion (desires, expr, complain)
{
int win = 0;
tree candidate;
+ tree cand = TREE_VALUE (conv);
- if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
+ if (winner && winner == cand)
continue;
- candidate = TREE_VALUE (conv);
+ candidate = TREE_TYPE (TREE_TYPE (cand));
if (TREE_CODE (candidate) == REFERENCE_TYPE)
candidate = TREE_TYPE (candidate);
@@ -1613,6 +1005,9 @@ build_expr_type_conversion (desires, expr, complain)
win = (desires & WANT_FLOAT); break;
case POINTER_TYPE:
win = (desires & WANT_POINTER); break;
+
+ default:
+ break;
}
if (win)
@@ -1623,153 +1018,29 @@ build_expr_type_conversion (desires, expr, complain)
{
cp_error ("ambiguous default type conversion from `%T'",
basetype);
- cp_error (" candidate conversions include `%T' and `%T'",
- TREE_VALUE (winner), TREE_VALUE (conv));
+ cp_error (" candidate conversions include `%D' and `%D'",
+ winner, cand);
}
return error_mark_node;
}
else
- winner = conv;
+ winner = cand;
}
}
if (winner)
- return build_type_conversion_1 (TREE_VALUE (winner), basetype, expr,
- TREE_PURPOSE (winner), 1);
-
- return NULL_TREE;
-}
-
-/* Must convert two aggregate types to non-aggregate type.
- Attempts to find a non-ambiguous, "best" type conversion.
-
- Return 1 on success, 0 on failure.
-
- @@ What are the real semantics of this supposed to be??? */
-int
-build_default_binary_type_conversion (code, arg1, arg2)
- enum tree_code code;
- tree *arg1, *arg2;
-{
- switch (code)
{
- case MULT_EXPR:
- case TRUNC_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case EXACT_DIV_EXPR:
- *arg1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
- *arg2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
- break;
-
- case TRUNC_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case BIT_AND_EXPR:
- case BIT_XOR_EXPR:
- case BIT_IOR_EXPR:
- *arg1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg1, 0);
- *arg2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg2, 0);
- break;
-
- case PLUS_EXPR:
- {
- tree a1, a2, p1, p2;
- int wins;
-
- a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
- a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
- p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0);
- p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0);
-
- wins = (a1 && a2) + (a1 && p2) + (p1 && a2);
-
- if (wins > 1)
- error ("ambiguous default type conversion for `operator +'");
-
- if (a1 && a2)
- *arg1 = a1, *arg2 = a2;
- else if (a1 && p2)
- *arg1 = a1, *arg2 = p2;
- else
- *arg1 = p1, *arg2 = a2;
- break;
- }
-
- case MINUS_EXPR:
- {
- tree a1, a2, p1, p2;
- int wins;
-
- a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
- a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
- p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0);
- p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0);
-
- wins = (a1 && a2) + (p1 && p2) + (p1 && a2);
-
- if (wins > 1)
- error ("ambiguous default type conversion for `operator -'");
-
- if (a1 && a2)
- *arg1 = a1, *arg2 = a2;
- else if (p1 && p2)
- *arg1 = p1, *arg2 = p2;
- else
- *arg1 = p1, *arg2 = a2;
- break;
- }
-
- case GT_EXPR:
- case LT_EXPR:
- case GE_EXPR:
- case LE_EXPR:
- case EQ_EXPR:
- case NE_EXPR:
- {
- tree a1, a2, p1, p2;
- int wins;
-
- a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
- a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
- p1 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg1, 0);
- p2 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg2, 0);
-
- wins = (a1 && a2) + (p1 && p2);
-
- if (wins > 1)
- cp_error ("ambiguous default type conversion for `%O'", code);
-
- if (a1 && a2)
- *arg1 = a1, *arg2 = a2;
- else
- *arg1 = p1, *arg2 = p2;
- break;
- }
-
- case TRUTH_ANDIF_EXPR:
- case TRUTH_ORIF_EXPR:
- *arg1 = convert (boolean_type_node, *arg1);
- *arg2 = convert (boolean_type_node, *arg2);
- break;
-
- default:
- *arg1 = NULL_TREE;
- *arg2 = NULL_TREE;
+ tree type = TREE_TYPE (TREE_TYPE (winner));
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+ return build_user_type_conversion (type, expr, LOOKUP_NORMAL);
}
- if (*arg1 == error_mark_node || *arg2 == error_mark_node)
- cp_error ("ambiguous default type conversion for `%O'", code);
-
- if (*arg1 && *arg2)
- return 1;
-
- return 0;
+ return NULL_TREE;
}
-/* Implements integral promotion (4.1) and float->double promotion. */
+/* Implements integral promotion (4.1) and float->double promotion. */
+
tree
type_promotes_to (type)
tree type;
@@ -1804,11 +1075,9 @@ type_promotes_to (type)
}
else if (C_PROMOTING_INTEGER_TYPE_P (type))
{
- /* Traditionally, unsignedness is preserved in default promotions.
- Otherwise, retain unsignedness if really not getting bigger. */
+ /* Retain unsignedness if really not getting bigger. */
if (TREE_UNSIGNED (type)
- && (flag_traditional
- || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
+ && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
type = unsigned_type_node;
else
type = integer_type_node;
@@ -1818,3 +1087,24 @@ type_promotes_to (type)
return cp_build_type_variant (type, constp, volatilep);
}
+
+
+/* The routines below this point are carefully written to conform to
+ the standard. They use the same terminology, and follow the rules
+ closely. Although they are used only in pt.c at the moment, they
+ should presumably be used everywhere in the future. */
+
+/* Attempt to perform qualification conversions on EXPR to convert it
+ to TYPE. Return the resulting expression, or error_mark_node if
+ the conversion was impossible. */
+
+tree
+perform_qualification_conversions (type, expr)
+ tree type;
+ tree expr;
+{
+ if (comp_target_types (type, TREE_TYPE (expr), 0) == 1)
+ return build1 (NOP_EXPR, type, expr);
+ else
+ return error_mark_node;
+}
diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c
index 103cb0d..68f62ae 100644
--- a/contrib/gcc/cp/decl.c
+++ b/contrib/gcc/cp/decl.c
@@ -1,6 +1,6 @@
/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
- Hacked by Michael Tiemann (tiemann@cygnus.com)
+ Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -27,17 +27,20 @@ Boston, MA 02111-1307, USA. */
/* ??? not all decl nodes are given the most useful possible
line numbers. For example, the CONST_DECLs for enum values. */
-#include <stdio.h>
#include "config.h"
+#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "flags.h"
#include "cp-tree.h"
#include "decl.h"
#include "lex.h"
-#include <sys/types.h>
#include <signal.h>
#include "obstack.h"
+#include "defaults.h"
+#include "output.h"
+#include "except.h"
+#include "toplev.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -45,19 +48,25 @@ Boston, MA 02111-1307, USA. */
extern tree builtin_return_address_fndecl;
extern struct obstack permanent_obstack;
+extern struct obstack* saveable_obstack;
extern int current_class_depth;
-extern tree cleanups_this_call;
-
extern tree static_ctors, static_dtors;
+extern int static_labelno;
+
+extern tree current_namespace;
+extern tree global_namespace;
+
+extern void (*print_error_function) PROTO((char *));
+
/* Stack of places to restore the search obstack back to. */
/* Obstack used for remembering local class declarations (like
enums and static (const) members. */
#include "stack.h"
-static struct obstack decl_obstack;
+struct obstack decl_obstack;
static struct stack_level *decl_stack;
#ifndef CHAR_TYPE_SIZE
@@ -98,9 +107,9 @@ static struct stack_level *decl_stack;
#ifndef BOOL_TYPE_SIZE
#ifdef SLOW_BYTE_ACCESS
-#define BOOL_TYPE_SIZE ((SLOW_BYTE_ACCESS) ? (BITS_PER_WORD) : (BITS_PER_UNIT))
+#define BOOL_TYPE_SIZE ((SLOW_BYTE_ACCESS) ? (POINTER_SIZE) : (CHAR_TYPE_SIZE))
#else
-#define BOOL_TYPE_SIZE BITS_PER_UNIT
+#define BOOL_TYPE_SIZE CHAR_TYPE_SIZE
#endif
#endif
@@ -125,12 +134,54 @@ static struct stack_level *decl_stack;
static tree grokparms PROTO((tree, int));
static tree lookup_nested_type PROTO((tree, tree));
static char *redeclaration_error_message PROTO((tree, tree));
-static void grok_op_properties PROTO((tree, int, int));
-
-tree define_function
- PROTO((char *, tree, enum built_in_function, void (*)(), char *));
+static tree push_overloaded_decl PROTO((tree, int));
+
+static struct stack_level *push_decl_level PROTO((struct stack_level *,
+ struct obstack *));
+static void push_binding_level PROTO((struct binding_level *, int,
+ int));
+static void pop_binding_level PROTO((void));
+static void suspend_binding_level PROTO((void));
+static void resume_binding_level PROTO((struct binding_level *));
+static struct binding_level *make_binding_level PROTO((void));
+static int namespace_bindings_p PROTO((void));
+static void declare_namespace_level PROTO((void));
+static void signal_catch PROTO((int));
+static void storedecls PROTO((tree));
+static void storetags PROTO((tree));
+static void require_complete_types_for_parms PROTO((tree));
+static void push_overloaded_decl_1 PROTO((tree));
+static int ambi_op_p PROTO((tree));
+static int unary_op_p PROTO((tree));
+static tree store_bindings PROTO((tree, tree));
+static tree lookup_tag_reverse PROTO((tree, tree));
+static tree obscure_complex_init PROTO((tree, tree));
+static tree maybe_build_cleanup_1 PROTO((tree, tree));
+static tree lookup_name_real PROTO((tree, int, int, int));
+static void warn_extern_redeclared_static PROTO((tree, tree));
+static void grok_reference_init PROTO((tree, tree, tree));
+static tree grokfndecl PROTO((tree, tree, tree, tree, int,
+ enum overload_flags, tree,
+ tree, tree, int, int, int, int, int, int, tree));
+static tree grokvardecl PROTO((tree, tree, RID_BIT_TYPE *, int, int, tree));
+static tree lookup_tag PROTO((enum tree_code, tree,
+ struct binding_level *, int));
+static void set_identifier_type_value_with_scope
+ PROTO((tree, tree, struct binding_level *));
+static void set_identifier_local_value_with_scope
+ PROTO((tree, tree, struct binding_level *));
+static void record_builtin_type PROTO((enum rid, char *, tree));
+static void record_unknown_type PROTO((tree, char *));
+static int member_function_or_else PROTO((tree, tree, char *));
+static void bad_specifiers PROTO((tree, char *, int, int, int, int,
+ int));
+static void lang_print_error_function PROTO((char *));
+
+#if defined (DEBUG_CP_BINDING_LEVELS)
+static void indent PROTO((void));
+#endif
-/* a node which has tree code ERROR_MARK, and whose type is itself.
+/* A node which has tree code ERROR_MARK, and whose type is itself.
All erroneous expressions are replaced with this node. All functions
that accept nodes as arguments should avoid generating error messages
if this node is one of the arguments, since it is undesirable to get
@@ -168,24 +219,41 @@ tree float_type_node;
tree double_type_node;
tree long_double_type_node;
+tree complex_integer_type_node;
+tree complex_float_type_node;
+tree complex_double_type_node;
+tree complex_long_double_type_node;
+
tree intQI_type_node;
tree intHI_type_node;
tree intSI_type_node;
tree intDI_type_node;
+tree intTI_type_node;
tree unsigned_intQI_type_node;
tree unsigned_intHI_type_node;
tree unsigned_intSI_type_node;
tree unsigned_intDI_type_node;
+tree unsigned_intTI_type_node;
-/* a VOID_TYPE node, and the same, packaged in a TREE_LIST. */
+tree java_byte_type_node;
+tree java_short_type_node;
+tree java_int_type_node;
+tree java_long_type_node;
+tree java_float_type_node;
+tree java_double_type_node;
+tree java_char_type_node;
+tree java_boolean_type_node;
+
+/* A VOID_TYPE node, and the same, packaged in a TREE_LIST. */
tree void_type_node, void_list_node;
tree void_zero_node;
/* Nodes for types `void *' and `const void *'. */
-tree ptr_type_node, const_ptr_type_node;
+tree ptr_type_node;
+tree const_ptr_type_node;
/* Nodes for types `char *' and `const char *'. */
@@ -209,38 +277,33 @@ tree wchar_array_type_node;
/* The bool data type, and constants */
tree boolean_type_node, boolean_true_node, boolean_false_node;
-/* type `int ()' -- used for implicit declaration of functions. */
+/* Type `int ()' -- used for implicit declaration of functions. */
tree default_function_type;
-/* function types `double (double)' and `double (double, double)', etc. */
-
-tree double_ftype_double, double_ftype_double_double;
-tree int_ftype_int, long_ftype_long;
+/* Function types `double (double)' and `double (double, double)', etc. */
-/* Function type `void (void *, void *, int)' and similar ones. */
-
-tree void_ftype_ptr_ptr_int, int_ftype_ptr_ptr_int, void_ftype_ptr_int_int;
-
-/* Function type `char *(char *, char *)' and similar ones */
-tree string_ftype_ptr_ptr, int_ftype_string_string;
-
-/* Function type `size_t (const char *)' */
-tree sizet_ftype_string;
+static tree double_ftype_double, double_ftype_double_double;
+static tree int_ftype_int, long_ftype_long;
+static tree float_ftype_float;
+static tree ldouble_ftype_ldouble;
/* Function type `int (const void *, const void *, size_t)' */
-tree int_ftype_cptr_cptr_sizet;
+static tree int_ftype_cptr_cptr_sizet;
/* C++ extensions */
tree vtable_entry_type;
tree delta_type_node;
#if 0
-/* Old rtti stuff. */
+/* Old rtti stuff. */
tree __baselist_desc_type_node;
tree __i_desc_type_node, __m_desc_type_node;
tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type;
#endif
-tree __t_desc_type_node, __tp_desc_type_node;
+tree __t_desc_type_node;
+#if 0
+tree __tp_desc_type_node;
+#endif
tree __access_mode_type_node;
tree __bltn_desc_type_node, __user_desc_type_node, __class_desc_type_node;
tree __ptr_desc_type_node, __attr_desc_type_node, __func_desc_type_node;
@@ -252,21 +315,44 @@ tree __ptr_desc_array_type, __attr_dec_array_type, __func_desc_array_type;
tree __ptmf_desc_array_type, __ptmd_desc_array_type;
#endif
+/* Indicates that there is a type value in some namespace, although
+ that is not necessarily in scope at the moment. */
+
+static tree global_type_node;
+
tree class_star_type_node;
tree class_type_node, record_type_node, union_type_node, enum_type_node;
tree unknown_type_node;
tree opaque_type_node, signature_type_node;
tree sigtable_entry_type;
-tree maybe_gc_cleanup;
/* Array type `vtable_entry_type[]' */
tree vtbl_type_node;
+/* namespace std */
+tree std_node;
+int in_std = 0;
+
+/* Expect only namespace names now. */
+static int only_namespace_names;
+
/* In a destructor, the point at which all derived class destroying
has been done, just before any base class destroying will be done. */
tree dtor_label;
+/* In a destructor, the last insn emitted after the start of the
+ function and the parms. */
+
+static rtx last_dtor_insn;
+
+/* In a constructor, the last insn emitted after the start of the
+ function and the parms, the exception specification and any
+ function-try-block. The constructor initializers are emitted after
+ this insn. */
+
+static rtx last_parm_cleanup_insn;
+
/* In a constructor, the point at which we are ready to return
the pointer to the initialized object. */
@@ -284,7 +370,7 @@ extern rtx cleanup_label, return_label;
but due to being an addressable named return value, would up
on the stack, this variable holds the named return value's
original location. */
-rtx original_result_rtx;
+static rtx original_result_rtx;
/* Sequence of insns which represents base initialization. */
tree base_init_expr;
@@ -293,23 +379,40 @@ tree base_init_expr;
Identifiers for `this' in member functions and the auto-delete
parameter for destructors. */
tree this_identifier, in_charge_identifier;
-/* Used in pointer to member functions, in vtables, and in sigtables. */
+tree ctor_identifier, dtor_identifier;
+/* Used in pointer to member functions, in vtables, and in sigtables. */
tree pfn_identifier, index_identifier, delta_identifier, delta2_identifier;
tree pfn_or_delta2_identifier, tag_identifier;
-tree vb_off_identifier, vt_off_identifier;
+tree vt_off_identifier;
+
+struct named_label_list
+{
+ struct binding_level *binding_level;
+ tree names_in_scope;
+ tree label_decl;
+ char *filename_o_goto;
+ int lineno_o_goto;
+ struct named_label_list *next;
+};
/* A list (chain of TREE_LIST nodes) of named label uses.
The TREE_PURPOSE field is the list of variables defined
- the the label's scope defined at the point of use.
+ in the label's scope defined at the point of use.
The TREE_VALUE field is the LABEL_DECL used.
The TREE_TYPE field holds `current_binding_level' at the
point of the label's use.
+ BWAHAHAAHAHahhahahahaah. No, no, no, said the little chicken.
+
+ Look at the pretty struct named_label_list. See the pretty struct
+ with the pretty named fields that describe what they do. See the
+ pretty lack of gratuitous casts. Notice the code got a lot cleaner.
+
Used only for jumps to as-yet undefined labels, since
jumps to defined labels can have their validity checked
by stmt.c. */
-static tree named_label_uses;
+static struct named_label_list *named_label_uses = NULL;
/* A list of objects which have constructors or destructors
which reside in the global scope. The decl is stored in
@@ -325,17 +428,14 @@ tree static_aggregates;
tree integer_zero_node;
tree null_pointer_node;
-/* A node for the integer constants 1, 2, and 3. */
+/* The value for __null (NULL), either of type `void *' or, with -ansi,
+ an integer type of the same size. */
-tree integer_one_node, integer_two_node, integer_three_node;
+tree null_node;
-/* Nonzero if we have seen an invalid cross reference
- to a struct, union, or enum, but not yet printed the message. */
+/* A node for the integer constants 1, 2, and 3. */
-tree pending_invalid_xref;
-/* File and line to appear in the eventual error message. */
-char *pending_invalid_xref_file;
-int pending_invalid_xref_line;
+tree integer_one_node, integer_two_node, integer_three_node;
/* While defining an enum type, this is 1 plus the last enumerator
constant value. */
@@ -375,13 +475,6 @@ static tree named_labels;
static tree shadowed_labels;
-#if 0 /* Not needed by C++ */
-/* Nonzero when store_parm_decls is called indicates a varargs function.
- Value not meaningful after store_parm_decls. */
-
-static int c_function_varargs;
-#endif
-
/* The FUNCTION_DECL for the function currently being compiled,
or 0 if between functions. */
tree current_function_decl;
@@ -427,7 +520,7 @@ extern int flag_no_nonansi_builtin;
extern int flag_ansi;
/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
- objects. */
+ objects. */
extern int flag_huge_objects;
/* Nonzero if we want to conserve space in the .o files. We do this
@@ -445,7 +538,7 @@ extern tree *current_lang_base, *current_lang_stack;
/* Set to 0 at beginning of a constructor, set to 1
if that function does an allocation before referencing its
instance variable. */
-int current_function_assigns_this;
+static int current_function_assigns_this;
int current_function_just_assigned_this;
/* Set to 0 at beginning of a function. Set non-zero when
@@ -453,14 +546,6 @@ int current_function_just_assigned_this;
if this flag is non-zero! */
int current_function_parms_stored;
-/* Current end of entries in the gc obstack for stack pointer variables. */
-
-int current_function_obstack_index;
-
-/* Flag saying whether we have used the obstack in this function or not. */
-
-int current_function_obstack_usage;
-
/* Flag used when debugging spew.c */
extern int spew_debug;
@@ -470,8 +555,14 @@ extern int spew_debug;
when entering another class scope (i.e. a cache miss). */
extern tree previous_class_values;
+/* A expression of value 0 with the same precision as a sizetype
+ node, but signed. */
+tree signed_size_zero_node;
+
/* Allocate a level of searching. */
+
+static
struct stack_level *
push_decl_level (stack, obstack)
struct stack_level *stack;
@@ -484,24 +575,22 @@ push_decl_level (stack, obstack)
}
/* For each binding contour we allocate a binding_level structure
- * which records the names defined in that contour.
- * Contours include:
- * 0) the global one
- * 1) one for each function definition,
- * where internal declarations of the parameters appear.
- * 2) one for each compound statement,
- * to record its declarations.
- *
- * The current meaning of a name can be found by searching the levels from
- * the current one out to the global one.
- *
- * Off to the side, may be the class_binding_level. This exists
- * only to catch class-local declarations. It is otherwise
- * nonexistent.
- *
- * Also there may be binding levels that catch cleanups that
- * must be run when exceptions occur.
- */
+ which records the names defined in that contour.
+ Contours include:
+ 0) the global one
+ 1) one for each function definition,
+ where internal declarations of the parameters appear.
+ 2) one for each compound statement,
+ to record its declarations.
+
+ The current meaning of a name can be found by searching the levels
+ from the current one out to the global one.
+
+ Off to the side, may be the class_binding_level. This exists only
+ to catch class-local declarations. It is otherwise nonexistent.
+
+ Also there may be binding levels that catch cleanups that must be
+ run when exceptions occur. */
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
@@ -509,21 +598,27 @@ push_decl_level (stack, obstack)
struct binding_level
{
/* A chain of _DECL nodes for all variables, constants, functions,
- * and typedef types. These are in the reverse of the order supplied.
- */
+ and typedef types. These are in the reverse of the order
+ supplied. */
tree names;
- /* A list of structure, union and enum definitions,
- * for looking up tag names.
- * It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name,
- * or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE,
- * or ENUMERAL_TYPE node.
- *
- * C++: the TREE_VALUE nodes can be simple types for component_bindings.
- *
- */
+ /* A list of structure, union and enum definitions, for looking up
+ tag names.
+ It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name,
+ or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE,
+ or ENUMERAL_TYPE node.
+
+ C++: the TREE_VALUE nodes can be simple types for
+ component_bindings. */
tree tags;
+ /* A list of USING_DECL nodes. */
+ tree usings;
+
+ /* A list of used namespaces. PURPOSE is the namespace,
+ VALUE the common ancestor with this binding_level's namespace. */
+ tree using_directives;
+
/* For each level, a list of shadowed outer-level local definitions
to be restored when this level is popped.
Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
@@ -554,7 +649,7 @@ struct binding_level
/* List of VAR_DECLS saved from a previous for statement.
These would be dead in ANSI-conforming code, but might
- be referenced in traditional code. */
+ be referenced in ARM-era code. */
tree dead_vars_from_for;
/* 1 for the level that holds the parameters of a function.
@@ -574,24 +669,19 @@ struct binding_level
unsigned more_cleanups_ok : 1;
unsigned have_cleanups : 1;
- /* Nonzero if we should accept any name as an identifier in
- this scope. This happens in some template definitions. */
- unsigned accept_any : 1;
-
- /* Nonzero if this level is for completing a template class definition
- inside a binding level that temporarily binds the parameters. This
- means that definitions here should not be popped off when unwinding
- this binding level. (Not actually implemented this way,
- unfortunately.) */
+ /* Nonzero if this level is for storing the decls for template
+ parameters and generic decls; these decls will be discarded and
+ replaced with a TEMPLATE_DECL. */
unsigned pseudo_global : 1;
/* This is set for a namespace binding level. */
unsigned namespace_p : 1;
- /* True if this level is that of a for-statement. */
+ /* True if this level is that of a for-statement where we need to
+ worry about ambiguous (ARM or ANSI) scope rules. */
unsigned is_for_scope : 1;
- /* One bit left for this word. */
+ /* Two bits left for this word. */
#if defined(DEBUG_CP_BINDING_LEVELS)
/* Binding depth at which this level began. */
@@ -687,7 +777,7 @@ pop_binding_level ()
if (global_binding_level)
{
- /* cannot pop a level, if there are none left to pop. */
+ /* Cannot pop a level, if there are none left to pop. */
if (current_binding_level == global_binding_level)
my_friendly_abort (123);
}
@@ -699,14 +789,10 @@ pop_binding_level ()
(is_class_level) ? "class" : "block",
current_binding_level, lineno);
if (is_class_level != (current_binding_level == class_binding_level))
-#if 0 /* XXX Don't abort when we're watching how things are being managed. */
- abort ();
-#else
- {
- indent ();
- fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
- }
-#endif
+ {
+ indent ();
+ fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
+ }
is_class_level = 0;
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
{
@@ -735,7 +821,7 @@ suspend_binding_level ()
if (global_binding_level)
{
- /* cannot suspend a level, if there are none left to suspend. */
+ /* Cannot suspend a level, if there are none left to suspend. */
if (current_binding_level == global_binding_level)
my_friendly_abort (123);
}
@@ -747,24 +833,14 @@ suspend_binding_level ()
(is_class_level) ? "class" : "block",
current_binding_level, lineno);
if (is_class_level != (current_binding_level == class_binding_level))
-#if 0 /* XXX Don't abort when we're watching how things are being managed. */
- abort ();
-#else
- {
- indent ();
- fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
- }
-#endif
+ {
+ indent ();
+ fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
+ }
is_class_level = 0;
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
{
- register struct binding_level *level = current_binding_level;
current_binding_level = current_binding_level->level_chain;
-#if 0 /* defined(DEBUG_CP_BINDING_LEVELS) */
- if (level->binding_depth != binding_depth)
- abort ();
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
-
class_binding_level = current_binding_level;
if (class_binding_level->parm_flag != 2)
class_binding_level = 0;
@@ -773,33 +849,15 @@ suspend_binding_level ()
}
}
-void
+static void
resume_binding_level (b)
struct binding_level *b;
{
- if (class_binding_level)
- {
-#if 1
- /* These are here because we cannot deal with shadows yet. */
- sorry ("cannot resume a namespace inside class");
- return;
-#else
- b->level_chain = class_binding_level;
- class_binding_level = (struct binding_level *)0;
-#endif
- }
- else
- {
-#if 1
- /* These are here because we cannot deal with shadows yet. */
- if (b->level_chain != current_binding_level)
- {
- sorry ("cannot resume a namespace inside a different namespace");
- return;
- }
-#endif
- b->level_chain = current_binding_level;
- }
+ /* Resuming binding levels is meant only for namespaces,
+ and those cannot nest into classes. */
+ my_friendly_assert(!class_binding_level, 386);
+ /* Also, resuming a non-directly nested namespace is a no-no. */
+ my_friendly_assert(b->level_chain == current_binding_level, 386);
current_binding_level = b;
#if defined(DEBUG_CP_BINDING_LEVELS)
b->binding_depth = binding_depth;
@@ -811,6 +869,16 @@ resume_binding_level (b)
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
}
+/* Create a new `struct binding_level'. */
+
+static
+struct binding_level *
+make_binding_level ()
+{
+ /* NOSTRICT */
+ return (struct binding_level *) xmalloc (sizeof (struct binding_level));
+}
+
/* Nonzero if we are currently in the global binding level. */
int
@@ -821,26 +889,20 @@ global_bindings_p ()
/* Nonzero if we are currently in a toplevel binding level. This
means either the global binding level or a namespace in a toplevel
- binding level. */
+ binding level.
+ Since there are no non-toplevel namespace levels, this really
+ means any namespace or pseudo-global level. */
int
toplevel_bindings_p ()
{
- struct binding_level *b = current_binding_level;
-
- while (1)
- {
- if (b == global_binding_level)
- return 1;
- if (! b->namespace_p)
- return 0;
- b=b->level_chain;
- }
+ return current_binding_level->namespace_p
+ || current_binding_level->pseudo_global;
}
/* Nonzero if this is a namespace scope. */
-int
+static int
namespace_bindings_p ()
{
return current_binding_level->namespace_p;
@@ -873,24 +935,12 @@ declare_parm_level ()
}
void
-declare_uninstantiated_type_level ()
-{
- current_binding_level->accept_any = 1;
-}
-
-int
-uninstantiated_type_level_p ()
-{
- return current_binding_level->accept_any;
-}
-
-void
declare_pseudo_global_level ()
{
current_binding_level->pseudo_global = 1;
}
-void
+static void
declare_namespace_level ()
{
current_binding_level->namespace_p = 1;
@@ -939,15 +989,15 @@ pushlevel (tag_transparent)
}
else
{
- /* Create a new `struct binding_level'. */
- newlevel = (struct binding_level *) xmalloc (sizeof (struct binding_level));
+ newlevel = make_binding_level ();
}
+
push_binding_level (newlevel, tag_transparent, keep_next_level_flag);
GNU_xref_start_scope ((HOST_WIDE_INT) newlevel);
keep_next_level_flag = 0;
}
-int
+void
note_level_for_for ()
{
current_binding_level->is_for_scope = 1;
@@ -1000,7 +1050,6 @@ poplevel (keep, reverse, functionbody)
Put it into forward order, just for cleanliness. */
tree decls;
int tmp = functionbody;
- int implicit_try_block = current_binding_level->parm_flag == 3;
int real_functionbody = current_binding_level->keep == 2
? ((functionbody = 0), tmp) : functionbody;
tree tags = functionbody >= 0 ? current_binding_level->tags : 0;
@@ -1012,41 +1061,11 @@ poplevel (keep, reverse, functionbody)
GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain,
current_binding_level->parm_flag,
- current_binding_level->keep,
- current_binding_level->tag_transparent);
+ current_binding_level->keep);
if (current_binding_level->keep == 1)
keep = 1;
- /* This warning is turned off because it causes warnings for
- declarations like `extern struct foo *x'. */
-#if 0
- /* Warn about incomplete structure types in this level. */
- for (link = tags; link; link = TREE_CHAIN (link))
- if (TYPE_SIZE (TREE_VALUE (link)) == NULL_TREE)
- {
- tree type = TREE_VALUE (link);
- char *errmsg;
- switch (TREE_CODE (type))
- {
- case RECORD_TYPE:
- errmsg = "`struct %s' incomplete in scope ending here";
- break;
- case UNION_TYPE:
- errmsg = "`union %s' incomplete in scope ending here";
- break;
- case ENUMERAL_TYPE:
- errmsg = "`enum %s' incomplete in scope ending here";
- break;
- }
- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- error (errmsg, IDENTIFIER_POINTER (TYPE_NAME (type)));
- else
- /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */
- error (errmsg, TYPE_NAME_STRING (type));
- }
-#endif /* 0 */
-
/* Get the decls in the order they were written.
Usually current_binding_level->names is in reverse order.
But parameter decls were previously put in forward order. */
@@ -1092,15 +1111,35 @@ poplevel (keep, reverse, functionbody)
block = make_node (BLOCK);
if (block != NULL_TREE)
{
- BLOCK_VARS (block) = decls;
- BLOCK_TYPE_TAGS (block) = tags;
- BLOCK_SUBBLOCKS (block) = subblocks;
- /* If we created the block earlier on, and we are just diddling it now,
- then it already should have a proper BLOCK_END_NOTE value associated
- with it, so avoid trashing that. Otherwise, for a new block, install
- a new BLOCK_END_NOTE value. */
- if (! block_previously_created)
- remember_end_note (block);
+ if (block_previously_created)
+ {
+ if (decls || tags || subblocks)
+ {
+ if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block))
+ {
+ warning ("internal compiler error: debugging info corrupted");
+ }
+ BLOCK_VARS (block) = decls;
+ BLOCK_TYPE_TAGS (block) = tags;
+
+ /* We can have previous subblocks and new subblocks when
+ doing fixup_gotos with complex cleanups. We chain the new
+ subblocks onto the end of any pre-existing subblocks. */
+ BLOCK_SUBBLOCKS (block) = chainon (BLOCK_SUBBLOCKS (block),
+ subblocks);
+ }
+ /* If we created the block earlier on, and we are just
+ diddling it now, then it already should have a proper
+ BLOCK_END_NOTE value associated with it. */
+ }
+ else
+ {
+ BLOCK_VARS (block) = decls;
+ BLOCK_TYPE_TAGS (block) = tags;
+ BLOCK_SUBBLOCKS (block) = subblocks;
+ /* Otherwise, for a new block, install a new BLOCK_END_NOTE value. */
+ remember_end_note (block);
+ }
}
/* In each subblock, record that this is its superior. */
@@ -1111,26 +1150,38 @@ poplevel (keep, reverse, functionbody)
/* Clear out the meanings of the local variables of this level. */
- for (link = current_binding_level->dead_vars_from_for;
- link != NULL_TREE; link = TREE_CHAIN (link))
- {
- if (DECL_DEAD_FOR_LOCAL (link))
- {
- tree id = DECL_NAME (link);
- if (IDENTIFIER_LOCAL_VALUE (id) == link)
- IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link);
- }
- }
-
if (current_binding_level->is_for_scope && flag_new_for_scope == 1)
{
+ struct binding_level *outer = current_binding_level->level_chain;
for (link = decls; link; link = TREE_CHAIN (link))
{
if (TREE_CODE (link) == VAR_DECL)
DECL_DEAD_FOR_LOCAL (link) = 1;
+ else
+ IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
+ }
+
+ /* Save declarations made in a 'for' statement so we can support pre-ANSI
+ 'for' scoping semantics. */
+
+ for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
+ {
+ tree id = TREE_PURPOSE (link);
+ tree decl = IDENTIFIER_LOCAL_VALUE (id);
+
+ if (decl && DECL_DEAD_FOR_LOCAL (decl))
+ {
+ /* In this case keep the dead for-decl visible,
+ but remember what (if anything) it shadowed. */
+ DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link);
+ TREE_CHAIN (decl) = outer->dead_vars_from_for;
+ outer->dead_vars_from_for = decl;
+ }
+ else
+ IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link);
}
}
- else
+ else /* Not special for scope. */
{
for (link = decls; link; link = TREE_CHAIN (link))
{
@@ -1148,50 +1199,42 @@ poplevel (keep, reverse, functionbody)
IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
}
}
- }
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
+ /* Restore all name-meanings of the outer levels
+ that were shadowed by this level. */
- if (current_binding_level->is_for_scope && flag_new_for_scope == 1)
- {
- struct binding_level *outer = current_binding_level->level_chain;
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
+ for (link = current_binding_level->shadowed;
+ link; link = TREE_CHAIN (link))
+ IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+
+ /* We first restore the regular decls and *then* the dead_vars_from_for
+ to handle this case:
+
+ int i; // i#1
+ {
+ for (int i; ; ) { ...} // i#2
+ int i; // i#3
+ } // we are here
+
+ In this case, we want remove the binding for i#3, restoring
+ that of i#2. Then we want to remove the binding for i#2,
+ and restore that of i#1. */
+
+ link = current_binding_level->dead_vars_from_for;
+ for (; link != NULL_TREE; link = TREE_CHAIN (link))
{
- tree id = TREE_PURPOSE (link);
- tree decl = IDENTIFIER_LOCAL_VALUE (id);
- if (DECL_DEAD_FOR_LOCAL (decl))
- DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link);
- else
- IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link);
+ tree id = DECL_NAME (link);
+ if (IDENTIFIER_LOCAL_VALUE (id) == link)
+ IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link);
}
- /* Save declarations made in a 'for' statement so we can support pre-ANSI
- 'for' scoping semantics. */
-
- /* We append the current names of for-variables to those from previous
- declarations, so that when we get around to do an poplevel
- on the OUTER level, we restore the any shadowed readl bindings.
- Note that the new names are put first on the combined list,
- so they get to be restored first. This is important if there are
- two for-loops using the same for-variable in the same block.
- The binding we really want restored is whatever binding was shadowed
- by the *first* for-variable, not the binding shadowed by the
- second for-variable (which would be the first for-variable). */
- outer->dead_vars_from_for
- = chainon (current_binding_level->names, outer->dead_vars_from_for);
+ for (link = current_binding_level->class_shadowed;
+ link; link = TREE_CHAIN (link))
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+ for (link = current_binding_level->type_shadowed;
+ link; link = TREE_CHAIN (link))
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
}
- else
- {
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- }
- for (link = current_binding_level->class_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->type_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
/* If the level being exited is the top level of a function,
check over all the labels. */
@@ -1238,12 +1281,12 @@ poplevel (keep, reverse, functionbody)
level_chain = current_binding_level->level_chain;
if (level_chain)
{
- tree labels;
- for (labels = named_label_uses; labels; labels = TREE_CHAIN (labels))
- if (TREE_TYPE (labels) == (tree)current_binding_level)
+ struct named_label_list *labels;
+ for (labels = named_label_uses; labels; labels = labels->next)
+ if (labels->binding_level == current_binding_level)
{
- TREE_TYPE (labels) = (tree)level_chain;
- TREE_PURPOSE (labels) = level_chain->names;
+ labels->binding_level = level_chain;
+ labels->names_in_scope = level_chain->names;
}
}
}
@@ -1277,11 +1320,6 @@ poplevel (keep, reverse, functionbody)
/* Take care of compiler's internal binding structures. */
if (tmp == 2)
{
-#if 0
- /* We did not call push_momentary for this
- binding contour, so there is nothing to pop. */
- pop_momentary ();
-#endif
expand_end_bindings (getdecls (), keep, 1);
/* Each and every BLOCK node created here in `poplevel' is important
(e.g. for proper debugging information) so if we created one
@@ -1299,31 +1337,6 @@ poplevel (keep, reverse, functionbody)
return block;
}
-/* Resume a binding level for a namespace. */
-void
-resume_level (b)
- struct binding_level *b;
-{
- tree decls, link;
-
- resume_binding_level (b);
-
- /* Resume the variable caches. */
- decls = current_binding_level->names;
-
- /* Restore the meanings of the local variables of this level. */
-
- for (link = decls; link; link = TREE_CHAIN (link))
- {
- if (DECL_NAME (link) != NULL_TREE)
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = link;
-
- /* If this is a TYPE_DECL, push it into the type value slot. */
- if (TREE_CODE (link) == TYPE_DECL)
- SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (link), TREE_TYPE (link));
- }
-}
-
/* Delete the node BLOCK from the current binding level.
This is used for the block inside a stmt expr ({...})
so that the block can be reinserted where appropriate. */
@@ -1361,15 +1374,6 @@ insert_block (block)
= chainon (current_binding_level->blocks, block);
}
-/* Add BLOCK to the current list of blocks for this binding contour. */
-void
-add_block_current_level (block)
- tree block;
-{
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
-}
-
/* Set the BLOCK node for the innermost scope
(the one we are currently in). */
@@ -1381,6 +1385,7 @@ set_block (block)
}
/* Do a pushlevel for class declarations. */
+
void
pushlevel_class ()
{
@@ -1398,8 +1403,7 @@ pushlevel_class ()
}
else
{
- /* Create a new `struct binding_level'. */
- newlevel = (struct binding_level *) xmalloc (sizeof (struct binding_level));
+ newlevel = make_binding_level ();
}
#if defined(DEBUG_CP_BINDING_LEVELS)
@@ -1423,6 +1427,7 @@ pushlevel_class ()
/* ...and a poplevel for class declarations. FORCE is used to force
clearing out of CLASS_VALUEs after a class definition. */
+
tree
poplevel_class (force)
int force;
@@ -1449,22 +1454,24 @@ poplevel_class (force)
else
/* Remember to save what IDENTIFIER's were bound in this scope so we
can recover from cache misses. */
- previous_class_values = class_binding_level->class_shadowed;
+ {
+ previous_class_type = current_class_type;
+ previous_class_values = class_binding_level->class_shadowed;
+ }
for (shadowed = level->type_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed));
GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
(HOST_WIDE_INT) class_binding_level->level_chain,
class_binding_level->parm_flag,
- class_binding_level->keep,
- class_binding_level->tag_transparent);
+ class_binding_level->keep);
if (class_binding_level->parm_flag != 2)
class_binding_level = (struct binding_level *)0;
- /* Now, pop out of the the binding level which we created up in the
+ /* Now, pop out of the binding level which we created up in the
`pushlevel_class' routine. */
#if defined(DEBUG_CP_BINDING_LEVELS)
is_class_level = 1;
@@ -1476,8 +1483,8 @@ poplevel_class (force)
}
/* For debugging. */
-int no_print_functions = 0;
-int no_print_builtins = 0;
+static int no_print_functions = 0;
+static int no_print_builtins = 0;
void
print_binding_level (lvl)
@@ -1502,11 +1509,11 @@ print_binding_level (lvl)
/* We can probably fit 3 names to a line? */
for (t = lvl->names; t; t = TREE_CHAIN (t))
{
- if (no_print_functions && (TREE_CODE(t) == FUNCTION_DECL))
+ if (no_print_functions && (TREE_CODE (t) == FUNCTION_DECL))
continue;
if (no_print_builtins
- && (TREE_CODE(t) == TYPE_DECL)
- && (!strcmp(DECL_SOURCE_FILE(t),"<built-in>")))
+ && (TREE_CODE (t) == TYPE_DECL)
+ && (!strcmp (DECL_SOURCE_FILE (t),"<built-in>")))
continue;
/* Function decls tend to have longer names. */
@@ -1521,7 +1528,7 @@ print_binding_level (lvl)
i = len;
}
print_node_brief (stderr, "", t, 0);
- if (TREE_CODE (t) == ERROR_MARK)
+ if (t == error_mark_node)
break;
}
if (i)
@@ -1585,17 +1592,7 @@ print_binding_level (lvl)
fprintf (stderr, " type-shadowed:");
for (t = lvl->type_shadowed; t; t = TREE_CHAIN (t))
{
-#if 0
- fprintf (stderr, "\n\t");
- print_node_brief (stderr, "<", TREE_PURPOSE (t), 0);
- if (TREE_VALUE (t))
- print_node_brief (stderr, " ", TREE_VALUE (t), 0);
- else
- fprintf (stderr, " (none)");
- fprintf (stderr, ">");
-#else
fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
-#endif
}
fprintf (stderr, "\n");
}
@@ -1643,148 +1640,247 @@ print_binding_stack ()
print_binding_level (global_binding_level);
}
-extern char * first_global_object_name;
+/* Namespace binding access routines: The namespace_bindings field of
+ the identifier is polymorphic, with three possible values:
+ NULL_TREE, a list of CPLUS_BINDINGS, or any other tree_node
+ indicating the BINDING_VALUE of global_namespace. */
+
+/* Check whether the a binding for the name to scope is known.
+ Assumes that the bindings of the name are already a list
+ of bindings. Returns the binding found, or NULL_TREE. */
-/* Get a unique name for each call to this routine for unnamed namespaces.
- Mostly copied from get_file_function_name. */
static tree
-get_unique_name ()
+find_binding (name, scope)
+ tree name;
+ tree scope;
{
- static int temp_name_counter = 0;
- char *buf;
- register char *p;
-
- if (first_global_object_name)
- p = first_global_object_name;
- else if (main_input_filename)
- p = main_input_filename;
- else
- p = input_filename;
+ tree iter, prev = NULL_TREE;
-#define UNNAMED_NAMESPACE_FORMAT "__%s_%d"
+ scope = ORIGINAL_NAMESPACE (scope);
+
+ for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter;
+ iter = TREE_CHAIN (iter))
+ {
+ my_friendly_assert (TREE_CODE (iter) == CPLUS_BINDING, 374);
+ if (BINDING_SCOPE (iter) == scope)
+ {
+ /* Move binding found to the fron of the list, so
+ subsequent lookups will find it faster. */
+ if (prev)
+ {
+ TREE_CHAIN (prev) = TREE_CHAIN (iter);
+ TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
+ }
+ return iter;
+ }
+ prev = iter;
+ }
+ return NULL_TREE;
+}
- buf = (char *) alloca (sizeof (UNNAMED_NAMESPACE_FORMAT) + strlen (p));
+/* Always returns a binding for name in scope. If the
+ namespace_bindings is not a list, convert it to one first.
+ If no binding is found, make a new one. */
- sprintf (buf, UNNAMED_NAMESPACE_FORMAT, p, temp_name_counter++);
+tree
+binding_for_name (name, scope)
+ tree name;
+ tree scope;
+{
+ tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ tree result;
- /* Don't need to pull weird characters out of global names. */
- if (p != first_global_object_name)
+ scope = ORIGINAL_NAMESPACE (scope);
+
+ if (b && TREE_CODE (b) != CPLUS_BINDING)
{
- for (p = buf+11; *p; p++)
- if (! ((*p >= '0' && *p <= '9')
-#if 0 /* we always want labels, which are valid C++ identifiers (+ `$') */
-#ifndef ASM_IDENTIFY_GCC /* this is required if `.' is invalid -- k. raeburn */
- || *p == '.'
-#endif
-#endif
-#ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */
- || *p == '$'
-#endif
-#ifndef NO_DOT_IN_LABEL /* this for `.'; unlikely, but... */
- || *p == '.'
-#endif
- || (*p >= 'A' && *p <= 'Z')
- || (*p >= 'a' && *p <= 'z')))
- *p = '_';
+ /* Get rid of optimization for global scope. */
+ IDENTIFIER_NAMESPACE_BINDINGS (name) = NULL_TREE;
+ BINDING_VALUE (binding_for_name (name, global_namespace)) = b;
+ b = IDENTIFIER_NAMESPACE_BINDINGS (name);
}
+ if (b && (result = find_binding (name, scope)))
+ return result;
+ /* Not found, make a new permanent one. */
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ result = make_node (CPLUS_BINDING);
+ TREE_CHAIN (result) = b;
+ IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
+ BINDING_SCOPE (result) = scope;
+ BINDING_TYPE (result) = NULL_TREE;
+ BINDING_VALUE (result) = NULL_TREE;
+ pop_obstacks ();
+ return result;
+}
- return get_identifier (buf);
+/* Return the binding value for name in scope, considering that
+ namespace_binding may or may not be a list of CPLUS_BINDINGS. */
+
+tree
+namespace_binding (name, scope)
+ tree name;
+ tree scope;
+{
+ tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ if (b == NULL_TREE)
+ return NULL_TREE;
+ if (scope == NULL_TREE)
+ scope = global_namespace;
+ if (TREE_CODE (b) != CPLUS_BINDING)
+ return (scope == global_namespace) ? b : NULL_TREE;
+ name = find_binding (name,scope);
+ if (name == NULL_TREE)
+ return name;
+ return BINDING_VALUE (name);
}
-/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we
- select a name that is unique to this compilation unit. */
+/* Set the binding value for name in scope. If modifying the binding
+ of global_namespace is attempted, try to optimize it. */
+
void
-push_namespace (name)
+set_namespace_binding (name, scope, val)
tree name;
+ tree scope;
+ tree val;
{
- extern tree current_namespace;
- tree old_id = get_namespace_id ();
- char *buf;
- tree d = make_node (NAMESPACE_DECL);
+ tree b;
- if (! name)
+ if (scope == NULL_TREE)
+ scope = global_namespace;
+
+ if (scope == global_namespace)
{
- /* Create a truly ugly name! */
- name = get_unique_name ();
+ b = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ if (b == NULL_TREE || TREE_CODE (b) != CPLUS_BINDING)
+ {
+ IDENTIFIER_NAMESPACE_BINDINGS (name) = val;
+ return;
+ }
}
+ b = binding_for_name (name, scope);
+ BINDING_VALUE (b) = val;
+}
- DECL_NAME (d) = name;
- DECL_ASSEMBLER_NAME (d) = name;
- /* pushdecl wants to check the size of it to see if it is incomplete... */
- TREE_TYPE (d) = void_type_node;
- /* Mark them as external, so redeclaration_error_message doesn't think
- they are duplicates. */
- DECL_EXTERNAL (d) = 1;
- d = pushdecl (d);
+/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we
+ select a name that is unique to this compilation unit. */
- if (NAMESPACE_LEVEL (d) == 0)
- {
- /* This is new for this compilation unit. */
- pushlevel (0);
- declare_namespace_level ();
- NAMESPACE_LEVEL (d) = (tree)current_binding_level;
+void
+push_namespace (name)
+ tree name;
+{
+ tree d;
+ int need_new = 1;
+ int implicit_use = 0;
+ int global = 0;
+ if (!global_namespace)
+ {
+ /* This must be ::. */
+ my_friendly_assert (name == get_identifier ("::"), 377);
+ global = 1;
+ }
+ else if (!name)
+ {
+ /* The name of anonymous namespace is unique for the translation
+ unit. */
+ static tree anon_name = NULL_TREE;
+ if (!anon_name)
+ anon_name = get_file_function_name ('N');
+ name = anon_name;
+ d = IDENTIFIER_NAMESPACE_VALUE (name);
+ if (d)
+ /* Reopening anonymous namespace. */
+ need_new = 0;
+ implicit_use = 1;
+ }
+ else if (current_namespace == global_namespace
+ && name == DECL_NAME (std_node))
+ {
+ in_std++;
+ return;
}
else
{
- resume_level ((struct binding_level*)NAMESPACE_LEVEL (d));
+ /* Check whether this is an extended namespace definition. */
+ d = IDENTIFIER_NAMESPACE_VALUE (name);
+ if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
+ {
+ need_new = 0;
+ if (DECL_NAMESPACE_ALIAS (d))
+ {
+ cp_error ("namespace alias `%D' not allowed here, assuming `%D'",
+ d, DECL_NAMESPACE_ALIAS (d));
+ d = DECL_NAMESPACE_ALIAS (d);
+ }
+ }
+ }
+
+ if (need_new)
+ {
+ /* Make a new namespace, binding the name to it. */
+ d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
+ /* The global namespace is not pushed, and the global binding
+ level is set elsewhere. */
+ if (!global)
+ {
+ d = pushdecl (d);
+ pushlevel (0);
+ declare_namespace_level ();
+ NAMESPACE_LEVEL (d) = current_binding_level;
+ }
}
+ else
+ resume_binding_level (NAMESPACE_LEVEL (d));
- /* This code is just is bit old now... */
- current_namespace = tree_cons (NULL_TREE, name, current_namespace);
- buf = (char *) alloca (4 + (old_id ? IDENTIFIER_LENGTH (old_id) : 0)
- + IDENTIFIER_LENGTH (name));
- sprintf (buf, "%s%s", old_id ? IDENTIFIER_POINTER (old_id) : "",
- IDENTIFIER_POINTER (name));
- TREE_PURPOSE (current_namespace) = get_identifier (buf);
+ if (implicit_use)
+ do_using_directive (d);
+ /* Enter the name space. */
+ current_namespace = d;
}
/* Pop from the scope of the current namespace. */
+
void
pop_namespace ()
{
- extern tree current_namespace;
- tree decls, link;
- current_namespace = TREE_CHAIN (current_namespace);
-
- /* Just in case we get out of sync. */
- if (! namespace_bindings_p ())
- poplevel (0, 0, 0);
+ if (current_namespace == global_namespace)
+ {
+ my_friendly_assert (in_std>0, 980421);
+ in_std--;
+ return;
+ }
+ current_namespace = CP_DECL_CONTEXT (current_namespace);
+ /* The binding level is not popped, as it might be re-opened later. */
+ suspend_binding_level ();
+}
- decls = current_binding_level->names;
+/* Concatenate the binding levels of all namespaces. */
- /* Clear out the meanings of the local variables of this level. */
+void
+cat_namespace_levels()
+{
+ tree current;
+ tree last;
+ struct binding_level *b;
- for (link = decls; link; link = TREE_CHAIN (link))
+ last = NAMESPACE_LEVEL (global_namespace) -> names;
+ /* The nested namespaces appear in the names list of their ancestors. */
+ for (current = last; current; current = TREE_CHAIN (current))
{
- if (DECL_NAME (link) != NULL_TREE)
+ if (TREE_CODE (current) != NAMESPACE_DECL
+ || DECL_NAMESPACE_ALIAS (current))
+ continue;
+ if (!DECL_LANG_SPECIFIC (current))
{
- /* If the ident. was used or addressed via a local extern decl,
- don't forget that fact. */
- if (DECL_EXTERNAL (link))
- {
- if (TREE_USED (link))
- TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1;
- if (TREE_ADDRESSABLE (link))
- TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
- }
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
+ /* Hmm. std. */
+ my_friendly_assert (current == std_node, 393);
+ continue;
}
+ b = NAMESPACE_LEVEL (current);
+ while (TREE_CHAIN (last))
+ last = TREE_CHAIN (last);
+ TREE_CHAIN (last) = NAMESPACE_LEVEL (current) -> names;
}
-
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
-
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->class_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->type_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-
- /* suspend a level. */
- suspend_binding_level ();
}
/* Subroutines for reverting temporarily to top-level for instantiation
@@ -1795,107 +1891,166 @@ pop_namespace ()
struct saved_scope {
struct binding_level *old_binding_level;
tree old_bindings;
+ tree old_namespace;
struct saved_scope *prev;
tree class_name, class_type, function_decl;
- tree base_init_list, member_init_list;
struct binding_level *class_bindings;
- tree previous_class_type;
tree *lang_base, *lang_stack, lang_name;
int lang_stacksize;
- tree named_labels;
+ int minimal_parse_mode;
+ tree last_function_parms;
+ tree template_parms;
+ HOST_WIDE_INT processing_template_decl;
+ tree previous_class_type, previous_class_values;
+ int processing_specialization;
+ int processing_explicit_instantiation;
};
static struct saved_scope *current_saved_scope;
-extern tree prev_class_type;
+
+/* A chain of the binding vecs created by store_bindings. We create a
+ whole bunch of these during compilation, on permanent_obstack, so we
+ can't just throw them away. */
+static tree free_binding_vecs;
+
+static tree
+store_bindings (names, old_bindings)
+ tree names, old_bindings;
+{
+ tree t;
+ for (t = names; t; t = TREE_CHAIN (t))
+ {
+ tree binding, t1, id;
+
+ if (TREE_CODE (t) == TREE_LIST)
+ id = TREE_PURPOSE (t);
+ else
+ id = DECL_NAME (t);
+
+ if (!id
+ || (!IDENTIFIER_LOCAL_VALUE (id)
+ && !IDENTIFIER_CLASS_VALUE (id)))
+ continue;
+
+ for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
+ if (TREE_VEC_ELT (t1, 0) == id)
+ goto skip_it;
+
+ if (free_binding_vecs)
+ {
+ binding = free_binding_vecs;
+ free_binding_vecs = TREE_CHAIN (free_binding_vecs);
+ }
+ else
+ binding = make_tree_vec (4);
+
+ if (id)
+ {
+ my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
+ TREE_VEC_ELT (binding, 0) = id;
+ TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
+ TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
+ TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
+ IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
+ IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
+ }
+ TREE_CHAIN (binding) = old_bindings;
+ old_bindings = binding;
+ skip_it:
+ ;
+ }
+ return old_bindings;
+}
void
-push_to_top_level ()
+maybe_push_to_top_level (pseudo)
+ int pseudo;
{
extern int current_lang_stacksize;
- struct saved_scope *s =
- (struct saved_scope *) xmalloc (sizeof (struct saved_scope));
- struct binding_level *b = current_binding_level;
+ struct saved_scope *s
+ = (struct saved_scope *) xmalloc (sizeof (struct saved_scope));
+ struct binding_level *b = inner_binding_level;
tree old_bindings = NULL_TREE;
+ if (current_function_decl)
+ push_cp_function_context (NULL_TREE);
+
+ if (previous_class_type)
+ old_bindings = store_bindings (previous_class_values, old_bindings);
+
/* Have to include global_binding_level, because class-level decls
aren't listed anywhere useful. */
for (; b; b = b->level_chain)
{
tree t;
- if (b == global_binding_level)
- continue;
-
- for (t = b->names; t; t = TREE_CHAIN (t))
- {
- tree binding, t1, t2 = t;
- tree id = DECL_ASSEMBLER_NAME (t2);
+ /* Template IDs are inserted into the global level. If they were
+ inserted into namespace level, finish_file wouldn't find them
+ when doing pending instantiations. Therefore, don't stop at
+ namespace level, but continue until :: . */
+ if (b == global_binding_level || (pseudo && b->pseudo_global))
+ break;
- if (!id
- || (!IDENTIFIER_LOCAL_VALUE (id)
- && !IDENTIFIER_CLASS_VALUE (id)))
- continue;
+ old_bindings = store_bindings (b->names, old_bindings);
+ /* We also need to check class_shadowed to save class-level type
+ bindings, since pushclass doesn't fill in b->names. */
+ if (b->parm_flag == 2)
+ old_bindings = store_bindings (b->class_shadowed, old_bindings);
- for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
- if (TREE_VEC_ELT (t1, 0) == id)
- goto skip_it;
-
- binding = make_tree_vec (4);
- if (id)
- {
- my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
- TREE_VEC_ELT (binding, 0) = id;
- TREE_VEC_ELT (binding, 1) = IDENTIFIER_TYPE_VALUE (id);
- TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
- TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
- IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
- IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
- }
- TREE_CHAIN (binding) = old_bindings;
- old_bindings = binding;
- skip_it:
- ;
- }
/* Unwind type-value slots back to top level. */
for (t = b->type_shadowed; t; t = TREE_CHAIN (t))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t));
}
- /* Clear out class-level bindings cache. */
- if (current_binding_level == global_binding_level
- && previous_class_type != NULL_TREE)
- {
- popclass (-1);
- previous_class_type = NULL_TREE;
- }
s->old_binding_level = current_binding_level;
- current_binding_level = global_binding_level;
+ current_binding_level = b;
+ s->old_namespace = current_namespace;
s->class_name = current_class_name;
s->class_type = current_class_type;
s->function_decl = current_function_decl;
- s->base_init_list = current_base_init_list;
- s->member_init_list = current_member_init_list;
s->class_bindings = class_binding_level;
- s->previous_class_type = previous_class_type;
s->lang_stack = current_lang_stack;
s->lang_base = current_lang_base;
s->lang_stacksize = current_lang_stacksize;
s->lang_name = current_lang_name;
- s->named_labels = named_labels;
+ s->minimal_parse_mode = minimal_parse_mode;
+ s->last_function_parms = last_function_parms;
+ s->template_parms = current_template_parms;
+ s->processing_template_decl = processing_template_decl;
+ s->previous_class_type = previous_class_type;
+ s->previous_class_values = previous_class_values;
+ s->processing_specialization = processing_specialization;
+ s->processing_explicit_instantiation = processing_explicit_instantiation;
+
current_class_name = current_class_type = NULL_TREE;
current_function_decl = NULL_TREE;
class_binding_level = (struct binding_level *)0;
- previous_class_type = NULL_TREE;
current_lang_stacksize = 10;
current_lang_stack = current_lang_base
= (tree *) xmalloc (current_lang_stacksize * sizeof (tree));
current_lang_name = lang_name_cplusplus;
strict_prototype = strict_prototypes_lang_cplusplus;
named_labels = NULL_TREE;
+ shadowed_labels = NULL_TREE;
+ minimal_parse_mode = 0;
+ previous_class_type = previous_class_values = NULL_TREE;
+ processing_specialization = 0;
+ processing_explicit_instantiation = 0;
+ current_template_parms = NULL_TREE;
+ processing_template_decl = 0;
+ current_namespace = global_namespace;
s->prev = current_saved_scope;
s->old_bindings = old_bindings;
current_saved_scope = s;
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+}
+
+void
+push_to_top_level ()
+{
+ maybe_push_to_top_level (0);
}
void
@@ -1905,28 +2060,36 @@ pop_from_top_level ()
struct saved_scope *s = current_saved_scope;
tree t;
+ /* Clear out class-level bindings cache. */
if (previous_class_type)
- previous_class_type = NULL_TREE;
+ {
+ popclass (-1);
+ previous_class_type = NULL_TREE;
+ }
+
+ pop_obstacks ();
current_binding_level = s->old_binding_level;
current_saved_scope = s->prev;
- for (t = s->old_bindings; t; t = TREE_CHAIN (t))
+ for (t = s->old_bindings; t; )
{
+ tree save = t;
tree id = TREE_VEC_ELT (t, 0);
if (id)
{
- IDENTIFIER_TYPE_VALUE (id) = TREE_VEC_ELT (t, 1);
+ SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
IDENTIFIER_LOCAL_VALUE (id) = TREE_VEC_ELT (t, 2);
IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
}
+ t = TREE_CHAIN (t);
+ TREE_CHAIN (save) = free_binding_vecs;
+ free_binding_vecs = save;
}
+ current_namespace = s->old_namespace;
current_class_name = s->class_name;
current_class_type = s->class_type;
- current_base_init_list = s->base_init_list;
- current_member_init_list = s->member_init_list;
current_function_decl = s->function_decl;
class_binding_level = s->class_bindings;
- previous_class_type = s->previous_class_type;
free (current_lang_base);
current_lang_base = s->lang_base;
current_lang_stack = s->lang_stack;
@@ -1936,9 +2099,19 @@ pop_from_top_level ()
strict_prototype = strict_prototypes_lang_cplusplus;
else if (current_lang_name == lang_name_c)
strict_prototype = strict_prototypes_lang_c;
- named_labels = s->named_labels;
+ minimal_parse_mode = s->minimal_parse_mode;
+ last_function_parms = s->last_function_parms;
+ current_template_parms = s->template_parms;
+ processing_template_decl = s->processing_template_decl;
+ previous_class_type = s->previous_class_type;
+ previous_class_values = s->previous_class_values;
+ processing_specialization = s->processing_specialization;
+ processing_explicit_instantiation = s->processing_explicit_instantiation;
free (s);
+
+ if (current_function_decl)
+ pop_cp_function_context (NULL_TREE);
}
/* Push a definition of struct, union or enum tag "name".
@@ -1948,7 +2121,7 @@ pop_from_top_level ()
Note that the definition may really be just a forward reference.
In that case, the TYPE_SIZE will be a NULL_TREE.
- C++ gratuitously puts all these tags in the name space. */
+ C++ gratuitously puts all these tags in the name space. */
/* When setting the IDENTIFIER_TYPE_VALUE field of an identifier ID,
record the shadowed value for this binding contour. TYPE is
@@ -1960,16 +2133,25 @@ set_identifier_type_value_with_scope (id, type, b)
tree type;
struct binding_level *b;
{
- if (b != global_binding_level)
+ if (!b->namespace_p)
{
- tree old_type_value = IDENTIFIER_TYPE_VALUE (id);
+ /* Shadow the marker, not the real thing, so that the marker
+ gets restored later. */
+ tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
b->type_shadowed
= tree_cons (id, old_type_value, b->type_shadowed);
}
+ else
+ {
+ tree binding = binding_for_name (id, current_namespace);
+ BINDING_TYPE (binding) = type;
+ /* Store marker instead of real type. */
+ type = global_type_node;
+ }
SET_IDENTIFIER_TYPE_VALUE (id, type);
}
-/* As set_identifier_type_value_with_scope, but using inner_binding_level. */
+/* As set_identifier_type_value_with_scope, but using inner_binding_level. */
void
set_identifier_type_value (id, type)
@@ -1979,59 +2161,50 @@ set_identifier_type_value (id, type)
set_identifier_type_value_with_scope (id, type, inner_binding_level);
}
-/* Subroutine "set_nested_typename" builds the nested-typename of
- the type decl in question. (Argument CLASSNAME can actually be
- a function as well, if that's the smallest containing scope.) */
-
static void
-set_nested_typename (decl, classname, name, type)
- tree decl, classname, name, type;
+set_identifier_local_value_with_scope (id, val, b)
+ tree id, val;
+ struct binding_level *b;
{
- char *buf;
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136);
+ tree oldlocal;
+ my_friendly_assert (! b->namespace_p, 980716);
- /* No need to do this for anonymous names, since they're unique. */
- if (ANON_AGGRNAME_P (name))
- {
- DECL_NESTED_TYPENAME (decl) = name;
- return;
- }
+ oldlocal = IDENTIFIER_LOCAL_VALUE (id);
+ b->shadowed = tree_cons (id, oldlocal, b->shadowed);
+ IDENTIFIER_LOCAL_VALUE (id) = val;
+}
- if (classname == NULL_TREE)
- classname = get_identifier ("");
+void
+set_identifier_local_value (id, val)
+ tree id, val;
+{
+ set_identifier_local_value_with_scope (id, val, current_binding_level);
+}
- my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137);
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138);
- buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname)
- + IDENTIFIER_LENGTH (name));
- sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname),
- IDENTIFIER_POINTER (name));
- DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
- TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1;
+/* Return the type associated with id. */
- /* Create an extra decl so that the nested name will have a type value
- where appropriate. */
- {
- tree nested, type_decl;
- nested = DECL_NESTED_TYPENAME (decl);
- type_decl = build_decl (TYPE_DECL, nested, type);
- DECL_NESTED_TYPENAME (type_decl) = nested;
- SET_DECL_ARTIFICIAL (type_decl);
- /* Mark the TYPE_DECL node created just above as a gratuitous one so that
- dwarfout.c will know not to generate a TAG_typedef DIE for it, and
- sdbout.c won't try to output a .def for "::foo". */
- DECL_IGNORED_P (type_decl) = 1;
-
- /* Remove this when local classes are fixed. */
- SET_IDENTIFIER_TYPE_VALUE (nested, type);
-
- pushdecl_nonclass_level (type_decl);
- }
+tree
+identifier_type_value (id)
+ tree id;
+{
+ /* There is no type with that name, anywhere. */
+ if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)
+ return NULL_TREE;
+ /* This is not the type marker, but the real thing. */
+ if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node)
+ return REAL_IDENTIFIER_TYPE_VALUE (id);
+ /* Have to search for it. It must be on the global level, now.
+ Ask lookup_name not to return non-types. */
+ id = lookup_name_real (id, 2, 1, 0);
+ if (id)
+ return TREE_TYPE (id);
+ return NULL_TREE;
}
/* Pop off extraneous binding levels left over due to syntax errors.
We don't pop past namespaces, as they might be valid. */
+
void
pop_everything ()
{
@@ -2050,41 +2223,10 @@ pop_everything ()
#endif
}
-#if 0 /* not yet, should get fixed properly later */
-/* Create a TYPE_DECL node with the correct DECL_ASSEMBLER_NAME.
- Other routines shouldn't use build_decl directly; they'll produce
- incorrect results with `-g' unless they duplicate this code.
-
- This is currently needed mainly for dbxout.c, but we can make
- use of it in method.c later as well. */
-tree
-make_type_decl (name, type)
- tree name, type;
-{
- tree decl, id;
- decl = build_decl (TYPE_DECL, name, type);
- if (TYPE_NAME (type) == name)
- /* Class/union/enum definition, or a redundant typedef for same. */
- {
- id = get_identifier (build_overload_name (type, 1, 1));
- DECL_ASSEMBLER_NAME (decl) = id;
- }
- else if (TYPE_NAME (type) != NULL_TREE)
- /* Explicit typedef, or implicit typedef for template expansion. */
- DECL_ASSEMBLER_NAME (decl) = DECL_ASSEMBLER_NAME (TYPE_NAME (type));
- else
- {
- /* XXX: Typedef for unnamed struct; some other situations.
- TYPE_NAME is null; what's right here? */
- }
- return decl;
-}
-#endif
-
/* Push a tag name NAME for struct/class/union/enum type TYPE.
- Normally put into into the inner-most non-tag-transparent scope,
+ Normally put it into the inner-most non-tag-transparent scope,
but if GLOBALIZE is true, put it in the inner-most non-class scope.
- The latter is needed for implicit declarations. */
+ The latter is needed for implicit declarations. */
void
pushtag (name, type, globalize)
@@ -2108,117 +2250,124 @@ pushtag (name, type, globalize)
if (name)
{
context = type ? TYPE_CONTEXT (type) : NULL_TREE;
- if (! context && ! globalize)
- context = current_scope ();
+ if (! context)
+ {
+ tree cs = current_scope ();
+
+ if (! globalize)
+ context = cs;
+ else if (cs != NULL_TREE
+ && TREE_CODE_CLASS (TREE_CODE (cs)) == 't')
+ /* When declaring a friend class of a local class, we want
+ to inject the newly named class into the scope
+ containing the local class, not the namespace scope. */
+ context = hack_decl_function_context (get_type_decl (cs));
+ }
if (context)
c_decl = TREE_CODE (context) == FUNCTION_DECL
? context : TYPE_MAIN_DECL (context);
-#if 0
- /* Record the identifier as the type's name if it has none. */
- if (TYPE_NAME (type) == NULL_TREE)
- TYPE_NAME (type) = name;
-#endif
-
+ if (!context)
+ context = current_namespace;
+
/* Do C++ gratuitous typedefing. */
if (IDENTIFIER_TYPE_VALUE (name) != type)
{
- register tree d;
- int newdecl = 0;
-
- if (b->parm_flag != 2
- || TYPE_SIZE (current_class_type) != NULL_TREE)
- {
- d = lookup_nested_type (type, c_decl);
+ register tree d = NULL_TREE;
+ int newdecl = 0, in_class = 0;
- if (d == NULL_TREE)
- {
- newdecl = 1;
-#if 0 /* not yet, should get fixed properly later */
- 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
- if (write_symbols == DWARF_DEBUG)
- {
- /* Mark the TYPE_DECL node we created just above as an
- gratuitous one. We need to do this so that dwarfout.c
- will understand that it is not supposed to output a
- TAG_typedef DIE for it. */
- DECL_IGNORED_P (d) = 1;
- }
-#endif /* DWARF_DEBUGGING_INFO */
- set_identifier_type_value_with_scope (name, type, b);
- }
- else
- d = TYPE_NAME (d);
-
- TYPE_NAME (type) = d;
-
- /* If it is anonymous, then we are called from pushdecl,
- and we don't want to infinitely recurse. */
- if (! ANON_AGGRNAME_P (name))
- {
- if (b->parm_flag == 2)
- d = pushdecl_class_level (d);
- else
- d = pushdecl_with_scope (d, b);
- }
- }
+ if ((b->pseudo_global && b->level_chain->parm_flag == 2)
+ || b->parm_flag == 2)
+ in_class = 1;
else
+ d = lookup_nested_type (type, c_decl);
+
+ if (d == NULL_TREE)
{
- /* Make nested declarations go into class-level scope. */
newdecl = 1;
d = build_decl (TYPE_DECL, name, type);
+ if (current_lang_name == lang_name_java)
+ TYPE_FOR_JAVA (type) = 1;
SET_DECL_ARTIFICIAL (d);
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG)
+ if (! in_class)
+ set_identifier_type_value_with_scope (name, type, b);
+ }
+ else
+ d = TYPE_MAIN_DECL (d);
+
+ TYPE_NAME (type) = d;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
+
+ if (processing_template_parmlist)
+ /* You can't declare a new template type in a template
+ parameter list. But, you can declare a non-template
+ type:
+
+ template <class A*> struct S;
+
+ is a forward-declaration of `A'. */
+ ;
+ else if (IS_AGGR_TYPE (type)
+ && (/* If !GLOBALIZE then we are looking at a
+ definition. It may not be a primary template.
+ (For example, in:
+
+ template <class T>
+ struct S1 { class S2 {}; }
+
+ we have to push_template_decl for S2.) */
+ (processing_template_decl && !globalize)
+ /* If we are declaring a friend template class, we
+ will have GLOBALIZE set, since something like:
+
+ template <class T>
+ struct S1 {
+ template <class U>
+ friend class S2;
+ };
+
+ declares S2 to be at global scope. */
+ || (processing_template_decl >
+ template_class_depth (current_class_type))))
+ {
+ d = push_template_decl_real (d, globalize);
+ /* If the current binding level is the binding level for
+ the template parameters (see the comment in
+ begin_template_parm_list) and the enclosing level is
+ a class scope, and we're not looking at a friend,
+ push the declaration of the member class into the
+ class scope. In the friend case, push_template_decl
+ will already have put the friend into global scope,
+ if appropriate. */
+ if (!globalize && b->pseudo_global &&
+ b->level_chain->parm_flag == 2)
{
- /* Mark the TYPE_DECL node we created just above as an
- gratuitous one. We need to do this so that dwarfout.c
- will understand that it is not supposed to output a
- TAG_typedef DIE for it. */
- DECL_IGNORED_P (d) = 1;
+ pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
+ b->level_chain);
+ /* Put this tag on the list of tags for the class,
+ since that won't happen below because B is not
+ the class binding level, but is instead the
+ pseudo-global level. */
+ b->level_chain->tags =
+ saveable_tree_cons (name, type, b->level_chain->tags);
+ TREE_NONLOCAL_FLAG (type) = 1;
+ if (TYPE_SIZE (current_class_type) == NULL_TREE)
+ CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
}
-#endif /* DWARF_DEBUGGING_INFO */
+ }
- TYPE_MAIN_DECL (type) = d;
+ if (b->parm_flag == 2)
+ d = pushdecl_class_level (d);
+ else
+ d = pushdecl_with_scope (d, b);
- /* Make sure we're in this type's scope when we push the
- decl for a template, otherwise class_binding_level will
- be NULL and we'll end up dying inside of
- push_class_level_binding. */
- if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
- pushclass (type, 0);
- d = pushdecl_class_level (d);
- if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
- popclass (0);
- }
if (newdecl)
{
- if (write_symbols != DWARF_DEBUG)
- {
- if (ANON_AGGRNAME_P (name))
- DECL_IGNORED_P (d) = 1;
- }
+ if (ANON_AGGRNAME_P (name))
+ DECL_IGNORED_P (d) = 1;
- if (context == NULL_TREE)
- /* Non-nested class. */
- set_nested_typename (d, NULL_TREE, name, type);
- else if (context && TREE_CODE (context) == FUNCTION_DECL)
- /* Function-nested class. */
- set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl),
- name, type);
- else /* if (context && IS_AGGR_TYPE (context)) */
- /* Class-nested class. */
- set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl),
- name, type);
-
- DECL_CONTEXT (d) = context;
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
+ DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
DECL_ASSEMBLER_NAME (d)
= get_identifier (build_overload_name (type, 1, 1));
}
@@ -2244,20 +2393,18 @@ pushtag (name, type, globalize)
convenient place to record the "scope start" address for
the tagged type. */
-#if 0 /* not yet, should get fixed properly later */
- tree d = make_type_decl (NULL_TREE, type);
-#else
tree d = build_decl (TYPE_DECL, NULL_TREE, type);
-#endif
TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
}
}
/* Counter used to create anonymous type names. */
+
static int anon_cnt = 0;
/* Return an IDENTIFIER which can be used as a name for
anonymous structs and unions. */
+
tree
make_anon_name ()
{
@@ -2269,6 +2416,7 @@ make_anon_name ()
/* Clear the TREE_PURPOSE slot of tags which have anonymous typenames.
This keeps dbxout from getting confused. */
+
void
clear_anon_tags ()
{
@@ -2303,6 +2451,7 @@ clear_anon_tags ()
For C++, we must compare the parameter list so that `int' can match
`int&' in a parameter position, but `int&' is not confused with
`const int&'. */
+
int
decls_match (newdecl, olddecl)
tree newdecl, olddecl;
@@ -2317,6 +2466,11 @@ decls_match (newdecl, olddecl)
tree p1 = TYPE_ARG_TYPES (f1);
tree p2 = TYPE_ARG_TYPES (f2);
+ if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl)
+ && ! (DECL_LANGUAGE (newdecl) == lang_c
+ && DECL_LANGUAGE (olddecl) == lang_c))
+ return 0;
+
/* When we parse a static member function definition,
we put together a FUNCTION_DECL which thinks its type
is METHOD_TYPE. Change that to FUNCTION_TYPE, and
@@ -2364,33 +2518,15 @@ decls_match (newdecl, olddecl)
else if (TREE_CODE (newdecl) == TEMPLATE_DECL
&& TREE_CODE (olddecl) == TEMPLATE_DECL)
{
- tree newargs = DECL_TEMPLATE_PARMS (newdecl);
- tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
- int i, len = TREE_VEC_LENGTH (newargs);
-
- if (TREE_VEC_LENGTH (oldargs) != len)
- return 0;
-
- for (i = 0; i < len; i++)
- {
- tree newarg = TREE_VALUE (TREE_VEC_ELT (newargs, i));
- tree oldarg = TREE_VALUE (TREE_VEC_ELT (oldargs, i));
- if (TREE_CODE (newarg) != TREE_CODE (oldarg))
- return 0;
- else if (TREE_CODE (newarg) == TYPE_DECL)
- /* continue */;
- else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
- return 0;
- }
-
- if (DECL_TEMPLATE_IS_CLASS (newdecl)
- != DECL_TEMPLATE_IS_CLASS (olddecl))
- types_match = 0;
- else if (DECL_TEMPLATE_IS_CLASS (newdecl))
- types_match = 1;
- else
- types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
- DECL_TEMPLATE_RESULT (newdecl));
+ if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
+ DECL_TEMPLATE_PARMS (olddecl)))
+ return 0;
+
+ if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
+ types_match = 1;
+ else
+ types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
+ DECL_TEMPLATE_RESULT (newdecl));
}
else
{
@@ -2400,8 +2536,20 @@ decls_match (newdecl, olddecl)
types_match = TREE_TYPE (newdecl) == NULL_TREE;
else if (TREE_TYPE (newdecl) == NULL_TREE)
types_match = 0;
+ /* Qualifiers must match, and they may be present on either, the type
+ or the decl. */
+ else if ((TREE_READONLY (newdecl)
+ || TYPE_READONLY (TREE_TYPE (newdecl)))
+ == (TREE_READONLY (olddecl)
+ || TYPE_READONLY (TREE_TYPE (olddecl)))
+ && (TREE_THIS_VOLATILE (newdecl)
+ || TYPE_VOLATILE (TREE_TYPE (newdecl)))
+ == (TREE_THIS_VOLATILE (olddecl)
+ || TYPE_VOLATILE (TREE_TYPE (olddecl))))
+ types_match = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (newdecl)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)), 1);
else
- types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1);
+ types_match = 0;
}
return types_match;
@@ -2414,9 +2562,6 @@ decls_match (newdecl, olddecl)
Note that this does not apply to the C++ case of declaring
a variable `extern const' and then later `const'.
- Don't complain if -traditional, since traditional compilers
- don't complain.
-
Don't complain about built-in functions, since they are beyond
the user's control. */
@@ -2431,8 +2576,7 @@ warn_extern_redeclared_static (newdecl, olddecl)
static char *implicit_extern_static_warning
= "`%D' was declared implicitly `extern' and later `static'";
- if (flag_traditional
- || TREE_CODE (newdecl) == TYPE_DECL)
+ if (TREE_CODE (newdecl) == TYPE_DECL)
return;
name = DECL_ASSEMBLER_NAME (newdecl);
@@ -2464,46 +2608,36 @@ warn_extern_redeclared_static (newdecl, olddecl)
int
duplicate_decls (newdecl, olddecl)
- register tree newdecl, olddecl;
+ tree newdecl, olddecl;
{
extern struct obstack permanent_obstack;
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0;
- int new_defines_function;
- tree previous_c_decl = NULL_TREE;
+ int new_defines_function = 0;
- if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
- DECL_MACHINE_ATTRIBUTES (newdecl) = DECL_MACHINE_ATTRIBUTES (olddecl);
+ if (newdecl == olddecl)
+ return 1;
types_match = decls_match (newdecl, olddecl);
- if (TREE_CODE (olddecl) != TREE_LIST)
- olddecl_friend = DECL_LANG_SPECIFIC (olddecl) && DECL_FRIEND_P (olddecl);
-
/* If either the type of the new decl or the type of the old decl is an
error_mark_node, then that implies that we have already issued an
error (earlier) for some bogus type specification, and in that case,
it is rather pointless to harass the user with yet more error message
- about the same declaration, so well just pretent the types match here. */
- if ((TREE_TYPE (newdecl)
- && TREE_CODE (TREE_TYPE (newdecl)) == ERROR_MARK)
- || (TREE_TYPE (olddecl)
- && TREE_CODE (TREE_TYPE (olddecl)) == ERROR_MARK))
+ about the same declaration, so just pretend the types match here. */
+ if (TREE_TYPE (newdecl) == error_mark_node
+ || TREE_TYPE (olddecl) == error_mark_node)
types_match = 1;
-
- if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL
- && IDENTIFIER_IMPLICIT_DECL (DECL_ASSEMBLER_NAME (newdecl)) == olddecl)
- /* If -traditional, avoid error for redeclaring fcn
- after implicit decl. */
- ;
- else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_ARTIFICIAL (olddecl)
- && (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl)))
+
+ /* Check for redeclaration and other discrepancies. */
+ if (TREE_CODE (olddecl) == FUNCTION_DECL
+ && DECL_ARTIFICIAL (olddecl)
+ && (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl)))
{
/* If you declare a built-in or predefined function name as static,
the old definition is overridden, but optionally warn this was a
bad choice of name. Ditto for overloads. */
- if (! DECL_PUBLIC (newdecl)
+ if (! TREE_PUBLIC (newdecl)
|| (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl)))
{
@@ -2539,14 +2673,30 @@ duplicate_decls (newdecl, olddecl)
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
+ if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
+ && TREE_CODE (newdecl) != TYPE_DECL
+ && ! (TREE_CODE (newdecl) == TEMPLATE_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL))
+ || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
+ && TREE_CODE (olddecl) != TYPE_DECL
+ && ! (TREE_CODE (olddecl) == TEMPLATE_DECL
+ && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
+ == TYPE_DECL))))
+ {
+ /* We do nothing special here, because C++ does such nasty
+ things with TYPE_DECLs. Instead, just let the TYPE_DECL
+ get shadowed, and know that if we need to find a TYPE_DECL
+ for a given name, we can look in the IDENTIFIER_TYPE_VALUE
+ slot of the identifier. */
+ return 0;
+ }
+
if ((TREE_CODE (newdecl) == FUNCTION_DECL
- && TREE_CODE (olddecl) == TEMPLATE_DECL
- && ! DECL_TEMPLATE_IS_CLASS (olddecl))
+ && DECL_FUNCTION_TEMPLATE_P (olddecl))
|| (TREE_CODE (olddecl) == FUNCTION_DECL
- && TREE_CODE (newdecl) == TEMPLATE_DECL
- && ! DECL_TEMPLATE_IS_CLASS (newdecl)))
+ && DECL_FUNCTION_TEMPLATE_P (newdecl)))
return 0;
-
+
cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
@@ -2563,14 +2713,24 @@ duplicate_decls (newdecl, olddecl)
{
/* The name of a class template may not be declared to refer to
any other template, class, function, object, namespace, value,
- or type in the same scope. */
- if (DECL_TEMPLATE_IS_CLASS (olddecl)
- || DECL_TEMPLATE_IS_CLASS (newdecl))
+ or type in the same scope. */
+ if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
+ || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
{
cp_error ("declaration of template `%#D'", newdecl);
cp_error_at ("conflicts with previous declaration `%#D'",
olddecl);
}
+ else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
+ && compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
+ TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))), 3)
+ && comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
+ DECL_TEMPLATE_PARMS (olddecl)))
+ {
+ cp_error ("new declaration `%#D'", newdecl);
+ cp_error_at ("ambiguates old declaration `%#D'", olddecl);
+ }
return 0;
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -2600,6 +2760,37 @@ duplicate_decls (newdecl, olddecl)
cp_error_at ("previous declaration as `%#D'", olddecl);
}
}
+ else if (TREE_CODE (newdecl) == FUNCTION_DECL
+ && ((DECL_TEMPLATE_SPECIALIZATION (olddecl)
+ && (!DECL_TEMPLATE_INFO (newdecl)
+ || (DECL_TI_TEMPLATE (newdecl)
+ != DECL_TI_TEMPLATE (olddecl))))
+ || (DECL_TEMPLATE_SPECIALIZATION (newdecl)
+ && (!DECL_TEMPLATE_INFO (olddecl)
+ || (DECL_TI_TEMPLATE (olddecl)
+ != DECL_TI_TEMPLATE (newdecl))))))
+ /* It's OK to have a template specialization and a non-template
+ with the same type, or to have specializations of two
+ different templates with the same type. Note that if one is a
+ specialization, and the other is an instantiation of the same
+ template, that we do not exit at this point. That situation
+ can occur if we instantiate a template class, and then
+ specialize one of its methods. This situation is legal, but
+ the declarations must be merged in the usual way. */
+ return 0;
+ else if (TREE_CODE (newdecl) == FUNCTION_DECL
+ && ((DECL_TEMPLATE_INSTANTIATION (olddecl)
+ && !DECL_USE_TEMPLATE (newdecl))
+ || (DECL_TEMPLATE_INSTANTIATION (newdecl)
+ && !DECL_USE_TEMPLATE (olddecl))))
+ /* One of the declarations is a template instantiation, and the
+ other is not a template at all. That's OK. */
+ return 0;
+ else if (TREE_CODE (newdecl) == NAMESPACE_DECL
+ && DECL_NAMESPACE_ALIAS (newdecl)
+ && DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
+ /* Redeclaration of namespace alias, ignore it. */
+ return 1;
else
{
char *errmsg = redeclaration_error_message (newdecl, olddecl);
@@ -2608,7 +2799,7 @@ duplicate_decls (newdecl, olddecl)
cp_error (errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
cp_error_at ((DECL_INITIAL (olddecl)
- && current_binding_level == global_binding_level)
+ && namespace_bindings_p ())
? "`%#D' previously defined here"
: "`%#D' previously declared here", olddecl);
}
@@ -2638,7 +2829,9 @@ duplicate_decls (newdecl, olddecl)
}
}
- if (TREE_CODE (olddecl) == FUNCTION_DECL)
+ if (DECL_LANG_SPECIFIC (olddecl) && DECL_USE_TEMPLATE (olddecl))
+ ;
+ else if (TREE_CODE (olddecl) == FUNCTION_DECL)
{
tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
@@ -2666,32 +2859,18 @@ duplicate_decls (newdecl, olddecl)
{
cp_error ("default argument given for parameter %d of `%#D'",
i, newdecl);
- cp_error_at ("conflicts with previous specification in `%#D'",
+ cp_error_at ("after previous specification in `%#D'",
olddecl);
}
}
- if (DECL_THIS_INLINE (newdecl) && ! DECL_THIS_INLINE (olddecl))
+ if (DECL_THIS_INLINE (newdecl) && ! DECL_THIS_INLINE (olddecl)
+ && TREE_ADDRESSABLE (olddecl) && warn_inline)
{
-#if 0 /* I think this will be correct, but it's really annoying. We should
- fix the compiler to find vtables by indirection so it isn't
- necessary. (jason 8/25/95) */
- if (DECL_VINDEX (olddecl) && ! DECL_ABSTRACT_VIRTUAL_P (olddecl))
- {
- cp_pedwarn ("virtual function `%#D' redeclared inline",
- newdecl);
- cp_pedwarn_at ("previous non-inline declaration here",
- olddecl);
- }
- else
-#endif
- if (TREE_ADDRESSABLE (olddecl))
- {
- cp_pedwarn ("`%#D' was used before it was declared inline",
- newdecl);
- cp_pedwarn_at ("previous non-inline declaration here",
- olddecl);
- }
+ cp_warning ("`%#D' was used before it was declared inline",
+ newdecl);
+ cp_warning_at ("previous non-inline declaration here",
+ olddecl);
}
}
/* These bits are logically part of the type for non-functions. */
@@ -2707,7 +2886,7 @@ duplicate_decls (newdecl, olddecl)
warn about it. */
warn_extern_redeclared_static (newdecl, olddecl);
- /* We have committed to returning 1 at this point. */
+ /* We have committed to returning 1 at this point. */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
/* Now that functions must hold information normally held
@@ -2720,15 +2899,28 @@ duplicate_decls (newdecl, olddecl)
DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
if (DECL_CLASS_CONTEXT (olddecl))
DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl);
- if (DECL_CHAIN (newdecl) == NULL_TREE)
- DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl);
- if (DECL_NEXT_METHOD (newdecl) == NULL_TREE)
- DECL_NEXT_METHOD (newdecl) = DECL_NEXT_METHOD (olddecl);
if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0)
DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_ABSTRACT_VIRTUAL_P (newdecl) |= DECL_ABSTRACT_VIRTUAL_P (olddecl);
+ DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
+ DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
+ new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
+
+ /* Optionally warn about more than one declaration for the same
+ name, but don't warn about a function declaration followed by a
+ definition. */
+ if (warn_redundant_decls && ! DECL_ARTIFICIAL (olddecl)
+ && !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
+ /* Don't warn about extern decl followed by definition. */
+ && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
+ /* Don't warn about friends, let add_friend take care of it. */
+ && ! DECL_FRIEND_P (newdecl))
+ {
+ cp_warning ("redundant redeclaration of `%D' in same scope", newdecl);
+ cp_warning_at ("previous declaration of `%D'", olddecl);
+ }
}
/* Deal with C++: must preserve virtual function table size. */
@@ -2737,8 +2929,6 @@ duplicate_decls (newdecl, olddecl)
register tree newtype = TREE_TYPE (newdecl);
register tree oldtype = TREE_TYPE (olddecl);
- DECL_NESTED_TYPENAME (newdecl) = DECL_NESTED_TYPENAME (olddecl);
-
if (newtype != error_mark_node && oldtype != error_mark_node
&& TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
{
@@ -2746,39 +2936,30 @@ duplicate_decls (newdecl, olddecl)
CLASSTYPE_FRIEND_CLASSES (newtype)
= CLASSTYPE_FRIEND_CLASSES (oldtype);
}
-#if 0
- /* why assert here? Just because debugging information is
- messed up? (mrs) */
- /* it happens on something like:
- typedef struct Thing {
- Thing();
- int x;
- } Thing;
- */
- my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl),
- 139);
-#endif
- }
-
- /* Special handling ensues if new decl is a function definition. */
- new_defines_function = (TREE_CODE (newdecl) == FUNCTION_DECL
- && DECL_INITIAL (newdecl) != NULL_TREE);
-
- /* Optionally warn about more than one declaration for the same name,
- but don't warn about a function declaration followed by a definition. */
- if (warn_redundant_decls
- && ! DECL_ARTIFICIAL (olddecl)
- && !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
- /* Don't warn about extern decl followed by (tentative) definition. */
- && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl)))
- {
- cp_warning ("redundant redeclaration of `%D' in same scope", newdecl);
- cp_warning_at ("previous declaration of `%D'", olddecl);
}
/* Copy all the DECL_... slots specified in the new decl
except for any that we copy here from the old type. */
+ DECL_MACHINE_ATTRIBUTES (newdecl)
+ = merge_machine_decl_attributes (olddecl, newdecl);
+ if (TREE_CODE (newdecl) == TEMPLATE_DECL)
+ {
+ if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE)
+ {
+ if (! duplicate_decls (DECL_TEMPLATE_RESULT (newdecl),
+ DECL_TEMPLATE_RESULT (olddecl)))
+ cp_error ("invalid redeclaration of %D", newdecl);
+ TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
+ DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
+ DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
+ }
+ DECL_TEMPLATE_SPECIALIZATIONS (newdecl)
+ = DECL_TEMPLATE_SPECIALIZATIONS (olddecl);
+
+ return 1;
+ }
+
if (types_match)
{
/* Automatically handles default parameters. */
@@ -2805,32 +2986,35 @@ duplicate_decls (newdecl, olddecl)
&& (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
!= TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
{
- tree ctype = NULL_TREE;
- ctype = DECL_CLASS_CONTEXT (newdecl);
TREE_TYPE (newdecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
TREE_TYPE (olddecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (oldtype));
- if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
+ if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
+ && DECL_SOURCE_LINE (olddecl) != 0
+ && flag_exceptions
+ && ! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
{
- cp_error ("declaration of `%D' throws different exceptions...",
+ cp_pedwarn ("declaration of `%D' throws different exceptions",
newdecl);
- cp_error_at ("...from previous declaration here", olddecl);
+ cp_pedwarn_at ("previous declaration here", olddecl);
}
}
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
- if (oldtype != TREE_TYPE (newdecl)
- && TREE_TYPE (newdecl) != error_mark_node)
+ if (newtype != canonical_type_variant (oldtype)
+ && TREE_TYPE (newdecl) != error_mark_node
+ && !(processing_template_decl && uses_template_parms (newdecl)))
layout_type (TREE_TYPE (newdecl));
- if (TREE_CODE (newdecl) == VAR_DECL
- || TREE_CODE (newdecl) == PARM_DECL
- || TREE_CODE (newdecl) == RESULT_DECL
- || TREE_CODE (newdecl) == FIELD_DECL
- || TREE_CODE (newdecl) == TYPE_DECL)
+ if ((TREE_CODE (newdecl) == VAR_DECL
+ || TREE_CODE (newdecl) == PARM_DECL
+ || TREE_CODE (newdecl) == RESULT_DECL
+ || TREE_CODE (newdecl) == FIELD_DECL
+ || TREE_CODE (newdecl) == TYPE_DECL)
+ && !(processing_template_decl && uses_template_parms (newdecl)))
layout_decl (newdecl, 0);
/* Merge the type qualifiers. */
@@ -2881,20 +3065,55 @@ duplicate_decls (newdecl, olddecl)
/* Merge the storage class information. */
DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
+ DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl);
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl);
if (! DECL_EXTERNAL (olddecl))
DECL_EXTERNAL (newdecl) = 0;
-
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
+
+ if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{
- DECL_C_STATIC (newdecl) = DECL_C_STATIC (olddecl);
DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
+ DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+ /* Don't really know how much of the language-specific
+ values we should copy from old to new. */
+ DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
+ DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
+ DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
+ if (DECL_TEMPLATE_INFO (newdecl) == NULL_TREE)
+ {
+ DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
+ DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
+ }
+ olddecl_friend = DECL_FRIEND_P (olddecl);
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
+ if (DECL_TEMPLATE_INSTANTIATION (olddecl)
+ && !DECL_TEMPLATE_INSTANTIATION (newdecl))
+ {
+ /* If newdecl is not a specialization, then it is not a
+ template-related function at all. And that means that we
+ shoud have exited above, returning 0. */
+ my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
+ 0);
+
+ if (TREE_USED (olddecl))
+ /* From [temp.expl.spec]:
+
+ If a template, a member template or the member of a class
+ template is explicitly specialized then that
+ specialization shall be declared before the first use of
+ that specialization that would cause an implicit
+ instantiation to take place, in every translation unit in
+ which such a use occurs. */
+ cp_error ("explicit specialization of %D after first use",
+ olddecl);
+
+ SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
+ }
DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl);
/* If either decl says `inline', this fn is inline, unless its
@@ -2907,9 +3126,13 @@ duplicate_decls (newdecl, olddecl)
{
DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
DECL_ASSEMBLER_NAME (olddecl) = DECL_ASSEMBLER_NAME (newdecl);
+ DECL_RTL (olddecl) = DECL_RTL (newdecl);
+ }
+ if (! types_match || new_defines_function)
+ {
+ /* These need to be copied so that the names are available. */
DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
- DECL_RTL (olddecl) = DECL_RTL (newdecl);
}
if (new_defines_function)
/* If defining a function declared with other language
@@ -2948,32 +3171,12 @@ duplicate_decls (newdecl, olddecl)
NAMESPACE_LEVEL (newdecl) = NAMESPACE_LEVEL (olddecl);
}
- if (TREE_CODE (newdecl) == TEMPLATE_DECL)
- {
- if (DECL_TEMPLATE_INFO (olddecl)->length)
- DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
- DECL_TEMPLATE_MEMBERS (newdecl) = DECL_TEMPLATE_MEMBERS (olddecl);
- DECL_TEMPLATE_INSTANTIATIONS (newdecl)
- = DECL_TEMPLATE_INSTANTIATIONS (olddecl);
- if (DECL_CHAIN (newdecl) == NULL_TREE)
- DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl);
- }
-
/* Now preserve various other info from the definition. */
TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl);
TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
DECL_ASSEMBLER_NAME (newdecl) = DECL_ASSEMBLER_NAME (olddecl);
- /* Don't really know how much of the language-specific
- values we should copy from old to new. */
- if (DECL_LANG_SPECIFIC (olddecl))
- {
- DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
- DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
- DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
- }
-
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
@@ -2991,9 +3194,44 @@ duplicate_decls (newdecl, olddecl)
#define ROUND(x) ((x + obstack_alignment_mask (&permanent_obstack)) \
& ~ obstack_alignment_mask (&permanent_obstack))
- if ((char *)newdecl + ROUND (function_size)
- + ROUND (sizeof (struct lang_decl))
- == obstack_next_free (&permanent_obstack))
+ if (DECL_TEMPLATE_INSTANTIATION (newdecl))
+ {
+ /* If newdecl is a template instantiation, it is possible that
+ the following sequence of events has occurred:
+
+ o A friend function was declared in a class template. The
+ class template was instantiated.
+
+ o The instantiation of the friend declaration was
+ recorded on the instantiation list, and is newdecl.
+
+ o Later, however, instantiate_class_template called pushdecl
+ on the newdecl to perform name injection. But, pushdecl in
+ turn called duplicate_decls when it discovered that another
+ declaration of a global function with the same name already
+ existed.
+
+ o Here, in duplicate_decls, we decided to clobber newdecl.
+
+ If we're going to do that, we'd better make sure that
+ olddecl, and not newdecl, is on the list of
+ instantiations so that if we try to do the instantiation
+ again we won't get the clobbered declaration. */
+
+ tree tmpl = DECL_TI_TEMPLATE (newdecl);
+ tree decls = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
+
+ for (; decls; decls = TREE_CHAIN (decls))
+ if (TREE_VALUE (decls) == newdecl)
+ TREE_VALUE (decls) = olddecl;
+ }
+
+ if (((char *)newdecl + ROUND (function_size) == (char *)nl
+ && ((char *)newdecl + ROUND (function_size)
+ + ROUND (sizeof (struct lang_decl))
+ == obstack_next_free (&permanent_obstack)))
+ || ((char *)newdecl + ROUND (function_size)
+ == obstack_next_free (&permanent_obstack)))
{
DECL_MAIN_VARIANT (newdecl) = olddecl;
DECL_LANG_SPECIFIC (olddecl) = ol;
@@ -3001,19 +3239,23 @@ duplicate_decls (newdecl, olddecl)
obstack_free (&permanent_obstack, newdecl);
}
- else if (LANG_DECL_PERMANENT (ol))
+ else if (LANG_DECL_PERMANENT (ol) && ol != nl)
{
if (DECL_MAIN_VARIANT (olddecl) == olddecl)
{
/* Save these lang_decls that would otherwise be lost. */
extern tree free_lang_decl_chain;
tree free_lang_decl = (tree) ol;
+
+ if (DECL_LANG_SPECIFIC (olddecl) == ol)
+ abort ();
+
TREE_CHAIN (free_lang_decl) = free_lang_decl_chain;
free_lang_decl_chain = free_lang_decl;
}
else
{
- /* Storage leak. */
+ /* Storage leak. */;
}
}
}
@@ -3029,6 +3271,10 @@ duplicate_decls (newdecl, olddecl)
if (olddecl_friend)
DECL_FRIEND_P (olddecl) = 1;
+ /* NEWDECL contains the merged attribute lists.
+ Update OLDDECL to be the same. */
+ DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
+
return 1;
}
@@ -3045,54 +3291,41 @@ pushdecl (x)
tree x;
{
register tree t;
-#if 0 /* not yet, should get fixed properly later */
- register tree name;
-#else
register tree name = DECL_ASSEMBLER_NAME (x);
-#endif
register struct binding_level *b = current_binding_level;
-#if 0
- static int nglobals; int len;
-
- len = list_length (global_binding_level->names);
- if (len < nglobals)
- my_friendly_abort (8);
- else if (len > nglobals)
- nglobals = len;
-#endif
-
- if (x != current_function_decl
+ if (current_function_decl && x != current_function_decl
+ /* A local declaration for a function doesn't constitute nesting. */
+ && (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x))
/* Don't change DECL_CONTEXT of virtual methods. */
&& (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
&& ! DECL_CONTEXT (x))
DECL_CONTEXT (x) = current_function_decl;
- /* A local declaration for a function doesn't constitute nesting. */
- if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0)
- DECL_CONTEXT (x) = 0;
-
-#if 0 /* not yet, should get fixed properly later */
- /* For functions and class static data, we currently look up the encoded
- form of the name. For types, we want the real name. The former will
- probably be changed soon, according to MDT. */
- if (TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
- name = DECL_ASSEMBLER_NAME (x);
- else
- name = DECL_NAME (x);
-#else
+ if (!DECL_CONTEXT (x))
+ DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
+
/* Type are looked up using the DECL_NAME, as that is what the rest of the
- compiler wants to use. */
+ compiler wants to use. */
if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
- || TREE_CODE (x) == NAMESPACE_DECL)
+ || TREE_CODE (x) == NAMESPACE_DECL || TREE_CODE (x) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (x) == TEMPLATE_TEMPLATE_PARM)
name = DECL_NAME (x);
-#endif
if (name)
{
+#if 0
+ /* Not needed...see below. */
char *file;
int line;
-
- t = lookup_name_current_level (name);
+#endif
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ name = TREE_OPERAND (name, 0);
+
+ /* Namespace-scoped variables are not found in the current level. */
+ if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x))
+ t = namespace_binding (name, DECL_CONTEXT (x));
+ else
+ t = lookup_name_current_level (name);
if (t == error_mark_node)
{
/* error_mark_node is 0 for a while during initialization! */
@@ -3102,20 +3335,25 @@ pushdecl (x)
else if (t != NULL_TREE)
{
+#if 0
+ /* This is turned off until I have time to do it right (bpk). */
+ /* With the code below that uses it... */
file = DECL_SOURCE_FILE (t);
line = DECL_SOURCE_LINE (t);
- if (TREE_CODE (x) == VAR_DECL && DECL_DEAD_FOR_LOCAL (x))
- ; /* This is OK. */
- else if (TREE_CODE (t) == PARM_DECL)
+#endif
+ if (TREE_CODE (t) == PARM_DECL)
{
if (DECL_CONTEXT (t) == NULL_TREE)
fatal ("parse errors have confused me too much");
+
+ /* Check for duplicate params. */
+ if (duplicate_decls (x, t))
+ return t;
}
else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c)
- || (TREE_CODE (x) == TEMPLATE_DECL
- && ! DECL_TEMPLATE_IS_CLASS (x)))
- && is_overloaded_fn (t))
- /* don't do anything just yet */;
+ || DECL_FUNCTION_TEMPLATE_P (x))
+ && is_overloaded_fn (t))
+ /* Don't do anything just yet. */;
else if (t == wchar_decl_node)
{
if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
@@ -3126,17 +3364,7 @@ pushdecl (x)
}
else if (TREE_CODE (t) != TREE_CODE (x))
{
- if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
- || (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
- {
- /* We do nothing special here, because C++ does such nasty
- things with TYPE_DECLs. Instead, just let the TYPE_DECL
- get shadowed, and know that if we need to find a TYPE_DECL
- for a given name, we can look in the IDENTIFIER_TYPE_VALUE
- slot of the identifier. */
- ;
- }
- else if (duplicate_decls (x, t))
+ if (duplicate_decls (x, t))
return t;
}
else if (duplicate_decls (x, t))
@@ -3178,6 +3406,20 @@ pushdecl (x)
return t;
}
+ else if (DECL_MAIN_P (x))
+ {
+ /* A redeclaration of main, but not a duplicate of the
+ previous one.
+
+ [basic.start.main]
+
+ This function shall not be overloaded. */
+ cp_error_at ("invalid redeclaration of `%D'", t);
+ cp_error ("as `%D'", x);
+ /* We don't try to push this declaration since that
+ causes a crash. */
+ return x;
+ }
}
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
@@ -3186,45 +3428,32 @@ pushdecl (x)
if (t != x || DECL_LANGUAGE (x) == lang_c)
return t;
}
- else if (TREE_CODE (x) == TEMPLATE_DECL && ! DECL_TEMPLATE_IS_CLASS (x))
+ else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
return push_overloaded_decl (x, 0);
- /* If declaring a type as a typedef, and the type has no known
- typedef name, install this TYPE_DECL as its typedef name. */
+ /* If declaring a type as a typedef, copy the type (unless we're
+ at line 0), and install this TYPE_DECL as the new type's typedef
+ name. See the extensive comment in ../c-decl.c (pushdecl). */
if (TREE_CODE (x) == TYPE_DECL)
{
tree type = TREE_TYPE (x);
- tree name = (type != error_mark_node) ? TYPE_NAME (type) : x;
+ if (DECL_SOURCE_LINE (x) == 0)
+ {
+ if (TYPE_NAME (type) == 0)
+ TYPE_NAME (type) = x;
+ }
+ else if (type != error_mark_node && TYPE_NAME (type) != x)
+ {
+ push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
- if (name == NULL_TREE || TREE_CODE (name) != TYPE_DECL)
- {
- /* If these are different names, and we're at the global
- binding level, make two equivalent definitions. */
- name = x;
- if (global_bindings_p ())
- TYPE_NAME (type) = x;
- }
- else
- {
- tree tname = DECL_NAME (name);
+ DECL_ORIGINAL_TYPE (x) = type;
+ type = build_type_copy (type);
+ TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
+ TYPE_NAME (type) = x;
+ TREE_TYPE (x) = type;
- /* This is a disgusting kludge for dealing with UPTs. */
- if (global_bindings_p () && ANON_AGGRNAME_P (tname))
- {
- /* do gratuitous C++ typedefing, and make sure that
- we access this type either through TREE_TYPE field
- or via the tags list. */
- TYPE_NAME (TREE_TYPE (x)) = x;
- pushtag (tname, TREE_TYPE (x), 0);
- }
- }
- my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140);
-
- /* Don't set nested_typename on template type parms, for instance.
- Any artificial decls that need DECL_NESTED_TYPENAME will have it
- set in pushtag. */
- if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
- set_nested_typename (x, current_class_name, DECL_NAME (x), type);
+ pop_obstacks ();
+ }
if (type != error_mark_node
&& TYPE_NAME (type)
@@ -3241,11 +3470,12 @@ pushdecl (x)
if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL)
{
tree decl;
+ tree bindings = binding_for_name (name, current_namespace);
- if (IDENTIFIER_GLOBAL_VALUE (name) != NULL_TREE
- && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name))
- || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))))
- decl = IDENTIFIER_GLOBAL_VALUE (name);
+ if (BINDING_VALUE (bindings) != NULL_TREE
+ && (DECL_EXTERNAL (BINDING_VALUE (bindings))
+ || TREE_PUBLIC (BINDING_VALUE (bindings))))
+ decl = BINDING_VALUE (bindings);
else
decl = NULL_TREE;
@@ -3259,21 +3489,16 @@ pushdecl (x)
}
}
- /* In PCC-compatibility mode, extern decls of vars with no current decl
- take effect at top level no matter where they are. */
- if (flag_traditional && DECL_EXTERNAL (x)
- && lookup_name (name, 0) == NULL_TREE)
- b = global_binding_level;
-
/* This name is new in its binding level.
Install the new declaration and return it. */
- if (b == global_binding_level)
+ if (namespace_bindings_p ())
{
/* Install a global value. */
+ tree bindings = binding_for_name (name, current_namespace);
/* If the first global decl has external linkage,
warn if we later see static one. */
- if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && DECL_PUBLIC (x))
+ if (BINDING_VALUE (bindings) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
/* Don't install an artificial TYPE_DECL if we already have
@@ -3281,7 +3506,12 @@ pushdecl (x)
if (TREE_CODE (x) != TYPE_DECL
|| t == NULL_TREE
|| ! DECL_ARTIFICIAL (x))
- IDENTIFIER_GLOBAL_VALUE (name) = x;
+ {
+ if (TREE_CODE (x) == FUNCTION_DECL)
+ my_friendly_assert ((BINDING_VALUE (bindings) == NULL_TREE)
+ || BINDING_VALUE (bindings) == x, 378);
+ BINDING_VALUE (bindings) = x;
+ }
/* Don't forget if the function was used via an implicit decl. */
if (IDENTIFIER_IMPLICIT_DECL (name)
@@ -3310,17 +3540,14 @@ pushdecl (x)
{
/* Here to install a non-global value. */
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
- tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
+ tree oldglobal = binding_for_name (name, current_namespace);
/* Don't install an artificial TYPE_DECL if we already have
another _DECL with that name. */
if (TREE_CODE (x) != TYPE_DECL
|| t == NULL_TREE
|| ! DECL_ARTIFICIAL (x))
- {
- b->shadowed = tree_cons (name, oldlocal, b->shadowed);
- IDENTIFIER_LOCAL_VALUE (name) = x;
- }
+ set_identifier_local_value_with_scope (name, x, b);
/* If this is a TYPE_DECL, push it into the type value slot. */
if (TREE_CODE (x) == TYPE_DECL)
@@ -3336,24 +3563,24 @@ pushdecl (x)
have a global definition or declaration for the function. */
if (oldlocal == NULL_TREE
&& DECL_EXTERNAL (x)
- && oldglobal != NULL_TREE
+ && BINDING_VALUE (oldglobal) != NULL_TREE
&& TREE_CODE (x) == FUNCTION_DECL
- && TREE_CODE (oldglobal) == FUNCTION_DECL)
+ && TREE_CODE (BINDING_VALUE (oldglobal)) == FUNCTION_DECL)
{
/* We have one. Their types must agree. */
- if (decls_match (x, oldglobal))
+ if (decls_match (x, BINDING_VALUE (oldglobal)))
/* OK */;
else
{
cp_warning ("extern declaration of `%#D' doesn't match", x);
- cp_warning_at ("global declaration `%#D'", oldglobal);
+ cp_warning_at ("global declaration `%#D'", BINDING_VALUE (oldglobal));
}
}
/* If we have a local external declaration,
and no file-scope declaration has yet been seen,
then if we later have a file-scope decl it must not be static. */
if (oldlocal == NULL_TREE
- && oldglobal == NULL_TREE
+ && BINDING_VALUE (oldglobal) == NULL_TREE
&& DECL_EXTERNAL (x)
&& TREE_PUBLIC (x))
{
@@ -3379,7 +3606,7 @@ pushdecl (x)
if (b->parm_flag == 1)
cp_error ("declaration of `%#D' shadows a parameter", name);
}
- else if (oldlocal != NULL_TREE && b->is_for_scope
+ else if (warn_shadow && oldlocal != NULL_TREE && b->is_for_scope
&& !DECL_DEAD_FOR_LOCAL (oldlocal))
{
warning ("variable `%s' shadows local",
@@ -3398,12 +3625,13 @@ 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
+ && current_class_ptr
&& !TREE_STATIC (name))
warnstring = "declaration of `%s' shadows a member of `this'";
else if (oldlocal != NULL_TREE)
warnstring = "declaration of `%s' shadows previous local";
- else if (oldglobal != NULL_TREE)
+ else if (BINDING_VALUE (oldglobal) != NULL_TREE)
+ /* XXX shadow warnings in outer-more namespaces */
warnstring = "declaration of `%s' shadows global declaration";
if (warnstring)
@@ -3435,29 +3663,47 @@ pushdecl (x)
return x;
}
-/* Same as pushdecl, but define X in binding-level LEVEL. */
+/* Same as pushdecl, but define X in binding-level LEVEL. We rely on the
+ caller to set DECL_CONTEXT properly. */
static tree
pushdecl_with_scope (x, level)
tree x;
struct binding_level *level;
{
- register struct binding_level *b = current_binding_level;
+ register struct binding_level *b;
+ tree function_decl = current_function_decl;
- current_binding_level = level;
- x = pushdecl (x);
- current_binding_level = b;
+ current_function_decl = NULL_TREE;
+ if (level->parm_flag == 2)
+ {
+ b = class_binding_level;
+ class_binding_level = level;
+ pushdecl_class_level (x);
+ class_binding_level = b;
+ }
+ else
+ {
+ b = current_binding_level;
+ current_binding_level = level;
+ x = pushdecl (x);
+ current_binding_level = b;
+ }
+ current_function_decl = function_decl;
return x;
}
-/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL,
+/* Like pushdecl, only it places X in the current namespace,
if appropriate. */
+
tree
-pushdecl_top_level (x)
+pushdecl_namespace_level (x)
tree x;
{
register struct binding_level *b = inner_binding_level;
- register tree t = pushdecl_with_scope (x, global_binding_level);
+ register tree t;
+
+ t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
/* Now, the type_shadowed stack may screw us. Munge it so it does
what we want. */
@@ -3487,34 +3733,28 @@ pushdecl_top_level (x)
}
else
{
-#if 0
- /* Disabled this 11/10/92, since there are many cases which
- behave just fine when *ptr doesn't satisfy either of these.
- For example, nested classes declared as friends of their enclosing
- class will not meet this criteria. (bpk) */
- my_friendly_assert (*ptr == NULL_TREE || *ptr == newval, 141);
-#endif
*ptr = newval;
}
}
return t;
}
-/* Like push_overloaded_decl, only it places X in GLOBAL_BINDING_LEVEL,
+/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL,
if appropriate. */
-void
-push_overloaded_decl_top_level (x, forget)
+
+tree
+pushdecl_top_level (x)
tree x;
- int forget;
{
- struct binding_level *b = current_binding_level;
-
- current_binding_level = global_binding_level;
- push_overloaded_decl (x, forget);
- current_binding_level = b;
+ tree cur_namespace = current_namespace;
+ current_namespace = global_namespace;
+ x = pushdecl_namespace_level (x);
+ current_namespace = cur_namespace;
+ return x;
}
/* Make the declaration of X appear in CLASS scope. */
+
tree
pushdecl_class_level (x)
tree x;
@@ -3527,21 +3767,24 @@ pushdecl_class_level (x)
{
if (TYPE_BEING_DEFINED (current_class_type))
{
- /* Check for inconsistent use of this name in the class body.
+ /* A name N used in a class S shall refer to the same declaration
+ in its context and when re-evaluated in the completed scope of S.
+
Types, enums, and static vars are checked here; other
members are checked in finish_struct. */
tree icv = IDENTIFIER_CLASS_VALUE (name);
- if (icv
+ if (icv && icv != x
+ && flag_optional_diags
/* Don't complain about inherited names. */
&& id_in_current_class (name)
/* Or shadowed tags. */
- && !(TREE_CODE (icv) == TYPE_DECL
+ && !(DECL_DECLARES_TYPE_P (icv)
&& DECL_CONTEXT (icv) == current_class_type))
{
- cp_error ("declaration of identifier `%D' as `%#D'", name, x);
- cp_error_at ("conflicts with previous use in class as `%#D'",
- icv);
+ cp_pedwarn ("declaration of identifier `%D' as `%#D'", name, x);
+ cp_pedwarn_at ("conflicts with previous use in class as `%#D'",
+ icv);
}
}
@@ -3549,49 +3792,47 @@ pushdecl_class_level (x)
if (TREE_CODE (x) == TYPE_DECL)
{
set_identifier_type_value (name, TREE_TYPE (x));
-
- /* Don't set nested_typename on template type parms, for instance.
- Any artificial decls that need DECL_NESTED_TYPENAME will have it
- set in pushtag. */
- if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
- set_nested_typename (x, current_class_name, name, TREE_TYPE (x));
}
}
return x;
}
+#if 0
/* This function is used to push the mangled decls for nested types into
the appropriate scope. Previously pushdecl_top_level was used, but that
is incorrect for members of local classes. */
-tree
+
+void
pushdecl_nonclass_level (x)
tree x;
{
struct binding_level *b = current_binding_level;
-#if 0
- /* Get out of class scope -- this isn't necessary, because class scope
- doesn't make it into current_binding_level. */
- while (b->parm_flag == 2)
- b = b->level_chain;
-#else
my_friendly_assert (b->parm_flag != 2, 180);
-#endif
+#if 0
/* Get out of template binding levels */
while (b->pseudo_global)
b = b->level_chain;
+#endif
pushdecl_with_scope (x, b);
}
+#endif
/* Make the declaration(s) of X appear in CLASS scope
under the name NAME. */
+
void
push_class_level_binding (name, x)
tree name;
tree x;
{
+ /* The class_binding_level will be NULL if x is a template
+ parameter name in a member template. */
+ if (!class_binding_level)
+ return;
+
if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
&& purpose_member (name, class_binding_level->class_shadowed))
return;
@@ -3605,22 +3846,55 @@ push_class_level_binding (name, x)
obstack_ptr_grow (&decl_obstack, x);
}
-/* Tell caller how to interpret a TREE_LIST which contains
- chains of FUNCTION_DECLS. */
-int
-overloaded_globals_p (list)
- tree list;
+/* Insert another USING_DECL into the current binding level,
+ returning this declaration. If this is a redeclaration,
+ do nothing and return NULL_TREE. */
+
+tree
+push_using_decl (scope, name)
+ tree scope;
+ tree name;
{
- my_friendly_assert (TREE_CODE (list) == TREE_LIST, 142);
+ tree decl;
+
+ my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383);
+ my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384);
+ for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
+ if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name)
+ break;
+ if (decl)
+ return NULL_TREE;
+ decl = build_lang_decl (USING_DECL, name, void_type_node);
+ DECL_INITIAL (decl) = scope;
+ TREE_CHAIN (decl) = current_binding_level->usings;
+ current_binding_level->usings = decl;
+ return decl;
+}
- /* Don't commit caller to seeing them as globals. */
- if (TREE_NONLOCAL_FLAG (list))
- return -1;
- /* Do commit caller to seeing them as globals. */
- if (TREE_CODE (TREE_PURPOSE (list)) == IDENTIFIER_NODE)
- return 1;
- /* Do commit caller to not seeing them as globals. */
- return 0;
+/* Add namespace to using_directives. Return NULL_TREE if nothing was
+ changed (i.e. there was already a directive), or the fresh
+ TREE_LIST otherwise. */
+
+tree
+push_using_directive (used)
+ tree used;
+{
+ tree ud = current_binding_level->using_directives;
+ tree iter, ancestor;
+
+ /* Check if we already have this. */
+ if (purpose_member (used, ud) != NULL_TREE)
+ return NULL_TREE;
+
+ /* Recursively add all namespaces used. */
+ for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
+ push_using_directive (TREE_PURPOSE (iter));
+
+ ancestor = namespace_ancestor (current_decl_namespace (), used);
+ ud = current_binding_level->using_directives;
+ ud = perm_tree_cons (used, ancestor, ud);
+ current_binding_level->using_directives = ud;
+ return ud;
}
/* DECL is a FUNCTION_DECL which may have other definitions already in
@@ -3635,19 +3909,19 @@ overloaded_globals_p (list)
The value returned may be a previous declaration if we guessed wrong
about what language DECL should belong to (C or C++). Otherwise,
it's always DECL (and never something that's not a _DECL). */
-tree
+
+static tree
push_overloaded_decl (decl, forgettable)
tree decl;
int forgettable;
{
tree orig_name = DECL_NAME (decl);
tree old;
- int doing_global = (global_bindings_p () || ! forgettable
- || flag_traditional || pseudo_global_level_p ());
+ int doing_global = (namespace_bindings_p () || ! forgettable);
if (doing_global)
{
- old = IDENTIFIER_GLOBAL_VALUE (orig_name);
+ old = namespace_binding (orig_name, DECL_CONTEXT (decl));
if (old && TREE_CODE (old) == FUNCTION_DECL
&& DECL_ARTIFICIAL (old)
&& (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
@@ -3671,18 +3945,12 @@ push_overloaded_decl (decl, forgettable)
if (old)
{
-#if 0
- /* We cache the value of builtin functions as ADDR_EXPRs
- in the name space. Convert it to some kind of _DECL after
- remembering what to forget. */
- if (TREE_CODE (old) == ADDR_EXPR)
- old = TREE_OPERAND (old, 0);
- else
-#endif
if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
{
tree t = TREE_TYPE (old);
- if (IS_AGGR_TYPE (t) && warn_shadow)
+ if (IS_AGGR_TYPE (t) && warn_shadow
+ && (! DECL_IN_SYSTEM_HEADER (decl)
+ || ! DECL_IN_SYSTEM_HEADER (old)))
cp_warning ("`%#D' hides constructor for `%#T'", decl, t);
old = NULL_TREE;
}
@@ -3690,9 +3958,10 @@ push_overloaded_decl (decl, forgettable)
{
tree tmp;
- for (tmp = get_first_fn (old); tmp; tmp = DECL_CHAIN (tmp))
- if (decl == tmp || duplicate_decls (decl, tmp))
- return tmp;
+ for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
+ if (decl == OVL_CURRENT (tmp)
+ || duplicate_decls (decl, OVL_CURRENT (tmp)))
+ return OVL_CURRENT (tmp);
}
else
{
@@ -3704,19 +3973,16 @@ push_overloaded_decl (decl, forgettable)
if (old || TREE_CODE (decl) == TEMPLATE_DECL)
{
- if (old && is_overloaded_fn (old))
- DECL_CHAIN (decl) = get_first_fn (old);
- else
- DECL_CHAIN (decl) = NULL_TREE;
- old = tree_cons (orig_name, decl, NULL_TREE);
- TREE_TYPE (old) = unknown_type_node;
+ if (old && TREE_CODE (old) != OVERLOAD)
+ old = ovl_cons (old, NULL_TREE);
+ old = ovl_cons (decl, old);
}
else
/* orig_name is not ambiguous. */
old = decl;
if (doing_global)
- IDENTIFIER_GLOBAL_VALUE (orig_name) = old;
+ set_namespace_binding (orig_name, current_namespace, old);
else
IDENTIFIER_LOCAL_VALUE (orig_name) = old;
@@ -3738,7 +4004,7 @@ implicitly_declare (functionid)
/* Save the decl permanently so we can warn if definition follows.
In ANSI C, warn_implicit is usually false, so the saves little space.
But in C++, it's usually true, hence the extra code. */
- if (temp && (flag_traditional || !warn_implicit || toplevel_bindings_p ()))
+ if (temp && (! warn_implicit || toplevel_bindings_p ()))
end_temporary_allocation ();
/* We used to reuse an old implicit decl here,
@@ -3750,8 +4016,7 @@ implicitly_declare (functionid)
TREE_PUBLIC (decl) = 1;
/* ANSI standard says implicit declarations are in the innermost block.
- So we record the decl in the standard fashion.
- If flag_traditional is set, pushdecl does it top-level. */
+ So we record the decl in the standard fashion. */
pushdecl (decl);
rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
@@ -3797,10 +4062,16 @@ redeclaration_error_message (newdecl, olddecl)
if (DECL_LANG_SPECIFIC (olddecl) && DECL_ABSTRACT_VIRTUAL_P (olddecl))
return 0;
+ /* If both functions come from different namespaces, this is not
+ a redeclaration - this is a conflict with a used function. */
+ if (DECL_NAMESPACE_SCOPE_P (olddecl)
+ && DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl))
+ return "`%D' conflicts with used function";
+
/* We'll complain about linkage mismatches in
warn_extern_redeclared_static. */
- /* defining the same name twice is no good. */
+ /* Defining the same name twice is no good. */
if (DECL_INITIAL (olddecl) != NULL_TREE
&& DECL_INITIAL (newdecl) != NULL_TREE)
{
@@ -3813,11 +4084,16 @@ redeclaration_error_message (newdecl, olddecl)
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
- if (DECL_INITIAL (olddecl) && DECL_INITIAL (newdecl))
+ if ((TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
+ && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl))
+ && DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)))
+ || (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL
+ && TYPE_SIZE (TREE_TYPE (newdecl))
+ && TYPE_SIZE (TREE_TYPE (olddecl))))
return "redefinition of `%#D'";
return 0;
}
- else if (current_binding_level == global_binding_level)
+ else if (toplevel_bindings_p ())
{
/* Objects declared at top level: */
/* If at least one is a reference, it's ok. */
@@ -3856,13 +4132,20 @@ lookup_label (id)
if ((decl == NULL_TREE
|| DECL_SOURCE_LINE (decl) == 0)
- && (named_label_uses == NULL_TREE
- || TREE_PURPOSE (named_label_uses) != current_binding_level->names
- || TREE_VALUE (named_label_uses) != decl))
- {
- named_label_uses
- = tree_cons (current_binding_level->names, decl, named_label_uses);
- TREE_TYPE (named_label_uses) = (tree)current_binding_level;
+ && (named_label_uses == NULL
+ || named_label_uses->names_in_scope != current_binding_level->names
+ || named_label_uses->label_decl != decl))
+ {
+ struct named_label_list *new_ent;
+ new_ent
+ = (struct named_label_list*)oballoc (sizeof (struct named_label_list));
+ new_ent->label_decl = decl;
+ new_ent->names_in_scope = current_binding_level->names;
+ new_ent->binding_level = current_binding_level;
+ new_ent->lineno_o_goto = lineno;
+ new_ent->filename_o_goto = input_filename;
+ new_ent->next = named_label_uses;
+ named_label_uses = new_ent;
}
/* Use a label already defined or ref'd with this name. */
@@ -3877,6 +4160,9 @@ lookup_label (id)
decl = build_decl (LABEL_DECL, id, void_type_node);
+ /* Make sure every label has an rtx. */
+ label_rtx (decl);
+
/* A label not explicitly declared must be local to where it's ref'd. */
DECL_CONTEXT (decl) = current_function_decl;
@@ -3890,7 +4176,7 @@ lookup_label (id)
SET_IDENTIFIER_LABEL_VALUE (id, decl);
named_labels = tree_cons (NULL_TREE, decl, named_labels);
- TREE_VALUE (named_label_uses) = decl;
+ named_label_uses->label_decl = decl;
return decl;
}
@@ -3913,7 +4199,6 @@ shadow_label (name)
{
shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE);
- SET_IDENTIFIER_LABEL_VALUE (decl, NULL_TREE);
}
return lookup_label (name);
@@ -3929,7 +4214,20 @@ define_label (filename, line, name)
int line;
tree name;
{
- tree decl = lookup_label (name);
+ tree decl;
+
+ if (minimal_parse_mode)
+ {
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ decl = build_decl (LABEL_DECL, name, void_type_node);
+ pop_obstacks ();
+ DECL_SOURCE_LINE (decl) = line;
+ DECL_SOURCE_FILE (decl) = filename;
+ add_tree (decl);
+ return decl;
+ }
+
+ decl = lookup_label (name);
/* After labels, make any new cleanups go into their
own new (temporary) binding contour. */
@@ -3953,7 +4251,7 @@ define_label (filename, line, name)
}
else
{
- tree uses, prev;
+ struct named_label_list *uses, *prev;
int identified = 0;
/* Mark label as having been defined. */
@@ -3962,17 +4260,17 @@ define_label (filename, line, name)
DECL_SOURCE_FILE (decl) = filename;
DECL_SOURCE_LINE (decl) = line;
- for (prev = NULL_TREE, uses = named_label_uses;
- uses;
- prev = uses, uses = TREE_CHAIN (uses))
- if (TREE_VALUE (uses) == decl)
+ prev = NULL;
+ uses = named_label_uses;
+ while (uses != NULL)
+ if (uses->label_decl == decl)
{
struct binding_level *b = current_binding_level;
while (b)
{
tree new_decls = b->names;
- tree old_decls = ((tree)b == TREE_TYPE (uses)
- ? TREE_PURPOSE (uses) : NULL_TREE);
+ tree old_decls = (b == uses->binding_level)
+ ? uses->names_in_scope : NULL_TREE;
while (new_decls != old_decls)
{
if (TREE_CODE (new_decls) == VAR_DECL
@@ -3985,23 +4283,35 @@ define_label (filename, line, name)
&& DECL_INITIAL (new_decls) != error_mark_node)
|| TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
{
- if (! identified)
- cp_error ("jump to label `%D'", decl);
- identified = 1;
+ if (! identified)
+ {
+ cp_error ("jump to label `%D'", decl);
+ error_with_file_and_line (uses->filename_o_goto,
+ uses->lineno_o_goto,
+ " from here");
+ identified = 1;
+ }
cp_error_at (" crosses initialization of `%#D'",
new_decls);
}
new_decls = TREE_CHAIN (new_decls);
}
- if ((tree)b == TREE_TYPE (uses))
+ if (b == uses->binding_level)
break;
b = b->level_chain;
}
- if (prev)
- TREE_CHAIN (prev) = TREE_CHAIN (uses);
+ if (prev != NULL)
+ prev->next = uses->next;
else
- named_label_uses = TREE_CHAIN (uses);
+ named_label_uses = uses->next;
+
+ uses = uses->next;
+ }
+ else
+ {
+ prev = uses;
+ uses = uses->next;
}
current_function_return_value = NULL_TREE;
return decl;
@@ -4034,6 +4344,7 @@ pop_switch ()
/* Same, but for CASE labels. If DECL is NULL_TREE, it's the default. */
/* XXX Note decl is never actually used. (bpk) */
+
void
define_case_label (decl)
tree decl;
@@ -4139,8 +4450,8 @@ storetags (tags)
static tree
lookup_tag (form, name, binding_level, thislevel_only)
enum tree_code form;
- struct binding_level *binding_level;
tree name;
+ struct binding_level *binding_level;
int thislevel_only;
{
register struct binding_level *level;
@@ -4156,6 +4467,27 @@ lookup_tag (form, name, binding_level, thislevel_only)
if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name)
return TREE_VALUE (tail);
}
+ else if (level->namespace_p)
+ /* Do namespace lookup. */
+ /* XXX: is this a real lookup, considering using-directives etc. ??? */
+ for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
+ {
+ tree old = BINDING_TYPE (binding_for_name (name, tail));
+ /* If it has an original type, it is a typedef, and we
+ should not return it. */
+ if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old)))
+ old = NULL_TREE;
+ if (old && TREE_CODE (old) != form
+ && !(form != ENUMERAL_TYPE && TREE_CODE (old) == TEMPLATE_DECL))
+ {
+ cp_error ("`%#D' redeclared as %C", old, form);
+ return NULL_TREE;
+ }
+ if (old)
+ return old;
+ if (thislevel_only || tail == global_namespace)
+ return NULL_TREE;
+ }
else
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
{
@@ -4165,21 +4497,30 @@ lookup_tag (form, name, binding_level, thislevel_only)
/* Should tighten this up; it'll probably permit
UNION_TYPE and a struct template, for example. */
if (code != form
- && !(form != ENUMERAL_TYPE
- && (code == TEMPLATE_DECL
- || code == UNINSTANTIATED_P_TYPE)))
-
+ && !(form != ENUMERAL_TYPE && code == TEMPLATE_DECL))
{
/* Definition isn't the kind we were looking for. */
cp_error ("`%#D' redeclared as %C", TREE_VALUE (tail),
form);
+ return NULL_TREE;
}
return TREE_VALUE (tail);
}
}
if (thislevel_only && ! level->tag_transparent)
- return NULL_TREE;
- if (current_class_type && level->level_chain == global_binding_level)
+ {
+ if (level->pseudo_global)
+ {
+ tree t = IDENTIFIER_CLASS_VALUE (name);
+ if (t && DECL_CLASS_TEMPLATE_P (t))
+ return TREE_TYPE (t);
+ t = IDENTIFIER_NAMESPACE_VALUE (name);
+ if (t && DECL_CLASS_TEMPLATE_P (t))
+ return TREE_TYPE (t);
+ }
+ return NULL_TREE;
+ }
+ if (current_class_type && level->level_chain->namespace_p)
{
/* Try looking in this class's tags before heading into
global binding level. */
@@ -4208,6 +4549,7 @@ lookup_tag (form, name, binding_level, thislevel_only)
{
cp_error ("`%#D' redeclared as %C in class scope",
TREE_VALUE (tail), form);
+ return NULL_TREE;
}
return TREE_VALUE (tail);
}
@@ -4218,7 +4560,7 @@ lookup_tag (form, name, binding_level, thislevel_only)
if (TYPE_SIZE (context) == NULL_TREE)
goto no_context;
/* Go to next enclosing type, if any. */
- context = DECL_CONTEXT (TYPE_NAME (context));
+ context = DECL_CONTEXT (TYPE_MAIN_DECL (context));
break;
case 'd':
context = DECL_CONTEXT (context);
@@ -4235,12 +4577,14 @@ lookup_tag (form, name, binding_level, thislevel_only)
return NULL_TREE;
}
+#if 0
void
set_current_level_tags_transparency (tags_transparent)
int tags_transparent;
{
current_binding_level->tag_transparent = tags_transparent;
}
+#endif
/* Given a type, find the tag that was defined for it and return the tag name.
Otherwise return 0. However, the value can never be 0
@@ -4271,36 +4615,10 @@ lookup_tag_reverse (type, name)
}
return NULL_TREE;
}
-
-/* Given type TYPE which was not declared in C++ language context,
- attempt to find a name by which it is referred. */
-tree
-typedecl_for_tag (tag)
- tree tag;
-{
- struct binding_level *b = current_binding_level;
-
- if (TREE_CODE (TYPE_NAME (tag)) == TYPE_DECL)
- return TYPE_NAME (tag);
-
- while (b)
- {
- tree decls = b->names;
- while (decls)
- {
- if (TREE_CODE (decls) == TYPE_DECL && TREE_TYPE (decls) == tag)
- break;
- decls = TREE_CHAIN (decls);
- }
- if (decls)
- return decls;
- b = b->level_chain;
- }
- return NULL_TREE;
-}
/* Lookup TYPE in CONTEXT (a chain of nested types or a FUNCTION_DECL).
Return the type value, or NULL_TREE if not found. */
+
static tree
lookup_nested_type (type, context)
tree type;
@@ -4341,22 +4659,233 @@ lookup_nested_type (type, context)
}
/* Look up NAME in the NAMESPACE. */
+
tree
lookup_namespace_name (namespace, name)
tree namespace, name;
{
- struct binding_level *b = (struct binding_level *)NAMESPACE_LEVEL (namespace);
- tree x;
+ struct tree_binding _b;
+ tree val;
+
+ my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
+ my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
+
+ val = binding_init (&_b);
+ if (!qualified_lookup_using_namespace (name, namespace, val, 0))
+ return error_mark_node;
- for (x = NULL_TREE; b && !x; b = b->level_chain)
+ if (BINDING_VALUE (val))
{
- for (x = b->names; x; x = TREE_CHAIN (x))
- if (DECL_NAME (x) == name || DECL_ASSEMBLER_NAME (x) == name)
- break;
- /* Must find directly in the namespace. */
- break;
+ val = BINDING_VALUE (val);
+
+ /* If we have a single function from a using decl, pull it out. */
+ if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
+ val = OVL_FUNCTION (val);
+ return val;
}
- return x;
+
+ cp_error ("`%D' undeclared in namespace `%D'", name, namespace);
+ return error_mark_node;
+}
+
+tree
+make_typename_type (context, name)
+ tree context, name;
+{
+ tree t, d;
+ tree fullname;
+
+ if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
+ name = TYPE_IDENTIFIER (name);
+ else if (TREE_CODE (name) == TYPE_DECL)
+ name = DECL_NAME (name);
+
+ fullname = name;
+
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ name = TREE_OPERAND (name, 0);
+ if (TREE_CODE (name) == TEMPLATE_DECL)
+ name = TREE_OPERAND (fullname, 0) = DECL_NAME (name);
+ }
+ if (TREE_CODE (name) != IDENTIFIER_NODE)
+ my_friendly_abort (2000);
+
+ if (! uses_template_parms (context)
+ || currently_open_class (context))
+ {
+ if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
+ {
+ if (IS_AGGR_TYPE (context))
+ t = lookup_field (context, name, 0, 0);
+ else
+ t = NULL_TREE;
+
+ if (t == NULL_TREE || TREE_CODE (t) != TEMPLATE_DECL
+ || TREE_CODE (DECL_RESULT (t)) != TYPE_DECL)
+ {
+ cp_error ("no class template named `%#T' in `%#T'",
+ name, context);
+ return error_mark_node;
+ }
+
+ return lookup_template_class (t, TREE_OPERAND (fullname, 1),
+ NULL_TREE, context);
+ }
+ else
+ {
+ if (IS_AGGR_TYPE (context))
+ t = lookup_field (context, name, 0, 1);
+ else
+ t = NULL_TREE;
+
+ if (t == NULL_TREE)
+ {
+ cp_error ("no type named `%#T' in `%#T'", name, context);
+ return error_mark_node;
+ }
+
+ return TREE_TYPE (t);
+ }
+ }
+
+ if (processing_template_decl)
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ t = make_lang_type (TYPENAME_TYPE);
+ TYPENAME_TYPE_FULLNAME (t) = fullname;
+ d = build_decl (TYPE_DECL, name, t);
+ if (processing_template_decl)
+ pop_obstacks ();
+
+ TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+ TYPE_NAME (TREE_TYPE (d)) = d;
+ TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ CLASSTYPE_GOT_SEMICOLON (t) = 1;
+
+ return t;
+}
+
+/* Select the right _DECL from multiple choices. */
+
+static tree
+select_decl (binding, flags)
+ tree binding;
+ int flags;
+{
+ tree val;
+ val = BINDING_VALUE (binding);
+ if (LOOKUP_NAMESPACES_ONLY (flags))
+ {
+ /* We are not interested in types. */
+ if (val && TREE_CODE (val) == NAMESPACE_DECL)
+ return val;
+ return NULL_TREE;
+ }
+
+ /* If we could have a type and
+ we have nothing or we need a type and have none. */
+ if (BINDING_TYPE (binding)
+ && (!val || ((flags & LOOKUP_PREFER_TYPES)
+ && TREE_CODE (val) != TYPE_DECL)))
+ val = TYPE_STUB_DECL (BINDING_TYPE (binding));
+ /* Don't return non-types if we really prefer types. */
+ else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
+ && (!looking_for_template || TREE_CODE (val) != TEMPLATE_DECL))
+ val = NULL_TREE;
+
+ return val;
+}
+
+/* Unscoped lookup of a global, iterate over namespaces, considering
+ using namespace statements. */
+
+static tree
+unqualified_namespace_lookup (name, flags)
+ tree name;
+ int flags;
+{
+ struct tree_binding _binding;
+ tree b = binding_init (&_binding);
+ tree initial = current_decl_namespace();
+ tree scope = initial;
+ tree siter;
+ struct binding_level *level;
+ tree val = NULL_TREE;
+
+ while (!val)
+ {
+ val = binding_for_name (name, scope);
+
+ /* Initialize binding for this context. */
+ BINDING_VALUE (b) = BINDING_VALUE (val);
+ BINDING_TYPE (b) = BINDING_TYPE (val);
+
+ /* Add all _DECLs seen through local using-directives. */
+ for (level = current_binding_level;
+ !level->namespace_p;
+ level = level->level_chain)
+ if (!lookup_using_namespace (name, b, level->using_directives,
+ scope, flags))
+ /* Give up because of error. */
+ return NULL_TREE;
+
+ /* Add all _DECLs seen through global using-directives. */
+ /* XXX local and global using lists should work equally. */
+ siter = initial;
+ while (1)
+ {
+ if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
+ scope, flags))
+ /* Give up because of error. */
+ return NULL_TREE;
+ if (siter == scope) break;
+ siter = CP_DECL_CONTEXT (siter);
+ }
+
+ val = select_decl (b, flags);
+ if (scope == global_namespace)
+ break;
+ scope = CP_DECL_CONTEXT (scope);
+ }
+ return val;
+}
+
+/* Combine prefer_type and namespaces_only into flags. */
+
+static int
+lookup_flags (prefer_type, namespaces_only)
+ int prefer_type, namespaces_only;
+{
+ if (namespaces_only)
+ return LOOKUP_PREFER_NAMESPACES;
+ if (prefer_type > 1)
+ return LOOKUP_PREFER_TYPES;
+ if (prefer_type > 0)
+ return LOOKUP_PREFER_BOTH;
+ return 0;
+}
+
+/* Given a lookup that returned VAL, use FLAGS to decide if we want to
+ ignore it or not. Subroutine of lookup_name_real. */
+
+static tree
+qualify_lookup (val, flags)
+ tree val;
+ int flags;
+{
+ if (val == NULL_TREE)
+ return val;
+ if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
+ return val;
+ if ((flags & LOOKUP_PREFER_TYPES)
+ && (TREE_CODE (val) == TYPE_DECL
+ || ((flags & LOOKUP_TEMPLATES_EXPECTED)
+ && DECL_CLASS_TEMPLATE_P (val))))
+ return val;
+ if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
+ return NULL_TREE;
+ return val;
}
/* Look up NAME in the current binding level and its superiors in the
@@ -4365,27 +4894,48 @@ lookup_namespace_name (namespace, name)
such declaration, or return a TREE_LIST with all the overloaded
definitions if there are many, or return 0 if it is undefined.
- If PREFER_TYPE is > 0, we prefer TYPE_DECLs.
+ If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces.
+ If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces).
If PREFER_TYPE is -2, we're being called from yylex(). (UGLY)
- Otherwise we prefer non-TYPE_DECLs. */
+ Otherwise we prefer non-TYPE_DECLs.
-tree
-lookup_name_real (name, prefer_type, nonclass)
+ If NONCLASS is non-zero, we don't look for the NAME in class scope,
+ using IDENTIFIER_CLASS_VALUE. */
+
+static tree
+lookup_name_real (name, prefer_type, nonclass, namespaces_only)
tree name;
- int prefer_type, nonclass;
+ int prefer_type, nonclass, namespaces_only;
{
register tree val;
int yylex = 0;
tree from_obj = NULL_TREE;
+ tree locval, classval;
+ int flags;
+
+ /* Hack: copy flag set by parser, if set. */
+ if (only_namespace_names)
+ namespaces_only = 1;
if (prefer_type == -2)
{
extern int looking_for_typename;
- tree type;
+ tree type = NULL_TREE;
yylex = 1;
prefer_type = looking_for_typename;
+ flags = lookup_flags (prefer_type, namespaces_only);
+ /* During parsing, we need to complain. */
+ flags |= LOOKUP_COMPLAIN;
+ /* If the next thing is '<', class templates are types. */
+ if (looking_for_template)
+ flags |= LOOKUP_TEMPLATES_EXPECTED;
+
+ /* std:: becomes :: for now. */
+ if (got_scope == std_node)
+ got_scope = void_type_node;
+
if (got_scope)
type = got_scope;
else if (got_object != error_mark_node)
@@ -4395,23 +4945,27 @@ lookup_name_real (name, prefer_type, nonclass)
{
if (type == error_mark_node)
return error_mark_node;
- else if (type == void_type_node)
- val = IDENTIFIER_GLOBAL_VALUE (name);
- else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
- /* TFIXME -- don't do this for UPTs in new model. */
- || TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
- {
- if (prefer_type > 0)
- val = create_nested_upt (type, name);
- else
- val = NULL_TREE;
- }
- else if (TREE_CODE (type) == NAMESPACE_DECL)
+ if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
+ type = TREE_TYPE (type);
+
+ if (TYPE_P (type))
+ type = complete_type (type);
+
+ if (TREE_CODE (type) == VOID_TYPE)
+ type = global_namespace;
+ if (TREE_CODE (type) == NAMESPACE_DECL)
{
- val = lookup_namespace_name (type, name);
+ struct tree_binding b;
+ val = binding_init (&b);
+ if (!qualified_lookup_using_namespace (name, type, val, flags))
+ return NULL_TREE;
+ val = select_decl (val, flags);
}
- else if (! IS_AGGR_TYPE (type))
- /* Someone else will give an error about this if needed. */
+ else if (! IS_AGGR_TYPE (type)
+ || TREE_CODE (type) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (type) == TYPENAME_TYPE)
+ /* Someone else will give an error about this if needed. */
val = NULL_TREE;
else if (TYPE_BEING_DEFINED (type))
{
@@ -4430,68 +4984,128 @@ lookup_name_real (name, prefer_type, nonclass)
}
}
}
- if (val == NULL_TREE
- && CLASSTYPE_LOCAL_TYPEDECLS (type))
+ if (val == NULL_TREE)
val = lookup_field (type, name, 0, 1);
}
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
- val = lookup_field (type, name, 0, prefer_type);
+ val = lookup_member (type, name, 0, prefer_type);
}
else
val = NULL_TREE;
if (got_scope)
goto done;
-
- /* This special lookup only applies to types. */
- else if (got_object && val && TREE_CODE (val) == TYPE_DECL)
+ else if (got_object && val)
from_obj = val;
}
-
- if (current_binding_level != global_binding_level
- && IDENTIFIER_LOCAL_VALUE (name))
- val = IDENTIFIER_LOCAL_VALUE (name);
+ else
+ flags = lookup_flags (prefer_type, namespaces_only);
+
+ locval = classval = NULL_TREE;
+
+ if (! namespace_bindings_p ())
+ locval = qualify_lookup (IDENTIFIER_LOCAL_VALUE (name), flags);
+
/* In C++ class fields are between local and global scope,
just before the global scope. */
- else if (current_class_type && ! nonclass)
+ if (current_class_type && ! nonclass)
{
- val = IDENTIFIER_CLASS_VALUE (name);
- if (val == NULL_TREE
- && TYPE_BEING_DEFINED (current_class_type)
- && CLASSTYPE_LOCAL_TYPEDECLS (current_class_type))
+ classval = IDENTIFIER_CLASS_VALUE (name);
+ if (classval == NULL_TREE && TYPE_BEING_DEFINED (current_class_type))
/* Try to find values from base classes if we are presently
defining a type. We are presently only interested in
TYPE_DECLs. */
- val = lookup_field (current_class_type, name, 0, 1);
+ classval = lookup_field (current_class_type, name, 0, 1);
+
+ /* Add implicit 'typename' to types from template bases. lookup_field
+ will do this for us. If classval is actually from an enclosing
+ scope, lookup_nested_field will get it for us. */
+ if (processing_template_decl
+ && classval && TREE_CODE (classval) == TYPE_DECL
+ && ! currently_open_class (DECL_CONTEXT (classval))
+ && uses_template_parms (current_class_type)
+ && ! DECL_ARTIFICIAL (classval))
+ classval = lookup_field (current_class_type, name, 0, 1);
/* yylex() calls this with -2, since we should never start digging for
the nested name at the point where we haven't even, for example,
created the COMPONENT_REF or anything like that. */
- if (val == NULL_TREE)
- val = lookup_nested_field (name, ! yylex);
+ if (classval == NULL_TREE)
+ classval = lookup_nested_field (name, ! yylex);
- if (val == NULL_TREE)
- val = IDENTIFIER_GLOBAL_VALUE (name);
+ classval = qualify_lookup (classval, flags);
}
+
+ if (locval && classval)
+ {
+ if (current_scope () == current_function_decl
+ && ! hack_decl_function_context (current_function_decl))
+ /* Not in a nested function. */
+ val = locval;
+ else
+ {
+ /* This is incredibly horrible. The whole concept of
+ IDENTIFIER_LOCAL_VALUE / IDENTIFIER_CLASS_VALUE /
+ IDENTIFIER_GLOBAL_VALUE needs to be scrapped for local
+ classes. */
+ tree lctx = hack_decl_function_context (locval);
+ tree cctx = hack_decl_function_context (classval);
+
+ if (lctx == current_scope ())
+ val = locval;
+ else if (lctx == cctx)
+ val = classval;
+ else
+ /* I don't know which is right; let's just guess for now. */
+ val = locval;
+ }
+ }
+ else if (locval)
+ val = locval;
+ else if (classval)
+ val = classval;
else
- val = IDENTIFIER_GLOBAL_VALUE (name);
+ val = unqualified_namespace_lookup (name, flags);
done:
if (val)
{
+ /* This should only warn about types used in qualified-ids. */
if (from_obj && from_obj != val)
- cp_error ("lookup in the scope of `%#T' does not match lookup in the current scope",
- got_object);
+ {
+ if (looking_for_typename && TREE_CODE (from_obj) == TYPE_DECL
+ && TREE_CODE (val) == TYPE_DECL
+ && TREE_TYPE (from_obj) != TREE_TYPE (val))
+ {
+ cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%#T')",
+ name, got_object, TREE_TYPE (from_obj));
+ cp_pedwarn (" does not match lookup in the current scope (`%#T')",
+ TREE_TYPE (val));
+ }
+
+ /* We don't change val to from_obj if got_object depends on
+ template parms because that breaks implicit typename for
+ destructor calls. */
+ if (! uses_template_parms (got_object))
+ val = from_obj;
+ }
if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
|| TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
;
+ /* Caller wants a class-or-namespace-name. */
+ else if (prefer_type == 1 && TREE_CODE (val) == NAMESPACE_DECL)
+ ;
else if (IDENTIFIER_HAS_TYPE_VALUE (name))
- val = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
+ val = TYPE_MAIN_DECL (IDENTIFIER_TYPE_VALUE (name));
else if (TREE_TYPE (val) == error_mark_node)
val = error_mark_node;
+
+ /* If we have a single function from a using decl, pull it out. */
+ if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
+ val = OVL_FUNCTION (val);
}
else if (from_obj)
val = from_obj;
@@ -4503,7 +5117,23 @@ tree
lookup_name_nonclass (name)
tree name;
{
- return lookup_name_real (name, 0, 1);
+ return lookup_name_real (name, 0, 1, 0);
+}
+
+tree
+lookup_function_nonclass (name, args)
+ tree name;
+ tree args;
+{
+ return lookup_arg_dependent (name, lookup_name_nonclass (name), args);
+}
+
+tree
+lookup_name_namespace_only (name)
+ tree name;
+{
+ /* type-or-namespace, nonclass, namespace_only */
+ return lookup_name_real (name, 1, 1, 1);
}
tree
@@ -4511,7 +5141,7 @@ lookup_name (name, prefer_type)
tree name;
int prefer_type;
{
- return lookup_name_real (name, prefer_type, 0);
+ return lookup_name_real (name, prefer_type, 0, 0);
}
/* Similar to `lookup_name' but look only at current binding level. */
@@ -4522,9 +5152,9 @@ lookup_name_current_level (name)
{
register tree t = NULL_TREE;
- if (current_binding_level == global_binding_level)
+ if (current_binding_level->namespace_p)
{
- t = IDENTIFIER_GLOBAL_VALUE (name);
+ t = IDENTIFIER_NAMESPACE_VALUE (name);
/* extern "C" function() */
if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST)
@@ -4535,20 +5165,57 @@ lookup_name_current_level (name)
struct binding_level *b = current_binding_level;
while (1)
{
- for (t = b->names; t; t = TREE_CHAIN (t))
- if (DECL_NAME (t) == name || DECL_ASSEMBLER_NAME (t) == name)
- goto out;
+ if (purpose_member (name, b->shadowed))
+ return IDENTIFIER_LOCAL_VALUE (name);
if (b->keep == 2)
b = b->level_chain;
else
break;
}
- out:
- ;
}
return t;
}
+
+/* Like lookup_name_current_level, but for types. */
+
+tree
+lookup_type_current_level (name)
+ tree name;
+{
+ register tree t = NULL_TREE;
+
+ my_friendly_assert (! current_binding_level->namespace_p, 980716);
+
+ if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
+ && REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node)
+ {
+ struct binding_level *b = current_binding_level;
+ while (1)
+ {
+ if (purpose_member (name, b->type_shadowed))
+ return REAL_IDENTIFIER_TYPE_VALUE (name);
+ if (b->keep == 2)
+ b = b->level_chain;
+ else
+ break;
+ }
+ }
+
+ return t;
+}
+
+void
+begin_only_namespace_names ()
+{
+ only_namespace_names = 1;
+}
+
+void
+end_only_namespace_names ()
+{
+ only_namespace_names = 0;
+}
/* Arrange for the user to get a source line number, even when the
compiler is going down in flames, so that she at least has a
@@ -4559,7 +5226,7 @@ lookup_name_current_level (name)
static void
signal_catch (sig)
- int sig;
+ int sig ATTRIBUTE_UNUSED;
{
signal (SIGSEGV, SIG_DFL);
#ifdef SIGIOT
@@ -4577,10 +5244,13 @@ signal_catch (sig)
my_friendly_abort (0);
}
+#if 0
+/* Unused -- brendan 970107 */
/* Array for holding types considered "built-in". These types
are output in the module in which `main' is defined. */
static tree *builtin_type_tdescs_arr;
static int builtin_type_tdescs_len, builtin_type_tdescs_max;
+#endif
/* Push the declarations of builtin types into the namespace.
RID_INDEX, if < RID_MAX is the index of the builtin type
@@ -4594,7 +5264,7 @@ record_builtin_type (rid_index, name, type)
tree type;
{
tree rname = NULL_TREE, tname = NULL_TREE;
- tree tdecl;
+ tree tdecl = NULL_TREE;
if ((int) rid_index < (int) RID_MAX)
rname = ridpointers[(int) rid_index];
@@ -4605,84 +5275,77 @@ record_builtin_type (rid_index, name, type)
if (tname)
{
-#if 0 /* not yet, should get fixed properly later */
- tdecl = pushdecl (make_type_decl (tname, type));
-#else
tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
-#endif
set_identifier_type_value (tname, NULL_TREE);
if ((int) rid_index < (int) RID_MAX)
- IDENTIFIER_GLOBAL_VALUE (tname) = tdecl;
+ /* Built-in types live in the global namespace. */
+ SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
}
if (rname != NULL_TREE)
{
if (tname != NULL_TREE)
{
set_identifier_type_value (rname, NULL_TREE);
- IDENTIFIER_GLOBAL_VALUE (rname) = tdecl;
+ SET_IDENTIFIER_GLOBAL_VALUE (rname, tdecl);
}
else
{
-#if 0 /* not yet, should get fixed properly later */
- tdecl = pushdecl (make_type_decl (rname, type));
-#else
tdecl = pushdecl (build_decl (TYPE_DECL, rname, type));
-#endif
set_identifier_type_value (rname, NULL_TREE);
}
}
+}
- if (flag_rtti)
- {
- if (builtin_type_tdescs_len+5 >= builtin_type_tdescs_max)
- {
- builtin_type_tdescs_max *= 2;
- builtin_type_tdescs_arr
- = (tree *)xrealloc (builtin_type_tdescs_arr,
- builtin_type_tdescs_max * sizeof (tree));
- }
- builtin_type_tdescs_arr[builtin_type_tdescs_len++] = type;
- if (TREE_CODE (type) != POINTER_TYPE)
- {
- builtin_type_tdescs_arr[builtin_type_tdescs_len++]
- = build_pointer_type (type);
- builtin_type_tdescs_arr[builtin_type_tdescs_len++]
- = build_pointer_type (build_type_variant (type, 1, 0));
- }
- if (TREE_CODE (type) != VOID_TYPE)
- {
- builtin_type_tdescs_arr[builtin_type_tdescs_len++]
- = build_reference_type (type);
- builtin_type_tdescs_arr[builtin_type_tdescs_len++]
- = build_reference_type (build_type_variant (type, 1, 0));
- }
+/* Record one of the standard Java types.
+ * Declare it as having the given NAME.
+ * If SIZE > 0, it is the size of one of the integral types;
+ * otherwise it is the negative of the size of one of the other types. */
+
+static tree
+record_builtin_java_type (name, size)
+ char *name;
+ int size;
+{
+ tree type, decl;
+ if (size > 0)
+ type = make_signed_type (size);
+ else if (size > -32)
+ { /* "__java_char" or ""__java_boolean". */
+ type = make_unsigned_type (-size);
+ /*if (size == -1) TREE_SET_CODE (type, BOOLEAN_TYPE);*/
}
+ else
+ { /* "__java_float" or ""__java_double". */
+ type = make_node (REAL_TYPE);
+ TYPE_PRECISION (type) = - size;
+ layout_type (type);
+ }
+ record_builtin_type (RID_MAX, name, type);
+ decl = TYPE_NAME (type);
+ DECL_IGNORED_P (decl) = 1;
+ TYPE_FOR_JAVA (type) = 1;
+ return type;
}
+/* Push a type into the namespace so that the back-ends ignore it. */
+
static void
-output_builtin_tdesc_entries ()
+record_unknown_type (type, name)
+ tree type;
+ char *name;
{
- extern struct obstack permanent_obstack;
-
- /* If there's more than one main in this file, don't crash. */
- if (builtin_type_tdescs_arr == 0)
- return;
-
- push_obstacks (&permanent_obstack, &permanent_obstack);
- while (builtin_type_tdescs_len > 0)
- {
- tree type = builtin_type_tdescs_arr[--builtin_type_tdescs_len];
- tree tdesc = build_t_desc (type, 0);
- TREE_ASM_WRITTEN (tdesc) = 0;
- build_t_desc (type, 2);
- }
- free (builtin_type_tdescs_arr);
- builtin_type_tdescs_arr = 0;
- pop_obstacks ();
-}
+ tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
+ /* Make sure the "unknown type" typedecl gets ignored for debug info. */
+ DECL_IGNORED_P (decl) = 1;
+ TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
+ TYPE_SIZE (type) = TYPE_SIZE (void_type_node);
+ TYPE_ALIGN (type) = 1;
+ TYPE_MODE (type) = TYPE_MODE (void_type_node);
+}
/* Push overloaded decl, in global scope, with one argument so it
can be used as a callback from define_function. */
+
static void
push_overloaded_decl_1 (x)
tree x;
@@ -4690,18 +5353,16 @@ push_overloaded_decl_1 (x)
push_overloaded_decl (x, 0);
}
-#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
- define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME)
-
#ifdef __GNUC__
__inline
#endif
-tree auto_function (name, type, code)
+tree
+auto_function (name, type, code)
tree name, type;
enum built_in_function code;
{
return define_function
- (IDENTIFIER_POINTER (name), type, code, (void (*)())push_overloaded_decl_1,
+ (IDENTIFIER_POINTER (name), type, code, push_overloaded_decl_1,
IDENTIFIER_POINTER (build_decl_overload (name, TYPE_ARG_TYPES (type),
0)));
}
@@ -4714,25 +5375,33 @@ tree auto_function (name, type, code)
void
init_decl_processing ()
{
- tree decl;
- register tree endlink, int_endlink, double_endlink, ptr_endlink;
+ register tree endlink, int_endlink, double_endlink, unsigned_endlink;
tree fields[20];
- /* Either char* or void*. */
- tree traditional_ptr_type_node;
/* Data type of memcpy. */
- tree memcpy_ftype;
-#if 0 /* Not yet. */
- /* Data type of strncpy. */
- tree strncpy_ftype;
-#endif
+ tree memcpy_ftype, strlen_ftype;
int wchar_type_size;
tree temp;
tree array_domain_type;
extern int flag_strict_prototype;
+ tree vb_off_identifier = NULL_TREE;
+ /* Function type `char *(char *, char *)' and similar ones */
+ tree string_ftype_ptr_ptr, int_ftype_string_string;
+ tree sizetype_endlink;
+ tree ptr_ftype, ptr_ftype_unsigned, ptr_ftype_sizetype;
+ tree void_ftype, void_ftype_int, void_ftype_ptr, ptr_ftype_void;
/* Have to make these distinct before we try using them. */
lang_name_cplusplus = get_identifier ("C++");
lang_name_c = get_identifier ("C");
+ lang_name_java = get_identifier ("Java");
+
+ /* Enter the global namespace. */
+ my_friendly_assert (global_namespace == NULL_TREE, 375);
+ my_friendly_assert (current_lang_name == NULL_TREE, 375);
+ current_lang_name = lang_name_cplusplus;
+ push_namespace (get_identifier ("::"));
+ global_namespace = current_namespace;
+ current_lang_name = NULL_TREE;
if (flag_strict_prototype == 2)
{
@@ -4747,19 +5416,20 @@ init_decl_processing ()
current_function_decl = NULL_TREE;
named_labels = NULL_TREE;
- named_label_uses = NULL_TREE;
+ named_label_uses = NULL;
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
+#ifndef __CYGWIN32__
/* Because most segmentation signals can be traced back into user
code, catch them and at least give the user a chance of working
- around compiler bugs. */
+ around compiler bugs. */
signal (SIGSEGV, signal_catch);
/* We will also catch aborts in the back-end through signal_catch and
give the user a chance to see where the error might be, and to defeat
aborts in the back-end when there have been errors previously in their
- code. */
+ code. */
#ifdef SIGIOT
signal (SIGIOT, signal_catch);
#endif
@@ -4772,13 +5442,15 @@ init_decl_processing ()
#ifdef SIGBUS
signal (SIGBUS, signal_catch);
#endif
+#else /* ndef __CYGWIN32__ */
+ /* Cygwin32 cannot handle catching signals other than
+ SIGABRT yet. We hope this will cease to be the case soon. */
+#ifdef SIGABRT
+ signal (SIGABRT, signal_catch);
+#endif
+#endif /* ndef __CYGWIN32__ */
gcc_obstack_init (&decl_obstack);
- if (flag_rtti)
- {
- builtin_type_tdescs_max = 100;
- builtin_type_tdescs_arr = (tree *)xmalloc (100 * sizeof (tree));
- }
/* Must lay these out before anything else gets laid out. */
error_mark_node = make_node (ERROR_MARK);
@@ -4790,9 +5462,14 @@ init_decl_processing ()
/* Make the binding_level structure for global names. */
pushlevel (0);
global_binding_level = current_binding_level;
+ /* The global level is the namespace level of ::. */
+ NAMESPACE_LEVEL (global_namespace) = global_binding_level;
+ declare_namespace_level ();
this_identifier = get_identifier (THIS_NAME);
in_charge_identifier = get_identifier (IN_CHARGE_NAME);
+ ctor_identifier = get_identifier (CTOR_NAME);
+ dtor_identifier = get_identifier (DTOR_NAME);
pfn_identifier = get_identifier (VTABLE_PFN_NAME);
index_identifier = get_identifier (VTABLE_INDEX_NAME);
delta_identifier = get_identifier (VTABLE_DELTA_NAME);
@@ -4813,10 +5490,10 @@ init_decl_processing ()
/* Define `char', which is like either `signed char' or `unsigned char'
but not the same as either. */
- char_type_node =
- (flag_signed_char
- ? make_signed_type (CHAR_TYPE_SIZE)
- : make_unsigned_type (CHAR_TYPE_SIZE));
+ char_type_node
+ = (flag_signed_char
+ ? make_signed_type (CHAR_TYPE_SIZE)
+ : make_unsigned_type (CHAR_TYPE_SIZE));
record_builtin_type (RID_CHAR, "char", char_type_node);
long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
@@ -4838,32 +5515,21 @@ init_decl_processing ()
record_builtin_type (RID_MAX, "long long unsigned",
long_long_unsigned_type_node);
- /* `unsigned long' is the standard type for sizeof.
- Traditionally, use a signed type.
- Note that stddef.h uses `unsigned long',
- and this must agree, even of long and int are the same size. */
- sizetype
- = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)));
- if (flag_traditional && TREE_UNSIGNED (sizetype))
- sizetype = signed_type (sizetype);
-
- ptrdiff_type_node
- = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
-
- TREE_TYPE (TYPE_SIZE (integer_type_node)) = sizetype;
- TREE_TYPE (TYPE_SIZE (char_type_node)) = sizetype;
- TREE_TYPE (TYPE_SIZE (unsigned_type_node)) = sizetype;
- TREE_TYPE (TYPE_SIZE (long_unsigned_type_node)) = sizetype;
- TREE_TYPE (TYPE_SIZE (long_integer_type_node)) = sizetype;
- TREE_TYPE (TYPE_SIZE (long_long_integer_type_node)) = sizetype;
- TREE_TYPE (TYPE_SIZE (long_long_unsigned_type_node)) = sizetype;
-
short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
record_builtin_type (RID_SHORT, "short int", short_integer_type_node);
short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
record_builtin_type (RID_MAX, "short unsigned int", short_unsigned_type_node);
record_builtin_type (RID_MAX, "unsigned short", short_unsigned_type_node);
+ /* `unsigned long' is the standard type for sizeof.
+ Note that stddef.h uses `unsigned long',
+ and this must agree, even if long and int are the same size. */
+ set_sizetype
+ (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
+
+ ptrdiff_type_node
+ = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
+
/* Define both `signed char' and `unsigned char'. */
signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
record_builtin_type (RID_MAX, "signed char", signed_char_type_node);
@@ -4879,6 +5545,8 @@ init_decl_processing ()
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
+ intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
+ pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
@@ -4887,6 +5555,8 @@ init_decl_processing ()
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
+ unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
+ pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
float_type_node = make_node (REAL_TYPE);
TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
@@ -4906,6 +5576,39 @@ init_decl_processing ()
record_builtin_type (RID_MAX, "long double", long_double_type_node);
layout_type (long_double_type_node);
+ complex_integer_type_node = make_node (COMPLEX_TYPE);
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
+ complex_integer_type_node));
+ TREE_TYPE (complex_integer_type_node) = integer_type_node;
+ layout_type (complex_integer_type_node);
+
+ complex_float_type_node = make_node (COMPLEX_TYPE);
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
+ complex_float_type_node));
+ TREE_TYPE (complex_float_type_node) = float_type_node;
+ layout_type (complex_float_type_node);
+
+ complex_double_type_node = make_node (COMPLEX_TYPE);
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
+ complex_double_type_node));
+ TREE_TYPE (complex_double_type_node) = double_type_node;
+ layout_type (complex_double_type_node);
+
+ complex_long_double_type_node = make_node (COMPLEX_TYPE);
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
+ complex_long_double_type_node));
+ TREE_TYPE (complex_long_double_type_node) = long_double_type_node;
+ layout_type (complex_long_double_type_node);
+
+ java_byte_type_node = record_builtin_java_type ("__java_byte", 8);
+ java_short_type_node = record_builtin_java_type ("__java_short", 16);
+ java_int_type_node = record_builtin_java_type ("__java_int", 32);
+ java_long_type_node = record_builtin_java_type ("__java_long", 64);
+ java_float_type_node = record_builtin_java_type ("__java_float", -32);
+ java_double_type_node = record_builtin_java_type ("__java_double", -64);
+ java_char_type_node = record_builtin_java_type ("__java_char", -16);
+ java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1);
+
integer_zero_node = build_int_2 (0, 0);
TREE_TYPE (integer_zero_node) = integer_type_node;
integer_one_node = build_int_2 (1, 0);
@@ -4917,6 +5620,9 @@ init_decl_processing ()
boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
+ TYPE_MAX_VALUE (boolean_type_node) = build_int_2 (1, 0);
+ TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node;
+ TYPE_PRECISION (boolean_type_node) = 1;
record_builtin_type (RID_BOOL, "bool", boolean_type_node);
boolean_false_node = build_int_2 (0, 0);
TREE_TYPE (boolean_false_node) = boolean_type_node;
@@ -4927,6 +5633,9 @@ init_decl_processing ()
size_zero_node = size_int (0);
size_one_node = size_int (1);
+ signed_size_zero_node = build_int_2 (0, 0);
+ TREE_TYPE (signed_size_zero_node) = make_signed_type (TYPE_PRECISION (sizetype));
+
void_type_node = make_node (VOID_TYPE);
record_builtin_type (RID_VOID, NULL_PTR, void_type_node);
layout_type (void_type_node); /* Uses integer_zero_node. */
@@ -4936,15 +5645,17 @@ init_decl_processing ()
null_pointer_node = build_int_2 (0, 0);
TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
layout_type (TREE_TYPE (null_pointer_node));
-
+
/* Used for expressions that do nothing, but are not errors. */
void_zero_node = build_int_2 (0, 0);
TREE_TYPE (void_zero_node) = void_type_node;
string_type_node = build_pointer_type (char_type_node);
- const_string_type_node =
- build_pointer_type (build_type_variant (char_type_node, 1, 0));
+ const_string_type_node
+ = build_pointer_type (build_type_variant (char_type_node, 1, 0));
+#if 0
record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
+#endif
/* Make a type to be the domain of a few array types
whose domains don't really matter.
@@ -4953,7 +5664,7 @@ init_decl_processing ()
initializations of __FUNCTION__ and __PRETTY_FUNCTION__. */
array_domain_type = build_index_type (build_int_2 (200, 0));
- /* make a type for arrays of characters.
+ /* Make a type for arrays of characters.
With luck nothing will ever really depend on the length of this
array type. */
char_array_type_node
@@ -4968,20 +5679,45 @@ init_decl_processing ()
default_function_type
= build_function_type (integer_type_node, NULL_TREE);
- build_pointer_type (default_function_type);
ptr_type_node = build_pointer_type (void_type_node);
- const_ptr_type_node =
- build_pointer_type (build_type_variant (void_type_node, 1, 0));
+ const_ptr_type_node
+ = build_pointer_type (build_type_variant (void_type_node, 1, 0));
+#if 0
record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node);
+#endif
endlink = void_list_node;
int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
double_endlink = tree_cons (NULL_TREE, double_type_node, endlink);
- ptr_endlink = tree_cons (NULL_TREE, ptr_type_node, endlink);
+ unsigned_endlink = tree_cons (NULL_TREE, unsigned_type_node, endlink);
+
+ ptr_ftype = build_function_type (ptr_type_node, NULL_TREE);
+ ptr_ftype_unsigned = build_function_type (ptr_type_node, unsigned_endlink);
+ sizetype_endlink = tree_cons (NULL_TREE, sizetype, endlink);
+ /* We realloc here because sizetype could be int or unsigned. S'ok. */
+ ptr_ftype_sizetype = build_function_type (ptr_type_node, sizetype_endlink);
+
+ void_ftype = build_function_type (void_type_node, endlink);
+ void_ftype_int = build_function_type (void_type_node, int_endlink);
+ void_ftype_ptr
+ = build_function_type (void_type_node,
+ tree_cons (NULL_TREE, ptr_type_node, endlink));
+ void_ftype_ptr
+ = build_exception_variant (void_ftype_ptr,
+ tree_cons (NULL_TREE, NULL_TREE, NULL_TREE));
+
+ float_ftype_float
+ = build_function_type (float_type_node,
+ tree_cons (NULL_TREE, float_type_node, endlink));
double_ftype_double
= build_function_type (double_type_node, double_endlink);
+ ldouble_ftype_ldouble
+ = build_function_type (long_double_type_node,
+ tree_cons (NULL_TREE, long_double_type_node,
+ endlink));
+
double_ftype_double_double
= build_function_type (double_type_node,
tree_cons (NULL_TREE, double_type_node,
@@ -4995,12 +5731,6 @@ init_decl_processing ()
tree_cons (NULL_TREE, long_integer_type_node,
endlink));
- void_ftype_ptr_ptr_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- int_endlink)));
-
int_ftype_cptr_cptr_sizet
= build_function_type (integer_type_node,
tree_cons (NULL_TREE, const_ptr_type_node,
@@ -5009,12 +5739,6 @@ init_decl_processing ()
sizetype,
endlink))));
- void_ftype_ptr_int_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- int_endlink)));
-
string_ftype_ptr_ptr /* strcpy prototype */
= build_function_type (string_type_node,
tree_cons (NULL_TREE, string_type_node,
@@ -5022,17 +5746,6 @@ init_decl_processing ()
const_string_type_node,
endlink)));
-#if 0
- /* Not yet. */
- strncpy_ftype /* strncpy prototype */
- = build_function_type (string_type_node,
- tree_cons (NULL_TREE, string_type_node,
- tree_cons (NULL_TREE, const_string_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink))));
-#endif
-
int_ftype_string_string /* strcmp prototype */
= build_function_type (integer_type_node,
tree_cons (NULL_TREE, const_string_type_node,
@@ -5040,69 +5753,51 @@ init_decl_processing ()
const_string_type_node,
endlink)));
- sizet_ftype_string /* strlen prototype */
+ strlen_ftype /* strlen prototype */
= build_function_type (sizetype,
tree_cons (NULL_TREE, const_string_type_node,
endlink));
- traditional_ptr_type_node
- = (flag_traditional ? string_type_node : ptr_type_node);
-
memcpy_ftype /* memcpy prototype */
- = build_function_type (traditional_ptr_type_node,
+ = build_function_type (ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, const_ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink))));
+ sizetype_endlink)));
if (flag_huge_objects)
delta_type_node = long_integer_type_node;
else
delta_type_node = short_integer_type_node;
- builtin_function ("__builtin_constant_p", int_ftype_int,
+ builtin_function ("__builtin_constant_p", default_function_type,
BUILT_IN_CONSTANT_P, NULL_PTR);
- builtin_return_address_fndecl =
- builtin_function ("__builtin_return_address",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- unsigned_type_node,
- endlink)),
- BUILT_IN_RETURN_ADDRESS, NULL_PTR);
+ builtin_return_address_fndecl
+ = builtin_function ("__builtin_return_address", ptr_ftype_unsigned,
+ BUILT_IN_RETURN_ADDRESS, NULL_PTR);
- builtin_function ("__builtin_frame_address",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- unsigned_type_node,
- endlink)),
+ builtin_function ("__builtin_frame_address", ptr_ftype_unsigned,
BUILT_IN_FRAME_ADDRESS, NULL_PTR);
+ ptr_ftype_void = build_function_type (ptr_type_node, endlink);
+ builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
+ builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
- builtin_function ("__builtin_alloca",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)),
+ builtin_function ("__builtin_alloca", ptr_ftype_sizetype,
BUILT_IN_ALLOCA, "alloca");
+ builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
/* Define alloca, ffs as builtins.
Declare _exit just to mark it as volatile. */
if (! flag_no_builtin && !flag_no_nonansi_builtin)
{
- temp = builtin_function ("alloca",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)),
+ temp = builtin_function ("alloca", ptr_ftype_sizetype,
BUILT_IN_ALLOCA, NULL_PTR);
/* Suppress error if redefined as a non-function. */
DECL_BUILT_IN_NONANSI (temp) = 1;
temp = builtin_function ("ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
/* Suppress error if redefined as a non-function. */
DECL_BUILT_IN_NONANSI (temp) = 1;
- temp = builtin_function ("_exit", build_function_type (void_type_node,
- int_endlink),
+ temp = builtin_function ("_exit", void_ftype_int,
NOT_BUILT_IN, NULL_PTR);
TREE_THIS_VOLATILE (temp) = 1;
TREE_SIDE_EFFECTS (temp) = 1;
@@ -5110,65 +5805,48 @@ init_decl_processing ()
DECL_BUILT_IN_NONANSI (temp) = 1;
}
- builtin_function ("__builtin_abs", int_ftype_int,
- BUILT_IN_ABS, NULL_PTR);
- builtin_function ("__builtin_fabs", double_ftype_double,
- BUILT_IN_FABS, NULL_PTR);
+ builtin_function ("__builtin_abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR);
+ builtin_function ("__builtin_fabsf", float_ftype_float, BUILT_IN_FABS,
+ NULL_PTR);
+ builtin_function ("__builtin_fabs", double_ftype_double, BUILT_IN_FABS,
+ NULL_PTR);
+ builtin_function ("__builtin_fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS,
+ NULL_PTR);
builtin_function ("__builtin_labs", long_ftype_long,
BUILT_IN_LABS, NULL_PTR);
- builtin_function ("__builtin_ffs", int_ftype_int,
- BUILT_IN_FFS, NULL_PTR);
- builtin_function ("__builtin_fsqrt", double_ftype_double,
- BUILT_IN_FSQRT, NULL_PTR);
- builtin_function ("__builtin_sin", double_ftype_double,
- BUILT_IN_SIN, "sin");
- builtin_function ("__builtin_cos", double_ftype_double,
- BUILT_IN_COS, "cos");
- builtin_function ("__builtin_saveregs",
- build_function_type (ptr_type_node, NULL_TREE),
+ builtin_function ("__builtin_saveregs", ptr_ftype,
BUILT_IN_SAVEREGS, NULL_PTR);
-/* EXPAND_BUILTIN_VARARGS is obsolete. */
-#if 0
- builtin_function ("__builtin_varargs",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink)),
- BUILT_IN_VARARGS, NULL_PTR);
-#endif
builtin_function ("__builtin_classify_type", default_function_type,
BUILT_IN_CLASSIFY_TYPE, NULL_PTR);
- builtin_function ("__builtin_next_arg",
- build_function_type (ptr_type_node, NULL_TREE),
+ builtin_function ("__builtin_next_arg", ptr_ftype,
BUILT_IN_NEXT_ARG, NULL_PTR);
- builtin_function ("__builtin_args_info",
+ builtin_function ("__builtin_args_info", int_ftype_int,
+ BUILT_IN_ARGS_INFO, NULL_PTR);
+ builtin_function ("__builtin_setjmp",
build_function_type (integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
endlink)),
- BUILT_IN_ARGS_INFO, NULL_PTR);
+ BUILT_IN_SETJMP, NULL_PTR);
+ builtin_function ("__builtin_longjmp",
+ build_function_type (integer_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ tree_cons (NULL_TREE,
+ integer_type_node,
+ endlink))),
+ BUILT_IN_LONGJMP, NULL_PTR);
/* Untyped call and return. */
- builtin_function ("__builtin_apply_args",
- build_function_type (ptr_type_node, NULL_TREE),
+ builtin_function ("__builtin_apply_args", ptr_ftype,
BUILT_IN_APPLY_ARGS, NULL_PTR);
temp = tree_cons (NULL_TREE,
build_pointer_type (build_function_type (void_type_node,
NULL_TREE)),
- tree_cons (NULL_TREE,
- ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)));
+ tree_cons (NULL_TREE, ptr_ftype_sizetype, NULL_TREE));
builtin_function ("__builtin_apply",
build_function_type (ptr_type_node, temp),
BUILT_IN_APPLY, NULL_PTR);
- builtin_function ("__builtin_return",
- build_function_type (void_type_node,
- tree_cons (NULL_TREE,
- ptr_type_node,
- endlink)),
+ builtin_function ("__builtin_return", void_ftype_ptr,
BUILT_IN_RETURN, NULL_PTR);
/* Currently under experimentation. */
@@ -5180,47 +5858,64 @@ init_decl_processing ()
BUILT_IN_STRCMP, "strcmp");
builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
BUILT_IN_STRCPY, "strcpy");
-#if 0
- /* Not yet. */
- builtin_function ("__builtin_strncpy", strncpy_ftype,
- BUILT_IN_STRNCPY, "strncpy");
-#endif
- builtin_function ("__builtin_strlen", sizet_ftype_string,
+ builtin_function ("__builtin_strlen", strlen_ftype,
BUILT_IN_STRLEN, "strlen");
+ builtin_function ("__builtin_sqrtf", float_ftype_float,
+ BUILT_IN_FSQRT, "sqrtf");
+ builtin_function ("__builtin_fsqrt", double_ftype_double,
+ BUILT_IN_FSQRT, NULL_PTR);
+ builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
+ BUILT_IN_FSQRT, "sqrtl");
+ builtin_function ("__builtin_sinf", float_ftype_float,
+ BUILT_IN_SIN, "sinf");
+ builtin_function ("__builtin_sin", double_ftype_double,
+ BUILT_IN_SIN, "sin");
+ builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
+ BUILT_IN_SIN, "sinl");
+ builtin_function ("__builtin_cosf", float_ftype_float,
+ BUILT_IN_COS, "cosf");
+ builtin_function ("__builtin_cos", double_ftype_double,
+ BUILT_IN_COS, "cos");
+ builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
+ BUILT_IN_COS, "cosl");
if (!flag_no_builtin)
{
-#if 0 /* These do not work well with libg++. */
builtin_function ("abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR);
builtin_function ("fabs", double_ftype_double, BUILT_IN_FABS, NULL_PTR);
builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, NULL_PTR);
-#endif
+ builtin_function ("fabsf", float_ftype_float, BUILT_IN_FABS, NULL_PTR);
+ builtin_function ("fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS,
+ NULL_PTR);
builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR);
builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP,
NULL_PTR);
- builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, NULL_PTR);
+ builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP,
+ NULL_PTR);
builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY,
NULL_PTR);
-#if 0
- /* Not yet. */
- builtin_function ("strncpy", strncpy_ftype, BUILT_IN_STRNCPY, NULL_PTR);
-#endif
- builtin_function ("strlen", sizet_ftype_string, BUILT_IN_STRLEN, NULL_PTR);
+ builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, NULL_PTR);
+ builtin_function ("sqrtf", float_ftype_float, BUILT_IN_FSQRT, NULL_PTR);
+ builtin_function ("sqrt", double_ftype_double, BUILT_IN_FSQRT, NULL_PTR);
+ builtin_function ("sqrtl", ldouble_ftype_ldouble, BUILT_IN_FSQRT,
+ NULL_PTR);
+ builtin_function ("sinf", float_ftype_float, BUILT_IN_SIN, NULL_PTR);
builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR);
+ builtin_function ("sinl", ldouble_ftype_ldouble, BUILT_IN_SIN, NULL_PTR);
+ builtin_function ("cosf", float_ftype_float, BUILT_IN_COS, NULL_PTR);
builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR);
+ builtin_function ("cosl", ldouble_ftype_ldouble, BUILT_IN_COS, NULL_PTR);
/* Declare these functions volatile
to avoid spurious "control drops through" warnings. */
- temp = builtin_function ("abort",
- build_function_type (void_type_node, endlink),
+ temp = builtin_function ("abort", void_ftype,
NOT_BUILT_IN, NULL_PTR);
TREE_THIS_VOLATILE (temp) = 1;
TREE_SIDE_EFFECTS (temp) = 1;
/* Well, these are actually ANSI, but we can't set DECL_BUILT_IN on
them... */
DECL_BUILT_IN_NONANSI (temp) = 1;
- temp = builtin_function ("exit", build_function_type (void_type_node,
- int_endlink),
+ temp = builtin_function ("exit", void_ftype_int,
NOT_BUILT_IN, NULL_PTR);
TREE_THIS_VOLATILE (temp) = 1;
TREE_SIDE_EFFECTS (temp) = 1;
@@ -5230,42 +5925,39 @@ init_decl_processing ()
#if 0
/* Support for these has not been written in either expand_builtin
or build_function_call. */
- builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, 0);
- builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, 0);
+ builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, NULL_PTR);
+ builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, NULL_PTR);
builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR,
- 0);
- builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL, 0);
+ NULL_PTR);
+ builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL,
+ NULL_PTR);
builtin_function ("__builtin_fmod", double_ftype_double_double,
- BUILT_IN_FMOD, 0);
+ BUILT_IN_FMOD, NULL_PTR);
builtin_function ("__builtin_frem", double_ftype_double_double,
- BUILT_IN_FREM, 0);
- builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, BUILT_IN_MEMSET,
- 0);
+ BUILT_IN_FREM, NULL_PTR);
+ builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int,
+ BUILT_IN_MEMSET, NULL_PTR);
builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP,
- 0);
+ NULL_PTR);
builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN,
- 0);
+ NULL_PTR);
#endif
/* C++ extensions */
unknown_type_node = make_node (UNKNOWN_TYPE);
-#if 0 /* not yet, should get fixed properly later */
- pushdecl (make_type_decl (get_identifier ("unknown type"),
- unknown_type_node));
-#else
- decl = pushdecl (build_decl (TYPE_DECL, get_identifier ("unknown type"),
- unknown_type_node));
- /* Make sure the "unknown type" typedecl gets ignored for debug info. */
- DECL_IGNORED_P (decl) = 1;
- TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
-#endif
- TYPE_SIZE (unknown_type_node) = TYPE_SIZE (void_type_node);
- TYPE_ALIGN (unknown_type_node) = 1;
- TYPE_MODE (unknown_type_node) = TYPE_MODE (void_type_node);
+ record_unknown_type (unknown_type_node, "unknown type");
+
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
TREE_TYPE (unknown_type_node) = unknown_type_node;
- /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same result. */
+
+ if (flag_ansi)
+ TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0);
+ else
+ TREE_TYPE (null_node) = build_pointer_type (unknown_type_node);
+
+ /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same
+ result. */
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
@@ -5274,7 +5966,7 @@ init_decl_processing ()
TYPE_MAIN_VARIANT (opaque_type_node) = opaque_type_node;
record_builtin_type (RID_MAX, 0, opaque_type_node);
- /* This is special for C++ so functions can be overloaded. */
+ /* This is special for C++ so functions can be overloaded. */
wchar_type_node
= TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE)));
wchar_type_size = TYPE_PRECISION (wchar_type_node);
@@ -5295,14 +5987,6 @@ init_decl_processing ()
wchar_array_type_node
= build_array_type (wchar_type_node, array_domain_type);
- /* This is a hack that should go away when we deliver the
- real gc code. */
- if (flag_gc)
- {
- builtin_function ("__gc_main", default_function_type, NOT_BUILT_IN, 0);
- pushdecl (lookup_name (get_identifier ("__gc_main"), 0));
- }
-
if (flag_vtable_thunks)
{
/* Make sure we get a unique function type, so we can give
@@ -5381,254 +6065,79 @@ init_decl_processing ()
record_builtin_type (RID_MAX, SIGTABLE_PTR_TYPE, sigtable_entry_type);
}
-#if 0
- if (flag_rtti)
- {
- /* Must build __t_desc type. Currently, type descriptors look like this:
+ std_node = build_decl (NAMESPACE_DECL,
+ get_identifier (flag_honor_std ? "fake std":"std"),
+ void_type_node);
+ pushdecl (std_node);
- struct __t_desc
- {
- const char *name;
- int size;
- int bits;
- struct __t_desc *points_to;
- int ivars_count, meths_count;
- struct __i_desc *ivars[];
- struct __m_desc *meths[];
- struct __t_desc *parents[];
- struct __t_desc *vbases[];
- int offsets[];
- };
-
- ...as per Linton's paper. */
-
- __t_desc_type_node = make_lang_type (RECORD_TYPE);
- __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 (build_pointer_type (__t_desc_type_node), NULL_TREE);
- __i_desc_array_type =
- build_array_type (build_pointer_type (__i_desc_type_node), NULL_TREE);
- __m_desc_array_type =
- 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);
- fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("size"),
- unsigned_type_node);
- fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("bits"),
- unsigned_type_node);
- fields[3] = build_lang_field_decl (FIELD_DECL,
- get_identifier ("points_to"),
- build_pointer_type (__t_desc_type_node));
- fields[4] = build_lang_field_decl (FIELD_DECL,
- get_identifier ("ivars_count"),
- integer_type_node);
- fields[5] = build_lang_field_decl (FIELD_DECL,
- get_identifier ("meths_count"),
- integer_type_node);
- fields[6] = build_lang_field_decl (FIELD_DECL, get_identifier ("ivars"),
- build_pointer_type (__i_desc_array_type));
- fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("meths"),
- build_pointer_type (__m_desc_array_type));
- fields[8] = build_lang_field_decl (FIELD_DECL, get_identifier ("parents"),
- build_pointer_type (__t_desc_array_type));
- fields[9] = build_lang_field_decl (FIELD_DECL, get_identifier ("vbases"),
- build_pointer_type (__t_desc_array_type));
- fields[10] = build_lang_field_decl (FIELD_DECL, get_identifier ("offsets"),
- build_pointer_type (integer_type_node));
- finish_builtin_type (__t_desc_type_node, "__t_desc", fields, 10, integer_type_node);
-
- /* ivar descriptors look like this:
-
- struct __i_desc
- {
- const char *name;
- int offset;
- struct __t_desc *type;
- };
- */
-
- fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
- string_type_node);
- 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"),
- build_pointer_type (__t_desc_type_node));
- finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2,
- integer_type_node);
-
- /* method descriptors look like this:
-
- struct __m_desc
- {
- const char *name;
- int vindex;
- struct __t_desc *vcontext;
- struct __t_desc *return_type;
- void (*address)();
- short parm_count;
- short required_parms;
- struct __t_desc *parm_types[];
- };
- */
-
- fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
- string_type_node);
- 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"),
- build_pointer_type (__t_desc_type_node));
- fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("return_type"),
- 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"),
- short_integer_type_node);
- 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 (build_pointer_type (__t_desc_type_node), NULL_TREE)));
- finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7,
- integer_type_node);
- }
-
- if (flag_rtti)
- {
- int i = builtin_type_tdescs_len;
- while (i > 0)
- {
- tree tdesc = build_t_desc (builtin_type_tdescs_arr[--i], 0);
- TREE_ASM_WRITTEN (tdesc) = 1;
- TREE_PUBLIC (TREE_OPERAND (tdesc, 0)) = 1;
- }
- }
-#endif /*flag_rtti*/
+ global_type_node = make_node (LANG_TYPE);
+ record_unknown_type (global_type_node, "global type");
/* Now, C++. */
current_lang_name = lang_name_cplusplus;
- auto_function (ansi_opname[(int) NEW_EXPR],
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE, sizetype,
- void_list_node)),
- NOT_BUILT_IN);
- auto_function (ansi_opname[(int) VEC_NEW_EXPR],
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE, sizetype,
- void_list_node)),
- NOT_BUILT_IN);
- auto_function (ansi_opname[(int) DELETE_EXPR],
- build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- void_list_node)),
- NOT_BUILT_IN);
- auto_function (ansi_opname[(int) VEC_DELETE_EXPR],
- build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- void_list_node)),
- NOT_BUILT_IN);
+ {
+ tree bad_alloc_type_node, newtype, deltype;
+ if (flag_honor_std)
+ push_namespace (get_identifier ("std"));
+ bad_alloc_type_node = xref_tag
+ (class_type_node, get_identifier ("bad_alloc"), NULL_TREE, 1);
+ if (flag_honor_std)
+ pop_namespace ();
+ newtype = build_exception_variant
+ (ptr_ftype_sizetype, build_tree_list (NULL_TREE, bad_alloc_type_node));
+ deltype = build_exception_variant
+ (void_ftype_ptr, build_tree_list (NULL_TREE, NULL_TREE));
+ auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN);
+ auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN);
+ auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN);
+ auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype, NOT_BUILT_IN);
+ }
abort_fndecl
- = define_function ("__pure_virtual",
- build_function_type (void_type_node, void_list_node),
+ = define_function ("__pure_virtual", void_ftype,
NOT_BUILT_IN, 0, 0);
/* Perform other language dependent initializations. */
init_class_processing ();
init_init_processing ();
init_search_processing ();
+ if (flag_rtti)
+ init_rtti_processing ();
- if (flag_handle_exceptions)
+ if (flag_exceptions)
init_exception_processing ();
- if (flag_gc)
- init_gc_processing ();
if (flag_no_inline)
{
flag_inline_functions = 0;
-#if 0
- /* This causes unnecessary emission of inline functions. */
- flag_default_inline = 0;
-#endif
}
- if (flag_cadillac)
- init_cadillac ();
+
+ if (! supports_one_only ())
+ flag_weak = 0;
/* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
declare_function_name ();
/* Prepare to check format strings against argument lists. */
init_function_format_info ();
-}
-
-/* initialize type descriptor type node of various rtti type. */
-
-int
-init_type_desc()
-{
- tree tdecl;
-
- tdecl = lookup_name (get_identifier ("type_info"), 0);
- if (tdecl == NULL_TREE)
- return 0;
- __t_desc_type_node = TREE_TYPE(tdecl);
- __tp_desc_type_node = build_pointer_type (__t_desc_type_node);
-
-#if 0
- tdecl = lookup_name (get_identifier ("__baselist_type_info"), 0);
- if (tdecl == NULL_TREE)
- return 0;
- __baselist_desc_type_node = TREE_TYPE (tdecl);
-#endif
-
- tdecl = lookup_name (get_identifier ("__builtin_type_info"), 0);
- if (tdecl == NULL_TREE)
- return 0;
- __bltn_desc_type_node = TREE_TYPE (tdecl);
-
- tdecl = lookup_name (get_identifier ("__user_type_info"), 0);
- if (tdecl == NULL_TREE)
- return 0;
- __user_desc_type_node = TREE_TYPE (tdecl);
-
- tdecl = lookup_name (get_identifier ("__class_type_info"), 0);
- if (tdecl == NULL_TREE)
- return 0;
- __class_desc_type_node = TREE_TYPE (tdecl);
-
- tdecl = lookup_field (__class_desc_type_node,
- get_identifier ("access_mode"), 0, 0);
- if (tdecl == NULL_TREE)
- return 0;
- __access_mode_type_node = TREE_TYPE (tdecl);
-
- tdecl = lookup_name (get_identifier ("__attr_type_info"), 0);
- if (tdecl == NULL_TREE)
- return 0;
- __attr_desc_type_node = TREE_TYPE (tdecl);
- tdecl = lookup_name (get_identifier ("__pointer_type_info"), 0);
- if (tdecl == NULL_TREE)
- return 0;
- __ptr_desc_type_node = TREE_TYPE (tdecl);
+ /* Show we use EH for cleanups. */
+ using_eh_for_cleanups ();
- tdecl = lookup_name (get_identifier ("__func_type_info"), 0);
- if (tdecl == NULL_TREE)
- return 0;
- __func_desc_type_node = TREE_TYPE (tdecl);
-
- tdecl = lookup_name (get_identifier ("__ptmf_type_info"), 0);
- if (tdecl == NULL_TREE)
- return 0;
- __ptmf_desc_type_node = TREE_TYPE (tdecl);
+ print_error_function = lang_print_error_function;
+ lang_get_alias_set = &c_get_alias_set;
+}
- tdecl = lookup_name (get_identifier ("__ptmd_type_info"), 0);
- if (tdecl == NULL_TREE)
- return 0;
- __ptmd_desc_type_node = TREE_TYPE (tdecl);
+/* Function to print any language-specific context for an error message. */
- return 1;
+static void
+lang_print_error_function (file)
+ char *file;
+{
+ default_print_error_function (file);
+ maybe_print_template_context ();
}
+
/* Make a definition for a builtin function named NAME and whose data type
is TYPE. TYPE should be a function type with argument types.
FUNCTION_CODE tells later passes how to compile calls to this function.
@@ -5642,7 +6151,7 @@ define_function (name, type, function_code, pfn, library_name)
char *name;
tree type;
enum built_in_function function_code;
- void (*pfn)();
+ void (*pfn) PROTO((tree));
char *library_name;
{
tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type);
@@ -5650,6 +6159,9 @@ define_function (name, type, function_code, pfn, library_name)
TREE_PUBLIC (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
+ my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392);
+ DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+
/* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
we cannot change DECL_ASSEMBLER_NAME until we have installed this
function in the namespace. */
@@ -5693,10 +6205,20 @@ shadow_tag (declspecs)
code = TREE_CODE (value);
if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE)
{
- my_friendly_assert (TYPE_NAME (value) != NULL_TREE, 261);
+ my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
- if (code == ENUMERAL_TYPE && TYPE_SIZE (value) == 0)
- cp_error ("forward declaration of `%#T'", value);
+ if (IS_AGGR_TYPE (value) && CLASSTYPE_USE_TEMPLATE (value))
+ {
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (value)
+ && TYPE_SIZE (value) == NULL_TREE)
+ {
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (value);
+ if (processing_template_decl)
+ push_template_decl (TYPE_MAIN_DECL (value));
+ }
+ else if (CLASSTYPE_TEMPLATE_INSTANTIATION (value))
+ cp_error ("specialization after instantiation of `%T'", value);
+ }
t = value;
ok_code = code;
@@ -5724,16 +6246,38 @@ shadow_tag (declspecs)
|| (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))))
{
+ /* See also grok_x_components. */
+ tree *q;
+
+ /* Wipe out memory of synthesized methods */
+ TYPE_HAS_CONSTRUCTOR (t) = 0;
+ TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
+ TYPE_HAS_INIT_REF (t) = 0;
+ TYPE_HAS_CONST_INIT_REF (t) = 0;
+ TYPE_HAS_ASSIGN_REF (t) = 0;
+ TYPE_HAS_ASSIGNMENT (t) = 0;
+ TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
+
+ q = &TYPE_METHODS (t);
+ while (*q)
+ {
+ if (DECL_ARTIFICIAL (*q))
+ *q = TREE_CHAIN (*q);
+ else
+ q = &TREE_CHAIN (*q);
+ }
+
/* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have
function members. */
+ if (TYPE_METHODS (t))
+ error ("an anonymous union cannot have function members");
+
if (TYPE_FIELDS (t))
{
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
- NULL_TREE, NULL_TREE);
+ NULL_TREE);
finish_anon_union (decl);
}
- else
- error ("anonymous union cannot have a function member");
}
else
{
@@ -5754,7 +6298,7 @@ shadow_tag (declspecs)
}
if (found_tag == 0)
- pedwarn ("abstract declarator used as declaration");
+ cp_error ("abstract declarator used as declaration");
else if (found_tag > 1)
pedwarn ("multiple types in one declaration");
}
@@ -5770,7 +6314,7 @@ groktypename (typename)
return typename;
return grokdeclarator (TREE_VALUE (typename),
TREE_PURPOSE (typename),
- TYPENAME, 0, NULL_TREE, NULL_TREE);
+ TYPENAME, 0, NULL_TREE);
}
/* Decode a declarator in an ordinary declaration or data definition.
@@ -5793,10 +6337,10 @@ groktypename (typename)
int debug_temp_inits = 1;
tree
-start_decl (declarator, declspecs, initialized, raises)
+start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree declarator, declspecs;
int initialized;
- tree raises;
+ tree attributes, prefix_attributes;
{
register tree decl;
register tree type, tem;
@@ -5804,9 +6348,12 @@ start_decl (declarator, declspecs, initialized, raises)
extern int have_extern_spec;
extern int used_extern_spec;
+#if 0
+ /* See code below that used this. */
int init_written = initialized;
+#endif
- /* This should only be done once on the top most decl. */
+ /* This should only be done once on the top most decl. */
if (have_extern_spec && !used_extern_spec)
{
declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"),
@@ -5814,16 +6361,16 @@ start_decl (declarator, declspecs, initialized, raises)
used_extern_spec = 1;
}
- decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, raises,
+ decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
NULL_TREE);
- if (decl == NULL_TREE || decl == void_type_node)
+ if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return NULL_TREE;
type = TREE_TYPE (decl);
/* Don't lose if destructors must be executed at file-level. */
- if (TREE_STATIC (decl)
- && TYPE_NEEDS_DESTRUCTOR (type)
+ if (! processing_template_decl && TREE_STATIC (decl)
+ && TYPE_NEEDS_DESTRUCTOR (complete_type (type))
&& !TREE_PERMANENT (decl))
{
push_obstacks (&permanent_obstack, &permanent_obstack);
@@ -5841,60 +6388,22 @@ start_decl (declarator, declspecs, initialized, raises)
pop_obstacks ();
}
- /* Corresponding pop_obstacks is done in `cp_finish_decl'. */
- push_obstacks_nochange ();
-
context
= (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
? DECL_CLASS_CONTEXT (decl)
: DECL_CONTEXT (decl);
- if (processing_template_decl)
+ if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL
+ && context != current_namespace && TREE_CODE (decl) == VAR_DECL)
{
- tree d;
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- /* Declarator is a call_expr; extract arguments from it, since
- grokdeclarator didn't do it. */
- tree args;
- args = copy_to_permanent (last_function_parms);
- if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- {
- tree t = TREE_TYPE (decl);
-
- t = TYPE_METHOD_BASETYPE (t); /* type method belongs to */
- if (TREE_CODE (t) != UNINSTANTIATED_P_TYPE)
- {
- t = build_pointer_type (t); /* base type of `this' */
-#if 1
- /* I suspect this is wrong. */
- t = build_type_variant (t, flag_this_is_variable <= 0,
- 0); /* type of `this' */
-#else
- t = build_type_variant (t, 0, 0); /* type of `this' */
-#endif
- t = build (PARM_DECL, t, this_identifier);
- TREE_CHAIN (t) = args;
- args = t;
- }
- }
- DECL_ARGUMENTS (decl) = args;
- }
- d = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), TREE_TYPE (decl));
- TREE_PUBLIC (d) = TREE_PUBLIC (decl);
- TREE_STATIC (d) = TREE_STATIC (decl);
- DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl)
- && !(context && !DECL_THIS_EXTERN (decl)));
- DECL_TEMPLATE_RESULT (d) = decl;
- decl = d;
+ /* When parsing the initializer, lookup should use the object's
+ namespace. */
+ push_decl_namespace (context);
}
- /* If this type of object needs a cleanup, and control may
- jump past it, make a new binding level so that it is cleaned
- up only when it is initialized first. */
- if (TYPE_NEEDS_DESTRUCTOR (type)
- && current_binding_level->more_cleanups_ok == 0)
- pushlevel_temporary (1);
+ /* We are only interested in class contexts, later. */
+ if (context && TREE_CODE (context) == NAMESPACE_DECL)
+ context = NULL_TREE;
if (initialized)
/* Is it valid for this decl to have an initializer at all?
@@ -5919,51 +6428,30 @@ start_decl (declarator, declspecs, initialized, raises)
break;
default:
- /* Don't allow initializations for incomplete types except for
- arrays which might be completed by the initialization. */
- if (type == error_mark_node)
- ; /* Don't complain again. */
- else if (TYPE_SIZE (type) != NULL_TREE)
- ; /* A complete type is ok. */
- else if (TREE_CODE (type) != ARRAY_TYPE)
- {
- cp_error ("variable `%#D' has initializer but incomplete type",
- decl);
- initialized = 0;
- }
- else if (TYPE_SIZE (TREE_TYPE (type)) == NULL_TREE)
+ if (! processing_template_decl)
{
- cp_error ("elements of array `%#D' have incomplete type", decl);
- initialized = 0;
+ if (type != error_mark_node)
+ {
+ if (TYPE_SIZE (type) != NULL_TREE
+ && ! TREE_CONSTANT (TYPE_SIZE (type)))
+ {
+ cp_error
+ ("variable-sized object `%D' may not be initialized",
+ decl);
+ initialized = 0;
+ }
+
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
+ {
+ cp_error
+ ("elements of array `%#D' have incomplete type", decl);
+ initialized = 0;
+ }
+ }
}
}
- if (!initialized
- && TREE_CODE (decl) != TYPE_DECL
- && TREE_CODE (decl) != TEMPLATE_DECL
- && IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl))
- {
- if (TYPE_SIZE (type) == NULL_TREE)
- {
- cp_error ("aggregate `%#D' has incomplete type and cannot be initialized",
- decl);
- /* Change the type so that assemble_variable will give
- DECL an rtl we can live with: (mem (const_int 0)). */
- TREE_TYPE (decl) = error_mark_node;
- type = error_mark_node;
- }
- else
- {
- /* If any base type in the hierarchy of TYPE needs a constructor,
- then we set initialized to 1. This way any nodes which are
- created for the purposes of initializing this aggregate
- will live as long as it does. This is necessary for global
- aggregates which do not have their initializers processed until
- the end of the file. */
- initialized = TYPE_NEEDS_CONSTRUCTING (type);
- }
- }
-
if (initialized)
{
if (! toplevel_bindings_p ()
@@ -5971,7 +6459,7 @@ start_decl (declarator, declspecs, initialized, raises)
cp_warning ("declaration of `%#D' has `extern' and is initialized",
decl);
DECL_EXTERNAL (decl) = 0;
- if ( toplevel_bindings_p ())
+ if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1;
/* Tell `pushdecl' this is an initialized decl
@@ -5980,130 +6468,106 @@ start_decl (declarator, declspecs, initialized, raises)
DECL_INITIAL (decl) = error_mark_node;
}
- if (context && TYPE_SIZE (context) != NULL_TREE)
+ if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE)
{
if (TREE_CODE (decl) == VAR_DECL)
{
tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
cp_error ("`%#D' is not a static member of `%#T'", decl, context);
- else if (duplicate_decls (decl, field))
- decl = field;
+ else
+ {
+ if (DECL_CONTEXT (field) != context)
+ {
+ cp_pedwarn ("ANSI C++ does not permit `%T::%D' to be defined as `%T::%D'",
+ DECL_CONTEXT (field), DECL_NAME (decl),
+ context, DECL_NAME (decl));
+ DECL_CONTEXT (decl) = DECL_CONTEXT (field);
+ }
+ /* Static data member are tricky; an in-class initialization
+ still doesn't provide a definition, so the in-class
+ declaration will have DECL_EXTERNAL set, but will have an
+ initialization. Thus, duplicate_decls won't warn
+ about this situation, and so we check here. */
+ if (DECL_INITIAL (decl) && DECL_INITIAL (field))
+ cp_error ("duplicate initialization of %D", decl);
+ if (duplicate_decls (decl, field))
+ decl = field;
+ }
}
else
{
- tree field = check_classfn (context, NULL_TREE, decl);
+ tree field = check_classfn (context, 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))
+ DECL_IN_AGGR_P (decl) = 0;
+ if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
+ || CLASSTYPE_USE_TEMPLATE (context))
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
- /* Stupid stupid stupid stupid (jason 7/21/95) */
- if (pedantic && DECL_EXTERNAL (decl)
- && ! DECL_TEMPLATE_SPECIALIZATION (decl))
+ if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
cp_pedwarn ("declaration of `%#D' outside of class is not definition",
decl);
pushclass (context, 2);
}
+ /* Set attributes here so if duplicate decl, will have proper attributes. */
+ cplus_decl_attributes (decl, attributes, prefix_attributes);
+
/* Add this decl to the current binding level, but not if it
comes from another scope, e.g. a static member variable.
TEM may equal DECL or it may be a previous decl of the same name. */
- if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE)
- || (TREE_CODE (decl) == TEMPLATE_DECL && !global_bindings_p ())
- || TREE_CODE (type) == LANG_TYPE)
+ if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE
+ /* Definitions of namespace members outside their namespace are
+ possible. */
+ && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
+ || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
+ || TREE_CODE (type) == LANG_TYPE
+ /* The declaration of template specializations does not affect
+ the functions available for overload resolution, so we do not
+ call pushdecl. */
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_TEMPLATE_SPECIALIZATION (decl)))
tem = decl;
else
tem = pushdecl (decl);
-
- /* Tell the back-end to use or not use .common as appropriate. If we say
- -fconserve-space, we want this to save space, at the expense of wrong
- semantics. If we say -fno-conserve-space, we want this to produce
- errors about redefs; to do this we force variables into the data
- segment. Common storage is okay for non-public uninitialized data;
- the linker can't match it with storage from other files, and we may
- save some disk space. */
- DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem);
-#if 0
- /* We don't do this yet for GNU C++. */
- /* For a local variable, define the RTL now. */
- if (! toplevel_bindings_p ()
- /* But not if this is a duplicate decl
- and we preserved the rtl from the previous one
- (which may or may not happen). */
- && DECL_RTL (tem) == NULL_RTX)
+ if (processing_template_decl)
{
- if (TYPE_SIZE (TREE_TYPE (tem)) != NULL_TREE)
- expand_decl (tem);
- else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
- && DECL_INITIAL (tem) != NULL_TREE)
- expand_decl (tem);
+ if (! current_function_decl)
+ tem = push_template_decl (tem);
+ else if (minimal_parse_mode)
+ DECL_VINDEX (tem)
+ = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
+ copy_to_permanent (declspecs),
+ NULL_TREE);
}
+
+
+#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
+ /* Tell the back-end to use or not use .common as appropriate. If we say
+ -fconserve-space, we want this to save .data space, at the expense of
+ wrong semantics. If we say -fno-conserve-space, we want this to
+ produce errors about redefs; to do this we force variables into the
+ data segment. */
+ DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem);
#endif
- if (TREE_CODE (decl) == TEMPLATE_DECL)
- {
- tree result = DECL_TEMPLATE_RESULT (decl);
- if (DECL_CONTEXT (result) != NULL_TREE)
- {
- tree type;
- type = DECL_CONTEXT (result);
+ if (! processing_template_decl)
+ start_decl_1 (tem);
- if (TREE_CODE (type) != UNINSTANTIATED_P_TYPE)
- {
- cp_error ("declaration of `%D' in non-template type `%T'",
- decl, type);
- return NULL_TREE;
- }
+ /* Corresponding pop_obstacks is done in `cp_finish_decl'. */
+ push_obstacks_nochange ();
- if (TREE_CODE (result) == FUNCTION_DECL)
- return tem;
- else if (TREE_CODE (result) == VAR_DECL)
- {
#if 0
- tree tmpl = UPT_TEMPLATE (type);
-
- fprintf (stderr, "%s:%d: adding ", __FILE__, __LINE__);
- print_node_brief (stderr, "", DECL_NAME (tem), 0);
- fprintf (stderr, " to class %s\n",
- IDENTIFIER_POINTER (DECL_NAME (tmpl)));
- DECL_TEMPLATE_MEMBERS (tmpl)
- = perm_tree_cons (DECL_NAME (tem), tem,
- DECL_TEMPLATE_MEMBERS (tmpl));
- return tem;
-#else
- sorry ("static data member templates");
- return NULL_TREE;
-#endif
- }
- else
- my_friendly_abort (13);
- }
- else if (TREE_CODE (result) == FUNCTION_DECL)
- /*tem = push_overloaded_decl (tem, 0)*/;
- else if (TREE_CODE (result) == VAR_DECL)
- {
- cp_error ("data template `%#D' must be member of a class template",
- result);
- return NULL_TREE;
- }
- else if (TREE_CODE (result) == TYPE_DECL)
- {
- cp_error ("invalid template `%#D'", result);
- return NULL_TREE;
- }
- else
- my_friendly_abort (14);
- }
-
+ /* We have no way of knowing whether the initializer will need to be
+ evaluated at run-time or not until we've parsed it, so let's just put
+ it in the permanent obstack. (jason) */
if (init_written
&& ! (TREE_CODE (tem) == PARM_DECL
|| (TREE_READONLY (tem)
@@ -6114,7 +6578,8 @@ start_decl (declarator, declspecs, initialized, raises)
use temporary storage. Do this even if we will ignore the value. */
if (toplevel_bindings_p () && debug_temp_inits)
{
- if (TYPE_NEEDS_CONSTRUCTING (type)
+ if (processing_template_decl
+ || TYPE_NEEDS_CONSTRUCTING (type)
|| TREE_CODE (type) == REFERENCE_TYPE)
/* In this case, the initializer must lay down in permanent
storage, since it will be saved until `finish_file' is run. */
@@ -6123,81 +6588,108 @@ start_decl (declarator, declspecs, initialized, raises)
temporary_allocation ();
}
}
-
- if (flag_cadillac)
- cadillac_start_decl (tem);
+#endif
return tem;
}
-#if 0 /* unused */
-static void
-make_temporary_for_reference (decl, ctor_call, init, cleanupp)
- tree decl, ctor_call, init;
- tree *cleanupp;
+void
+start_decl_1 (decl)
+ tree decl;
{
tree type = TREE_TYPE (decl);
- tree target_type = TREE_TYPE (type);
- tree tmp, tmp_addr;
+ int initialized = (DECL_INITIAL (decl) != NULL_TREE);
- if (ctor_call)
- {
- tmp_addr = TREE_VALUE (TREE_OPERAND (ctor_call, 1));
- if (TREE_CODE (tmp_addr) == NOP_EXPR)
- tmp_addr = TREE_OPERAND (tmp_addr, 0);
- my_friendly_assert (TREE_CODE (tmp_addr) == ADDR_EXPR, 146);
- tmp = TREE_OPERAND (tmp_addr, 0);
- }
- else
+ /* If this type of object needs a cleanup, and control may
+ jump past it, make a new binding level so that it is cleaned
+ up only when it is initialized first. */
+ if (TYPE_NEEDS_DESTRUCTOR (type)
+ && current_binding_level->more_cleanups_ok == 0)
+ pushlevel_temporary (1);
+
+ if (initialized)
+ /* Is it valid for this decl to have an initializer at all?
+ If not, set INITIALIZED to zero, which will indirectly
+ tell `cp_finish_decl' to ignore the initializer once it is parsed. */
{
- tmp = get_temp_name (target_type, toplevel_bindings_p ());
- tmp_addr = build_unary_op (ADDR_EXPR, tmp, 0);
+ /* Don't allow initializations for incomplete types except for
+ arrays which might be completed by the initialization. */
+ if (type == error_mark_node)
+ ; /* Don't complain again. */
+ else if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
+ ; /* A complete type is ok. */
+ else if (TREE_CODE (type) != ARRAY_TYPE)
+ {
+ cp_error ("variable `%#D' has initializer but incomplete type",
+ decl);
+ initialized = 0;
+ type = TREE_TYPE (decl) = error_mark_node;
+ }
+ else if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
+ {
+ if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
+ cp_error ("elements of array `%#D' have incomplete type", decl);
+ /* else we already gave an error in start_decl. */
+ initialized = 0;
+ }
}
- TREE_TYPE (tmp_addr) = build_pointer_type (target_type);
- DECL_INITIAL (decl) = convert (build_pointer_type (target_type), tmp_addr);
- TREE_TYPE (DECL_INITIAL (decl)) = type;
- if (TYPE_NEEDS_CONSTRUCTING (target_type))
+ if (!initialized
+ && TREE_CODE (decl) != TYPE_DECL
+ && TREE_CODE (decl) != TEMPLATE_DECL
+ && IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl))
{
- if (toplevel_bindings_p ())
+ if ((! processing_template_decl || ! uses_template_parms (type))
+ && TYPE_SIZE (complete_type (type)) == NULL_TREE)
{
- /* lay this variable out now. Otherwise `output_addressed_constants'
- gets confused by its initializer. */
- make_decl_rtl (tmp, NULL_PTR, 1);
- static_aggregates = perm_tree_cons (init, tmp, static_aggregates);
+ cp_error ("aggregate `%#D' has incomplete type and cannot be initialized",
+ decl);
+ /* Change the type so that assemble_variable will give
+ DECL an rtl we can live with: (mem (const_int 0)). */
+ type = TREE_TYPE (decl) = error_mark_node;
}
else
{
- if (ctor_call != NULL_TREE)
- init = ctor_call;
- else
- init = build_method_call (tmp, constructor_name_full (target_type),
- build_tree_list (NULL_TREE, init),
- NULL_TREE, LOOKUP_NORMAL);
- DECL_INITIAL (decl) = build (COMPOUND_EXPR, type, init,
- DECL_INITIAL (decl));
- *cleanupp = maybe_build_cleanup (tmp);
+ /* If any base type in the hierarchy of TYPE needs a constructor,
+ then we set initialized to 1. This way any nodes which are
+ created for the purposes of initializing this aggregate
+ will live as long as it does. This is necessary for global
+ aggregates which do not have their initializers processed until
+ the end of the file. */
+ initialized = TYPE_NEEDS_CONSTRUCTING (type);
}
}
- else
+
+#if 0
+ /* We don't do this yet for GNU C++. */
+ /* For a local variable, define the RTL now. */
+ if (! toplevel_bindings_p ()
+ /* But not if this is a duplicate decl
+ and we preserved the rtl from the previous one
+ (which may or may not happen). */
+ && DECL_RTL (tem) == NULL_RTX)
{
- DECL_INITIAL (tmp) = init;
- TREE_STATIC (tmp) = toplevel_bindings_p ();
- cp_finish_decl (tmp, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
+ if (TYPE_SIZE (TREE_TYPE (tem)) != NULL_TREE)
+ expand_decl (tem);
+ else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
+ && DECL_INITIAL (tem) != NULL_TREE)
+ expand_decl (tem);
}
- if (TREE_STATIC (tmp))
- preserve_initializer ();
-}
#endif
+ if (! initialized)
+ DECL_INITIAL (decl) = NULL_TREE;
+}
+
/* Handle initialization of references.
- These three arguments from from `cp_finish_decl', and have the
- same meaning here that they do there. */
-/* quotes on semantics can be found in ARM 8.4.3. */
+ These three arguments are from `cp_finish_decl', and have the
+ same meaning here that they do there.
+
+ Quotes on semantics can be found in ARM 8.4.3. */
+
static void
-grok_reference_init (decl, type, init, cleanupp)
+grok_reference_init (decl, type, init)
tree decl, type, init;
- tree *cleanupp;
{
tree tmp;
@@ -6224,6 +6716,10 @@ grok_reference_init (decl, type, init, cleanupp)
return;
}
+ if (TREE_TYPE (init) && TREE_CODE (TREE_TYPE (init)) == UNKNOWN_TYPE)
+ /* decay_conversion is probably wrong for references to functions. */
+ init = decay_conversion (instantiate_type (TREE_TYPE (type), init, 1));
+
if (TREE_CODE (init) == TREE_LIST)
init = build_compound_expr (init);
@@ -6238,39 +6734,14 @@ grok_reference_init (decl, type, init, cleanupp)
}
tmp = convert_to_reference
- (type, init, CONV_IMPLICIT, LOOKUP_SPECULATIVELY|LOOKUP_NORMAL, decl);
+ (type, init, CONV_IMPLICIT,
+ LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl);
if (tmp == error_mark_node)
goto fail;
else if (tmp != NULL_TREE)
{
- tree subtype = TREE_TYPE (type);
init = tmp;
-
- /* Associate the cleanup with the reference so that we
- don't get burned by "aggressive" cleanup policy. */
- if (TYPE_NEEDS_DESTRUCTOR (subtype))
- {
- if (TREE_CODE (init) == WITH_CLEANUP_EXPR)
- {
- *cleanupp = TREE_OPERAND (init, 2);
- TREE_OPERAND (init, 2) = error_mark_node;
- }
- else
- {
- if (TREE_CODE (tmp) == ADDR_EXPR)
- tmp = TREE_OPERAND (tmp, 0);
- if (TREE_CODE (tmp) == TARGET_EXPR)
- {
- *cleanupp = build_delete
- (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;
- }
- }
- }
-
DECL_INITIAL (decl) = save_expr (init);
}
else
@@ -6318,10 +6789,12 @@ obscure_complex_init (decl, init)
return NULL_TREE;
}
+#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
if (toplevel_bindings_p () && ! DECL_COMMON (decl))
DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE,
NULL_TREE);
else
+#endif
DECL_INITIAL (decl) = error_mark_node;
return init;
@@ -6357,11 +6830,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
int flags;
{
register tree type;
- tree cleanup = NULL_TREE, ttype;
+ tree cleanup = NULL_TREE, ttype = NULL_TREE;
int was_incomplete;
int temporary = allocation_temporary_p ();
char *asmspec = NULL;
int was_readonly = 0;
+ int already_used = 0;
/* If this is 0, then we did not change obstacks. */
if (! decl)
@@ -6375,6 +6849,23 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
+ if (init && TREE_CODE (init) == NAMESPACE_DECL)
+ {
+ cp_error ("Cannot initialize `%D' to namespace `%D'",
+ decl, init);
+ init = NULL_TREE;
+ }
+
+ if (TREE_CODE (decl) == VAR_DECL
+ && DECL_CONTEXT (decl)
+ && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
+ && DECL_CONTEXT (decl) != current_namespace
+ && init)
+ {
+ /* Leave the namespace of the object. */
+ pop_decl_namespace ();
+ }
+
/* If the type of the thing we are declaring either has
a constructor, or has a virtual function table pointer,
AND its initialization was accepted by `start_decl',
@@ -6391,8 +6882,27 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
return;
}
- was_incomplete = (DECL_SIZE (decl) == NULL_TREE);
+ if (processing_template_decl)
+ {
+ if (init && DECL_INITIAL (decl))
+ DECL_INITIAL (decl) = init;
+ if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl))
+ {
+ tree stmt = DECL_VINDEX (decl);
+ /* If the decl is declaring a member of a local class (in a
+ template function), the DECL_VINDEX will either be NULL,
+ or it will be an actual virtual function index, not a
+ DECL_STMT. */
+ if (stmt != NULL_TREE && TREE_CODE (stmt) == DECL_STMT)
+ {
+ DECL_VINDEX (decl) = NULL_TREE;
+ TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
+ add_tree (stmt);
+ }
+ }
+ goto finish_end0;
+ }
/* Take care of TYPE_DECLs up front. */
if (TREE_CODE (decl) == TYPE_DECL)
{
@@ -6411,35 +6921,21 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
CLASSTYPE_GOT_SEMICOLON (type) = 1;
}
GNU_xref_decl (current_function_decl, decl);
+
+ /* If we have installed this as the canonical typedef for this
+ type, and that type has not been defined yet, delay emitting
+ the debug information for it, as we will emit it later. */
+ if (TYPE_MAIN_DECL (TREE_TYPE (decl)) == decl
+ && TYPE_SIZE (TREE_TYPE (decl)) == NULL_TREE)
+ TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
+
rest_of_decl_compilation (decl, NULL_PTR,
- DECL_CONTEXT (decl) == NULL_TREE, 0);
+ DECL_CONTEXT (decl) == NULL_TREE, at_eof);
goto finish_end;
}
if (TREE_CODE (decl) != FUNCTION_DECL)
{
ttype = target_type (type);
-#if 0 /* WTF? -KR
- Leave this out until we can figure out why it was
- needed/desirable in the first place. Then put a comment
- here explaining why. Or just delete the code if no ill
- effects arise. */
- if (TYPE_NAME (ttype)
- && TREE_CODE (TYPE_NAME (ttype)) == TYPE_DECL
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (ttype)))
- {
- tree old_id = TYPE_IDENTIFIER (ttype);
- char *newname = (char *)alloca (IDENTIFIER_LENGTH (old_id) + 2);
- /* Need to preserve template data for UPT nodes. */
- tree old_template = IDENTIFIER_TEMPLATE (old_id);
- newname[0] = '_';
- bcopy (IDENTIFIER_POINTER (old_id), newname + 1,
- IDENTIFIER_LENGTH (old_id) + 1);
- old_id = get_identifier (newname);
- lookup_tag_reverse (ttype, old_id);
- TYPE_IDENTIFIER (ttype) = old_id;
- IDENTIFIER_TEMPLATE (old_id) = old_template;
- }
-#endif
}
if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl)
@@ -6480,7 +6976,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
make_decl_rtl (decl, NULL_PTR,
toplevel_bindings_p ()
|| pseudo_global_level_p ());
- grok_reference_init (decl, type, init, &cleanup);
+ grok_reference_init (decl, type, init);
init = NULL_TREE;
}
@@ -6620,7 +7116,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (TREE_CODE (decl) == VAR_DECL)
{
if (DECL_SIZE (decl) == NULL_TREE
- && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
+ && TYPE_SIZE (complete_type (TREE_TYPE (decl))) != NULL_TREE)
layout_decl (decl, 0);
if (TREE_STATIC (decl) && DECL_SIZE (decl) == NULL_TREE)
@@ -6645,8 +7141,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
/* Let debugger know it should output info for this type. */
note_debug_info_needed (ttype);
- if (TREE_STATIC (decl) && DECL_CONTEXT (decl)
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
+ if (TREE_STATIC (decl) && DECL_CLASS_SCOPE_P (decl))
note_debug_info_needed (DECL_CONTEXT (decl));
if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
@@ -6659,21 +7154,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
cp_error ("storage size of `%D' isn't constant", decl);
}
- if (!DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type))
+ if (! DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type)
+ /* Cleanups for static variables are handled by `finish_file'. */
+ && ! TREE_STATIC (decl))
{
int yes = suspend_momentary ();
-
- /* If INIT comes from a functional cast, use the cleanup
- we built for that. Otherwise, make our own cleanup. */
- if (init && TREE_CODE (init) == WITH_CLEANUP_EXPR
- && comptypes (TREE_TYPE (decl), TREE_TYPE (init), 1))
- {
- cleanup = TREE_OPERAND (init, 2);
- init = TREE_OPERAND (init, 0);
- current_binding_level->have_cleanups = 1;
- }
- else
- cleanup = maybe_build_cleanup (decl);
+ cleanup = maybe_build_cleanup (decl);
resume_momentary (yes);
}
}
@@ -6691,24 +7177,96 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
unless the type is an undefined structure or union.
If not, it will get done when the type is completed. */
+ was_incomplete = (DECL_SIZE (decl) == NULL_TREE);
+
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == RESULT_DECL)
{
/* ??? FIXME: What about nested classes? */
int toplev = toplevel_bindings_p () || pseudo_global_level_p ();
int was_temp
- = ((flag_traditional
- || (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)))
+ = (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
&& allocation_temporary_p ());
if (was_temp)
end_temporary_allocation ();
+ /* Static data in a function with comdat linkage also has comdat
+ linkage. */
if (TREE_CODE (decl) == VAR_DECL
- && ! toplevel_bindings_p ()
- && ! TREE_STATIC (decl)
- && type_needs_gc_entry (type))
- DECL_GC_OFFSET (decl) = size_int (++current_function_obstack_index);
+ && TREE_STATIC (decl)
+ /* Don't mess with __FUNCTION__. */
+ && ! TREE_ASM_WRITTEN (decl)
+ && current_function_decl
+ && DECL_CONTEXT (decl) == current_function_decl
+ && (DECL_THIS_INLINE (current_function_decl)
+ || DECL_TEMPLATE_INSTANTIATION (current_function_decl))
+ && TREE_PUBLIC (current_function_decl))
+ {
+ /* Rather than try to get this right with inlining, we suppress
+ inlining of such functions. */
+ current_function_cannot_inline
+ = "function with static variable cannot be inline";
+
+ /* If flag_weak, we don't need to mess with this, as we can just
+ make the function weak, and let it refer to its unique local
+ copy. This works because we don't allow the function to be
+ inlined. */
+ if (! flag_weak)
+ {
+ if (DECL_INTERFACE_KNOWN (current_function_decl))
+ {
+ TREE_PUBLIC (decl) = 1;
+ DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
+ }
+ else if (DECL_INITIAL (decl) == NULL_TREE
+ || DECL_INITIAL (decl) == error_mark_node)
+ {
+ TREE_PUBLIC (decl) = 1;
+ DECL_COMMON (decl) = 1;
+ }
+ /* else we lose. We can only do this if we can use common,
+ which we can't if it has been initialized. */
+
+ if (TREE_PUBLIC (decl))
+ DECL_ASSEMBLER_NAME (decl)
+ = build_static_name (current_function_decl, DECL_NAME (decl));
+ else if (! DECL_ARTIFICIAL (decl))
+ {
+ cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
+ cp_warning_at (" you can work around this by removing the initializer"), decl;
+ }
+ }
+ }
+
+ else if (TREE_CODE (decl) == VAR_DECL
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_COMDAT (decl))
+ {
+ /* Dynamically initialized vars go into common. */
+ if (DECL_INITIAL (decl) == NULL_TREE
+ || DECL_INITIAL (decl) == error_mark_node)
+ DECL_COMMON (decl) = 1;
+ else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
+ {
+ DECL_COMMON (decl) = 1;
+ DECL_INITIAL (decl) = error_mark_node;
+ }
+ else
+ {
+ /* Statically initialized vars are weak or comdat, if
+ supported. */
+ if (flag_weak)
+ make_decl_one_only (decl);
+ else
+ {
+ /* We can't do anything useful; leave vars for explicit
+ instantiation. */
+ DECL_EXTERNAL (decl) = 1;
+ DECL_NOT_REALLY_EXTERN (decl) = 0;
+ }
+ }
+ }
if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
make_decl_rtl (decl, NULL_PTR, toplev);
@@ -6751,7 +7309,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
make_decl_rtl (decl, asmspec, toplev);
}
else
- rest_of_decl_compilation (decl, asmspec, toplev, 0);
+ rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
}
else if (TREE_CODE (decl) == VAR_DECL
&& DECL_LANG_SPECIFIC (decl)
@@ -6772,14 +7330,14 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
make_decl_rtl (decl, asmspec, 1);
}
else
- rest_of_decl_compilation (decl, asmspec, toplev, 0);
+ rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
}
else
/* Just a constant field. Should not need any rtl. */
goto finish_end0;
}
else
- rest_of_decl_compilation (decl, asmspec, toplev, 0);
+ rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
if (was_temp)
resume_temporary_allocation ();
@@ -6804,22 +7362,22 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (TREE_CODE (decl) == FUNCTION_DECL)
;
- else if (DECL_EXTERNAL (decl))
- ;
+ else if (DECL_EXTERNAL (decl)
+ && ! (DECL_LANG_SPECIFIC (decl)
+ && DECL_NOT_REALLY_EXTERN (decl)))
+ {
+ if (init)
+ DECL_INITIAL (decl) = init;
+ }
else if (TREE_STATIC (decl) && type != error_mark_node)
{
/* Cleanups for static variables are handled by `finish_file'. */
if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
|| TYPE_NEEDS_DESTRUCTOR (type))
expand_static_init (decl, init);
-
- /* Make entry in appropriate vector. */
- if (flag_gc && type_needs_gc_entry (type))
- build_static_gc_entry (decl, type);
}
else if (! toplev)
{
- tree old_cleanups = cleanups_this_call;
/* This is a declared decl which must live until the
end of the binding contour. It may need a cleanup. */
@@ -6846,7 +7404,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 (! cp_expand_decl_cleanup (NULL_TREE, cleanup))
+ if (! expand_decl_cleanup (NULL_TREE, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
/* Cleanup used up here. */
@@ -6854,10 +7412,59 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
}
}
+ if (current_binding_level->is_for_scope)
+ {
+ struct binding_level *outer = current_binding_level->level_chain;
+
+ /* Check to see if the same name is already bound at
+ the outer level, either because it was directly declared,
+ or because a dead for-decl got preserved. In either case,
+ the code would not have been valid under the ARM
+ scope rules, so clear is_for_scope for the
+ current_binding_level.
+
+ Otherwise, we need to preserve the temp slot for decl
+ to last into the outer binding level. */
+
+ int handling_dead_for_vars = 0;
+ tree link = outer->names;
+ for (; ; link = TREE_CHAIN (link))
+ {
+ if (link == NULL && handling_dead_for_vars == 0)
+ {
+ link = outer->dead_vars_from_for;
+ handling_dead_for_vars = 1;
+ }
+ if (link == NULL)
+ {
+ if (DECL_IN_MEMORY_P (decl))
+ preserve_temp_slots (DECL_RTL (decl));
+ break;
+ }
+ if (DECL_NAME (link) == DECL_NAME (decl))
+ {
+ if (handling_dead_for_vars)
+ {
+ tree shadowing
+ = purpose_member (DECL_NAME (decl),
+ current_binding_level->shadowed);
+ if (shadowing && TREE_VALUE (shadowing) == link)
+ TREE_VALUE (shadowing)
+ = DECL_SHADOWED_FOR_VAR (link);
+ }
+ current_binding_level->is_for_scope = 0;
+ break;
+ }
+ }
+ }
+
+ expand_start_target_temps ();
+
if (DECL_SIZE (decl) && type != error_mark_node)
{
/* Compute and store the initial value. */
expand_decl_init (decl);
+ already_used = TREE_USED (decl) || TREE_USED (type);
if (init || TYPE_NEEDS_CONSTRUCTING (type))
{
@@ -6870,19 +7477,34 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
was initialized was ever used. Don't do this if it has a
destructor, so we don't complain about the 'resource
allocation is initialization' idiom. */
- if (TYPE_NEEDS_CONSTRUCTING (type) && cleanup == NULL_TREE)
+ /* Now set attribute((unused)) on types so decls of
+ that type will be marked used. (see TREE_USED, above.)
+ This avoids the warning problems this particular code
+ tried to work around. */
+
+ if (TYPE_NEEDS_CONSTRUCTING (type)
+ && ! already_used
+ && cleanup == NULL_TREE
+ && DECL_NAME (decl))
TREE_USED (decl) = 0;
+ if (already_used)
+ TREE_USED (decl) = 1;
+ }
+
+ /* Cleanup any temporaries needed for the initial value. */
+ expand_end_target_temps ();
+
+ if (DECL_SIZE (decl) && type != error_mark_node)
+ {
/* Store the cleanup, if there was one. */
if (cleanup)
{
- if (! cp_expand_decl_cleanup (decl, cleanup))
+ if (! expand_decl_cleanup (decl, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
}
}
- /* Cleanup any temporaries needed for the initial value. */
- expand_cleanups_to (old_cleanups);
}
finish_end0:
@@ -6896,18 +7518,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
&& (TREE_CODE (decl) == VAR_DECL
/* We also have a pushclass done that we need to undo here
if we're at top level and declare a method. */
- || (TREE_CODE (decl) == FUNCTION_DECL
- /* If size hasn't been set, we're still defining it,
- and therefore inside the class body; don't pop
- the binding level.. */
- && TYPE_SIZE (context) != NULL_TREE
- /* The binding level gets popped elsewhere for a
- friend declaration inside another class. */
- /*
- && TYPE_IDENTIFIER (context) == current_class_name
- */
- && context == current_class_type
- )))
+ || TREE_CODE (decl) == FUNCTION_DECL)
+ /* If size hasn't been set, we're still defining it,
+ and therefore inside the class body; don't pop
+ the binding level.. */
+ && TYPE_SIZE (context) != NULL_TREE
+ && context == current_class_type)
popclass (1);
}
}
@@ -6917,6 +7533,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
/* If requested, warn about definitions of large data objects. */
if (warn_larger_than
+ && ! processing_template_decl
&& (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
&& !DECL_EXTERNAL (decl))
{
@@ -6941,12 +7558,10 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (was_readonly)
TREE_READONLY (decl) = 1;
-
- if (flag_cadillac)
- cadillac_finish_decl (decl);
}
/* This is here for a midend callback from c-common.c */
+
void
finish_decl (decl, init, asmspec_tree)
tree decl, init;
@@ -6961,7 +7576,6 @@ expand_static_init (decl, init)
tree init;
{
tree oldstatic = value_member (decl, static_aggregates);
- tree old_cleanups;
if (oldstatic)
{
@@ -6973,7 +7587,7 @@ expand_static_init (decl, init)
/* Emit code to perform this initialization but once. */
tree temp;
- /* Remember this information until end of file. */
+ /* Remember this information until end of file. */
push_obstacks (&permanent_obstack, &permanent_obstack);
/* Emit code to perform this initialization but once. */
@@ -6981,7 +7595,8 @@ expand_static_init (decl, init)
rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
expand_start_cond (build_binary_op (EQ_EXPR, temp,
integer_zero_node, 1), 0);
- old_cleanups = cleanups_this_call;
+ expand_start_target_temps ();
+
expand_assignment (temp, integer_one_node, 0, 0);
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
|| (init && TREE_CODE (init) == TREE_LIST))
@@ -6993,7 +7608,43 @@ expand_static_init (decl, init)
expand_assignment (decl, init, 0, 0);
/* Cleanup any temporaries needed for the initial value. */
- expand_cleanups_to (old_cleanups);
+ expand_end_target_temps ();
+
+ if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
+ {
+ tree cleanup, fcall;
+ static tree Atexit = 0;
+ if (Atexit == 0)
+ {
+ tree atexit_fndecl, PFV, pfvlist;
+ /* Remember this information until end of file. */
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ PFV = build_pointer_type (build_function_type
+ (void_type_node, void_list_node));
+
+ pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
+
+ push_lang_context (lang_name_c);
+ atexit_fndecl
+ = builtin_function ("atexit",
+ build_function_type (void_type_node,
+ pfvlist),
+ NOT_BUILT_IN, NULL_PTR);
+ assemble_external (atexit_fndecl);
+ Atexit = default_conversion (atexit_fndecl);
+ pop_lang_context ();
+ pop_obstacks ();
+ }
+
+ cleanup = start_anon_func ();
+ expand_expr_stmt (build_cleanup (decl));
+ end_anon_func ();
+ mark_addressable (cleanup);
+ cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
+ fcall = build_function_call (Atexit, expr_tree_cons (NULL_TREE, cleanup, NULL_TREE));
+ expand_expr_stmt (fcall);
+ }
+
expand_end_cond ();
if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
{
@@ -7001,7 +7652,7 @@ expand_static_init (decl, init)
TREE_STATIC (static_aggregates) = 1;
}
- /* Resume old (possibly temporary) allocation. */
+ /* Resume old (possibly temporary) allocation. */
pop_obstacks ();
}
else
@@ -7100,6 +7751,7 @@ complete_array_type (type, initial_value, do_default)
/* Return zero if something is declared to be a member of type
CTYPE when in the context of CUR_TYPE. STRING is the error
message to print in that case. Otherwise, quietly return 1. */
+
static int
member_function_or_else (ctype, cur_type, string)
tree ctype, cur_type;
@@ -7117,6 +7769,7 @@ member_function_or_else (ctype, cur_type, string)
/* Generate errors possibly applicable for a given set of specifiers.
This is for ARM $7.1.2. */
+
static void
bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
tree object;
@@ -7147,18 +7800,23 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
RAISES is a list of exceptions that this function can raise.
CHECK is 1 if we must find this method in CTYPE, 0 if we should
not look, and -1 if we should not call `grokclassfn' at all. */
+
static tree
-grokfndecl (ctype, type, declarator, virtualp, flags, quals,
- raises, attrlist, check, publicp, inlinep)
+grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
+ raises, attrlist, check, friendp, publicp, inlinep, funcdef_flag,
+ template_count, in_namespace)
tree ctype, type;
tree declarator;
+ tree orig_declarator;
int virtualp;
enum overload_flags flags;
tree quals, raises, attrlist;
- int check, publicp, inlinep;
+ int check, friendp, publicp, inlinep, funcdef_flag, template_count;
+ tree in_namespace;
{
tree cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
+ tree t;
if (ctype)
cname = TREE_CODE (TYPE_NAME (ctype)) == TYPE_DECL
@@ -7169,26 +7827,28 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (raises)
{
type = build_exception_variant (type, raises);
- raises = TYPE_RAISES_EXCEPTIONS (type);
}
+
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
- /* propagate volatile out from type to decl */
+ /* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type))
- TREE_THIS_VOLATILE (decl) = 1;
+ TREE_THIS_VOLATILE (decl) = 1;
+
+ /* This decl is not from the current namespace. */
+ if (in_namespace)
+ set_decl_namespace (decl, in_namespace);
/* Should probably propagate const out from type to decl I bet (mrs). */
if (staticp)
{
DECL_STATIC_FUNCTION_P (decl) = 1;
DECL_CONTEXT (decl) = ctype;
- DECL_CLASS_CONTEXT (decl) = ctype;
}
- /* All function decls start out public; we'll fix their linkage later (at
- definition or EOF) if appropriate. */
- TREE_PUBLIC (decl) = 1;
+ if (ctype)
+ DECL_CLASS_CONTEXT (decl) = ctype;
- if (ctype == NULL_TREE && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
+ if (ctype == NULL_TREE && MAIN_NAME_P (declarator))
{
if (inlinep)
error ("cannot declare `main' to be inline");
@@ -7198,8 +7858,12 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
publicp = 1;
}
+ TREE_PUBLIC (decl) = publicp;
if (! publicp)
- DECL_C_STATIC (decl) = 1;
+ {
+ DECL_INTERFACE_KNOWN (decl) = 1;
+ DECL_NOT_REALLY_EXTERN (decl) = 1;
+ }
if (inlinep)
DECL_THIS_INLINE (decl) = DECL_INLINE (decl) = 1;
@@ -7215,10 +7879,43 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
grok_op_properties (decl, virtualp, check < 0);
+ if (ctype && hack_decl_function_context (decl))
+ DECL_NO_STATIC_CHAIN (decl) = 1;
+
+ for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
+ if (TREE_PURPOSE (t)
+ && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
+ {
+ add_defarg_fn (decl);
+ break;
+ }
+
+ if (friendp
+ && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
+ {
+ if (funcdef_flag)
+ cp_error
+ ("defining explicit specialization `%D' in friend declaration",
+ orig_declarator);
+ else
+ {
+ /* A friend declaration of the form friend void f<>(). Record
+ the information in the TEMPLATE_ID_EXPR. */
+ SET_DECL_IMPLICIT_INSTANTIATION (decl);
+ DECL_TEMPLATE_INFO (decl)
+ = perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
+ TREE_OPERAND (orig_declarator, 1),
+ NULL_TREE);
+ }
+ }
+
/* Caller will do the rest of this. */
if (check < 0)
return decl;
+ if (check && funcdef_flag)
+ DECL_INITIAL (decl) = error_mark_node;
+
if (flags == NO_SPECIAL && ctype && constructor_name (cname) == declarator)
{
tree tmp;
@@ -7230,26 +7927,40 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
DECL_CONSTRUCTOR_P (decl) = 1;
grokclassfn (ctype, declarator, decl, flags, quals);
- if (check)
- check_classfn (ctype, declarator, decl);
+
+ decl = check_explicit_specialization (orig_declarator, decl,
+ template_count,
+ 2 * (funcdef_flag != 0) +
+ 4 * (friendp != 0));
+
+ if ((! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
+ && check)
+ {
+ tmp = check_classfn (ctype, decl);
+
+ if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
+ tmp = DECL_TEMPLATE_RESULT(tmp);
+
+ if (tmp && DECL_ARTIFICIAL (tmp))
+ cp_error ("definition of implicitly-declared `%D'", tmp);
+ if (tmp && duplicate_decls (decl, tmp))
+ return tmp;
+ }
if (! grok_ctor_properties (ctype, decl))
return NULL_TREE;
if (check == 0 && ! current_function_decl)
{
- /* FIXME: this should only need to look at
- IDENTIFIER_GLOBAL_VALUE. */
- tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
+ /* Assembler names live in the global namespace. */
+ tmp = IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl));
if (tmp == NULL_TREE)
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
+ SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl), decl);
else if (TREE_CODE (tmp) != TREE_CODE (decl))
cp_error ("inconsistent declarations for `%D'", decl);
else
{
duplicate_decls (decl, tmp);
decl = tmp;
- /* avoid creating circularities. */
- DECL_CHAIN (decl) = NULL_TREE;
}
make_decl_rtl (decl, NULL_PTR, 1);
}
@@ -7264,8 +7975,36 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (ctype != NULL_TREE)
grokclassfn (ctype, cname, decl, flags, quals);
- if (ctype != NULL_TREE && check)
- check_classfn (ctype, cname, decl);
+ decl = check_explicit_specialization (orig_declarator, decl,
+ template_count,
+ 2 * (funcdef_flag != 0) +
+ 4 * (friendp != 0));
+ if (ctype != NULL_TREE
+ && (! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
+ && check)
+ {
+ tmp = check_classfn (ctype, decl);
+
+ if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
+ tmp = DECL_TEMPLATE_RESULT (tmp);
+
+ if (tmp && DECL_STATIC_FUNCTION_P (tmp)
+ && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
+ {
+ /* Remove the `this' parm added by grokclassfn.
+ XXX Isn't this done in start_function, too? */
+ revert_static_member_fn (&decl, NULL, NULL);
+ last_function_parms = TREE_CHAIN (last_function_parms);
+ }
+ if (tmp && DECL_ARTIFICIAL (tmp))
+ cp_error ("definition of implicitly-declared `%D'", tmp);
+ if (tmp)
+ {
+ if (!duplicate_decls (decl, tmp))
+ my_friendly_abort (892);
+ return tmp;
+ }
+ }
if (ctype == NULL_TREE || check)
return decl;
@@ -7275,19 +8014,25 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
methods, though. */
if (! current_function_decl)
{
- /* FIXME: this should only need to look at
- IDENTIFIER_GLOBAL_VALUE. */
- tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
- if (tmp == NULL_TREE)
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
- else if (TREE_CODE (tmp) != TREE_CODE (decl))
- cp_error ("inconsistent declarations for `%D'", decl);
- else
+ if (!DECL_TEMPLATE_SPECIALIZATION (decl))
{
- duplicate_decls (decl, tmp);
- decl = tmp;
- /* avoid creating circularities. */
- DECL_CHAIN (decl) = NULL_TREE;
+ /* We don't do this for specializations since the
+ equivalent checks will be done later. Also, at this
+ point the DECL_ASSEMBLER_NAME is not yet fully
+ accurate. */
+
+ /* FIXME: this should only need to look at
+ IDENTIFIER_GLOBAL_VALUE. */
+ tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
+ if (tmp == NULL_TREE)
+ SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl), decl);
+ else if (TREE_CODE (tmp) != TREE_CODE (decl))
+ cp_error ("inconsistent declarations for `%D'", decl);
+ else
+ {
+ duplicate_decls (decl, tmp);
+ decl = tmp;
+ }
}
if (attrlist)
@@ -7295,95 +8040,30 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
TREE_VALUE (attrlist));
make_decl_rtl (decl, NULL_PTR, 1);
}
-
- /* If this declaration supersedes the declaration of
- a method declared virtual in the base class, then
- mark this field as being virtual as well. */
- {
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype));
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo))
- || flag_all_virtual == 1)
- {
- tmp = get_matching_virtual (base_binfo, decl,
- flags == DTOR_FLAG);
- if (tmp)
- {
- /* If this function overrides some virtual in some base
- class, then the function itself is also necessarily
- virtual, even if the user didn't explicitly say so. */
- DECL_VIRTUAL_P (decl) = 1;
-
- /* The TMP we really want is the one from the deepest
- baseclass on this path, taking care not to
- duplicate if we have already found it (via another
- path to its virtual baseclass. */
- if (staticp)
- {
- cp_error ("method `%D' may not be declared static",
- decl);
- cp_error_at ("(since `%D' declared virtual in base class.)",
- tmp);
- break;
- }
- virtualp = 1;
-
- {
- /* The argument types may have changed... */
- tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
- tree base_variant = TREE_TYPE (TREE_VALUE (argtypes));
-
- argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))),
- TREE_CHAIN (argtypes));
- /* But the return type has not. */
- type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
- if (raises)
- {
- type = build_exception_variant (type, raises);
- raises = TYPE_RAISES_EXCEPTIONS (type);
- }
- TREE_TYPE (decl) = type;
- DECL_VINDEX (decl)
- = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
- }
- break;
- }
- }
- }
- }
if (virtualp)
{
+ DECL_VIRTUAL_P (decl) = 1;
if (DECL_VINDEX (decl) == NULL_TREE)
DECL_VINDEX (decl) = error_mark_node;
IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
- if (ctype && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype)
- /* If this function is derived from a template, don't
- make it public. This shouldn't be here, but there's
- no good way to override the interface pragmas for one
- function or class only. Bletch. */
- && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (ctype)) == NULL_TREE
- && (write_virtuals == 2
- || (write_virtuals == 3
- && CLASSTYPE_INTERFACE_KNOWN (ctype))))
- TREE_PUBLIC (decl) = 1;
}
}
return decl;
}
static tree
-grokvardecl (type, declarator, specbits, initialized, constp)
+grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
tree type;
tree declarator;
- RID_BIT_TYPE specbits;
+ RID_BIT_TYPE *specbits_in;
int initialized;
int constp;
+ tree in_namespace;
{
tree decl;
+ RID_BIT_TYPE specbits;
+
+ specbits = *specbits_in;
if (TREE_CODE (type) == OFFSET_TYPE)
{
@@ -7397,9 +8077,17 @@ grokvardecl (type, declarator, specbits, initialized, constp)
DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator);
}
else
- decl = build_decl (VAR_DECL, declarator, type);
+ {
+ tree context = in_namespace ? in_namespace : current_namespace;
+ decl = build_decl (VAR_DECL, declarator, complete_type (type));
+ if (context != global_namespace && namespace_bindings_p ()
+ && current_lang_name != lang_name_c)
+ DECL_ASSEMBLER_NAME (decl) = build_static_name (context,
+ declarator);
+ }
- DECL_ASSEMBLER_NAME (decl) = current_namespace_id (DECL_ASSEMBLER_NAME (decl));
+ if (in_namespace)
+ set_decl_namespace (decl, in_namespace);
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
@@ -7409,8 +8097,7 @@ grokvardecl (type, declarator, specbits, initialized, constp)
/* In class context, static means one per class,
public access, and static storage. */
- if (DECL_FIELD_CONTEXT (decl) != NULL_TREE
- && IS_AGGR_TYPE (DECL_FIELD_CONTEXT (decl)))
+ if (DECL_CLASS_SCOPE_P (decl))
{
TREE_PUBLIC (decl) = 1;
TREE_STATIC (decl) = 1;
@@ -7433,7 +8120,7 @@ grokvardecl (type, declarator, specbits, initialized, constp)
return decl;
}
-/* Create a canonical pointer to member function type. */
+/* Create a canonical pointer to member function type. */
tree
build_ptrmemfunc_type (type)
@@ -7462,9 +8149,9 @@ build_ptrmemfunc_type (type)
t = make_lang_type (RECORD_TYPE);
- /* Let the front-end know this is a pointer to member function. */
+ /* Let the front-end know this is a pointer to member function... */
TYPE_PTRMEMFUNC_FLAG (t) = 1;
- /* and not really an aggregate. */
+ /* ... and not really an aggregate. */
IS_AGGR_TYPE (t) = 0;
fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
@@ -7482,7 +8169,7 @@ build_ptrmemfunc_type (type)
TYPE_SET_PTRMEMFUNC_TYPE (type, t);
- /* Seems to be wanted. */
+ /* Seems to be wanted. */
CLASSTYPE_GOT_SEMICOLON (t) = 1;
return t;
}
@@ -7546,12 +8233,12 @@ build_ptrmemfunc_type (type)
enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
tree
-grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrlist)
+grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree declspecs;
tree declarator;
enum decl_context decl_context;
int initialized;
- tree raises, attrlist;
+ tree attrlist;
{
RID_BIT_TYPE specbits;
int nclasses = 0;
@@ -7563,6 +8250,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
+ int defaulted_int = 0;
int opaque_typedef = 0;
tree typedef_decl = NULL_TREE;
char *name;
@@ -7570,8 +8258,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
int funcdef_flag = 0;
enum tree_code innermost_code = ERROR_MARK;
int bitfield = 0;
- int size_varies = 0;
+#if 0
+ /* See the code below that used this. */
tree decl_machine_attr = NULL_TREE;
+#endif
/* Set this to error_mark_node for FIELD_DECLs we could not handle properly.
All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */
tree init = NULL_TREE;
@@ -7586,6 +8276,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL;
tree quals = NULL_TREE;
+ tree raises = NULL_TREE;
+ int template_count = 0;
+ tree in_namespace = NULL_TREE;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
@@ -7595,228 +8288,263 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
else if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
- if (flag_traditional && allocation_temporary_p ())
- end_temporary_allocation ();
-
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
{
- tree last = NULL_TREE;
- register tree decl = declarator;
+ tree *next = &declarator;
+ register tree decl;
name = NULL;
- while (decl)
- switch (TREE_CODE (decl))
- {
- case COND_EXPR:
- ctype = NULL_TREE;
- decl = TREE_OPERAND (decl, 0);
- break;
-
- case BIT_NOT_EXPR: /* for C++ destructors! */
+ while (next && *next)
+ {
+ decl = *next;
+ switch (TREE_CODE (decl))
{
- tree name = TREE_OPERAND (decl, 0);
- tree rename = NULL_TREE;
-
- my_friendly_assert (flags == NO_SPECIAL, 152);
- flags = DTOR_FLAG;
- return_type = return_dtor;
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
- if (ctype == NULL_TREE)
- {
- if (current_class_type == NULL_TREE)
- {
- error ("destructors must be member functions");
- flags = NO_SPECIAL;
- }
- else
- {
- tree t = constructor_name (current_class_name);
- if (t != name)
- rename = t;
- }
- }
- else
- {
- tree t = constructor_name (ctype);
- if (t != name)
- rename = t;
- }
-
- if (rename)
- {
- error ("destructor `%s' must match class name `%s'",
- IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (rename));
- TREE_OPERAND (decl, 0) = rename;
- }
- decl = name;
- }
- break;
-
- case ADDR_EXPR: /* C++ reference declaration */
- /* fall through */
- case ARRAY_REF:
- case INDIRECT_REF:
- ctype = NULL_TREE;
- innermost_code = TREE_CODE (decl);
- last = decl;
- decl = TREE_OPERAND (decl, 0);
- break;
+ case COND_EXPR:
+ ctype = NULL_TREE;
+ next = &TREE_OPERAND (decl, 0);
+ break;
- case CALL_EXPR:
- if (parmlist_is_exprlist (TREE_OPERAND (decl, 1)))
+ case BIT_NOT_EXPR: /* For C++ destructors! */
{
- /* This is actually a variable declaration using constructor
- syntax. We need to call start_decl and cp_finish_decl so we
- can get the variable initialized... */
-
- if (last)
- /* We need to insinuate ourselves into the declarator in place
- of the CALL_EXPR. */
- TREE_OPERAND (last, 0) = TREE_OPERAND (decl, 0);
+ tree name = TREE_OPERAND (decl, 0);
+ tree rename = NULL_TREE;
+
+ my_friendly_assert (flags == NO_SPECIAL, 152);
+ flags = DTOR_FLAG;
+ return_type = return_dtor;
+ if (TREE_CODE (name) == TYPE_DECL)
+ TREE_OPERAND (decl, 0) = name = constructor_name (name);
+ my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
+ if (ctype == NULL_TREE)
+ {
+ if (current_class_type == NULL_TREE)
+ {
+ error ("destructors must be member functions");
+ flags = NO_SPECIAL;
+ }
+ else
+ {
+ tree t = constructor_name (current_class_name);
+ if (t != name)
+ rename = t;
+ }
+ }
else
- declarator = TREE_OPERAND (decl, 0);
-
- init = TREE_OPERAND (decl, 1);
-
- decl = start_decl (declarator, declspecs, 1, NULL_TREE);
- finish_decl (decl, init, NULL_TREE);
- return 0;
- }
- innermost_code = TREE_CODE (decl);
- if (decl_context == FIELD && ctype == NULL_TREE)
- ctype = current_class_type;
- if (ctype
- && TREE_OPERAND (decl, 0) == constructor_name_full (ctype))
- TREE_OPERAND (decl, 0) = constructor_name (ctype);
- decl = TREE_OPERAND (decl, 0);
- if (ctype != NULL_TREE
- && decl != NULL_TREE && flags != DTOR_FLAG
- && decl == constructor_name (ctype))
- {
- return_type = return_ctor;
- ctor_return_type = ctype;
- }
- ctype = NULL_TREE;
- break;
-
- case IDENTIFIER_NODE:
- dname = decl;
- decl = NULL_TREE;
+ {
+ tree t = constructor_name (ctype);
+ if (t != name)
+ rename = t;
+ }
- if (! IDENTIFIER_OPNAME_P (dname)
- /* Linux headers use '__op'. Arrgh. */
- || IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname))
- name = IDENTIFIER_POINTER (dname);
- else
- {
- if (IDENTIFIER_TYPENAME_P (dname))
+ if (rename)
{
- my_friendly_assert (flags == NO_SPECIAL, 154);
- flags = TYPENAME_FLAG;
- ctor_return_type = TREE_TYPE (dname);
- return_type = return_conversion;
+ cp_error ("destructor `%T' must match class name `%T'",
+ name, rename);
+ TREE_OPERAND (decl, 0) = rename;
}
- name = operator_name_string (dname);
+ next = &name;
}
- break;
+ break;
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- /* Parse error puts this typespec where
- a declarator should go. */
- error ("declarator name missing");
- dname = TYPE_NAME (decl);
- if (dname && TREE_CODE (dname) == TYPE_DECL)
- dname = DECL_NAME (dname);
- name = dname ? IDENTIFIER_POINTER (dname) : "<nameless>";
- declspecs = temp_tree_cons (NULL_TREE, decl, declspecs);
- decl = NULL_TREE;
- break;
+ case ADDR_EXPR: /* C++ reference declaration */
+ /* Fall through. */
+ case ARRAY_REF:
+ case INDIRECT_REF:
+ ctype = NULL_TREE;
+ innermost_code = TREE_CODE (decl);
+ next = &TREE_OPERAND (decl, 0);
+ break;
- /* C++ extension */
- case SCOPE_REF:
- {
- /* Perform error checking, and convert class names to types.
- We may call grokdeclarator multiple times for the same
- tree structure, so only do the conversion once. In this
- case, we have exactly what we want for `ctype'. */
- tree cname = TREE_OPERAND (decl, 0);
- if (cname == NULL_TREE)
- ctype = NULL_TREE;
- /* Can't use IS_AGGR_TYPE because CNAME might not be a type. */
- else if (IS_AGGR_TYPE_CODE (TREE_CODE (cname))
- || TREE_CODE (cname) == UNINSTANTIATED_P_TYPE)
- ctype = cname;
- else if (! is_aggr_typedef (cname, 1))
+ case CALL_EXPR:
+ if (parmlist_is_exprlist (TREE_OPERAND (decl, 1)))
{
- TREE_OPERAND (decl, 0) = NULL_TREE;
- }
- /* Must test TREE_OPERAND (decl, 1), in case user gives
- us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */
- else if (TREE_OPERAND (decl, 1)
- && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)
- {
- TREE_OPERAND (decl, 0) = IDENTIFIER_TYPE_VALUE (cname);
+ /* This is actually a variable declaration using constructor
+ syntax. We need to call start_decl and cp_finish_decl so we
+ can get the variable initialized... */
+
+ *next = TREE_OPERAND (decl, 0);
+ init = TREE_OPERAND (decl, 1);
+
+ decl = start_decl (declarator, declspecs, 1, NULL_TREE, NULL_TREE);
+ /* Look for __unused__ attribute */
+ if (TREE_USED (TREE_TYPE (decl)))
+ TREE_USED (decl) = 1;
+ finish_decl (decl, init, NULL_TREE);
+ return 0;
}
- else if (ctype == NULL_TREE)
+ innermost_code = TREE_CODE (decl);
+ if (decl_context == FIELD && ctype == NULL_TREE)
+ ctype = current_class_type;
+ if (ctype
+ && TREE_OPERAND (decl, 0)
+ && (TREE_CODE (TREE_OPERAND (decl, 0)) == TYPE_DECL
+ && ((DECL_NAME (TREE_OPERAND (decl, 0))
+ == constructor_name_full (ctype))
+ || (DECL_NAME (TREE_OPERAND (decl, 0))
+ == constructor_name (ctype)))))
+ TREE_OPERAND (decl, 0) = constructor_name (ctype);
+ next = &TREE_OPERAND (decl, 0);
+ decl = *next;
+ if (ctype != NULL_TREE
+ && decl != NULL_TREE && flags != DTOR_FLAG
+ && decl == constructor_name (ctype))
{
- ctype = IDENTIFIER_TYPE_VALUE (cname);
- TREE_OPERAND (decl, 0) = ctype;
+ return_type = return_ctor;
+ ctor_return_type = ctype;
}
- else if (TREE_COMPLEXITY (decl) == current_class_depth)
- TREE_OPERAND (decl, 0) = ctype;
- else
+ ctype = NULL_TREE;
+ break;
+
+ case TEMPLATE_ID_EXPR:
{
- if (! UNIQUELY_DERIVED_FROM_P (IDENTIFIER_TYPE_VALUE (cname),
- ctype))
- {
- cp_error ("type `%T' is not derived from type `%T'",
- IDENTIFIER_TYPE_VALUE (cname), ctype);
- TREE_OPERAND (decl, 0) = NULL_TREE;
- }
+ tree fns = TREE_OPERAND (decl, 0);
+
+ if (TREE_CODE (fns) == LOOKUP_EXPR)
+ fns = TREE_OPERAND (fns, 0);
+
+ if (TREE_CODE (fns) == IDENTIFIER_NODE)
+ dname = fns;
+ else if (is_overloaded_fn (fns))
+ dname = DECL_NAME (get_first_fn (fns));
else
- {
- ctype = IDENTIFIER_TYPE_VALUE (cname);
- TREE_OPERAND (decl, 0) = ctype;
- }
+ my_friendly_abort (0);
}
+ /* Fall through. */
- if (ctype
- && TREE_OPERAND (decl, 1) == constructor_name_full (ctype))
- TREE_OPERAND (decl, 1) = constructor_name (ctype);
- decl = TREE_OPERAND (decl, 1);
- if (ctype)
+ case IDENTIFIER_NODE:
+ if (TREE_CODE (decl) == IDENTIFIER_NODE)
+ dname = decl;
+
+ next = 0;
+
+ if (is_rid (dname))
{
- if (TREE_CODE (decl) == IDENTIFIER_NODE
- && constructor_name (ctype) == decl)
- {
- return_type = return_ctor;
- ctor_return_type = ctype;
- }
- else if (TREE_CODE (decl) == BIT_NOT_EXPR
- && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
- && (constructor_name (ctype) == TREE_OPERAND (decl, 0)
- || constructor_name_full (ctype) == TREE_OPERAND (decl, 0)))
+ cp_error ("declarator-id missing; using reserved word `%D'",
+ dname);
+ name = IDENTIFIER_POINTER (dname);
+ }
+ if (! IDENTIFIER_OPNAME_P (dname)
+ /* GNU/Linux headers use '__op'. Arrgh. */
+ || (IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname)))
+ name = IDENTIFIER_POINTER (dname);
+ else
+ {
+ if (IDENTIFIER_TYPENAME_P (dname))
{
- return_type = return_dtor;
- ctor_return_type = ctype;
- flags = DTOR_FLAG;
- decl = TREE_OPERAND (decl, 0) = constructor_name (ctype);
+ my_friendly_assert (flags == NO_SPECIAL, 154);
+ flags = TYPENAME_FLAG;
+ ctor_return_type = TREE_TYPE (dname);
+ return_type = return_conversion;
}
+ name = operator_name_string (dname);
}
- }
- break;
+ break;
- case ERROR_MARK:
- decl = NULL_TREE;
- break;
+ /* C++ extension */
+ case SCOPE_REF:
+ {
+ /* Perform error checking, and decide on a ctype. */
+ tree cname = TREE_OPERAND (decl, 0);
+ if (cname == NULL_TREE)
+ ctype = NULL_TREE;
+ else if (TREE_CODE (cname) == NAMESPACE_DECL)
+ {
+ ctype = NULL_TREE;
+ in_namespace = TREE_OPERAND (decl, 0);
+ TREE_OPERAND (decl, 0) = NULL_TREE;
+ }
+ else if (! is_aggr_type (cname, 1))
+ TREE_OPERAND (decl, 0) = NULL_TREE;
+ /* Must test TREE_OPERAND (decl, 1), in case user gives
+ us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */
+ else if (TREE_OPERAND (decl, 1)
+ && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)
+ ctype = cname;
+ else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (cname) == TEMPLATE_TEMPLATE_PARM)
+ {
+ cp_error ("`%T::%D' is not a valid declarator", cname,
+ TREE_OPERAND (decl, 1));
+ cp_error (" perhaps you want `typename %T::%D' to make it a type",
+ cname, TREE_OPERAND (decl, 1));
+ return void_type_node;
+ }
+ else if (ctype == NULL_TREE)
+ ctype = cname;
+ else if (TREE_COMPLEXITY (decl) == current_class_depth)
+ TREE_OPERAND (decl, 0) = ctype;
+ else
+ {
+ if (! UNIQUELY_DERIVED_FROM_P (cname, ctype))
+ {
+ cp_error ("type `%T' is not derived from type `%T'",
+ cname, ctype);
+ TREE_OPERAND (decl, 0) = NULL_TREE;
+ }
+ else
+ ctype = cname;
+ }
- default:
- return 0; /* We used to do a 155 abort here. */
- }
+ if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL
+ && ((DECL_NAME (TREE_OPERAND (decl, 1))
+ == constructor_name_full (ctype))
+ || (DECL_NAME (TREE_OPERAND (decl, 1))
+ == constructor_name (ctype))))
+ TREE_OPERAND (decl, 1) = constructor_name (ctype);
+ next = &TREE_OPERAND (decl, 1);
+ decl = *next;
+ if (ctype)
+ {
+ if (TREE_CODE (decl) == IDENTIFIER_NODE
+ && constructor_name (ctype) == decl)
+ {
+ return_type = return_ctor;
+ ctor_return_type = ctype;
+ }
+ else if (TREE_CODE (decl) == BIT_NOT_EXPR
+ && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
+ && (constructor_name (ctype) == TREE_OPERAND (decl, 0)
+ || constructor_name_full (ctype) == TREE_OPERAND (decl, 0)))
+ {
+ return_type = return_dtor;
+ ctor_return_type = ctype;
+ flags = DTOR_FLAG;
+ TREE_OPERAND (decl, 0) = constructor_name (ctype);
+ next = &TREE_OPERAND (decl, 0);
+ }
+ }
+ }
+ break;
+
+ case ERROR_MARK:
+ next = 0;
+ break;
+
+ case TYPE_DECL:
+ /* Parse error puts this typespec where
+ a declarator should go. */
+ cp_error ("`%T' specified as declarator-id", DECL_NAME (decl));
+ if (TREE_TYPE (decl) == current_class_type)
+ cp_error (" perhaps you want `%T' for a constructor",
+ current_class_name);
+ dname = DECL_NAME (decl);
+ name = IDENTIFIER_POINTER (dname);
+
+ /* Avoid giving two errors for this. */
+ IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
+
+ declspecs = temp_tree_cons (NULL_TREE, integer_type_node,
+ declspecs);
+ *next = dname;
+ next = 0;
+ break;
+
+ default:
+ cp_compiler_error ("`%D' as declarator", decl);
+ return 0; /* We used to do a 155 abort here. */
+ }
+ }
if (name == NULL)
name = "type name";
}
@@ -7849,7 +8577,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
We also want to avoid calling this a PARM if it is in a namespace. */
- if (decl_context == NORMAL && ! namespace_bindings_p ())
+ if (decl_context == NORMAL && ! namespace_bindings_p ()
+ && ! pseudo_global_level_p ())
{
struct binding_level *b = current_binding_level;
current_binding_level = b->level_chain;
@@ -7911,7 +8640,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
goto found;
}
- /* C++ aggregate types. */
+ /* C++ aggregate types. */
if (IDENTIFIER_HAS_TYPE_VALUE (id))
{
if (type)
@@ -7927,9 +8656,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
{
if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
{
- if (pedantic && ! in_system_header)
+ if (pedantic && ! in_system_header && warn_long_long)
pedwarn ("ANSI C++ does not support `long long'");
- else if (longlong)
+ if (longlong)
error ("`long long long' is too long for GCC");
else
longlong = 1;
@@ -7941,6 +8670,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
}
}
+ /* C++ aggregate types. */
+ else if (TREE_CODE (id) == TYPE_DECL || TREE_CODE (id) == TEMPLATE_DECL)
+ {
+ if (type)
+ cp_error ("multiple declarations `%T' and `%T'", type,
+ TREE_TYPE (id));
+ else
+ {
+ type = TREE_TYPE (id);
+ TREE_VALUE (spec) = type;
+ }
+ goto found;
+ }
if (type)
error ("two or more data types in declaration of `%s'", name);
else if (TREE_CODE (id) == IDENTIFIER_NODE)
@@ -7952,11 +8694,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
else
{
type = TREE_TYPE (t);
+#if 0
+ /* See the code below that used this. */
decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
+#endif
typedef_decl = t;
}
}
- else if (TREE_CODE (id) != ERROR_MARK)
+ else if (id != error_mark_node)
/* Can't change CLASS nodes into RECORD nodes here! */
type = id;
@@ -7965,7 +8710,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
typedef_type = type;
- /* No type at all: default to `int', and set EXPLICIT_INT
+ /* No type at all: default to `int', and set DEFAULTED_INT
because it was not a user-defined typedef.
Except when we have a `typedef' inside a signature, in
which case the type defaults to `unknown type' and is
@@ -7979,7 +8724,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
{
/* These imply 'int'. */
type = integer_type_node;
- explicit_int = 1;
+ defaulted_int = 1;
}
if (type == NULL_TREE)
@@ -7993,18 +8738,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
type = ctor_return_type;
else if (current_class_type
&& IS_SIGNATURE (current_class_type)
- && (RIDBIT_SETP (RID_TYPEDEF, specbits)
- || SIGNATURE_GROKKING_TYPEDEF (current_class_type))
+ && RIDBIT_SETP (RID_TYPEDEF, specbits)
&& (decl_context == FIELD || decl_context == NORMAL))
{
explicit_int = 0;
opaque_typedef = 1;
type = copy_node (opaque_type_node);
}
- /* access declaration */
- else if (decl_context == FIELD && declarator
- && TREE_CODE (declarator) == SCOPE_REF)
- type = void_type_node;
else
{
if (funcdef_flag)
@@ -8016,10 +8756,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
pedwarn ("ANSI C++ forbids typedef which does not specify a type");
- else if (declspecs == NULL_TREE &&
- (innermost_code != CALL_EXPR || pedantic))
- cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type or storage class",
- dname);
+ else if (innermost_code != CALL_EXPR || pedantic
+ || (warn_return_type && return_type == return_normal))
+ {
+ if (innermost_code == CALL_EXPR)
+ cp_pedwarn ("return-type of `%D' defaults to `int'", dname);
+ else
+ cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type",
+ dname);
+ }
type = integer_type_node;
}
}
@@ -8044,13 +8789,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
type = ctor_return_type;
}
- /* Catch typedefs that only specify a type, like 'typedef int;'. */
- else if (RIDBIT_SETP (RID_TYPEDEF, specbits) && declarator == NULL_TREE)
- {
- /* Template "this is a type" syntax; just ignore for now. */
- if (processing_template_defn)
- return void_type_node;
- }
ctype = NULL_TREE;
@@ -8097,7 +8835,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
else
{
ok = 1;
- if (!explicit_int && !explicit_char && pedantic)
+ if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
{
pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
name);
@@ -8117,13 +8855,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
}
+ if (RIDBIT_SETP (RID_COMPLEX, specbits)
+ && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
+ {
+ error ("complex invalid for `%s'", name);
+ RIDBIT_RESET (RID_COMPLEX, specbits);
+ }
+
/* Decide whether an integer type is signed or not.
Optionally treat bitfields as signed by default. */
if (RIDBIT_SETP (RID_UNSIGNED, specbits)
- /* Traditionally, all bitfields are unsigned. */
- || (bitfield && flag_traditional)
|| (bitfield && ! flag_signed_bitfields
- && (explicit_int || explicit_char
+ && (explicit_int || defaulted_int || explicit_char
/* A typedef for plain `int' without `signed'
can be controlled just like plain `int'. */
|| ! (typedef_decl != NULL_TREE
@@ -8154,21 +8897,46 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
else if (RIDBIT_SETP (RID_SHORT, specbits))
type = short_integer_type_node;
+ if (RIDBIT_SETP (RID_COMPLEX, specbits))
+ {
+ /* If we just have "complex", it is equivalent to
+ "complex double", but if any modifiers at all are specified it is
+ the complex form of TYPE. E.g, "complex short" is
+ "complex short int". */
+
+ if (defaulted_int && ! longlong
+ && ! (RIDBIT_SETP (RID_LONG, specbits)
+ || RIDBIT_SETP (RID_SHORT, specbits)
+ || RIDBIT_SETP (RID_SIGNED, specbits)
+ || RIDBIT_SETP (RID_UNSIGNED, specbits)))
+ type = complex_double_type_node;
+ else if (type == integer_type_node)
+ type = complex_integer_type_node;
+ else if (type == float_type_node)
+ type = complex_float_type_node;
+ else if (type == double_type_node)
+ type = complex_double_type_node;
+ else if (type == long_double_type_node)
+ type = complex_long_double_type_node;
+ else
+ type = build_complex_type (type);
+ }
+
+ if (return_type == return_conversion
+ && (RIDBIT_SETP (RID_CONST, specbits)
+ || RIDBIT_SETP (RID_VOLATILE, specbits)))
+ cp_error ("`operator %T' cannot be cv-qualified",
+ ctor_return_type);
+
/* Set CONSTP if this declaration is `const', whether by
explicit specification or via a typedef.
Likewise for VOLATILEP. */
constp = !! RIDBIT_SETP (RID_CONST, specbits) + TYPE_READONLY (type);
volatilep = !! RIDBIT_SETP (RID_VOLATILE, specbits) + TYPE_VOLATILE (type);
+ type = build_type_variant (type, 0, 0);
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
-#if 0
- /* This sort of redundancy is blessed in a footnote to the Sep 94 WP. */
- if (constp > 1)
- warning ("duplicate `const'");
- if (volatilep > 1)
- warning ("duplicate `volatile'");
-#endif
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
RIDBIT_RESET (RID_VIRTUAL, specbits);
explicitp = RIDBIT_SETP (RID_EXPLICIT, specbits) != 0;
@@ -8198,20 +8966,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
error ("non-object member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
-#if 0
- if (RIDBIT_SETP (RID_TYPEDEF, specbits))
- {
- error ("non-object member `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
- }
- /* Because local typedefs are parsed twice, we don't want this
- message here. */
- else if (decl_context != FIELD)
- {
- error ("non-member `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
- }
-#endif
}
/* Warn if two storage classes are given. Default to `auto'. */
@@ -8248,16 +9002,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
/* Static anonymous unions are dealt with here. */
if (staticp && decl_context == TYPENAME
&& TREE_CODE (declspecs) == TREE_LIST
- && TREE_CODE (TREE_VALUE (declspecs)) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_VALUE (declspecs))))
+ && ANON_UNION_TYPE_P (TREE_VALUE (declspecs)))
decl_context = FIELD;
/* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual'
is used in a signature member function declaration. */
if (decl_context == FIELD
&& IS_SIGNATURE (current_class_type)
- && RIDBIT_NOTSETP(RID_TYPEDEF, specbits)
- && !SIGNATURE_GROKKING_TYPEDEF (current_class_type))
+ && RIDBIT_NOTSETP (RID_TYPEDEF, specbits))
{
if (constp)
{
@@ -8301,82 +9053,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
&& (RIDBIT_SETP (RID_REGISTER, specbits)
|| RIDBIT_SETP (RID_AUTO, specbits)))
;
+ else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
+ ;
else if (decl_context == FIELD
- && RIDBIT_SETP (RID_TYPEDEF, specbits))
- {
- /* Processing a typedef declaration nested within a class type
- definition. */
- register tree scanner;
- register tree previous_declspec;
- tree loc_typedecl;
-
- if (initialized)
- error ("typedef declaration includes an initializer");
-
- /* To process a class-local typedef declaration, we descend down
- the chain of declspecs looking for the `typedef' spec. When
- we find it, we replace it with `static', and then recursively
- call `grokdeclarator' with the original declarator and with
- the newly adjusted declspecs. This call should return a
- FIELD_DECL node with the TREE_TYPE (and other parts) set
- appropriately. We can then just change the TREE_CODE on that
- from FIELD_DECL to TYPE_DECL and we're done. */
-
- for (previous_declspec = NULL_TREE, scanner = declspecs;
- scanner;
- previous_declspec = scanner, scanner = TREE_CHAIN (scanner))
- {
- if (TREE_VALUE (scanner) == ridpointers[(int) RID_TYPEDEF])
- break;
- }
-
- if (previous_declspec)
- TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner);
- else
- declspecs = TREE_CHAIN (scanner);
-
- declspecs = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
- declspecs);
-
- /* In the recursive call to grokdeclarator we need to know
- whether we are working on a signature-local typedef. */
- if (IS_SIGNATURE (current_class_type))
- SIGNATURE_GROKKING_TYPEDEF (current_class_type) = 1;
-
- loc_typedecl =
- grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE, NULL_TREE);
-
- if (previous_declspec)
- TREE_CHAIN (previous_declspec) = scanner;
-
- if (loc_typedecl != error_mark_node)
- {
- register int i = sizeof (struct lang_decl_flags) / sizeof (int);
- register int *pi;
-
- TREE_SET_CODE (loc_typedecl, TYPE_DECL);
- /* This is the same field as DECL_ARGUMENTS, which is set for
- function typedefs by the above grokdeclarator. */
- DECL_NESTED_TYPENAME (loc_typedecl) = 0;
-
- pi = (int *) permalloc (sizeof (struct lang_decl_flags));
- while (i > 0)
- pi[--i] = 0;
- DECL_LANG_SPECIFIC (loc_typedecl) = (struct lang_decl *) pi;
- }
-
- if (IS_SIGNATURE (current_class_type))
- {
- SIGNATURE_GROKKING_TYPEDEF (current_class_type) = 0;
- if (loc_typedecl != error_mark_node && opaque_typedef)
- SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1;
- }
-
- return loc_typedecl;
- }
- else if (decl_context == FIELD
- && (! IS_SIGNATURE (current_class_type)
- || SIGNATURE_GROKKING_TYPEDEF (current_class_type))
+ && ! IS_SIGNATURE (current_class_type)
/* C++ allows static class elements */
&& RIDBIT_SETP (RID_STATIC, specbits))
/* C++ also allows inlines and signed and unsigned elements,
@@ -8391,7 +9071,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
if (declarator)
{
- tmp = TREE_OPERAND (declarator, 0);
+ /* Avoid trying to get an operand off an identifier node. */
+ if (TREE_CODE (declarator) == IDENTIFIER_NODE)
+ tmp = declarator;
+ else
+ tmp = TREE_OPERAND (declarator, 0);
op = IDENTIFIER_OPNAME_P (tmp);
}
error ("storage class specified for %s `%s'",
@@ -8436,28 +9120,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
{
if (RIDBIT_SETP (RID_AUTO, specbits))
error ("top-level declaration of `%s' specifies `auto'", name);
-#if 0
- if (RIDBIT_SETP (RID_REGISTER, specbits))
- error ("top-level declaration of `%s' specifies `register'", name);
-#endif
-#if 0
- /* I'm not sure under what circumstances we should turn
- on the extern bit, and under what circumstances we should
- warn if other bits are turned on. */
- if (decl_context == NORMAL
- && RIDBIT_NOSETP (RID_EXTERN, specbits)
- && ! root_lang_context_p ())
- {
- RIDBIT_SET (RID_EXTERN, specbits);
- }
-#endif
}
+ if (nclasses > 0 && friendp)
+ error ("storage class specifiers invalid in friend function declarations");
+
/* Now figure out the structure of the declarator proper.
Descend through it, creating more complex types, until we reach
the declared identifier (or NULL_TREE, in an absolute declarator). */
- while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE)
+ while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
+ && TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
{
/* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
an INDIRECT_REF (for *...),
@@ -8480,7 +9153,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
array or function or pointer, and DECLARATOR has had its
outermost layer removed. */
- if (TREE_CODE (type) == ERROR_MARK)
+ if (type == error_mark_node)
{
if (TREE_CODE (declarator) == SCOPE_REF)
declarator = TREE_OPERAND (declarator, 1);
@@ -8496,11 +9169,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
ctype = TYPE_METHOD_BASETYPE (type);
if (ctype != NULL_TREE)
{
-#if 0 /* not yet, should get fixed properly later */
- tree dummy = make_type_decl (NULL_TREE, type);
-#else
tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
-#endif
ctype = grok_method_quals (ctype, dummy, quals);
type = TREE_TYPE (dummy);
quals = NULL_TREE;
@@ -8519,7 +9188,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
/* Check for some types that there cannot be arrays of. */
- if (TYPE_MAIN_VARIANT (type) == void_type_node)
+ if (TREE_CODE (type) == VOID_TYPE)
{
cp_error ("declaration of `%D' as array of voids", dname);
type = error_mark_node;
@@ -8574,15 +9243,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
the function; then build_vec_delete will need this
value. */
int yes = suspend_momentary ();
- /* might be a cast */
+ /* Might be a cast. */
if (TREE_CODE (size) == NOP_EXPR
&& TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0)))
size = TREE_OPERAND (size, 0);
- /* If this is a template parameter, it'll be constant, but
- we don't know what the value is yet. */
- if (TREE_CODE (size) == TEMPLATE_CONST_PARM)
- goto dont_grok_size;
+ /* If this involves a template parameter, it'll be
+ constant, but we don't know what the value is yet. */
+ if (processing_template_decl)
+ {
+ itype = make_node (INTEGER_TYPE);
+ TYPE_MIN_VALUE (itype) = size_zero_node;
+ TYPE_MAX_VALUE (itype) = build_min
+ (MINUS_EXPR, sizetype, size, integer_one_node);
+ goto dont_grok_size;
+ }
if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE)
@@ -8620,20 +9295,36 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
else
cp_pedwarn ("ANSI C++ forbids variable-size array");
}
- /* Make sure the array size remains visibly nonconstant
- even if it is (eg) a const variable with known value. */
- size_varies = 1;
}
- dont_grok_size:
- itype =
- fold (build_binary_op (MINUS_EXPR,
- convert (index_type, size),
- convert (index_type,
- integer_one_node), 1));
+ itype
+ = fold (build_binary_op (MINUS_EXPR,
+ cp_convert (index_type, size),
+ cp_convert (index_type,
+ integer_one_node), 1));
if (! TREE_CONSTANT (itype))
itype = variable_size (itype);
- itype = build_index_type (itype);
+ else if (TREE_OVERFLOW (itype))
+ {
+ error ("overflow in array dimension");
+ TREE_OVERFLOW (itype) = 0;
+ }
+
+ /* If we're a parm, we need to have a permanent type so
+ mangling checks for re-use will work right. If both the
+ element and index types are permanent, the array type
+ will be, too. */
+ if (decl_context == PARM
+ && allocation_temporary_p () && TREE_PERMANENT (type))
+ {
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ itype = build_index_type (itype);
+ pop_obstacks ();
+ }
+ else
+ itype = build_index_type (itype);
+
+ dont_grok_size:
resume_momentary (yes);
}
@@ -8693,15 +9384,23 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
inner_decl = TREE_OPERAND (inner_decl, 1);
+ if (inner_decl && TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR)
+ inner_decl = dname;
+
/* Pick up type qualifiers which should be applied to `this'. */
quals = TREE_OPERAND (declarator, 2);
+ /* Pick up the exception specifications. */
+ raises = TREE_TYPE (declarator);
+
/* Say it's a definition only for the CALL_EXPR
closest to the identifier. */
- funcdecl_p =
- inner_decl && (TREE_CODE (inner_decl) == IDENTIFIER_NODE
- || TREE_CODE (inner_decl) == BIT_NOT_EXPR);
-
+ funcdecl_p
+ = inner_decl
+ && (TREE_CODE (inner_decl) == IDENTIFIER_NODE
+ || TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR
+ || TREE_CODE (inner_decl) == BIT_NOT_EXPR);
+
if (ctype == NULL_TREE
&& decl_context == FIELD
&& funcdecl_p
@@ -8726,8 +9425,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
error ("destructor cannot be static member function");
if (quals)
{
- error ("destructors cannot be declared `const' or `volatile'");
- return void_type_node;
+ cp_error ("destructors may not be `%s'",
+ IDENTIFIER_POINTER (TREE_VALUE (quals)));
+ quals = NULL_TREE;
}
if (decl_context == FIELD)
{
@@ -8736,7 +9436,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
return void_type_node;
}
}
- else /* it's a constructor. */
+ else /* It's a constructor. */
{
if (explicitp == 1)
explicitp = 2;
@@ -8752,20 +9452,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
if (quals)
{
- error ("constructors cannot be declared `const' or `volatile'");
- return void_type_node;
+ cp_error ("constructors may not be `%s'",
+ IDENTIFIER_POINTER (TREE_VALUE (quals)));
+ quals = NULL_TREE;
}
{
RID_BIT_TYPE tmp_bits;
- bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE));
+ bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof (RID_BIT_TYPE));
RIDBIT_RESET (RID_INLINE, tmp_bits);
RIDBIT_RESET (RID_STATIC, tmp_bits);
if (RIDBIT_ANY_SET (tmp_bits))
error ("return value type specifier for constructor ignored");
}
type = build_pointer_type (ctype);
- if (decl_context == FIELD &&
- IS_SIGNATURE (current_class_type))
+ if (decl_context == FIELD
+ && IS_SIGNATURE (current_class_type))
{
error ("constructor not allowed in signature");
return void_type_node;
@@ -8801,16 +9502,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
name);
}
- /* Traditionally, declaring return type float means double. */
-
- if (flag_traditional
- && TYPE_MAIN_VARIANT (type) == float_type_node)
- {
- type = build_type_variant (double_type_node,
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- }
-
/* Construct the function type and go to the next
inner layer of declarator. */
@@ -8821,31 +9512,39 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
arg_types = grokparms (inner_parms, funcdecl_p ? funcdef_flag : 0);
- if (declarator)
+ if (declarator && flags == DTOR_FLAG)
{
- /* Get past destructors, etc.
- We know we have one because FLAGS will be non-zero.
-
- Complain about improper parameter lists here. */
+ /* A destructor declared in the body of a class will
+ be represented as a BIT_NOT_EXPR. But, we just
+ want the underlying IDENTIFIER. */
if (TREE_CODE (declarator) == BIT_NOT_EXPR)
+ declarator = TREE_OPERAND (declarator, 0);
+
+ if (strict_prototype == 0 && arg_types == NULL_TREE)
+ arg_types = void_list_node;
+ else if (arg_types == NULL_TREE
+ || arg_types != void_list_node)
{
- declarator = TREE_OPERAND (declarator, 0);
-
- if (strict_prototype == 0 && arg_types == NULL_TREE)
- arg_types = void_list_node;
- else if (arg_types == NULL_TREE
- || arg_types != void_list_node)
- {
- error ("destructors cannot be specified with parameters");
- arg_types = void_list_node;
- }
+ cp_error ("destructors may not have parameters");
+ arg_types = void_list_node;
+ last_function_parms = NULL_TREE;
}
}
- /* ANSI seems to say that `const int foo ();'
+ /* ANSI says that `const int foo ();'
does not make the function foo const. */
- type = build_function_type (type,
- flag_traditional ? 0 : arg_types);
+ type = build_function_type (type, arg_types);
+
+ {
+ tree t;
+ for (t = arg_types; t; t = TREE_CHAIN (t))
+ if (TREE_PURPOSE (t)
+ && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
+ {
+ add_defarg_fn (type);
+ break;
+ }
+ }
}
break;
@@ -8928,7 +9627,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
else
{
- if (TYPE_MAIN_VARIANT (type) == void_type_node)
+ if (TREE_CODE (type) == VOID_TYPE)
error ("invalid type: `void &'");
else
type = build_reference_type (type);
@@ -8990,6 +9689,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
resolve to. The code here just needs to build
up appropriate member types. */
tree sname = TREE_OPERAND (declarator, 1);
+ tree t;
+
/* Destructors can have their visibilities changed as well. */
if (TREE_CODE (sname) == BIT_NOT_EXPR)
sname = TREE_OPERAND (sname, 0);
@@ -8997,10 +9698,29 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
if (TREE_COMPLEXITY (declarator) == 0)
/* This needs to be here, in case we are called
multiple times. */ ;
+ else if (TREE_COMPLEXITY (declarator) == -1)
+ /* Namespace member. */
+ pop_decl_namespace ();
else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
- /* don't fall out into global scope. Hides real bug? --eichin */ ;
+ /* Don't fall out into global scope. Hides real bug? --eichin */ ;
+ else if (! IS_AGGR_TYPE_CODE
+ (TREE_CODE (TREE_OPERAND (declarator, 0))))
+ ;
else if (TREE_COMPLEXITY (declarator) == current_class_depth)
{
+ /* Resolve any TYPENAME_TYPEs from the decl-specifier-seq
+ that refer to ctype. They couldn't be resolved earlier
+ because we hadn't pushed into the class yet.
+ Example: resolve 'B<T>::type' in
+ 'B<typename B<T>::type> B<T>::f () { }'. */
+ if (current_template_parms
+ && uses_template_parms (type)
+ && uses_template_parms (current_class_type))
+ {
+ tree args = current_template_args ();
+ type = tsubst (type, args, NULL_TREE);
+ }
+
/* This pop_nested_class corresponds to the
push_nested_class used to push into class scope for
parsing the argument list of a function decl, in
@@ -9022,6 +9742,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
ctype = TREE_OPERAND (declarator, 0);
+ t = ctype;
+ while (t != NULL_TREE)
+ {
+ if (CLASSTYPE_TEMPLATE_INFO (t) &&
+ !CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
+ template_count += 1;
+ t = TYPE_MAIN_DECL (t);
+ if (DECL_LANG_SPECIFIC (t))
+ t = DECL_CLASS_CONTEXT (t);
+ else
+ t = NULL_TREE;
+ }
+
if (sname == NULL_TREE)
goto done_scoping;
@@ -9055,53 +9788,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
return void_type_node;
}
}
- else if (TYPE_SIZE (ctype) != NULL_TREE
- || (RIDBIT_SETP (RID_TYPEDEF, specbits)))
+ else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
+ || TYPE_SIZE (complete_type (ctype)) != NULL_TREE)
{
- tree t;
- /* have to move this code elsewhere in this function.
+ /* Have to move this code elsewhere in this function.
this code is used for i.e., typedef int A::M; M *pm;
It is? How? jason 10/2/94 */
- if (explicit_int == -1 && decl_context == FIELD
- && funcdef_flag == 0)
- {
- /* The code in here should only be used to build
- stuff that will be grokked as access decls. */
- t = lookup_field (ctype, sname, 0, 0);
- if (t)
- {
- t = build_lang_field_decl (FIELD_DECL, build_nt (SCOPE_REF, ctype, t), type);
- DECL_INITIAL (t) = init;
- return t;
- }
- /* No such field, try member functions. */
- t = lookup_fnfields (TYPE_BINFO (ctype), sname, 0);
- if (t)
- {
- if (flags == DTOR_FLAG)
- t = TREE_VALUE (t);
- else if (CLASSTYPE_METHOD_VEC (ctype)
- && TREE_VALUE (t) == TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (ctype), 0))
- {
- /* Don't include destructor with constructors. */
- t = DECL_CHAIN (TREE_VALUE (t));
- if (t == NULL_TREE)
- cp_error ("`%T' does not have any constructors",
- ctype);
- t = build_tree_list (NULL_TREE, t);
- }
- t = build_lang_field_decl (FIELD_DECL, build_nt (SCOPE_REF, ctype, t), type);
- DECL_INITIAL (t) = init;
- return t;
- }
-
- cp_error
- ("field `%D' is not a member of structure `%T'",
- sname, ctype);
- }
-
if (current_class_type)
{
cp_error ("cannot declare member `%T::%s' within `%T'",
@@ -9112,14 +9806,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
else if (uses_template_parms (ctype))
{
- enum tree_code c;
if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
- c = FUNCTION_DECL;
- }
+ type
+ = build_cplus_method_type (build_type_variant (ctype,
+ constp,
+ volatilep),
+ TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
}
else
{
@@ -9192,7 +9885,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
}
- if (RIDBIT_SETP (RID_TYPEDEF, specbits))
+ if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
{
tree decl;
@@ -9200,45 +9893,61 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
in typenames, fields or parameters. */
if (constp || volatilep)
type = cp_build_type_variant (type, constp, volatilep);
+ if (current_lang_name == lang_name_java)
+ TYPE_FOR_JAVA (type) = 1;
+
+ if (decl_context == FIELD)
+ {
+ if (declarator == current_class_name)
+ cp_pedwarn ("ANSI C++ forbids nested type `%D' with same name as enclosing class",
+ declarator);
+ decl = build_lang_decl (TYPE_DECL, declarator, type);
+ if (IS_SIGNATURE (current_class_type) && opaque_typedef)
+ SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1;
+ }
+ else
+ {
+ /* Make sure this typedef lives as long as its type,
+ since it might be used as a template parameter. */
+ if (type != error_mark_node)
+ push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
+ decl = build_decl (TYPE_DECL, declarator, type);
+ if (type != error_mark_node)
+ pop_obstacks ();
+ }
/* If the user declares "struct {...} foo" then `foo' will have
an anonymous name. Fill that name in now. Nothing can
refer to it, so nothing needs know about the name change.
The TYPE_NAME field was filled in by build_struct_xref. */
if (type != error_mark_node
+ && !TYPE_READONLY (type) && !TYPE_VOLATILE (type)
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
{
- /* replace the anonymous name with the real name everywhere. */
+ /* Replace the anonymous name with the real name everywhere. */
lookup_tag_reverse (type, declarator);
- TYPE_IDENTIFIER (type) = declarator;
+ TYPE_NAME (type) = decl;
if (TYPE_LANG_SPECIFIC (type))
TYPE_WAS_ANONYMOUS (type) = 1;
- {
- tree d = TYPE_NAME (type), c = DECL_CONTEXT (d);
-
- if (!c)
- set_nested_typename (d, 0, declarator, type);
- else if (TREE_CODE (c) == FUNCTION_DECL)
- set_nested_typename (d, DECL_ASSEMBLER_NAME (c),
- declarator, type);
- else
- set_nested_typename (d, TYPE_NESTED_NAME (c), declarator, type);
+ /* XXX Temporarily set the scope.
+ When returning, start_decl expects it as NULL_TREE,
+ and will then then set it using pushdecl. */
+ my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 980404);
+ if (current_class_type)
+ DECL_CONTEXT (decl) = current_class_type;
+ else
+ DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
- DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
- DECL_ASSEMBLER_NAME (d)
- = get_identifier (build_overload_name (type, 1, 1));
- }
+ DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl);
+ DECL_ASSEMBLER_NAME (decl)
+ = get_identifier (build_overload_name (type, 1, 1));
+ DECL_CONTEXT (decl) = NULL_TREE;
}
-#if 0 /* not yet, should get fixed properly later */
- decl = make_type_decl (declarator, type);
-#else
- decl = build_decl (TYPE_DECL, declarator, type);
-#endif
if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE)
{
cp_error_at ("typedef name may not be class-qualified", decl);
@@ -9266,6 +9975,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
error ("non-object member `%s' cannot be declared mutable", name);
}
+ bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
+ inlinep, friendp, raises != NULL_TREE);
+
+ if (initialized)
+ error ("typedef declaration includes an initializer");
+
return decl;
}
@@ -9289,10 +10004,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
/* Note that the grammar rejects storage classes
in typenames, fields or parameters. */
if (constp || volatilep)
- if (IS_SIGNATURE (type))
- error ("`const' or `volatile' specified with signature type");
- else
- type = cp_build_type_variant (type, constp, volatilep);
+ {
+ if (IS_SIGNATURE (type))
+ error ("`const' or `volatile' specified with signature type");
+ else
+ type = cp_build_type_variant (type, constp, volatilep);
+ }
/* Special case: "friend class foo" looks like a TYPENAME context. */
if (friendp)
@@ -9322,11 +10039,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
else if (quals)
{
-#if 0 /* not yet, should get fixed properly later */
- tree dummy = make_type_decl (declarator, type);
-#else
tree dummy = build_decl (TYPE_DECL, declarator, type);
-#endif
if (ctype == NULL_TREE)
{
my_friendly_assert (TREE_CODE (type) == METHOD_TYPE, 159);
@@ -9352,19 +10065,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
We don't complain about parms either, but that is because
a better error message can be made later. */
- if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM)
+ if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM)
{
if (! declarator)
error ("unnamed variable or field declared void");
else if (TREE_CODE (declarator) == IDENTIFIER_NODE)
{
if (IDENTIFIER_OPNAME_P (declarator))
-#if 0 /* How could this happen? */
- error ("operator `%s' declared void",
- operator_name_string (declarator));
-#else
my_friendly_abort (356);
-#endif
else
error ("variable or field `%s' declared void", name);
}
@@ -9390,7 +10098,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
if (TREE_CODE (type) == ARRAY_TYPE)
{
- /* Transfer const-ness of array into that of type pointed to. */
+ /* Transfer const-ness of array into that of type pointed to. */
type = build_pointer_type
(cp_build_type_variant (TREE_TYPE (type), constp, volatilep));
volatilep = constp = 0;
@@ -9399,13 +10107,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
type = build_pointer_type (type);
else if (TREE_CODE (type) == OFFSET_TYPE)
type = build_pointer_type (type);
- else if (type == void_type_node && declarator)
+ else if (TREE_CODE (type) == VOID_TYPE && declarator)
{
error ("declaration of `%s' as void", name);
return NULL_TREE;
}
- decl = build_decl (PARM_DECL, declarator, type);
+ decl = build_decl (PARM_DECL, declarator, complete_type (type));
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -9438,6 +10146,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
int publicp = 0;
+ tree function_context;
+
+ /* We catch the others as conflicts with the builtin
+ typedefs. */
+ if (friendp && declarator == ridpointers[(int) RID_SIGNED])
+ {
+ cp_error ("function `%D' cannot be declared friend",
+ declarator);
+ friendp = 0;
+ }
if (friendp == 0)
{
@@ -9478,15 +10196,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
- publicp = (! friendp
- || RIDBIT_SETP (RID_EXTERN, specbits)
- || ! (funcdef_flag < 0 || inlinep));
- decl = grokfndecl (ctype, type, declarator,
+ function_context = (ctype != NULL_TREE) ?
+ hack_decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
+ publicp = (! friendp || ! staticp)
+ && function_context == NULL_TREE;
+ decl = grokfndecl (ctype, type,
+ TREE_CODE (declarator) != TEMPLATE_ID_EXPR
+ ? declarator : dname,
+ declarator,
virtualp, flags, quals, raises, attrlist,
- friendp ? -1 : 0, publicp, inlinep);
+ friendp ? -1 : 0, friendp, publicp, inlinep,
+ funcdef_flag, template_count, in_namespace);
if (decl == NULL_TREE)
return NULL_TREE;
+#if 0
+ /* This clobbers the attrs stored in `decl' from `attrlist'. */
+ /* The decl and setting of decl_machine_attr is also turned off. */
decl = build_decl_attribute_variant (decl, decl_machine_attr);
+#endif
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
@@ -9497,13 +10224,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
members of other classes. */
/* All method decls are public, so tell grokfndecl to set
TREE_PUBLIC, also. */
- decl = grokfndecl (ctype, type, declarator,
+ decl = grokfndecl (ctype, type, declarator, declarator,
virtualp, flags, quals, raises, attrlist,
- friendp ? -1 : 0, 1, 0);
+ friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
+ template_count, in_namespace);
if (decl == NULL_TREE)
return NULL_TREE;
}
- else if (TYPE_SIZE (type) == NULL_TREE && !staticp
+ else if (!staticp && ! processing_template_decl
+ && TYPE_SIZE (complete_type (type)) == NULL_TREE
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{
if (declarator)
@@ -9515,7 +10244,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
instantiation made the field's type be incomplete. */
if (current_class_type
&& TYPE_NAME (current_class_type)
- && IDENTIFIER_TEMPLATE (DECL_NAME (TYPE_NAME (current_class_type)))
+ && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))
&& declspecs && TREE_VALUE (declspecs)
&& TREE_TYPE (TREE_VALUE (declspecs)) == type)
cp_error (" in instantiation of template `%T'",
@@ -9545,7 +10274,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
tree t = NULL_TREE;
if (decl && DECL_NAME (decl))
t = do_friend (ctype, declarator, decl,
- last_function_parms, flags, quals);
+ last_function_parms, flags, quals,
+ funcdef_flag);
if (t && funcdef_flag)
return t;
@@ -9559,6 +10289,27 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
{
if (initialized)
{
+ if (!staticp)
+ {
+ /* An attempt is being made to initialize a non-static
+ member. But, from [class.mem]:
+
+ 4 A member-declarator can contain a
+ constant-initializer only if it declares a static
+ member (_class.static_) of integral or enumeration
+ type, see _class.static.data_.
+
+ This used to be relatively common practice, but
+ the rest of the compiler does not correctly
+ handle the initialization unless the member is
+ static so we make it static below. */
+ cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'",
+ constp ? "const member" : "member",
+ declarator);
+ cp_pedwarn ("making `%D' static", declarator);
+ staticp = 1;
+ }
+
/* Motion 10 at San Diego: If a static const integral data
member is initialized with an integral constant
expression, the initializer may appear either in the
@@ -9566,34 +10317,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
but not both. If it appears in the class, the member is
a member constant. The file-scope definition is always
required. */
- if (staticp)
- {
- if (pedantic)
- {
- if (! constp)
- cp_pedwarn ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
- declarator);
-
- else if (! INTEGRAL_TYPE_P (type))
- cp_pedwarn ("ANSI C++ forbids member constant `%D' of non-integral type `%T'", declarator, type);
- }
- }
-
- /* Note that initialization of const members is prohibited
- by the draft ANSI standard, though it appears to be in
- common practice. 12.6.2: The argument list is used to
- initialize the named nonstatic member.... This (or an
- initializer list) is the only way to initialize
- nonstatic const and reference members. */
- else if (pedantic || ! constp)
- cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'",
- constp ? "const member" : "member", declarator);
+ if (! constp)
+ /* According to Mike Stump, we generate bad code for
+ this case, so we might as well always make it an
+ error. */
+ cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
+ declarator);
+
+ if (pedantic && ! INTEGRAL_TYPE_P (type)
+ && !uses_template_parms (type))
+ cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", declarator, type);
}
- if (staticp || (constp && initialized))
+ if (staticp)
{
/* ANSI C++ Apr '95 wp 9.2 */
- if (staticp && declarator == current_class_name)
+ if (declarator == current_class_name)
cp_pedwarn ("ANSI C++ forbids static member `%D' with same name as enclosing class",
declarator);
@@ -9604,7 +10343,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
decl = build_lang_field_decl (VAR_DECL, declarator, type);
TREE_STATIC (decl) = 1;
/* In class context, 'static' means public access. */
- TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = !!staticp;
+ TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1;
}
else
{
@@ -9622,12 +10361,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
{
- tree original_name = declarator;
+ tree original_name;
int publicp = 0;
if (! declarator)
return NULL_TREE;
+ if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+ original_name = dname;
+ else
+ original_name = declarator;
+
if (RIDBIT_SETP (RID_AUTO, specbits))
error ("storage class `auto' invalid for function `%s'", name);
else if (RIDBIT_SETP (RID_REGISTER, specbits))
@@ -9637,7 +10381,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
if (! toplevel_bindings_p ()
- && ! processing_template_decl
&& (RIDBIT_SETP (RID_STATIC, specbits)
|| RIDBIT_SETP (RID_INLINE, specbits))
&& pedantic)
@@ -9657,36 +10400,44 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
if (current_lang_name == lang_name_cplusplus
- && ! (IDENTIFIER_LENGTH (original_name) == 4
- && IDENTIFIER_POINTER (original_name)[0] == 'm'
- && strcmp (IDENTIFIER_POINTER (original_name), "main") == 0)
+ && ! processing_template_decl
+ && ! MAIN_NAME_P (original_name)
&& ! (IDENTIFIER_LENGTH (original_name) > 10
&& IDENTIFIER_POINTER (original_name)[0] == '_'
&& IDENTIFIER_POINTER (original_name)[1] == '_'
&& strncmp (IDENTIFIER_POINTER (original_name)+2, "builtin_", 8) == 0))
/* Plain overloading: will not be grok'd by grokclassfn. */
- declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
+ if (name_mangling_version < 1
+ || TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
+ declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
}
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
TREE_TYPE (type), TYPE_ARG_TYPES (type));
- /* Record presence of `static'. In C++, `inline' implies `static'. */
+ /* Record presence of `static'. */
publicp = (ctype != NULL_TREE
|| RIDBIT_SETP (RID_EXTERN, specbits)
- || (!RIDBIT_SETP (RID_STATIC, specbits)
- && !RIDBIT_SETP (RID_INLINE, specbits)));
+ || !RIDBIT_SETP (RID_STATIC, specbits));
- decl = grokfndecl (ctype, type, original_name,
+ decl = grokfndecl (ctype, type, original_name, declarator,
virtualp, flags, quals, raises, attrlist,
- processing_template_decl ? 0 : friendp ? 2 : 1,
- publicp, inlinep);
+ 1, friendp,
+ publicp, inlinep, funcdef_flag,
+ template_count, in_namespace);
if (decl == NULL_TREE)
return NULL_TREE;
- if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c)
- DECL_ASSEMBLER_NAME (decl) = current_namespace_id (declarator);
+ /* Among other times, could occur from check_explicit_specialization
+ returning an error_mark_node. */
+ if (decl == error_mark_node)
+ return error_mark_node;
+ if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c
+ && (! DECL_USE_TEMPLATE (decl) ||
+ name_mangling_version < 1))
+ DECL_ASSEMBLER_NAME (decl) = declarator;
+
if (staticp == 1)
{
int illegal_static = 0;
@@ -9730,7 +10481,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
if (TREE_CODE (type) == ARRAY_TYPE)
{
- /* Transfer const-ness of array into that of type pointed to. */
+ /* Transfer const-ness of array into that of type
+ pointed to. */
type = build_pointer_type
(cp_build_type_variant (TREE_TYPE (type), constp, volatilep));
volatilep = constp = 0;
@@ -9742,7 +10494,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
/* An uninitialized decl with `extern' is a reference. */
- decl = grokvardecl (type, declarator, specbits, initialized, constp);
+ decl = grokvardecl (type, declarator, &specbits,
+ initialized, constp, in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -9804,6 +10557,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
An empty exprlist is a parmlist. An exprlist which
contains only identifiers at the global level
is a parmlist. Otherwise, it is an exprlist. */
+
int
parmlist_is_exprlist (exprs)
tree exprs;
@@ -9830,14 +10584,18 @@ parmlist_is_exprlist (exprs)
be complete.
C++: also subroutine of `start_function'. */
+
static void
require_complete_types_for_parms (parms)
tree parms;
{
+ if (processing_template_decl)
+ return;
+
while (parms)
{
tree type = TREE_TYPE (parms);
- if (TYPE_SIZE (type) == NULL_TREE)
+ if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
{
if (DECL_NAME (parms))
error ("parameter `%s' has incomplete type",
@@ -9928,14 +10686,14 @@ grokparms (first_parm, funcdef_flag)
}
else if (first_parm != NULL_TREE
&& TREE_CODE (TREE_VALUE (first_parm)) != TREE_LIST
- && TREE_VALUE (first_parm) != void_type_node)
+ && TREE_CODE (TREE_VALUE (first_parm)) != VOID_TYPE)
my_friendly_abort (145);
else
{
/* Types were specified. This is a list of declarators
each represented as a TREE_LIST node. */
register tree parm, chain;
- int any_init = 0, any_error = 0, saw_void = 0;
+ int any_init = 0, any_error = 0;
if (first_parm != NULL_TREE)
{
@@ -9944,42 +10702,41 @@ grokparms (first_parm, funcdef_flag)
for (parm = first_parm; parm != NULL_TREE; parm = chain)
{
- tree type, list_node = parm;
+ tree type = NULL_TREE, list_node = parm;
register tree decl = TREE_VALUE (parm);
tree init = TREE_PURPOSE (parm);
chain = TREE_CHAIN (parm);
/* @@ weak defense against parse errors. */
- if (decl != void_type_node && TREE_CODE (decl) != TREE_LIST)
+ if (TREE_CODE (decl) != VOID_TYPE
+ && TREE_CODE (decl) != TREE_LIST)
{
/* Give various messages as the need arises. */
if (TREE_CODE (decl) == STRING_CST)
- error ("invalid string constant `%s'",
- TREE_STRING_POINTER (decl));
+ cp_error ("invalid string constant `%E'", decl);
else if (TREE_CODE (decl) == INTEGER_CST)
error ("invalid integer constant in parameter list, did you forget to give parameter name?");
continue;
}
- if (decl != void_type_node)
+ if (TREE_CODE (decl) != VOID_TYPE)
{
- /* @@ May need to fetch out a `raises' here. */
decl = grokdeclarator (TREE_VALUE (decl),
TREE_PURPOSE (decl),
PARM, init != NULL_TREE,
- NULL_TREE, NULL_TREE);
+ NULL_TREE);
if (! decl)
continue;
type = TREE_TYPE (decl);
- if (TYPE_MAIN_VARIANT (type) == void_type_node)
+ if (TREE_CODE (type) == VOID_TYPE)
decl = void_type_node;
else if (TREE_CODE (type) == METHOD_TYPE)
{
if (DECL_NAME (decl))
- /* Cannot use `error_with_decl' here because
+ /* Cannot use the decl here because
we don't have DECL_CONTEXT set up yet. */
- error ("parameter `%s' invalidly declared method type",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ cp_error ("parameter `%D' invalidly declared method type",
+ DECL_NAME (decl));
else
error ("parameter invalidly declared method type");
type = build_pointer_type (type);
@@ -9988,8 +10745,8 @@ grokparms (first_parm, funcdef_flag)
else if (TREE_CODE (type) == OFFSET_TYPE)
{
if (DECL_NAME (decl))
- error ("parameter `%s' invalidly declared offset type",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ cp_error ("parameter `%D' invalidly declared offset type",
+ DECL_NAME (decl));
else
error ("parameter invalidly declared offset type");
type = build_pointer_type (type);
@@ -10000,18 +10757,18 @@ grokparms (first_parm, funcdef_flag)
&& CLASSTYPE_ABSTRACT_VIRTUALS (type))
{
abstract_virtuals_error (decl, type);
- any_error = 1; /* seems like a good idea */
+ any_error = 1; /* Seems like a good idea. */
}
else if (TREE_CODE (type) == RECORD_TYPE
&& TYPE_LANG_SPECIFIC (type)
&& IS_SIGNATURE (type))
{
signature_error (decl, type);
- any_error = 1; /* seems like a good idea */
+ any_error = 1; /* Seems like a good idea. */
}
}
- if (decl == void_type_node)
+ if (TREE_CODE (decl) == VOID_TYPE)
{
if (result == NULL_TREE)
{
@@ -10023,7 +10780,6 @@ grokparms (first_parm, funcdef_flag)
TREE_CHAIN (last_result) = void_list_node;
last_result = void_list_node;
}
- saw_void = 1;
if (chain
&& (chain != void_list_node || TREE_CHAIN (chain)))
error ("`void' in parameter list must be entire list");
@@ -10045,6 +10801,11 @@ grokparms (first_parm, funcdef_flag)
any_init++;
if (TREE_CODE (init) == SAVE_EXPR)
PARM_DECL_EXPR (init) = 1;
+ else if (processing_template_decl)
+ ;
+ /* Unparsed default arg from in-class decl. */
+ else if (TREE_CODE (init) == DEFAULT_ARG)
+ ;
else if (TREE_CODE (init) == VAR_DECL
|| TREE_CODE (init) == PARM_DECL)
{
@@ -10054,7 +10815,7 @@ grokparms (first_parm, funcdef_flag)
argument expressions.'' dpANSI C++ 8.2.6 */
/* If extern int i; within a function is not
considered a local variable, then this code is
- wrong. */
+ wrong. */
cp_error ("local variable `%D' may not be used as a default argument", init);
any_error = 1;
}
@@ -10063,15 +10824,13 @@ grokparms (first_parm, funcdef_flag)
}
else
init = require_instantiated_type (type, init, integer_zero_node);
- }
-#if 0 /* This is too early to check; trailing parms might be merged in by
- duplicate_decls. */
- else if (any_init)
- {
- error ("all trailing parameters must have default arguments");
- any_error = 1;
+ if (! processing_template_decl
+ && init != error_mark_node
+ && TREE_CODE (init) != DEFAULT_ARG
+ && ! can_convert_arg (type, TREE_TYPE (init), init))
+ cp_pedwarn ("invalid type `%T' for default argument to `%#D'",
+ TREE_TYPE (init), decl);
}
-#endif
}
else
init = NULL_TREE;
@@ -10086,7 +10845,7 @@ grokparms (first_parm, funcdef_flag)
TREE_CHAIN (last_decl) = decl;
last_decl = decl;
}
- if (TREE_PERMANENT (list_node))
+ if (! current_function_decl && TREE_PERMANENT (list_node))
{
TREE_PURPOSE (list_node) = init;
TREE_VALUE (list_node) = type;
@@ -10122,7 +10881,40 @@ grokparms (first_parm, funcdef_flag)
return result;
}
+
+/* Called from the parser to update an element of TYPE_ARG_TYPES for some
+ FUNCTION_TYPE with the newly parsed version of its default argument, which
+ was previously digested as text. See snarf_defarg et al in lex.c. */
+
+void
+replace_defarg (arg, init)
+ tree arg, init;
+{
+ if (! processing_template_decl
+ && ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init))
+ cp_pedwarn ("invalid type `%T' for default argument to `%T'",
+ TREE_TYPE (init), TREE_VALUE (arg));
+ TREE_PURPOSE (arg) = init;
+}
+int
+copy_args_p (d)
+ tree d;
+{
+ tree t = FUNCTION_ARG_CHAIN (d);
+ if (DECL_CONSTRUCTOR_P (d)
+ && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (d)))
+ t = TREE_CHAIN (t);
+ if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t)))
+ == DECL_CLASS_CONTEXT (d))
+ && (TREE_CHAIN (t) == NULL_TREE
+ || TREE_CHAIN (t) == void_list_node
+ || TREE_PURPOSE (TREE_CHAIN (t))))
+ return 1;
+ return 0;
+}
+
/* These memoizing functions keep track of special properties which
a class may have. `grok_ctor_properties' notices whether a class
has a constructor of the form X(X&), and also complains
@@ -10130,6 +10922,7 @@ grokparms (first_parm, funcdef_flag)
`grok_op_properties' takes notice of the various forms of
operator= which are defined, as well as what sorts of type conversion
may apply. Both functions take a FUNCTION_DECL as an argument. */
+
int
grok_ctor_properties (ctype, decl)
tree ctype, decl;
@@ -10141,41 +10934,33 @@ grok_ctor_properties (ctype, decl)
added to any ctor so we can tell if the class has been initialized
yet. This could screw things up in this function, so we deliberately
ignore the leading int if we're in that situation. */
- if (parmtypes
- && TREE_VALUE (parmtypes) == integer_type_node
- && TYPE_USES_VIRTUAL_BASECLASSES (ctype))
+ if (TYPE_USES_VIRTUAL_BASECLASSES (ctype))
{
+ my_friendly_assert (parmtypes
+ && TREE_VALUE (parmtypes) == integer_type_node,
+ 980529);
parmtypes = TREE_CHAIN (parmtypes);
parmtype = TREE_VALUE (parmtypes);
}
if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype)
- {
- if (TREE_CHAIN (parmtypes) == NULL_TREE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype
+ && (TREE_CHAIN (parmtypes) == NULL_TREE
|| TREE_CHAIN (parmtypes) == void_list_node
- || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
- {
- TYPE_HAS_INIT_REF (ctype) = 1;
- if (TYPE_READONLY (TREE_TYPE (parmtype)))
- TYPE_HAS_CONST_INIT_REF (ctype) = 1;
- }
- else
- TYPE_GETS_INIT_AGGR (ctype) = 1;
+ || TREE_PURPOSE (TREE_CHAIN (parmtypes))))
+ {
+ TYPE_HAS_INIT_REF (ctype) = 1;
+ if (TYPE_READONLY (TREE_TYPE (parmtype)))
+ TYPE_HAS_CONST_INIT_REF (ctype) = 1;
}
- else if (TYPE_MAIN_VARIANT (parmtype) == ctype)
+ else if (TYPE_MAIN_VARIANT (parmtype) == ctype
+ && TREE_CHAIN (parmtypes) != NULL_TREE
+ && TREE_CHAIN (parmtypes) == void_list_node)
{
- if (TREE_CHAIN (parmtypes) != NULL_TREE
- && TREE_CHAIN (parmtypes) == void_list_node)
- {
- cp_error ("invalid constructor; you probably meant `%T (%T&)'",
- ctype, ctype);
- SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
-
- return 0;
- }
- else
- TYPE_GETS_INIT_AGGR (ctype) = 1;
+ cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
+ ctype, ctype);
+ SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
+ return 0;
}
else if (TREE_CODE (parmtype) == VOID_TYPE
|| TREE_PURPOSE (parmtypes) != NULL_TREE)
@@ -10185,6 +10970,7 @@ grok_ctor_properties (ctype, decl)
}
/* An operator with this name can be either unary or binary. */
+
static int
ambi_op_p (name)
tree name;
@@ -10198,6 +10984,7 @@ ambi_op_p (name)
}
/* An operator with this name can only be unary. */
+
static int
unary_op_p (name)
tree name;
@@ -10209,7 +10996,8 @@ unary_op_p (name)
}
/* Do a little sanity-checking on how they declared their operator. */
-static void
+
+void
grok_op_properties (decl, virtualp, friendp)
tree decl;
int virtualp, friendp;
@@ -10252,10 +11040,10 @@ grok_op_properties (decl, virtualp, friendp)
/* Take care of function decl if we had syntax errors. */
if (argtypes == NULL_TREE)
- TREE_TYPE (decl) =
- build_function_type (ptr_type_node,
- hash_tree_chain (integer_type_node,
- void_list_node));
+ TREE_TYPE (decl)
+ = build_function_type (ptr_type_node,
+ hash_tree_chain (integer_type_node,
+ void_list_node));
else
TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
}
@@ -10266,10 +11054,10 @@ grok_op_properties (decl, virtualp, friendp)
revert_static_member_fn (&decl, NULL, NULL);
if (argtypes == NULL_TREE)
- TREE_TYPE (decl) =
- build_function_type (void_type_node,
- hash_tree_chain (ptr_type_node,
- void_list_node));
+ TREE_TYPE (decl)
+ = build_function_type (void_type_node,
+ hash_tree_chain (ptr_type_node,
+ void_list_node));
else
{
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
@@ -10301,7 +11089,7 @@ grok_op_properties (decl, virtualp, friendp)
cp_error ("`%D' must be either a non-static member function or a non-member function", decl);
if (p)
- for (; TREE_VALUE (p) != void_type_node ; p = TREE_CHAIN (p))
+ for (; TREE_CODE (TREE_VALUE (p)) != VOID_TYPE ; p = TREE_CHAIN (p))
{
tree arg = TREE_VALUE (p);
if (TREE_CODE (arg) == REFERENCE_TYPE)
@@ -10310,7 +11098,8 @@ grok_op_properties (decl, virtualp, friendp)
/* This lets bad template code slip through. */
if (IS_AGGR_TYPE (arg)
|| TREE_CODE (arg) == ENUMERAL_TYPE
- || TREE_CODE (arg) == TEMPLATE_TYPE_PARM)
+ || TREE_CODE (arg) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
goto foundaggr;
}
cp_error
@@ -10321,11 +11110,10 @@ grok_op_properties (decl, virtualp, friendp)
}
}
- if (name == ansi_opname[(int) CALL_EXPR]
- || name == ansi_opname[(int) METHOD_CALL_EXPR])
- return; /* no restrictions on args */
+ if (name == ansi_opname[(int) CALL_EXPR])
+ return; /* No restrictions on args. */
- if (IDENTIFIER_TYPENAME_P (name))
+ if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
{
tree t = TREE_TYPE (name);
if (TREE_CODE (t) == VOID_TYPE)
@@ -10339,7 +11127,9 @@ grok_op_properties (decl, virtualp, friendp)
if (t == current_class_type)
what = "the same type";
+ /* Don't force t to be complete here. */
else if (IS_AGGR_TYPE (t)
+ && TYPE_SIZE (t)
&& DERIVED_FROM_P (t, current_class_type))
what = "a base class";
@@ -10367,10 +11157,6 @@ grok_op_properties (decl, virtualp, friendp)
if (TREE_CODE (parmtype) != REFERENCE_TYPE
|| TYPE_READONLY (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1;
-#if 0 /* Too soon; done in grok_function_init */
- if (DECL_ABSTRACT_VIRTUAL_P (decl))
- TYPE_HAS_ABSTRACT_ASSIGN_REF (current_class_type) = 1;
-#endif
}
}
else if (name == ansi_opname[(int) COND_EXPR])
@@ -10388,6 +11174,7 @@ grok_op_properties (decl, virtualp, friendp)
{
if ((name == ansi_opname[(int) POSTINCREMENT_EXPR]
|| name == ansi_opname[(int) POSTDECREMENT_EXPR])
+ && ! processing_template_decl
&& TREE_VALUE (TREE_CHAIN (argtypes)) != integer_type_node)
{
if (methodp)
@@ -10406,6 +11193,31 @@ grok_op_properties (decl, virtualp, friendp)
else
cp_error ("`%D' must take either one or two arguments", decl);
}
+
+ /* More Effective C++ rule 6. */
+ if (warn_ecpp
+ && (name == ansi_opname[(int) POSTINCREMENT_EXPR]
+ || name == ansi_opname[(int) POSTDECREMENT_EXPR]))
+ {
+ tree arg = TREE_VALUE (argtypes);
+ tree ret = TREE_TYPE (TREE_TYPE (decl));
+ if (methodp || TREE_CODE (arg) == REFERENCE_TYPE)
+ arg = TREE_TYPE (arg);
+ arg = TYPE_MAIN_VARIANT (arg);
+ if (list_length (argtypes) == 2)
+ {
+ if (TREE_CODE (ret) != REFERENCE_TYPE
+ || !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
+ arg, 1))
+ cp_warning ("prefix `%D' should return `%T'", decl,
+ build_reference_type (arg));
+ }
+ else
+ {
+ if (!comptypes (TYPE_MAIN_VARIANT (ret), arg, 1))
+ cp_warning ("postfix `%D' should return `%T'", decl, arg);
+ }
+ }
}
else if (unary_op_p (name))
{
@@ -10426,7 +11238,25 @@ grok_op_properties (decl, virtualp, friendp)
else
cp_error ("`%D' must take exactly two arguments", decl);
}
- }
+
+ /* More Effective C++ rule 7. */
+ if (warn_ecpp
+ && (name == ansi_opname [TRUTH_ANDIF_EXPR]
+ || name == ansi_opname [TRUTH_ORIF_EXPR]
+ || name == ansi_opname [COMPOUND_EXPR]))
+ cp_warning ("user-defined `%D' always evaluates both arguments",
+ decl);
+ }
+
+ /* Effective C++ rule 23. */
+ if (warn_ecpp
+ && list_length (argtypes) == 3
+ && (name == ansi_opname [PLUS_EXPR]
+ || name == ansi_opname [MINUS_EXPR]
+ || name == ansi_opname [TRUNC_DIV_EXPR]
+ || name == ansi_opname [MULT_EXPR])
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
+ cp_warning ("`%D' should return by value", decl);
/* 13.4.0.8 */
if (argtypes)
@@ -10465,9 +11295,20 @@ xref_tag (code_type_node, name, binfo, globalize)
enum tag_types tag_code;
enum tree_code code;
int temp = 0;
- int i;
register tree ref, t;
struct binding_level *b = inner_binding_level;
+ int got_type = 0;
+ tree attributes = NULL_TREE;
+
+ /* If we are called from the parser, code_type_node will sometimes be a
+ TREE_LIST. This indicates that the user wrote
+ "class __attribute__ ((foo)) bar". Extract the attributes so we can
+ use them later. */
+ if (TREE_CODE (code_type_node) == TREE_LIST)
+ {
+ attributes = TREE_PURPOSE (code_type_node);
+ code_type_node = TREE_VALUE (code_type_node);
+ }
tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
switch (tag_code)
@@ -10489,18 +11330,34 @@ xref_tag (code_type_node, name, binfo, globalize)
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
- t = IDENTIFIER_TYPE_VALUE (name);
- if (t && TREE_CODE (t) != code)
+ if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
+ {
+ t = name;
+ name = TYPE_IDENTIFIER (t);
+ got_type = 1;
+ }
+ else
+ t = IDENTIFIER_TYPE_VALUE (name);
+ if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM)
t = NULL_TREE;
if (! globalize)
{
- /* If we know we are defining this tag, only look it up in this scope
- * and don't try to find it as a type. */
- if (t && TYPE_CONTEXT(t) && TREE_MANGLED (name))
+ if (pedantic && t && (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM))
+ {
+ cp_pedwarn ("redeclaration of template type-parameter `%T'", name);
+ cp_pedwarn_at (" previously declared here", t);
+ }
+ if (t && TYPE_CONTEXT (t) && got_type)
ref = t;
else
- ref = lookup_tag (code, name, b, 1);
+ {
+ /* If we know we are defining this tag, only look it up in
+ this scope and don't try to find it as a type. */
+ ref = lookup_tag (code, name, b, 1);
+ }
}
else
{
@@ -10513,6 +11370,15 @@ xref_tag (code_type_node, name, binfo, globalize)
{
/* Try finding it as a type declaration. If that wins, use it. */
ref = lookup_name (name, 1);
+
+ if (ref != NULL_TREE
+ && processing_template_decl
+ && DECL_CLASS_TEMPLATE_P (ref)
+ && template_class_depth (current_class_type) == 0)
+ /* Since GLOBALIZE is true, we're declaring a global
+ template, so we want this type. */
+ ref = DECL_RESULT (ref);
+
if (ref && TREE_CODE (ref) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (ref)) == code)
ref = TREE_TYPE (ref);
@@ -10539,6 +11405,8 @@ xref_tag (code_type_node, name, binfo, globalize)
if (code == ENUMERAL_TYPE)
{
+ cp_error ("use of enum `%#D' without previous declaration", name);
+
ref = make_node (ENUMERAL_TYPE);
/* Give the type a default layout like unsigned int
@@ -10556,8 +11424,6 @@ xref_tag (code_type_node, name, binfo, globalize)
done in `start_enum'. */
pushtag (name, ref, globalize);
- if (flag_cadillac)
- cadillac_start_enum (ref);
}
else
{
@@ -10582,50 +11448,27 @@ xref_tag (code_type_node, name, binfo, globalize)
#endif
pushtag (name, ref, globalize);
class_binding_level = old_b;
-
- if (flag_cadillac)
- cadillac_start_struct (ref);
}
}
else
{
/* If it no longer looks like a nested type, make sure it's
- in global scope. */
- if (b == global_binding_level && !class_binding_level
- && IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE)
- IDENTIFIER_GLOBAL_VALUE (name) = TYPE_NAME (ref);
-
-#if 0
- if (binfo)
+ in global scope.
+ If it is not an IDENTIFIER, this is not a declaration */
+ if (b->namespace_p && !class_binding_level
+ && TREE_CODE (name) == IDENTIFIER_NODE)
{
- tree tt1 = binfo;
- tree tt2 = TYPE_BINFO_BASETYPES (ref);
-
- if (TYPE_BINFO_BASETYPES (ref))
- for (i = 0; tt1; i++, tt1 = TREE_CHAIN (tt1))
- if (TREE_VALUE (tt1) != TYPE_IDENTIFIER (BINFO_TYPE (TREE_VEC_ELT (tt2, i))))
- {
- cp_error ("redeclaration of derivation chain of type `%#T'",
- ref);
- break;
- }
-
- if (tt1 == NULL_TREE)
- /* The user told us something we already knew. */
- goto just_return;
-
- /* In C++, since these migrate into the global scope, we must
- build them on the permanent obstack. */
- end_temporary_allocation ();
+ if (IDENTIFIER_NAMESPACE_VALUE (name) == NULL_TREE)
+ SET_IDENTIFIER_NAMESPACE_VALUE (name, TYPE_NAME (ref));
}
-#endif
+
+ if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref))
+ redeclare_class_template (ref, current_template_parms);
}
if (binfo)
xref_basetypes (code_type_node, name, ref, binfo);
- just_return:
-
/* Until the type is defined, tentatively accept whatever
structure tag the user hands us. */
if (TYPE_SIZE (ref) == NULL_TREE
@@ -10641,9 +11484,30 @@ xref_tag (code_type_node, name, binfo, globalize)
pop_obstacks ();
+ TREE_TYPE (ref) = attributes;
+
return ref;
}
+tree
+xref_tag_from_type (old, id, globalize)
+ tree old, id;
+ int globalize;
+{
+ tree code_type_node;
+
+ if (TREE_CODE (old) == RECORD_TYPE)
+ code_type_node = (CLASSTYPE_DECLARED_CLASS (old)
+ ? class_type_node : record_type_node);
+ else
+ code_type_node = union_type_node;
+
+ if (id == NULL_TREE)
+ id = TYPE_IDENTIFIER (old);
+
+ return xref_tag (code_type_node, id, NULL_TREE, globalize);
+}
+
void
xref_basetypes (code_type_node, name, ref, binfo)
tree code_type_node;
@@ -10672,34 +11536,42 @@ xref_basetypes (code_type_node, name, ref, binfo)
{
/* The base of a derived struct is public by default. */
int via_public
- = (TREE_PURPOSE (binfo) == (tree)access_public
- || TREE_PURPOSE (binfo) == (tree)access_public_virtual
+ = (TREE_PURPOSE (binfo) == access_public_node
+ || TREE_PURPOSE (binfo) == access_public_virtual_node
|| (tag_code != class_type
- && (TREE_PURPOSE (binfo) == (tree)access_default
- || TREE_PURPOSE (binfo) == (tree)access_default_virtual)));
- int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected;
+ && (TREE_PURPOSE (binfo) == access_default_node
+ || TREE_PURPOSE (binfo) == access_default_virtual_node)));
+ int via_protected
+ = (TREE_PURPOSE (binfo) == access_protected_node
+ || TREE_PURPOSE (binfo) == access_protected_virtual_node);
int via_virtual
- = (TREE_PURPOSE (binfo) == (tree)access_private_virtual
- || TREE_PURPOSE (binfo) == (tree)access_public_virtual
- || TREE_PURPOSE (binfo) == (tree)access_default_virtual);
- tree basetype = TREE_TYPE (TREE_VALUE (binfo));
+ = (TREE_PURPOSE (binfo) == access_private_virtual_node
+ || TREE_PURPOSE (binfo) == access_protected_virtual_node
+ || TREE_PURPOSE (binfo) == access_public_virtual_node
+ || TREE_PURPOSE (binfo) == access_default_virtual_node);
+ tree basetype = TREE_VALUE (binfo);
tree base_binfo;
- GNU_xref_hier (IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (TREE_VALUE (binfo)),
- via_public, via_virtual, 0);
-
if (basetype && TREE_CODE (basetype) == TYPE_DECL)
basetype = TREE_TYPE (basetype);
- if (!basetype || TREE_CODE (basetype) != RECORD_TYPE)
+ if (!basetype
+ || (TREE_CODE (basetype) != RECORD_TYPE
+ && TREE_CODE (basetype) != TYPENAME_TYPE
+ && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (basetype) != TEMPLATE_TEMPLATE_PARM))
{
cp_error ("base type `%T' fails to be a struct or class type",
TREE_VALUE (binfo));
continue;
}
+
+ GNU_xref_hier (name, basetype, via_public, via_virtual, 0);
+
#if 1
- /* This code replaces similar code in layout_basetypes. */
- else if (TYPE_INCOMPLETE (basetype))
+ /* This code replaces similar code in layout_basetypes.
+ We put the complete_type first for implicit `typename'. */
+ if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE
+ && ! (current_template_parms && uses_template_parms (basetype)))
{
cp_error ("base class `%T' has incomplete type", basetype);
continue;
@@ -10716,6 +11588,10 @@ xref_basetypes (code_type_node, name, ref, binfo)
continue;
}
+ if (TYPE_FOR_JAVA (basetype)
+ && current_lang_stack == current_lang_base)
+ TYPE_FOR_JAVA (ref) = 1;
+
/* Note that the BINFO records which describe individual
inheritances are *not* shared in the lattice! They
cannot be shared because a given baseclass may be
@@ -10735,17 +11611,7 @@ xref_basetypes (code_type_node, name, ref, binfo)
BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
SET_CLASSTYPE_MARKED (basetype);
-#if 0
- /* XYZZY TEST VIRTUAL BASECLASSES */
- if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE
- && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
- && via_virtual == 0)
- {
- warning ("making type `%s' a virtual baseclass",
- TYPE_NAME_STRING (basetype));
- via_virtual = 1;
- }
-#endif
+
/* We are free to modify these bits because they are meaningless
at top level, and BASETYPE is a top-level type. */
if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
@@ -10754,7 +11620,6 @@ xref_basetypes (code_type_node, name, ref, binfo)
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
}
- TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
@@ -10783,7 +11648,7 @@ xref_basetypes (code_type_node, name, ref, binfo)
}
-static tree current_local_enum = NULL_TREE;
+tree current_local_enum = NULL_TREE;
/* Begin compiling the definition of an enumeration type.
NAME is its name (or null if anonymous).
@@ -10798,6 +11663,14 @@ start_enum (name)
register tree enumtype = NULL_TREE;
struct binding_level *b = inner_binding_level;
+ /* We are wasting space here and putting these on the permanent_obstack so
+ that typeid(local enum) will work correctly. */
+#if 0
+ if (processing_template_decl && current_function_decl)
+#endif
+
+ end_temporary_allocation ();
+
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
forward reference. */
@@ -10806,36 +11679,23 @@ start_enum (name)
enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1);
if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
- cp_error ("multiple definition of enum `%T'", enumtype);
+ cp_error ("multiple definition of `%#T'", enumtype);
else
{
enumtype = make_node (ENUMERAL_TYPE);
pushtag (name, enumtype, 0);
}
+ if (b->pseudo_global)
+ cp_error ("template declaration of `%#T'", enumtype);
+
if (current_class_type)
TREE_ADDRESSABLE (b->tags) = 1;
- current_local_enum = NULL_TREE;
-
-#if 0 /* This stuff gets cleared in finish_enum anyway. */
- if (TYPE_VALUES (enumtype) != NULL_TREE)
- /* Completely replace its old definition.
- The old enumerators remain defined, however. */
- TYPE_VALUES (enumtype) = NULL_TREE;
-
- /* Initially, set up this enum as like `int'
- so that we can create the enumerators' declarations and values.
- Later on, the precision of the type may be changed and
- it may be laid out again. */
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
- TYPE_SIZE (enumtype) = NULL_TREE;
- fixup_signed_type (enumtype);
-#endif
+ current_local_enum = NULL_TREE;
- /* We copy this value because enumerated type constants
- are really of the type of the enumerator, not integer_type_node. */
- enum_next_value = copy_node (integer_zero_node);
+ /* We don't copy this value because build_enumerator needs to do it. */
+ enum_next_value = integer_zero_node;
enum_overflow = 0;
GNU_xref_decl (current_function_decl, enumtype);
@@ -10851,36 +11711,52 @@ tree
finish_enum (enumtype, values)
register tree enumtype, values;
{
- register tree minnode, maxnode;
+ register tree minnode = NULL_TREE, maxnode = NULL_TREE;
/* Calculate the maximum value of any enumerator in this type. */
if (values)
{
register tree pair;
register tree value = DECL_INITIAL (TREE_VALUE (values));
-
- /* Speed up the main loop by performing some precalculations */
- TREE_TYPE (TREE_VALUE (values)) = enumtype;
- TREE_TYPE (value) = enumtype;
+
+ if (! processing_template_decl)
+ {
+ /* Speed up the main loop by performing some precalculations */
+ TREE_TYPE (TREE_VALUE (values)) = enumtype;
+ TREE_TYPE (value) = enumtype;
+ minnode = maxnode = value;
+ }
TREE_VALUE (values) = value;
- minnode = maxnode = value;
for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
{
value = DECL_INITIAL (TREE_VALUE (pair));
- TREE_TYPE (TREE_VALUE (pair)) = enumtype;
- TREE_TYPE (value) = enumtype;
+ if (! processing_template_decl)
+ {
+ TREE_TYPE (TREE_VALUE (pair)) = enumtype;
+ TREE_TYPE (value) = enumtype;
+ if (tree_int_cst_lt (maxnode, value))
+ maxnode = value;
+ else if (tree_int_cst_lt (value, minnode))
+ minnode = value;
+ }
TREE_VALUE (pair) = value;
- if (tree_int_cst_lt (maxnode, value))
- maxnode = value;
- else if (tree_int_cst_lt (value, minnode))
- minnode = value;
}
}
else
maxnode = minnode = integer_zero_node;
- TYPE_VALUES (enumtype) = values;
+ TYPE_VALUES (enumtype) = nreverse (values);
+
+ if (processing_template_decl)
+ {
+ if (current_function_decl)
+ {
+ add_tree (build_min (TAG_DEFN, enumtype));
+ resume_temporary_allocation ();
+ }
+ return enumtype;
+ }
{
int unsignedp = tree_int_cst_sgn (minnode) >= 0;
@@ -10898,7 +11774,7 @@ finish_enum (enumtype, values)
else
fixup_signed_type (enumtype);
- if (flag_short_enums || precision > TYPE_PRECISION (integer_type_node))
+ if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
/* Use the width of the narrowest normal C type which is wide enough. */
TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
(precision, 1));
@@ -10909,9 +11785,6 @@ finish_enum (enumtype, values)
layout_type (enumtype);
}
- if (flag_cadillac)
- cadillac_finish_enum (enumtype);
-
{
register tree tem;
@@ -10923,6 +11796,7 @@ finish_enum (enumtype, values)
TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
+ TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
TYPE_MODE (tem) = TYPE_MODE (enumtype);
TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
@@ -10931,12 +11805,7 @@ finish_enum (enumtype, values)
}
/* Finish debugging output for this type. */
-#if 0
- /* @@ Do we ever generate generate ENUMERAL_TYPE nodes for which debugging
- information should *not* be generated? I think not. */
- if (! DECL_IGNORED_P (TYPE_NAME (enumtype)))
-#endif
- rest_of_type_compilation (enumtype, global_bindings_p ());
+ rest_of_type_compilation (enumtype, namespace_bindings_p ());
return enumtype;
}
@@ -10951,61 +11820,51 @@ build_enumerator (name, value)
tree name, value;
{
tree decl, result;
- /* Change this to zero if we find VALUE is not shareable. */
- int shareable = 1;
/* Remove no-op casts from the value. */
if (value)
STRIP_TYPE_NOPS (value);
- /* Validate and default VALUE. */
- if (value != NULL_TREE)
- {
- if (TREE_READONLY_DECL_P (value))
- {
- value = decl_constant_value (value);
- shareable = 0;
- }
-
- if (TREE_CODE (value) == INTEGER_CST)
- {
- value = default_conversion (value);
- constant_expression_warning (value);
- }
- else
- {
- cp_error ("enumerator value for `%D' not integer constant", name);
- value = NULL_TREE;
- }
- }
-
- /* The order of things is reversed here so that we
- can check for possible sharing of enum values,
- to keep that from happening. */
- /* Default based on previous value. */
- if (value == NULL_TREE)
- {
- value = enum_next_value;
- if (enum_overflow)
- cp_error ("overflow in enumeration values at `%D'", name);
- }
-
- /* Remove no-op casts from the value. */
- if (value)
- STRIP_TYPE_NOPS (value);
-
- /* Make up for hacks in lex.c. */
- if (value == integer_zero_node)
- value = build_int_2 (0, 0);
- else if (value == integer_one_node)
- value = build_int_2 (1, 0);
- else if (TREE_CODE (value) == INTEGER_CST
- && (shareable == 0
- || TREE_CODE (TREE_TYPE (value)) == ENUMERAL_TYPE))
- {
- value = copy_node (value);
- TREE_TYPE (value) = integer_type_node;
- }
+ if (! processing_template_decl)
+ {
+ /* Validate and default VALUE. */
+ if (value != NULL_TREE)
+ {
+ if (TREE_READONLY_DECL_P (value))
+ value = decl_constant_value (value);
+
+ if (TREE_CODE (value) == INTEGER_CST)
+ {
+ value = default_conversion (value);
+ constant_expression_warning (value);
+ }
+ else
+ {
+ cp_error ("enumerator value for `%D' not integer constant", name);
+ value = NULL_TREE;
+ }
+ }
+
+ /* Default based on previous value. */
+ if (value == NULL_TREE && ! processing_template_decl)
+ {
+ value = enum_next_value;
+ if (enum_overflow)
+ cp_error ("overflow in enumeration values at `%D'", name);
+ }
+
+ /* Remove no-op casts from the value. */
+ if (value)
+ STRIP_TYPE_NOPS (value);
+
+ /* We have to always copy here; not all INTEGER_CSTs are unshared,
+ and there's no wedding ring. Look at size_int()...*/
+ value = copy_node (value);
+#if 0
+ /* To fix MAX_VAL enum consts. (bkoz) */
+ TREE_TYPE (value) = integer_type_node;
+#endif
+ }
/* C++ associates enums with global, function, or class declarations. */
@@ -11027,26 +11886,27 @@ build_enumerator (name, value)
a function could mean local to a class method. */
decl = build_decl (CONST_DECL, name, integer_type_node);
DECL_INITIAL (decl) = value;
+ TREE_READONLY (decl) = 1;
pushdecl (decl);
GNU_xref_decl (current_function_decl, decl);
}
- /* Set basis for default for next value. */
- enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
- integer_one_node, PLUS_EXPR);
- enum_overflow = tree_int_cst_lt (enum_next_value, value);
-
- if (enum_next_value == integer_one_node)
- enum_next_value = copy_node (enum_next_value);
+ if (! processing_template_decl)
+ {
+ /* Set basis for default for next value. */
+ enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
+ integer_one_node, PLUS_EXPR);
+ enum_overflow = tree_int_cst_lt (enum_next_value, value);
+ }
result = saveable_tree_cons (name, decl, NULL_TREE);
return result;
}
tree
-grok_enum_decls (type, decl)
- tree type, decl;
+grok_enum_decls (decl)
+ tree decl;
{
tree d = current_local_enum;
@@ -11055,7 +11915,6 @@ grok_enum_decls (type, decl)
while (1)
{
- TREE_TYPE (d) = type;
if (TREE_CHAIN (d) == NULL_TREE)
{
TREE_CHAIN (d) = decl;
@@ -11070,6 +11929,8 @@ grok_enum_decls (type, decl)
return decl;
}
+static int function_depth;
+
/* Create the FUNCTION_DECL for a function definition.
DECLSPECS and DECLARATOR are the parts of the declaration;
they describe the function's name and the type it returns,
@@ -11092,11 +11953,11 @@ grok_enum_decls (type, decl)
@@ something we had previously. */
int
-start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
- tree declspecs, declarator, raises, attrs;
+start_function (declspecs, declarator, attrs, pre_parsed_p)
+ tree declspecs, declarator, attrs;
int pre_parsed_p;
{
- tree decl1, olddecl;
+ tree decl1;
tree ctype = NULL_TREE;
tree fntype;
tree restype;
@@ -11105,10 +11966,10 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
int doing_friend = 0;
/* Sanity check. */
- my_friendly_assert (TREE_VALUE (void_list_node) == void_type_node, 160);
+ my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
- /* Assume, until we see it does. */
+ /* Assume, until we see it does. */
current_function_returns_value = 0;
current_function_returns_null = 0;
warn_about_return_type = 0;
@@ -11118,17 +11979,15 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
current_function_just_assigned_this = 0;
current_function_parms_stored = 0;
original_result_rtx = NULL_RTX;
- current_function_obstack_index = 0;
- current_function_obstack_usage = 0;
base_init_expr = NULL_TREE;
- protect_list = NULL_TREE;
current_base_init_list = NULL_TREE;
current_member_init_list = NULL_TREE;
ctor_label = dtor_label = NULL_TREE;
+ static_labelno = 0;
clear_temp_name ();
- /* This should only be done once on the top most decl. */
+ /* This should only be done once on the top most decl. */
if (have_extern_spec && !used_extern_spec)
{
declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
@@ -11139,31 +11998,25 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
{
decl1 = declarator;
+#if 0
+ /* What was this testing for, exactly? */
if (! DECL_ARGUMENTS (decl1)
&& !DECL_STATIC_FUNCTION_P (decl1)
- && DECL_CONTEXT (decl1)
- && DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl1)))
- && IDENTIFIER_TEMPLATE (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl1)))))
+ && !DECL_ARTIFICIAL (decl1)
+ && DECL_CLASS_SCOPE_P (decl1)
+ && TYPE_IDENTIFIER (DECL_CONTEXT (decl1))
+ && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (DECL_CONTEXT (decl1))))
{
+ tree binding = binding_for_name (DECL_NAME (decl1),
+ current_namespace);
cp_error ("redeclaration of `%#D'", decl1);
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1)))
cp_error_at ("previous declaration here", IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1)));
- else if (IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl1)))
- cp_error_at ("previous declaration here", IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl1)));
- }
-
- /* This can happen if a template class is instantiated as part of the
- specialization of a member function which is defined in the class
- template. We should just use the specialization, but for now give an
- error. */
- if (DECL_INITIAL (decl1) != NULL_TREE)
- {
- cp_error_at ("specialization of `%#D' not supported", decl1);
- cp_error ("when defined in the class template body", decl1);
+ else if (BINDING_VALUE (binding))
+ cp_error_at ("previous declaration here", BINDING_VALUE (binding));
}
+#endif
- last_function_parms = DECL_ARGUMENTS (decl1);
- last_function_parm_tags = NULL_TREE;
fntype = TREE_TYPE (decl1);
if (TREE_CODE (fntype) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (fntype);
@@ -11184,23 +12037,23 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
doing_friend = 1;
}
- raises = TYPE_RAISES_EXCEPTIONS (fntype);
-
/* In a fcn definition, arg types must be complete. */
- require_complete_types_for_parms (last_function_parms);
+ require_complete_types_for_parms (DECL_ARGUMENTS (decl1));
/* In case some arg types were completed since the declaration was
parsed, fix up the decls. */
{
- tree t = last_function_parms;
+ tree t = DECL_ARGUMENTS (decl1);
for (; t; t = TREE_CHAIN (t))
layout_decl (t, 0);
}
+
+ last_function_parms = DECL_ARGUMENTS (decl1);
+ last_function_parm_tags = NULL_TREE;
}
else
{
- decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, raises,
- NULL_TREE);
+ decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, 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;
@@ -11212,7 +12065,7 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
&& ! CLASSTYPE_GOT_SEMICOLON (restype))
{
cp_error ("semicolon missing after declaration of `%#T'", restype);
- shadow_tag (build_tree_list (NULL_TREE, restype));
+ shadow_tag (build_expr_list (NULL_TREE, restype));
CLASSTYPE_GOT_SEMICOLON (restype) = 1;
if (TREE_CODE (fntype) == FUNCTION_TYPE)
fntype = build_function_type (integer_type_node,
@@ -11226,15 +12079,13 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
if (TREE_CODE (fntype) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (fntype);
- else if (IDENTIFIER_LENGTH (DECL_NAME (decl1)) == 4
- && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (decl1)), "main")
- && DECL_CONTEXT (decl1) == NULL_TREE)
+ else if (DECL_MAIN_P (decl1))
{
/* If this doesn't return integer_type, complain. */
if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
{
if (pedantic || warn_return_type)
- pedwarn ("return type for `main' changed to integer type");
+ pedwarn ("return type for `main' changed to `int'");
TREE_TYPE (decl1) = fntype = default_function_type;
}
warn_about_return_type = 0;
@@ -11248,53 +12099,57 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
current_function_decl = decl1;
+ /* Save the parm names or decls from this function's declarator
+ where store_parm_decls will find them. */
+ current_function_parms = last_function_parms;
+ current_function_parm_tags = last_function_parm_tags;
- if (flag_cadillac)
- cadillac_start_function (decl1);
- else
- announce_function (decl1);
+ announce_function (decl1);
- if (TYPE_SIZE (TREE_TYPE (fntype)) == NULL_TREE)
+ if (! processing_template_decl)
{
- if (IS_AGGR_TYPE (TREE_TYPE (fntype)))
- error_with_aggr_type (TREE_TYPE (fntype),
- "return-type `%s' is an incomplete type");
- else
- error ("return-type is an incomplete type");
-
- /* Make it return void instead, but don't change the
- type of the DECL_RESULT, in case we have a named return value. */
- if (ctype)
- TREE_TYPE (decl1)
- = build_cplus_method_type (build_type_variant (ctype,
- TREE_READONLY (decl1),
- TREE_SIDE_EFFECTS (decl1)),
- void_type_node,
- FUNCTION_ARG_CHAIN (decl1));
- else
- TREE_TYPE (decl1)
- = build_function_type (void_type_node,
- TYPE_ARG_TYPES (TREE_TYPE (decl1)));
- DECL_RESULT (decl1)
- = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (fntype)));
- TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (TREE_TYPE (fntype));
- TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (TREE_TYPE (fntype));
- }
+ if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE)
+ {
+ cp_error ("return-type `%#T' is an incomplete type",
+ TREE_TYPE (fntype));
+
+ /* Make it return void instead, but don't change the
+ type of the DECL_RESULT, in case we have a named return value. */
+ if (ctype)
+ TREE_TYPE (decl1)
+ = build_cplus_method_type (build_type_variant (ctype,
+ TREE_READONLY (decl1),
+ TREE_SIDE_EFFECTS (decl1)),
+ void_type_node,
+ FUNCTION_ARG_CHAIN (decl1));
+ else
+ TREE_TYPE (decl1)
+ = build_function_type (void_type_node,
+ TYPE_ARG_TYPES (TREE_TYPE (decl1)));
+ DECL_RESULT (decl1)
+ = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (fntype)));
+ TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (TREE_TYPE (fntype));
+ TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (TREE_TYPE (fntype));
+ }
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
- && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype)))
- abstract_virtuals_error (decl1, TREE_TYPE (fntype));
+ if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
+ && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype)))
+ abstract_virtuals_error (decl1, TREE_TYPE (fntype));
+ }
if (warn_about_return_type)
- warning ("return-type defaults to `int'");
+ pedwarn ("return-type defaults to `int'");
+
+ /* Effective C++ rule 15. See also c_expand_return. */
+ if (warn_ecpp
+ && DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
+ && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
+ cp_warning ("`operator=' should return a reference to `*this'");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
error_mark_node is replaced below (in poplevel) with the BLOCK. */
DECL_INITIAL (decl1) = error_mark_node;
- /* Didn't get anything from C. */
- olddecl = NULL_TREE;
-
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
@@ -11303,26 +12158,51 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */
- if (pre_parsed_p == 0)
- {
- current_function_decl = decl1 = pushdecl (decl1);
+ if (processing_template_decl)
+ decl1 = push_template_decl (decl1);
+ else if (pre_parsed_p == 0)
+ {
+ /* A specialization is not used to guide overload resolution. */
+ if ((flag_guiding_decls
+ || !DECL_TEMPLATE_SPECIALIZATION (decl1))
+ && ! DECL_FUNCTION_MEMBER_P (decl1))
+ decl1 = pushdecl (decl1);
+ else
+ {
+ /* We need to set the DECL_CONTEXT. */
+ if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
+ DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
+ /* And make sure we have enough default args. */
+ check_default_args (decl1);
+ }
DECL_MAIN_VARIANT (decl1) = decl1;
fntype = TREE_TYPE (decl1);
}
- else
- current_function_decl = decl1;
+
+ current_function_decl = decl1;
if (DECL_INTERFACE_KNOWN (decl1))
{
+ tree ctx = hack_decl_function_context (decl1);
+
if (DECL_NOT_REALLY_EXTERN (decl1))
DECL_EXTERNAL (decl1) = 0;
+
+ if (ctx != NULL_TREE && DECL_THIS_INLINE (ctx)
+ && TREE_PUBLIC (ctx))
+ /* This is a function in a local class in an extern inline
+ function. */
+ comdat_linkage (decl1);
}
/* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external.
It doesn't matter whether it's inline or not. */
- else if (interface_unknown == 0)
+ else if (interface_unknown == 0
+ && (! DECL_TEMPLATE_INSTANTIATION (decl1)
+ || flag_alt_external_templates))
{
- if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
+ if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)
+ || processing_template_decl)
DECL_EXTERNAL (decl1)
= (interface_only
|| (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
@@ -11337,14 +12217,13 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
So clear DECL_EXTERNAL. */
DECL_EXTERNAL (decl1) = 0;
- if (DECL_THIS_INLINE (decl1) && ! DECL_INTERFACE_KNOWN (decl1))
+ if ((DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
+ && ! DECL_INTERFACE_KNOWN (decl1)
+ /* Don't try to defer nested functions for now. */
+ && ! hack_decl_function_context (decl1))
DECL_DEFER_OUTPUT (decl1) = 1;
else
- {
- DECL_INTERFACE_KNOWN (decl1) = 1;
- if (DECL_C_STATIC (decl1))
- TREE_PUBLIC (decl1) = 0;
- }
+ DECL_INTERFACE_KNOWN (decl1) = 1;
}
if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1))
@@ -11353,8 +12232,8 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
TREE_TYPE (decl1) = fntype
= build_function_type (TREE_TYPE (fntype),
TREE_CHAIN (TYPE_ARG_TYPES (fntype)));
- last_function_parms = TREE_CHAIN (last_function_parms);
- DECL_ARGUMENTS (decl1) = last_function_parms;
+ current_function_parms = TREE_CHAIN (current_function_parms);
+ DECL_ARGUMENTS (decl1) = current_function_parms;
ctype = NULL_TREE;
}
restype = TREE_TYPE (fntype);
@@ -11364,15 +12243,15 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
push_nested_class (ctype, 1);
/* If we're compiling a friend function, neither of the variables
- current_class_decl nor current_class_type will have values. */
+ current_class_ptr nor current_class_type will have values. */
if (! doing_friend)
{
/* We know that this was set up by `grokclassfn'.
We do not wait until `store_parm_decls', since evil
parse errors may never get us to that point. Here
we keep the consistency between `current_class_type'
- and `current_class_decl'. */
- tree t = last_function_parms;
+ and `current_class_ptr'. */
+ tree t = current_function_parms;
my_friendly_assert (t != NULL_TREE
&& TREE_CODE (t) == PARM_DECL, 162);
@@ -11382,14 +12261,14 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
int i = suspend_momentary ();
/* Fool build_indirect_ref. */
- current_class_decl = NULL_TREE;
- C_C_D = build_indirect_ref (t, NULL_PTR);
- current_class_decl = t;
+ current_class_ptr = NULL_TREE;
+ current_class_ref = build_indirect_ref (t, NULL_PTR);
+ current_class_ptr = t;
resume_momentary (i);
}
else
/* We're having a signature pointer here. */
- C_C_D = current_class_decl = t;
+ current_class_ref = current_class_ptr = t;
}
}
@@ -11399,40 +12278,27 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
push_nested_class (DECL_CONTEXT (decl1), 2);
else
push_memoized_context (0, 1);
- current_class_decl = C_C_D = NULL_TREE;
+ current_class_ptr = current_class_ref = NULL_TREE;
}
pushlevel (0);
current_binding_level->parm_flag = 1;
- /* Save the parm names or decls from this function's declarator
- where store_parm_decls will find them. */
- current_function_parms = last_function_parms;
- current_function_parm_tags = last_function_parm_tags;
-
GNU_xref_function (decl1, current_function_parms);
if (attrs)
cplus_decl_attributes (decl1, NULL_TREE, attrs);
make_function_rtl (decl1);
- /* Allocate further tree nodes temporarily during compilation
- of this function only. Tiemann moved up here from bottom of fn. */
- temporary_allocation ();
-
/* Promote the value to int before returning it. */
if (C_PROMOTING_INTEGER_TYPE_P (restype))
- {
- /* It retains unsignedness if traditional or if it isn't
- really getting wider. */
- if (TREE_UNSIGNED (restype)
- && (flag_traditional
- || TYPE_PRECISION (restype)
- == TYPE_PRECISION (integer_type_node)))
- restype = unsigned_type_node;
- else
- restype = integer_type_node;
- }
+ restype = type_promotes_to (restype);
+
+ /* If this fcn was already referenced via a block-scope `extern' decl
+ (or an implicit decl), propagate certain information about the usage. */
+ if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl1)))
+ TREE_ADDRESSABLE (decl1) = 1;
+
if (DECL_RESULT (decl1) == NULL_TREE)
{
DECL_RESULT (decl1)
@@ -11441,6 +12307,22 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (restype);
}
+ /* Allocate further tree nodes temporarily during compilation
+ of this function only. Tiemann moved up here from bottom of fn. */
+ /* If this is a nested function, then we must continue to allocate RTL
+ on the permanent obstack in case we need to inline it later. */
+ if (! hack_decl_function_context (decl1))
+ temporary_allocation ();
+
+ if (processing_template_decl)
+ {
+ ++minimal_parse_mode;
+ last_tree = DECL_SAVED_TREE (decl1)
+ = build_nt (EXPR_STMT, void_zero_node);
+ }
+
+ ++function_depth;
+
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1))
&& DECL_LANGUAGE (decl1) == lang_cplusplus)
{
@@ -11454,36 +12336,18 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
}
- /* If this fcn was already referenced via a block-scope `extern' decl
- (or an implicit decl), propagate certain information about the usage. */
- if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl1)))
- TREE_ADDRESSABLE (decl1) = 1;
-
return 1;
}
+/* Called after store_parm_decls for a function-try-block. We need to update
+ last_parm_cleanup_insn so that the base initializers for a constructor
+ are run within this block, not before it. */
+
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));
+ last_parm_cleanup_insn = get_last_insn ();
}
/* Store the parameter declarations into the current function declaration.
@@ -11498,6 +12362,7 @@ store_parm_decls ()
register tree fndecl = current_function_decl;
register tree parm;
int parms_have_cleanups = 0;
+ tree cleanups = NULL_TREE;
/* This is either a chain of PARM_DECLs (when a prototype is used). */
tree specparms = current_function_parms;
@@ -11534,22 +12399,18 @@ store_parm_decls ()
/* Must clear this because it might contain TYPE_DECLs declared
at class level. */
storedecls (NULL_TREE);
+
for (parm = nreverse (specparms); parm; parm = next)
{
next = TREE_CHAIN (parm);
if (TREE_CODE (parm) == PARM_DECL)
{
- tree cleanup = maybe_build_cleanup (parm);
+ tree cleanup;
if (DECL_NAME (parm) == NULL_TREE)
{
-#if 0
- cp_error_at ("parameter name omitted", parm);
-#else
- /* for C++, this is not an error. */
pushdecl (parm);
-#endif
}
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
+ else if (TREE_CODE (TREE_TYPE (parm)) == VOID_TYPE)
cp_error ("parameter `%D' declared void", parm);
else
{
@@ -11572,13 +12433,14 @@ store_parm_decls ()
pushdecl (parm);
}
- if (cleanup)
+ if (! processing_template_decl
+ && (cleanup = maybe_build_cleanup (parm), cleanup))
{
expand_decl (parm);
- if (! cp_expand_decl_cleanup (parm, cleanup))
- cp_error ("parser lost in parsing declaration of `%D'",
- parm);
parms_have_cleanups = 1;
+
+ /* Keep track of the cleanups. */
+ cleanups = tree_cons (parm, cleanup, cleanups);
}
}
else
@@ -11609,7 +12471,29 @@ store_parm_decls ()
/* Initialize the RTL code for the function. */
DECL_SAVED_INSNS (fndecl) = NULL_RTX;
- expand_function_start (fndecl, parms_have_cleanups);
+ if (! processing_template_decl)
+ expand_function_start (fndecl, parms_have_cleanups);
+
+ current_function_parms_stored = 1;
+
+ /* If this function is `main', emit a call to `__main'
+ to run global initializers, etc. */
+ if (DECL_MAIN_P (fndecl))
+ expand_main_function ();
+
+ /* Now that we have initialized the parms, we can start their
+ cleanups. We cannot do this before, since expand_decl_cleanup
+ should not be called before the parm can be used. */
+ if (cleanups
+ && ! processing_template_decl)
+ {
+ for (cleanups = nreverse (cleanups); cleanups; cleanups = TREE_CHAIN (cleanups))
+ {
+ if (! expand_decl_cleanup (TREE_PURPOSE (cleanups), TREE_VALUE (cleanups)))
+ cp_error ("parser lost in parsing declaration of `%D'",
+ TREE_PURPOSE (cleanups));
+ }
+ }
/* Create a binding contour which can be used to catch
cleanup-generated temporaries. Also, if the return value needs or
@@ -11620,57 +12504,20 @@ store_parm_decls ()
expand_start_bindings (0);
}
- current_function_parms_stored = 1;
-
- if (flag_gc)
- {
- maybe_gc_cleanup = build_tree_list (NULL_TREE, error_mark_node);
- if (! cp_expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup))
- cp_error ("parser lost in parsing declaration of `%D'", fndecl);
- }
-
- /* If this function is `main', emit a call to `__main'
- to run global initializers, etc. */
- if (DECL_NAME (fndecl)
- && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
- && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0
- && DECL_CONTEXT (fndecl) == NULL_TREE)
- {
- expand_main_function ();
-
- if (flag_gc)
- expand_expr (build_function_call (lookup_name (get_identifier ("__gc_main"), 0), NULL_TREE),
- 0, VOIDmode, 0);
-#if 0
- /* done at a different time */
- if (flag_rtti)
- output_builtin_tdesc_entries ();
-#endif
- }
-
- /* Take care of exception handling things. */
- if (flag_handle_exceptions)
+ if (! processing_template_decl && flag_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);
}
+
+ last_parm_cleanup_insn = get_last_insn ();
+ last_dtor_insn = get_last_insn ();
}
/* Bind a name and initialization to the return value of
the current function. */
+
void
store_return_init (return_id, init)
tree return_id, init;
@@ -11691,8 +12538,7 @@ store_return_init (return_id, init)
DECL_ASSEMBLER_NAME (decl) = return_id;
}
else
- error ("return identifier `%s' already in place",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ cp_error ("return identifier `%D' already in place", decl);
}
/* Can't let this happen for constructors. */
@@ -11716,7 +12562,12 @@ store_return_init (return_id, init)
/* Let `cp_finish_decl' know that this initializer is ok. */
DECL_INITIAL (decl) = init;
pushdecl (decl);
- cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
+
+ if (minimal_parse_mode)
+ add_tree (build_min_nt (RETURN_INIT, return_id,
+ copy_to_permanent (init)));
+ else
+ cp_finish_decl (decl, init, NULL_TREE, 0, 0);
}
}
@@ -11731,7 +12582,10 @@ store_return_init (return_id, init)
C++: CALL_POPLEVEL is non-zero if an extra call to poplevel
(and expand_end_bindings) must be made to take care of the binding
contour for the base initializers. This is only relevant for
- constructors. */
+ constructors.
+
+ NESTED is nonzero if we were in the middle of compiling another function
+ when we started on this one. */
void
finish_function (lineno, call_poplevel, nested)
@@ -11751,6 +12605,9 @@ finish_function (lineno, call_poplevel, nested)
if (fndecl == NULL_TREE)
return;
+ if (! nested && function_depth > 1)
+ nested = 1;
+
fntype = TREE_TYPE (fndecl);
/* TREE_READONLY (fndecl) = 1;
@@ -11764,382 +12621,391 @@ finish_function (lineno, call_poplevel, nested)
store_parm_decls ();
}
- if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/)
+ if (processing_template_decl)
{
- tree ttype = target_type (fntype);
- tree parmdecl;
-
- if (IS_AGGR_TYPE (ttype))
- /* Let debugger know it should output info for this type. */
- note_debug_info_needed (ttype);
-
- for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
+ if (DECL_CONSTRUCTOR_P (fndecl) && call_poplevel)
{
- ttype = target_type (TREE_TYPE (parmdecl));
+ decls = getdecls ();
+ expand_end_bindings (decls, decls != NULL_TREE, 0);
+ poplevel (decls != NULL_TREE, 0, 0);
+ }
+ }
+ else
+ {
+ if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/)
+ {
+ tree ttype = target_type (fntype);
+ tree parmdecl;
+
if (IS_AGGR_TYPE (ttype))
/* Let debugger know it should output info for this type. */
note_debug_info_needed (ttype);
+
+ for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
+ {
+ ttype = target_type (TREE_TYPE (parmdecl));
+ if (IS_AGGR_TYPE (ttype))
+ /* Let debugger know it should output info for this type. */
+ note_debug_info_needed (ttype);
+ }
}
- }
- /* Clean house because we will need to reorder insns here. */
- do_pending_stack_adjust ();
+ /* Clean house because we will need to reorder insns here. */
+ do_pending_stack_adjust ();
- if (dtor_label)
- {
- tree binfo = TYPE_BINFO (current_class_type);
- tree cond = integer_one_node;
- tree exprstmt, vfields;
- tree in_charge_node = lookup_name (in_charge_identifier, 0);
- tree virtual_size;
- int ok_to_optimize_dtor = 0;
-
- if (current_function_assigns_this)
- cond = build (NE_EXPR, boolean_type_node,
- current_class_decl, integer_zero_node);
- else
+ if (dtor_label)
{
- int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
+ tree binfo = TYPE_BINFO (current_class_type);
+ tree cond = integer_one_node;
+ tree exprstmt;
+ tree in_charge_node = lookup_name (in_charge_identifier, 0);
+ tree virtual_size;
+ int ok_to_optimize_dtor = 0;
+ int empty_dtor = get_last_insn () == last_dtor_insn;
- /* If this destructor is empty, then we don't need to check
- whether `this' is NULL in some cases. */
- if ((flag_this_is_variable & 1) == 0)
- ok_to_optimize_dtor = 1;
- else if (get_last_insn () == get_first_nonparm_insn ())
- ok_to_optimize_dtor
- = (n_baseclasses == 0
- || (n_baseclasses == 1
- && TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0))));
- }
+ if (current_function_assigns_this)
+ cond = build (NE_EXPR, boolean_type_node,
+ current_class_ptr, integer_zero_node);
+ else
+ {
+ int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
+
+ /* If this destructor is empty, then we don't need to check
+ whether `this' is NULL in some cases. */
+ if ((flag_this_is_variable & 1) == 0)
+ ok_to_optimize_dtor = 1;
+ else if (empty_dtor)
+ ok_to_optimize_dtor
+ = (n_baseclasses == 0
+ || (n_baseclasses == 1
+ && TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0))));
+ }
- /* These initializations might go inline. Protect
- the binding level of the parms. */
- pushlevel (0);
- expand_start_bindings (0);
+ /* These initializations might go inline. Protect
+ the binding level of the parms. */
+ pushlevel (0);
+ expand_start_bindings (0);
- if (current_function_assigns_this)
- {
- current_function_assigns_this = 0;
- current_function_just_assigned_this = 0;
- }
+ if (current_function_assigns_this)
+ {
+ current_function_assigns_this = 0;
+ current_function_just_assigned_this = 0;
+ }
- /* Generate the code to call destructor on base class.
- If this destructor belongs to a class with virtual
- functions, then set the virtual function table
- pointer to represent the type of our base class. */
+ /* Generate the code to call destructor on base class.
+ If this destructor belongs to a class with virtual
+ functions, then set the virtual function table
+ pointer to represent the type of our base class. */
- /* This side-effect makes call to `build_delete' generate the
- code we have to have at the end of this destructor. */
- TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
+ /* This side-effect makes call to `build_delete' generate the
+ code we have to have at the end of this destructor. */
+ TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
- /* These are two cases where we cannot delegate deletion. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
- || TYPE_GETS_REG_DELETE (current_class_type))
- exprstmt = build_delete (current_class_type, C_C_D, integer_zero_node,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
- else
- exprstmt = build_delete (current_class_type, C_C_D, in_charge_node,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
-
- /* If we did not assign to this, then `this' is non-zero at
- the end of a destructor. As a special optimization, don't
- emit test if this is an empty destructor. If it does nothing,
- it does nothing. If it calls a base destructor, the base
- destructor will perform the test. */
-
- if (exprstmt != error_mark_node
- && (TREE_CODE (exprstmt) != NOP_EXPR
- || TREE_OPERAND (exprstmt, 0) != integer_zero_node
- || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)))
- {
- expand_label (dtor_label);
- if (cond != integer_one_node)
- expand_start_cond (cond, 0);
- if (exprstmt != void_zero_node)
- /* Don't call `expand_expr_stmt' if we're not going to do
- anything, since -Wall will give a diagnostic. */
- expand_expr_stmt (exprstmt);
-
- /* Run destructor on all virtual baseclasses. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- {
- tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
- expand_start_cond (build (BIT_AND_EXPR, integer_type_node,
- in_charge_node, integer_two_node), 0);
- while (vbases)
+ /* These are two cases where we cannot delegate deletion. */
+ if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
+ || TYPE_GETS_REG_DELETE (current_class_type))
+ exprstmt = build_delete (current_class_type, current_class_ref, integer_zero_node,
+ LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0);
+ else
+ exprstmt = build_delete (current_class_type, current_class_ref, in_charge_node,
+ LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0);
+
+ /* If we did not assign to this, then `this' is non-zero at
+ the end of a destructor. As a special optimization, don't
+ emit test if this is an empty destructor. If it does nothing,
+ it does nothing. If it calls a base destructor, the base
+ destructor will perform the test. */
+
+ if (exprstmt != error_mark_node
+ && (TREE_CODE (exprstmt) != NOP_EXPR
+ || TREE_OPERAND (exprstmt, 0) != integer_zero_node
+ || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)))
+ {
+ expand_label (dtor_label);
+ if (cond != integer_one_node)
+ expand_start_cond (cond, 0);
+ if (exprstmt != void_zero_node)
+ /* Don't call `expand_expr_stmt' if we're not going to do
+ anything, since -Wall will give a diagnostic. */
+ expand_expr_stmt (exprstmt);
+
+ /* Run destructor on all virtual baseclasses. */
+ if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
{
- if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
+ tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
+ expand_start_cond (build (BIT_AND_EXPR, integer_type_node,
+ in_charge_node, integer_two_node), 0);
+ while (vbases)
{
- tree ptr = convert_pointer_to_vbase (BINFO_TYPE (vbases), current_class_decl);
- expand_expr_stmt (build_delete (build_pointer_type (BINFO_TYPE (vbases)),
- ptr, integer_zero_node,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0));
+ if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
+ {
+ tree vb = get_vbase
+ (BINFO_TYPE (vbases),
+ TYPE_BINFO (current_class_type));
+ expand_expr_stmt
+ (build_scoped_method_call
+ (current_class_ref, vb, dtor_identifier,
+ build_expr_list (NULL_TREE, integer_zero_node)));
+ }
+ vbases = TREE_CHAIN (vbases);
}
- vbases = TREE_CHAIN (vbases);
+ expand_end_cond ();
}
- expand_end_cond ();
+
+ do_pending_stack_adjust ();
+ if (cond != integer_one_node)
+ expand_end_cond ();
}
- do_pending_stack_adjust ();
- if (cond != integer_one_node)
- expand_end_cond ();
- }
+ TYPE_HAS_DESTRUCTOR (current_class_type) = 1;
- TYPE_HAS_DESTRUCTOR (current_class_type) = 1;
-
- virtual_size = c_sizeof (current_class_type);
-
- /* At the end, call delete if that's what's requested. */
- if (TYPE_GETS_REG_DELETE (current_class_type))
- /* This NOP_EXPR means we are in a static call context. */
- exprstmt =
- build_method_call
- (build_indirect_ref
- (build1 (NOP_EXPR, build_pointer_type (current_class_type),
- error_mark_node),
- NULL_PTR),
- ansi_opname[(int) DELETE_EXPR],
- tree_cons (NULL_TREE, current_class_decl,
- build_tree_list (NULL_TREE, virtual_size)),
- NULL_TREE, LOOKUP_NORMAL);
- else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0,
- virtual_size);
- else
- exprstmt = NULL_TREE;
+ virtual_size = c_sizeof (current_class_type);
- if (exprstmt)
- {
- cond = build (BIT_AND_EXPR, integer_type_node,
- in_charge_node, integer_one_node);
- expand_start_cond (cond, 0);
- expand_expr_stmt (exprstmt);
- expand_end_cond ();
- }
+ /* At the end, call delete if that's what's requested. */
- /* End of destructor. */
- expand_end_bindings (NULL_TREE, getdecls() != NULL_TREE, 0);
- poplevel (2, 0, 0); /* XXX change to 1 */
+ /* FDIS sez: At the point of definition of a virtual destructor
+ (including an implicit definition), non-placement operator
+ delete shall be looked up in the scope of the destructor's
+ class and if found shall be accessible and unambiguous.
- /* Back to the top of destructor. */
- /* Dont execute destructor code if `this' is NULL. */
+ This is somewhat unclear, but I take it to mean that if the
+ class only defines placement deletes we don't do anything here.
+ So we pass LOOKUP_SPECULATIVELY; delete_sanity will complain
+ for us if they ever try to delete one of these. */
- start_sequence ();
+ if (TYPE_GETS_REG_DELETE (current_class_type)
+ || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+ exprstmt = build_op_delete_call
+ (DELETE_EXPR, current_class_ptr, virtual_size,
+ LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
+ else
+ exprstmt = NULL_TREE;
- /* Make all virtual function table pointers in non-virtual base
- classes point to CURRENT_CLASS_TYPE's virtual function
- tables. */
- expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_decl);
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- expand_indirect_vtbls_init (binfo, C_C_D, current_class_decl, 0);
- if (! ok_to_optimize_dtor)
- {
- cond = build_binary_op (NE_EXPR,
- current_class_decl, integer_zero_node, 1);
- expand_start_cond (cond, 0);
- }
+ if (exprstmt)
+ {
+ cond = build (BIT_AND_EXPR, integer_type_node,
+ in_charge_node, integer_one_node);
+ expand_start_cond (cond, 0);
+ expand_expr_stmt (exprstmt);
+ expand_end_cond ();
+ }
- insns = get_insns ();
- end_sequence ();
+ /* End of destructor. */
+ expand_end_bindings (NULL_TREE, getdecls () != NULL_TREE, 0);
+ poplevel (2, 0, 0); /* XXX change to 1 */
+
+ /* Back to the top of destructor. */
+ /* Don't execute destructor code if `this' is NULL. */
+
+ start_sequence ();
+
+ /* If the dtor is empty, and we know there is not possible way we
+ could use any vtable entries, before they are possibly set by
+ a base class dtor, we don't have to setup the vtables, as we
+ know that any base class dtoring will set up any vtables it
+ needs. We avoid MI, because one base class dtor can do a
+ virtual dispatch to an overridden function that would need to
+ have a non-related vtable set up, we cannot avoid setting up
+ vtables in that case. We could change this to see if there is
+ just one vtable. */
+ if (! empty_dtor || TYPE_USES_COMPLEX_INHERITANCE (current_class_type))
+ {
+ /* Make all virtual function table pointers in non-virtual base
+ classes point to CURRENT_CLASS_TYPE's virtual function
+ tables. */
+ expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_ptr);
- last_parm_insn = get_first_nonparm_insn ();
- if (last_parm_insn == NULL_RTX)
- last_parm_insn = get_last_insn ();
- else
- last_parm_insn = previous_insn (last_parm_insn);
+ if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+ expand_indirect_vtbls_init (binfo, current_class_ref, current_class_ptr);
+ }
+
+ if (! ok_to_optimize_dtor)
+ {
+ cond = build_binary_op (NE_EXPR,
+ current_class_ptr, integer_zero_node, 1);
+ expand_start_cond (cond, 0);
+ }
- emit_insns_after (insns, last_parm_insn);
+ insns = get_insns ();
+ end_sequence ();
- if (! ok_to_optimize_dtor)
- expand_end_cond ();
- }
- else if (current_function_assigns_this)
- {
- /* Does not need to call emit_base_init, because
- that is done (if needed) just after assignment to this
- is seen. */
+ last_parm_insn = get_first_nonparm_insn ();
+ if (last_parm_insn == NULL_RTX)
+ last_parm_insn = get_last_insn ();
+ else
+ last_parm_insn = previous_insn (last_parm_insn);
- if (DECL_CONSTRUCTOR_P (current_function_decl))
- {
- end_protect_partials ();
- expand_label (ctor_label);
- ctor_label = NULL_TREE;
+ emit_insns_after (insns, last_parm_insn);
- if (call_poplevel)
- {
- decls = getdecls ();
- expand_end_bindings (decls, decls != NULL_TREE, 0);
- poplevel (decls != NULL_TREE, 0, 0);
- }
- c_expand_return (current_class_decl);
+ if (! ok_to_optimize_dtor)
+ expand_end_cond ();
}
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (
- DECL_RESULT (current_function_decl))) != void_type_node
- && return_label != NULL_RTX)
- no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+ else if (current_function_assigns_this)
+ {
+ /* Does not need to call emit_base_init, because
+ that is done (if needed) just after assignment to this
+ is seen. */
- current_function_assigns_this = 0;
- current_function_just_assigned_this = 0;
- base_init_expr = NULL_TREE;
- }
- else if (DECL_CONSTRUCTOR_P (fndecl))
- {
- tree allocated_this;
- tree cond, thenclause;
- /* Allow constructor for a type to get a new instance of the object
- using `build_new'. */
- tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type);
- CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE;
+ if (DECL_CONSTRUCTOR_P (current_function_decl))
+ {
+ end_protect_partials ();
+ expand_label (ctor_label);
+ ctor_label = NULL_TREE;
- DECL_RETURNS_FIRST_ARG (fndecl) = 1;
+ if (call_poplevel)
+ {
+ decls = getdecls ();
+ expand_end_bindings (decls, decls != NULL_TREE, 0);
+ poplevel (decls != NULL_TREE, 0, 0);
+ }
+ /* c_expand_return knows to return 'this' from a constructor. */
+ c_expand_return (NULL_TREE);
+ }
+ else if (TREE_CODE (TREE_TYPE (DECL_RESULT (current_function_decl))) != VOID_TYPE
+ && return_label != NULL_RTX)
+ no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- if (flag_this_is_variable > 0)
- {
- cond = build_binary_op (EQ_EXPR,
- current_class_decl, integer_zero_node, 1);
- thenclause = build_modify_expr (current_class_decl, NOP_EXPR,
- build_new (NULL_TREE, current_class_type, void_type_node, 0));
+ current_function_assigns_this = 0;
+ current_function_just_assigned_this = 0;
+ base_init_expr = NULL_TREE;
}
+ else if (DECL_CONSTRUCTOR_P (fndecl))
+ {
+ tree cond = NULL_TREE, thenclause = NULL_TREE;
+ /* Allow constructor for a type to get a new instance of the object
+ using `build_new'. */
+ tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type);
+ CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE;
- CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
+ DECL_RETURNS_FIRST_ARG (fndecl) = 1;
- start_sequence ();
+ if (flag_this_is_variable > 0)
+ {
+ cond = build_binary_op (EQ_EXPR,
+ current_class_ptr, integer_zero_node, 1);
+ thenclause = build_modify_expr (current_class_ptr, NOP_EXPR,
+ build_new (NULL_TREE, current_class_type, void_type_node, 0));
+ }
- if (flag_this_is_variable > 0)
- {
- expand_start_cond (cond, 0);
- expand_expr_stmt (thenclause);
- expand_end_cond ();
- }
+ CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
-#if 0
- if (DECL_NAME (fndecl) == NULL_TREE
- && TREE_CHAIN (DECL_ARGUMENTS (fndecl)) != NULL_TREE)
- build_default_constructor (fndecl);
-#endif
+ start_sequence ();
- /* Emit insns from `emit_base_init' which sets up virtual
- function table pointer(s). */
- if (base_init_expr)
- {
- expand_expr_stmt (base_init_expr);
- base_init_expr = NULL_TREE;
- }
+ if (flag_this_is_variable > 0)
+ {
+ expand_start_cond (cond, 0);
+ expand_expr_stmt (thenclause);
+ expand_end_cond ();
+ }
- insns = get_insns ();
- end_sequence ();
+ /* Emit insns from `emit_base_init' which sets up virtual
+ function table pointer(s). */
+ if (base_init_expr)
+ {
+ expand_expr_stmt (base_init_expr);
+ base_init_expr = NULL_TREE;
+ }
- /* 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.
+ insns = get_insns ();
+ end_sequence ();
- If optimization is enabled, last_parm_insn may move, so
- we don't hold on to it (across emit_base_init). */
- last_parm_insn = get_first_nonparm_insn ();
- if (last_parm_insn == NULL_RTX)
- last_parm_insn = get_last_insn ();
- else
- last_parm_insn = previous_insn (last_parm_insn);
+ /* This is where the body of the constructor begins. */
- emit_insns_after (insns, last_parm_insn);
+ emit_insns_after (insns, last_parm_cleanup_insn);
- end_protect_partials ();
+ end_protect_partials ();
- /* This is where the body of the constructor ends. */
- expand_label (ctor_label);
- ctor_label = NULL_TREE;
+ /* This is where the body of the constructor ends. */
+ expand_label (ctor_label);
+ ctor_label = NULL_TREE;
- if (call_poplevel)
- {
- decls = getdecls ();
- expand_end_bindings (decls, decls != NULL_TREE, 0);
- poplevel (decls != NULL_TREE, 1, 0);
- }
+ if (call_poplevel)
+ {
+ decls = getdecls ();
+ expand_end_bindings (decls, decls != NULL_TREE, 0);
+ poplevel (decls != NULL_TREE, 1, 0);
+ }
- c_expand_return (current_class_decl);
+ /* c_expand_return knows to return 'this' from a constructor. */
+ c_expand_return (NULL_TREE);
- current_function_assigns_this = 0;
- current_function_just_assigned_this = 0;
- }
- else if (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
- && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")
- && DECL_CONTEXT (fndecl) == NULL_TREE)
- {
- /* Make it so that `main' always returns 0 by default. */
+ current_function_assigns_this = 0;
+ current_function_just_assigned_this = 0;
+ }
+ else if (DECL_MAIN_P (fndecl))
+ {
+ /* Make it so that `main' always returns 0 by default. */
#ifdef VMS
- c_expand_return (integer_one_node);
+ c_expand_return (integer_one_node);
#else
- c_expand_return (integer_zero_node);
+ c_expand_return (integer_zero_node);
#endif
- }
- else if (return_label != NULL_RTX
- && current_function_return_value == NULL_TREE
- && ! DECL_NAME (DECL_RESULT (current_function_decl)))
- no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- if (flag_gc)
- expand_gc_prologue_and_epilogue ();
+ }
+ else if (return_label != NULL_RTX
+ && current_function_return_value == NULL_TREE
+ && ! DECL_NAME (DECL_RESULT (current_function_decl)))
+ no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- /* If this function is supposed to return a value, ensure that
- we do not fall into the cleanups by mistake. The end of our
- function will look like this:
+ if (flag_exceptions)
+ expand_exception_blocks ();
- user code (may have return stmt somewhere)
- goto no_return_label
- cleanup_label:
- cleanups
- goto return_label
- no_return_label:
- NOTE_INSN_FUNCTION_END
- return_label:
- things for return
+ /* If this function is supposed to return a value, ensure that
+ we do not fall into the cleanups by mistake. The end of our
+ function will look like this:
+
+ user code (may have return stmt somewhere)
+ goto no_return_label
+ cleanup_label:
+ cleanups
+ goto return_label
+ no_return_label:
+ NOTE_INSN_FUNCTION_END
+ return_label:
+ things for return
+
+ If the user omits a return stmt in the USER CODE section, we
+ will have a control path which reaches NOTE_INSN_FUNCTION_END.
+ Otherwise, we won't. */
+ if (no_return_label)
+ {
+ DECL_CONTEXT (no_return_label) = fndecl;
+ DECL_INITIAL (no_return_label) = error_mark_node;
+ DECL_SOURCE_FILE (no_return_label) = input_filename;
+ DECL_SOURCE_LINE (no_return_label) = lineno;
+ expand_goto (no_return_label);
+ }
- If the user omits a return stmt in the USER CODE section, we
- will have a control path which reaches NOTE_INSN_FUNCTION_END.
- Otherwise, we won't. */
- if (no_return_label)
- {
- DECL_CONTEXT (no_return_label) = fndecl;
- DECL_INITIAL (no_return_label) = error_mark_node;
- DECL_SOURCE_FILE (no_return_label) = input_filename;
- DECL_SOURCE_LINE (no_return_label) = lineno;
- expand_goto (no_return_label);
- }
+ if (cleanup_label)
+ {
+ /* Remove the binding contour which is used
+ to catch cleanup-generated temporaries. */
+ expand_end_bindings (0, 0, 0);
+ poplevel (0, 0, 0);
- if (cleanup_label)
- {
- /* remove the binding contour which is used
- to catch cleanup-generated temporaries. */
- expand_end_bindings (0, 0, 0);
- poplevel (0, 0, 0);
- }
+ /* Emit label at beginning of cleanup code for parameters. */
+ emit_label (cleanup_label);
+ }
- if (cleanup_label)
- /* Emit label at beginning of cleanup code for parameters. */
- emit_label (cleanup_label);
+ /* Get return value into register if that's where it's supposed to be. */
+ if (original_result_rtx)
+ fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx);
- /* Get return value into register if that's where it's supposed to be. */
- if (original_result_rtx)
- fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx);
+ /* Finish building code that will trigger warnings if users forget
+ to make their functions return values. */
+ if (no_return_label || cleanup_label)
+ emit_jump (return_label);
+ if (no_return_label)
+ {
+ /* We don't need to call `expand_*_return' here because we
+ don't need any cleanups here--this path of code is only
+ for error checking purposes. */
+ expand_label (no_return_label);
+ }
- /* Finish building code that will trigger warnings if users forget
- to make their functions return values. */
- if (no_return_label || cleanup_label)
- emit_jump (return_label);
- if (no_return_label)
- {
- /* We don't need to call `expand_*_return' here because we
- don't need any cleanups here--this path of code is only
- for error checking purposes. */
- expand_label (no_return_label);
+ /* Generate rtl for function exit. */
+ expand_function_end (input_filename, lineno, 1);
}
- /* Generate rtl for function exit. */
- expand_function_end (input_filename, lineno, 1);
-
- if (flag_handle_exceptions)
- expand_exception_blocks ();
-
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
this function's blocks. */
@@ -12147,7 +13013,7 @@ finish_function (lineno, call_poplevel, nested)
my_friendly_abort (122);
poplevel (1, 0, 1);
- /* reset scope for C++: if we were in the scope of a class,
+ /* Reset scope for C++: if we were in the scope of a class,
then when we finish this function, we are not longer so.
This cannot be done until we know for sure that no more
class members will ever be referenced in this function
@@ -12161,79 +13027,115 @@ finish_function (lineno, call_poplevel, nested)
pop_memoized_context (1);
/* Must mark the RESULT_DECL as being in this function. */
- DECL_CONTEXT (DECL_RESULT (fndecl)) = DECL_INITIAL (fndecl);
-
- /* Obey `register' declarations if `setjmp' is called in this fn. */
- if (flag_traditional && current_function_calls_setjmp)
- setjmp_protect (DECL_INITIAL (fndecl));
+ DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
/* Set the BLOCK_SUPERCONTEXT of the outermost function scope to point
to the FUNCTION_DECL node itself. */
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
- /* So we can tell if jump_optimize sets it to 1. */
- can_reach_end = 0;
+ if (! processing_template_decl)
+ {
+ int saved_flag_keep_inline_functions =
+ flag_keep_inline_functions;
- /* Run the optimizers and output the assembler code for this function. */
- rest_of_compilation (fndecl);
+ /* So we can tell if jump_optimize sets it to 1. */
+ can_reach_end = 0;
- if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
- {
- /* Set DECL_EXTERNAL so that assemble_external will be called as
- necessary. We'll clear it again in finish_file. */
- if (! DECL_EXTERNAL (fndecl))
- DECL_NOT_REALLY_EXTERN (fndecl) = 1;
- DECL_EXTERNAL (fndecl) = 1;
- mark_inline_for_output (fndecl);
- }
+ if (DECL_CONTEXT (fndecl) != NULL_TREE
+ && hack_decl_function_context (fndecl))
+ /* Trick rest_of_compilation into not deferring output of this
+ function, even if it is inline, since the rtl_obstack for
+ this function is the function_obstack of the enclosing
+ function and will be deallocated when the enclosing
+ function is gone. See save_tree_status. */
+ flag_keep_inline_functions = 1;
+
+ /* Run the optimizers and output the assembler code for this
+ function. */
- if (ctype && TREE_ASM_WRITTEN (fndecl))
- note_debug_info_needed (ctype);
+ if (DECL_ARTIFICIAL (fndecl))
+ {
+ /* Do we really *want* to inline this synthesized method? */
- current_function_returns_null |= can_reach_end;
+ int save_fif = flag_inline_functions;
+ flag_inline_functions = 1;
- /* Since we don't normally go through c_expand_return for constructors,
- this normally gets the wrong value.
- Also, named return values have their return codes emitted after
- NOTE_INSN_FUNCTION_END, confusing jump.c. */
- if (DECL_CONSTRUCTOR_P (fndecl)
- || DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE)
- current_function_returns_null = 0;
+ /* Turn off DECL_INLINE for the moment so function_cannot_inline_p
+ will check our size. */
+ DECL_INLINE (fndecl) = 0;
- if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
- cp_warning ("`noreturn' function `%D' does return", fndecl);
- else if ((warn_return_type || pedantic)
- && current_function_returns_null
- && TYPE_MAIN_VARIANT (TREE_TYPE (fntype)) != void_type_node)
- {
- /* If this function returns non-void and control can drop through,
- complain. */
- cp_pedwarn ("control reaches end of non-void function `%D'", fndecl);
+ rest_of_compilation (fndecl);
+ flag_inline_functions = save_fif;
+ }
+ else
+ rest_of_compilation (fndecl);
+
+ flag_keep_inline_functions = saved_flag_keep_inline_functions;
+
+ if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
+ {
+ /* Set DECL_EXTERNAL so that assemble_external will be called as
+ necessary. We'll clear it again in finish_file. */
+ if (! DECL_EXTERNAL (fndecl))
+ DECL_NOT_REALLY_EXTERN (fndecl) = 1;
+ DECL_EXTERNAL (fndecl) = 1;
+ mark_inline_for_output (fndecl);
+ }
+
+ if (ctype && TREE_ASM_WRITTEN (fndecl))
+ note_debug_info_needed (ctype);
+
+ current_function_returns_null |= can_reach_end;
+
+ /* Since we don't normally go through c_expand_return for constructors,
+ this normally gets the wrong value.
+ Also, named return values have their return codes emitted after
+ NOTE_INSN_FUNCTION_END, confusing jump.c. */
+ if (DECL_CONSTRUCTOR_P (fndecl)
+ || DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE)
+ current_function_returns_null = 0;
+
+ if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
+ cp_warning ("`noreturn' function `%D' does return", fndecl);
+ else if ((warn_return_type || pedantic)
+ && current_function_returns_null
+ && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE)
+ {
+ /* If this function returns non-void and control can drop through,
+ complain. */
+ cp_warning ("control reaches end of non-void function `%D'", fndecl);
+ }
+ /* With just -W, complain only if function returns both with
+ and without a value. */
+ else if (extra_warnings
+ && current_function_returns_value && current_function_returns_null)
+ warning ("this function may return with or without a value");
}
- /* With just -W, complain only if function returns both with
- and without a value. */
- else if (extra_warnings
- && current_function_returns_value && current_function_returns_null)
- warning ("this function may return with or without a value");
+
+ --function_depth;
/* Free all the tree nodes making up this function. */
/* Switch back to allocating nodes permanently
until we start another function. */
+ if (processing_template_decl)
+ {
+ --minimal_parse_mode;
+ DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
+ }
+
if (! nested)
permanent_allocation (1);
- if (flag_cadillac)
- cadillac_finish_function (fndecl);
-
if (DECL_SAVED_INSNS (fndecl) == NULL_RTX)
{
+ tree t;
+
/* Stop pointing to the local nodes about to be freed. */
/* But DECL_INITIAL must remain nonzero so we know this
was an actual function definition. */
DECL_INITIAL (fndecl) = error_mark_node;
- if (! DECL_CONSTRUCTOR_P (fndecl)
- || !TYPE_USES_VIRTUAL_BASECLASSES (TYPE_METHOD_BASETYPE (fntype)))
- DECL_ARGUMENTS (fndecl) = NULL_TREE;
+ for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
+ DECL_RTL (t) = DECL_INCOMING_RTL (t) = NULL_RTX;
}
if (DECL_STATIC_CONSTRUCTOR (fndecl))
@@ -12249,8 +13151,9 @@ finish_function (lineno, call_poplevel, nested)
current_function_decl = NULL_TREE;
}
- named_label_uses = NULL_TREE;
- current_class_decl = NULL_TREE;
+ named_label_uses = NULL;
+ current_class_ptr = NULL_TREE;
+ current_class_ref = NULL_TREE;
}
/* Create the FUNCTION_DECL for a function definition.
@@ -12275,11 +13178,12 @@ finish_function (lineno, call_poplevel, nested)
DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING
CHANGES TO CODE IN `grokfield'. */
+
tree
-start_method (declspecs, declarator, raises)
- tree declarator, declspecs, raises;
+start_method (declspecs, declarator)
+ tree declarator, declspecs;
{
- tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, raises,
+ tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
NULL_TREE);
/* Something too ugly to handle. */
@@ -12287,7 +13191,7 @@ start_method (declspecs, declarator, raises)
return NULL_TREE;
/* Pass friends other than inline friend functions back. */
- if (TYPE_MAIN_VARIANT (fndecl) == void_type_node)
+ if (fndecl == void_type_node)
return fndecl;
if (TREE_CODE (fndecl) != FUNCTION_DECL)
@@ -12295,17 +13199,14 @@ start_method (declspecs, declarator, raises)
return NULL_TREE;
if (IS_SIGNATURE (current_class_type))
- {
- IS_DEFAULT_IMPLEMENTATION (fndecl) = 1;
- /* In case we need this info later. */
- HAS_DEFAULT_IMPLEMENTATION (current_class_type) = 1;
- }
+ IS_DEFAULT_IMPLEMENTATION (fndecl) = 1;
if (DECL_IN_AGGR_P (fndecl))
{
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type)
{
- if (DECL_CONTEXT (fndecl))
+ if (DECL_CONTEXT (fndecl)
+ && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
cp_error ("`%D' is already defined in class %s", fndecl,
TYPE_NAME_STRING (DECL_CONTEXT (fndecl)));
}
@@ -12317,11 +13218,8 @@ start_method (declspecs, declarator, raises)
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
- if (processing_template_defn)
- {
- SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
- repo_template_used (fndecl);
- }
+ if (processing_template_decl)
+ fndecl = push_template_decl (fndecl);
/* We read in the parameters on the maybepermanent_obstack,
but we won't be getting back to them until after we
@@ -12331,14 +13229,6 @@ start_method (declspecs, declarator, raises)
if (! DECL_FRIEND_P (fndecl))
{
- if (DECL_CHAIN (fndecl) != NULL_TREE)
- {
- /* Need a fresh node here so that we don't get circularity
- when we link these together. If FNDECL was a friend, then
- `pushdecl' does the right thing, which is nothing wrt its
- current value of DECL_CHAIN. */
- fndecl = copy_node (fndecl);
- }
if (TREE_CHAIN (fndecl))
{
fndecl = copy_node (fndecl);
@@ -12385,7 +13275,7 @@ finish_method (decl)
register tree link;
- if (TYPE_MAIN_VARIANT (decl) == void_type_node)
+ if (decl == void_type_node)
return decl;
old_initial = DECL_INITIAL (fndecl);
@@ -12418,13 +13308,12 @@ finish_method (decl)
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
for (link = current_binding_level->type_shadowed;
link; link = TREE_CHAIN (link))
- IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain,
current_binding_level->parm_flag,
- current_binding_level->keep,
- current_binding_level->tag_transparent);
+ current_binding_level->keep);
poplevel (0, 0, 0);
@@ -12462,7 +13351,7 @@ hack_incomplete_structures (type)
for (list = &current_binding_level->incomplete; *list; )
{
tree decl = TREE_VALUE (*list);
- if (decl && TREE_TYPE (decl) == type
+ if ((decl && TREE_TYPE (decl) == type)
|| (TREE_TYPE (decl)
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
&& TREE_TYPE (TREE_TYPE (decl)) == type))
@@ -12479,7 +13368,7 @@ hack_incomplete_structures (type)
expand_decl (decl);
cleanup = maybe_build_cleanup (decl);
expand_decl_init (decl);
- if (! cp_expand_decl_cleanup (decl, cleanup))
+ if (! expand_decl_cleanup (decl, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
}
@@ -12490,32 +13379,21 @@ hack_incomplete_structures (type)
}
}
-/* Nonzero if presently building a cleanup. Needed because
- SAVE_EXPRs are not the right things to use inside of cleanups.
- They are only ever evaluated once, where the cleanup
- might be evaluated several times. In this case, a later evaluation
- of the cleanup might fill in the SAVE_EXPR_RTL, and it will
- not be valid for an earlier cleanup. */
-
-int building_cleanup;
-
/* If DECL is of a type which needs a cleanup, build that cleanup here.
- We don't build cleanups if just going for syntax checking, since
- fixup_cleanups does not know how to not handle them.
+ See build_delete for information about AUTO_DELETE.
Don't build these on the momentary obstack; they must live
the life of the binding contour. */
-tree
-maybe_build_cleanup (decl)
- tree decl;
+
+static tree
+maybe_build_cleanup_1 (decl, auto_delete)
+ tree decl, auto_delete;
{
tree type = TREE_TYPE (decl);
if (TYPE_NEEDS_DESTRUCTOR (type))
{
int temp = 0, flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
tree rval;
- int old_building_cleanup = building_cleanup;
- building_cleanup = 1;
if (TREE_CODE (decl) != PARM_DECL)
temp = suspend_momentary ();
@@ -12533,22 +13411,40 @@ maybe_build_cleanup (decl)
|| flag_expensive_optimizations)
flags |= LOOKUP_NONVIRTUAL;
- rval = build_delete (TREE_TYPE (rval), rval, integer_two_node, flags, 0);
+ rval = build_delete (TREE_TYPE (rval), rval, auto_delete, flags, 0);
if (TYPE_USES_VIRTUAL_BASECLASSES (type)
&& ! TYPE_HAS_DESTRUCTOR (type))
- rval = build_compound_expr (tree_cons (NULL_TREE, rval,
- build_tree_list (NULL_TREE, build_vbase_delete (type, decl))));
+ rval = build_compound_expr (expr_tree_cons (NULL_TREE, rval,
+ build_expr_list (NULL_TREE, build_vbase_delete (type, decl))));
if (TREE_CODE (decl) != PARM_DECL)
resume_momentary (temp);
- building_cleanup = old_building_cleanup;
-
return rval;
}
return 0;
}
+
+/* If DECL is of a type which needs a cleanup, build that cleanup
+ here. The cleanup does free the storage with a call to delete. */
+
+tree
+maybe_build_cleanup_and_delete (decl)
+ tree decl;
+{
+ return maybe_build_cleanup_1 (decl, integer_three_node);
+}
+
+/* If DECL is of a type which needs a cleanup, build that cleanup
+ here. The cleanup does not free the storage with a call a delete. */
+
+tree
+maybe_build_cleanup (decl)
+ tree decl;
+{
+ return maybe_build_cleanup_1 (decl, integer_two_node);
+}
/* Expand a C++ expression at the statement level.
This is needed to ferret out nodes which have UNKNOWN_TYPE.
@@ -12556,13 +13452,21 @@ maybe_build_cleanup (decl)
expressions are combined with other, type-providing, expressions,
leaving only orphan expressions, such as:
- &class::bar; / / takes its address, but does nothing with it.
+ &class::bar; / / takes its address, but does nothing with it. */
- */
void
cplus_expand_expr_stmt (exp)
tree exp;
{
+ if (processing_template_decl)
+ {
+ add_tree (build_min_nt (EXPR_STMT, exp));
+ return;
+ }
+
+ /* Arrange for all temps to disappear. */
+ expand_start_target_temps ();
+
if (TREE_TYPE (exp) == unknown_type_node)
{
if (TREE_CODE (exp) == ADDR_EXPR || TREE_CODE (exp) == TREE_LIST)
@@ -12572,8 +13476,6 @@ cplus_expand_expr_stmt (exp)
}
else
{
- int remove_implicit_immediately = 0;
-
if (TREE_CODE (exp) == FUNCTION_DECL)
{
cp_warning ("reference, not call, to function `%D'", exp);
@@ -12585,12 +13487,22 @@ cplus_expand_expr_stmt (exp)
libg++ to miscompile, and tString to core dump. */
exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
#endif
- expand_expr_stmt (break_out_cleanups (exp));
+
+ /* Strip unused implicit INDIRECT_REFs of references. */
+ if (TREE_CODE (exp) == INDIRECT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
+ exp = TREE_OPERAND (exp, 0);
+
+ /* If we don't do this, we end up down inside expand_expr
+ trying to do TYPE_MODE on the ERROR_MARK, and really
+ go outside the bounds of the type. */
+ if (exp != error_mark_node)
+ expand_expr_stmt (break_out_cleanups (exp));
}
/* Clean up any pending cleanups. This happens when a function call
returns a cleanup-needing value that nobody uses. */
- expand_cleanups_to (NULL_TREE);
+ expand_end_target_temps ();
}
/* When a stmt has been parsed, this function is called.
@@ -12618,9 +13530,6 @@ finish_stmt ()
check_base_init (current_class_type);
}
current_function_assigns_this = 1;
-
- if (flag_cadillac)
- cadillac_finish_stmt ();
}
/* Change a static member function definition into a FUNCTION_TYPE, instead
@@ -12679,18 +13588,20 @@ struct cp_function
tree shadowed_labels;
tree ctor_label;
tree dtor_label;
- tree protect_list;
+ rtx last_dtor_insn;
+ rtx last_parm_cleanup_insn;
tree base_init_list;
tree member_init_list;
tree base_init_expr;
- tree class_decl;
- tree C_C_D;
+ tree current_class_ptr;
+ tree current_class_ref;
rtx result_rtx;
struct cp_function *next;
struct binding_level *binding_level;
+ int static_labelno;
};
-struct cp_function *cp_function_chain;
+static struct cp_function *cp_function_chain;
extern int temp_name_counter;
@@ -12717,17 +13628,19 @@ push_cp_function_context (context)
p->binding_level = current_binding_level;
p->ctor_label = ctor_label;
p->dtor_label = dtor_label;
+ p->last_dtor_insn = last_dtor_insn;
+ p->last_parm_cleanup_insn = last_parm_cleanup_insn;
p->assigns_this = current_function_assigns_this;
p->just_assigned_this = current_function_just_assigned_this;
p->parms_stored = current_function_parms_stored;
p->result_rtx = original_result_rtx;
p->base_init_expr = base_init_expr;
- p->protect_list = protect_list;
p->temp_name_counter = temp_name_counter;
p->base_init_list = current_base_init_list;
p->member_init_list = current_member_init_list;
- p->class_decl = current_class_decl;
- p->C_C_D = C_C_D;
+ p->current_class_ptr = current_class_ptr;
+ p->current_class_ref = current_class_ref;
+ p->static_labelno = static_labelno;
}
/* Restore the variables used during compilation of a C++ function. */
@@ -12745,17 +13658,6 @@ pop_cp_function_context (context)
SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)),
TREE_VALUE (link));
-#if 0
- if (DECL_SAVED_INSNS (current_function_decl) == 0)
- {
- /* Stop pointing to the local nodes about to be freed. */
- /* But DECL_INITIAL must remain nonzero so we know this
- was an actual function definition. */
- DECL_INITIAL (current_function_decl) = error_mark_node;
- DECL_ARGUMENTS (current_function_decl) = 0;
- }
-#endif
-
pop_function_context_from (context);
cp_function_chain = p->next;
@@ -12768,7 +13670,8 @@ pop_cp_function_context (context)
current_binding_level = p->binding_level;
ctor_label = p->ctor_label;
dtor_label = p->dtor_label;
- protect_list = p->protect_list;
+ last_dtor_insn = p->last_dtor_insn;
+ last_parm_cleanup_insn = p->last_parm_cleanup_insn;
current_function_assigns_this = p->assigns_this;
current_function_just_assigned_this = p->just_assigned_this;
current_function_parms_stored = p->parms_stored;
@@ -12777,102 +13680,15 @@ pop_cp_function_context (context)
temp_name_counter = p->temp_name_counter;
current_base_init_list = p->base_init_list;
current_member_init_list = p->member_init_list;
- current_class_decl = p->class_decl;
- C_C_D = p->C_C_D;
+ current_class_ptr = p->current_class_ptr;
+ current_class_ref = p->current_class_ref;
+ static_labelno = p->static_labelno;
free (p);
}
-/* FSF LOCAL dje prefix attributes */
-/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
- lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).
-
- The head of the declspec list is stored in DECLSPECS.
- The head of the attribute list is stored in PREFIX_ATTRIBUTES.
-
- Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of
- the list elements. We drop the containing TREE_LIST nodes and link the
- resulting attributes together the way decl_attributes expects them. */
-
-void
-split_specs_attrs (specs_attrs, declspecs, prefix_attributes)
- tree specs_attrs;
- tree *declspecs, *prefix_attributes;
-{
- tree t, s, a, next, specs, attrs;
-
- /* This can happen in c++ (eg: decl: typespec initdecls ';'). */
- if (specs_attrs != NULL_TREE
- && TREE_CODE (specs_attrs) != TREE_LIST)
- {
- *declspecs = specs_attrs;
- *prefix_attributes = NULL_TREE;
- return;
- }
-
- /* Remember to keep the lists in the same order, element-wise. */
-
- specs = s = NULL_TREE;
- attrs = a = NULL_TREE;
- for (t = specs_attrs; t; t = next)
- {
- next = TREE_CHAIN (t);
- /* Declspecs have a non-NULL TREE_VALUE. */
- if (TREE_VALUE (t) != NULL_TREE)
- {
- if (specs == NULL_TREE)
- specs = s = t;
- else
- {
- TREE_CHAIN (s) = t;
- s = t;
- }
- }
- else
- {
- if (attrs == NULL_TREE)
- attrs = a = TREE_PURPOSE (t);
- else
- {
- TREE_CHAIN (a) = TREE_PURPOSE (t);
- a = TREE_PURPOSE (t);
- }
- }
- }
-
- /* Terminate the lists. */
- if (s != NULL_TREE)
- TREE_CHAIN (s) = NULL_TREE;
- if (a != NULL_TREE)
- TREE_CHAIN (a) = NULL_TREE;
-
- /* All done. */
- *declspecs = specs;
- *prefix_attributes = attrs;
-}
-
-/* Strip attributes from SPECS_ATTRS, a list of declspecs and attributes.
- This function is used by the parser when a rule will accept attributes
- in a particular position, but we don't want to support that just yet.
-
- A warning is issued for every ignored attribute. */
-
-tree
-strip_attrs (specs_attrs)
- tree specs_attrs;
+int
+in_function_p ()
{
- tree specs, attrs;
-
- split_specs_attrs (specs_attrs, &specs, &attrs);
-
- while (attrs)
- {
- warning ("`%s' attribute ignored",
- IDENTIFIER_POINTER (TREE_PURPOSE (attrs)));
- attrs = TREE_CHAIN (attrs);
- }
-
- return specs;
+ return function_depth != 0;
}
-/* END FSF LOCAL */
-
diff --git a/contrib/gcc/cp/decl.h b/contrib/gcc/cp/decl.h
index 0824c13..f55dca5 100644
--- a/contrib/gcc/cp/decl.h
+++ b/contrib/gcc/cp/decl.h
@@ -31,7 +31,7 @@ enum decl_context
};
/* We need this in here to get the decl_context definition. */
-extern tree grokdeclarator PROTO((tree, tree, enum decl_context, int, tree, tree));
+extern tree grokdeclarator PROTO((tree, tree, enum decl_context, int, tree));
/* C++: Keep these around to reduce calls to `get_identifier'.
Identifiers for `this' in member functions and the auto-delete
diff --git a/contrib/gcc/cp/decl2.c b/contrib/gcc/cp/decl2.c
index 9b7f88e..c87c607 100644
--- a/contrib/gcc/cp/decl2.c
+++ b/contrib/gcc/cp/decl2.c
@@ -1,5 +1,5 @@
/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA. */
line numbers. For example, the CONST_DECLs for enum values. */
#include "config.h"
-#include <stdio.h>
+#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "flags.h"
@@ -36,11 +36,33 @@ Boston, MA 02111-1307, USA. */
#include "decl.h"
#include "lex.h"
#include "output.h"
+#include "except.h"
+#include "expr.h"
#include "defaults.h"
+#include "toplev.h"
+#include "dwarf2out.h"
+#include "dwarfout.h"
+
+#if USE_CPPLIB
+#include "cpplib.h"
+extern cpp_reader parse_in;
+extern cpp_options parse_options;
+static int cpp_initialized;
+#endif
+
+static tree get_sentry PROTO((tree));
+static void mark_vtable_entries PROTO((tree));
+static void grok_function_init PROTO((tree, tree));
+static int finish_vtable_vardecl PROTO((tree, tree));
+static int prune_vtable_vardecl PROTO((tree, tree));
+static void finish_sigtable_vardecl PROTO((tree, tree));
+static int is_namespace_ancestor PROTO((tree, tree));
+static void add_using_namespace PROTO((tree, tree, int));
+static tree ambiguous_decl PROTO((tree, tree, tree,int));
+static tree build_anon_union_vars PROTO((tree, tree*, int, int));
+static void check_decl_namespace PROTO((void));
-extern tree get_file_function_name ();
-extern tree cleanups_this_call;
-static void grok_function_init ();
+extern int current_class_depth;
/* A list of virtual function tables we must make sure to write out. */
tree pending_vtables;
@@ -51,7 +73,7 @@ tree pending_vtables;
tree pending_statics;
/* A list of functions which were declared inline, but which we
- may need to emit outline anyway. */
+ may need to emit outline anyway. */
static tree saved_inlines;
/* Used to help generate temporary names which are unique within
@@ -67,9 +89,23 @@ static int global_temp_name_counter;
extern int spew_debug;
+/* Nonzero if we're done parsing and into end-of-file activities. */
+
+int at_eof;
+
/* Functions called along with real static constructors and destructors. */
tree static_ctors, static_dtors;
+
+/* The current open namespace, and ::. */
+
+tree current_namespace;
+tree global_namespace;
+
+/* The stack for namespaces of current declarations. */
+
+static tree decl_namespace_list;
+
/* C (and C++) language-specific option variables. */
@@ -99,7 +135,8 @@ int flag_no_builtin;
int flag_no_nonansi_builtin;
-/* Nonzero means do some things the same way PCC does. */
+/* Nonzero means do some things the same way PCC does. Only provided so
+ the compiler will link. */
int flag_traditional;
@@ -122,7 +159,7 @@ int flag_ansi;
int flag_implement_inlines = 1;
/* Nonzero means do emit exported implementations of templates, instead of
- multiple static copies in each file that needs a definition. */
+ multiple static copies in each file that needs a definition. */
int flag_external_templates;
@@ -140,20 +177,32 @@ int flag_implicit_templates = 1;
int warn_implicit = 1;
+/* Nonzero means warn about usage of long long when `-pedantic'. */
+
+int warn_long_long = 1;
+
/* Nonzero means warn when all ctors or dtors are private, and the class
has no friends. */
int warn_ctor_dtor_privacy = 1;
-/* True if we want to implement vtbvales using "thunks".
- The default is off now, but will be on later. */
+/* True if we want to implement vtables using "thunks".
+ The default is off. */
-int flag_vtable_thunks;
+#ifndef DEFAULT_VTABLE_THUNKS
+#define DEFAULT_VTABLE_THUNKS 0
+#endif
+int flag_vtable_thunks = DEFAULT_VTABLE_THUNKS;
/* True if we want to deal with repository information. */
int flag_use_repository;
+/* Nonzero if we want to issue diagnostics that the standard says are not
+ required. */
+
+int flag_optional_diags = 1;
+
/* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous
to be useful, except in thoroughly ANSIfied programs. */
@@ -165,24 +214,10 @@ int warn_write_strings;
int warn_cast_qual;
-/* Nonzero means warn that dbx info for template class methods isn't fully
- supported yet. */
-
-int warn_template_debugging;
-
-/* Warn about traditional constructs whose meanings changed in ANSI C. */
-
-int warn_traditional;
-
/* Nonzero means warn about sizeof(function) or addition/subtraction
of function pointers. */
-int warn_pointer_arith;
-
-/* Nonzero means warn for non-prototype function decls
- or non-prototyped defs without previous prototype. */
-
-int warn_strict_prototypes;
+int warn_pointer_arith = 1;
/* Nonzero means warn for any function def without prototype decl. */
@@ -197,7 +232,11 @@ int warn_redundant_decls;
int warn_missing_braces;
-/* Warn about *printf or *scanf format/argument anomalies. */
+/* Warn about comparison of signed and unsigned values. */
+
+int warn_sign_compare;
+
+/* Warn about *printf or *scanf format/argument anomalies. */
int warn_format;
@@ -219,7 +258,7 @@ int warn_parentheses;
int warn_overloaded_virtual;
/* Non-zero means warn when declaring a class that has a non virtual
- destructor, when it really ought to have a virtual one. */
+ destructor, when it really ought to have a virtual one. */
int warn_nonvdtor;
/* Non-zero means warn when a function is declared extern and later inline. */
@@ -231,8 +270,32 @@ int warn_reorder;
/* Non-zero means warn when synthesis behavior differs from Cfront's. */
int warn_synth;
-/* Nonzero means `$' can be in an identifier.
- See cccp.c for reasons why this breaks some obscure ANSI C programs. */
+/* Non-zero means warn when we convert a pointer to member function
+ into a pointer to (void or function). */
+int warn_pmf2ptr = 1;
+
+/* Nonzero means warn about violation of some Effective C++ style rules. */
+
+int warn_ecpp;
+
+/* Nonzero means warn where overload resolution chooses a promotion from
+ unsigned to signed over a conversion to an unsigned of the same size. */
+
+int warn_sign_promo;
+
+/* Nonzero means warn when an old-style cast is used. */
+
+int warn_old_style_cast;
+
+/* Warn about #pragma directives that are not recognised. */
+
+int warn_unknown_pragmas; /* Tri state variable. */
+
+/* Nonzero means warn about use of multicharacter literals. */
+
+int warn_multichar = 1;
+
+/* Nonzero means `$' can be in an identifier. */
#ifndef DOLLARS_IN_IDENTIFIERS
#define DOLLARS_IN_IDENTIFIERS 1
@@ -284,15 +347,12 @@ int flag_memoize_lookups; int flag_save_memoized_contexts;
int write_virtuals;
-/* Nonzero means we should attempt to elide constructors when possible. */
+/* Nonzero means we should attempt to elide constructors when possible.
+ FIXME: This flag is obsolete, and should be torn out along with the
+ old overloading code. */
int flag_elide_constructors;
-/* Nonzero means recognize and handle exception handling constructs.
- Use ansi syntax and semantics. WORK IN PROGRESS! */
-
-int flag_handle_exceptions;
-
/* Nonzero means recognize and handle signature language constructs. */
int flag_handle_signatures;
@@ -307,17 +367,9 @@ int flag_default_inline = 1;
0 means enums can convert to ints, but not vice-versa. */
int flag_int_enum_equivalence;
-/* Controls whether compiler is operating under LUCID's Cadillac
- system. 1 means yes, 0 means no. */
-int flag_cadillac;
-
-/* Controls whether compiler generates code to build objects
- that can be collected when they become garbage. */
-int flag_gc;
-
/* Controls whether compiler generates 'type descriptor' that give
run-time type information. */
-int flag_rtti;
+int flag_rtti = 1;
/* Nonzero if we wish to output cross-referencing information
for the GNU class browser. */
@@ -336,7 +388,7 @@ extern int flag_gnu_xref;
int flag_assume_nonnull_objects = 1;
/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
- objects. */
+ objects. */
int flag_huge_objects;
@@ -369,6 +421,39 @@ int flag_check_new;
int flag_new_for_scope = 1;
+/* Nonzero if we want to emit defined symbols with common-like linkage as
+ weak symbols where possible, in order to conform to C++ semantics.
+ Otherwise, emit them as local symbols. */
+
+int flag_weak = 1;
+
+/* Nonzero to enable experimental ABI changes. */
+
+int flag_new_abi;
+
+/* Nonzero to not ignore namespace std. */
+
+int flag_honor_std;
+
+/* Maximum template instantiation depth. Must be at least 17 for ANSI
+ compliance. */
+
+int max_tinst_depth = 17;
+
+/* The name-mangling scheme to use. Must be 1 or greater to support
+ template functions with identical types, but different template
+ arguments. */
+int name_mangling_version = 2;
+
+/* Nonzero means that guiding declarations are allowed. */
+int flag_guiding_decls;
+
+/* Nonzero if squashed mangling is to be performed.
+ This uses the B and K codes to reference previously seen class types
+ and class qualifiers. */
+int flag_do_squangling;
+
+
/* Table of language-dependent -f options.
STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE
@@ -384,6 +469,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"short-enums", &flag_short_enums, 1},
{"short-double", &flag_short_double, 1},
{"cond-mismatch", &flag_cond_mismatch, 1},
+ {"squangle", &flag_do_squangling, 1},
{"asm", &flag_no_asm, 0},
{"builtin", &flag_no_builtin, 0},
{"ident", &flag_no_ident, 0},
@@ -394,12 +480,12 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"all-virtual", &flag_all_virtual, 1},
{"memoize-lookups", &flag_memoize_lookups, 1},
{"elide-constructors", &flag_elide_constructors, 1},
- {"handle-exceptions", &flag_handle_exceptions, 1},
+ {"handle-exceptions", &flag_exceptions, 1},
{"handle-signatures", &flag_handle_signatures, 1},
{"default-inline", &flag_default_inline, 1},
{"dollars-in-identifiers", &dollars_in_ident, 1},
{"enum-int-equiv", &flag_int_enum_equivalence, 1},
- {"gc", &flag_gc, 1},
+ {"honor-std", &flag_honor_std, 1},
{"rtti", &flag_rtti, 1},
{"xref", &flag_gnu_xref, 1},
{"nonnull-objects", &flag_assume_nonnull_objects, 1},
@@ -409,26 +495,44 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"huge-objects", &flag_huge_objects, 1},
{"conserve-space", &flag_conserve_space, 1},
{"vtable-thunks", &flag_vtable_thunks, 1},
- {"short-temps", &flag_short_temps, 1},
{"access-control", &flag_access_control, 1},
{"nonansi-builtins", &flag_no_nonansi_builtin, 0},
{"gnu-keywords", &flag_no_gnu_keywords, 0},
{"operator-names", &flag_operator_names, 1},
+ {"optional-diags", &flag_optional_diags, 1},
{"check-new", &flag_check_new, 1},
{"repo", &flag_use_repository, 1},
- {"for-scope", &flag_new_for_scope, 2}
+ {"for-scope", &flag_new_for_scope, 2},
+ {"weak", &flag_weak, 1}
};
/* Decode the string P as a language-specific option.
- Return 1 if it is recognized (and handle it);
- return 0 if not recognized. */
+ Return the number of strings consumed for a valid option.
+ Otherwise return 0. */
int
-lang_decode_option (p)
- char *p;
+lang_decode_option (argc, argv)
+ int argc;
+ char **argv;
+
{
+ int strings_processed;
+ char *p = argv[0];
+#if USE_CPPLIB
+ if (! cpp_initialized)
+ {
+ cpp_reader_init (&parse_in);
+ parse_in.data = &parse_options;
+ cpp_options_init (&parse_options);
+ cpp_initialized = 1;
+ }
+ strings_processed = cpp_handle_option (&parse_in, argc, argv);
+#else
+ strings_processed = 0;
+#endif /* ! USE_CPPLIB */
+
if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
- flag_traditional = 1, dollars_in_ident = 1, flag_writable_strings = 1,
+ flag_writable_strings = 1,
flag_this_is_variable = 1, flag_new_for_scope = 0;
/* The +e options are for cfront compatibility. They come in as
`-+eN', to kludge around gcc.c's argument handling. */
@@ -451,68 +555,107 @@ lang_decode_option (p)
/* Some kind of -f option.
P's value is the option sans `-f'.
Search for it in the table of options. */
- int found = 0, j;
+ int found = 0;
+ size_t j;
p += 2;
/* Try special -f options. */
+ if (!strcmp (p, "handle-exceptions")
+ || !strcmp (p, "no-handle-exceptions"))
+ warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)");
+
if (!strcmp (p, "save-memoized"))
{
flag_memoize_lookups = 1;
flag_save_memoized_contexts = 1;
found = 1;
}
- if (!strcmp (p, "no-save-memoized"))
+ else if (!strcmp (p, "no-save-memoized"))
{
flag_memoize_lookups = 0;
flag_save_memoized_contexts = 0;
found = 1;
}
- else if (! strncmp (p, "cadillac", 8))
+ else if (! strcmp (p, "alt-external-templates"))
{
- flag_cadillac = atoi (p+9);
+ flag_external_templates = 1;
+ flag_alt_external_templates = 1;
found = 1;
}
- else if (! strncmp (p, "no-cadillac", 11))
+ else if (! strcmp (p, "no-alt-external-templates"))
{
- flag_cadillac = 0;
+ flag_alt_external_templates = 0;
found = 1;
}
- else if (! strcmp (p, "gc"))
+ else if (!strcmp (p, "repo"))
{
- flag_gc = 1;
- /* This must come along for the ride. */
- flag_rtti = 1;
+ flag_use_repository = 1;
+ flag_implicit_templates = 0;
found = 1;
}
- else if (! strcmp (p, "no-gc"))
+ else if (!strcmp (p, "guiding-decls"))
{
- flag_gc = 0;
- /* This must come along for the ride. */
- flag_rtti = 0;
+ flag_guiding_decls = 1;
+ name_mangling_version = 0;
found = 1;
}
- else if (! strcmp (p, "alt-external-templates"))
+ else if (!strcmp (p, "no-guiding-decls"))
{
- flag_external_templates = 1;
- flag_alt_external_templates = 1;
+ flag_guiding_decls = 0;
found = 1;
}
- else if (! strcmp (p, "no-alt-external-templates"))
+ else if (!strcmp (p, "ansi-overloading"))
+ found = 1;
+ else if (!strcmp (p, "no-ansi-overloading"))
{
- flag_alt_external_templates = 0;
+ error ("-fno-ansi-overloading is no longer supported");
found = 1;
}
- else if (!strcmp (p, "ansi-overloading"))
+ else if (!strcmp (p, "new-abi"))
{
- warning ("-fansi-overloading is no longer meaningful");
- found = 1;
+ flag_new_abi = 1;
+ flag_do_squangling = 1;
+ flag_honor_std = 1;
+ flag_vtable_thunks = 1;
}
- else if (!strcmp (p, "repo"))
+ else if (!strcmp (p, "no-new-abi"))
{
- flag_use_repository = 1;
- flag_implicit_templates = 0;
- found = 1;
+ flag_new_abi = 0;
+ flag_do_squangling = 0;
+ flag_honor_std = 0;
+ }
+ else if (!strncmp (p, "template-depth-", 15))
+ {
+ char *endp = p + 15;
+ while (*endp)
+ {
+ if (*endp >= '0' && *endp <= '9')
+ endp++;
+ else
+ {
+ error ("Invalid option `%s'", p - 2);
+ goto template_depth_lose;
+ }
+ }
+ max_tinst_depth = atoi (p + 15);
+ template_depth_lose: ;
+ }
+ else if (!strncmp (p, "name-mangling-version-", 22))
+ {
+ char *endp = p + 22;
+ while (*endp)
+ {
+ if (*endp >= '0' && *endp <= '9')
+ endp++;
+ else
+ {
+ error ("Invalid option `%s'", p - 2);
+ goto mangling_version_lose;
+ }
+ }
+ name_mangling_version = atoi (p + 22);
+ mangling_version_lose: ;
}
else for (j = 0;
!found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]);
@@ -546,6 +689,8 @@ lang_decode_option (p)
if (!strcmp (p, "implicit"))
warn_implicit = setting;
+ else if (!strcmp (p, "long-long"))
+ warn_long_long = setting;
else if (!strcmp (p, "return-type"))
warn_return_type = setting;
else if (!strcmp (p, "ctor-dtor-privacy"))
@@ -554,20 +699,18 @@ lang_decode_option (p)
warn_write_strings = setting;
else if (!strcmp (p, "cast-qual"))
warn_cast_qual = setting;
- else if (!strcmp (p, "traditional"))
- warn_traditional = setting;
else if (!strcmp (p, "char-subscripts"))
warn_char_subscripts = setting;
else if (!strcmp (p, "pointer-arith"))
warn_pointer_arith = setting;
- else if (!strcmp (p, "strict-prototypes"))
- warn_strict_prototypes = setting;
else if (!strcmp (p, "missing-prototypes"))
warn_missing_prototypes = setting;
else if (!strcmp (p, "redundant-decls"))
warn_redundant_decls = setting;
else if (!strcmp (p, "missing-braces"))
warn_missing_braces = setting;
+ else if (!strcmp (p, "sign-compare"))
+ warn_sign_compare = setting;
else if (!strcmp (p, "format"))
warn_format = setting;
else if (!strcmp (p, "conversion"))
@@ -582,6 +725,22 @@ lang_decode_option (p)
warn_reorder = setting;
else if (!strcmp (p, "synth"))
warn_synth = setting;
+ else if (!strcmp (p, "pmf-conversions"))
+ warn_pmf2ptr = setting;
+ else if (!strcmp (p, "effc++"))
+ warn_ecpp = setting;
+ else if (!strcmp (p, "sign-promo"))
+ warn_sign_promo = setting;
+ else if (!strcmp (p, "old-style-cast"))
+ warn_old_style_cast = setting;
+ else if (!strcmp (p, "overloaded-virtual"))
+ warn_overloaded_virtual = setting;
+ else if (!strcmp (p, "multichar"))
+ warn_multichar = setting;
+ else if (!strcmp (p, "unknown-pragmas"))
+ /* Set to greater than 1, so that even unknown pragmas in
+ system headers will be warned about. */
+ warn_unknown_pragmas = setting * 2;
else if (!strcmp (p, "comment"))
; /* cpp handles this one. */
else if (!strcmp (p, "comments"))
@@ -592,7 +751,6 @@ lang_decode_option (p)
; /* cpp handles this one. */
else if (!strcmp (p, "all"))
{
- extra_warnings = setting;
warn_return_type = setting;
warn_unused = setting;
warn_implicit = setting;
@@ -601,23 +759,25 @@ lang_decode_option (p)
warn_format = setting;
warn_parentheses = setting;
warn_missing_braces = setting;
+ warn_sign_compare = setting;
warn_extern_inline = setting;
warn_nonvdtor = setting;
+ warn_multichar = setting;
/* We save the value of warn_uninitialized, since if they put
-Wuninitialized on the command line, we need to generate a
warning about not using it without also specifying -O. */
if (warn_uninitialized != 1)
warn_uninitialized = (setting ? 2 : 0);
- warn_template_debugging = setting;
warn_reorder = setting;
+ warn_sign_promo = setting;
+ /* Only warn about unknown pragmas that are not in system
+ headers. */
+ warn_unknown_pragmas = 1;
}
-
- else if (!strcmp (p, "overloaded-virtual"))
- warn_overloaded_virtual = setting;
- else return 0;
+ else return strings_processed;
}
else if (!strcmp (p, "-ansi"))
- dollars_in_ident = 0, flag_no_nonansi_builtin = 1, flag_ansi = 1,
+ flag_no_nonansi_builtin = 1, flag_ansi = 1,
flag_no_gnu_keywords = 1, flag_operator_names = 1;
#ifdef SPEW_DEBUG
/* Undocumented, only ever used when you're invoking cc1plus by hand, since
@@ -627,7 +787,7 @@ lang_decode_option (p)
spew_debug = 1;
#endif
else
- return 0;
+ return strings_processed;
return 1;
}
@@ -635,6 +795,7 @@ lang_decode_option (p)
/* Incorporate `const' and `volatile' qualifiers for member functions.
FUNCTION is a TYPE_DECL or a FUNCTION_DECL.
QUALS is a list of qualifiers. */
+
tree
grok_method_quals (ctype, function, quals)
tree ctype, function, quals;
@@ -682,28 +843,10 @@ grok_method_quals (ctype, function, quals)
return ctype;
}
-#if 0 /* Not used. */
-/* This routine replaces cryptic DECL_NAMEs with readable DECL_NAMEs.
- It leaves DECL_ASSEMBLER_NAMEs with the correct value. */
-/* This does not yet work with user defined conversion operators
- It should. */
-static void
-substitute_nice_name (decl)
- tree decl;
-{
- if (DECL_NAME (decl) && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE)
- {
- char *n = decl_as_string (DECL_NAME (decl), 1);
- if (n[strlen (n) - 1] == ' ')
- n[strlen (n) - 1] = 0;
- DECL_NAME (decl) = get_identifier (n);
- }
-}
-#endif
-
/* Warn when -fexternal-templates is used and #pragma
interface/implementation is not used all the times it should be,
inform the user. */
+
void
warn_if_unknown_interface (decl)
tree decl;
@@ -734,6 +877,7 @@ warn_if_unknown_interface (decl)
}
/* A subroutine of the parser, to handle a component list. */
+
tree
grok_x_components (specs, components)
tree specs, components;
@@ -758,8 +902,7 @@ grok_x_components (specs, components)
{
case VAR_DECL:
/* Static anonymous unions come out as VAR_DECLs. */
- if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_TYPE (t))))
+ if (ANON_UNION_TYPE_P (TREE_TYPE (t)))
return t;
/* We return SPECS here, because in the parser it was ending
@@ -772,31 +915,37 @@ grok_x_components (specs, components)
/* This code may be needed for UNION_TYPEs as
well. */
tcode = record_type_node;
- if (CLASSTYPE_DECLARED_CLASS(t))
+ if (CLASSTYPE_DECLARED_CLASS (t))
tcode = class_type_node;
- else if (IS_SIGNATURE(t))
+ else if (IS_SIGNATURE (t))
tcode = signature_type_node;
-
- t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
- if (TYPE_CONTEXT(t))
- CLASSTYPE_NO_GLOBALIZE(t) = 1;
+
+ if (CLASSTYPE_IS_TEMPLATE (t))
+ /* In this case, the TYPE_IDENTIFIER will be something
+ like S<T>, rather than S, so to get the correct name we
+ look at the template. */
+ x = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
+ else
+ x = TYPE_IDENTIFIER (t);
+
+ t = xref_tag (tcode, x, NULL_TREE, 0);
return NULL_TREE;
break;
case UNION_TYPE:
case ENUMERAL_TYPE:
- if (TREE_CODE(t) == UNION_TYPE)
+ if (TREE_CODE (t) == UNION_TYPE)
tcode = union_type_node;
else
tcode = enum_type_node;
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
- if (TREE_CODE(t) == UNION_TYPE && TYPE_CONTEXT(t))
- CLASSTYPE_NO_GLOBALIZE(t) = 1;
- if (TREE_CODE (t) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ if (ANON_UNION_TYPE_P (t))
{
+ /* See also shadow_tag. */
+
struct pending_inline **p;
+ tree *q;
x = build_lang_field_decl (FIELD_DECL, NULL_TREE, t);
/* Wipe out memory of synthesized methods */
@@ -808,13 +957,24 @@ grok_x_components (specs, components)
TYPE_HAS_ASSIGNMENT (t) = 0;
TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
+ q = &TYPE_METHODS (t);
+ while (*q)
+ {
+ if (DECL_ARTIFICIAL (*q))
+ *q = TREE_CHAIN (*q);
+ else
+ q = &TREE_CHAIN (*q);
+ }
+ if (TYPE_METHODS (t))
+ error ("an anonymous union cannot have function members");
+
p = &pending_inlines;
for (; *p; *p = (*p)->next)
if (DECL_CONTEXT ((*p)->fndecl) != t)
break;
}
else if (TREE_CODE (t) == ENUMERAL_TYPE)
- x = grok_enum_decls (t, NULL_TREE);
+ x = grok_enum_decls (NULL_TREE);
else
x = NULL_TREE;
return x;
@@ -827,13 +987,63 @@ grok_x_components (specs, components)
}
}
else
- {
- t = TREE_TYPE (components);
- if (TREE_CODE (t) == ENUMERAL_TYPE && TREE_NONLOCAL_FLAG (t))
- return grok_enum_decls (t, components);
- else
- return components;
- }
+ /* There may or may not be any enum decls to grok, but
+ grok_enum_decls will just return components, if there aren't
+ any. We used to try to figure out whether or not there were
+ any enum decls based on the type of components, but that's too
+ hard; it might be something like `enum { a } *p;'. */
+ return grok_enum_decls (components);
+}
+
+/* Constructors for types with virtual baseclasses need an "in-charge" flag
+ saying whether this constructor is responsible for initialization of
+ virtual baseclasses or not. All destructors also need this "in-charge"
+ flag, which additionally determines whether or not the destructor should
+ free the memory for the object.
+
+ This function adds the "in-charge" flag to member function FN if
+ appropriate. It is called from grokclassfn and tsubst.
+ FN must be either a constructor or destructor. */
+
+void
+maybe_retrofit_in_chrg (fn)
+ tree fn;
+{
+ tree basetype, arg_types, parms, parm, fntype;
+
+ if (DECL_CONSTRUCTOR_P (fn)
+ && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CLASS_CONTEXT (fn))
+ && ! DECL_CONSTRUCTOR_FOR_VBASE_P (fn))
+ /* OK */;
+ else if (! DECL_CONSTRUCTOR_P (fn)
+ && TREE_CHAIN (DECL_ARGUMENTS (fn)) == NULL_TREE)
+ /* OK */;
+ else
+ return;
+
+ if (DECL_CONSTRUCTOR_P (fn))
+ DECL_CONSTRUCTOR_FOR_VBASE_P (fn) = 1;
+
+ /* First add it to DECL_ARGUMENTS... */
+ parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
+ /* Mark the artificial `__in_chrg' parameter as "artificial". */
+ SET_DECL_ARTIFICIAL (parm);
+ DECL_ARG_TYPE (parm) = integer_type_node;
+ TREE_READONLY (parm) = 1;
+ parms = DECL_ARGUMENTS (fn);
+ TREE_CHAIN (parm) = TREE_CHAIN (parms);
+ TREE_CHAIN (parms) = parm;
+
+ /* ...and then to TYPE_ARG_TYPES. */
+ arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ basetype = TREE_TYPE (TREE_VALUE (arg_types));
+ arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types));
+ fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)),
+ arg_types);
+ if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
+ fntype = build_exception_variant (fntype,
+ TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)));
+ TREE_TYPE (fn) = fntype;
}
/* Classes overload their constituent function names automatically.
@@ -866,8 +1076,6 @@ 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)
{
@@ -894,24 +1102,6 @@ grokclassfn (ctype, cname, function, flags, quals)
&& (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function)))
constp = 0;
- if (DECL_CONSTRUCTOR_P (function))
- {
- if (TYPE_USES_VIRTUAL_BASECLASSES (ctype))
- {
- DECL_CONSTRUCTOR_FOR_VBASE_P (function) = 1;
- /* In this case we need "in-charge" flag saying whether
- this constructor is responsible for initialization
- of virtual baseclasses or not. */
- parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
- /* Mark the artificial `__in_chrg' parameter as "artificial". */
- SET_DECL_ARTIFICIAL (parm);
- DECL_ARG_TYPE (parm) = integer_type_node;
- DECL_REGISTER (parm) = 1;
- TREE_CHAIN (parm) = last_function_parms;
- last_function_parms = parm;
- }
- }
-
parm = build_decl (PARM_DECL, this_identifier, type);
/* Mark the artificial `this' parameter as "artificial". */
SET_DECL_ARTIFICIAL (parm);
@@ -925,99 +1115,37 @@ grokclassfn (ctype, cname, function, flags, quals)
last_function_parms = parm;
}
- if (flags == DTOR_FLAG)
+ DECL_ARGUMENTS (function) = last_function_parms;
+ /* First approximations. */
+ DECL_CONTEXT (function) = ctype;
+ DECL_CLASS_CONTEXT (function) = ctype;
+
+ if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))
{
- char *buf, *dbuf;
- tree const_integer_type = build_type_variant (integer_type_node, 1, 0);
- int len = sizeof (DESTRUCTOR_DECL_PREFIX)-1;
-
- arg_types = hash_tree_chain (const_integer_type, void_list_node);
- TREE_SIDE_EFFECTS (arg_types) = 1;
- /* Build the overload name. It will look like `7Example'. */
- if (IDENTIFIER_TYPE_VALUE (cname))
- dbuf = build_overload_name (IDENTIFIER_TYPE_VALUE (cname), 1, 1);
- else if (IDENTIFIER_LOCAL_VALUE (cname))
- dbuf = build_overload_name (TREE_TYPE (IDENTIFIER_LOCAL_VALUE (cname)), 1, 1);
- else
- /* Using ctype fixes the `X::Y::~Y()' crash. The cname has no type when
- it's defined out of the class definition, since poplevel_class wipes
- it out. This used to be internal error 346. */
- dbuf = build_overload_name (ctype, 1, 1);
- buf = (char *) alloca (strlen (dbuf) + sizeof (DESTRUCTOR_DECL_PREFIX));
- bcopy (DESTRUCTOR_DECL_PREFIX, buf, len);
- buf[len] = '\0';
- strcat (buf, dbuf);
- DECL_ASSEMBLER_NAME (function) = get_identifier (buf);
- parm = build_decl (PARM_DECL, in_charge_identifier, const_integer_type);
- /* Mark the artificial `__in_chrg' parameter as "artificial". */
- SET_DECL_ARTIFICIAL (parm);
- TREE_USED (parm) = 1;
-#if 0
- /* We don't need to mark the __in_chrg parameter itself as `const'
- since its type is already `const int'. In fact we MUST NOT mark
- it as `const' cuz that will screw up the debug info (causing it
- to say that the type of __in_chrg is `const const int'). */
- TREE_READONLY (parm) = 1;
-#endif
- DECL_ARG_TYPE (parm) = const_integer_type;
- /* This is the same chain as DECL_ARGUMENTS (...). */
- TREE_CHAIN (last_function_parms) = parm;
+ maybe_retrofit_in_chrg (function);
+ arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
+ }
- fntype = build_cplus_method_type (qualtype, void_type_node,
- arg_types);
- if (raises)
- {
- fntype = build_exception_variant (fntype, raises);
- }
- TREE_TYPE (function) = fntype;
+ if (flags == DTOR_FLAG)
+ {
+ DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype);
TYPE_HAS_DESTRUCTOR (ctype) = 1;
}
else
{
- tree these_arg_types;
-
- if (DECL_CONSTRUCTOR_FOR_VBASE_P (function))
- {
- arg_types = hash_tree_chain (integer_type_node,
- TREE_CHAIN (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));
- }
-
- these_arg_types = arg_types;
-
if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
/* Only true for static member functions. */
- these_arg_types = hash_tree_chain (build_pointer_type (qualtype),
- arg_types);
+ arg_types = hash_tree_chain (build_pointer_type (qualtype),
+ arg_types);
DECL_ASSEMBLER_NAME (function)
- = build_decl_overload (fn_name, these_arg_types,
+ = build_decl_overload (fn_name, arg_types,
1 + DECL_CONSTRUCTOR_P (function));
-
-#if 0
- /* This code is going into the compiler, but currently, it makes
- libg++/src/Integer.cc not compile. The problem is that the nice name
- winds up going into the symbol table, and conversion operations look
- for the manged name. */
- substitute_nice_name (function);
-#endif
}
-
- DECL_ARGUMENTS (function) = last_function_parms;
- /* First approximations. */
- DECL_CONTEXT (function) = ctype;
- DECL_CLASS_CONTEXT (function) = ctype;
}
/* Work on the expr used by alignof (this is only called by the parser). */
+
tree
grok_alignof (expr)
tree expr;
@@ -1025,6 +1153,9 @@ grok_alignof (expr)
tree best, t;
int bestalign;
+ if (processing_template_decl)
+ return build_min (ALIGNOF_EXPR, sizetype, expr);
+
if (TREE_CODE (expr) == COMPONENT_REF
&& DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
error ("`__alignof__' applied to a bit-field");
@@ -1061,6 +1192,7 @@ grok_alignof (expr)
/* Create an ARRAY_REF, checking for the user doing things backwards
along the way. */
+
tree
grok_array_decl (array_expr, index_exp)
tree array_expr, index_exp;
@@ -1070,6 +1202,10 @@ grok_array_decl (array_expr, index_exp)
if (type == error_mark_node || index_exp == error_mark_node)
return error_mark_node;
+ if (processing_template_decl)
+ return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE,
+ array_expr, index_exp);
+
if (type == NULL_TREE)
{
/* Something has gone very wrong. Assume we are mistakenly reducing
@@ -1083,8 +1219,7 @@ grok_array_decl (array_expr, index_exp)
type = TREE_TYPE (type);
/* If they have an `operator[]', use that. */
- if (TYPE_LANG_SPECIFIC (type)
- && TYPE_OVERLOADS_ARRAY_REF (type))
+ if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
array_expr, index_exp, NULL_TREE);
@@ -1130,78 +1265,70 @@ grok_array_decl (array_expr, index_exp)
for doing an array delete. If DOING_VEC is 2, they gave us the
array size as an argument to delete.
Implements ARM $5.3.4. This is called from the parser. */
+
tree
delete_sanity (exp, size, doing_vec, use_global_delete)
tree exp, size;
int doing_vec, use_global_delete;
{
- tree t = stabilize_reference (convert_from_reference (exp));
- tree type = TREE_TYPE (t);
- enum tree_code code = TREE_CODE (type);
+ tree t, type;
/* For a regular vector delete (aka, no size argument) we will pass
this down as a NULL_TREE into build_vec_delete. */
tree maxindex = NULL_TREE;
- /* This is used for deleting arrays. */
- tree elt_size;
- switch (doing_vec)
+ if (exp == error_mark_node)
+ return exp;
+
+ if (processing_template_decl)
{
- case 2:
- maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
- if (! flag_traditional)
- pedwarn ("anachronistic use of array size in vector delete");
- /* Fall through. */
- case 1:
- elt_size = c_sizeof (type);
- break;
- default:
- if (code != POINTER_TYPE)
- {
- cp_error ("type `%#T' argument given to `delete', expected pointer",
- type);
- return error_mark_node;
- }
+ t = build_min (DELETE_EXPR, void_type_node, exp, size);
+ DELETE_EXPR_USE_GLOBAL (t) = use_global_delete;
+ DELETE_EXPR_USE_VEC (t) = doing_vec;
+ return t;
+ }
+
+ if (TREE_CODE (exp) == OFFSET_REF)
+ exp = resolve_offset_ref (exp);
+ exp = convert_from_reference (exp);
+ t = stabilize_reference (exp);
+ t = build_expr_type_conversion (WANT_POINTER, t, 1);
- /* Deleting a pointer with the value zero is valid and has no effect. */
- if (integer_zerop (t))
- return build1 (NOP_EXPR, void_type_node, t);
+ if (t == NULL_TREE || t == error_mark_node)
+ {
+ cp_error ("type `%#T' argument given to `delete', expected pointer",
+ TREE_TYPE (exp));
+ return error_mark_node;
}
- if (code == POINTER_TYPE)
+ if (doing_vec == 2)
{
-#if 0
- /* As of Valley Forge, you can delete a pointer to constant. */
- /* You can't delete a pointer to constant. */
- if (TREE_READONLY (TREE_TYPE (type)))
- {
- error ("`const *' cannot be deleted");
- return error_mark_node;
- }
-#endif
- /* You also can't delete functions. */
- if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
- {
- error ("cannot delete a function");
- return error_mark_node;
- }
+ maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
+ pedwarn ("anachronistic use of array size in vector delete");
}
-#if 0
- /* If the type has no destructor, then we should build a regular
- delete, instead of a vector delete. Otherwise, we would end
- up passing a bogus offset into __builtin_delete, which is
- not expecting it. */
- if (doing_vec
- && TREE_CODE (type) == POINTER_TYPE
- && !TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)))
+ type = TREE_TYPE (t);
+
+ /* As of Valley Forge, you can delete a pointer to const. */
+
+ /* You can't delete functions. */
+ if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
{
- doing_vec = 0;
- use_global_delete = 1;
+ error ("cannot delete a function");
+ return error_mark_node;
}
-#endif
+
+ /* An array can't have been allocated by new, so complain. */
+ if (TREE_CODE (t) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == ARRAY_TYPE)
+ cp_warning ("deleting array `%#D'", TREE_OPERAND (t, 0));
+
+ /* Deleting a pointer with the value zero is valid and has no effect. */
+ if (integer_zerop (t))
+ return build1 (NOP_EXPR, void_type_node, t);
if (doing_vec)
- return build_vec_delete (t, maxindex, elt_size, integer_one_node,
+ return build_vec_delete (t, maxindex, integer_one_node,
integer_two_node, use_global_delete);
else
{
@@ -1210,31 +1337,123 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
{
/* Only do access checking here; we'll be calling op delete
from the destructor. */
- tree tmp = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, t,
- size_zero_node, NULL_TREE);
+ tree tmp = build_op_delete_call (DELETE_EXPR, t, size_zero_node,
+ LOOKUP_NORMAL, NULL_TREE);
if (tmp == error_mark_node)
return error_mark_node;
}
return build_delete (type, t, integer_three_node,
- LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE,
- use_global_delete);
+ LOOKUP_NORMAL, use_global_delete);
}
}
+/* Report an error if the indicated template declaration is not the
+ sort of thing that should be a member template. */
+
+void
+check_member_template (tmpl)
+ tree tmpl;
+{
+ tree decl;
+
+ my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+ decl = DECL_TEMPLATE_RESULT (tmpl);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || (TREE_CODE (decl) == TYPE_DECL
+ && IS_AGGR_TYPE (TREE_TYPE (decl))))
+ {
+ if (current_function_decl)
+ /* 14.5.2.2 [temp.mem]
+
+ A local class shall not have member templates. */
+ cp_error ("declaration of member template `%#D' in local class",
+ decl);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
+ {
+ /* 14.5.2.3 [temp.mem]
+
+ A member function template shall not be virtual. */
+ cp_error
+ ("invalid use of `virtual' in template declaration of `%#D'",
+ decl);
+ DECL_VIRTUAL_P (decl) = 0;
+ }
+
+ /* The debug-information generating code doesn't know what to do
+ with member templates. */
+ DECL_IGNORED_P (tmpl) = 1;
+ }
+ else
+ cp_error ("template declaration of `%#D'", decl);
+}
+
+/* Return true iff TYPE is a valid Java parameter or return type. */
+
+int
+acceptable_java_type (type)
+ tree type;
+{
+ if (TREE_CODE (type) == VOID_TYPE || TYPE_FOR_JAVA (type))
+ return 1;
+ if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ type = TREE_TYPE (type);
+ if (TREE_CODE (type) == RECORD_TYPE)
+ {
+ complete_type (type);
+ return TYPE_FOR_JAVA (type);
+ }
+ }
+ return 0;
+}
+
+/* For a METHOD in a Java class CTYPE, return 1 if
+ the parameter and return types are valid Java types.
+ Otherwise, print appropriate error messages, and return 0. */
+
+int
+check_java_method (ctype, method)
+ tree ctype, method;
+{
+ int jerr = 0;
+ tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (method));
+ tree ret_type = TREE_TYPE (TREE_TYPE (method));
+ if (! acceptable_java_type (ret_type))
+ {
+ cp_error ("Java method '%D' has non-Java return type `%T'",
+ method, ret_type);
+ jerr++;
+ }
+ for (; arg_types != NULL_TREE; arg_types = TREE_CHAIN (arg_types))
+ {
+ tree type = TREE_VALUE (arg_types);
+ if (! acceptable_java_type (type))
+ {
+ cp_error ("Java method '%D' has non-Java parameter type `%T'",
+ method, type);
+ jerr++;
+ }
+ }
+ return jerr ? 0 : 1;
+}
+
/* Sanity check: report error if this function FUNCTION is not
really a member of the class (CTYPE) it is supposed to belong to.
CNAME is the same here as it is for grokclassfn above. */
tree
-check_classfn (ctype, cname, function)
- tree ctype, cname, function;
+check_classfn (ctype, function)
+ tree ctype, function;
{
tree fn_name = DECL_NAME (function);
- tree fndecl;
- tree method_vec = CLASSTYPE_METHOD_VEC (ctype);
+ tree fndecl, fndecls;
+ tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
tree *methods = 0;
tree *end = 0;
+ tree templates = NULL_TREE;
if (method_vec != 0)
{
@@ -1242,65 +1461,100 @@ check_classfn (ctype, cname, function)
end = TREE_VEC_END (method_vec);
/* First suss out ctors and dtors. */
- if (*methods && fn_name == DECL_NAME (*methods))
+ if (*methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
+ && DECL_CONSTRUCTOR_P (function))
+ goto got_it;
+ if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
+ && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
goto got_it;
while (++methods != end)
{
- if (fn_name == DECL_NAME (*methods))
+ fndecl = *methods;
+ if (fn_name == DECL_NAME (OVL_CURRENT (*methods)))
{
got_it:
- fndecl = *methods;
- while (fndecl)
+ for (fndecls = *methods; fndecls != NULL_TREE;
+ fndecls = OVL_NEXT (fndecls))
{
- if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl))
+ fndecl = OVL_CURRENT (fndecls);
+ /* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL is
+ not mangled, so the check below does not work
+ correctly in that case. Since mangled destructor names
+ do not include the type of the arguments, we
+ can't use this short-cut for them, either. */
+ if (TREE_CODE (function) != TEMPLATE_DECL
+ && TREE_CODE (fndecl) != TEMPLATE_DECL
+ && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))
+ && (DECL_ASSEMBLER_NAME (function)
+ == DECL_ASSEMBLER_NAME (fndecl)))
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 fndecl;
-#else
+
+ /* We cannot simply call decls_match because this
+ doesn't work for static member functions that are
+ pretending to be methods, and because the name
+ may have been changed by asm("new_name"). */
if (DECL_NAME (function) == DECL_NAME (fndecl))
{
tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
/* Get rid of the this parameter on functions that become
- static. */
+ static. */
if (DECL_STATIC_FUNCTION_P (fndecl)
&& TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
p1 = TREE_CHAIN (p1);
if (comptypes (TREE_TYPE (TREE_TYPE (function)),
TREE_TYPE (TREE_TYPE (fndecl)), 1)
- && compparms (p1, p2, 3))
- {
- if (DECL_STATIC_FUNCTION_P (fndecl)
- && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
- revert_static_member_fn (&function, NULL, NULL);
- return fndecl;
- }
+ && compparms (p1, p2, 3)
+ && (DECL_TEMPLATE_SPECIALIZATION (function)
+ == DECL_TEMPLATE_SPECIALIZATION (fndecl))
+ && (!DECL_TEMPLATE_SPECIALIZATION (function)
+ || (DECL_TI_TEMPLATE (function)
+ == DECL_TI_TEMPLATE (fndecl))))
+ return fndecl;
+
+ if (is_member_template (fndecl))
+ /* This function might be an instantiation
+ or specialization of fndecl. */
+ templates =
+ scratch_tree_cons (NULL_TREE, fndecl, templates);
}
-#endif
- fndecl = DECL_CHAIN (fndecl);
}
break; /* loser */
}
+ else if (TREE_CODE (fndecl) == TEMPLATE_DECL
+ && IDENTIFIER_TYPENAME_P (DECL_NAME (fndecl))
+ && IDENTIFIER_TYPENAME_P (fn_name))
+ /* The method in the class is a member template
+ conversion operator. We are declaring another
+ conversion operator. It is possible that even though
+ the names don't match, there is some specialization
+ occurring. */
+ templates =
+ scratch_tree_cons (NULL_TREE, fndecl, templates);
}
}
+ if (templates)
+ /* This function might be an instantiation or a specialization.
+ We should verify that this is possible. If it is, we must
+ somehow add the new declaration to the method vector for the
+ class. Perhaps we should use add_method? For now, we simply
+ return NULL_TREE, which lets the caller know that this
+ function is new, but we don't print an error message. */
+ return NULL_TREE;
+
if (methods != end)
{
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);
+ cp_error_at ("candidate%s: %+#D", OVL_NEXT (fndecl) ? "s are" : " is",
+ OVL_CURRENT (fndecl));
+ while (fndecl = OVL_NEXT (fndecl), fndecl)
+ cp_error_at (" %#D", OVL_CURRENT(fndecl));
}
else
{
@@ -1309,8 +1563,8 @@ check_classfn (ctype, cname, function)
function, ctype);
}
- /* If we did not find the method in the class, add it to
- avoid spurious errors. */
+ /* If we did not find the method in the class, add it to avoid
+ spurious errors. */
add_method (ctype, methods, function);
return NULL_TREE;
}
@@ -1336,8 +1590,8 @@ check_classfn (ctype, cname, function)
CHANGES TO CODE IN `start_method'. */
tree
-grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
- tree declarator, declspecs, raises, init, asmspec_tree, attrlist;
+grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
+ tree declarator, declspecs, init, asmspec_tree, attrlist;
{
register tree value;
char *asmspec = 0;
@@ -1356,14 +1610,25 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
flags = 0;
}
+ if (declspecs == NULL_TREE
+ && TREE_CODE (declarator) == SCOPE_REF
+ && TREE_CODE (TREE_OPERAND (declarator, 1)) == IDENTIFIER_NODE)
+ {
+ /* Access declaration */
+ if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0))))
+ ;
+ else if (TREE_COMPLEXITY (declarator) == current_class_depth)
+ pop_nested_class (1);
+ return do_class_using_decl (declarator);
+ }
+
if (init
&& TREE_CODE (init) == TREE_LIST
&& TREE_VALUE (init) == error_mark_node
&& TREE_CHAIN (init) == NULL_TREE)
- init = NULL_TREE;
+ init = NULL_TREE;
- value = grokdeclarator (declarator, declspecs, FIELD, init != 0,
- raises, NULL_TREE);
+ value = grokdeclarator (declarator, declspecs, FIELD, init != 0, NULL_TREE);
if (! value)
return value; /* friend or constructor went bad. */
@@ -1374,7 +1639,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
if (DECL_NAME (value) != NULL_TREE
&& IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_'
&& ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr"))
- cp_error ("member `%D' conflicts with virtual function table field name", value);
+ cp_error ("member `%D' conflicts with virtual function table field name",
+ value);
/* Stash away type declarations. */
if (TREE_CODE (value) == TYPE_DECL)
@@ -1384,15 +1650,11 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
DECL_CLASS_CONTEXT (value) = current_class_type;
CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
- /* If we declare a typedef name for something that has no name,
- the typedef name is used for linkage. See 7.1.3 p4 94/0158. */
- if (TYPE_NAME (TREE_TYPE (value))
- && TREE_CODE (TYPE_NAME (TREE_TYPE (value))) == TYPE_DECL
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_TYPE (value))))
- {
- TYPE_NAME (TREE_TYPE (value)) = value;
- TYPE_STUB_DECL (TREE_TYPE (value)) = value;
- }
+ /* Now that we've updated the context, we need to remangle the
+ name for this TYPE_DECL. */
+ DECL_ASSEMBLER_NAME (value) = DECL_NAME (value);
+ DECL_ASSEMBLER_NAME (value) =
+ get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
pushdecl_class_level (value);
return value;
@@ -1412,9 +1674,6 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
return void_type_node;
}
- if (flag_cadillac)
- cadillac_start_decl (value);
-
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
@@ -1458,6 +1717,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
because `decl_const_value' would mis-interpret it
as only meaning that this VAR_DECL is defined. */
init = build1 (NOP_EXPR, TREE_TYPE (value), init);
+ else if (processing_template_decl)
+ ;
else if (! TREE_CONSTANT (init))
{
/* We can allow references to things that are effectively
@@ -1477,45 +1738,51 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
/* The corresponding pop_obstacks is in cp_finish_decl. */
push_obstacks_nochange ();
+ if (processing_template_decl && ! current_function_decl
+ && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
+ value = push_template_decl (value);
+
if (attrlist)
cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
TREE_VALUE (attrlist));
if (TREE_CODE (value) == VAR_DECL)
{
+ my_friendly_assert (TREE_PUBLIC (value), 0);
+
/* We cannot call pushdecl here, because that would
fill in the value of our TREE_CHAIN. Instead, we
modify cp_finish_decl to do the right thing, namely, to
put this decl out straight away. */
- if (TREE_PUBLIC (value))
+ /* current_class_type can be NULL_TREE in case of error. */
+ if (asmspec == 0 && current_class_type)
{
- /* current_class_type can be NULL_TREE in case of error. */
- if (asmspec == 0 && current_class_type)
- {
- TREE_PUBLIC (value) = 1;
- DECL_INITIAL (value) = error_mark_node;
- DECL_ASSEMBLER_NAME (value)
- = build_static_name (current_class_type, DECL_NAME (value));
- }
- pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics);
-
- /* Static consts need not be initialized in the class definition. */
- if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (value)))
- {
- static int explanation = 0;
-
- error ("initializer invalid for static member with constructor");
- if (explanation++ == 0)
- error ("(you really want to initialize it separately)");
- init = 0;
- }
- /* Force the compiler to know when an uninitialized static
- const member is being used. */
- if (TYPE_READONLY (value) && init == 0)
- TREE_USED (value) = 1;
+ TREE_PUBLIC (value) = 1;
+ DECL_INITIAL (value) = error_mark_node;
+ DECL_ASSEMBLER_NAME (value)
+ = build_static_name (current_class_type, DECL_NAME (value));
}
+ if (! processing_template_decl)
+ pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics);
+
+ /* Static consts need not be initialized in the class definition. */
+ if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (value)))
+ {
+ static int explanation = 0;
+
+ error ("initializer invalid for static member with constructor");
+ if (explanation++ == 0)
+ error ("(you really want to initialize it separately)");
+ init = 0;
+ }
+ /* Force the compiler to know when an uninitialized static
+ const member is being used. */
+ if (TYPE_READONLY (value) && init == 0)
+ TREE_USED (value) = 1;
DECL_INITIAL (value) = init;
DECL_IN_AGGR_P (value) = 1;
+ DECL_CONTEXT (value) = current_class_type;
+ DECL_CLASS_CONTEXT (value) = current_class_type;
cp_finish_decl (value, init, asmspec_tree, 1, flags);
pushdecl_class_level (value);
@@ -1539,15 +1806,6 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
}
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
- when we link these together. */
- value = copy_node (value);
- /* When does this happen? */
- my_friendly_assert (init == NULL_TREE, 193);
- }
if (asmspec)
{
/* This must override the asm specifier which was placed
@@ -1583,7 +1841,7 @@ grokbitfield (declarator, declspecs, width)
tree declarator, declspecs, width;
{
register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
- 0, NULL_TREE, NULL_TREE);
+ 0, NULL_TREE);
if (! value) return NULL_TREE; /* friends went bad. */
@@ -1621,216 +1879,20 @@ grokbitfield (declarator, declspecs, width)
if (width != error_mark_node)
{
- /* detect invalid field size. */
- if (TREE_CODE (width) == CONST_DECL)
- width = DECL_INITIAL (width);
- else if (TREE_READONLY_DECL_P (width))
- width = decl_constant_value (width);
- if (TREE_CODE (width) != INTEGER_CST)
- {
- cp_error ("structure field `%D' width not an integer constant",
- value);
- DECL_INITIAL (value) = NULL_TREE;
- }
- else
- {
- constant_expression_warning (width);
- DECL_INITIAL (value) = width;
- DECL_BIT_FIELD (value) = 1;
- }
+ constant_expression_warning (width);
+ DECL_INITIAL (value) = width;
+ DECL_BIT_FIELD (value) = 1;
}
DECL_IN_AGGR_P (value) = 1;
return value;
}
-#if 0
-/* Like GROKFIELD, except that the declarator has been
- buried in DECLSPECS. Find the declarator, and
- return something that looks like it came from
- GROKFIELD. */
-tree
-groktypefield (declspecs, parmlist)
- tree declspecs;
- tree parmlist;
-{
- tree spec = declspecs;
- tree prev = NULL_TREE;
-
- tree type_id = NULL_TREE;
- tree quals = NULL_TREE;
- tree lengths = NULL_TREE;
- tree decl = NULL_TREE;
-
- while (spec)
- {
- register tree id = TREE_VALUE (spec);
-
- if (TREE_CODE (spec) != TREE_LIST)
- /* Certain parse errors slip through. For example,
- `int class ();' is not caught by the parser. Try
- weakly to recover here. */
- return NULL_TREE;
-
- if (TREE_CODE (id) == TYPE_DECL
- || (TREE_CODE (id) == IDENTIFIER_NODE && TREE_TYPE (id)))
- {
- /* We have a constructor/destructor or
- conversion operator. Use it. */
- if (prev)
- TREE_CHAIN (prev) = TREE_CHAIN (spec);
- else
- declspecs = TREE_CHAIN (spec);
-
- type_id = id;
- goto found;
- }
- prev = spec;
- spec = TREE_CHAIN (spec);
- }
-
- /* Nope, we have a conversion operator to a scalar type or something
- else, that includes things like constructor declarations for
- templates. */
- spec = declspecs;
- while (spec)
- {
- tree id = TREE_VALUE (spec);
-
- if (TREE_CODE (id) == IDENTIFIER_NODE)
- {
- if (id == ridpointers[(int)RID_INT]
- || id == ridpointers[(int)RID_DOUBLE]
- || id == ridpointers[(int)RID_FLOAT]
- || id == ridpointers[(int)RID_WCHAR])
- {
- if (type_id)
- error ("extra `%s' ignored",
- IDENTIFIER_POINTER (id));
- else
- type_id = id;
- }
- else if (id == ridpointers[(int)RID_LONG]
- || id == ridpointers[(int)RID_SHORT]
- || id == ridpointers[(int)RID_CHAR])
- {
- lengths = tree_cons (NULL_TREE, id, lengths);
- }
- else if (id == ridpointers[(int)RID_VOID])
- {
- if (type_id)
- error ("spurious `void' type ignored");
- else
- error ("conversion to `void' type invalid");
- }
- else if (id == ridpointers[(int)RID_AUTO]
- || id == ridpointers[(int)RID_REGISTER]
- || id == ridpointers[(int)RID_TYPEDEF]
- || id == ridpointers[(int)RID_CONST]
- || id == ridpointers[(int)RID_VOLATILE])
- {
- error ("type specifier `%s' used invalidly",
- IDENTIFIER_POINTER (id));
- }
- else if (id == ridpointers[(int)RID_FRIEND]
- || id == ridpointers[(int)RID_VIRTUAL]
- || id == ridpointers[(int)RID_INLINE]
- || id == ridpointers[(int)RID_UNSIGNED]
- || id == ridpointers[(int)RID_SIGNED]
- || id == ridpointers[(int)RID_STATIC]
- || id == ridpointers[(int)RID_EXTERN])
- {
- quals = tree_cons (NULL_TREE, id, quals);
- }
- else
- {
- /* Happens when we have a global typedef
- and a class-local member function with
- the same name. */
- type_id = id;
- goto found;
- }
- }
- else if (TREE_CODE (id) == RECORD_TYPE)
- {
- type_id = TYPE_NAME (id);
- if (TREE_CODE (type_id) == TYPE_DECL)
- type_id = DECL_NAME (type_id);
- if (type_id == NULL_TREE)
- error ("identifier for aggregate type conversion omitted");
- }
- else if (TREE_CODE_CLASS (TREE_CODE (id)) == 't')
- error ("`operator' missing on conversion operator or tag missing from type");
- else
- my_friendly_abort (194);
- spec = TREE_CHAIN (spec);
- }
-
- if (type_id)
- declspecs = chainon (lengths, quals);
- else if (lengths)
- {
- if (TREE_CHAIN (lengths))
- error ("multiple length specifiers");
- type_id = ridpointers[(int)RID_INT];
- declspecs = chainon (lengths, quals);
- }
- else if (quals)
- {
- error ("no type given, defaulting to `operator int ...'");
- type_id = ridpointers[(int)RID_INT];
- declspecs = quals;
- }
- else
- return NULL_TREE;
-
- found:
- decl = grokdeclarator (build_parse_node (CALL_EXPR, type_id, parmlist, NULL_TREE),
- declspecs, FIELD, 0, NULL_TREE, NULL_TREE);
- if (decl == NULL_TREE)
- return NULL_TREE;
-
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CHAIN (decl) != NULL_TREE)
- {
- /* Need a fresh node here so that we don't get circularity
- when we link these together. */
- decl = copy_node (decl);
- }
-
- if (decl == void_type_node
- || (TREE_CODE (decl) == FUNCTION_DECL
- && TREE_CODE (TREE_TYPE (decl)) != METHOD_TYPE))
- /* bunch of friends. */
- return decl;
-
- if (DECL_IN_AGGR_P (decl))
- {
- cp_error ("`%D' already defined in the class ", decl);
- return void_type_node;
- }
-
- cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0, 0);
-
- /* If this declaration is common to another declaration
- complain about such redundancy, and return NULL_TREE
- so that we don't build a circular list. */
- if (DECL_CHAIN (decl))
- {
- cp_error ("function `%D' declared twice in class %T", decl,
- DECL_CONTEXT (decl));
- return NULL_TREE;
- }
- DECL_IN_AGGR_P (decl) = 1;
- return decl;
-}
-#endif
-
tree
grokoptypename (declspecs, declarator)
tree declspecs, declarator;
{
- tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0,
- NULL_TREE, NULL_TREE);
+ tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE);
return build_typename_overload (t);
}
@@ -1874,11 +1936,18 @@ copy_assignment_arg_p (parmtype, virtualp)
tree parmtype;
int virtualp;
{
+ if (current_class_type == NULL_TREE)
+ return 0;
+
if (TREE_CODE (parmtype) == REFERENCE_TYPE)
parmtype = TREE_TYPE (parmtype);
if ((TYPE_MAIN_VARIANT (parmtype) == current_class_type)
- || (virtualp && DERIVED_FROM_P (parmtype, current_class_type)))
+#if 0
+ /* Non-standard hack to support old Booch components. */
+ || (! virtualp && DERIVED_FROM_P (parmtype, current_class_type))
+#endif
+ )
return 1;
return 0;
@@ -1895,14 +1964,17 @@ grok_function_init (decl, init)
if (TREE_CODE (type) == FUNCTION_TYPE)
cp_error ("initializer specified for non-member function `%D'", decl);
+#if 0
+ /* We'll check for this in finish_struct_1. */
else if (DECL_VINDEX (decl) == NULL_TREE)
cp_error ("initializer specified for non-virtual method `%D'", decl);
+#endif
else if (integer_zerop (init))
{
#if 0
/* Mark this function as being "defined". */
DECL_INITIAL (decl) = error_mark_node;
- /* pure virtual destructors must be defined. */
+ /* pure virtual destructors must be defined. */
/* pure virtual needs to be defined (as abort) only when put in
vtbl. For wellformed call, it should be itself. pr4737 */
if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)))
@@ -1922,88 +1994,10 @@ grok_function_init (decl, init)
TYPE_HAS_ABSTRACT_ASSIGN_REF (current_class_type) = 1;
}
}
- else if (TREE_CODE (init) == OFFSET_REF
- && TREE_OPERAND (init, 0) == NULL_TREE
- && TREE_CODE (TREE_TYPE (init)) == METHOD_TYPE)
- {
- tree basetype = DECL_CLASS_CONTEXT (init);
- tree basefn = TREE_OPERAND (init, 1);
- if (TREE_CODE (basefn) != FUNCTION_DECL)
- cp_error ("non-method initializer invalid for method `%D'", decl);
- else if (! BINFO_OFFSET_ZEROP (TYPE_BINFO (DECL_CLASS_CONTEXT (basefn))))
- sorry ("base member function from other than first base class");
- else
- {
- tree binfo = get_binfo (basetype, TYPE_METHOD_BASETYPE (type), 1);
- if (binfo == error_mark_node)
- ;
- else if (binfo == 0)
- error_not_base_type (TYPE_METHOD_BASETYPE (TREE_TYPE (init)),
- TYPE_METHOD_BASETYPE (type));
- else
- {
- /* Mark this function as being defined,
- and give it new rtl. */
- DECL_INITIAL (decl) = error_mark_node;
- DECL_RTL (decl) = DECL_RTL (basefn);
- }
- }
- }
else
cp_error ("invalid initializer for virtual method `%D'", decl);
}
-/* When we get a declaration of the form
-
- type cname::fname ...
-
- the node for `cname::fname' gets built here in a special way.
- Namely, we push into `cname's scope. When this declaration is
- processed, we pop back out. */
-tree
-build_push_scope (cname, name)
- tree cname;
- tree name;
-{
- extern int current_class_depth;
- tree ctype, rval;
- int is_ttp = 0;
-
- if (cname == error_mark_node)
- return error_mark_node;
-
- ctype = IDENTIFIER_TYPE_VALUE (cname);
-
- if (TREE_CODE (ctype) == TEMPLATE_TYPE_PARM)
- is_ttp = 1;
- else if (ctype == NULL_TREE || ! IS_AGGR_TYPE (ctype))
- {
- cp_error ("`%T' not defined as aggregate type", cname);
- return name;
- }
- else if (IS_SIGNATURE (ctype))
- {
- error ("cannot push into signature scope, scope resolution operator ignored");
- return name;
- }
-
- rval = build_parse_node (SCOPE_REF, cname, name);
-
- /* Don't need to push the scope if we're already in it.
- We also don't need to push the scope for a ptr-to-member/method. */
-
- if (ctype == current_class_type || TREE_CODE (name) != IDENTIFIER_NODE
- || is_ttp)
- return rval;
-
- /* We do need to push the scope in this case, since CTYPE helps
- determine subsequent initializers (i.e., Foo::Bar x = foo_enum_1;). */
-
- push_nested_class (ctype, 3);
- TREE_COMPLEXITY (rval) = current_class_depth;
- return rval;
-}
-
void
cplus_decl_attributes (decl, attributes, prefix_attributes)
tree decl, attributes, prefix_attributes;
@@ -2025,22 +2019,25 @@ cplus_decl_attributes (decl, attributes, prefix_attributes)
specified class. Argument can be RECORD_TYPE, TYPE_DECL, or
IDENTIFIER_NODE. When given a template, this routine doesn't
lose the specialization. */
+
tree
constructor_name_full (thing)
tree thing;
{
- if (TREE_CODE (thing) == UNINSTANTIATED_P_TYPE)
- return DECL_NAME (UPT_TEMPLATE (thing));
- if (IS_AGGR_TYPE_CODE (TREE_CODE (thing)))
+ if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (thing) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (thing) == TYPENAME_TYPE)
+ thing = TYPE_NAME (thing);
+ else if (IS_AGGR_TYPE_CODE (TREE_CODE (thing)))
{
if (TYPE_WAS_ANONYMOUS (thing) && TYPE_HAS_CONSTRUCTOR (thing))
- thing = DECL_NAME (TREE_VEC_ELT (TYPE_METHODS (thing), 0));
+ thing = DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (thing), 0)));
else
thing = TYPE_NAME (thing);
}
if (TREE_CODE (thing) == TYPE_DECL
|| (TREE_CODE (thing) == TEMPLATE_DECL
- && DECL_TEMPLATE_IS_CLASS (thing)))
+ && TREE_CODE (DECL_TEMPLATE_RESULT (thing)) == TYPE_DECL))
thing = DECL_NAME (thing);
my_friendly_assert (TREE_CODE (thing) == IDENTIFIER_NODE, 197);
return thing;
@@ -2051,6 +2048,7 @@ constructor_name_full (thing)
specified class. Argument can be RECORD_TYPE, TYPE_DECL, or
IDENTIFIER_NODE. When given a template, return the plain
unspecialized name. */
+
tree
constructor_name (thing)
tree thing;
@@ -2060,13 +2058,13 @@ constructor_name (thing)
t = IDENTIFIER_TEMPLATE (thing);
if (!t)
return thing;
- t = TREE_PURPOSE (t);
- return DECL_NAME (t);
+ return t;
}
/* Cache the value of this class's main virtual function table pointer
in a register variable. This will save one indirection if a
more than one virtual function call is made this function. */
+
void
setup_vtbl_ptr ()
{
@@ -2074,10 +2072,18 @@ setup_vtbl_ptr ()
if (base_init_expr == 0
&& DECL_CONSTRUCTOR_P (current_function_decl))
- emit_base_init (current_class_type, 0);
+ {
+ if (processing_template_decl)
+ add_tree (build_min_nt
+ (CTOR_INITIALIZER,
+ current_member_init_list, current_base_init_list));
+ else
+ emit_base_init (current_class_type, 0);
+ }
}
/* Record the existence of an addressable inline function. */
+
void
mark_inline_for_output (decl)
tree decl;
@@ -2147,6 +2153,7 @@ get_temp_name (type, staticp)
}
TREE_USED (decl) = 1;
TREE_STATIC (decl) = staticp;
+ DECL_ARTIFICIAL (decl) = 1;
/* If this is a local variable, then lay out its rtl now.
Otherwise, callers of this function are responsible for dealing
@@ -2165,39 +2172,99 @@ get_temp_name (type, staticp)
It is not entered into current_binding_level, because
that breaks things when it comes time to do final cleanups
(which take place "outside" the binding contour of the function). */
+
tree
get_temp_regvar (type, init)
tree type, init;
{
- static char buf[sizeof (AUTO_TEMP_FORMAT) + 20] = { '_' };
tree decl;
- sprintf (buf+1, AUTO_TEMP_FORMAT, temp_name_counter++);
- decl = build_decl (VAR_DECL, get_identifier (buf), type);
+ decl = build_decl (VAR_DECL, NULL_TREE, type);
TREE_USED (decl) = 1;
DECL_REGISTER (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
- if (init)
- store_init_value (decl, init);
-
+ DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
/* We can expand these without fear, since they cannot need
constructors or destructors. */
- expand_decl (decl);
- expand_decl_init (decl);
-
- if (type_needs_gc_entry (type))
- DECL_GC_OFFSET (decl) = size_int (++current_function_obstack_index);
+ expand_expr (build_modify_expr (decl, INIT_EXPR, init),
+ NULL_RTX, VOIDmode, 0);
return decl;
}
-/* Make the macro TEMP_NAME_P available to units which do not
- include c-tree.h. */
-int
-temp_name_p (decl)
- tree decl;
+/* Hunts through the global anonymous union ANON_DECL, building
+ appropriate VAR_DECLs. Stores cleanups on the list of ELEMS, and
+ returns a VAR_DECL whose size is the same as the size of the
+ ANON_DECL, if one is available. */
+
+tree
+build_anon_union_vars (anon_decl, elems, static_p, external_p)
+ tree anon_decl;
+ tree* elems;
+ int static_p;
+ int external_p;
{
- return TEMP_NAME_P (decl);
+ tree type = TREE_TYPE (anon_decl);
+ tree main_decl = NULL_TREE;
+ tree field;
+
+ for (field = TYPE_FIELDS (type);
+ field != NULL_TREE;
+ field = TREE_CHAIN (field))
+ {
+ tree 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);
+
+ if (DECL_NAME (field) == NULL_TREE
+ && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+ {
+ decl = build_anon_union_vars (field, elems, static_p, external_p);
+ if (!decl)
+ continue;
+ }
+ else
+ {
+ decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
+ /* tell `pushdecl' that this is not tentative. */
+ DECL_INITIAL (decl) = error_mark_node;
+ TREE_PUBLIC (decl) = 0;
+ TREE_STATIC (decl) = static_p;
+ DECL_EXTERNAL (decl) = external_p;
+ decl = pushdecl (decl);
+ DECL_INITIAL (decl) = NULL_TREE;
+ }
+
+ /* Only write out one anon union element--choose the one that
+ can hold them all. */
+ if (main_decl == NULL_TREE
+ && simple_cst_equal (DECL_SIZE (decl),
+ DECL_SIZE (anon_decl)) == 1)
+ main_decl = decl;
+ else
+ /* ??? This causes there to be no debug info written out
+ about this decl. */
+ TREE_ASM_WRITTEN (decl) = 1;
+
+ if (DECL_NAME (field) == NULL_TREE
+ && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+ /* The remainder of the processing was already done in the
+ recursive call. */
+ continue;
+
+ /* If there's a cleanup to do, it belongs in the
+ TREE_PURPOSE of the following TREE_LIST. */
+ *elems = scratch_tree_cons (NULL_TREE, decl, *elems);
+ TREE_TYPE (*elems) = type;
+ }
+
+ return main_decl;
}
/* Finish off the processing of a UNION_TYPE structure.
@@ -2206,18 +2273,19 @@ temp_name_p (decl)
union is an anonymous union, we arrange for that
as well. PUBLIC_P is nonzero if this union is
not declared static. */
+
void
finish_anon_union (anon_union_decl)
tree anon_union_decl;
{
tree type = TREE_TYPE (anon_union_decl);
- tree field, main_decl = NULL_TREE;
tree elems = NULL_TREE;
+ tree main_decl;
int public_p = TREE_PUBLIC (anon_union_decl);
int static_p = TREE_STATIC (anon_union_decl);
int external_p = DECL_EXTERNAL (anon_union_decl);
- if ((field = TYPE_FIELDS (type)) == NULL_TREE)
+ if (TYPE_FIELDS (type) == NULL_TREE)
return;
if (public_p)
@@ -2226,46 +2294,9 @@ finish_anon_union (anon_union_decl)
return;
}
- for (; field; field = TREE_CHAIN (field))
- {
- tree decl;
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
+ main_decl = build_anon_union_vars (anon_union_decl, &elems,
+ static_p, external_p);
- 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;
- TREE_PUBLIC (decl) = public_p;
- TREE_STATIC (decl) = static_p;
- DECL_EXTERNAL (decl) = external_p;
- decl = pushdecl (decl);
-
- /* Only write out one anon union element--choose the one that
- can hold them all. */
- if (main_decl == NULL_TREE
- && 1 == simple_cst_equal (DECL_SIZE (decl),
- DECL_SIZE (anon_union_decl)))
- {
- main_decl = decl;
- }
- else
- {
- /* ??? This causes there to be no debug info written out
- about this decl. */
- TREE_ASM_WRITTEN (decl) = 1;
- }
-
- DECL_INITIAL (decl) = NULL_TREE;
- /* If there's a cleanup to do, it belongs in the
- TREE_PURPOSE of the following TREE_LIST. */
- elems = tree_cons (NULL_TREE, decl, elems);
- TREE_TYPE (elems) = type;
- }
if (static_p)
{
if (main_decl)
@@ -2283,84 +2314,6 @@ finish_anon_union (anon_union_decl)
/* The following call assumes that there are never any cleanups
for anonymous unions--a reasonable assumption. */
expand_anon_union_decl (anon_union_decl, NULL_TREE, elems);
-
- if (flag_cadillac)
- cadillac_finish_anon_union (anon_union_decl);
-}
-
-/* Finish and output a table which is generated by the compiler.
- NAME is the name to give the table.
- TYPE is the type of the table entry.
- INIT is all the elements in the table.
- PUBLICP is non-zero if this table should be given external access. */
-tree
-finish_table (name, type, init, publicp)
- tree name, type, init;
- int publicp;
-{
- tree itype, atype, decl;
- static tree empty_table;
- int is_empty = 0;
- tree asmspec;
-
- itype = build_index_type (size_int (list_length (init) - 1));
- atype = build_cplus_array_type (type, itype);
- layout_type (atype);
-
- if (TREE_VALUE (init) == integer_zero_node
- && TREE_CHAIN (init) == NULL_TREE)
- {
-#if 0
- if (empty_table == NULL_TREE)
-#endif
- {
- empty_table = get_temp_name (atype, 1);
- init = build (CONSTRUCTOR, atype, NULL_TREE, init);
- TREE_CONSTANT (init) = 1;
- TREE_STATIC (init) = 1;
- DECL_INITIAL (empty_table) = init;
- asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)),
- IDENTIFIER_POINTER (DECL_NAME (empty_table)));
- cp_finish_decl (empty_table, NULL_TREE, asmspec, 0, 0);
- }
- is_empty = 1;
- }
-
- if (name == NULL_TREE)
- {
- if (is_empty)
- return empty_table;
- decl = get_temp_name (atype, 1);
- }
- else
- {
- decl = build_decl (VAR_DECL, name, atype);
- decl = pushdecl (decl);
- TREE_STATIC (decl) = 1;
- }
-
- if (is_empty == 0)
- {
- TREE_PUBLIC (decl) = publicp;
- init = build (CONSTRUCTOR, atype, NULL_TREE, init);
- TREE_CONSTANT (init) = 1;
- TREE_STATIC (init) = 1;
- DECL_INITIAL (decl) = init;
- asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (decl)),
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- }
- else
- {
- /* This will cause DECL to point to EMPTY_TABLE in rtl-land. */
- DECL_EXTERNAL (decl) = 1;
- TREE_STATIC (decl) = 0;
- init = 0;
- asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)),
- IDENTIFIER_POINTER (DECL_NAME (empty_table)));
- }
-
- cp_finish_decl (decl, NULL_TREE, asmspec, 0, 0);
- return decl;
}
/* Finish processing a builtin type TYPE. It's name is NAME,
@@ -2369,6 +2322,7 @@ finish_table (name, type, init, publicp)
used in FIELDS.
It is given the same alignment as ALIGN_TYPE. */
+
void
finish_builtin_type (type, name, fields, len, align_type)
tree type;
@@ -2395,6 +2349,7 @@ finish_builtin_type (type, name, fields, len, align_type)
#else
TYPE_NAME (type) = build_decl (TYPE_DECL, get_identifier (name), type);
#endif
+ TYPE_STUB_DECL (type) = TYPE_NAME (type);
layout_decl (TYPE_NAME (type), 0);
}
@@ -2402,8 +2357,6 @@ finish_builtin_type (type, name, fields, len, align_type)
`operator new' and `operator delete' correspond to
what compiler will be expecting. */
-extern tree sizetype;
-
tree
coerce_new_type (type)
tree type;
@@ -2433,7 +2386,10 @@ tree
coerce_delete_type (type)
tree type;
{
- int e1 = 0, e2 = 0, e3 = 0;
+ int e1 = 0, e2 = 0;
+#if 0
+ e3 = 0;
+#endif
tree arg_types = TYPE_ARG_TYPES (type);
if (TREE_CODE (type) == METHOD_TYPE)
@@ -2441,12 +2397,15 @@ coerce_delete_type (type)
type = build_function_type (TREE_TYPE (type), TREE_CHAIN (arg_types));
arg_types = TREE_CHAIN (arg_types);
}
+
if (TREE_TYPE (type) != void_type_node)
e1 = 1, error ("`operator delete' must return type `void'");
+
if (arg_types == NULL_TREE
|| TREE_VALUE (arg_types) != ptr_type_node)
e2 = 1, error ("`operator delete' takes type `void *' as first parameter");
+#if 0
if (arg_types
&& TREE_CHAIN (arg_types)
&& TREE_CHAIN (arg_types) != void_list_node)
@@ -2466,8 +2425,10 @@ coerce_delete_type (type)
error ("`...' invalid in specification of `operator delete'");
}
}
+
if (e3)
- arg_types = tree_cons (NULL_TREE, ptr_type_node, build_tree_list (NULL_TREE, sizetype));
+ arg_types = tree_cons (NULL_TREE, ptr_type_node,
+ build_tree_list (NULL_TREE, sizetype));
else if (e3 |= e2)
{
if (arg_types == NULL_TREE)
@@ -2476,37 +2437,96 @@ coerce_delete_type (type)
arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types));
}
else e3 |= e1;
+#endif
- if (e3)
+ if (e2)
+ arg_types = tree_cons (NULL_TREE, ptr_type_node,
+ arg_types ? TREE_CHAIN (arg_types): NULL_TREE);
+ if (e2 || e1)
type = build_function_type (void_type_node, arg_types);
return type;
}
+extern tree abort_fndecl;
+
static void
mark_vtable_entries (decl)
tree decl;
{
tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl));
+ if (flag_rtti)
+ {
+ tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (TREE_CHAIN (entries))
+ : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
+ tree fn = TREE_OPERAND (fnaddr, 0);
+ TREE_ADDRESSABLE (fn) = 1;
+ mark_used (fn);
+ }
skip_rtti_stuff (&entries);
for (; entries; entries = TREE_CHAIN (entries))
{
- tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries));
+ tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries)
+ : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
tree fn = TREE_OPERAND (fnaddr, 0);
TREE_ADDRESSABLE (fn) = 1;
- if (DECL_ABSTRACT_VIRTUAL_P (fn))
+ if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn))
{
- extern tree abort_fndecl;
- if (flag_vtable_thunks)
- fnaddr = TREE_VALUE (entries);
- TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl;
+ TREE_OPERAND (fnaddr, 0) = fn = copy_node (fn);
+ DECL_RTL (fn) = DECL_RTL (abort_fndecl);
+ mark_used (abort_fndecl);
+ }
+ if (TREE_CODE (fn) == THUNK_DECL && DECL_EXTERNAL (fn))
+ {
+ DECL_EXTERNAL (fn) = 0;
+ emit_thunk (fn);
}
- assemble_external (fn);
+ mark_used (fn);
}
}
+/* Set DECL up to have the closest approximation of "initialized common"
+ linkage available. */
+
+void
+comdat_linkage (decl)
+ tree decl;
+{
+ if (flag_weak)
+ make_decl_one_only (decl);
+ else
+ TREE_PUBLIC (decl) = 0;
+
+ if (DECL_LANG_SPECIFIC (decl))
+ DECL_COMDAT (decl) = 1;
+}
+
+/* For win32 we also want to put explicit instantiations in
+ linkonce sections, so that they will be merged with implicit
+ instantiations; otherwise we get duplicate symbol errors. */
+
+void
+maybe_make_one_only (decl)
+ tree decl;
+{
+ /* This is not necessary on targets that support weak symbols, because
+ the implicit instantiations will defer to the explicit one. */
+ if (! supports_one_only () || SUPPORTS_WEAK)
+ return;
+
+ /* We can't set DECL_COMDAT on functions, or finish_file will think
+ we can get away with not emitting them if they aren't used.
+ We can't use make_decl_one_only for variables, because their
+ DECL_INITIAL may not have been set properly yet. */
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ make_decl_one_only (decl);
+ else
+ comdat_linkage (decl);
+}
+
/* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
based on TYPE and other static flags.
@@ -2534,6 +2554,11 @@ import_export_vtable (decl, type, final)
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type);
DECL_INTERFACE_KNOWN (decl) = 1;
+
+ /* For WIN32 we also want to put explicit instantiations in
+ linkonce sections. */
+ if (CLASSTYPE_EXPLICIT_INSTANTIATION (type))
+ maybe_make_one_only (decl);
}
else
{
@@ -2542,11 +2567,12 @@ import_export_vtable (decl, type, final)
int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type);
+#ifndef MULTIPLE_SYMBOL_SPACES
if (! found && ! final)
{
tree method;
- for (method = CLASSTYPE_METHODS (type); method != NULL_TREE;
- method = DECL_NEXT_METHOD (method))
+ for (method = TYPE_METHODS (type); method != NULL_TREE;
+ method = TREE_CHAIN (method))
if (DECL_VINDEX (method) != NULL_TREE
&& ! DECL_THIS_INLINE (method)
&& ! DECL_ABSTRACT_VIRTUAL_P (method))
@@ -2555,17 +2581,11 @@ import_export_vtable (decl, type, final)
break;
}
}
+#endif
if (final || ! found)
{
-#ifdef ASSEMBLE_EXTERNAL
- if (TREE_PUBLIC (decl))
- cp_error ("all virtual functions redeclared inline");
-#endif
- if (SUPPORTS_WEAK)
- DECL_WEAK (decl) = 1;
- else
- TREE_PUBLIC (decl) = 0;
+ comdat_linkage (decl);
DECL_EXTERNAL (decl) = 0;
}
else
@@ -2576,86 +2596,84 @@ import_export_vtable (decl, type, final)
}
}
-static void
-import_export_template (type)
- tree type;
-{
- if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
- && ! flag_implicit_templates
- && CLASSTYPE_INTERFACE_UNKNOWN (type))
- {
- SET_CLASSTYPE_INTERFACE_KNOWN (type);
- CLASSTYPE_INTERFACE_ONLY (type) = 1;
- CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 0;
- }
-}
-
-static void
-finish_prevtable_vardecl (prev, vars)
- tree prev, vars;
+/* Determine whether or not we want to specifically import or export CTYPE,
+ using various heuristics. */
+
+void
+import_export_class (ctype)
+ tree ctype;
{
- tree ctype = DECL_CONTEXT (vars);
- import_export_template (ctype);
+ /* -1 for imported, 1 for exported. */
+ int import_export = 0;
+
+ if (CLASSTYPE_INTERFACE_KNOWN (ctype))
+ return;
+
+#ifdef VALID_MACHINE_TYPE_ATTRIBUTE
+ /* FIXME this should really use some sort of target-independent macro. */
+ if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
+ import_export = -1;
+#endif
- if (CLASSTYPE_INTERFACE_UNKNOWN (ctype) && TYPE_VIRTUAL_P (ctype)
+ /* If we got -fno-implicit-templates, we import template classes that
+ weren't explicitly instantiated. */
+ if (import_export == 0
+ && CLASSTYPE_IMPLICIT_INSTANTIATION (ctype)
+ && ! flag_implicit_templates)
+ import_export = -1;
+
+#ifndef MULTIPLE_SYMBOL_SPACES
+ /* Base our import/export status on that of the first non-inline,
+ non-abstract virtual function, if any. */
+ if (import_export == 0
+ && TYPE_VIRTUAL_P (ctype)
&& ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
{
tree method;
- for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
- method = DECL_NEXT_METHOD (method))
+ for (method = TYPE_METHODS (ctype); method != NULL_TREE;
+ method = TREE_CHAIN (method))
{
if (DECL_VINDEX (method) != NULL_TREE
&& !DECL_THIS_INLINE (method)
&& !DECL_ABSTRACT_VIRTUAL_P (method))
{
- SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
- CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = ! DECL_EXTERNAL (method);
- CLASSTYPE_INTERFACE_ONLY (ctype) = DECL_EXTERNAL (method);
+ import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
break;
}
}
}
+#endif
- import_export_vtable (vars, ctype, 1);
-
- /* We cannot use TREE_USED here, as it may be set by the expanding of a
- ctor that is used to build a global object. The long term plan is to
- make the TD entries statically initialized and move this to
- finish_vtable_vardecl time. */
- if (flag_rtti && write_virtuals >= 0
- && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || 1 || TREE_USED (vars)))
+ if (import_export)
{
- /* Kick out the type descriptor before we dump out global
- initializers, as they are initialized at run time and
- we have to find them when we scan for things that need initialized
- at the top level. */
- build_t_desc (ctype, 1);
+ SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
+ CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = (import_export > 0);
+ CLASSTYPE_INTERFACE_ONLY (ctype) = (import_export < 0);
}
}
-static void
+static int
finish_vtable_vardecl (prev, vars)
tree prev, vars;
{
+ tree ctype = DECL_CONTEXT (vars);
+ import_export_class (ctype);
+ import_export_vtable (vars, ctype, 1);
+
if (write_virtuals >= 0
- && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)))
+ && ! DECL_EXTERNAL (vars)
+ && ((TREE_PUBLIC (vars) && ! DECL_WEAK (vars) && ! DECL_ONE_ONLY (vars))
+ || CLASSTYPE_EXPLICIT_INSTANTIATION (DECL_CONTEXT (vars))
+ || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars))
+ || (hack_decl_function_context (vars) && TREE_USED (vars)))
+ && ! TREE_ASM_WRITTEN (vars))
{
-#if 0
- /* The long term plan it to make the TD entries statically initialized,
- have the entries built and emitted here. When that happens, this
- can be enabled, and the other call to build_t_desc removed. */
- /* Kick out the type descriptor before writing out the vtable. */
- if (flag_rtti)
- build_t_desc (DECL_CONTEXT (vars), 1);
-#endif
-
/* Write it out. */
mark_vtable_entries (vars);
if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
store_init_value (vars, DECL_INITIAL (vars));
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG)
+ if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
{
/* Mark the VAR_DECL node representing the vtable itself as a
"gratuitous" one, thereby forcing dwarfout.c to ignore it.
@@ -2680,32 +2698,35 @@ finish_vtable_vardecl (prev, vars)
DECL_IGNORED_P (vars) = 1;
}
-#endif /* DWARF_DEBUGGING_INFO */
rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
+ return 1;
}
- else if (! TREE_USED (vars))
+ else if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars)))
/* We don't know what to do with this one yet. */
- return;
+ return 0;
/* We know that PREV must be non-zero here. */
TREE_CHAIN (prev) = TREE_CHAIN (vars);
+ return 0;
}
-static void
+static int
prune_vtable_vardecl (prev, vars)
tree prev, vars;
{
/* We know that PREV must be non-zero here. */
TREE_CHAIN (prev) = TREE_CHAIN (vars);
+ return 1;
}
-void
+int
walk_vtables (typedecl_fn, vardecl_fn)
- register void (*typedecl_fn)();
- register void (*vardecl_fn)();
+ register void (*typedecl_fn) PROTO ((tree, tree));
+ register int (*vardecl_fn) PROTO ((tree, tree));
{
tree prev, vars;
+ int flag = 0;
for (prev = 0, vars = getdecls (); vars; vars = TREE_CHAIN (vars))
{
@@ -2713,7 +2734,8 @@ walk_vtables (typedecl_fn, vardecl_fn)
if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars))
{
- if (vardecl_fn) (*vardecl_fn) (prev, vars);
+ if (vardecl_fn)
+ flag |= (*vardecl_fn) (prev, vars);
if (prev && TREE_CHAIN (prev) != vars)
continue;
@@ -2728,6 +2750,8 @@ walk_vtables (typedecl_fn, vardecl_fn)
prev = vars;
}
+
+ return flag;
}
static void
@@ -2746,8 +2770,8 @@ finish_sigtable_vardecl (prev, vars)
void
walk_sigtables (typedecl_fn, vardecl_fn)
- register void (*typedecl_fn)();
- register void (*vardecl_fn)();
+ register void (*typedecl_fn) PROTO((tree, tree));
+ register void (*vardecl_fn) PROTO((tree, tree));
{
tree prev, vars;
@@ -2773,10 +2797,10 @@ walk_sigtables (typedecl_fn, vardecl_fn)
}
/* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an
- inline function at end-of-file. */
+ inline function or template instantiation at end-of-file. */
void
-import_export_inline (decl)
+import_export_decl (decl)
tree decl;
{
if (DECL_INTERFACE_KNOWN (decl))
@@ -2784,12 +2808,18 @@ import_export_inline (decl)
if (DECL_TEMPLATE_INSTANTIATION (decl))
{
- if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
+ DECL_NOT_REALLY_EXTERN (decl) = 1;
+ if (DECL_IMPLICIT_INSTANTIATION (decl)
+ && (flag_implicit_templates || DECL_THIS_INLINE (decl)))
{
- if (SUPPORTS_WEAK)
- DECL_WEAK (decl) = 1;
+ if (!TREE_PUBLIC (decl))
+ /* Templates are allowed to have internal linkage. See
+ [basic.link]. */
+ ;
+ else if (TREE_CODE (decl) == FUNCTION_DECL)
+ comdat_linkage (decl);
else
- TREE_PUBLIC (decl) = 0;
+ DECL_COMDAT (decl) = 1;
}
else
DECL_NOT_REALLY_EXTERN (decl) = 0;
@@ -2797,31 +2827,307 @@ import_export_inline (decl)
else if (DECL_FUNCTION_MEMBER_P (decl))
{
tree ctype = DECL_CLASS_CONTEXT (decl);
- if (CLASSTYPE_INTERFACE_KNOWN (ctype) && ! DECL_ARTIFICIAL (decl))
+ import_export_class (ctype);
+ if (CLASSTYPE_INTERFACE_KNOWN (ctype)
+ && (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl)))
{
DECL_NOT_REALLY_EXTERN (decl)
= ! (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
}
- else if (SUPPORTS_WEAK)
- DECL_WEAK (decl) = 1;
else
- TREE_PUBLIC (decl) = 0;
+ comdat_linkage (decl);
}
- else if (DECL_C_STATIC (decl))
- TREE_PUBLIC (decl) = 0;
- else if (SUPPORTS_WEAK)
- DECL_WEAK (decl) = 1;
+ /* tinfo function */
+ else if (DECL_ARTIFICIAL (decl) && DECL_MUTABLE_P (decl))
+ {
+ tree ctype = TREE_TYPE (DECL_NAME (decl));
+
+ if (IS_AGGR_TYPE (ctype))
+ import_export_class (ctype);
+
+ if (IS_AGGR_TYPE (ctype) && CLASSTYPE_INTERFACE_KNOWN (ctype)
+ && TYPE_VIRTUAL_P (ctype)
+ /* If the type is a cv-qualified variant of a type, then we
+ must emit the tinfo function in this translation unit
+ since it will not be emitted when the vtable for the type
+ is output (which is when the unqualified version is
+ generated). */
+ && ctype == TYPE_MAIN_VARIANT (ctype))
+ {
+ DECL_NOT_REALLY_EXTERN (decl)
+ = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
+ || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
+
+ /* For WIN32 we also want to put explicit instantiations in
+ linkonce sections. */
+ if (CLASSTYPE_EXPLICIT_INSTANTIATION (ctype))
+ maybe_make_one_only (decl);
+ }
+ else if (TYPE_BUILT_IN (ctype) && ctype == TYPE_MAIN_VARIANT (ctype))
+ DECL_NOT_REALLY_EXTERN (decl) = 0;
+ else
+ comdat_linkage (decl);
+ }
else
- TREE_PUBLIC (decl) = 0;
+ comdat_linkage (decl);
DECL_INTERFACE_KNOWN (decl) = 1;
}
+tree
+build_cleanup (decl)
+ tree decl;
+{
+ tree temp;
+ tree type = TREE_TYPE (decl);
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ temp = decl;
+ else
+ {
+ mark_addressable (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);
+ return temp;
+}
+
extern int parse_time, varconst_time;
+extern tree pending_templates;
+extern tree maybe_templates;
+
+static tree
+get_sentry (base)
+ tree base;
+{
+ tree sname = get_id_2 ("__sn", base);
+ /* For struct X foo __attribute__((weak)), there is a counter
+ __snfoo. Since base is already an assembler name, sname should
+ be globally unique */
+ tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
+ if (! sentry)
+ {
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ sentry = build_decl (VAR_DECL, sname, integer_type_node);
+ TREE_PUBLIC (sentry) = 1;
+ DECL_ARTIFICIAL (sentry) = 1;
+ TREE_STATIC (sentry) = 1;
+ TREE_USED (sentry) = 1;
+ DECL_COMMON (sentry) = 1;
+ pushdecl_top_level (sentry);
+ cp_finish_decl (sentry, NULL_TREE, NULL_TREE, 0, 0);
+ pop_obstacks ();
+ }
+ return sentry;
+}
+
+/* Start the process of running a particular set of global constructors
+ or destructors. Subroutine of do_[cd]tors. */
+
+static void
+start_objects (method_type)
+ int method_type;
+{
+ tree fnname;
+
+ /* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
+
+ fnname = get_file_function_name (method_type);
+
+ start_function (void_list_node,
+ make_call_declarator (fnname, void_list_node, NULL_TREE,
+ NULL_TREE),
+ NULL_TREE, 0);
+
+#if defined(ASM_OUTPUT_CONSTRUCTOR) && defined(ASM_OUTPUT_DESTRUCTOR)
+ /* It can be a static function as long as collect2 does not have
+ to scan the object file to find its ctor/dtor routine. */
+ TREE_PUBLIC (current_function_decl) = 0;
+#endif
+
+ store_parm_decls ();
+ pushlevel (0);
+ clear_last_expr ();
+ push_momentary ();
+ expand_start_bindings (0);
+}
+
+/* Finish the process of running a particular set of global constructors
+ or destructors. Subroutine of do_[cd]tors. */
-#define TIMEVAR(VAR, BODY) \
-do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0)
+static void
+finish_objects (method_type)
+ int method_type;
+{
+ char *fnname;
+
+ tree list = (method_type == 'I' ? static_ctors : static_dtors);
+
+ if (! current_function_decl && list)
+ start_objects (method_type);
+
+ for (; list; list = TREE_CHAIN (list))
+ expand_expr_stmt (build_function_call (TREE_VALUE (list), NULL_TREE));
+
+ if (! current_function_decl)
+ return;
+
+ fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+
+ /* Finish up. */
+ expand_end_bindings (getdecls (), 1, 0);
+ poplevel (1, 0, 0);
+ pop_momentary ();
+ finish_function (lineno, 0, 0);
+
+ if (method_type == 'I')
+ assemble_constructor (fnname);
+ else
+ assemble_destructor (fnname);
+}
+
+/* Generate a function to run a set of global destructors. Subroutine of
+ finish_file. */
+
+static void
+do_dtors ()
+{
+ tree vars = static_aggregates;
+
+ for (; vars; vars = TREE_CHAIN (vars))
+ {
+ tree decl = TREE_VALUE (vars);
+ tree type = TREE_TYPE (decl);
+ tree temp;
+
+ if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars)
+ && ! DECL_EXTERNAL (decl))
+ {
+ int protect = (TREE_PUBLIC (decl) && (DECL_COMMON (decl)
+ || DECL_ONE_ONLY (decl)
+ || DECL_WEAK (decl)));
+
+ if (! current_function_decl)
+ start_objects ('D');
+
+ temp = build_cleanup (decl);
+
+ if (protect)
+ {
+ tree sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
+ sentry = build_unary_op (PREDECREMENT_EXPR, sentry, 0);
+ sentry = build_binary_op (EQ_EXPR, sentry, integer_zero_node, 1);
+ expand_start_cond (sentry, 0);
+ }
+
+ expand_expr_stmt (temp);
+
+ if (protect)
+ expand_end_cond ();
+ }
+ }
+
+ finish_objects ('D');
+}
+
+/* Generate a function to run a set of global constructors. Subroutine of
+ finish_file. */
+
+static void
+do_ctors ()
+{
+ tree vars = static_aggregates;
+
+ /* Reverse the list so it's in the right order for ctors. */
+ vars = nreverse (vars);
+
+ for (; vars; vars = TREE_CHAIN (vars))
+ {
+ tree decl = TREE_VALUE (vars);
+ tree init = TREE_PURPOSE (vars);
+
+ /* If this was a static attribute within some function's scope,
+ then don't initialize it here. Also, don't bother
+ with initializers that contain errors. */
+ if (TREE_STATIC (vars)
+ || DECL_EXTERNAL (decl)
+ || (init && TREE_CODE (init) == TREE_LIST
+ && value_member (error_mark_node, init)))
+ continue;
+
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ int protect = (TREE_PUBLIC (decl) && (DECL_COMMON (decl)
+ || DECL_ONE_ONLY (decl)
+ || DECL_WEAK (decl)));
+
+ if (! current_function_decl)
+ start_objects ('I');
+
+ /* Set these global variables so that GDB at least puts
+ us near the declaration which required the initialization. */
+ input_filename = DECL_SOURCE_FILE (decl);
+ lineno = DECL_SOURCE_LINE (decl);
+ emit_note (input_filename, lineno);
+
+ /* 9.5p5: The initializer of a static member of a class has
+ the same access rights as a member function. */
+ if (member_p (decl))
+ {
+ DECL_CLASS_CONTEXT (current_function_decl)
+ = DECL_CONTEXT (decl);
+ DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
+ }
+
+ if (protect)
+ {
+ tree sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
+ sentry = build_unary_op (PREINCREMENT_EXPR, sentry, 0);
+ sentry = build_binary_op
+ (EQ_EXPR, sentry, integer_one_node, 1);
+ expand_start_cond (sentry, 0);
+ }
+
+ expand_start_target_temps ();
+
+ if (IS_AGGR_TYPE (TREE_TYPE (decl))
+ || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ expand_aggr_init (decl, init, 0, 0);
+ else 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, EXPAND_NORMAL);
+ }
+ else
+ expand_assignment (decl, init, 0, 0);
+
+ /* The expression might have involved increments and
+ decrements. */
+ emit_queue ();
+
+ /* Cleanup any temporaries needed for the initial value. */
+ expand_end_target_temps ();
+
+ if (protect)
+ expand_end_cond ();
+
+ DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
+ DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
+ }
+ else if (decl == error_mark_node)
+ /* OK */;
+ else
+ my_friendly_abort (22);
+ }
+
+ finish_objects ('I');
+}
/* This routine is called from the last rule in yyparse ().
Its job is to create all the code needed to initialize and
@@ -2838,18 +3144,15 @@ finish_file ()
tree vars;
int needs_cleaning = 0, needs_messing_up = 0;
- if (flag_detailed_statistics)
- dump_tree_statistics ();
+ at_eof = 1;
/* Bad parse errors. Just forget about it. */
if (! global_bindings_p () || current_class_type)
return;
- start_time = get_run_time ();
+ check_decl_namespace ();
- /* Push into C language context, because that's all
- we'll need here. */
- push_lang_context (lang_name_c);
+ start_time = get_run_time ();
/* Otherwise, GDB can get confused, because in only knows
about source for LINENO-1 lines. */
@@ -2858,6 +3161,45 @@ finish_file ()
interface_unknown = 1;
interface_only = 0;
+ for (fnname = pending_templates; fnname; fnname = TREE_CHAIN (fnname))
+ {
+ tree srcloc = TREE_PURPOSE (fnname);
+ tree decl = TREE_VALUE (fnname);
+
+ input_filename = SRCLOC_FILE (srcloc);
+ lineno = SRCLOC_LINE (srcloc);
+
+ if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't')
+ {
+ instantiate_class_template (decl);
+ if (CLASSTYPE_TEMPLATE_INSTANTIATION (decl))
+ for (vars = TYPE_METHODS (decl); vars; vars = TREE_CHAIN (vars))
+ if (! DECL_ARTIFICIAL (vars))
+ instantiate_decl (vars);
+ }
+ else
+ instantiate_decl (decl);
+ }
+
+ for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
+ {
+ tree args, fn, decl = TREE_VALUE (fnname);
+
+ if (DECL_INITIAL (decl))
+ continue;
+
+ fn = TREE_PURPOSE (fnname);
+ args = get_bindings (fn, decl, NULL_TREE);
+ fn = instantiate_template (fn, args);
+ instantiate_decl (fn);
+ }
+
+ cat_namespace_levels();
+
+ /* Push into C language context, because that's all
+ we'll need here. */
+ push_lang_context (lang_name_c);
+
#if 1
/* The reason for pushing garbage onto the global_binding_level is to
ensure that we can slice out _DECLs which pertain to virtual function
@@ -2870,7 +3212,7 @@ finish_file ()
virtual function tables, moving the implementation of this code to
decl.c (where we can manipulate global_binding_level directly),
popping the garbage after pushing it and slicing away the vtable
- stuff, or just leaving it alone. */
+ stuff, or just leaving it alone. */
/* Make last thing in global scope not be a virtual function table. */
#if 0 /* not yet, should get fixed properly later */
@@ -2883,199 +3225,28 @@ finish_file ()
pushdecl (vars);
#endif
- /* Walk to mark the inline functions we need, then output them so
- that we can pick up any other tdecls that those routines need. */
- walk_vtables ((void (*)())0, finish_prevtable_vardecl);
-
+ for (vars = static_aggregates; vars; vars = TREE_CHAIN (vars))
+ if (! TREE_ASM_WRITTEN (TREE_VALUE (vars)))
+ rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1);
vars = static_aggregates;
- if (static_ctors || vars || might_have_exceptions_p ())
+ if (static_ctors || vars)
needs_messing_up = 1;
- if (static_dtors)
+ if (static_dtors || vars)
needs_cleaning = 1;
- /* See if we really need the hassle. */
- while (vars && needs_cleaning == 0)
- {
- tree decl = TREE_VALUE (vars);
- tree type = TREE_TYPE (decl);
- if (TYPE_NEEDS_DESTRUCTOR (type))
- {
- needs_cleaning = 1;
- needs_messing_up = 1;
- break;
- }
- else
- needs_messing_up |= TYPE_NEEDS_CONSTRUCTING (type);
- vars = TREE_CHAIN (vars);
- }
-
- if (needs_cleaning == 0)
- 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),
- NULL_TREE, NULL_TREE, 0);
- fnname = DECL_ASSEMBLER_NAME (current_function_decl);
- store_parm_decls ();
-
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
-
- /* These must be done in backward order to destroy,
- in which they happen to be! */
- for (vars = static_aggregates; vars; vars = TREE_CHAIN (vars))
+ /* The aggregates are listed in reverse declaration order, for cleaning. */
+ if (needs_cleaning)
{
- tree decl = TREE_VALUE (vars);
- tree type = TREE_TYPE (decl);
- tree temp = TREE_PURPOSE (vars);
-
- if (TYPE_NEEDS_DESTRUCTOR (type))
- {
- if (TREE_STATIC (vars))
- expand_start_cond (build_binary_op (NE_EXPR, temp, integer_zero_node, 1), 0);
- if (TREE_CODE (type) == ARRAY_TYPE)
- temp = decl;
- else
- {
- mark_addressable (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);
- expand_expr_stmt (temp);
-
- if (TREE_STATIC (vars))
- expand_end_cond ();
- }
+ do_dtors ();
}
- for (; static_dtors; static_dtors = TREE_CHAIN (static_dtors))
- expand_expr_stmt (build_function_call (TREE_VALUE (static_dtors),
- NULL_TREE));
-
- expand_end_bindings (getdecls(), 1, 0);
- poplevel (1, 0, 0);
- pop_momentary ();
-
- finish_function (lineno, 0, 0);
-
- assemble_destructor (IDENTIFIER_POINTER (fnname));
-
- /* if it needed cleaning, then it will need messing up: drop through */
-
- mess_up:
- /* Must do this while we think we are at the top level. */
- vars = nreverse (static_aggregates);
+ /* do_ctors will reverse the lists for messing up. */
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),
- NULL_TREE, NULL_TREE, 0);
- fnname = DECL_ASSEMBLER_NAME (current_function_decl);
- store_parm_decls ();
-
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
-
- if (might_have_exceptions_p ())
- register_exception_table ();
-
- while (vars)
- {
- tree decl = TREE_VALUE (vars);
- tree init = TREE_PURPOSE (vars);
- tree old_cleanups = cleanups_this_call;
-
- /* If this was a static attribute within some function's scope,
- then don't initialize it here. Also, don't bother
- with initializers that contain errors. */
- if (TREE_STATIC (vars)
- || (init && TREE_CODE (init) == TREE_LIST
- && value_member (error_mark_node, init)))
- {
- vars = TREE_CHAIN (vars);
- continue;
- }
-
- if (TREE_CODE (decl) == VAR_DECL)
- {
- /* Set these global variables so that GDB at least puts
- us near the declaration which required the initialization. */
- input_filename = DECL_SOURCE_FILE (decl);
- lineno = DECL_SOURCE_LINE (decl);
- emit_note (input_filename, lineno);
-
- /* 9.5p5: The initializer of a static member of a class has
- the same access rights as a member function. */
- DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
- DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
-
- if (IS_AGGR_TYPE (TREE_TYPE (decl))
- || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- expand_aggr_init (decl, init, 0, 0);
- else 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_assignment (decl, init, 0, 0);
-
- DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
- }
- else if (TREE_CODE (decl) == SAVE_EXPR)
- {
- if (! PARM_DECL_EXPR (decl))
- {
- /* a `new' expression at top level. */
- expand_expr (decl, const0_rtx, VOIDmode, 0);
- free_temp_slots ();
- 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)
- ;
- else my_friendly_abort (22);
- vars = TREE_CHAIN (vars);
- /* Cleanup any temporaries needed for the initial value. */
- expand_cleanups_to (old_cleanups);
- }
-
- for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors))
- expand_expr_stmt (build_function_call (TREE_VALUE (static_ctors),
- NULL_TREE));
-
- expand_end_bindings (getdecls(), 1, 0);
- poplevel (1, 0, 0);
- pop_momentary ();
-
- finish_function (lineno, 0, 0);
- assemble_constructor (IDENTIFIER_POINTER (fnname));
+ do_ctors ();
}
- expand_builtin_throw ();
-
permanent_allocation (1);
/* Done with C language context needs. */
@@ -3086,10 +3257,21 @@ finish_file ()
while (pending_statics)
{
tree decl = TREE_VALUE (pending_statics);
- if (TREE_USED (decl) == 1
- || TREE_READONLY (decl) == 0
- || DECL_INITIAL (decl) == 0)
- rest_of_decl_compilation (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1);
+
+ /* Output DWARF debug information. */
+#ifdef DWARF_DEBUGGING_INFO
+ if (write_symbols == DWARF_DEBUG)
+ dwarfout_file_scope_decl (decl, 1);
+#endif
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ dwarf2out_decl (decl);
+#endif
+
+ DECL_DEFER_OUTPUT (decl) = 0;
+ rest_of_decl_compilation
+ (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1);
+
pending_statics = TREE_CHAIN (pending_statics);
}
@@ -3100,18 +3282,17 @@ finish_file ()
start_time = get_run_time ();
if (flag_handle_signatures)
- walk_sigtables ((void (*)())0, finish_sigtable_vardecl);
+ walk_sigtables ((void (*) PROTO ((tree, tree))) 0,
+ finish_sigtable_vardecl);
for (fnname = saved_inlines; fnname; fnname = TREE_CHAIN (fnname))
{
tree decl = TREE_VALUE (fnname);
- import_export_inline (decl);
- if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
- && TREE_PUBLIC (decl) && ! DECL_WEAK (decl)
- && DECL_NOT_REALLY_EXTERN (decl))
- synthesize_method (decl);
+ import_export_decl (decl);
}
+ mark_all_runtime_matches ();
+
/* Now write out inline functions which had their addresses taken and
which were not declared virtual and which were not declared `extern
inline'. */
@@ -3120,87 +3301,92 @@ finish_file ()
while (reconsider)
{
- tree last = saved_inlines = tree_cons (NULL_TREE, NULL_TREE,
- saved_inlines);
- tree last_head = last;
- tree place = TREE_CHAIN (saved_inlines);
+ tree *p = &saved_inlines;
reconsider = 0;
- walk_vtables ((void (*)())0, finish_vtable_vardecl);
+ /* We need to do this each time so that newly completed template
+ types don't wind up at the front of the list. Sigh. */
+ vars = build_decl (TYPE_DECL, make_anon_name (), integer_type_node);
+ DECL_IGNORED_P (vars) = 1;
+ SET_DECL_ARTIFICIAL (vars);
+ pushdecl (vars);
- for (; place; place = TREE_CHAIN (place))
- {
- tree decl = TREE_VALUE (place);
+ reconsider |= walk_vtables ((void (*) PROTO((tree, tree))) 0,
+ finish_vtable_vardecl);
- /* Slice out the empty elements put in just above in the
- previous reconsidering. */
- if (decl == NULL_TREE)
- {
- TREE_CHAIN (last) = TREE_CHAIN (place);
- continue;
- }
+ while (*p)
+ {
+ tree decl = TREE_VALUE (*p);
- if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl))
+ if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
+ && TREE_USED (decl)
+ && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
{
- if (TREE_USED (decl))
- {
- synthesize_method (decl);
- if (TREE_ASM_WRITTEN (decl))
- reconsider = 1;
- }
+ if (DECL_MUTABLE_P (decl))
+ synthesize_tinfo_fn (decl);
else
- {
- last = place;
- continue;
- }
+ synthesize_method (decl);
+ reconsider = 1;
}
- if (TREE_ASM_WRITTEN (decl) || DECL_SAVED_INSNS (decl) == 0)
- {
- TREE_CHAIN (last) = TREE_CHAIN (place);
- continue;
- }
+ /* Catch new template instantiations. */
+ if (decl != TREE_VALUE (*p))
+ continue;
- if ((TREE_PUBLIC (decl) && ! DECL_WEAK (decl))
- || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
- || flag_keep_inline_functions)
+ if (TREE_ASM_WRITTEN (decl)
+ || (DECL_SAVED_INSNS (decl) == 0 && ! DECL_ARTIFICIAL (decl)))
+ *p = TREE_CHAIN (*p);
+ else if (DECL_INITIAL (decl) == 0)
+ p = &TREE_CHAIN (*p);
+ else if ((TREE_PUBLIC (decl) && ! DECL_COMDAT (decl))
+ || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
+ || flag_keep_inline_functions)
{
- TREE_CHAIN (last) = TREE_CHAIN (place);
-
if (DECL_NOT_REALLY_EXTERN (decl))
{
DECL_EXTERNAL (decl) = 0;
reconsider = 1;
- temporary_allocation ();
+ /* We can't inline this function after it's been
+ emitted. We want a variant of
+ output_inline_function that doesn't prevent
+ subsequent integration... */
+ DECL_INLINE (decl) = 0;
output_inline_function (decl);
permanent_allocation (1);
}
- continue;
+ *p = TREE_CHAIN (*p);
}
-
- last = place;
+ else
+ p = &TREE_CHAIN (*p);
}
}
+
+ /* It's possible that some of the remaining inlines will still be
+ needed. For example, a static inline whose address is used in
+ the initializer for a file-scope static variable will be
+ needed. Code in compile_file will handle this, but we mustn't
+ pretend that there are no definitions for the inlines, or it
+ won't be able to.
+
+ FIXME: This won't catch member functions. We should really
+ unify this stuff with the compile_file stuff. */
+ for (vars = saved_inlines; vars != NULL_TREE; vars = TREE_CHAIN (vars))
+ {
+ tree decl = TREE_VALUE (vars);
+
+ if (DECL_NOT_REALLY_EXTERN (decl)
+ && !DECL_COMDAT (decl)
+ && DECL_INITIAL (decl) != NULL_TREE)
+ DECL_EXTERNAL (decl) = 0;
+ }
}
/* Now delete from the chain of variables all virtual function tables.
We output them all ourselves, because each will be treated specially. */
- walk_vtables ((void (*)())0, prune_vtable_vardecl);
-
- for (vars = getdecls (); vars; vars = TREE_CHAIN (vars))
- {
- if (TREE_CODE (vars) == THUNK_DECL)
- emit_thunk (vars);
- else if (TREE_CODE (vars) == FUNCTION_DECL
- && ! DECL_INTERFACE_KNOWN (vars)
- && DECL_C_STATIC (vars))
- TREE_PUBLIC (vars) = 0;
- }
-
- if (might_have_exceptions_p ())
- emit_exception_table ();
+ walk_vtables ((void (*) PROTO((tree, tree))) 0,
+ prune_vtable_vardecl);
if (write_virtuals == 2)
{
@@ -3222,7 +3408,10 @@ finish_file ()
varconst_time += this_time - start_time;
if (flag_detailed_statistics)
- dump_time_statistics ();
+ {
+ dump_tree_statistics ();
+ dump_time_statistics ();
+ }
}
/* This is something of the form 'A()()()()()+1' that has turned out to be an
@@ -3233,6 +3422,7 @@ finish_file ()
Maybe this shouldn't be recursive, but how often will it actually be
used? (jason) */
+
tree
reparse_absdcl_as_expr (type, decl)
tree type, decl;
@@ -3244,7 +3434,7 @@ reparse_absdcl_as_expr (type, decl)
/* recurse */
decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0));
- decl = build_x_function_call (decl, NULL_TREE, current_class_decl);
+ decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node)
decl = require_complete_type (decl);
@@ -3259,13 +3449,15 @@ reparse_absdcl_as_expr (type, decl)
In the above example, DECL is the `(int)(int)(int)', and EXPR is the
`1'. */
+
tree
reparse_absdcl_as_casts (decl, expr)
tree decl, expr;
{
tree type;
- if (TREE_CODE (expr) == CONSTRUCTOR)
+ if (TREE_CODE (expr) == CONSTRUCTOR
+ && TREE_TYPE (expr) == 0)
{
type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
decl = TREE_OPERAND (decl, 0);
@@ -3289,62 +3481,298 @@ reparse_absdcl_as_casts (decl, expr)
{
type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
decl = TREE_OPERAND (decl, 0);
- expr = build_c_cast (type, expr, 0);
+ expr = build_c_cast (type, expr);
}
+ if (warn_old_style_cast)
+ warning ("use of old-style cast");
+
return expr;
}
-/* Recursive helper function for reparse_decl_as_expr. It may be a good
- idea to reimplement this using an explicit stack, rather than recursion. */
-static tree
-reparse_decl_as_expr1 (decl)
- tree decl;
+/* Given plain tree nodes for an expression, build up the full semantics. */
+
+tree
+build_expr_from_tree (t)
+ tree t;
{
- switch (TREE_CODE (decl))
+ if (t == NULL_TREE || t == error_mark_node)
+ return t;
+
+ switch (TREE_CODE (t))
{
case IDENTIFIER_NODE:
- return do_identifier (decl);
+ return do_identifier (t, 0, NULL_TREE);
+
+ case LOOKUP_EXPR:
+ if (LOOKUP_EXPR_GLOBAL (t))
+ return do_scoped_id (TREE_OPERAND (t, 0), 0);
+ else
+ return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE);
+
+ case TEMPLATE_ID_EXPR:
+ return (lookup_template_function
+ (build_expr_from_tree (TREE_OPERAND (t, 0)),
+ build_expr_from_tree (TREE_OPERAND (t, 1))));
+
case INDIRECT_REF:
return build_x_indirect_ref
- (reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)), "unary *");
- case ADDR_EXPR:
- return build_x_unary_op (ADDR_EXPR,
- reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)));
+ (build_expr_from_tree (TREE_OPERAND (t, 0)), "unary *");
+
+ case CAST_EXPR:
+ return build_functional_cast
+ (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+ case REINTERPRET_CAST_EXPR:
+ return build_reinterpret_cast
+ (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+ case CONST_CAST_EXPR:
+ return build_const_cast
+ (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+ case DYNAMIC_CAST_EXPR:
+ return build_dynamic_cast
+ (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+ case STATIC_CAST_EXPR:
+ return build_static_cast
+ (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case NEGATE_EXPR:
case BIT_NOT_EXPR:
- return build_x_unary_op (BIT_NOT_EXPR,
- reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)));
+ case ABS_EXPR:
+ case TRUTH_NOT_EXPR:
+ case ADDR_EXPR:
+ case CONVERT_EXPR: /* Unary + */
+ if (TREE_TYPE (t))
+ return t;
+ return build_x_unary_op (TREE_CODE (t),
+ build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case EXACT_DIV_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_ANDTC_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case TRUNC_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case RSHIFT_EXPR:
+ case LSHIFT_EXPR:
+ case RROTATE_EXPR:
+ case LROTATE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ case MAX_EXPR:
+ case MIN_EXPR:
+ case LE_EXPR:
+ case GE_EXPR:
+ case LT_EXPR:
+ case GT_EXPR:
+ case MEMBER_REF:
+ return build_x_binary_op
+ (TREE_CODE (t),
+ build_expr_from_tree (TREE_OPERAND (t, 0)),
+ build_expr_from_tree (TREE_OPERAND (t, 1)));
+
+ case DOTSTAR_EXPR:
+ return build_m_component_ref
+ (build_expr_from_tree (TREE_OPERAND (t, 0)),
+ build_expr_from_tree (TREE_OPERAND (t, 1)));
+
case SCOPE_REF:
- return build_offset_ref (TREE_OPERAND (decl, 0), TREE_OPERAND (decl, 1));
+ return build_offset_ref (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
+
case ARRAY_REF:
- return grok_array_decl (reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)),
- TREE_OPERAND (decl, 1));
+ if (TREE_OPERAND (t, 0) == NULL_TREE)
+ /* new-type-id */
+ return build_parse_node (ARRAY_REF, NULL_TREE,
+ build_expr_from_tree (TREE_OPERAND (t, 1)));
+ return grok_array_decl (build_expr_from_tree (TREE_OPERAND (t, 0)),
+ build_expr_from_tree (TREE_OPERAND (t, 1)));
+
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ {
+ tree r = build_expr_from_tree (TREE_OPERAND (t, 0));
+ if (TREE_CODE_CLASS (TREE_CODE (r)) != 't')
+ r = TREE_TYPE (r);
+ return TREE_CODE (t) == SIZEOF_EXPR ? c_sizeof (r) : c_alignof (r);
+ }
+
+ case MODOP_EXPR:
+ return build_x_modify_expr
+ (build_expr_from_tree (TREE_OPERAND (t, 0)),
+ TREE_CODE (TREE_OPERAND (t, 1)),
+ build_expr_from_tree (TREE_OPERAND (t, 2)));
+
+ case ARROW_EXPR:
+ return build_x_arrow
+ (build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+ case NEW_EXPR:
+ return build_new
+ (build_expr_from_tree (TREE_OPERAND (t, 0)),
+ build_expr_from_tree (TREE_OPERAND (t, 1)),
+ build_expr_from_tree (TREE_OPERAND (t, 2)),
+ NEW_EXPR_USE_GLOBAL (t));
+
+ case DELETE_EXPR:
+ return delete_sanity
+ (build_expr_from_tree (TREE_OPERAND (t, 0)),
+ build_expr_from_tree (TREE_OPERAND (t, 1)),
+ DELETE_EXPR_USE_VEC (t), DELETE_EXPR_USE_GLOBAL (t));
+
+ case COMPOUND_EXPR:
+ if (TREE_OPERAND (t, 1) == NULL_TREE)
+ return build_x_compound_expr
+ (build_expr_from_tree (TREE_OPERAND (t, 0)));
+ else
+ my_friendly_abort (42);
+
+ case METHOD_CALL_EXPR:
+ if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
+ {
+ tree ref = TREE_OPERAND (t, 0);
+ return build_scoped_method_call
+ (build_expr_from_tree (TREE_OPERAND (t, 1)),
+ build_expr_from_tree (TREE_OPERAND (ref, 0)),
+ TREE_OPERAND (ref, 1),
+ build_expr_from_tree (TREE_OPERAND (t, 2)));
+ }
+ return build_method_call
+ (build_expr_from_tree (TREE_OPERAND (t, 1)),
+ TREE_OPERAND (t, 0),
+ build_expr_from_tree (TREE_OPERAND (t, 2)),
+ NULL_TREE, LOOKUP_NORMAL);
+
+ case CALL_EXPR:
+ if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
+ {
+ tree ref = TREE_OPERAND (t, 0);
+ return build_member_call
+ (build_expr_from_tree (TREE_OPERAND (ref, 0)),
+ TREE_OPERAND (ref, 1),
+ build_expr_from_tree (TREE_OPERAND (t, 1)));
+ }
+ else
+ {
+ tree name = TREE_OPERAND (t, 0);
+ tree id;
+ tree args = build_expr_from_tree (TREE_OPERAND (t, 1));
+ if (args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR
+ && !LOOKUP_EXPR_GLOBAL (name)
+ && TREE_CODE ((id = TREE_OPERAND (name, 0))) == IDENTIFIER_NODE
+ && (!current_class_type
+ || !lookup_member (current_class_type, id, 0, 0)))
+ {
+ /* Do Koenig lookup if there are no class members. */
+ name = do_identifier (id, 0, args);
+ }
+ else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
+ || ! really_overloaded_fn (name))
+ name = build_expr_from_tree (name);
+ return build_x_function_call (name, args, current_class_ref);
+ }
+
+ case COND_EXPR:
+ return build_x_conditional_expr
+ (build_expr_from_tree (TREE_OPERAND (t, 0)),
+ build_expr_from_tree (TREE_OPERAND (t, 1)),
+ build_expr_from_tree (TREE_OPERAND (t, 2)));
+
+ case TREE_LIST:
+ {
+ tree purpose, value, chain;
+
+ if (t == void_list_node)
+ return t;
+
+ purpose = TREE_PURPOSE (t);
+ if (purpose)
+ purpose = build_expr_from_tree (purpose);
+ value = TREE_VALUE (t);
+ if (value)
+ value = build_expr_from_tree (value);
+ chain = TREE_CHAIN (t);
+ if (chain && chain != void_type_node)
+ chain = build_expr_from_tree (chain);
+ return expr_tree_cons (purpose, value, chain);
+ }
+
+ case COMPONENT_REF:
+ return build_x_component_ref
+ (build_expr_from_tree (TREE_OPERAND (t, 0)),
+ TREE_OPERAND (t, 1), NULL_TREE, 1);
+
+ case THROW_EXPR:
+ return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+ case CONSTRUCTOR:
+ {
+ tree r;
+
+ /* digest_init will do the wrong thing if we let it. */
+ if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
+ return t;
+
+ r = build_nt (CONSTRUCTOR, NULL_TREE,
+ build_expr_from_tree (CONSTRUCTOR_ELTS (t)));
+
+ if (TREE_TYPE (t))
+ return digest_init (TREE_TYPE (t), r, 0);
+ return r;
+ }
+
+ case TYPEID_EXPR:
+ if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't')
+ return get_typeid (TREE_OPERAND (t, 0));
+ return build_x_typeid (build_expr_from_tree (TREE_OPERAND (t, 0)));
+
+ case VAR_DECL:
+ return convert_from_reference (t);
+
default:
- my_friendly_abort (5);
- return NULL_TREE;
+ return t;
}
}
/* This is something of the form `int (*a)++' that has turned out to be an
expr. It was only converted into parse nodes, so we need to go through
and build up the semantics. Most of the work is done by
- reparse_decl_as_expr1, above.
+ build_expr_from_tree, above.
In the above example, TYPE is `int' and DECL is `*a'. */
+
tree
reparse_decl_as_expr (type, decl)
tree type, decl;
{
- decl = reparse_decl_as_expr1 (decl);
+ decl = build_expr_from_tree (decl);
if (type)
- return build_functional_cast (type, build_tree_list (NULL_TREE, decl));
+ return build_functional_cast (type, build_expr_list (NULL_TREE, decl));
else
return decl;
}
/* This is something of the form `int (*a)' that has turned out to be a
decl. It was only converted into parse nodes, so we need to do the
- checking that make_{pointer,reference}_declarator do. */
+ checking that make_{pointer,reference}_declarator do. */
tree
finish_decl_parsing (decl)
@@ -3385,20 +3813,13 @@ check_cp_case_value (value)
if (value == NULL_TREE)
return value;
- /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.
- Strip such NOP_EXPRs. */
- if (TREE_CODE (value) == NOP_EXPR
- && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
- value = TREE_OPERAND (value, 0);
+ /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
+ STRIP_TYPE_NOPS (value);
if (TREE_READONLY_DECL_P (value))
{
value = decl_constant_value (value);
- /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.
- Strip such NOP_EXPRs. */
- if (TREE_CODE (value) == NOP_EXPR
- && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
- value = TREE_OPERAND (value, 0);
+ STRIP_TYPE_NOPS (value);
}
value = fold (value);
@@ -3418,81 +3839,832 @@ check_cp_case_value (value)
return value;
}
-tree current_namespace;
+/* Return 1 if root encloses child. */
-/* Get the inner part of a namespace id. It doesn't have any prefix, nor
- postfix. Returns 0 if in global namespace. */
-tree
-get_namespace_id ()
+static int
+is_namespace_ancestor (root, child)
+ tree root, child;
{
- tree x = current_namespace;
- if (x)
- x = TREE_PURPOSE (x);
- return x;
+ if (root == child)
+ return 1;
+ if (root == global_namespace)
+ return 1;
+ if (child == global_namespace)
+ return 0;
+ return is_namespace_ancestor (root, CP_DECL_CONTEXT (child));
}
+
+
+/* Return the namespace that is the common ancestor
+ of two given namespaces. */
-/* Build up a DECL_ASSEMBLER_NAME for NAME in the current namespace. */
tree
-current_namespace_id (name)
+namespace_ancestor (ns1, ns2)
+ tree ns1, ns2;
+{
+ if (is_namespace_ancestor (ns1, ns2))
+ return ns1;
+ return namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2);
+}
+
+/* Insert used into the using list of user. Set indirect_flag if this
+ directive is not directly from the source. Also find the common
+ ancestor and let our users know about the new namespace */
+static void
+add_using_namespace (user, used, indirect)
+ tree user;
+ tree used;
+ int indirect;
+{
+ tree t;
+ /* Using oneself is a no-op. */
+ if (user == used)
+ return;
+ my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
+ my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
+ /* Check if we already have this. */
+ t = purpose_member (used, DECL_NAMESPACE_USING (user));
+ if (t != NULL_TREE)
+ {
+ if (!indirect)
+ /* Promote to direct usage. */
+ TREE_INDIRECT_USING (t) = 0;
+ return;
+ }
+
+ /* Add used to the user's using list. */
+ DECL_NAMESPACE_USING (user)
+ = perm_tree_cons (used, namespace_ancestor (user, used),
+ DECL_NAMESPACE_USING (user));
+
+ TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
+
+ /* Add user to the used's users list. */
+ DECL_NAMESPACE_USERS (used)
+ = perm_tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
+
+ /* Recursively add all namespaces used. */
+ for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
+ /* indirect usage */
+ add_using_namespace (user, TREE_PURPOSE (t), 1);
+
+ /* Tell everyone using us about the new used namespaces. */
+ for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
+ add_using_namespace (TREE_PURPOSE (t), used, 1);
+}
+
+/* Combines two sets of overloaded functions into an OVERLOAD chain, removing
+ duplicates. The first list becomes the tail of the result.
+
+ The algorithm is O(n^2). */
+
+static tree
+merge_functions (s1, s2)
+ tree s1;
+ tree s2;
+{
+ for (; s2; s2 = OVL_NEXT (s2))
+ {
+ tree fn = OVL_CURRENT (s2);
+ if (! ovl_member (fn, s1))
+ s1 = build_overload (fn, s1);
+ }
+ return s1;
+}
+
+/* This should return an error not all definitions define functions.
+ It is not an error if we find two functions with exactly the
+ same signature, only if these are selected in overload resolution.
+ old is the current set of bindings, new the freshly-found binding.
+ XXX Do we want to give *all* candidates in case of ambiguity?
+ XXX In what way should I treat extern declarations?
+ XXX I don't want to repeat the entire duplicate_decls here */
+
+static tree
+ambiguous_decl (name, old, new, flags)
tree name;
+ tree old;
+ tree new;
+ int flags;
{
- tree old_id = get_namespace_id ();
- char *buf;
+ tree val, type;
+ my_friendly_assert (old != NULL_TREE, 393);
+ /* Copy the value. */
+ val = BINDING_VALUE (new);
+ if (val)
+ switch (TREE_CODE (val))
+ {
+ case TEMPLATE_DECL:
+ /* If we expect types or namespaces, and not templates,
+ or this is not a template class. */
+ if (LOOKUP_QUALIFIERS_ONLY (flags)
+ && (!(flags & LOOKUP_TEMPLATES_EXPECTED)
+ || !DECL_CLASS_TEMPLATE_P (val)))
+ val = NULL_TREE;
+ break;
+ case TYPE_DECL:
+ if (LOOKUP_NAMESPACES_ONLY (flags))
+ val = NULL_TREE;
+ break;
+ case NAMESPACE_DECL:
+ if (LOOKUP_TYPES_ONLY (flags))
+ val = NULL_TREE;
+ break;
+ default:
+ if (LOOKUP_QUALIFIERS_ONLY (flags))
+ val = NULL_TREE;
+ }
+
+ if (!BINDING_VALUE (old))
+ BINDING_VALUE (old) = val;
+ else if (val && val != BINDING_VALUE (old))
+ {
+ if (is_overloaded_fn (BINDING_VALUE (old))
+ && is_overloaded_fn (val))
+ {
+ BINDING_VALUE (old) = merge_functions (BINDING_VALUE (old),
+ val);
+ }
+ else
+ {
+ /* Some declarations are functions, some are not. */
+ if (flags & LOOKUP_COMPLAIN)
+ {
+ cp_error ("use of `%D' is ambiguous", name);
+ cp_error_at (" first declared as `%#D' here",
+ BINDING_VALUE (old));
+ cp_error_at (" also declared as `%#D' here", val);
+ }
+ return error_mark_node;
+ }
+ }
+ /* ... and copy the type. */
+ type = BINDING_TYPE (new);
+ if (LOOKUP_NAMESPACES_ONLY (flags))
+ type = NULL_TREE;
+ if (!BINDING_TYPE (old))
+ BINDING_TYPE (old) = type;
+ else if (type && BINDING_TYPE (old) != type)
+ {
+ if (flags & LOOKUP_COMPLAIN)
+ {
+ cp_error ("`%D' denotes an ambiguous type",name);
+ cp_error_at (" first type here", BINDING_TYPE (old));
+ cp_error_at (" other type here", type);
+ }
+ }
+ return old;
+}
- /* Global names retain old encoding. */
- if (! old_id)
- return name;
+/* Add the bindings of name in used namespaces to val.
+ The using list is defined by usings, and the lookup goes to scope.
+ Returns zero on errors. */
- buf = (char *) alloca (8 + IDENTIFIER_LENGTH (old_id)
- + IDENTIFIER_LENGTH (name));
- sprintf (buf, "__ns_%s_%s", IDENTIFIER_POINTER (old_id),
- IDENTIFIER_POINTER (name));
- return get_identifier (buf);
+int
+lookup_using_namespace (name, val, usings, scope, flags)
+ tree name, val, usings, scope;
+ int flags;
+{
+ tree iter;
+ tree val1;
+ /* Iterate over all used namespaces in current, searching for using
+ directives of scope. */
+ for (iter = usings; iter; iter = TREE_CHAIN (iter))
+ if (TREE_VALUE (iter) == scope)
+ {
+ val1 = binding_for_name (name, TREE_PURPOSE (iter));
+ /* Resolve ambiguities. */
+ val = ambiguous_decl (name, val, val1, flags);
+ }
+ return val != error_mark_node;
}
+/* [namespace.qual]
+ Excepts the name to lookup and its qualifying scope.
+ Returns the name/type pair found into the CPLUS_BINDING result,
+ or 0 on error. */
+
+int
+qualified_lookup_using_namespace (name, scope, result, flags)
+ tree name;
+ tree scope;
+ tree result;
+ int flags;
+{
+ /* Maintain a list of namespaces visited... */
+ tree seen = NULL_TREE;
+ /* ... and a list of namespace yet to see. */
+ tree todo = NULL_TREE;
+ tree usings;
+ while (scope && (result != error_mark_node))
+ {
+ seen = temp_tree_cons (scope, NULL_TREE, seen);
+ result = ambiguous_decl (name, result,
+ binding_for_name (name, scope), flags);
+ if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
+ /* Consider using directives. */
+ for (usings = DECL_NAMESPACE_USING (scope); usings;
+ usings = TREE_CHAIN (usings))
+ /* If this was a real directive, and we have not seen it. */
+ if (!TREE_INDIRECT_USING (usings)
+ && !purpose_member (TREE_PURPOSE (usings), seen))
+ todo = temp_tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
+ if (todo)
+ {
+ scope = TREE_PURPOSE (todo);
+ todo = TREE_CHAIN (todo);
+ }
+ else
+ scope = NULL_TREE; /* If there never was a todo list. */
+ }
+ return result != error_mark_node;
+}
+
+/* [namespace.memdef]/2 */
+
+/* Set the context of a declaration to scope. Complain if we are not
+ outside scope. */
+
+void
+set_decl_namespace (decl, scope)
+ tree decl;
+ tree scope;
+{
+ tree old;
+ if (scope == std_node)
+ scope = global_namespace;
+ /* Get rid of namespace aliases. */
+ scope = ORIGINAL_NAMESPACE (scope);
+
+ if (!is_namespace_ancestor (current_namespace, scope))
+ cp_error ("declaration of `%D' not in a namespace surrounding `%D'",
+ decl, scope);
+ DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
+ if (scope != current_namespace)
+ {
+ /* See whether this has been declared in the namespace. */
+ old = namespace_binding (DECL_NAME (decl), scope);
+ if (!old)
+ /* No old declaration at all. */
+ goto complain;
+ if (!is_overloaded_fn (decl))
+ /* Don't compare non-function decls with decls_match here,
+ since it can't check for the correct constness at this
+ point. pushdecl will find those errors later. */
+ return;
+ /* Since decl is a function, old should contain a function decl. */
+ if (!is_overloaded_fn (old))
+ goto complain;
+ for (; old; old = OVL_NEXT (old))
+ if (decls_match (decl, OVL_CURRENT (old)))
+ return;
+ }
+ else
+ return;
+ complain:
+ cp_error ("`%D' should have been declared inside `%D'",
+ decl, scope);
+}
+
+/* Compute the namespace where a declaration is defined. */
+
+tree
+decl_namespace (decl)
+ tree decl;
+{
+ while (DECL_CONTEXT (decl))
+ {
+ decl = DECL_CONTEXT (decl);
+ if (TREE_CODE (decl) == NAMESPACE_DECL)
+ return decl;
+ if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't')
+ decl = TYPE_STUB_DECL (decl);
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 390);
+ }
+
+ return global_namespace;
+}
+
+/* Return the namespace where the current declaration is declared. */
+
+tree
+current_decl_namespace ()
+{
+ tree result;
+ /* If we have been pushed into a different namespace, use it. */
+ if (decl_namespace_list)
+ return TREE_PURPOSE (decl_namespace_list);
+
+ if (current_class_type)
+ result = decl_namespace (TYPE_STUB_DECL (current_class_type));
+ else if (current_function_decl)
+ result = decl_namespace (current_function_decl);
+ else
+ result = current_namespace;
+ return result;
+}
+
+/* Temporarily set the namespace for the current declaration. */
+
+void
+push_decl_namespace (decl)
+ tree decl;
+{
+ if (TREE_CODE (decl) != NAMESPACE_DECL)
+ decl = decl_namespace (decl);
+ decl_namespace_list = tree_cons (decl, NULL_TREE, decl_namespace_list);
+}
+
+void
+pop_decl_namespace ()
+{
+ decl_namespace_list = TREE_CHAIN (decl_namespace_list);
+}
+
+static void
+check_decl_namespace ()
+{
+ my_friendly_assert (decl_namespace_list == NULL_TREE, 980711);
+}
+
+/* [basic.lookup.koenig] */
+/* A non-zero return value in the functions below indicates an error.
+ All nodes allocated in the procedure are on the scratch obstack. */
+
+struct arg_lookup
+{
+ tree name;
+ tree namespaces;
+ tree classes;
+ tree functions;
+};
+
+static int arg_assoc PROTO((struct arg_lookup*, tree));
+static int arg_assoc_args PROTO((struct arg_lookup*, tree));
+
+/* Add a function to the lookup structure.
+ Returns 1 on error. */
+
+static int
+add_function (k, fn)
+ struct arg_lookup *k;
+ tree fn;
+{
+ if (ovl_member (fn, k->functions))
+ return 0;
+ /* We must find only functions, or exactly one non-function. */
+ if (k->functions && is_overloaded_fn (k->functions)
+ && is_overloaded_fn (fn))
+ k->functions = build_overload (fn, k->functions);
+ else
+ if(k->functions)
+ {
+ tree f1 = OVL_CURRENT (k->functions);
+ tree f2 = fn;
+ if (is_overloaded_fn (f1))
+ {
+ fn = f1; f1 = f2; f2 = fn;
+ }
+ cp_error_at ("`%D' is not a function,", f1);
+ cp_error_at (" conflict with `%D'", f2);
+ cp_error (" in call to `%D'", k->name);
+ return 1;
+ }
+ else
+ k->functions = fn;
+ return 0;
+}
+
+/* Add functions of a namespace to the lookup structure.
+ Returns 1 on error. */
+
+static int
+arg_assoc_namespace (k, scope)
+ struct arg_lookup *k;
+ tree scope;
+{
+ tree value;
+
+ if (purpose_member (scope, k->namespaces))
+ return 0;
+ k->namespaces = tree_cons (scope, NULL_TREE, k->namespaces);
+
+ value = namespace_binding (k->name, scope);
+ if (!value)
+ return 0;
+
+ for (; value; value = OVL_NEXT (value))
+ if (add_function (k, OVL_CURRENT (value)))
+ return 1;
+
+ return 0;
+}
+
+/* Adds everything associated with class to the lookup structure.
+ Returns 1 on error. */
+
+static int
+arg_assoc_class (k, type)
+ struct arg_lookup* k;
+ tree type;
+{
+ tree list, friends, context;
+ int i;
+
+ if (purpose_member (type, k->classes))
+ return 0;
+ k->classes = tree_cons (type, NULL_TREE, k->classes);
+
+ context = decl_namespace (TYPE_MAIN_DECL (type));
+ if (arg_assoc_namespace (k, context))
+ return 1;
+
+ /* Process baseclasses. */
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++)
+ if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i)))
+ return 1;
+
+ /* Process friends. */
+ for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
+ list = TREE_CHAIN (list))
+ if (k->name == TREE_PURPOSE (list))
+ for (friends = TREE_VALUE (list); friends;
+ friends = TREE_CHAIN (friends))
+ /* Only interested in global functions with potentially hidden
+ (i.e. unqualified) declarations. */
+ if (TREE_PURPOSE (list) == error_mark_node && TREE_VALUE (list)
+ && decl_namespace (TREE_VALUE (list)) == context)
+ if (add_function (k, TREE_VALUE (list)))
+ return 1;
+
+ /* Process template arguments. */
+ if (CLASSTYPE_TEMPLATE_INFO (type))
+ {
+ list = innermost_args (CLASSTYPE_TI_ARGS (type), 0);
+ for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
+ arg_assoc (k, TREE_VEC_ELT (list, i));
+ }
+
+ return 0;
+}
+
+/* Adds everything associated with a given type.
+ Returns 1 on error. */
+
+static int
+arg_assoc_type (k, type)
+ struct arg_lookup *k;
+ tree type;
+{
+ switch (TREE_CODE (type))
+ {
+ case VOID_TYPE:
+ case INTEGER_TYPE:
+ case REAL_TYPE:
+ case COMPLEX_TYPE:
+ case CHAR_TYPE:
+ case BOOLEAN_TYPE:
+ return 0;
+ case RECORD_TYPE:
+ if (TYPE_PTRMEMFUNC_P (type))
+ return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type));
+ return arg_assoc_class (k, type);
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ case ARRAY_TYPE:
+ return arg_assoc_type (k, TREE_TYPE (type));
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type)));
+ case OFFSET_TYPE:
+ /* Pointer to member: associate class type and value type. */
+ if (arg_assoc_type (k, TYPE_OFFSET_BASETYPE (type)))
+ return 1;
+ return arg_assoc_type (k, TREE_TYPE (type));
+ case METHOD_TYPE:
+ /* The basetype is referenced in the first arg type, so just
+ fall through. */
+ case FUNCTION_TYPE:
+ /* Associate the parameter types. */
+ if (arg_assoc_args (k, TYPE_ARG_TYPES (type)))
+ return 1;
+ /* Associate the return type. */
+ return arg_assoc_type (k, TREE_TYPE (type));
+ case TEMPLATE_TYPE_PARM:
+ return 0;
+ case LANG_TYPE:
+ if (type == unknown_type_node)
+ return 0;
+ /* else fall through */
+ default:
+ my_friendly_abort (390);
+ }
+ return 0;
+}
+
+/* Adds everything associated with arguments. Returns 1 on error. */
+
+static int
+arg_assoc_args (k, args)
+ struct arg_lookup* k;
+ tree args;
+{
+ for (; args; args = TREE_CHAIN (args))
+ if (arg_assoc (k, TREE_VALUE (args)))
+ return 1;
+ return 0;
+}
+
+/* Adds everything associated with a given tree_node. Returns 1 on error. */
+
+static int
+arg_assoc (k, n)
+ struct arg_lookup* k;
+ tree n;
+{
+ if (n == error_mark_node)
+ return 0;
+
+ if (TREE_CODE_CLASS (TREE_CODE (n)) == 't')
+ return arg_assoc_type (k, n);
+
+ if (! type_unknown_p (n))
+ return arg_assoc_type (k, TREE_TYPE (n));
+
+ if (TREE_CODE (n) == ADDR_EXPR)
+ n = TREE_OPERAND (n, 0);
+ while (TREE_CODE (n) == TREE_LIST)
+ n = TREE_VALUE (n);
+
+ my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
+
+ for (; n; n = TREE_CHAIN (n))
+ if (arg_assoc (k, OVL_FUNCTION (n)))
+ return 1;
+
+ return 0;
+}
+
+/* Performs Koenig lookup depending on arguments, where fns
+ are the functions found in normal lookup. */
+
+tree
+lookup_arg_dependent (name, fns, args)
+ tree name;
+ tree fns;
+ tree args;
+{
+ struct arg_lookup k;
+ k.name = name;
+ k.functions = fns;
+ k.namespaces = NULL_TREE;
+ k.classes = NULL_TREE;
+
+ push_scratch_obstack ();
+ arg_assoc_args (&k, args);
+ pop_obstacks ();
+ return k.functions;
+}
+
+/* Process a namespace-alias declaration. */
+
void
do_namespace_alias (alias, namespace)
tree alias, namespace;
{
+ tree binding;
+ tree old;
+
+ if (TREE_CODE (namespace) != NAMESPACE_DECL)
+ {
+ /* The parser did not find it, so it's not there. */
+ cp_error ("unknown namespace `%D'", namespace);
+ return;
+ }
+
+ namespace = ORIGINAL_NAMESPACE (namespace);
+
+ /* Build the alias. */
+ alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
+ DECL_NAMESPACE_ALIAS (alias) = namespace;
+ pushdecl (alias);
}
-tree
-do_toplevel_using_decl (decl)
+/* Check a non-member using-declaration. Return the name and scope
+ being used, and the USING_DECL, or NULL_TREE on failure. */
+
+static tree
+validate_nonmember_using_decl (decl, scope, name)
tree decl;
+ tree *scope;
+ tree *name;
{
- if (decl == NULL_TREE || decl == error_mark_node)
+ if (TREE_CODE (decl) == SCOPE_REF
+ && TREE_OPERAND (decl, 0) == std_node)
+ {
+ *scope = global_namespace;
+ *name = TREE_OPERAND (decl, 1);
+ }
+ else if (TREE_CODE (decl) == SCOPE_REF)
+ {
+ *scope = TREE_OPERAND (decl, 0);
+ *name = TREE_OPERAND (decl, 1);
+ }
+ else if (TREE_CODE (decl) == IDENTIFIER_NODE
+ || TREE_CODE (decl) == TYPE_DECL)
+ {
+ *scope = global_namespace;
+ *name = decl;
+ }
+ else
+ my_friendly_abort (382);
+ if (TREE_CODE_CLASS (TREE_CODE (*name)) == 'd')
+ *name = DECL_NAME (*name);
+ /* Make a USING_DECL. */
+ return push_using_decl (*scope, *name);
+}
+
+/* Process local and global using-declarations. */
+
+static void
+do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
+ tree scope, name;
+ tree oldval, oldtype;
+ tree *newval, *newtype;
+{
+ tree decls;
+ struct tree_binding _decls;
+
+ *newval = *newtype = NULL_TREE;
+ decls = binding_init (&_decls);
+ if (!qualified_lookup_using_namespace (name, scope, decls, 0))
+ /* Lookup error */
return;
- if (TREE_CODE (decl) == SCOPE_REF)
- decl = resolve_scope_to_name (NULL_TREE, decl);
+ if (!BINDING_VALUE (decls) && !BINDING_TYPE (decls))
+ {
+ cp_error ("`%D' not declared", name);
+ return;
+ }
+
+ /* Check for using functions. */
+ if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls)))
+ {
+ tree tmp, tmp1;
+
+ if (oldval && !is_overloaded_fn (oldval))
+ {
+ duplicate_decls (OVL_CURRENT (BINDING_VALUE (decls)), oldval);
+ oldval = NULL_TREE;
+ }
+
+ *newval = oldval;
+ for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
+ {
+ /* Compare each new function with each old one.
+ If the old function was also used, there is no conflict. */
+ for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
+ if (OVL_CURRENT (tmp) == OVL_CURRENT (tmp1))
+ break;
+ else if (OVL_USED (tmp1))
+ continue;
+ else if (duplicate_decls (OVL_CURRENT (tmp), OVL_CURRENT (tmp1)))
+ return;
+
+ /* Duplicate use, ignore */
+ if (tmp1)
+ continue;
+
+ *newval = build_overload (OVL_CURRENT (tmp), *newval);
+ if (TREE_CODE (*newval) != OVERLOAD)
+ *newval = ovl_cons (*newval, NULL_TREE);
+ OVL_USED (*newval) = 1;
+ }
+ }
+ else
+ {
+ *newval = BINDING_VALUE (decls);
+ if (oldval)
+ duplicate_decls (*newval, oldval);
+ }
- /* Is this the right way to do an id list? */
- if (TREE_CODE (decl) != TREE_LIST)
+ *newtype = BINDING_TYPE (decls);
+ if (oldtype && *newtype && oldtype != *newtype)
{
- pushdecl (decl);
+ cp_error ("using directive `%D' introduced ambiguous type `%T'",
+ name, oldtype);
+ return;
}
- else
- while (decl)
- {
- pushdecl (TREE_VALUE (decl));
- decl = TREE_CHAIN (decl);
- }
+}
+
+/* Process a using-declaration not appearing in class or local scope. */
+
+void
+do_toplevel_using_decl (decl)
+ tree decl;
+{
+ tree scope, name, binding;
+ tree oldval, oldtype, newval, newtype;
+
+ decl = validate_nonmember_using_decl (decl, &scope, &name);
+ if (decl == NULL_TREE)
+ return;
+
+ binding = binding_for_name (name, current_namespace);
+
+ oldval = BINDING_VALUE (binding);
+ oldtype = BINDING_TYPE (binding);
+
+ do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
+
+ /* Copy declarations found. */
+ if (newval)
+ BINDING_VALUE (binding) = newval;
+ if (newtype)
+ BINDING_TYPE (binding) = newtype;
+ return;
+}
+
+/* Process a using-declaration at function scope. */
+
+void
+do_local_using_decl (decl)
+ tree decl;
+{
+ tree scope, name;
+ tree oldval, oldtype, newval, newtype;
+
+ decl = validate_nonmember_using_decl (decl, &scope, &name);
+ if (decl == NULL_TREE)
+ return;
+
+ oldval = lookup_name_current_level (name);
+ oldtype = lookup_type_current_level (name);
+
+ do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
+
+ if (newval)
+ set_identifier_local_value (name, newval);
+ if (newtype)
+ set_identifier_type_value (name, newtype);
}
tree
do_class_using_decl (decl)
tree decl;
{
- tree type;
+ tree name, value;
- /* Ignore for now, unimplemented. */
- return NULL_TREE;
+ if (TREE_CODE (decl) != SCOPE_REF
+ || TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (decl, 0))) != 't')
+ {
+ cp_error ("using-declaration for non-member at class scope");
+ return NULL_TREE;
+ }
+ name = TREE_OPERAND (decl, 1);
+ if (TREE_CODE (name) == BIT_NOT_EXPR)
+ {
+ cp_error ("using-declaration for destructor");
+ return NULL_TREE;
+ }
+ if (TREE_CODE (name) == TYPE_DECL)
+ name = DECL_NAME (name);
+
+ my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
+
+ value = build_lang_field_decl (USING_DECL, name, void_type_node);
+ DECL_INITIAL (value) = TREE_OPERAND (decl, 0);
+ return value;
}
+/* Process a using-directive. */
+
void
do_using_directive (namespace)
tree namespace;
{
+ if (namespace == std_node)
+ return;
+ /* using namespace A::B::C; */
+ if (TREE_CODE (namespace) == SCOPE_REF)
+ namespace = TREE_OPERAND (namespace, 1);
+ if (TREE_CODE (namespace) == IDENTIFIER_NODE)
+ {
+ /* Lookup in lexer did not find a namespace. */
+ cp_error ("namespace `%T' undeclared", namespace);
+ return;
+ }
+ if (TREE_CODE (namespace) != NAMESPACE_DECL)
+ {
+ cp_error ("`%T' is not a namespace", namespace);
+ return;
+ }
+ namespace = ORIGINAL_NAMESPACE (namespace);
+ if (!toplevel_bindings_p ())
+ push_using_directive (namespace);
+ else
+ /* direct usage */
+ add_using_namespace (current_namespace, namespace, 0);
}
void
@@ -3507,9 +4679,46 @@ check_default_args (x)
saw_def = 1;
else if (saw_def)
{
- cp_error ("default argument missing for parameter %P of `%#D'",
- i, x);
+ cp_error_at ("default argument missing for parameter %P of `%+#D'",
+ i, x);
break;
}
}
}
+
+void
+mark_used (decl)
+ tree decl;
+{
+ TREE_USED (decl) = 1;
+ if (processing_template_decl)
+ return;
+ assemble_external (decl);
+ /* Is it a synthesized method that needs to be synthesized? */
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CLASS_CONTEXT (decl)
+ && DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
+ /* Kludge: don't synthesize for default args. */
+ && current_function_decl)
+ synthesize_method (decl);
+ if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
+ instantiate_decl (decl);
+}
+
+/* Helper function for named_class_head_sans_basetype nonterminal. */
+
+tree
+handle_class_head (aggr, scope, id)
+ tree aggr, scope, id;
+{
+ if (TREE_CODE (id) == TYPE_DECL)
+ return id;
+
+ if (scope)
+ cp_error ("`%T' does not have a nested type named `%D'", scope, id);
+ else
+ cp_error ("no file-scope type named `%D'", id);
+
+ id = xref_tag
+ (aggr, make_anon_name (), NULL_TREE, 1);
+ return TYPE_MAIN_DECL (id);
+}
diff --git a/contrib/gcc/cp/errfn.c b/contrib/gcc/cp/errfn.c
index 4da07fa..8d20682 100644
--- a/contrib/gcc/cp/errfn.c
+++ b/contrib/gcc/cp/errfn.c
@@ -20,16 +20,22 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
+#include "system.h"
#include "tree.h"
-#include <stdio.h>
-#include <ctype.h>
+#include "toplev.h"
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
/* cp_printer is the type of a function which converts an argument into
a string for digestion by printf. The cp_printer function should deal
with all memory management; the functions in this file will not free
the char*s returned. See error.c for an example use of this code. */
-typedef char* cp_printer PROTO((HOST_WIDE_INT, int));
+typedef char* cp_printer PROTO((tree, int));
extern cp_printer * cp_printers[256];
/* Whether or not we should try to be quiet for errors and warnings; this is
@@ -44,187 +50,235 @@ extern int cp_line_of PROTO((tree));
#define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
-#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]
+/* This function supports only `%s', `%d', `%%', and the C++ print
+ codes. */
+#ifdef __STDC__
+static void
+cp_thing (errorfn *errfn, int atarg1, const char *format, va_list ap)
+#else
static void
-cp_thing (errfn, atarg1, format, arglist)
+cp_thing (errfn, atarg1, format, ap)
errorfn *errfn;
int atarg1;
- char *format;
- arglist_dcl
+ const char *format;
+ va_list ap;
+#endif
{
- char *fmt;
- char *f;
- char *ap;
- int arg;
- HOST_WIDE_INT atarg = atarg1 ? a1 : 0;
- HOST_WIDE_INT args[NARGS];
- ARGSINIT
-
- fmt = STRDUP(format);
-
- for (f = fmt, arg = 0; *f; ++f)
+ static char *buf;
+ static long buflen;
+ int nargs = 0;
+ long len;
+ long offset;
+ const char *f;
+ tree atarg = 0;
+
+ len = strlen (format) + 1;
+ if (len > buflen)
+ {
+ buflen = len;
+ buf = xrealloc (buf, buflen);
+ }
+ offset = 0;
+
+ for (f = format; *f; ++f)
{
cp_printer * function;
int alternate;
int maybe_here;
/* ignore text */
- if (*f != '%') continue;
+ if (*f != '%')
+ {
+ buf[offset++] = *f;
+ continue;
+ }
++f;
alternate = 0;
maybe_here = 0;
- /* ignore most flags */
- while (*f == ' ' || *f == '-' || *f == '+' || *f == '#')
+ /* Check for '+' and '#' (in that order). */
+ if (*f == '+')
{
- if (*f == '+')
- maybe_here = 1;
- else if (*f == '#')
- alternate = 1;
+ maybe_here = 1;
++f;
}
-
- /* ignore field width */
- if (*f == '*')
+ if (*f == '#')
{
+ alternate = 1;
++f;
- ++arg;
}
- else
- while (isdigit (*f))
- ++f;
- /* ignore precision */
- if (*f == '.')
+ /* no field width or precision */
+
+ function = cp_printers[(int)*f];
+
+ if (function || *f == 's')
{
- ++f;
- if (*f == '*')
+ char *p;
+ int plen;
+
+ if (*f == 's')
{
- ++f;
- ++arg;
+ p = va_arg (ap, char *);
+ nargs++;
}
else
- while (isdigit (*f))
- ++f;
- }
+ {
+ tree t = va_arg (ap, tree);
+ nargs++;
- /* ignore "long" */
- if (*f == 'l')
- ++f;
+ /* This indicates that ATARG comes from a different
+ location than normal. */
+ if (maybe_here && atarg1)
+ atarg = t;
- function = cp_printers[(int)*f];
+ /* If atarg1 is set and this is the first argument, then
+ set ATARG appropriately. */
+ if (atarg1 && nargs == 1)
+ atarg = t;
- if (function)
- {
- char *p;
-
- if (arg >= NARGS) abort ();
-
- if (maybe_here && atarg1)
- atarg = args[arg];
+ p = (*function) (t, alternate);
+ }
- /* Must use a temporary to avoid calling *function twice */
- p = (*function) (args[arg], alternate);
- args[arg] = (HOST_WIDE_INT) STRDUP(p);
- *f = 's';
+ plen = strlen (p);
+ len += plen;
+ if (len > buflen)
+ {
+ buflen = len;
+ buf = xrealloc (buf, len);
+ }
+ strcpy (buf + offset, p);
+ offset += plen;
}
+ else if (*f == '%')
+ {
+ /* A `%%' has occurred in the input string. Since the
+ string we produce here will be passed to vprintf we must
+ preserve both `%' characters. */
- ++arg; /* Assume valid format string */
-
+ len += 2;
+ if (len > buflen)
+ {
+ buflen = len;
+ buf = xrealloc (buf, len);
+ }
+ strcpy (buf + offset, "%%");
+ offset += 2;
+ }
+ else
+ {
+ if (*f != 'd')
+ abort ();
+ len += HOST_BITS_PER_INT / 2;
+ if (len > buflen)
+ {
+ buflen = len;
+ buf = xrealloc (buf, len);
+ }
+ sprintf (buf + offset, "%d", va_arg (ap, int));
+ nargs++;
+ offset += strlen (buf + offset);
+ /* With an ANSI C library one could write
+ out += sprintf (...); */
+ }
}
+ buf[offset] = '\0';
+
+ /* If ATARG1 is set, but we haven't extracted any arguments, then
+ extract one tree argument for ATARG. */
+ if (nargs == 0 && atarg1)
+ atarg = va_arg (ap, tree);
if (atarg)
{
- char *file = cp_file_of ((tree) atarg);
- int line = cp_line_of ((tree) atarg);
- (*errfn) (file, line, fmt, ARGSLIST);
+ char *file = cp_file_of (atarg);
+ int line = cp_line_of (atarg);
+ (*errfn) (file, line, buf);
}
else
- (*errfn) (fmt, ARGSLIST);
+ (*errfn) (buf);
}
-void
-cp_error (format, arglist)
- char *format;
- arglist_dcl
+#ifdef __STDC__
+#define DECLARE(name) void name (const char *format, ...)
+#define INIT va_start (ap, format)
+#else
+#define DECLARE(name) void name (format, va_alist) char *format; va_dcl
+#define INIT va_start (ap)
+#endif
+
+DECLARE (cp_error)
{
- extern errorfn error;
+ va_list ap;
+ INIT;
if (! cp_silent)
- cp_thing (error, 0, format, arglist);
+ cp_thing ((errorfn *) error, 0, format, ap);
+ va_end (ap);
}
-void
-cp_warning (format, arglist)
- char *format;
- arglist_dcl
+DECLARE (cp_warning)
{
- extern errorfn warning;
+ va_list ap;
+ INIT;
if (! cp_silent)
- cp_thing (warning, 0, format, arglist);
+ cp_thing ((errorfn *) warning, 0, format, ap);
+ va_end (ap);
}
-void
-cp_pedwarn (format, arglist)
- char *format;
- arglist_dcl
+DECLARE (cp_pedwarn)
{
- extern errorfn pedwarn;
+ va_list ap;
+ INIT;
if (! cp_silent)
- cp_thing (pedwarn, 0, format, arglist);
+ cp_thing ((errorfn *) pedwarn, 0, format, ap);
+ va_end (ap);
}
-void
-cp_compiler_error (format, arglist)
- char *format;
- arglist_dcl
+DECLARE (cp_compiler_error)
{
extern errorfn compiler_error;
+ va_list ap;
+ INIT;
if (! cp_silent)
- cp_thing (compiler_error, 0, format, arglist);
+ cp_thing (compiler_error, 0, format, ap);
+ va_end (ap);
}
-void
-cp_sprintf (format, arglist)
- char *format;
- arglist_dcl
+DECLARE (cp_sprintf)
{
- cp_thing ((errorfn *) sprintf, 0, format, arglist);
+ va_list ap;
+ INIT;
+ cp_thing ((errorfn *) sprintf, 0, format, ap);
+ va_end (ap);
}
-void
-cp_error_at (format, arglist)
- char *format;
- arglist_dcl
+DECLARE (cp_error_at)
{
- extern errorfn error_with_file_and_line;
+ va_list ap;
+ INIT;
if (! cp_silent)
- cp_thing (error_with_file_and_line, 1, format, arglist);
+ cp_thing ((errorfn *) error_with_file_and_line, 1, format, ap);
+ va_end (ap);
}
-void
-cp_warning_at (format, arglist)
- char *format;
- arglist_dcl
+DECLARE (cp_warning_at)
{
- extern errorfn warning_with_file_and_line;
+ va_list ap;
+ INIT;
if (! cp_silent)
- cp_thing (warning_with_file_and_line, 1, format, arglist);
+ cp_thing ((errorfn *) warning_with_file_and_line, 1, format, ap);
+ va_end (ap);
}
-void
-cp_pedwarn_at (format, arglist)
- char *format;
- arglist_dcl
+DECLARE (cp_pedwarn_at)
{
- extern errorfn pedwarn_with_file_and_line;
+ va_list ap;
+ INIT;
if (! cp_silent)
- cp_thing (pedwarn_with_file_and_line, 1, format, arglist);
+ cp_thing ((errorfn *) pedwarn_with_file_and_line, 1, format, ap);
+ va_end (ap);
}
diff --git a/contrib/gcc/cp/error.c b/contrib/gcc/cp/error.c
index 4eb196e..bb21bcb 100644
--- a/contrib/gcc/cp/error.c
+++ b/contrib/gcc/cp/error.c
@@ -1,6 +1,6 @@
/* Call-backs for C++ error reporting.
This code is non-reentrant.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,10 +20,11 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
+#include "system.h"
#include "tree.h"
#include "cp-tree.h"
#include "obstack.h"
-#include <ctype.h>
+#include "toplev.h"
typedef char* cp_printer ();
@@ -34,21 +35,22 @@ typedef char* cp_printer ();
#define L language_as_string
#define O op_as_string
#define P parm_as_string
+#define Q assop_as_string
#define T type_as_string
#define V cv_as_string
-#define _ (cp_printer *) 0
+#define o (cp_printer *) 0
cp_printer * cp_printers[256] =
-{
+{
/*0 1 2 3 4 5 6 7 8 9 A B C D E F */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x00 */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x10 */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */
- _, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */
- P, _, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */
+ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x00 */
+ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x10 */
+ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x20 */
+ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x30 */
+ o, A, o, C, D, E, o, o, o, o, o, o, L, o, o, O, /* 0x40 */
+ P, Q, o, o, T, o, V, o, o, o, o, o, o, o, o, o, /* 0x50 */
+ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x60 */
+ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x70 */
};
#undef C
#undef D
@@ -56,9 +58,10 @@ cp_printer * cp_printers[256] =
#undef L
#undef O
#undef P
+#undef Q
#undef T
#undef V
-#undef _
+#undef o
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -77,16 +80,32 @@ static char *scratch_firstobj;
IDENTIFIER_LENGTH (ID)))
# define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S)))
# define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
-# define OB_PUTI(CST) do { sprintf (digit_buffer, "%d", (CST)); \
+# define OB_PUTI(CST) do { sprintf (digit_buffer, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)(CST)); \
OB_PUTCP (digit_buffer); } while (0)
# define OB_UNPUT(N) obstack_blank (&scratch_obstack, - (N));
# define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t)))
-static void dump_type (), dump_decl (), dump_function_decl ();
-static void dump_expr (), dump_unary_op (), dump_binary_op ();
-static void dump_aggr_type (), dump_type_prefix (), dump_type_suffix ();
-static void dump_function_name ();
+enum pad { none, before, after };
+
+static void dump_type PROTO((tree, int));
+static void dump_type_real PROTO((tree, int, int));
+static void dump_simple_decl PROTO((tree, tree, int));
+static void dump_decl PROTO((tree, int));
+static void dump_function_decl PROTO((tree, int));
+static void dump_expr PROTO((tree, int));
+static void dump_unary_op PROTO((char *, tree, int));
+static void dump_binary_op PROTO((char *, tree));
+static void dump_aggr_type PROTO((tree, int, int));
+static void dump_type_prefix PROTO((tree, int, int));
+static void dump_type_suffix PROTO((tree, int, int));
+static void dump_function_name PROTO((tree));
+static void dump_expr_list PROTO((tree));
+static void dump_global_iord PROTO((tree));
+static void dump_readonly_or_volatile PROTO((tree, enum pad));
+static void dump_char PROTO((int));
+static char *aggr_variety PROTO((tree));
+static tree ident_fndecl PROTO((tree));
void
init_error ()
@@ -95,8 +114,6 @@ init_error ()
scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
}
-enum pad { none, before, after };
-
static void
dump_readonly_or_volatile (t, p)
tree t;
@@ -119,11 +136,13 @@ dump_readonly_or_volatile (t, p)
value. */
static char digit_buffer[128];
-/* Dump into the obstack a human-readable equivalent of TYPE. */
+/* Dump into the obstack a human-readable equivalent of TYPE. */
+
static void
-dump_type (t, v)
+dump_type_real (t, v, canonical_name)
tree t;
int v; /* verbose? */
+ int canonical_name;
{
if (t == NULL_TREE)
return;
@@ -145,19 +164,19 @@ dump_type (t, v)
/* i.e. function taking no arguments */
if (t != void_list_node)
{
- dump_type (TREE_VALUE (t), v);
+ dump_type_real (TREE_VALUE (t), v, canonical_name);
/* Can this happen other than for default arguments? */
if (TREE_PURPOSE (t) && v)
{
OB_PUTS (" = ");
- dump_expr (TREE_PURPOSE (t));
+ dump_expr (TREE_PURPOSE (t), 0);
}
if (TREE_CHAIN (t))
{
if (TREE_CHAIN (t) != void_list_node)
{
OB_PUTC2 (',', ' ');
- dump_type (TREE_CHAIN (t), v);
+ dump_type_real (TREE_CHAIN (t), v, canonical_name);
}
}
else OB_PUTS (" ...");
@@ -169,7 +188,7 @@ dump_type (t, v)
break;
case TREE_VEC:
- dump_type (BINFO_TYPE (t), v);
+ dump_type_real (BINFO_TYPE (t), v, canonical_name);
break;
case RECORD_TYPE:
@@ -179,21 +198,27 @@ dump_type (t, v)
&& (IS_SIGNATURE_POINTER (t) || IS_SIGNATURE_REFERENCE (t)))
{
if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
- dump_type (SIGNATURE_TYPE (t), v);
+ dump_readonly_or_volatile (t, after);
+ dump_type_real (SIGNATURE_TYPE (t), v, canonical_name);
if (IS_SIGNATURE_POINTER (t))
OB_PUTC ('*');
else
OB_PUTC ('&');
}
else
- dump_aggr_type (t, v);
+ dump_aggr_type (t, v, canonical_name);
break;
case TYPE_DECL:
+ case TEMPLATE_DECL:
dump_decl (t, v);
break;
+ case COMPLEX_TYPE:
+ OB_PUTS ("complex ");
+ dump_type_real (TREE_TYPE (t), v, canonical_name);
+ break;
+
case INTEGER_TYPE:
if (!TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && TREE_UNSIGNED (t))
OB_PUTS ("unsigned ");
@@ -204,17 +229,56 @@ dump_type (t, v)
case REAL_TYPE:
case VOID_TYPE:
case BOOLEAN_TYPE:
- dump_readonly_or_volatile (t, after);
- OB_PUTID (TYPE_IDENTIFIER (t));
+ {
+ tree type;
+ dump_readonly_or_volatile (t, after);
+ type = canonical_name ? TYPE_MAIN_VARIANT (t) : t;
+ if (TYPE_NAME (type) && TYPE_IDENTIFIER (type))
+ OB_PUTID (TYPE_IDENTIFIER (type));
+ else
+ /* Types like intQI_type_node and friends have no names.
+ These don't come up in user error messages, but it's nice
+ to be able to print them from the debugger. */
+ OB_PUTS ("{anonymous}");
+ }
break;
- case TEMPLATE_TYPE_PARM:
- OB_PUTID (TYPE_IDENTIFIER (t));
+ case TEMPLATE_TEMPLATE_PARM:
+ if (!CLASSTYPE_TEMPLATE_INFO (t))
+ {
+ /* For parameters inside template signature. */
+ if (TYPE_IDENTIFIER (t))
+ OB_PUTID (TYPE_IDENTIFIER (t));
+ else
+ OB_PUTS ("{anonymous template template parm}");
+ }
+ else
+ {
+ int i;
+ tree args = CLASSTYPE_TI_ARGS (t);
+ OB_PUTID (TYPE_IDENTIFIER (t));
+ OB_PUTC ('<');
+ for (i = 0; i < TREE_VEC_LENGTH (args); i++)
+ {
+ tree arg = TREE_VEC_ELT (args, i);
+ if (TREE_CODE_CLASS (TREE_CODE (arg)) == 't'
+ || TREE_CODE (arg) == TEMPLATE_DECL)
+ dump_type_real (arg, 0, canonical_name);
+ else
+ dump_expr (arg, 0);
+ if (i < TREE_VEC_LENGTH (args)-1)
+ OB_PUTC2 (',', ' ');
+ }
+ OB_PUTC ('>');
+ }
break;
- case UNINSTANTIATED_P_TYPE:
- OB_PUTID (DECL_NAME (UPT_TEMPLATE (t)));
- OB_PUTS ("<...>");
+ case TEMPLATE_TYPE_PARM:
+ dump_readonly_or_volatile (t, after);
+ if (TYPE_IDENTIFIER (t))
+ OB_PUTID (TYPE_IDENTIFIER (t));
+ else
+ OB_PUTS ("{anonymous template type parm}");
break;
/* This is not always necessary for pointers and such, but doing this
@@ -226,8 +290,15 @@ dump_type (t, v)
offset_type:
case FUNCTION_TYPE:
case METHOD_TYPE:
- dump_type_prefix (t, v);
- dump_type_suffix (t, v);
+ dump_type_prefix (t, v, canonical_name);
+ dump_type_suffix (t, v, canonical_name);
+ break;
+
+ case TYPENAME_TYPE:
+ OB_PUTS ("typename ");
+ dump_type_real (TYPE_CONTEXT (t), 0, canonical_name);
+ OB_PUTS ("::");
+ OB_PUTID (TYPE_IDENTIFIER (t));
break;
default:
@@ -252,12 +323,22 @@ aggr_variety (t)
return "struct";
}
-/* Print out a class declaration, in the form `class foo'. */
static void
-dump_aggr_type (t, v)
+dump_type (t, v)
tree t;
int v; /* verbose? */
{
+ dump_type_real (t, v, 0);
+}
+
+/* Print out a class declaration, in the form `class foo'. */
+
+static void
+dump_aggr_type (t, v, canonical_name)
+ tree t;
+ int v; /* verbose? */
+ int canonical_name;
+{
tree name;
char *variety = aggr_variety (t);
@@ -269,9 +350,9 @@ dump_aggr_type (t, v)
OB_PUTC (' ');
}
- name = TYPE_NAME (t);
+ name = TYPE_NAME (canonical_name ? TYPE_MAIN_VARIANT (t) : t);
- if (name && DECL_CONTEXT (name))
+ if (name && DECL_CONTEXT (name) && DECL_CONTEXT (name) != global_namespace)
{
/* FUNCTION_DECL or RECORD_TYPE */
dump_decl (DECL_CONTEXT (name), 0);
@@ -308,9 +389,10 @@ dump_aggr_type (t, v)
int *[]&. */
static void
-dump_type_prefix (t, v)
+dump_type_prefix (t, v, canonical_name)
tree t;
int v; /* verbosity */
+ int canonical_name;
{
if (TYPE_PTRMEMFUNC_P (t))
{
@@ -324,7 +406,7 @@ dump_type_prefix (t, v)
{
tree sub = TREE_TYPE (t);
- dump_type_prefix (sub, v);
+ dump_type_prefix (sub, v, canonical_name);
/* A tree for a member pointer looks like pointer to offset,
so let the OFFSET_TYPE case handle it. */
if (TREE_CODE (sub) != OFFSET_TYPE)
@@ -358,7 +440,7 @@ dump_type_prefix (t, v)
case REFERENCE_TYPE:
{
tree sub = TREE_TYPE (t);
- dump_type_prefix (sub, v);
+ dump_type_prefix (sub, v, canonical_name);
switch (TREE_CODE (sub))
{
@@ -382,11 +464,11 @@ dump_type_prefix (t, v)
case OFFSET_TYPE:
offset_type:
- dump_type_prefix (TREE_TYPE (t), v);
+ dump_type_prefix (TREE_TYPE (t), v, canonical_name);
if (TREE_CODE (t) == OFFSET_TYPE) /* pmfs deal with this in d_t_p */
{
OB_PUTC (' ');
- dump_type (TYPE_OFFSET_BASETYPE (t), 0);
+ dump_type_real (TYPE_OFFSET_BASETYPE (t), 0, canonical_name);
OB_PUTC2 (':', ':');
}
OB_PUTC ('*');
@@ -396,19 +478,19 @@ dump_type_prefix (t, v)
/* Can only be reached through function pointer -- this would not be
correct if FUNCTION_DECLs used it. */
case FUNCTION_TYPE:
- dump_type_prefix (TREE_TYPE (t), v);
+ dump_type_prefix (TREE_TYPE (t), v, canonical_name);
OB_PUTC2 (' ', '(');
break;
case METHOD_TYPE:
- dump_type_prefix (TREE_TYPE (t), v);
+ dump_type_prefix (TREE_TYPE (t), v, canonical_name);
OB_PUTC2 (' ', '(');
- dump_aggr_type (TYPE_METHOD_BASETYPE (t), 0);
+ dump_aggr_type (TYPE_METHOD_BASETYPE (t), 0, canonical_name);
OB_PUTC2 (':', ':');
break;
case ARRAY_TYPE:
- dump_type_prefix (TREE_TYPE (t), v);
+ dump_type_prefix (TREE_TYPE (t), v, canonical_name);
break;
case ENUMERAL_TYPE:
@@ -419,14 +501,16 @@ dump_type_prefix (t, v)
case REAL_TYPE:
case RECORD_TYPE:
case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
case TREE_LIST:
case TYPE_DECL:
case TREE_VEC:
- case UNINSTANTIATED_P_TYPE:
case UNION_TYPE:
case UNKNOWN_TYPE:
case VOID_TYPE:
- dump_type (t, v);
+ case TYPENAME_TYPE:
+ case COMPLEX_TYPE:
+ dump_type_real (t, v, canonical_name);
break;
default:
@@ -436,9 +520,10 @@ dump_type_prefix (t, v)
}
static void
-dump_type_suffix (t, v)
+dump_type_suffix (t, v, canonical_name)
tree t;
int v; /* verbose? */
+ int canonical_name;
{
if (TYPE_PTRMEMFUNC_P (t))
t = TYPE_PTRMEMFUNC_FN_TYPE (t);
@@ -450,7 +535,7 @@ dump_type_suffix (t, v)
case OFFSET_TYPE:
if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
OB_PUTC (')');
- dump_type_suffix (TREE_TYPE (t), v);
+ dump_type_suffix (TREE_TYPE (t), v, canonical_name);
break;
/* Can only be reached through function pointer */
@@ -471,16 +556,25 @@ dump_type_suffix (t, v)
if (TREE_CODE (t) == METHOD_TYPE)
dump_readonly_or_volatile
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before);
- dump_type_suffix (TREE_TYPE (t), v);
+ dump_type_suffix (TREE_TYPE (t), v, canonical_name);
break;
}
case ARRAY_TYPE:
OB_PUTC ('[');
if (TYPE_DOMAIN (t))
- OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1);
+ {
+ if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == INTEGER_CST)
+ OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1);
+ else if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == MINUS_EXPR)
+ dump_expr (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0), 0);
+ else
+ dump_expr (fold (build_binary_op
+ (PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)),
+ integer_one_node, 1)), 0);
+ }
OB_PUTC (']');
- dump_type_suffix (TREE_TYPE (t), v);
+ dump_type_suffix (TREE_TYPE (t), v, canonical_name);
break;
case ENUMERAL_TYPE:
@@ -491,13 +585,15 @@ dump_type_suffix (t, v)
case REAL_TYPE:
case RECORD_TYPE:
case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
case TREE_LIST:
case TYPE_DECL:
case TREE_VEC:
- case UNINSTANTIATED_P_TYPE:
case UNION_TYPE:
case UNKNOWN_TYPE:
case VOID_TYPE:
+ case TYPENAME_TYPE:
+ case COMPLEX_TYPE:
break;
default:
@@ -508,7 +604,8 @@ dump_type_suffix (t, v)
/* Return a function declaration which corresponds to the IDENTIFIER_NODE
argument. */
-tree
+
+static tree
ident_fndecl (t)
tree t;
{
@@ -538,9 +635,9 @@ ident_fndecl (t)
#endif
#define GLOBAL_IORD_P(NODE) \
- !strncmp(IDENTIFIER_POINTER(NODE),GLOBAL_THING,sizeof(GLOBAL_THING)-1)
+ ! strncmp (IDENTIFIER_POINTER(NODE), GLOBAL_THING, sizeof (GLOBAL_THING) - 1)
-void
+static void
dump_global_iord (t)
tree t;
{
@@ -560,6 +657,31 @@ dump_global_iord (t)
}
static void
+dump_simple_decl (t, type, v)
+ tree t;
+ tree type;
+ int v;
+{
+ if (v > 0)
+ {
+ dump_type_prefix (type, v, 0);
+ OB_PUTC (' ');
+ dump_readonly_or_volatile (t, after);
+ }
+ if (DECL_CLASS_SCOPE_P (t))
+ {
+ dump_type (DECL_CONTEXT (t), 0);
+ OB_PUTC2 (':', ':');
+ }
+ if (DECL_NAME (t))
+ dump_decl (DECL_NAME (t), v);
+ else
+ OB_PUTS ("{anon}");
+ if (v > 0)
+ dump_type_suffix (type, v, 0);
+}
+
+static void
dump_decl (t, v)
tree t;
int v; /* verbosity */
@@ -576,18 +698,20 @@ dump_decl (t, v)
case TYPE_DECL:
{
/* Don't say 'typedef class A' */
- tree type = TREE_TYPE (t);
- if (((IS_AGGR_TYPE (type) && ! TYPE_PTRMEMFUNC_P (type))
- || TREE_CODE (type) == ENUMERAL_TYPE)
- && type == TYPE_MAIN_VARIANT (type))
+ if (DECL_ARTIFICIAL (t))
{
- dump_type (type, v);
+ if (v > 0 && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
+ /* Say `class T' not just `T'. */
+ OB_PUTS ("class ");
+
+ dump_type (TREE_TYPE (t), v);
break;
}
}
if (v > 0)
OB_PUTS ("typedef ");
- goto general;
+ dump_simple_decl (t, DECL_ORIGINAL_TYPE (t)
+ ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), v);
break;
case VAR_DECL:
@@ -600,32 +724,24 @@ dump_decl (t, v)
/* else fall through */
case FIELD_DECL:
case PARM_DECL:
- general:
- if (v > 0)
- {
- dump_type_prefix (TREE_TYPE (t), v);
- OB_PUTC (' ');
- dump_readonly_or_volatile (t, after);
- }
- /* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */
- if (DECL_CONTEXT (t)
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't')
- {
- dump_type (DECL_CONTEXT (t), 0);
- OB_PUTC2 (':', ':');
- }
- if (DECL_NAME (t))
- dump_decl (DECL_NAME (t), v);
- else
- OB_PUTS ("{anon}");
- if (v > 0)
- dump_type_suffix (TREE_TYPE (t), v);
+ dump_simple_decl (t, TREE_TYPE (t), v);
break;
case NAMESPACE_DECL:
+ if (DECL_CONTEXT (t) != global_namespace)
+ {
+ dump_decl (DECL_CONTEXT (t), v);
+ OB_PUTC2 (':',':');
+ }
OB_PUTID (DECL_NAME (t));
break;
+ case SCOPE_REF:
+ dump_decl (TREE_OPERAND (t, 0), 0);
+ OB_PUTS ("::");
+ dump_decl (TREE_OPERAND (t, 1), 0);
+ break;
+
case ARRAY_REF:
dump_decl (TREE_OPERAND (t, 0), v);
OB_PUTC ('[');
@@ -646,7 +762,7 @@ dump_decl (t, v)
break;
/* These special cases are duplicated here so that other functions
- can feed identifiers to cp_error and get them demangled properly. */
+ can feed identifiers to cp_error and get them demangled properly. */
case IDENTIFIER_NODE:
{ tree f;
if (DESTRUCTOR_NAME_P (t)
@@ -677,45 +793,64 @@ dump_decl (t, v)
case FUNCTION_DECL:
if (GLOBAL_IORD_P (DECL_ASSEMBLER_NAME (t)))
dump_global_iord (DECL_ASSEMBLER_NAME (t));
+ else if (! DECL_LANG_SPECIFIC (t))
+ OB_PUTS ("{internal}");
else
dump_function_decl (t, v);
break;
case TEMPLATE_DECL:
{
- tree args = DECL_TEMPLATE_PARMS (t);
- int i, len = args ? TREE_VEC_LENGTH (args) : 0;
- OB_PUTS ("template <");
- for (i = 0; i < len; i++)
+ tree orig_args = DECL_TEMPLATE_PARMS (t);
+ tree args;
+ int i;
+ for (args = orig_args = nreverse (orig_args);
+ args;
+ args = TREE_CHAIN (args))
{
- tree arg = TREE_VEC_ELT (args, i);
- tree defval = TREE_PURPOSE (arg);
- arg = TREE_VALUE (arg);
- if (TREE_CODE (arg) == TYPE_DECL)
- {
- OB_PUTS ("class ");
- OB_PUTID (DECL_NAME (arg));
- }
- else
- dump_decl (arg, 1);
+ int len = TREE_VEC_LENGTH (TREE_VALUE (args));
- if (defval)
+ OB_PUTS ("template <");
+ for (i = 0; i < len; i++)
{
- OB_PUTS (" = ");
- dump_decl (defval, 1);
- }
+ tree arg = TREE_VEC_ELT (TREE_VALUE (args), i);
+ tree defval = TREE_PURPOSE (arg);
+ arg = TREE_VALUE (arg);
+ if (TREE_CODE (arg) == TYPE_DECL)
+ {
+ if (DECL_NAME (arg))
+ {
+ OB_PUTS ("class ");
+ OB_PUTID (DECL_NAME (arg));
+ }
+ else
+ OB_PUTS ("class");
+ }
+ else
+ dump_decl (arg, 1);
+
+ if (defval)
+ {
+ OB_PUTS (" = ");
+ if (TREE_CODE (arg) == TYPE_DECL
+ || TREE_CODE (arg) == TEMPLATE_DECL)
+ dump_type (defval, 1);
+ else
+ dump_expr (defval, 1);
+ }
- OB_PUTC2 (',', ' ');
+ OB_PUTC2 (',', ' ');
+ }
+ if (len != 0)
+ OB_UNPUT (2);
+ OB_PUTC2 ('>', ' ');
}
- if (len != 0)
- OB_UNPUT (2);
- OB_PUTC2 ('>', ' ');
+ nreverse(orig_args);
- if (DECL_TEMPLATE_IS_CLASS (t))
- {
- OB_PUTS ("class ");
- OB_PUTID (DECL_NAME (t));
- }
+ if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
+ dump_type (TREE_TYPE (t), v);
+ else if (TREE_TYPE (t) == NULL_TREE)
+ my_friendly_abort (353);
else switch (NEXT_CODE (t))
{
case METHOD_TYPE:
@@ -724,20 +859,60 @@ dump_decl (t, v)
break;
default:
- my_friendly_abort (353);
+ /* This case can occur with some illegal code. */
+ dump_type (TREE_TYPE (t), v);
+ }
+ }
+ break;
+
+ case TEMPLATE_ID_EXPR:
+ {
+ tree args;
+ tree name = TREE_OPERAND (t, 0);
+ if (is_overloaded_fn (name))
+ name = DECL_NAME (get_first_fn (name));
+ dump_decl (name, v);
+ OB_PUTC ('<');
+ for (args = TREE_OPERAND (t, 1); args; args = TREE_CHAIN (args))
+ {
+ if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (args))) == 't'
+ || TREE_CODE (TREE_VALUE (args)) == TEMPLATE_DECL)
+ dump_type (TREE_VALUE (args), 0);
+ else
+ dump_expr (TREE_VALUE (args), 0);
+ if (TREE_CHAIN (args))
+ OB_PUTC2 (',', ' ');
}
+ OB_PUTC ('>');
}
break;
+ case LOOKUP_EXPR:
+ dump_decl (TREE_OPERAND (t, 0), v);
+ break;
+
case LABEL_DECL:
OB_PUTID (DECL_NAME (t));
break;
case CONST_DECL:
- if (NEXT_CODE (t) == ENUMERAL_TYPE)
- goto general;
- else
+ if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
+ || (DECL_INITIAL (t) &&
+ TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX))
+ dump_simple_decl (t, TREE_TYPE (t), v);
+ else if (DECL_NAME (t))
+ dump_decl (DECL_NAME (t), v);
+ else if (DECL_INITIAL (t))
dump_expr (DECL_INITIAL (t), 0);
+ else
+ OB_PUTS ("enumerator");
+ break;
+
+ case USING_DECL:
+ OB_PUTS ("using ");
+ dump_type (DECL_INITIAL (t), 0);
+ OB_PUTS ("::");
+ OB_PUTID (DECL_NAME (t));
break;
default:
@@ -755,11 +930,18 @@ dump_function_decl (t, v)
tree t;
int v;
{
- tree name = DECL_ASSEMBLER_NAME (t);
- tree fntype = TREE_TYPE (t);
- tree parmtypes = TYPE_ARG_TYPES (fntype);
+ tree name;
+ tree fntype;
+ tree parmtypes;
tree cname = NULL_TREE;
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ t = DECL_TEMPLATE_RESULT (t);
+
+ name = DECL_ASSEMBLER_NAME (t);
+ fntype = TREE_TYPE (t);
+ parmtypes = TYPE_ARG_TYPES (fntype);
+
/* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT. */
if (DECL_CONTEXT (t))
cname = DECL_CLASS_CONTEXT (t);
@@ -778,7 +960,7 @@ dump_function_decl (t, v)
&& ! DECL_CONSTRUCTOR_P (t)
&& ! DESTRUCTOR_NAME_P (name))
{
- dump_type_prefix (TREE_TYPE (fntype), 1);
+ dump_type_prefix (TREE_TYPE (fntype), 1, 0);
OB_PUTC (' ');
}
}
@@ -809,7 +991,7 @@ dump_function_decl (t, v)
OB_PUTC (')');
if (v && ! IDENTIFIER_TYPENAME_P (name))
- dump_type_suffix (TREE_TYPE (fntype), 1);
+ dump_type_suffix (TREE_TYPE (fntype), 1, 0);
if (TREE_CODE (fntype) == METHOD_TYPE)
{
@@ -825,6 +1007,7 @@ dump_function_decl (t, v)
/* Handle the function name for a FUNCTION_DECL node, grokking operators
and destructors properly. */
+
static void
dump_function_name (t)
tree t;
@@ -858,11 +1041,98 @@ dump_function_name (t)
}
else
dump_decl (name, 0);
+
+ if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t))
+ {
+ tree args = DECL_TEMPLATE_INFO (t) ? DECL_TI_ARGS (t) : NULL_TREE;
+
+ if (args != NULL_TREE
+ && DECL_CONTEXT (t) != NULL_TREE
+ && uses_template_parms (DECL_CONTEXT (t))
+ /* This next clause checks that there is only one level of
+ template arguments. In that case, they are the
+ arguments for the class context. */
+ && (TREE_CODE (args) == TREE_LIST
+ || (TREE_CODE (args) == TREE_VEC
+ && TREE_VEC_ELT (args, 0) != NULL_TREE
+ && TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)))
+ /* We have something like this:
+
+ template <class T> struct S { void f(); };
+
+ and we are printing S<int>::f(). This is a template
+ instantiation, but we don't print anything after the f. */
+ ;
+ else
+ {
+ OB_PUTC ('<');
+
+ /* Be careful only to print things when we have them, so as not
+ to crash producing error messages. */
+ if (args)
+ {
+ if (TREE_CODE (args) == TREE_LIST)
+ {
+ tree arg;
+ int need_comma = 0;
+
+ for (arg = args; arg; arg = TREE_CHAIN (arg))
+ {
+ tree a = TREE_VALUE (arg);
+
+ if (need_comma)
+ OB_PUTS (", ");
+
+ if (a)
+ {
+ if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
+ || TREE_CODE (a) == TEMPLATE_DECL)
+ dump_type (a, 0);
+ else
+ dump_expr (a, 0);
+ }
+
+ need_comma = 1;
+ }
+ }
+ else if (TREE_CODE (args) == TREE_VEC)
+ {
+ int i;
+ int need_comma = 0;
+
+ if (TREE_VEC_LENGTH (args) > 0
+ && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+ args = TREE_VEC_ELT (args,
+ TREE_VEC_LENGTH (args) - 1);
+
+ for (i = 0; i < TREE_VEC_LENGTH (args); i++)
+ {
+ tree a = TREE_VEC_ELT (args, i);
+
+ if (need_comma)
+ OB_PUTS (", ");
+
+ if (a)
+ {
+ if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
+ || TREE_CODE (a) == TEMPLATE_DECL)
+ dump_type (a, 0);
+ else
+ dump_expr (a, 0);
+ }
+
+ need_comma = 1;
+ }
+ }
+ }
+ OB_PUTC ('>');
+ }
+ }
}
static void
dump_char (c)
- char c;
+ int c;
{
switch (c)
{
@@ -897,7 +1167,7 @@ dump_char (c)
OB_PUTS ("\\\"");
break;
default:
- if (isprint (c))
+ if (ISPRINT (c))
OB_PUTC (c);
else
{
@@ -908,6 +1178,7 @@ dump_char (c)
}
/* Print out a list of initializers (subr of dump_expr) */
+
static void
dump_expr_list (l)
tree l;
@@ -922,6 +1193,7 @@ dump_expr_list (l)
}
/* Print out an expression */
+
static void
dump_expr (t, nop)
tree t;
@@ -934,6 +1206,8 @@ dump_expr (t, nop)
case FIELD_DECL:
case CONST_DECL:
case FUNCTION_DECL:
+ case TEMPLATE_DECL:
+ case NAMESPACE_DECL:
dump_decl (t, -1);
break;
@@ -950,12 +1224,12 @@ dump_expr (t, nop)
}
else if (type == boolean_type_node)
{
- if (t == boolean_false_node)
+ if (t == boolean_false_node
+ || (TREE_INT_CST_LOW (t) == 0
+ && TREE_INT_CST_HIGH (t) == 0))
OB_PUTS ("false");
else if (t == boolean_true_node)
OB_PUTS ("true");
- else
- my_friendly_abort (366);
}
else if (type == char_type_node)
{
@@ -995,7 +1269,7 @@ dump_expr (t, nop)
#else
{
unsigned char *p = (unsigned char *) &TREE_REAL_CST (t);
- int i;
+ size_t i;
strcpy (digit_buffer, "0x");
for (i = 0; i < sizeof TREE_REAL_CST (t); i++)
sprintf (digit_buffer + 2 + 2*i, "%02x", *p++);
@@ -1044,10 +1318,11 @@ dump_expr (t, nop)
}
break;
- case NEW_EXPR:
+ case AGGR_INIT_EXPR:
OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t)));
OB_PUTC ('(');
- dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
+ if (TREE_OPERAND (t, 1))
+ dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
OB_PUTC (')');
break;
@@ -1059,7 +1334,7 @@ dump_expr (t, nop)
if (TREE_CODE (fn) == ADDR_EXPR)
fn = TREE_OPERAND (fn, 0);
- if (NEXT_CODE (fn) == METHOD_TYPE)
+ if (TREE_TYPE (fn) != NULL_TREE && NEXT_CODE (fn) == METHOD_TYPE)
{
tree ob = TREE_VALUE (args);
if (TREE_CODE (ob) == ADDR_EXPR)
@@ -1076,16 +1351,37 @@ dump_expr (t, nop)
args = TREE_CHAIN (args);
}
dump_expr (fn, 0);
- OB_PUTC('(');
+ OB_PUTC ('(');
dump_expr_list (args);
OB_PUTC (')');
}
break;
- case WITH_CLEANUP_EXPR:
- /* Note that this only works for G++ cleanups. If somebody
- builds a general cleanup, there's no way to represent it. */
- dump_expr (TREE_OPERAND (t, 0), 0);
+ case NEW_EXPR:
+ {
+ tree type = TREE_OPERAND (t, 1);
+ if (NEW_EXPR_USE_GLOBAL (t))
+ OB_PUTS ("::");
+ OB_PUTS ("new ");
+ if (TREE_OPERAND (t, 0))
+ {
+ OB_PUTC ('(');
+ dump_expr_list (TREE_OPERAND (t, 0));
+ OB_PUTS (") ");
+ }
+ if (TREE_CODE (type) == ARRAY_REF)
+ type = build_cplus_array_type
+ (TREE_OPERAND (type, 0),
+ build_index_type (size_binop (MINUS_EXPR, TREE_OPERAND (type, 1),
+ integer_one_node)));
+ dump_type (type, 0);
+ if (TREE_OPERAND (t, 2))
+ {
+ OB_PUTC ('(');
+ dump_expr_list (TREE_OPERAND (t, 2));
+ OB_PUTC (')');
+ }
+ }
break;
case TARGET_EXPR:
@@ -1188,7 +1484,8 @@ dump_expr (t, nop)
}
else
{
- if (NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
+ if (TREE_OPERAND (t,0) != NULL_TREE
+ && NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
dump_expr (TREE_OPERAND (t, 0), nop);
else
dump_unary_op ("*", t, nop);
@@ -1215,7 +1512,7 @@ dump_expr (t, nop)
/* FIXME: This is a KLUDGE workaround for a parsing problem. There
should be another level of INDIRECT_REF so that I don't have to do
this. */
- if (NEXT_CODE (t) == POINTER_TYPE)
+ if (TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == POINTER_TYPE)
{
tree next = TREE_TYPE (TREE_TYPE (t));
@@ -1240,8 +1537,46 @@ dump_expr (t, nop)
break;
case CONSTRUCTOR:
+ if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
+ {
+ tree idx = build_component_ref (t, index_identifier, NULL_TREE, 0);
+
+ if (integer_all_onesp (idx))
+ {
+ tree pfn = PFN_FROM_PTRMEMFUNC (t);
+ dump_expr (pfn, 0);
+ break;
+ }
+ if (TREE_CODE (idx) == INTEGER_CST
+ && TREE_INT_CST_HIGH (idx) == 0)
+ {
+ tree virtuals;
+ unsigned HOST_WIDE_INT n;
+
+ t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
+ t = TYPE_METHOD_BASETYPE (t);
+ virtuals = BINFO_VIRTUALS (TYPE_BINFO (TYPE_MAIN_VARIANT (t)));
+
+ n = TREE_INT_CST_LOW (idx);
+
+ /* Map vtable index back one, to allow for the null pointer to
+ member. */
+ --n;
+
+ while (n > 0 && virtuals)
+ {
+ --n;
+ virtuals = TREE_CHAIN (virtuals);
+ }
+ if (virtuals)
+ {
+ dump_expr (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
+ break;
+ }
+ }
+ }
OB_PUTC ('{');
- dump_expr_list (CONSTRUCTOR_ELTS (t), 0);
+ dump_expr_list (CONSTRUCTOR_ELTS (t));
OB_PUTC ('}');
break;
@@ -1255,12 +1590,82 @@ dump_expr (t, nop)
dump_expr (TREE_OPERAND (t, 1), 0);
else
{
- sorry ("operand of OFFSET_REF not understood");
- goto error;
+ dump_expr (TREE_OPERAND (t, 0), 0);
+ OB_PUTS (" .* ");
+ dump_expr (TREE_OPERAND (t, 1), 0);
}
break;
}
+ case TEMPLATE_PARM_INDEX:
+ dump_decl (TEMPLATE_PARM_DECL (t), -1);
+ break;
+
+ case IDENTIFIER_NODE:
+ OB_PUTID (t);
+ break;
+
+ case SCOPE_REF:
+ dump_type (TREE_OPERAND (t, 0), 0);
+ OB_PUTS ("::");
+ dump_expr (TREE_OPERAND (t, 1), 0);
+ break;
+
+ case CAST_EXPR:
+ if (TREE_OPERAND (t, 0) == NULL_TREE
+ || TREE_CHAIN (TREE_OPERAND (t, 0)))
+ {
+ dump_type (TREE_TYPE (t), 0);
+ OB_PUTC ('(');
+ dump_expr_list (TREE_OPERAND (t, 0));
+ OB_PUTC (')');
+ }
+ else
+ {
+ OB_PUTC ('(');
+ dump_type (TREE_TYPE (t), 0);
+ OB_PUTC (')');
+ OB_PUTC ('(');
+ dump_expr_list (TREE_OPERAND (t, 0));
+ OB_PUTC (')');
+ }
+ break;
+
+ case LOOKUP_EXPR:
+ OB_PUTID (TREE_OPERAND (t, 0));
+ break;
+
+ case ARROW_EXPR:
+ dump_expr (TREE_OPERAND (t, 0), nop);
+ OB_PUTS ("->");
+ break;
+
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ if (TREE_CODE (t) == SIZEOF_EXPR)
+ OB_PUTS ("sizeof (");
+ else
+ {
+ my_friendly_assert (TREE_CODE (t) == ALIGNOF_EXPR, 0);
+ OB_PUTS ("__alignof__ (");
+ }
+ if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't')
+ dump_type (TREE_OPERAND (t, 0), 0);
+ else
+ dump_unary_op ("*", t, 0);
+ OB_PUTC (')');
+ break;
+
+ case DEFAULT_ARG:
+ OB_PUTS ("{unparsed}");
+ break;
+
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
+ case CLEANUP_POINT_EXPR:
+ dump_expr (TREE_OPERAND (t, 0), nop);
+ break;
+
case TREE_LIST:
if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
{
@@ -1278,7 +1683,6 @@ dump_expr (t, nop)
/* fall through to ERROR_MARK... */
case ERROR_MARK:
- error:
OB_PUTCP ("{error}");
break;
}
@@ -1311,34 +1715,47 @@ dump_unary_op (opstring, t, nop)
}
char *
-fndecl_as_string (cname, fndecl, print_ret_type_p)
- tree cname, fndecl;
+fndecl_as_string (fndecl, print_ret_type_p)
+ tree fndecl;
int print_ret_type_p;
{
return decl_as_string (fndecl, print_ret_type_p);
}
-/* Same, but handtype a _TYPE.
+/* Same, but handle a _TYPE.
Called from convert_to_reference, mangle_class_name_for_template,
- build_unary_op, and GNU_xref_decl. */
+ build_unary_op, and GNU_xref_decl. If CANONICAL_NAME is non-zero,
+ when describing a typedef, we use the name of the type described,
+ rather than the name of the typedef. */
+
char *
-type_as_string (typ, v)
+type_as_string_real (typ, v, canonical_name)
tree typ;
int v;
+ int canonical_name;
{
OB_INIT ();
- dump_type (typ, v);
+ dump_type_real (typ, v, canonical_name);
OB_FINISH ();
return (char *)obstack_base (&scratch_obstack);
}
+
+char *
+type_as_string (typ, v)
+ tree typ;
+ int v;
+{
+ return type_as_string_real (typ, v, 0);
+}
+
char *
expr_as_string (decl, v)
tree decl;
- int v;
+ int v ATTRIBUTE_UNUSED;
{
OB_INIT ();
@@ -1351,6 +1768,7 @@ expr_as_string (decl, v)
/* A cross between type_as_string and fndecl_as_string.
Only called from substitute_nice_name. */
+
char *
decl_as_string (decl, v)
tree decl;
@@ -1365,14 +1783,48 @@ decl_as_string (decl, v)
return (char *)obstack_base (&scratch_obstack);
}
+/* Generate the three forms of printable names for lang_printable_name. */
+
+char *
+lang_decl_name (decl, v)
+ tree decl;
+ int v;
+{
+ if (v >= 2)
+ return decl_as_string (decl, 1);
+
+ OB_INIT ();
+
+ if (v == 1 && DECL_CLASS_SCOPE_P (decl))
+ {
+ tree cname;
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ cname = DECL_CLASS_CONTEXT (decl);
+ else
+ cname = DECL_CONTEXT (decl);
+ dump_type (cname, 0);
+ OB_PUTC2 (':', ':');
+ }
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ dump_function_name (decl);
+ else
+ dump_decl (DECL_NAME (decl), 0);
+
+ OB_FINISH ();
+
+ return (char *)obstack_base (&scratch_obstack);
+}
+
+
char *
cp_file_of (t)
tree t;
{
- if (TREE_CODE (t) == PARM_DECL)
+ if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
return DECL_SOURCE_FILE (DECL_CONTEXT (t));
else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
- return DECL_SOURCE_FILE (TYPE_NAME (t));
+ return DECL_SOURCE_FILE (TYPE_MAIN_DECL (t));
else
return DECL_SOURCE_FILE (t);
}
@@ -1382,18 +1834,13 @@ cp_line_of (t)
tree t;
{
int line = 0;
- if (TREE_CODE (t) == PARM_DECL)
+ if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
line = DECL_SOURCE_LINE (DECL_CONTEXT (t));
if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
t = TREE_TYPE (t);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
- {
- if (IS_AGGR_TYPE (t))
- line = CLASSTYPE_SOURCE_LINE (t);
- else
- line = DECL_SOURCE_LINE (TYPE_NAME (t));
- }
+ line = DECL_SOURCE_LINE (TYPE_MAIN_DECL (t));
else
line = DECL_SOURCE_LINE (t);
@@ -1406,7 +1853,7 @@ cp_line_of (t)
char *
code_as_string (c, v)
enum tree_code c;
- int v;
+ int v ATTRIBUTE_UNUSED;
{
return tree_code_name [c];
}
@@ -1414,7 +1861,7 @@ code_as_string (c, v)
char *
language_as_string (c, v)
enum languages c;
- int v;
+ int v ATTRIBUTE_UNUSED;
{
switch (c)
{
@@ -1424,6 +1871,9 @@ language_as_string (c, v)
case lang_cplusplus:
return "C++";
+ case lang_java:
+ return "Java";
+
default:
my_friendly_abort (355);
return 0;
@@ -1431,9 +1881,11 @@ language_as_string (c, v)
}
/* Return the proper printed version of a parameter to a C++ function. */
+
char *
parm_as_string (p, v)
- int p, v;
+ int p;
+ int v ATTRIBUTE_UNUSED;
{
if (p < 0)
return "`this'";
@@ -1445,7 +1897,7 @@ parm_as_string (p, v)
char *
op_as_string (p, v)
enum tree_code p;
- int v;
+ int v ATTRIBUTE_UNUSED;
{
static char buf[] = "operator ";
@@ -1457,20 +1909,48 @@ op_as_string (p, v)
}
char *
+assop_as_string (p, v)
+ enum tree_code p;
+ int v ATTRIBUTE_UNUSED;
+{
+ static char buf[] = "operator ";
+
+ if (p == 0)
+ return "{unknown}";
+
+ strcpy (buf + 9, assignop_tab [p]);
+ return buf;
+}
+
+char *
args_as_string (p, v)
tree p;
int v;
{
if (p == NULL_TREE)
- return "...";
+ return "";
+
+ if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (p))) == 't')
+ return type_as_string (p, v);
- return type_as_string (p, v);
+ OB_INIT ();
+ for (; p; p = TREE_CHAIN (p))
+ {
+ if (TREE_VALUE (p) == null_node)
+ OB_PUTS ("NULL");
+ else
+ dump_type (error_type (TREE_VALUE (p)), v);
+ if (TREE_CHAIN (p))
+ OB_PUTS (", ");
+ }
+ OB_FINISH ();
+ return (char *)obstack_base (&scratch_obstack);
}
char *
cv_as_string (p, v)
tree p;
- int v;
+ int v ATTRIBUTE_UNUSED;
{
OB_INIT ();
diff --git a/contrib/gcc/cp/except.c b/contrib/gcc/cp/except.c
index 51577f8..d294497 100644
--- a/contrib/gcc/cp/except.c
+++ b/contrib/gcc/cp/except.c
@@ -1,5 +1,5 @@
/* Handle exceptional things in C++.
- Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc.
Contributed by Michael Tiemann <tiemann@cygnus.com>
Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
initial re-implementation courtesy Tad Hunt.
@@ -22,91 +22,48 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* High-level class interface. */
-
#include "config.h"
+#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "cp-tree.h"
#include "flags.h"
#include "obstack.h"
#include "expr.h"
+#include "output.h"
+#include "except.h"
+#include "function.h"
+#include "defaults.h"
+#include "toplev.h"
+#include "eh-common.h"
-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 () */
+/* Holds the fndecl for __builtin_return_address. */
tree builtin_return_address_fndecl;
-tree throw_fndecl;
-
-static int
-doing_eh (do_warn)
- int do_warn;
-{
- if (! flag_handle_exceptions)
- {
- static int warned = 0;
- if (! warned && do_warn)
- {
- error ("exception handling disabled, use -fhandle-exceptions to enable.");
- warned = 1;
- }
- return 0;
- }
- return 1;
-}
-
-
-/*
-NO GNEWS IS GOOD GNEWS WITH GARRY GNUS: This version is much closer
-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. 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 shortcoming 1 is simple.
- -Tad Hunt (tad@mail.csh.rit.edu)
-
-*/
/* A couple of backend routines from m88k.c */
-/* used to cache a call to __builtin_return_address () */
-static tree BuiltinReturnAddress;
-
-
-#include <stdio.h>
-
-/* XXX - Tad: for EH */
-/* output an exception table entry */
-
-static void
-output_exception_table_entry (file, start_label, end_label, eh_label)
- FILE *file;
- rtx start_label, end_label, eh_label;
-{
- char label[100];
-
- assemble_integer (start_label, GET_MODE_SIZE (Pmode), 1);
- assemble_integer (end_label, GET_MODE_SIZE (Pmode), 1);
- assemble_integer (eh_label, GET_MODE_SIZE (Pmode), 1);
- putc ('\n', file); /* blank line */
-}
-
-static void
-easy_expand_asm (str)
- char *str;
-{
- expand_asm (build_string (strlen (str)+1, str));
-}
-
+static void push_eh_cleanup PROTO((void));
+static tree build_eh_type_type PROTO((tree));
+static tree build_eh_type PROTO((tree));
+static void expand_end_eh_spec PROTO((tree));
+static tree call_eh_info PROTO((void));
+static void push_eh_info PROTO((void));
+static tree get_eh_info PROTO((void));
+static tree get_eh_value PROTO((void));
+static tree get_eh_type PROTO((void));
+static tree get_eh_caught PROTO((void));
+static tree get_eh_handlers PROTO((void));
+static tree do_pop_exception PROTO((void));
+static void process_start_catch_block PROTO((tree, tree));
+static void process_start_catch_block_old PROTO((tree, tree));
+static tree build_eh_type_type_ref PROTO((tree));
+static tree build_terminate_handler PROTO((void));
+static tree alloc_eh_object PROTO((tree));
#if 0
-/* This is the startup, and finish stuff per exception table. */
+/* This is the startup, and finish stuff per exception table. */
/* XXX - Tad: exception handling section */
#ifndef EXCEPT_SECTION_ASM_OP
@@ -114,14 +71,6 @@ easy_expand_asm (str)
#endif
#ifdef EXCEPT_SECTION_ASM_OP
-typedef struct {
- void *start_protect;
- void *end_protect;
- void *exception_handler;
- } exception_table;
-#endif /* EXCEPT_SECTION_ASM_OP */
-
-#ifdef EXCEPT_SECTION_ASM_OP
/* on machines which support it, the exception table lives in another section,
but it needs a label so we can reference it... This sets up that
@@ -145,45 +94,9 @@ asm (TEXT_SECTION_ASM_OP);
#endif
-void
-exception_section ()
-{
-#ifdef ASM_OUTPUT_SECTION_NAME
- named_section (NULL_TREE, ".gcc_except_table");
-#else
- if (flag_pic)
- data_section ();
- else
-#if defined(TARGET_POWERPC) /* are we on a __rs6000? */
- data_section ();
-#else
- readonly_data_section ();
-#endif
-#endif
-}
-
-
-
-
-/* from: my-cp-except.c */
-
-/* VI: ":set ts=4" */
-#if 0
-#include <stdio.h> */
-#include "config.h"
-#include "tree.h"
-#include "rtl.h"
-#include "cp-tree.h"
-#endif
#include "decl.h"
-#if 0
-#include "flags.h"
-#endif
#include "insn-flags.h"
#include "obstack.h"
-#if 0
-#include "expr.h"
-#endif
/* ======================================================================
Briefly the algorithm works like this:
@@ -194,15 +107,15 @@ exception_section ()
output to start the protection for that block.
When a destructor or end try block is encountered, pop_eh_entry
- (&eh_stack) is called. Pop_eh_entry () returns the ehEntry it
- created when push_eh_entry () was called. The ehEntry structure
+ (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
+ created when push_eh_entry () was called. The eh_entry structure
contains three things at this point. The start protect label,
the end protect label, and the exception handler label. The end
protect label should be output before the call to the destructor
(if any). If it was a destructor, then its parse tree is stored
- in the finalization variable in the ehEntry structure. Otherwise
+ in the finalization variable in the eh_entry structure. Otherwise
the finalization variable is set to NULL to reflect the fact that
- is the the end of a try block. Next, this modified ehEntry node
+ it is the end of a try block. Next, this modified eh_entry node
is enqueued in the finalizations queue by calling
enqueue_eh_entry (&queue,entry).
@@ -231,12 +144,12 @@ exception_section ()
any of those finalizations throw an exception, we must call
terminate according to the ARM (section r.15.6.1). What this
means is that we need to dequeue and emit finalizations for each
- entry in the ehQueue until we get to an entry with a NULL
+ entry in the eh_queue until we get to an entry with a NULL
finalization field. For any of the finalization entries, if it
is not a call to terminate (), we must protect it by giving it
another start label, end label, and exception handler label,
setting its finalization tree to be a call to terminate (), and
- enqueue'ing this new ehEntry to be output at an outer level.
+ enqueue'ing this new eh_entry to be output at an outer level.
Finally, after all that is done, we can get around to outputting
the catch block which basically wraps all the "catch (...) {...}"
statements in a big if/then/else construct that matches the
@@ -244,66 +157,21 @@ exception_section ()
===================================================================== */
-extern rtx emit_insn PROTO((rtx));
-extern rtx gen_nop PROTO(());
-
/* local globals for function calls
====================================================================== */
-/* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and
- "set_unexpected ()" after default_conversion. (lib-except.c) */
-static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch, Throw;
+/* Used to cache "terminate" and "__throw_type_match*". */
+static tree Terminate, CatchMatch;
-/* used to cache __find_first_exception_table_match ()
- for throw (lib-except.c) */
+/* Used to cache __find_first_exception_table_match for throw. */
static tree FirstExceptionMatch;
-/* used to cache a call to __unwind_function () (lib-except.c) */
+/* Used to cache a call to __unwind_function. */
static tree Unwind;
-/* holds a ready to emit call to "terminate ()". */
-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. */
-
-/* =================================================================== */
-
-struct labelNode {
- rtx label;
- struct labelNode *chain;
-};
-
-
-/* this is the most important structure here. Basically this is how I store
- an exception table entry internally. */
-struct ehEntry {
- rtx start_label;
- rtx end_label;
- rtx exception_handler_label;
-
- tree finalization;
- tree context;
-};
-
-struct ehNode {
- struct ehEntry *entry;
- struct ehNode *chain;
-};
-
-struct ehStack {
- struct ehNode *top;
-};
-
-struct ehQueue {
- struct ehNode *head;
- struct ehNode *tail;
-};
/* ========================================================================= */
@@ -313,538 +181,247 @@ struct ehQueue {
========================================================================= */
-/* Holds the pc for doing "throw" */
-tree saved_pc;
-/* Holds the type of the thing being thrown. */
-tree saved_throw_type;
-/* Holds the value being thrown. */
-tree saved_throw_value;
+extern rtx catch_clauses;
+extern tree const_ptr_type_node;
-int throw_used;
-
-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 labelNode *false_label_stack = NULL;
-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 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 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));
-static struct ehEntry *copy_eh_entry PROTO((struct ehEntry *entry));
-
-
-
-/* All my cheesy stack/queue/misc data structure handling routines
-
- ========================================================================= */
-
-static void
-push_label_entry (labelstack, label)
- struct labelNode **labelstack;
- rtx label;
-{
- struct labelNode *newnode=(struct labelNode*)xmalloc (sizeof (struct labelNode));
-
- newnode->label = label;
- newnode->chain = *labelstack;
- *labelstack = newnode;
-}
-
-static rtx
-pop_label_entry (labelstack)
- struct labelNode **labelstack;
-{
- rtx label;
- struct labelNode *tempnode;
-
- if (! *labelstack) return NULL_RTX;
-
- tempnode = *labelstack;
- label = tempnode->label;
- *labelstack = (*labelstack)->chain;
- free (tempnode);
-
- return label;
-}
-
-static rtx
-top_label_entry (labelstack)
- struct labelNode **labelstack;
-{
- if (! *labelstack) return NULL_RTX;
+/* sets up all the global eh stuff that needs to be initialized at the
+ start of compilation.
- return (*labelstack)->label;
-}
+ This includes:
+ - Setting up all the function call trees. */
-/* Push to permanent obstack for rtl generation.
- One level only! */
-static struct obstack *saved_rtl_obstack;
void
-push_rtl_perm ()
-{
- extern struct obstack permanent_obstack;
- extern struct obstack *rtl_obstack;
-
- saved_rtl_obstack = rtl_obstack;
- rtl_obstack = &permanent_obstack;
-}
-
-/* Pop back to normal rtl handling. */
-static void
-pop_rtl_from_perm ()
+init_exception_processing ()
{
- extern struct obstack permanent_obstack;
- extern struct obstack *rtl_obstack;
+ /* void vtype () */
+ tree vtype = build_function_type (void_type_node, void_list_node);
- rtl_obstack = saved_rtl_obstack;
-}
-
-static rtx
-push_eh_entry (stack)
- struct ehStack *stack;
-{
- struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
- struct ehEntry *entry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
-
- if (stack == NULL) {
- free (node);
- free (entry);
- return NULL_RTX;
- }
-
- /* 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 ();
- 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;
-
- entry->finalization = NULL_TREE;
- entry->context = current_function_decl;
-
- node->entry = entry;
- node->chain = stack->top;
- stack->top = node;
-
- enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
-
- return entry->start_label;
-}
+ if (flag_honor_std)
+ push_namespace (get_identifier ("std"));
+ Terminate = auto_function (get_identifier ("terminate"),
+ vtype, NOT_BUILT_IN);
+ TREE_THIS_VOLATILE (Terminate) = 1;
+ if (flag_honor_std)
+ pop_namespace ();
-static struct ehEntry *
-pop_eh_entry (stack)
- struct ehStack *stack;
-{
- struct ehNode *tempnode;
- struct ehEntry *tempentry;
+ push_lang_context (lang_name_c);
- if (stack && (tempnode = stack->top)) {
- tempentry = tempnode->entry;
- stack->top = stack->top->chain;
- free (tempnode);
+ set_exception_lang_code (EH_LANG_C_plus_plus);
+ set_exception_version_code (1);
+
+ CatchMatch
+ = builtin_function (flag_rtti
+ ? "__throw_type_match_rtti"
+ : "__throw_type_match",
+ build_function_type (ptr_type_node,
+ tree_cons (NULL_TREE, const_ptr_type_node,
+ tree_cons (NULL_TREE, const_ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ void_list_node)))),
+ NOT_BUILT_IN, NULL_PTR);
+ FirstExceptionMatch
+ = builtin_function ("__find_first_exception_table_match",
+ build_function_type (ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ void_list_node)),
+ NOT_BUILT_IN, NULL_PTR);
+ Unwind
+ = builtin_function ("__unwind_function",
+ build_function_type (void_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ void_list_node)),
+ NOT_BUILT_IN, NULL_PTR);
- return tempentry;
- }
+ pop_lang_context ();
- return NULL;
+ /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
+ be protected with __terminate. */
+ protect_cleanup_actions_with_terminate = 1;
}
-static struct ehEntry *
-copy_eh_entry (entry)
- struct ehEntry *entry;
-{
- struct ehEntry *newentry;
-
- newentry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
- memcpy ((void*)newentry, (void*)entry, sizeof (struct ehEntry));
+/* Retrieve a pointer to the cp_eh_info node for the current exception. */
- return newentry;
-}
-
-static void
-enqueue_eh_entry (queue, entry)
- struct ehQueue *queue;
- struct ehEntry *entry;
+static tree
+call_eh_info ()
{
- struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
+ tree fn;
- node->entry = entry;
- node->chain = NULL;
-
- if (queue->head == NULL)
- {
- queue->head = node;
- }
+ fn = get_identifier ("__cp_eh_info");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
else
{
- queue->tail->chain = node;
+ tree t1, t, fields[7];
+
+ /* Declare cp_eh_info * __cp_eh_info (void),
+ as defined in exception.cc. */
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
+ /* struct cp_eh_info. This must match exception.cc. Note that this
+ type is not pushed anywhere. */
+ t1= make_lang_type (RECORD_TYPE);
+ fields[0] = build_lang_field_decl (FIELD_DECL,
+ get_identifier ("handler_label"), ptr_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL,
+ get_identifier ("dynamic_handler_chain"), ptr_type_node);
+ fields[2] = build_lang_field_decl (FIELD_DECL,
+ get_identifier ("info"), ptr_type_node);
+ /* N.B.: The fourth field LEN is expected to be
+ the number of fields - 1, not the total number of fields. */
+ finish_builtin_type (t1, "eh_context", fields, 2, ptr_type_node);
+ t1 = build_pointer_type (t1);
+
+ t1= make_lang_type (RECORD_TYPE);
+ fields[0] = build_lang_field_decl (FIELD_DECL,
+ get_identifier ("match_function"), ptr_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL,
+ get_identifier ("language"), short_integer_type_node);
+ fields[2] = build_lang_field_decl (FIELD_DECL,
+ get_identifier ("version"), short_integer_type_node);
+ /* N.B.: The fourth field LEN is expected to be
+ the number of fields - 1, not the total number of fields. */
+ finish_builtin_type (t1, "__eh_info", fields, 2, ptr_type_node);
+ t = make_lang_type (RECORD_TYPE);
+ fields[0] = build_lang_field_decl (FIELD_DECL,
+ get_identifier ("eh_info"), t1);
+ fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("value"),
+ ptr_type_node);
+ fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
+ ptr_type_node);
+ fields[3] = build_lang_field_decl
+ (FIELD_DECL, get_identifier ("cleanup"),
+ build_pointer_type (build_function_type
+ (ptr_type_node, tree_cons
+ (NULL_TREE, ptr_type_node, void_list_node))));
+ fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("caught"),
+ boolean_type_node);
+ fields[5] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"),
+ build_pointer_type (t));
+ fields[6] = build_lang_field_decl
+ (FIELD_DECL, get_identifier ("handlers"), long_integer_type_node);
+ /* N.B.: The fourth field LEN is expected to be
+ the number of fields - 1, not the total number of fields. */
+ finish_builtin_type (t, "cp_eh_info", fields, 6, ptr_type_node);
+ t = build_pointer_type (t);
+
+ /* And now the function. */
+ fn = build_lang_decl (FUNCTION_DECL, fn,
+ build_function_type (t, void_list_node));
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ pushdecl_top_level (fn);
+ make_function_rtl (fn);
+ assemble_external (fn);
+ pop_obstacks ();
}
- queue->tail = node;
+ return build_function_call (fn, NULL_TREE);
}
-static struct ehEntry *
-dequeue_eh_entry (queue)
- struct ehQueue *queue;
-{
- struct ehNode *tempnode;
- struct ehEntry *tempentry;
-
- if (queue->head == NULL)
- return NULL;
-
- tempnode = queue->head;
- queue->head = queue->head->chain;
-
- tempentry = tempnode->entry;
- free (tempnode);
-
- return tempentry;
-}
+/* Retrieve a pointer to the cp_eh_info node for the current exception
+ and save it in the current binding level. */
static void
-new_eh_queue (queue)
- struct ehQueue *queue;
+push_eh_info ()
{
- queue->head = queue->tail = NULL;
+ tree decl, fn = call_eh_info ();
+
+ /* Remember the pointer to the current exception info; it won't change
+ during this catch block. */
+ decl = build_decl (VAR_DECL, get_identifier ("__exception_info"),
+ TREE_TYPE (fn));
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_INITIAL (decl) = fn;
+ decl = pushdecl (decl);
+ cp_finish_decl (decl, fn, NULL_TREE, 0, 0);
}
-static void
-new_eh_stack (stack)
- struct ehStack *stack;
-{
- stack->top = NULL;
-}
+/* Returns a reference to the cp_eh_info node for the current exception. */
-/* cheesyness to save some typing. returns the return value rtx */
-rtx
-do_function_call (func, params, return_type)
- tree func, params, return_type;
+static tree
+get_eh_info ()
{
- 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;
+ /* Look for the pointer pushed in push_eh_info. */
+ tree t = lookup_name (get_identifier ("__exception_info"), 0);
+ return build_indirect_ref (t, NULL_PTR);
}
-static void
-expand_internal_throw (pc)
- rtx pc;
-{
- tree params;
+/* Returns a reference to the current exception object. */
- 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
-lang_interim_eh (finalization)
- tree finalization;
+static tree
+get_eh_value ()
{
- if (finalization)
- end_protect (finalization);
- else
- start_protect ();
+ return build_component_ref (get_eh_info (), get_identifier ("value"),
+ NULL_TREE, 0);
}
-extern tree auto_function PROTO((tree, tree, enum built_in_function));
-
-/* sets up all the global eh stuff that needs to be initialized at the
- start of compilation.
+/* Returns a reference to the current exception type. */
- This includes:
- - Setting up all the function call trees
- - Initializing the ehqueue
- - Initializing the eh_table_output_queue
- - Initializing the ehstack
-*/
-
-void
-init_exception_processing ()
+static tree
+get_eh_type ()
{
- extern tree define_function ();
- tree unexpected_fndecl, terminate_fndecl;
- tree set_unexpected_fndecl, set_terminate_fndecl;
- 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
- (void_type_node, void_list_node));
-
- /* arg list for the build_function_type call for set_terminate () and
- set_unexpected () */
- tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
-
- /* void (*pfvtype (void (*) ()))() */
- tree pfvtype = build_function_type (PFV, pfvlist);
-
- /* void vtype () */
- tree vtype = build_function_type (void_type_node, void_list_node);
-
- set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
- pfvtype, NOT_BUILT_IN);
- set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
- pfvtype, NOT_BUILT_IN);
- unexpected_fndecl = auto_function (get_identifier ("unexpected"),
- vtype, NOT_BUILT_IN);
- terminate_fndecl = auto_function (get_identifier ("terminate"),
- vtype, NOT_BUILT_IN);
-
- interim_eh_hook = lang_interim_eh;
-
- push_lang_context (lang_name_c);
-
- catch_match_fndecl =
- define_function (flag_rtti
- ? "__throw_type_match_rtti"
- : "__throw_type_match",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- void_list_node)))),
- NOT_BUILT_IN,
- pushdecl,
- 0);
- find_first_exception_match_fndecl =
- define_function ("__find_first_exception_table_match",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- void_list_node)),
- NOT_BUILT_IN,
- pushdecl,
- 0);
- unwind_fndecl =
- define_function ("__unwind_function",
- build_function_type (void_type_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);
- SetTerminate = default_conversion (set_terminate_fndecl);
- SetUnexpected = default_conversion (set_unexpected_fndecl);
- 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 ();
-
- new_eh_queue (&ehqueue);
- new_eh_queue (&eh_table_output_queue);
- new_eh_stack (&ehstack);
-
- 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);
+ return build_component_ref (get_eh_info (), get_identifier ("type"),
+ NULL_TREE, 0);
}
-/* call this to begin a block of unwind protection (ie: when an object is
- constructed) */
-void
-start_protect ()
-{
- if (! doing_eh (0))
- return;
+/* Returns a reference to whether or not the current exception
+ has been caught. */
- emit_label (push_eh_entry (&ehstack));
-}
-
-/* call this to end a block of unwind protection. the finalization tree is
- the finalization which needs to be run in order to cleanly unwind through
- this level of protection. (ie: call this when a scope is exited)*/
-void
-end_protect (finalization)
- tree finalization;
+static tree
+get_eh_caught ()
{
- struct ehEntry *entry;
-
- if (! doing_eh (0))
- return;
-
- 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;
-
- enqueue_eh_entry (&ehqueue, entry);
+ return build_component_ref (get_eh_info (), get_identifier ("caught"),
+ NULL_TREE, 0);
}
-/* call this on start of a try block. */
-void
-expand_start_try_stmts ()
-{
- if (! doing_eh (1))
- return;
-
- start_protect ();
-}
+/* Returns a reference to whether or not the current exception
+ has been caught. */
-void
-expand_end_try_stmts ()
+static tree
+get_eh_handlers ()
{
- end_protect (integer_zero_node);
+ return build_component_ref (get_eh_info (), get_identifier ("handlers"),
+ NULL_TREE, 0);
}
+/* Build a type value for use at runtime for a type that is matched
+ against by the exception handling system. */
-/* call this to start processing of all the catch blocks. */
-void
-expand_start_all_catch ()
+static tree
+build_eh_type_type (type)
+ tree type;
{
- struct ehEntry *entry;
- rtx label;
-
- if (! doing_eh (1))
- return;
-
- emit_line_note (input_filename, lineno);
- label = gen_label_rtx ();
+ char *typestring;
+ tree exp;
- /* The label for the exception handling block we will save. This is
- Lresume, in the documention. */
- emit_label (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 ());
+ if (type == error_mark_node)
+ return error_mark_node;
- push_label_entry (&caught_return_label_stack, label);
+ /* peel back references, so they match. */
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
- /* 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 ();
+ /* Peel off cv qualifiers. */
+ type = TYPE_MAIN_VARIANT (type);
- while (1)
+ if (flag_rtti)
{
- entry = dequeue_eh_entry (&ehqueue);
- emit_label (entry->exception_handler_label);
-
- expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
-
- /* When we get down to the matching entry, stop. */
- 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);
+ return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
}
-}
-
-/* call this to end processing of all the catch blocks. */
-void
-expand_end_all_catch ()
-{
- rtx new_catch_clause;
-
- if (! doing_eh (1))
- return;
-
- /* Code to throw out to outer context, if we fall off end of catch
- 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);
- /* 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. */
+ 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 type that is matched
- against by the exception handling system. */
+/* Build the address of a runtime type for use in the runtime matching
+ field of the new exception model */
+
static tree
-build_eh_type_type (type)
+build_eh_type_type_ref (type)
tree type;
{
char *typestring;
@@ -853,25 +430,37 @@ build_eh_type_type (type)
if (type == error_mark_node)
return error_mark_node;
- /* peel back references, so they match. */
+ /* peel back references, so they match. */
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
- /* Peel off cv qualifiers. */
+ /* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
if (flag_rtti)
{
- return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
+ exp = get_tinfo_fn (type);
+ TREE_USED (exp) = 1;
+ mark_inline_for_output (exp);
+ exp = build1 (ADDR_EXPR, ptr_type_node, exp);
}
-
- typestring = build_overload_name (type, 1, 1);
- exp = combine_strings (build_string (strlen (typestring)+1, typestring));
- return build1 (ADDR_EXPR, ptr_type_node, exp);
+ else
+ {
+ typestring = build_overload_name (type, 1, 1);
+ exp = combine_strings (build_string (strlen (typestring)+1, typestring));
+ exp = build1 (ADDR_EXPR, ptr_type_node, exp);
+ }
+ pop_obstacks ();
+ return (exp);
}
+
/* Build a type value for use at runtime for a exp that is thrown or
matched against by the exception handling system. */
+
static tree
build_eh_type (exp)
tree exp;
@@ -884,64 +473,200 @@ build_eh_type (exp)
return build_eh_type_type (TREE_TYPE (exp));
}
-/* call this to start a catch block. Typename is the typename, and identifier
+/* This routine is called to mark all the symbols representing runtime
+ type functions in the exception table as haveing been referenced.
+ This will make sure code is emitted for them. Called from finish_file. */
+void
+mark_all_runtime_matches ()
+{
+ int x,num;
+ void **ptr;
+ tree exp;
+
+ num = find_all_handler_type_matches (&ptr);
+ if (num == 0 || ptr == NULL)
+ return;
+
+ for (x=0; x <num; x++)
+ {
+ exp = (tree) ptr[x];
+ if (TREE_CODE (exp) == ADDR_EXPR)
+ {
+ exp = TREE_OPERAND (exp, 0);
+ if (TREE_CODE (exp) == FUNCTION_DECL)
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (exp)) = 1;
+ }
+ }
+
+ free (ptr);
+}
+
+/* Build up a call to __cp_pop_exception, to destroy the exception object
+ for the current catch block. HANDLER is either true or false, telling
+ the library whether or not it is being called from an exception handler;
+ if it is, it avoids destroying the object on rethrow. */
+
+static tree
+do_pop_exception ()
+{
+ tree fn, cleanup;
+ fn = get_identifier ("__cp_pop_exception");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ {
+ /* Declare void __cp_pop_exception (void *),
+ as defined in exception.cc. */
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ fn = build_lang_decl
+ (FUNCTION_DECL, fn,
+ build_function_type (void_type_node, tree_cons
+ (NULL_TREE, ptr_type_node, void_list_node)));
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ pushdecl_top_level (fn);
+ make_function_rtl (fn);
+ assemble_external (fn);
+ pop_obstacks ();
+ }
+
+ /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
+ cleanup = lookup_name (get_identifier ("__exception_info"), 0);
+ cleanup = build_function_call (fn, expr_tree_cons
+ (NULL_TREE, cleanup, NULL_TREE));
+ return cleanup;
+}
+
+/* This routine creates the cleanup for the current exception. */
+
+static void
+push_eh_cleanup ()
+{
+ int yes;
+
+ expand_expr (build_unary_op (PREINCREMENT_EXPR, get_eh_handlers (), 1),
+ const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ yes = suspend_momentary ();
+ /* All cleanups must last longer than normal. */
+ expand_decl_cleanup (NULL_TREE, do_pop_exception ());
+ resume_momentary (yes);
+}
+
+/* Build up a call to terminate on the function obstack, for use as an
+ exception handler. */
+
+static tree
+build_terminate_handler ()
+{
+ int yes = suspend_momentary ();
+ tree term = build_function_call (Terminate, NULL_TREE);
+ resume_momentary (yes);
+ return term;
+}
+
+/* Call this to start a catch block. Typename is the typename, and identifier
is the variable to place the object in or NULL if the variable doesn't
matter. If typename is NULL, that means its a "catch (...)" or catch
everything. In that case we don't need to do any type checking.
(ie: it ends up as the "else" clause rather than an "else if" clause) */
+
void
expand_start_catch_block (declspecs, declarator)
tree declspecs, declarator;
{
- rtx false_label_rtx;
- rtx protect_label_rtx;
- tree decl = NULL_TREE;
- tree init;
+ tree decl;
+
+ if (processing_template_decl)
+ {
+ if (declspecs)
+ {
+ decl = grokdeclarator (declarator, declspecs, CATCHPARM,
+ 1, NULL_TREE);
+ pushdecl (decl);
+ decl = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
+ copy_to_permanent (declspecs),
+ NULL_TREE);
+ add_tree (decl);
+ }
+ return;
+ }
if (! doing_eh (1))
return;
- /* Create a binding level for the parm. */
+ if (flag_new_exceptions)
+ process_start_catch_block (declspecs, declarator);
+ else
+ process_start_catch_block_old (declspecs, declarator);
+}
+
+
+/* This function performs the expand_start_catch_block functionality for
+ exceptions implemented in the old style, where catch blocks were all
+ called, and had to check the runtime information themselves. */
+
+static void
+process_start_catch_block_old (declspecs, declarator)
+ tree declspecs, declarator;
+{
+ rtx false_label_rtx;
+ tree decl = NULL_TREE;
+ tree init;
+
+ /* Create a binding level for the eh_info and the exception object
+ cleanup. */
+ pushlevel (0);
expand_start_bindings (0);
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);
- push_label_entry (&false_label_stack, protect_label_rtx);
+ push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
+
+ emit_line_note (input_filename, lineno);
+
+ push_eh_info ();
if (declspecs)
{
+ decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
+
+ if (decl == NULL_TREE)
+ error ("invalid catch parameter");
+ }
+
+ if (decl)
+ {
tree exp;
rtx call_rtx, return_value_rtx;
tree init_type;
- decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1,
- NULL_TREE, NULL_TREE);
+ /* Make sure we mark the catch param as used, otherwise we'll get
+ a warning about an unused ((anonymous)). */
+ TREE_USED (decl) = 1;
- if (decl == NULL_TREE)
- {
- error ("invalid catch parameter");
- return;
- }
-
- /* Figure out the type that the initializer is. */
+ /* Figure out the type that the initializer is. */
init_type = TREE_TYPE (decl);
if (TREE_CODE (init_type) != REFERENCE_TYPE
&& TREE_CODE (init_type) != POINTER_TYPE)
init_type = build_reference_type (init_type);
- exp = saved_throw_value;
- exp = tree_cons (NULL_TREE,
+ exp = get_eh_value ();
+
+ /* Since pointers are passed by value, initialize a reference to
+ pointer catch parm with the address of the value slot. */
+ if (TREE_CODE (init_type) == REFERENCE_TYPE
+ && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
+ exp = build_unary_op (ADDR_EXPR, exp, 1);
+
+ exp = expr_tree_cons (NULL_TREE,
build_eh_type_type (TREE_TYPE (decl)),
- tree_cons (NULL_TREE,
- saved_throw_type,
- tree_cons (NULL_TREE, exp, NULL_TREE)));
+ expr_tree_cons (NULL_TREE,
+ get_eh_type (),
+ expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
exp = build_function_call (CatchMatch, exp);
call_rtx = expand_call (exp, NULL_RTX, 0);
- assemble_external (TREE_OPERAND (CatchMatch, 0));
return_value_rtx = hard_function_value (ptr_type_node, exp);
@@ -952,543 +677,405 @@ expand_start_catch_block (declspecs, declarator)
/* if it returned FALSE, jump over the catch block, else fall into it */
emit_jump_insn (gen_beq (false_label_rtx));
- init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));
+ push_eh_cleanup ();
+
+ /* Create a binding level for the parm. */
+ pushlevel (0);
+ expand_start_bindings (0);
+
+ init = convert_from_reference (make_tree (init_type, call_rtx));
+
+ /* If the constructor for the catch parm exits via an exception, we
+ must call terminate. See eh23.C. */
+ if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ {
+ /* Generate the copy constructor call directly so we can wrap it.
+ See also expand_default_init. */
+ init = ocp_convert (TREE_TYPE (decl), init,
+ CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
+ init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
+ build_terminate_handler ());
+ }
- /* Do we need the below two lines? */
/* Let `cp_finish_decl' know that this initializer is ok. */
DECL_INITIAL (decl) = init;
decl = pushdecl (decl);
- cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
+
+ start_decl_1 (decl);
+ cp_finish_decl (decl, DECL_INITIAL (decl),
+ NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
}
else
{
- /* Fall into the catch all section. */
+ push_eh_cleanup ();
+
+ /* Create a binding level for the parm. */
+ pushlevel (0);
+ expand_start_bindings (0);
+
+ /* Fall into the catch all section. */
}
- /* This is the starting of something to protect. */
- emit_label (protect_label_rtx);
+ init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
+ expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
emit_line_note (input_filename, lineno);
}
+/* This function performs the expand_start_catch_block functionality for
+ exceptions implemented in the new style. __throw determines whether
+ a handler needs to be called or not, so the handler itself has to do
+ nothing additionaal. */
-/* 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 ()
+static void
+process_start_catch_block (declspecs, declarator)
+ tree declspecs, declarator;
{
- struct ehEntry *entry;
- rtx first_label = NULL_RTX;
+ tree decl = NULL_TREE;
+ tree init;
- while ((entry = dequeue_eh_entry (&ehqueue)) != 0)
+ /* Create a binding level for the eh_info and the exception object
+ cleanup. */
+ pushlevel (0);
+ expand_start_bindings (0);
+
+
+ if (declspecs)
{
- if (! first_label)
- first_label = entry->exception_handler_label;
- emit_label (entry->exception_handler_label);
+ decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
- expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
+ if (decl == NULL_TREE)
+ error ("invalid catch parameter");
+ }
+
+ if (decl)
+ start_catch_handler (build_eh_type_type_ref (TREE_TYPE (decl)));
+ else
+ start_catch_handler (CATCH_ALL_TYPE);
+
+ emit_line_note (input_filename, lineno);
+
+ push_eh_info ();
+
+ if (decl)
+ {
+ tree exp;
+ tree init_type;
+
+ /* Make sure we mark the catch param as used, otherwise we'll get
+ a warning about an unused ((anonymous)). */
+ TREE_USED (decl) = 1;
+
+ /* Figure out the type that the initializer is. */
+ init_type = TREE_TYPE (decl);
+ if (TREE_CODE (init_type) != REFERENCE_TYPE
+ && TREE_CODE (init_type) != POINTER_TYPE)
+ init_type = build_reference_type (init_type);
+
+ exp = get_eh_value ();
+
+ /* Since pointers are passed by value, initialize a reference to
+ pointer catch parm with the address of the value slot. */
+ if (TREE_CODE (init_type) == REFERENCE_TYPE
+ && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
+ exp = build_unary_op (ADDR_EXPR, exp, 1);
- /* 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));
+ exp = ocp_convert (init_type , exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
- /* leftover try block, opps. */
- if (entry->finalization == integer_zero_node)
- abort ();
+ push_eh_cleanup ();
- free (entry);
+ /* Create a binding level for the parm. */
+ pushlevel (0);
+ expand_start_bindings (0);
+
+ init = convert_from_reference (exp);
+
+ /* If the constructor for the catch parm exits via an exception, we
+ must call terminate. See eh23.C. */
+ if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ {
+ /* Generate the copy constructor call directly so we can wrap it.
+ See also expand_default_init. */
+ init = ocp_convert (TREE_TYPE (decl), init,
+ CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
+ init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
+ build_terminate_handler ());
+ }
+
+ /* Let `cp_finish_decl' know that this initializer is ok. */
+ DECL_INITIAL (decl) = init;
+ decl = pushdecl (decl);
+
+ cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
+ }
+ else
+ {
+ push_eh_cleanup ();
+
+ /* Create a binding level for the parm. */
+ pushlevel (0);
+ expand_start_bindings (0);
+
+ /* Fall into the catch all section. */
}
- return first_label;
+ init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
+ expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ emit_line_note (input_filename, lineno);
}
+
+
/* 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 ()
-{
- rtx start_protect_label_rtx;
- rtx end_protect_label_rtx;
- tree decls;
- struct ehEntry entry;
+void
+expand_end_catch_block ()
+{
if (! doing_eh (1))
return;
- /* fall to outside the try statement when done executing handler and
+ /* Cleanup the EH parameter. */
+ expand_end_bindings (getdecls (), kept_level_p (), 0);
+ poplevel (kept_level_p (), 1, 0);
+
+ /* Cleanup the EH object. */
+ expand_end_bindings (getdecls (), kept_level_p (), 0);
+ poplevel (kept_level_p (), 1, 0);
+
+ /* 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));
-
- /* We end the rethrow protection region as soon as we hit a label. */
- end_protect_label_rtx = expand_leftover_cleanups ();
-
- /* 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);
+ expand_goto (top_label_entry (&caught_return_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. */
+ /* 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));
+ if (! flag_new_exceptions)
+ emit_label (pop_label_entry (&false_label_stack));
+}
+
+/* An exception spec is implemented more or less like:
- /* 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;
+ try {
+ function body;
+ } catch (...) {
+ void *p[] = { typeid(raises) };
+ __check_eh_spec (p, count);
+ }
- LABEL_PRESERVE_P (entry.start_label) = 1;
- LABEL_PRESERVE_P (entry.end_label) = 1;
- LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
+ __check_eh_spec in exception.cc handles all the details. */
- /* 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));
+void
+expand_start_eh_spec ()
+{
+ expand_start_try_stmts ();
}
-/* unwind the stack. */
static void
-do_unwind (inner_throw_label)
- rtx inner_throw_label;
+expand_end_eh_spec (raises)
+ tree raises;
{
-#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);
- fcall = build_function_call (BuiltinReturnAddress, params);
- 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. */
- 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(ARM_FRAME_RTX) /* was __arm */
- if (flag_omit_frame_pointer)
- sorry ("this implementation of exception handling requires a frame pointer");
-
- 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 defined(TARGET_88000) /* was m88k */
- rtx temp_frame = frame_pointer_rtx;
+ tree tmp, fn, decl, types = NULL_TREE;
+ int count = 0;
- temp_frame = memory_address (Pmode, temp_frame);
- temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
+ expand_start_all_catch ();
+ expand_start_catch_block (NULL_TREE, NULL_TREE);
- /* hopefully this will successfully pop the frame! */
- emit_move_insn (frame_pointer_rtx, temp_frame);
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
- emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
- emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
- (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
+ /* Build up an array of type_infos. */
+ for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
+ {
+ types = expr_tree_cons
+ (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
+ ++count;
+ }
-#if 0
- emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
- -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
+ types = build_nt (CONSTRUCTOR, NULL_TREE, types);
+ TREE_HAS_CONSTRUCTOR (types) = 1;
- emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
+ /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
+ tmp = build_array_type (const_ptr_type_node, NULL_TREE);
+ decl = build_decl (VAR_DECL, NULL_TREE, tmp);
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_INITIAL (decl) = types;
+ cp_finish_decl (decl, types, NULL_TREE, 0, 0);
- emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
- (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
-#endif
-#endif
-#if !defined(TARGET_88000) && !defined(ARM_FRAME_RTX) && !defined(SPARC_STACK_ALIGN)
- tree fcall;
- tree params;
- rtx return_val_rtx;
+ decl = decay_conversion (decl);
- /* 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);
+ fn = get_identifier ("__check_eh_spec");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ {
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
+ tmp = tree_cons
+ (NULL_TREE, integer_type_node, tree_cons
+ (NULL_TREE, TREE_TYPE (decl), void_list_node));
+ tmp = build_function_type (void_type_node, tmp);
- do_function_call (Unwind, params, NULL_TREE);
- assemble_external (TREE_OPERAND (Unwind, 0));
- emit_barrier ();
-#endif
+ fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ TREE_THIS_VOLATILE (fn) = 1;
+ pushdecl_top_level (fn);
+ make_function_rtl (fn);
+ assemble_external (fn);
+ pop_obstacks ();
+ }
+
+ tmp = expr_tree_cons (NULL_TREE, build_int_2 (count, 0), expr_tree_cons
+ (NULL_TREE, decl, NULL_TREE));
+ tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
+ expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ expand_end_catch_block ();
+ expand_end_all_catch ();
}
+/* 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 ()
+{
+ do_pending_stack_adjust ();
+ push_to_sequence (catch_clauses);
+ expand_leftover_cleanups ();
+ do_pending_stack_adjust ();
+ catch_clauses = get_insns ();
+ end_sequence ();
+
+ /* Do this after we expand leftover cleanups, so that the
+ expand_eh_region_end that expand_end_eh_spec does will match the
+ right expand_eh_region_start, 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)));
+ do_pending_stack_adjust ();
+ push_to_sequence (catch_clauses);
+ expand_leftover_cleanups ();
+ do_pending_stack_adjust ();
+ catch_clauses = get_insns ();
+ end_sequence ();
+ }
-/* 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.
+ if (catch_clauses)
+ {
+ rtx funcend = gen_label_rtx ();
+ emit_jump (funcend);
- expands "throw" as the following pseudo code:
+ /* We cannot protect n regions this way if we must flow into the
+ EH region through the top of the region, as we have to with
+ the setjmp/longjmp approach. */
+ if (exceptions_via_longjmp == 0)
+ expand_eh_region_start ();
- throw:
- eh = find_first_exception_match (saved_pc);
- if (!eh) goto gotta_rethrow_it;
- goto eh;
+ emit_insns (catch_clauses);
+ catch_clauses = NULL_RTX;
- gotta_rethrow_it:
- saved_pc = __builtin_return_address (0);
- pop_to_previous_level ();
- goto throw;
+ if (exceptions_via_longjmp == 0)
+ expand_eh_region_end (build_terminate_handler ());
- */
-void
-expand_builtin_throw ()
+ expand_leftover_cleanups ();
+
+ emit_label (funcend);
+ }
+}
+
+tree
+start_anon_func ()
{
- tree fcall;
+ static int counter = 0;
+ int old_interface_unknown = interface_unknown;
+ char name[32];
tree params;
- rtx return_val_rtx;
- rtx gotta_rethrow_it;
- rtx gotta_call_terminate;
- rtx unwind_and_throw;
- rtx goto_unwind_and_throw;
- rtx top_of_loop;
- rtx unwind_first;
tree t;
- if (! doing_eh (0))
- return;
+ push_cp_function_context (NULL_TREE);
+ push_to_top_level ();
- if (! throw_used)
- return;
+ /* No need to mangle this. */
+ push_lang_context (lang_name_c);
+
+ interface_unknown = 1;
params = void_list_node;
- t = build_parse_node (CALL_EXPR, get_identifier ("__throw"), params, NULL_TREE);
+ /* tcf stands for throw clean function. */
+ sprintf (name, "__tcf_%d", counter++);
+ t = make_call_declarator (get_identifier (name), params, NULL_TREE,
+ NULL_TREE);
start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
void_list_node),
- t, NULL_TREE, NULL_TREE, 0);
+ t, NULL_TREE, 0);
store_parm_decls ();
pushlevel (0);
clear_last_expr ();
push_momentary ();
expand_start_bindings (0);
+ emit_line_note (input_filename, lineno);
- 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, saved_pc, NULL_TREE),
- ptr_type_node);
- assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
-
- /* did we find one? */
- emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
- GET_MODE (return_val_rtx), 0, 0);
-
- /* if not, jump to gotta_rethrow_it */
- emit_jump_insn (gen_beq (gotta_rethrow_it));
-
- /* we found it, so jump to it */
- emit_indirect_jump (return_val_rtx);
-
- /* code to deal with unwinding and looking for it again */
- emit_label (gotta_rethrow_it);
-
- /* call to __builtin_return_address () */
-#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, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
-#else
- 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);
-#endif
-
- /* did __builtin_return_address () return a valid address? */
- emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
- GET_MODE (return_val_rtx), 0, 0);
-
- emit_jump_insn (gen_beq (gotta_call_terminate));
-
-#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)));
-
- /* If we are generating code for an ARM2/ARM3 machine or for an ARM6 in 26 bit
- mode, the condition codes must be masked out of the return value, or else
- 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, Pmode, return_val_rtx, gen_rtx (AND, Pmode, return_val_rtx, GEN_INT (0x03fffffc))));
-#else
-#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);
-#endif
-#endif
+ interface_unknown = old_interface_unknown;
- /* yes it did */
- 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
+ pop_lang_context ();
- /* Fall into epilogue to unwind prologue. */
- }
+ return current_function_decl;
+}
- expand_end_bindings (getdecls(), 1, 0);
+void
+end_anon_func ()
+{
+ expand_end_bindings (getdecls (), 1, 0);
poplevel (1, 0, 0);
pop_momentary ();
finish_function (lineno, 0, 0);
-}
-
-void
-expand_start_eh_spec ()
-{
- start_protect ();
+ pop_from_top_level ();
+ pop_cp_function_context (NULL_TREE);
}
-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);
-}
+/* Return a pointer to a buffer for an exception object of type TYPE. */
-/* 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 ()
+static tree
+alloc_eh_object (type)
+ tree type;
{
- static rtx funcend;
- rtx insns;
-
- start_sequence ();
-
- funcend = gen_label_rtx ();
- emit_jump (funcend);
- /* expand_null_return (); */
-
- start_sequence ();
+ tree fn, exp;
- /* 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)
+ fn = get_identifier ("__eh_alloc");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
{
- 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 ();
+ /* Declare __eh_alloc (size_t), as defined in exception.cc. */
+ tree tmp;
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
+ fn = build_lang_decl (FUNCTION_DECL, fn,
+ build_function_type (ptr_type_node, tmp));
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ pushdecl_top_level (fn);
+ make_function_rtl (fn);
+ assemble_external (fn);
+ pop_obstacks ();
}
- {
- /* 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)
- {
- 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);
+ exp = build_function_call (fn, expr_tree_cons
+ (NULL_TREE, size_in_bytes (type), NULL_TREE));
+ exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
+ return exp;
}
-
-/* call this to expand a throw statement. This follows the following
+/* Expand a throw statement. This follows the following
algorithm:
1. Allocate space to save the current PC onto the stack.
@@ -1497,30 +1084,40 @@ expand_exception_blocks ()
3. If this is the first call to throw in this function:
generate a label for the throw block
4. jump to the throw block label. */
+
void
expand_throw (exp)
tree exp;
{
- rtx label;
+ tree fn;
+ static tree cleanup_type;
if (! doing_eh (1))
return;
- /* This is the label that represents where in the code we were, when
- we got an exception. This needs to be updated when we rethrow an
- exception, so that the matching routine knows to search out. */
- label = gen_label_rtx ();
- emit_label (label);
-
if (exp)
{
tree throw_type;
- tree e;
+ tree cleanup = NULL_TREE, e;
/* throw expression */
- /* First, decay it. */
+ /* First, decay it. */
exp = decay_conversion (exp);
+ /* cleanup_type is void (*)(void *, int),
+ the internal type of a destructor. */
+ if (cleanup_type == NULL_TREE)
+ {
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ cleanup_type = build_pointer_type
+ (build_function_type
+ (void_type_node, tree_cons
+ (NULL_TREE, ptr_type_node, tree_cons
+ (NULL_TREE, integer_type_node, void_list_node))));
+ pop_obstacks ();
+ }
+
if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
{
throw_type = build_eh_type (exp);
@@ -1528,163 +1125,167 @@ expand_throw (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);
+ tree object, ptr;
- if (exp == error_mark_node)
- error (" in thrown expression");
+ /* OK, this is kind of wacky. The WP says that we call
+ terminate
- throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR));
- }
+ when the exception handling mechanism, after completing
+ evaluation of the expression to be thrown but before the
+ exception is caught (_except.throw_), calls a user function
+ that exits via an uncaught exception.
- 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
- {
- /* rethrow current exception */
- /* This part is easy, as we don't have to do anything else. */
- }
+ So we have to protect the actual initialization of the
+ exception object with terminate(), but evaluate the expression
+ first. We also expand the call to __eh_alloc
+ first. Since there could be temps in the expression, we need
+ to handle that, too. */
- expand_internal_throw (gen_rtx (LABEL_REF, Pmode, label));
-}
+ expand_start_target_temps ();
-void
-end_protect_partials () {
- while (protect_list)
- {
- end_protect (TREE_VALUE (protect_list));
- protect_list = TREE_CHAIN (protect_list);
- }
-}
+#if 0
+ /* Unfortunately, this doesn't work. */
+ preexpand_calls (exp);
+#else
+ /* Store the throw expression into a temp. This can be less
+ efficient than storing it into the allocated space directly, but
+ oh well. To do this efficiently we would need to insinuate
+ ourselves into expand_call. */
+ if (TREE_SIDE_EFFECTS (exp))
+ {
+ tree temp = build (VAR_DECL, TREE_TYPE (exp));
+ DECL_ARTIFICIAL (temp) = 1;
+ layout_decl (temp, 0);
+ DECL_RTL (temp) = assign_temp (TREE_TYPE (exp), 2, 0, 1);
+ expand_expr (build (INIT_EXPR, TREE_TYPE (exp), temp, exp),
+ NULL_RTX, VOIDmode, 0);
+ expand_decl_cleanup (NULL_TREE, maybe_build_cleanup (temp));
+ exp = temp;
+ }
+#endif
-int
-might_have_exceptions_p ()
-{
- if (eh_table_output_queue.head)
- return 1;
- return 0;
-}
+ /* Allocate the space for the exception. */
+ ptr = save_expr (alloc_eh_object (TREE_TYPE (exp)));
+ expand_expr (ptr, const0_rtx, VOIDmode, 0);
-/* Output the exception table.
- Return the number of handlers. */
-void
-emit_exception_table ()
-{
- int count = 0;
- extern FILE *asm_out_file;
- struct ehEntry *entry;
- tree eh_node_decl;
+ expand_eh_region_start ();
- if (! doing_eh (0))
- return;
+ object = build_indirect_ref (ptr, NULL_PTR);
+ exp = build_modify_expr (object, INIT_EXPR, exp);
- exception_section ();
+ if (exp == error_mark_node)
+ error (" in thrown expression");
- /* Beginning marker for table. */
- assemble_align (GET_MODE_ALIGNMENT (Pmode));
- assemble_label ("__EXCEPTION_TABLE__");
- output_exception_table_entry (asm_out_file,
- const0_rtx, const0_rtx, const0_rtx);
+ expand_expr (exp, const0_rtx, VOIDmode, 0);
+ expand_eh_region_end (build_terminate_handler ());
+ expand_end_target_temps ();
- while (entry = dequeue_eh_entry (&eh_table_output_queue))
- {
- tree context = entry->context;
+ throw_type = build_eh_type (object);
- if (context && ! TREE_ASM_WRITTEN (context))
- continue;
+ if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
+ {
+ cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
+ dtor_identifier, 0);
+ cleanup = TREE_VALUE (cleanup);
+ mark_used (cleanup);
+ mark_addressable (cleanup);
+ /* Pretend it's a normal function. */
+ cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
+ }
- count++;
- output_exception_table_entry (asm_out_file,
- entry->start_label, entry->end_label,
- entry->exception_handler_label);
- }
+ exp = ptr;
+ }
- /* Ending marker for table. */
- assemble_label ("__EXCEPTION_END__");
- output_exception_table_entry (asm_out_file,
- constm1_rtx, constm1_rtx, constm1_rtx);
-}
+ if (cleanup == NULL_TREE)
+ {
+ cleanup = build_int_2 (0, 0);
+ TREE_TYPE (cleanup) = cleanup_type;
+ }
-void
-register_exception_table ()
-{
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__register_exceptions"), 0,
- VOIDmode, 1,
- gen_rtx (SYMBOL_REF, Pmode, "__EXCEPTION_TABLE__"),
- Pmode);
-}
+ fn = get_identifier ("__cp_push_exception");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ {
+ /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
+ as defined in exception.cc. */
+ tree tmp;
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ tmp = tree_cons
+ (NULL_TREE, ptr_type_node, tree_cons
+ (NULL_TREE, ptr_type_node, tree_cons
+ (NULL_TREE, cleanup_type, void_list_node)));
+ fn = build_lang_decl (FUNCTION_DECL, fn,
+ build_function_type (void_type_node, tmp));
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ pushdecl_top_level (fn);
+ make_function_rtl (fn);
+ assemble_external (fn);
+ pop_obstacks ();
+ }
-/* Build a throw expression. */
-tree
-build_throw (e)
- tree e;
-{
- if (e != error_mark_node)
+ e = expr_tree_cons (NULL_TREE, exp, expr_tree_cons
+ (NULL_TREE, throw_type, expr_tree_cons
+ (NULL_TREE, cleanup, NULL_TREE)));
+ e = build_function_call (fn, e);
+ expand_expr (e, const0_rtx, VOIDmode, 0);
+ }
+ else
{
- e = build1 (THROW_EXPR, void_type_node, e);
- TREE_SIDE_EFFECTS (e) = 1;
- TREE_USED (e) = 1;
+ /* rethrow current exception; note that it's no longer caught. */
+
+ tree fn = get_identifier ("__uncatch_exception");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ {
+ /* Declare void __uncatch_exception (void)
+ as defined in exception.cc. */
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ fn = build_lang_decl (FUNCTION_DECL, fn,
+ build_function_type (void_type_node,
+ void_list_node));
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ pushdecl_top_level (fn);
+ make_function_rtl (fn);
+ assemble_external (fn);
+ pop_obstacks ();
+ }
+
+ exp = build_function_call (fn, NULL_TREE);
+ expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
- return e;
-}
-start_eh_unwinder ()
-{
- start_protect ();
+ expand_internal_throw ();
}
-end_eh_unwinder (end)
- rtx end;
+/* Build a throw expression. */
+
+tree
+build_throw (e)
+ tree e;
{
- tree expr;
- rtx return_val_rtx, ret_val, label;
+ if (e == error_mark_node)
+ return e;
- if (! doing_eh (0))
- return;
+ if (processing_template_decl)
+ return build_min (THROW_EXPR, void_type_node, e);
- 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
+ if (! flag_ansi && e == null_node)
+ {
+ cp_warning ("throwing NULL");
+ e = integer_zero_node;
+ }
-#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);
+ e = build1 (THROW_EXPR, void_type_node, e);
+ TREE_SIDE_EFFECTS (e) = 1;
+ TREE_USED (e) = 1;
-#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);
+ return e;
}
diff --git a/contrib/gcc/cp/exception.cc b/contrib/gcc/cp/exception.cc
new file mode 100644
index 0000000..4c10404
--- /dev/null
+++ b/contrib/gcc/cp/exception.cc
@@ -0,0 +1,324 @@
+// Functions for Exception Support for -*- C++ -*-
+// Copyright (C) 1994, 1995, 1996, 1998 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#pragma implementation "exception"
+
+#include "typeinfo"
+#include "exception"
+#include <stddef.h>
+#include "eh-common.h"
+
+/* Define terminate, unexpected, set_terminate, set_unexpected as
+ well as the default terminate func and default unexpected func. */
+
+extern std::terminate_handler __terminate_func __attribute__((__noreturn__));
+using std::terminate;
+
+void
+std::terminate ()
+{
+ __terminate_func ();
+}
+
+void
+__default_unexpected ()
+{
+ terminate ();
+}
+
+static std::unexpected_handler __unexpected_func __attribute__((__noreturn__))
+ = __default_unexpected;
+
+std::terminate_handler
+std::set_terminate (std::terminate_handler func)
+{
+ std::terminate_handler old = __terminate_func;
+
+ __terminate_func = func;
+ return old;
+}
+
+std::unexpected_handler
+std::set_unexpected (std::unexpected_handler func)
+{
+ std::unexpected_handler old = __unexpected_func;
+
+ __unexpected_func = func;
+ return old;
+}
+
+void
+std::unexpected ()
+{
+ __unexpected_func ();
+}
+
+/* C++-specific state about the current exception.
+ This must match init_exception_processing().
+
+ Note that handlers and caught are not redundant; when rethrown, an
+ exception can have multiple active handlers and still be considered
+ uncaught. */
+
+struct cp_eh_info
+{
+ __eh_info eh_info;
+ void *value;
+ void *type;
+ void (*cleanup)(void *, int);
+ bool caught;
+ cp_eh_info *next;
+ long handlers;
+ void *original_value;
+};
+
+/* Language-specific EH info pointer, defined in libgcc2. */
+
+extern "C" cp_eh_info **__get_eh_info (); // actually void **
+
+/* Is P the type_info node for a pointer of some kind? */
+
+extern bool __is_pointer (void *);
+
+
+/* OLD Compiler hook to return a pointer to the info for the current exception.
+ Used by get_eh_info (). This fudges the actualy returned value to
+ point to the beginning of what USE to be the cp_eh_info structure.
+ THis is so that old code that dereferences this pointer will find
+ things where it expects it to be.*/
+extern "C" void *
+__cp_exception_info (void)
+{
+ return &((*__get_eh_info ())->value);
+}
+
+/* Compiler hook to return a pointer to the info for the current exception.
+ Used by get_eh_info (). */
+
+extern "C" cp_eh_info *
+__cp_eh_info (void)
+{
+ return *__get_eh_info ();
+}
+
+/* Allocate a buffer for a cp_eh_info and an exception object of size SIZE,
+ and return a pointer to the beginning of the object's space. */
+
+extern "C" void * malloc (size_t);
+extern "C" void *
+__eh_alloc (size_t size)
+{
+ void *p = malloc (size);
+ if (p == 0)
+ terminate ();
+ return p;
+}
+
+/* Free the memory for an cp_eh_info and associated exception, given
+ a pointer to the cp_eh_info. */
+
+extern "C" void free (void *);
+extern "C" void
+__eh_free (void *p)
+{
+ free (p);
+}
+
+
+typedef void * (* rtimetype) (void);
+
+extern "C" void *
+__cplus_type_matcher (cp_eh_info *info, rtimetype match_info,
+ exception_descriptor *exception_table)
+{
+ void *ret;
+
+ if (exception_table->lang.language != EH_LANG_C_plus_plus)
+ return NULL;
+
+ if (match_info == CATCH_ALL_TYPE)
+ return info->value;
+
+ /* we don't worry about version info yet, there is only one version! */
+
+ void *match_type = match_info ();
+ ret = __throw_type_match_rtti (match_type, info->type, info->original_value);
+ /* change value of exception */
+ if (ret)
+ info->value = ret;
+ return ret;
+}
+
+
+/* Compiler hook to push a new exception onto the stack.
+ Used by expand_throw(). */
+
+extern "C" void
+__cp_push_exception (void *value, void *type, void (*cleanup)(void *, int))
+{
+ cp_eh_info *p = (cp_eh_info *) __eh_alloc (sizeof (cp_eh_info));
+
+ p->value = value;
+ p->type = type;
+ p->cleanup = cleanup;
+ p->handlers = 0;
+ p->caught = false;
+ p->original_value = value;
+
+ p->eh_info.match_function = __cplus_type_matcher;
+ p->eh_info.language = EH_LANG_C_plus_plus;
+ p->eh_info.version = 1;
+
+ cp_eh_info **q = __get_eh_info ();
+
+ p->next = *q;
+ *q = p;
+}
+
+/* Compiler hook to pop an exception that has been finalized. Used by
+ push_eh_cleanup(). P is the info for the exception caught by the
+ current catch block. */
+
+extern "C" void
+__cp_pop_exception (cp_eh_info *p)
+{
+ cp_eh_info **q = __get_eh_info ();
+
+ --p->handlers;
+
+ /* Don't really pop if there are still active handlers for our exception,
+ or if our exception is being rethrown (i.e. if the active exception is
+ our exception and it is uncaught). */
+ if (p->handlers != 0
+ || (p == *q && !p->caught))
+ return;
+
+ for (; *q; q = &((*q)->next))
+ if (*q == p)
+ break;
+
+ if (! *q)
+ terminate ();
+
+ *q = p->next;
+
+ if (p->cleanup)
+ /* 2 is a magic value for destructors; see build_delete(). */
+ p->cleanup (p->value, 2);
+
+ if (! __is_pointer (p->type))
+ __eh_free (p->value);
+
+ __eh_free (p);
+}
+
+extern "C" void
+__uncatch_exception (void)
+{
+ cp_eh_info *p = __cp_eh_info ();
+ if (p == 0)
+ terminate ();
+ p->caught = false;
+}
+
+/* As per [except.unexpected]:
+ If an exception is thrown, we check it against the spec. If it doesn't
+ match, we call unexpected (). If unexpected () throws, we check that
+ exception against the spec. If it doesn't match, if the spec allows
+ bad_exception we throw that; otherwise we call terminate ().
+
+ The compiler treats an exception spec as a try block with a generic
+ handler that just calls this function with a list of the allowed
+ exception types, so we have an active exception that can be rethrown.
+
+ This function does not return. */
+
+extern "C" void
+__check_eh_spec (int n, const void **spec)
+{
+ cp_eh_info *p = __cp_eh_info ();
+
+ for (int i = 0; i < n; ++i)
+ {
+ if (__throw_type_match_rtti (spec[i], p->type, p->value))
+ throw;
+ }
+
+ try
+ {
+ std::unexpected ();
+ }
+ catch (...)
+ {
+ // __exception_info is an artificial var pushed into each catch block.
+ if (p != __exception_info)
+ {
+ p = __exception_info;
+ for (int i = 0; i < n; ++i)
+ {
+ if (__throw_type_match_rtti (spec[i], p->type, p->value))
+ throw;
+ }
+ }
+
+ const std::type_info &bad_exc = typeid (std::bad_exception);
+ for (int i = 0; i < n; ++i)
+ {
+ if (__throw_type_match_rtti (spec[i], &bad_exc, p->value))
+ throw std::bad_exception ();
+ }
+
+ terminate ();
+ }
+}
+
+extern "C" void
+__throw_bad_cast (void)
+{
+ throw std::bad_cast ();
+}
+
+extern "C" void
+__throw_bad_typeid (void)
+{
+ throw std::bad_typeid ();
+}
+
+/* Has the current exception been caught? */
+
+bool
+std::uncaught_exception ()
+{
+ cp_eh_info *p = __cp_eh_info ();
+ return p && ! p->caught;
+}
+
+const char * std::exception::
+what () const
+{
+ return typeid (*this).name ();
+}
diff --git a/contrib/gcc/cp/expr.c b/contrib/gcc/cp/expr.c
index 99a611e..4c3d8b6 100644
--- a/contrib/gcc/cp/expr.c
+++ b/contrib/gcc/cp/expr.c
@@ -21,18 +21,24 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include "system.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
#include "expr.h"
#include "cp-tree.h"
+#include "toplev.h"
-#undef NULL
-#define NULL 0
+#if 0
+static tree extract_aggr_init PROTO((tree, tree));
+static tree extract_scalar_init PROTO((tree, tree));
+#endif
+static rtx cplus_expand_expr PROTO((tree, rtx, enum machine_mode,
+ enum expand_modifier));
/* Hook used by expand_expr to expand language-specific tree codes. */
-rtx
+static rtx
cplus_expand_expr (exp, target, tmode, modifier)
tree exp;
rtx target;
@@ -42,11 +48,10 @@ cplus_expand_expr (exp, target, tmode, modifier)
tree type = TREE_TYPE (exp);
register enum machine_mode mode = TYPE_MODE (type);
register enum tree_code code = TREE_CODE (exp);
- rtx original_target = target;
int ignore = target == const0_rtx;
if (ignore)
- target = 0, original_target = 0;
+ target = 0;
/* No sense saving up arithmetic to be done
if it's all in the wrong mode to form part of an address.
@@ -57,7 +62,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
switch (code)
{
- case NEW_EXPR:
+ case AGGR_INIT_EXPR:
{
/* Something needs to be initialized, but we didn't know
where that thing was when building the tree. For example,
@@ -74,8 +79,6 @@ cplus_expand_expr (exp, target, tmode, modifier)
tree func = TREE_OPERAND (exp, 0);
tree args = TREE_OPERAND (exp, 1);
tree type = TREE_TYPE (exp), slot;
- tree fn_type = TREE_TYPE (TREE_TYPE (func));
- tree return_type = TREE_TYPE (fn_type);
tree call_exp;
rtx call_target, return_target;
int pcc_struct_return = 0;
@@ -84,14 +87,8 @@ cplus_expand_expr (exp, target, tmode, modifier)
`target' represents. SLOT holds the slot for TARGET. */
slot = TREE_OPERAND (exp, 2);
- if (target == 0)
- {
- /* Should always be called with a target in BLKmode case. */
- my_friendly_assert (mode != BLKmode, 205);
- my_friendly_assert (DECL_RTL (slot) != 0, 206);
-
- target = gen_reg_rtx (mode);
- }
+ /* Should always be called with a target. */
+ my_friendly_assert (target != NULL_RTX, 205);
/* The target the initializer will initialize (CALL_TARGET)
must now be directed to initialize the target we are
@@ -110,97 +107,58 @@ cplus_expand_expr (exp, target, tmode, modifier)
parameter value. */
mark_addressable (slot);
if (TREE_PERMANENT (args))
- args = tree_cons (0, build1 (ADDR_EXPR, type, slot),
+ args = expr_tree_cons (0, build1 (ADDR_EXPR, type, slot),
TREE_CHAIN (args));
else
TREE_VALUE (args) = build1 (ADDR_EXPR, type, slot);
call_target = 0;
}
- else if (TREE_CODE (return_type) == REFERENCE_TYPE)
- {
- type = return_type;
- call_target = 0;
- }
else
{
-#ifdef PCC_STATIC_STRUCT_RETURN
- pcc_struct_return = 1;
- call_target = 0;
-#else
call_target = target;
+#ifdef PCC_STATIC_STRUCT_RETURN
+ if (aggregate_value_p (type))
+ {
+ pcc_struct_return = 1;
+ call_target = 0;
+ }
#endif
}
- if (call_target)
- {
- /* Make this a valid memory address now. The code below assumes
- that it can compare rtx and make assumptions based on the
- result. The assumptions are true only if the address was
- valid to begin with. */
- call_target = validize_mem (call_target);
- }
- call_exp = build (CALL_EXPR, type, func, args, 0);
+ call_exp = build (CALL_EXPR, type, func, args, NULL_TREE);
TREE_SIDE_EFFECTS (call_exp) = 1;
return_target = expand_call (call_exp, call_target, ignore);
- if (call_target == 0)
- {
- if (pcc_struct_return)
- {
- extern int flag_access_control;
- int old_ac = flag_access_control;
-
- tree init = build_decl (VAR_DECL, 0, type);
- TREE_ADDRESSABLE (init) = 1;
- DECL_RTL (init) = return_target;
-
- flag_access_control = 0;
- expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
- flag_access_control = old_ac;
-
- if (TYPE_NEEDS_DESTRUCTOR (type))
- {
- init = build_decl (VAR_DECL, 0,
- build_reference_type (type));
- DECL_RTL (init) = XEXP (return_target, 0);
-
- init = maybe_build_cleanup (convert_from_reference (init));
- if (init != NULL_TREE)
- expand_expr (init, 0, 0, 0);
- }
- call_target = return_target = DECL_RTL (slot);
- }
- else
- call_target = return_target;
- }
-
- if (call_target != return_target)
- {
- my_friendly_assert (TYPE_HAS_TRIVIAL_INIT_REF (type), 317);
- if (GET_MODE (return_target) == BLKmode)
- emit_block_move (call_target, return_target, expr_size (exp),
- TYPE_ALIGN (type) / BITS_PER_UNIT);
- else
- emit_move_insn (call_target, return_target);
- }
- if (TREE_CODE (return_type) == REFERENCE_TYPE)
+ if (call_target)
+ /* Trust that the right thing has been done; it's too hard to
+ verify. */
+ return return_target;
+
+ /* If we're suffering under the ancient PCC_STATIC_STRUCT_RETURN
+ calling convention, we need to copy the return value out of
+ the static return buffer into slot. */
+ if (pcc_struct_return)
{
- tree init;
-
- if (GET_CODE (call_target) == REG
- && REGNO (call_target) < FIRST_PSEUDO_REGISTER)
- my_friendly_abort (39);
+ extern int flag_access_control;
+ int old_ac = flag_access_control;
- type = TREE_TYPE (exp);
+ tree init = build_decl (VAR_DECL, NULL_TREE,
+ build_reference_type (type));
+ DECL_RTL (init) = XEXP (return_target, 0);
+ init = convert_from_reference (init);
- init = build (RTL_EXPR, return_type, 0, call_target);
- /* We got back a reference to the type we want. Now initialize
- target with that. */
+ flag_access_control = 0;
expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
+ flag_access_control = old_ac;
+
+ if (TYPE_NEEDS_DESTRUCTOR (type))
+ {
+ init = maybe_build_cleanup (init);
+ if (init != NULL_TREE)
+ expand_expr (init, const0_rtx, VOIDmode, 0);
+ }
}
- if (DECL_RTL (slot) != target)
- emit_move_insn (DECL_RTL (slot), target);
return DECL_RTL (slot);
}
@@ -226,13 +184,16 @@ 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;
- }
+ case VEC_INIT_EXPR:
+ return expand_expr
+ (expand_vec_init
+ (NULL_TREE, TREE_OPERAND (exp, 0),
+ build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2),
+ integer_one_node, 1),
+ TREE_OPERAND (exp, 1), 0), target, tmode, modifier);
+
+ case NEW_EXPR:
+ return expand_expr (build_new_1 (exp), target, tmode, modifier);
default:
break;
@@ -278,19 +239,7 @@ fixup_result_decl (decl, result)
}
}
-/* Return nonzero iff DECL is memory-based. The DECL_RTL of
- certain const variables might be a CONST_INT, or a REG
- in some cases. We cannot use `memory_operand' as a test
- here because on most RISC machines, a variable's address
- is not, by itself, a legitimate address. */
-
-int
-decl_in_memory_p (decl)
- tree decl;
-{
- return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM;
-}
-
+#if 0
/* Expand this initialization inline and see if it's simple enough that
it can be done at compile-time. */
@@ -333,8 +282,8 @@ extract_scalar_init (decl, init)
to = XEXP (r, 0);
- if (! (to == value ||
- (GET_CODE (to) == SUBREG && XEXP (to, 0) == value)))
+ if (! (to == value
+ || (GET_CODE (to) == SUBREG && XEXP (to, 0) == value)))
return 0;
r = XEXP (r, 1);
@@ -351,6 +300,7 @@ extract_scalar_init (decl, init)
return t;
}
+#endif
int
extract_init (decl, init)
@@ -358,6 +308,7 @@ extract_init (decl, init)
{
return 0;
+#if 0
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
init = extract_aggr_init (decl, init);
@@ -369,4 +320,93 @@ extract_init (decl, init)
DECL_INITIAL (decl) = init;
return 1;
+#endif
+}
+
+void
+do_case (start, end)
+ tree start, end;
+{
+ tree value1 = NULL_TREE, value2 = NULL_TREE, label;
+
+ if (start != NULL_TREE && TREE_TYPE (start) != NULL_TREE
+ && POINTER_TYPE_P (TREE_TYPE (start)))
+ error ("pointers are not permitted as case values");
+
+ if (end && pedantic)
+ pedwarn ("ANSI C++ forbids range expressions in switch statement");
+
+ if (processing_template_decl)
+ {
+ add_tree (build_min_nt (CASE_LABEL, start, end));
+ return;
+ }
+
+ if (start)
+ value1 = check_cp_case_value (start);
+ if (end)
+ value2 = check_cp_case_value (end);
+
+ label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+
+ if (value1 != error_mark_node
+ && value2 != error_mark_node)
+ {
+ tree duplicate;
+ int success;
+
+ if (end)
+ success = pushcase_range (value1, value2, convert_and_check,
+ label, &duplicate);
+ else if (start)
+ success = pushcase (value1, convert_and_check, label, &duplicate);
+ else
+ success = pushcase (NULL_TREE, 0, label, &duplicate);
+
+ if (success == 1)
+ {
+ if (end)
+ error ("case label not within a switch statement");
+ else if (start)
+ cp_error ("case label `%E' not within a switch statement", start);
+ else
+ error ("default label not within a switch statement");
+ }
+ else if (success == 2)
+ {
+ if (end)
+ {
+ error ("duplicate (or overlapping) case value");
+ cp_error_at ("this is the first entry overlapping that value",
+ duplicate);
+ }
+ else if (start)
+ {
+ cp_error ("duplicate case value `%E'", start);
+ cp_error_at ("previously used here", duplicate);
+ }
+ else
+ {
+ error ("multiple default labels in one switch");
+ cp_error_at ("this is the first default label", duplicate);
+ }
+ }
+ else if (success == 3)
+ warning ("case value out of range");
+ else if (success == 4)
+ warning ("empty range specified");
+ else if (success == 5)
+ {
+ if (end)
+ error ("case label within scope of cleanup or variable array");
+ else if (! start)
+ error ("`default' label within scope of cleanup or variable array");
+ else
+ cp_error ("case label `%E' within scope of cleanup or variable array", start);
+ }
+ }
+ if (start)
+ define_case_label (label);
+ else
+ define_case_label (NULL_TREE);
}
diff --git a/contrib/gcc/cp/friend.c b/contrib/gcc/cp/friend.c
new file mode 100644
index 0000000..58747ef
--- /dev/null
+++ b/contrib/gcc/cp/friend.c
@@ -0,0 +1,484 @@
+/* Help friends in C++.
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "rtl.h"
+#include "cp-tree.h"
+#include "flags.h"
+#include "output.h"
+#include "toplev.h"
+
+static void add_friend PROTO((tree, tree));
+static void add_friends PROTO((tree, tree, tree));
+
+/* Friend data structures are described in cp-tree.h. */
+
+int
+is_friend (type, supplicant)
+ tree type, supplicant;
+{
+ int declp;
+ register tree list;
+ tree context;
+
+ if (supplicant == NULL_TREE || type == NULL_TREE)
+ return 0;
+
+ declp = (TREE_CODE_CLASS (TREE_CODE (supplicant)) == 'd');
+
+ if (declp)
+ /* It's a function decl. */
+ {
+ tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type));
+ tree name = DECL_NAME (supplicant);
+ tree ctype;
+
+ if (DECL_FUNCTION_MEMBER_P (supplicant))
+ ctype = DECL_CLASS_CONTEXT (supplicant);
+ else
+ ctype = NULL_TREE;
+
+ for (; list ; list = TREE_CHAIN (list))
+ {
+ if (name == TREE_PURPOSE (list))
+ {
+ tree friends = TREE_VALUE (list);
+ for (; friends ; friends = TREE_CHAIN (friends))
+ {
+ if (comptypes (ctype, TREE_PURPOSE (friends), 1))
+ return 1;
+
+ if (TREE_VALUE (friends) == NULL_TREE)
+ continue;
+
+ if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL)
+ {
+ if (is_specialization_of (supplicant,
+ TREE_VALUE (friends)))
+ return 1;
+
+ continue;
+ }
+
+ /* FIXME: The use of comptypes here is bogus, since
+ two specializations of a template with non-type
+ parameters may have the same type, but be
+ different. */
+ if (comptypes (TREE_TYPE (supplicant),
+ TREE_TYPE (TREE_VALUE (friends)), 1))
+ return 1;
+ }
+ break;
+ }
+ }
+ }
+ else
+ /* It's a type. */
+ {
+ if (type == supplicant)
+ return 1;
+
+ list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type)));
+ for (; list ; list = TREE_CHAIN (list))
+ {
+ tree t = TREE_VALUE (list);
+
+ if (TREE_CODE (t) == TEMPLATE_DECL ?
+ is_specialization_of (TYPE_MAIN_DECL (supplicant), t) :
+ comptypes (supplicant, t, 1))
+ return 1;
+ }
+ }
+
+ if (declp && DECL_FUNCTION_MEMBER_P (supplicant))
+ context = DECL_CLASS_CONTEXT (supplicant);
+ else if (! declp)
+ /* Local classes have the same access as the enclosing function. */
+ context = hack_decl_function_context (TYPE_MAIN_DECL (supplicant));
+ else
+ context = NULL_TREE;
+
+ /* A namespace is not friend to anybody. */
+ if (context && TREE_CODE (context) == NAMESPACE_DECL)
+ context = NULL_TREE;
+
+ if (context)
+ return is_friend (type, context);
+
+ return 0;
+}
+
+/* Add a new friend to the friends of the aggregate type TYPE.
+ DECL is the FUNCTION_DECL of the friend being added. */
+
+static void
+add_friend (type, decl)
+ tree type, decl;
+{
+ tree typedecl = TYPE_MAIN_DECL (type);
+ tree list = DECL_FRIENDLIST (typedecl);
+ tree name = DECL_NAME (decl);
+
+ while (list)
+ {
+ if (name == TREE_PURPOSE (list))
+ {
+ tree friends = TREE_VALUE (list);
+ for (; friends ; friends = TREE_CHAIN (friends))
+ {
+ if (decl == TREE_VALUE (friends))
+ {
+ cp_warning ("`%D' is already a friend of class `%T'",
+ decl, type);
+ cp_warning_at ("previous friend declaration of `%D'",
+ TREE_VALUE (friends));
+ return;
+ }
+ }
+ TREE_VALUE (list) = tree_cons (error_mark_node, decl,
+ TREE_VALUE (list));
+ return;
+ }
+ list = TREE_CHAIN (list);
+ }
+ DECL_FRIENDLIST (typedecl)
+ = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
+ DECL_FRIENDLIST (typedecl));
+ if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR])
+ {
+ tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
+ if (parmtypes && TREE_CHAIN (parmtypes))
+ {
+ tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes));
+ if (TREE_CODE (parmtype) == REFERENCE_TYPE
+ && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl))
+ TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1;
+ }
+ }
+}
+
+/* Declare that every member function NAME in FRIEND_TYPE
+ (which may be NULL_TREE) is a friend of type TYPE. */
+
+static void
+add_friends (type, name, friend_type)
+ tree type, name, friend_type;
+{
+ tree typedecl = TYPE_MAIN_DECL (type);
+ tree list = DECL_FRIENDLIST (typedecl);
+
+ while (list)
+ {
+ if (name == TREE_PURPOSE (list))
+ {
+ tree friends = TREE_VALUE (list);
+ while (friends && TREE_PURPOSE (friends) != friend_type)
+ friends = TREE_CHAIN (friends);
+ if (friends)
+ {
+ if (friend_type)
+ warning ("method `%s::%s' is already a friend of class",
+ TYPE_NAME_STRING (friend_type),
+ IDENTIFIER_POINTER (name));
+ else
+ warning ("function `%s' is already a friend of class `%s'",
+ IDENTIFIER_POINTER (name),
+ IDENTIFIER_POINTER (DECL_NAME (typedecl)));
+ }
+ else
+ TREE_VALUE (list) = tree_cons (friend_type, NULL_TREE,
+ TREE_VALUE (list));
+ return;
+ }
+ list = TREE_CHAIN (list);
+ }
+ DECL_FRIENDLIST (typedecl)
+ = tree_cons (name,
+ build_tree_list (friend_type, NULL_TREE),
+ DECL_FRIENDLIST (typedecl));
+ if (! strncmp (IDENTIFIER_POINTER (name),
+ IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]),
+ strlen (IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]))))
+ {
+ TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
+ sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists");
+ }
+}
+
+/* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already
+ been defined, we make all of its member functions friends of
+ TYPE. If not, we make it a pending friend, which can later be added
+ when its definition is seen. If a type is defined, then its TYPE_DECL's
+ DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend
+ classes that are not defined. If a type has not yet been defined,
+ then the DECL_WAITING_FRIENDS contains a list of types
+ waiting to make it their friend. Note that these two can both
+ be in use at the same time! */
+
+void
+make_friend_class (type, friend_type)
+ tree type, friend_type;
+{
+ tree classes;
+ int is_template_friend;
+
+ if (IS_SIGNATURE (type))
+ {
+ error ("`friend' declaration in signature definition");
+ return;
+ }
+ if (IS_SIGNATURE (friend_type))
+ {
+ error ("signature type `%s' declared `friend'",
+ IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type)));
+ return;
+ }
+ if (processing_template_decl > template_class_depth (type))
+ /* If the TYPE is a template then it makes sense for it to be
+ friends with itself; this means that each instantiation is
+ friends with all other instantiations. */
+ is_template_friend = 1;
+ else if (comptypes (type, friend_type, 1))
+ {
+ pedwarn ("class `%s' is implicitly friends with itself",
+ TYPE_NAME_STRING (type));
+ return;
+ }
+ else
+ is_template_friend = 0;
+
+ GNU_xref_hier (type, friend_type, 0, 0, 1);
+
+ if (is_template_friend)
+ friend_type = CLASSTYPE_TI_TEMPLATE (friend_type);
+
+ classes = CLASSTYPE_FRIEND_CLASSES (type);
+ while (classes
+ /* Stop if we find the same type on the list. */
+ && !(TREE_CODE (TREE_VALUE (classes)) == TEMPLATE_DECL ?
+ friend_type == TREE_VALUE (classes) :
+ comptypes (TREE_VALUE (classes), friend_type, 1)))
+ classes = TREE_CHAIN (classes);
+ if (classes)
+ cp_warning ("`%T' is already a friend of `%T'",
+ TREE_VALUE (classes), type);
+ else
+ {
+ CLASSTYPE_FRIEND_CLASSES (type)
+ = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
+ }
+}
+
+/* Main friend processor. This is large, and for modularity purposes,
+ has been removed from grokdeclarator. It returns `void_type_node'
+ to indicate that something happened, though a FIELD_DECL is
+ not returned.
+
+ CTYPE is the class this friend belongs to.
+
+ DECLARATOR is the name of the friend.
+
+ DECL is the FUNCTION_DECL that the friend is.
+
+ In case we are parsing a friend which is part of an inline
+ definition, we will need to store PARM_DECL chain that comes
+ with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL.
+
+ FLAGS is just used for `grokclassfn'.
+
+ QUALS say what special qualifies should apply to the object
+ pointed to by `this'. */
+
+tree
+do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
+ tree ctype, declarator, decl, parmdecls;
+ enum overload_flags flags;
+ tree quals;
+ int funcdef_flag;
+{
+ int is_friend_template = 0;
+
+ /* Every decl that gets here is a friend of something. */
+ DECL_FRIEND_P (decl) = 1;
+
+ if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+ {
+ declarator = TREE_OPERAND (declarator, 0);
+ if (TREE_CODE (declarator) == LOOKUP_EXPR)
+ declarator = TREE_OPERAND (declarator, 0);
+ if (is_overloaded_fn (declarator))
+ declarator = DECL_NAME (get_first_fn (declarator));
+ }
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ is_friend_template = processing_template_decl >
+ template_class_depth (current_class_type);
+
+ if (ctype)
+ {
+ tree cname = TYPE_NAME (ctype);
+ if (TREE_CODE (cname) == TYPE_DECL)
+ cname = DECL_NAME (cname);
+
+ /* A method friend. */
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ if (flags == NO_SPECIAL && ctype && declarator == cname)
+ DECL_CONSTRUCTOR_P (decl) = 1;
+
+ /* This will set up DECL_ARGUMENTS for us. */
+ grokclassfn (ctype, cname, decl, flags, quals);
+
+ if (is_friend_template)
+ decl = DECL_TI_TEMPLATE (push_template_decl (decl));
+
+ if (TYPE_SIZE (ctype) != 0 && template_class_depth (ctype) == 0)
+ decl = check_classfn (ctype, decl);
+
+ /* TYPE_BEING_DEFINED is a hack for nested classes having
+ member functions of the enclosing class as friends. Will
+ go away as parsing of classes gets rewritten. */
+ if (TREE_TYPE (decl) != error_mark_node)
+ {
+ if (TYPE_BEING_DEFINED (ctype) ||
+ TYPE_SIZE (ctype) || template_class_depth (ctype) > 0)
+ add_friend (current_class_type, decl);
+ else
+ cp_error ("member `%D' declared as friend before type `%T' defined",
+ decl, ctype);
+ }
+ }
+ else
+ {
+ /* Possibly a bunch of method friends. */
+
+ /* Get the class they belong to. */
+ tree ctype = IDENTIFIER_TYPE_VALUE (cname);
+ tree fields = lookup_fnfields (TYPE_BINFO (ctype), declarator, 0);
+
+ if (fields)
+ add_friends (current_class_type, declarator, ctype);
+ else
+ cp_error ("method `%D' is not a member of class `%T'",
+ declarator, ctype);
+ decl = void_type_node;
+ }
+ }
+ else if (TREE_CODE (decl) == FUNCTION_DECL
+ && (MAIN_NAME_P (declarator)
+ || (IDENTIFIER_LENGTH (declarator) > 10
+ && IDENTIFIER_POINTER (declarator)[0] == '_'
+ && IDENTIFIER_POINTER (declarator)[1] == '_'
+ && strncmp (IDENTIFIER_POINTER (declarator)+2,
+ "builtin_", 8) == 0)))
+ {
+ /* raw "main", and builtin functions never gets overloaded,
+ but they can become friends. */
+ add_friend (current_class_type, decl);
+ DECL_FRIEND_P (decl) = 1;
+ decl = void_type_node;
+ }
+ /* A global friend.
+ @@ or possibly a friend from a base class ?!? */
+ else if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ /* Friends must all go through the overload machinery,
+ even though they may not technically be overloaded.
+
+ Note that because classes all wind up being top-level
+ in their scope, their friend wind up in top-level scope as well. */
+ DECL_ASSEMBLER_NAME (decl)
+ = build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)),
+ TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
+ DECL_ARGUMENTS (decl) = parmdecls;
+ if (funcdef_flag)
+ DECL_CLASS_CONTEXT (decl) = current_class_type;
+
+ if (! DECL_USE_TEMPLATE (decl))
+ {
+ /* We can call pushdecl here, because the TREE_CHAIN of this
+ FUNCTION_DECL is not needed for other purposes. Don't do this
+ for a template instantiation. */
+ if (!is_friend_template)
+ {
+ /* However, we don't call pushdecl() for a friend
+ function of a template class, since in general,
+ such a declaration depends on template
+ parameters. Instead, we call pushdecl when the
+ class is instantiated. */
+ if (template_class_depth (current_class_type) == 0)
+ decl = pushdecl (decl);
+ }
+ else
+ decl = push_template_decl (decl);
+
+ if (! funcdef_flag && ! flag_guiding_decls && ! is_friend_template
+ && current_template_parms && uses_template_parms (decl))
+ {
+ static int explained;
+ cp_warning ("friend declaration `%#D'", decl);
+ warning (" declares a non-template function");
+ if (! explained)
+ {
+ warning (" (if this is not what you intended, make sure");
+ warning (" the function template has already been declared,");
+ warning (" and add <> after the function name here)");
+ explained = 1;
+ }
+ }
+ }
+
+ make_decl_rtl (decl, NULL_PTR, 1);
+ add_friend (current_class_type,
+ is_friend_template ? DECL_TI_TEMPLATE (decl) : decl);
+ DECL_FRIEND_P (decl) = 1;
+ }
+ else
+ {
+ /* @@ Should be able to ingest later definitions of this function
+ before use. */
+ tree decl = lookup_name_nonclass (declarator);
+ if (decl == NULL_TREE)
+ {
+ cp_warning ("implicitly declaring `%T' as struct", declarator);
+ decl = xref_tag (record_type_node, declarator, NULL_TREE, 1);
+ decl = TYPE_MAIN_DECL (decl);
+ }
+
+ /* Allow abbreviated declarations of overloaded functions,
+ but not if those functions are really class names. */
+ if (TREE_CODE (decl) == TREE_LIST && TREE_TYPE (TREE_PURPOSE (decl)))
+ {
+ cp_warning ("`friend %T' archaic, use `friend class %T' instead",
+ declarator, declarator);
+ decl = TREE_TYPE (TREE_PURPOSE (decl));
+ }
+
+ if (TREE_CODE (decl) == TREE_LIST)
+ add_friends (current_class_type, TREE_PURPOSE (decl), NULL_TREE);
+ else
+ make_friend_class (current_class_type, TREE_TYPE (decl));
+ decl = void_type_node;
+ }
+ return decl;
+}
diff --git a/contrib/gcc/cp/g++.1 b/contrib/gcc/cp/g++.1
index ae016fa..5101d5f 100644
--- a/contrib/gcc/cp/g++.1
+++ b/contrib/gcc/cp/g++.1
@@ -430,38 +430,6 @@ differently depending on whether `\|\c
testing both of these predefined macros you can distinguish four
situations: GNU C, traditional GNU C, other ANSI C compilers, and
other old C compilers.
-.TP
-\ \ \ \(bu
-In the preprocessor, comments convert to nothing at all, rather than
-to a space. This allows traditional token concatenation.
-.TP
-\ \ \ \(bu
-In the preprocessor, macro arguments are recognized within string
-constants in a macro definition (and their values are stringified,
-though without additional quote marks, when they appear in such a
-context). The preprocessor always considers a string constant to end
-at a newline.
-.TP
-\ \ \ \(bu
-The preprocessor does not predefine the macro \c
-.B __STDC__\c
-\& when you use
-`\|\c
-.B \-traditional\c
-\&\|', but still predefines\c
-.B __GNUC__\c
-\& (since the GNU extensions indicated by
-.B __GNUC__\c
-\& are not affected by
-`\|\c
-.B \-traditional\c
-\&\|'). If you need to write header files that work
-differently depending on whether `\|\c
-.B \-traditional\c
-\&\|' is in use, by
-testing both of these predefined macros you can distinguish four
-situations: GNU C, traditional GNU C, other ANSI C compilers, and
-other old C compilers.
.PP
.TP
\ \ \ \(bu
diff --git a/contrib/gcc/cp/g++spec.c b/contrib/gcc/cp/g++spec.c
new file mode 100644
index 0000000..542ca06
--- /dev/null
+++ b/contrib/gcc/cp/g++spec.c
@@ -0,0 +1,269 @@
+/* Specific flags and argument handling of the C++ front-end.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+
+#include "system.h"
+
+#include "gansidecl.h"
+
+/* This bit is set if we saw a `-xfoo' language specification. */
+#define LANGSPEC (1<<1)
+/* This bit is set if they did `-lm' or `-lmath'. */
+#define MATHLIB (1<<2)
+/* This bit is set if they did `-lc'. */
+#define WITHLIBC (1<<3)
+
+#ifndef MATH_LIBRARY
+#define MATH_LIBRARY "-lm"
+#endif
+#ifndef NEED_MATH_LIBRARY
+#define NEED_MATH_LIBRARY 1 /* Default is pass MATH_LIBRARY to linker */
+#endif
+
+extern char *xmalloc PROTO((size_t));
+
+void
+lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
+ void (*fn)();
+ int *in_argc;
+ char ***in_argv;
+ int *in_added_libraries;
+{
+ int i, j;
+
+ /* If non-zero, the user gave us the `-v' flag. */
+ int saw_verbose_flag = 0;
+
+ /* This will be 0 if we encounter a situation where we should not
+ link in libstdc++. */
+ int library = 1;
+
+ /* The number of arguments being added to what's in argv, other than
+ libraries. We use this to track the number of times we've inserted
+ -xc++/-xnone. */
+ int added = 2;
+
+ /* Used to track options that take arguments, so we don't go wrapping
+ those with -xc++/-xnone. */
+ char *quote = NULL;
+
+ /* The new argument list will be contained in this. */
+ char **arglist;
+
+ /* Non-zero if we saw a `-xfoo' language specification on the
+ command line. Used to avoid adding our own -xc++ if the user
+ already gave a language for the file. */
+ int saw_speclang = 0;
+
+ /* "-lm" or "-lmath" if it appears on the command line. */
+ char *saw_math = 0;
+
+ /* "-lc" if it appears on the command line. */
+ char *saw_libc = 0;
+
+ /* An array used to flag each argument that needs a bit set for
+ LANGSPEC, MATHLIB, or WITHLIBC. */
+ int *args;
+
+ /* By default, we throw on the math library. */
+ int need_math = NEED_MATH_LIBRARY;
+
+ /* The total number of arguments with the new stuff. */
+ int argc;
+
+ /* The argument list. */
+ char **argv;
+
+ /* The number of libraries added in. */
+ int added_libraries;
+
+ /* The total number of arguments with the new stuff. */
+ int num_args = 1;
+
+ argc = *in_argc;
+ argv = *in_argv;
+ added_libraries = *in_added_libraries;
+
+ args = (int *) xmalloc (argc * sizeof (int));
+ bzero ((char *) args, argc * sizeof (int));
+
+ for (i = 1; i < argc; i++)
+ {
+ /* If the previous option took an argument, we swallow it here. */
+ if (quote)
+ {
+ quote = NULL;
+ continue;
+ }
+
+ /* We don't do this anymore, since we don't get them with minus
+ signs on them. */
+ if (argv[i][0] == '\0' || argv[i][1] == '\0')
+ continue;
+
+ if (argv[i][0] == '-')
+ {
+ if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0
+ || strcmp (argv[i], "-nodefaultlibs") == 0))
+ {
+ library = 0;
+ }
+ else if (strcmp (argv[i], "-lm") == 0
+ || strcmp (argv[i], "-lmath") == 0
+#ifdef ALT_LIBM
+ || strcmp (argv[i], ALT_LIBM) == 0
+#endif
+ )
+ {
+ args[i] |= MATHLIB;
+ need_math = 0;
+ }
+ else if (strcmp (argv[i], "-lc") == 0)
+ args[i] |= WITHLIBC;
+ else if (strcmp (argv[i], "-v") == 0)
+ {
+ saw_verbose_flag = 1;
+ if (argc == 2)
+ {
+ /* If they only gave us `-v', don't try to link
+ in libg++. */
+ library = 0;
+ }
+ }
+ else if (strncmp (argv[i], "-x", 2) == 0)
+ saw_speclang = 1;
+ else if (((argv[i][2] == '\0'
+ && (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
+ || strcmp (argv[i], "-Tdata") == 0))
+ quote = argv[i];
+ else if (library != 0 && ((argv[i][2] == '\0'
+ && (char *) strchr ("cSEM", argv[i][1]) != NULL)
+ || strcmp (argv[i], "-MM") == 0))
+ {
+ /* Don't specify libraries if we won't link, since that would
+ cause a warning. */
+ library = 0;
+ added -= 2;
+ }
+ else
+ /* Pass other options through. */
+ continue;
+ }
+ else
+ {
+ int len;
+
+ if (saw_speclang)
+ {
+ saw_speclang = 0;
+ continue;
+ }
+
+ /* If the filename ends in .c or .i, put options around it.
+ But not if a specified -x option is currently active. */
+ len = strlen (argv[i]);
+ if (len > 2
+ && (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i')
+ && argv[i][len - 2] == '.')
+ {
+ args[i] |= LANGSPEC;
+ added += 2;
+ }
+ }
+ }
+
+ if (quote)
+ (*fn) ("argument to `%s' missing\n", quote);
+
+ /* If we know we don't have to do anything, bail now. */
+ if (! added && ! library)
+ {
+ free (args);
+ return;
+ }
+
+ num_args = argc + added + need_math;
+ arglist = (char **) xmalloc (num_args * sizeof (char *));
+
+ /* NOTE: We start at 1 now, not 0. */
+ for (i = 0, j = 0; i < argc; i++, j++)
+ {
+ arglist[j] = argv[i];
+
+ /* Make sure -lstdc++ is before the math library, since libstdc++
+ itself uses those math routines. */
+ if (!saw_math && (args[i] & MATHLIB) && library)
+ {
+ --j;
+ saw_math = argv[i];
+ }
+
+ if (!saw_libc && (args[i] & WITHLIBC) && library)
+ {
+ --j;
+ saw_libc = argv[i];
+ }
+
+ /* Wrap foo.c and foo.i files in a language specification to
+ force the gcc compiler driver to run cc1plus on them. */
+ if (args[i] & LANGSPEC)
+ {
+ int len = strlen (argv[i]);
+ if (argv[i][len - 1] == 'i')
+ arglist[j++] = "-xc++-cpp-output";
+ else
+ arglist[j++] = "-xc++";
+ arglist[j++] = argv[i];
+ arglist[j] = "-xnone";
+ }
+ }
+
+ /* Add `-lstdc++' if we haven't already done so. */
+ if (library)
+ {
+ arglist[j++] = "-lstdc++";
+ added_libraries++;
+ }
+ if (saw_math)
+ arglist[j++] = saw_math;
+ else if (library && need_math)
+ {
+ arglist[j++] = MATH_LIBRARY;
+ added_libraries++;
+ }
+ if (saw_libc)
+ arglist[j++] = saw_libc;
+
+ arglist[j] = NULL;
+
+ *in_argc = j;
+ *in_argv = arglist;
+ *in_added_libraries = added_libraries;
+}
+
+/* Called before linking. Returns 0 on success and -1 on failure. */
+int lang_specific_pre_link () /* Not used for C++. */
+{
+ return 0;
+}
+
+/* Number of extra output files that lang_specific_pre_link may generate. */
+int lang_specific_extra_outfiles = 0; /* Not used for C++. */
diff --git a/contrib/gcc/cp/gxx.gperf b/contrib/gcc/cp/gxx.gperf
index e5465e8..71538567 100644
--- a/contrib/gcc/cp/gxx.gperf
+++ b/contrib/gcc/cp/gxx.gperf
@@ -5,24 +5,31 @@ struct resword { char *name; short token; enum rid rid;};
%%
__alignof, ALIGNOF, NORID
__alignof__, ALIGNOF, NORID
-__asm, GCC_ASM_KEYWORD, NORID
-__asm__, GCC_ASM_KEYWORD, NORID
+__asm, ASM_KEYWORD, NORID
+__asm__, ASM_KEYWORD, NORID
__attribute, ATTRIBUTE, NORID
__attribute__, ATTRIBUTE, NORID
-__const, TYPE_QUAL, RID_CONST
-__const__, TYPE_QUAL, RID_CONST
+__complex, TYPESPEC, RID_COMPLEX
+__complex__, TYPESPEC, RID_COMPLEX
+__const, CV_QUALIFIER, RID_CONST
+__const__, CV_QUALIFIER, RID_CONST
__extension__, EXTENSION, NORID
+__imag, IMAGPART, NORID
+__imag__, IMAGPART, NORID
__inline, SCSPEC, RID_INLINE
__inline__, SCSPEC, RID_INLINE
__label__, LABEL, NORID
+__null, CONSTANT, RID_NULL
+__real, REALPART, NORID
+__real__, REALPART, NORID
__signature__, AGGR, RID_SIGNATURE /* Extension */,
__signed, TYPESPEC, RID_SIGNED
__signed__, TYPESPEC, RID_SIGNED
__sigof__, SIGOF, NORID /* Extension */,
__typeof, TYPEOF, NORID
__typeof__, TYPEOF, NORID
-__volatile, TYPE_QUAL, RID_VOLATILE
-__volatile__, TYPE_QUAL, RID_VOLATILE
+__volatile, CV_QUALIFIER, RID_VOLATILE
+__volatile__, CV_QUALIFIER, RID_VOLATILE
__wchar_t, TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,
asm, ASM_KEYWORD, NORID,
and, ANDAND, NORID,
@@ -37,7 +44,7 @@ catch, CATCH, NORID,
char, TYPESPEC, RID_CHAR,
class, AGGR, RID_CLASS,
compl, '~', NORID,
-const, TYPE_QUAL, RID_CONST,
+const, CV_QUALIFIER, RID_CONST,
const_cast, CONST_CAST, NORID,
continue, CONTINUE, NORID,
default, DEFAULT, NORID,
@@ -66,7 +73,6 @@ not_eq, EQCOMPARE, NORID,
operator, OPERATOR, NORID,
or, OROR, NORID,
or_eq, ASSIGN, NORID,
-overload, OVERLOAD, NORID,
private, VISSPEC, RID_PRIVATE,
protected, VISSPEC, RID_PROTECTED,
public, VISSPEC, RID_PUBLIC,
@@ -96,7 +102,7 @@ unsigned, TYPESPEC, RID_UNSIGNED,
using, USING, NORID,
virtual, SCSPEC, RID_VIRTUAL,
void, TYPESPEC, RID_VOID,
-volatile, TYPE_QUAL, RID_VOLATILE,
+volatile, CV_QUALIFIER, RID_VOLATILE,
while, WHILE, NORID,
xor, '^', NORID,
xor_eq, ASSIGN, NORID,
diff --git a/contrib/gcc/cp/gxxint.texi b/contrib/gcc/cp/gxxint.texi
index 015a33c..7cb57f2 100644
--- a/contrib/gcc/cp/gxxint.texi
+++ b/contrib/gcc/cp/gxxint.texi
@@ -9,7 +9,7 @@
@chapter Internal Architecture of the Compiler
This is meant to describe the C++ front-end for gcc in detail.
-Questions and comments to mrs@@cygnus.com.
+Questions and comments to Benjamin Kosnik @code{<bkoz@@cygnus.com>}.
@menu
* Limitations of g++::
@@ -26,6 +26,7 @@ Questions and comments to mrs@@cygnus.com.
* Copying Objects::
* Exception Handling::
* Free Store::
+* Mangling:: Function name mangling for C++ and Java
* Concept Index::
@end menu
@@ -53,38 +54,6 @@ Access checking is unimplemented for nested types.
@item
@code{volatile} is not implemented in general.
-@cindex pointers to members
-@item
-Pointers to members are only minimally supported, and there are places
-where the grammar doesn't even properly accept them yet.
-
-@cindex multiple inheritance
-@item
-@code{this} will be wrong in virtual members functions defined in a
-virtual base class, when they are overridden in a derived class, when
-called via a non-left most object.
-
-An example would be:
-
-@example
-extern "C" int printf(const char*, ...);
-struct A @{ virtual void f() @{ @} @};
-struct B : virtual A @{ int b; B() : b(0) @{@} void f() @{ b++; @} @};
-struct C : B @{@};
-struct D : B @{@};
-struct E : C, D @{@};
-int main()
-@{
- E e;
- C& c = e; D& d = e;
- c.f(); d.f();
- printf ("C::b = %d, D::b = %d\n", e.C::b, e.D::b);
- return 0;
-@}
-@end example
-
-This will print out 2, 0, instead of 1,1.
-
@end itemize
@node Routines, Implementation Specifics, Limitations of g++, Top
@@ -269,6 +238,13 @@ The functions @code{convert_to_aggr} and @code{build_method_call} use
a given candidate function (that's how we get the list of candidates for
@code{ideal_candidate}).
+@item The Explicit Keyword
+
+The use of @code{explicit} on a constructor is used by @code{grokdeclarator}
+to set the field @code{DECL_NONCONVERTING_P}. That value is used by
+@code{build_method_call} and @code{build_user_type_conversion_1} to decide
+if a particular constructor should be used as a candidate for conversions.
+
@end itemize
@node Glossary, Macros, Implementation Specifics, Top
@@ -310,9 +286,7 @@ vtables. See also vtable and vfield.
This section describes some of the macros used on trees. The list
should be alphabetical. Eventually all macros should be documented
-here. There are some postscript drawings that can be used to better
-understand from of the more complex data structures, contact Mike Stump
-(@code{mrs@@cygnus.com}) for information about them.
+here.
@table @code
@item BINFO_BASETYPES
@@ -521,18 +495,6 @@ FIELD_DECLs
@end display
-@item DECL_NESTED_TYPENAME
-Holds the fully qualified type name. Example, Base::Derived.
-
-Has values of:
-
- IDENTIFIER_NODEs
-
-What things can this be used on:
-
- TYPE_DECLs
-
-
@item DECL_NAME
Has values of:
@@ -682,6 +644,15 @@ appear in cp-decl.c and cp-decl2.c, so the are a good candidate for
proper fixing, and removal.
+@item TREE_HAS_CONSTRUCTOR
+A flag to indicate when a CALL_EXPR represents a call to a constructor.
+If set, we know that the type of the object, is the complete type of the
+object, and that the value returned is nonnull. When used in this
+fashion, it is an optimization. Can also be used on SAVE_EXPRs to
+indicate when they are of fixed type and nonnull. Can also be used on
+INDIRECT_EXPRs on CALL_EXPRs that represent a call to a constructor.
+
+
@item TREE_PRIVATE
Set for FIELD_DECLs by finish_struct. But not uniformly set.
@@ -859,7 +830,7 @@ get_binfo (VF_BASETYPE_VALUE (vfield), t, 0)
@end example
@noindent
-will return the binfo for the the given vfield.
+will return the binfo for the given vfield.
May or may not be set at @code{modify_vtable_entries} time. Set at
@code{finish_base_struct} time.
@@ -871,7 +842,7 @@ What things can this be used on:
@item VF_DERIVED_VALUE
Identifies the type of the most derived class of the vfield, excluding
-the the class this vfield is for.
+the class this vfield is for.
Set at @code{finish_base_struct} time.
@@ -1217,24 +1188,32 @@ 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.
+arrays. Exception specifications are now handled. Thrown objects are
+now cleaned up all the time. We can now tell if we have an active
+exception being thrown or not (__eh_type != 0). We use this to call
+terminate if someone does a throw; without there being an active
+exception object. uncaught_exception () works. Exception handling
+should work right if you optimize. Exception handling should work with
+-fpic or -fPIC.
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 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.
+-fno-rtti is used. Only works on a SPARC (like Suns) (both -mflat and
+-mno-flat models work), SPARClite, Hitachi SH, i386, arm, rs6000,
+PowerPC, Alpha, mips, VAX, m68k and z8k machines. SPARC v9 may not
+work. HPPA is mostly done, but throwing between a shared library and
+user code doesn't yet work. Some targets have support for data-driven
+unwinding. 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. The new EH code doesn't rely upon the
+__unwind_function for C++ code, instead it creates per function
+unwinders right inside the function, unfortunately, on many platforms
+the definition of RETURN_ADDR_RTX in the tm.h file for the machine port
+is wrong. See below for details on __unwind_function. 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.
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
@@ -1266,12 +1245,13 @@ 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 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.
+Thrown objects are usually allocated on the heap, in the usual way. 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. We should
+extend it so that all small (<4*sizeof(void*)) objects are stored
+directly, instead of allocated on the heap.
When the backend returns a value, it can create new exception regions
that need protecting. The new region should rethrow the object in
@@ -1285,13 +1265,13 @@ Ln: throw value;
copy value onto heap
jump throw (Ln, id, address of copy of value on heap)
- try {
+ try @{
+Lstart: the start of the main EH region
|... ...
+Lend: the end of the main EH region
- } catch (T o) {
+ @} catch (T o) @{
...1
- }
+ @}
Lresume:
nop used to make sure there is something before
the next region ends, if there is one
@@ -1312,7 +1292,7 @@ Lover:
[
[
call throw_type_match
- if (eq) {
+ if (eq) @{
] these lines disappear when there is no catch condition
+Lsregion2:
| ...1
@@ -1320,7 +1300,7 @@ Lover:
|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 --------------------------
@@ -1336,7 +1316,7 @@ Ldone:
start_all_catch emits labels: Lresume,
-#end example
+@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
@@ -1346,7 +1326,7 @@ 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; }
+ 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
@@ -1423,6 +1403,33 @@ 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.
+Or just support DWARF 2 unwind info.
+
+@subsection New Backend Exception Support
+
+This subsection discusses various aspects of the design of the
+data-driven model being implemented for the exception handling backend.
+
+The goal is to generate enough data during the compilation of user code,
+such that we can dynamically unwind through functions at run time with a
+single routine (@code{__throw}) that lives in libgcc.a, built by the
+compiler, and dispatch into associated exception handlers.
+
+This information is generated by the DWARF 2 debugging backend, and
+includes all of the information __throw needs to unwind an arbitrary
+frame. It specifies where all of the saved registers and the return
+address can be found at any point in the function.
+
+Major disadvantages when enabling exceptions are:
+
+@itemize @bullet
+@item
+Code that uses caller saved registers, can't, when flow can be
+transferred into that code from an exception handler. In high performance
+code this should not usually be true, so the effects should be minimal.
+
+@end itemize
+
@subsection Backend Exception Support
The backend must be extended to fully support exceptions. Right now
@@ -1453,7 +1460,7 @@ descriptor that refers to fully contained code that has been eliminated
should also be removed, although not doing this is harmless in terms of
semantics.
-#end itemize
+@end itemize
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.
@@ -1469,9 +1476,9 @@ 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.
+handler. I have a feeling insns might be 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
+transferred 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
@@ -1490,21 +1497,6 @@ 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
@@ -1513,31 +1505,15 @@ 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
+@node Free Store, Mangling, Exception Handling, Top
@section Free Store
-operator new [] adds a magic cookie to the beginning of arrays for which
-the number of elements will be needed by operator delete []. These are
-arrays of objects with destructors and arrays of objects that define
-operator delete [] with the optional size_t argument. This cookie can
-be examined from a program as follows:
+@code{operator new []} adds a magic cookie to the beginning of arrays
+for which the number of elements will be needed by @code{operator delete
+[]}. These are arrays of objects with destructors and arrays of objects
+that define @code{operator delete []} with the optional size_t argument.
+This cookie can be examined from a program as follows:
@example
typedef unsigned long size_t;
@@ -1576,8 +1552,373 @@ The linkage code in g++ is horribly twisted in order to meet two design goals:
To meet the first goal, we defer emission of inlines and vtables until
the end of the translation unit, where we can decide whether or not they
are needed, and how to emit them if they are.
+
+@node Mangling, Concept Index, Free Store, Top
+@section Function name mangling for C++ and Java
+
+Both C++ and Jave provide overloaded function and methods,
+which are methods with the same types but different parameter lists.
+Selecting the correct version is done at compile time.
+Though the overloaded functions have the same name in the source code,
+they need to be translated into different assembler-level names,
+since typical assemblers and linkers cannot handle overloading.
+This process of encoding the parameter types with the method name
+into a unique name is called @dfn{name mangling}. The inverse
+process is called @dfn{demangling}.
+
+It is convenient that C++ and Java use compatible mangling schemes,
+since the makes life easier for tools such as gdb, and it eases
+integration between C++ and Java.
+
+Note there is also a standard "Jave Native Interface" (JNI) which
+implements a different calling convention, and uses a different
+mangling scheme. The JNI is a rather abstract ABI so Java can call methods
+written in C or C++;
+we are concerned here about a lower-level interface primarily
+intended for methods written in Java, but that can also be used for C++
+(and less easily C).
+
+Note that on systems that follow BSD tradition, a C identifier @code{var}
+would get "mangled" into the assembler name @samp{_var}. On such
+systems, all other mangled names are also prefixed by a @samp{_}
+which is not shown in the following examples.
+
+@subsection Method name mangling
+
+C++ mangles a method by emitting the function name, followed by @code{__},
+followed by encodings of any method qualifiers (such as @code{const}),
+followed by the mangling of the method's class,
+followed by the mangling of the parameters, in order.
+
+For example @code{Foo::bar(int, long) const} is mangled
+as @samp{bar__C3Fooil}.
+
+For a constructor, the method name is left out.
+That is @code{Foo::Foo(int, long) const} is mangled
+as @samp{__C3Fooil}.
+
+GNU Java does the same.
+
+@subsection Primitive types
+
+The C++ types @code{int}, @code{long}, @code{short}, @code{char},
+and @code{long long} are mangled as @samp{i}, @samp{l},
+@samp{s}, @samp{c}, and @samp{x}, respectively.
+The corresponding unsigned types have @samp{U} prefixed
+to the mangling. The type @code{signed char} is mangled @samp{Sc}.
+
+The C++ and Java floating-point types @code{float} and @code{double}
+are mangled as @samp{f} and @samp{d} respectively.
+
+The C++ @code{bool} type and the Java @code{boolean} type are
+mangled as @samp{b}.
+
+The C++ @code{wchar_t} and the Java @code{char} types are
+mangled as @samp{w}.
+
+The Java integral types @code{byte}, @code{short}, @code{int}
+and @code{long} are mangled as @samp{c}, @samp{s}, @samp{i},
+and @samp{x}, respectively.
+
+C++ code that has included @code{javatypes.h} will mangle
+the typedefs @code{jbyte}, @code{jshort}, @code{jint}
+and @code{jlong} as respectively @samp{c}, @samp{s}, @samp{i},
+and @samp{x}. (This has not been implemented yet.)
+
+@subsection Mangling of simple names
+
+A simple class, package, template, or namespace name is
+encoded as the number of characters in the name, followed by
+the actual characters. Thus the class @code{Foo}
+is encoded as @samp{3Foo}.
+
+If any of the characters in the name are not alphanumeric
+(i.e not one of the standard ASCII letters, digits, or '_'),
+or the initial character is a digit, then the name is
+mangled as a sequence of encoded Unicode letters.
+A Unicode encoding starts with a @samp{U} to indicate
+that Unicode escapes are used, followed by the number of
+bytes used by the Unicode encoding, followed by the bytes
+representing the encoding. ASSCI letters and
+non-initial digits are encoded without change. However, all
+other characters (including underscore and initial digits) are
+translated into a sequence starting with an underscore,
+followed by the big-endian 4-hex-digit lower-case encoding of the character.
+
+If a method name contains Unicode-escaped characters, the
+entire mangled method name is followed by a @samp{U}.
+
+For example, the method @code{X\u0319::M\u002B(int)} is encoded as
+@samp{M_002b__U6X_0319iU}.
+
+
+@subsection Pointer and reference types
+
+A C++ pointer type is mangled as @samp{P} followed by the
+mangling of the type pointed to.
+
+A C++ reference type as mangled as @samp{R} followed by the
+mangling of the type referenced.
+
+A Java object reference type is equivalent
+to a C++ pointer parameter, so we mangle such an parameter type
+as @samp{P} followed by the mangling of the class name.
+
+@subsection Squangled type compression
+
+Squangling (enabled with the @samp{-fsquangle} option), utilizes
+the @samp{B} code to indicate reuse of a previously
+seen type within an indentifier. Types are recognized in a left to
+right manner and given increasing values, which are
+appended to the code in the standard manner. Ie, multiple digit numbers
+are delimited by @samp{_} characters. A type is considered to be any
+non primitive type, regardless of whether its a parameter, template
+parameter, or entire template. Certain codes are considered modifiers
+of a type, and are not included as part of the type. These are the
+@samp{C}, @samp{V}, @samp{P}, @samp{A}, @samp{R}, and @samp{U} codes,
+denoting constant, volatile, pointer, array, reference, and unsigned.
+These codes may precede a @samp{B} type in order to make the required
+modifications to the type.
+
+For example:
+@example
+template <class T> class class1 @{ @};
+
+template <class T> class class2 @{ @};
+
+class class3 @{ @};
+
+int f(class2<class1<class3> > a ,int b, const class1<class3>&c, class3 *d) @{ @}
+
+ B0 -> class2<class1<class3>
+ B1 -> class1<class3>
+ B2 -> class3
+@end example
+Produces the mangled name @samp{f__FGt6class21Zt6class11Z6class3iRCB1PB2}.
+The int parameter is a basic type, and does not receive a B encoding...
+
+@subsection Qualified names
+
+Both C++ and Java allow a class to be lexically nested inside another
+class. C++ also supports namespaces (not yet implemented by G++).
+Java also supports packages.
+
+These are all mangled the same way: First the letter @samp{Q}
+indicates that we are emitting a qualified name.
+That is followed by the number of parts in the qualified name.
+If that number is 9 or less, it is emitted with no delimiters.
+Otherwise, an underscore is written before and after the count.
+Then follows each part of the qualified name, as described above.
+
+For example @code{Foo::\u0319::Bar} is encoded as
+@samp{Q33FooU5_03193Bar}.
+
+Squangling utilizes the the letter @samp{K} to indicate a
+remembered portion of a qualified name. As qualified names are processed
+for an identifier, the names are numbered and remembered in a
+manner similar to the @samp{B} type compression code.
+Names are recognized left to right, and given increasing values, which are
+appended to the code in the standard manner. ie, multiple digit numbers
+are delimited by @samp{_} characters.
+
+For example
+@example
+class Andrew
+@{
+ class WasHere
+ @{
+ class AndHereToo
+ @{
+ @};
+ @};
+@};
+
+f(Andrew&r1, Andrew::WasHere& r2, Andrew::WasHere::AndHereToo& r3) @{ @}
+
+ K0 -> Andrew
+ K1 -> Andrew::WasHere
+ K2 -> Andrew::WasHere::AndHereToo
+@end example
+Function @samp{f()} would be mangled as :
+@samp{f__FR6AndrewRQ2K07WasHereRQ2K110AndHereToo}
+
+There are some occasions when either a @samp{B} or @samp{K} code could
+be chosen, preference is always given to the @samp{B} code. Ie, the example
+in the section on @samp{B} mangling could have used a @samp{K} code
+instead of @samp{B2}.
+
+@subsection Templates
+
+A class template instantiation is encoded as the letter @samp{t},
+followed by the encoding of the template name, followed
+the number of template parameters, followed by encoding of the template
+parameters. If a template parameter is a type, it is written
+as a @samp{Z} followed by the encoding of the type.
+
+A function template specialization (either an instantiation or an
+explicit specialization) is encoded by an @samp{H} followed by the
+encoding of the template parameters, as described above, followed by an
+@samp{_}, the encoding of the argument types to the template function
+(not the specialization), another @samp{_}, and the return type. (Like
+the argument types, the return type is the return type of the function
+template, not the specialization.) Template parameters in the argument
+and return types are encoded by an @samp{X} for type parameters, or a
+@samp{Y} for constant parameters, an index indicating their position
+in the template parameter list declaration, and their template depth.
+
+@subsection Arrays
+
+C++ array types are mangled by emitting @samp{A}, followed by
+the length of the array, followed by an @samp{_}, followed by
+the mangling of the element type. Of course, normally
+array parameter types decay into a pointer types, so you
+don't see this.
+
+Java arrays are objects. A Java type @code{T[]} is mangled
+as if it were the C++ type @code{JArray<T>}.
+For example @code{java.lang.String[]} is encoded as
+@samp{Pt6JArray1ZPQ34java4lang6String}.
+
+@subsection Static fields
+
+Both C++ and Java classes can have static fields.
+These are allocated statically, and are shared among all instances.
+
+The mangling starts with a prefix (@samp{_} in most systems), which is
+followed by the mangling
+of the class name, followed by the "joiner" and finally the field name.
+The joiner (see @code{JOINER} in @code{cp-tree.h}) is a special
+separator character. For historical reasons (and idiosyncracies
+of assembler syntax) it can @samp{$} or @samp{.} (or even
+@samp{_} on a few systems). If the joiner is @samp{_} then the prefix
+is @samp{__static_} instead of just @samp{_}.
+
+For example @code{Foo::Bar::var} (or @code{Foo.Bar.var} in Java syntax)
+would be encoded as @samp{_Q23Foo3Bar$var} or @samp{_Q23Foo3Bar.var}
+(or rarely @samp{__static_Q23Foo3Bar_var}).
+
+If the name of a static variable needs Unicode escapes,
+the Unicode indicator @samp{U} comes before the "joiner".
+This @code{\u1234Foo::var\u3445} becomes @code{_U8_1234FooU.var_3445}.
+
+@subsection Table of demangling code characters
+
+The following special characters are used in mangling:
+
+@table @samp
+@item A
+Indicates a C++ array type.
+
+@item b
+Encodes the C++ @code{bool} type,
+and the Java @code{boolean} type.
+
+@item B
+Used for squangling. Similar in concept to the 'T' non-squangled code.
+
+@item c
+Encodes the C++ @code{char} type, and the Java @code{byte} type.
+
+@item C
+A modifier to indicate a @code{const} type.
+Also used to indicate a @code{const} member function
+(in which cases it precedes the encoding of the method's class).
+
+@item d
+Encodes the C++ and Java @code{double} types.
+
+@item e
+Indicates extra unknown arguments @code{...}.
+
+@item E
+Indicates the opening parenthesis of an expression.
+
+@item f
+Encodes the C++ and Java @code{float} types.
+
+@item F
+Used to indicate a function type.
+
+@item H
+Used to indicate a template function.
+
+@item i
+Encodes the C++ and Java @code{int} types.
+
+@item J
+Indicates a complex type.
+
+@item K
+Used by squangling to compress qualified names.
+
+@item l
+Encodes the C++ @code{long} type.
+
+@item P
+Indicates a pointer type. Followed by the type pointed to.
+
+@item Q
+Used to mangle qualified names, which arise from nested classes.
+Should also be used for namespaces (?).
+In Java used to mangle package-qualified names, and inner classes.
+
+@item r
+Encodes the GNU C++ @code{long double} type.
+
+@item R
+Indicates a reference type. Followed by the referenced type.
+
+@item s
+Encodes the C++ and java @code{short} types.
+
+@item S
+A modifier that indicates that the following integer type is signed.
+Only used with @code{char}.
+
+Also used as a modifier to indicate a static member function.
+
+@item t
+Indicates a template instantiation.
+
+@item T
+A back reference to a previously seen type.
+
+@item U
+A modifier that indicates that the following integer type is unsigned.
+Also used to indicate that the following class or namespace name
+is encoded using Unicode-mangling.
+
+@item v
+Encodes the C++ and Java @code{void} types.
+
+@item V
+A modified for a @code{const} type or method.
+
+@item w
+Encodes the C++ @code{wchar_t} type, and the Java @code{char} types.
+
+@item W
+Indicates the closing parenthesis of an expression.
+
+@item x
+Encodes the GNU C++ @code{long long} type, and the Java @code{long} type.
+
+@item X
+Encodes a template type parameter, when part of a function type.
+
+@item Y
+Encodes a template constant parameter, when part of a function type.
+
+@item Z
+Used for template type parameters.
+
+@end table
+
+The letters @samp{G}, @samp{M}, @samp{O}, and @samp{p}
+also seem to be used for obscure purposes ...
+
+@node Concept Index, , Mangling, Top
-@node Concept Index, , Free Store, Top
@section Concept Index
@printindex cp
diff --git a/contrib/gcc/cp/inc/exception b/contrib/gcc/cp/inc/exception
new file mode 100644
index 0000000..9954146
--- /dev/null
+++ b/contrib/gcc/cp/inc/exception
@@ -0,0 +1,43 @@
+// Exception Handling support header for -*- C++ -*-
+// Copyright (C) 1995, 1996 Free Software Foundation
+
+#ifndef __EXCEPTION__
+#define __EXCEPTION__
+
+#pragma interface "exception"
+
+extern "C++" {
+
+#ifdef __HONOR_STD
+namespace std {
+#endif
+
+class exception {
+public:
+ exception () { }
+ virtual ~exception () { }
+ virtual const char* what () const;
+};
+
+class bad_exception : public exception {
+public:
+ bad_exception () { }
+ virtual ~bad_exception () { }
+};
+
+typedef void (*terminate_handler) ();
+typedef void (*unexpected_handler) ();
+
+terminate_handler set_terminate (terminate_handler);
+void terminate () __attribute__ ((__noreturn__));
+unexpected_handler set_unexpected (unexpected_handler);
+void unexpected () __attribute__ ((__noreturn__));
+bool uncaught_exception ();
+
+#ifdef __HONOR_STD
+} // namespace std
+#endif
+
+} // extern "C++"
+
+#endif
diff --git a/contrib/gcc/cp/inc/new b/contrib/gcc/cp/inc/new
new file mode 100644
index 0000000..0f25a5c
--- /dev/null
+++ b/contrib/gcc/cp/inc/new
@@ -0,0 +1,46 @@
+// The -*- C++ -*- dynamic memory management header.
+// Copyright (C) 1994, 1996 Free Software Foundation
+
+#ifndef __NEW__
+#define __NEW__
+
+#pragma interface "new"
+#include <stddef.h>
+#include <exception>
+
+extern "C++" {
+
+#ifdef __HONOR_STD
+namespace std {
+#endif
+
+ class bad_alloc : public exception {
+ public:
+ virtual const char* what() const throw() { return "bad_alloc"; }
+ };
+
+ struct nothrow_t {};
+ extern const nothrow_t nothrow;
+ typedef void (*new_handler)();
+ new_handler set_new_handler (new_handler);
+
+#ifdef __HONOR_STD
+} // namespace std
+#endif
+
+// replaceable signatures
+void *operator new (size_t) throw (std::bad_alloc);
+void *operator new[] (size_t) throw (std::bad_alloc);
+void operator delete (void *) throw();
+void operator delete[] (void *) throw();
+void *operator new (size_t, const std::nothrow_t&) throw();
+void *operator new[] (size_t, const std::nothrow_t&) throw();
+void operator delete (void *, const std::nothrow_t&) throw();
+void operator delete[] (void *, const std::nothrow_t&) throw();
+
+// default placement versions of operator new
+inline void *operator new(size_t, void *place) throw() { return place; }
+inline void *operator new[](size_t, void *place) throw() { return place; }
+} // extern "C++"
+
+#endif
diff --git a/contrib/gcc/cp/inc/new.h b/contrib/gcc/cp/inc/new.h
new file mode 100644
index 0000000..799db7e
--- /dev/null
+++ b/contrib/gcc/cp/inc/new.h
@@ -0,0 +1,13 @@
+// -*- C++ -*- forwarding header.
+
+#ifndef __NEW_H__
+#define __NEW_H__
+
+#include <new>
+
+#ifdef __HONOR_STD
+using std::new_handler;
+using std::set_new_handler;
+#endif
+
+#endif // __NEW_H__
diff --git a/contrib/gcc/cp/inc/typeinfo b/contrib/gcc/cp/inc/typeinfo
new file mode 100644
index 0000000..e46acb9
--- /dev/null
+++ b/contrib/gcc/cp/inc/typeinfo
@@ -0,0 +1,62 @@
+// RTTI support for -*- C++ -*-
+// Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+#ifndef __TYPEINFO__
+#define __TYPEINFO__
+
+#pragma interface "typeinfo"
+
+#include <exception>
+
+extern "C++" {
+
+#ifdef __HONOR_STD
+namespace std {
+#endif
+
+class type_info {
+private:
+ // assigning type_info is not supported. made private.
+ type_info& operator= (const type_info&);
+ type_info (const type_info&);
+
+protected:
+ type_info (const char *n): _name (n) { }
+
+ const char *_name;
+
+public:
+ // destructor
+ virtual ~type_info ();
+
+ bool before (const type_info& arg) const;
+ const char* name () const
+ { return _name; }
+ bool operator== (const type_info& arg) const;
+ bool operator!= (const type_info& arg) const;
+};
+
+inline bool type_info::
+operator!= (const type_info& arg) const
+{
+ return !operator== (arg);
+}
+
+class bad_cast : public exception {
+public:
+ bad_cast() { }
+ virtual ~bad_cast() { }
+};
+
+class bad_typeid : public exception {
+ public:
+ bad_typeid () { }
+ virtual ~bad_typeid () { }
+};
+
+#ifdef __HONOR_STD
+} // namespace std
+#endif
+
+} // extern "C++"
+#endif
diff --git a/contrib/gcc/cp/init.c b/contrib/gcc/cp/init.c
index 9752a9b..931d033 100644
--- a/contrib/gcc/cp/init.c
+++ b/contrib/gcc/cp/init.c
@@ -1,5 +1,5 @@
/* Handle initialization things in C++.
- Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-96, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -19,18 +19,20 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* High-level class interface. */
+/* High-level class interface. */
#include "config.h"
+#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "cp-tree.h"
#include "flags.h"
#include "output.h"
+#include "except.h"
+#include "expr.h"
+#include "toplev.h"
-#undef NULL
-#define NULL 0
+extern void compiler_error ();
/* In C++, structures with well-defined constructors are initialized by
those constructors, unasked. CURRENT_BASE_INIT_LIST
@@ -43,35 +45,36 @@ Boston, MA 02111-1307, USA. */
line. Perhaps this was not intended. */
tree current_base_init_list, current_member_init_list;
-void emit_base_init ();
-void check_base_init ();
-static void expand_aggr_vbase_init ();
-void expand_member_init ();
-void expand_aggr_init ();
-
-static void expand_aggr_init_1 ();
-static void expand_recursive_init_1 ();
-static void expand_recursive_init ();
+static void expand_aggr_vbase_init_1 PROTO((tree, tree, tree, tree));
+static void expand_aggr_vbase_init PROTO((tree, tree, tree, tree));
+static void expand_aggr_init_1 PROTO((tree, tree, tree, tree, int,
+ int));
+static void expand_default_init PROTO((tree, tree, tree, tree, int,
+ int));
+static tree build_vec_delete_1 PROTO((tree, tree, tree, tree, tree,
+ int));
+static void perform_member_init PROTO((tree, tree, tree, int));
+static void sort_base_init PROTO((tree, tree *, tree *));
+static tree build_builtin_call PROTO((tree, tree, tree));
+static tree build_array_eh_cleanup PROTO((tree, tree, tree));
+static int member_init_ok_or_else PROTO((tree, tree, char *));
static void expand_virtual_init PROTO((tree, tree));
-tree expand_vec_init ();
-
-static void add_friend (), add_friends ();
+static tree sort_member_init PROTO((tree));
+static tree build_partial_cleanup_for PROTO((tree));
+static tree initializing_context PROTO((tree));
/* Cache _builtin_new and _builtin_delete exprs. */
static tree BIN, BID, BIVN, BIVD;
-/* Cache the identifier nodes for the two magic field of a new cookie. */
+/* Cache the identifier nodes for the magic field of a new cookie. */
static tree nc_nelts_field_id;
-#if 0
-static tree nc_ptr_2comp_field_id;
-#endif
static tree minus_one;
/* Set up local variable for this file. MUST BE CALLED AFTER
INIT_DECL_PROCESSING. */
-tree BI_header_type, BI_header_size;
+static tree BI_header_type, BI_header_size;
void init_init_processing ()
{
@@ -119,6 +122,7 @@ void init_init_processing ()
Relies upon binfo being inside TYPE_BINFO (TREE_TYPE (TREE_TYPE
(addr))). */
+
void
expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
tree real_binfo, binfo, addr;
@@ -132,8 +136,8 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
{
tree real_base_binfo = TREE_VEC_ELT (real_binfos, i);
tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable =
- i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
+ int is_not_base_vtable
+ = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
if (! TREE_VIA_VIRTUAL (real_base_binfo))
expand_direct_vtbls_init (real_base_binfo, base_binfo,
is_not_base_vtable, can_elide, addr);
@@ -153,23 +157,26 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
/* 348 - 351 */
/* Subroutine of emit_base_init. */
+
static void
-perform_member_init (member, name, init, explicit, protect_list)
- tree member, name, init, *protect_list;
+perform_member_init (member, name, init, explicit)
+ tree member, name, init;
int explicit;
{
tree decl;
tree type = TREE_TYPE (member);
+ expand_start_target_temps ();
+
if (TYPE_NEEDS_CONSTRUCTING (type)
|| (init && TYPE_HAS_CONSTRUCTOR (type)))
{
/* Since `init' is already a TREE_LIST on the current_member_init_list,
only build it into one if we aren't already a list. */
if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST)
- init = build_tree_list (NULL_TREE, init);
+ init = build_expr_list (NULL_TREE, init);
- decl = build_component_ref (C_C_D, name, 0, explicit);
+ decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
if (explicit
&& TREE_CODE (type) == ARRAY_TYPE
@@ -190,9 +197,17 @@ perform_member_init (member, name, init, explicit, protect_list)
{
if (explicit)
{
- cp_error ("incomplete initializer for member `%D' of class `%T' which has no constructor",
- member, current_class_type);
- init = error_mark_node;
+ /* default-initialization. */
+ if (AGGREGATE_TYPE_P (type))
+ init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ cp_error ("default-initialization of `%#D', which has reference type",
+ member);
+ init = error_mark_node;
+ }
+ else
+ init = integer_zero_node;
}
/* member traversal: note it leaves init NULL */
else if (TREE_CODE (TREE_TYPE (member)) == REFERENCE_TYPE)
@@ -215,38 +230,47 @@ perform_member_init (member, name, init, explicit, protect_list)
current_member_init_list. */
if (init || explicit)
{
- decl = build_component_ref (C_C_D, name, 0, explicit);
+ decl = build_component_ref (current_class_ref, name, NULL_TREE,
+ explicit);
expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
}
}
- expand_cleanups_to (NULL_TREE);
+
+ expand_end_target_temps ();
+ free_temp_slots ();
if (TYPE_NEEDS_DESTRUCTOR (type))
{
- tree expr = build_component_ref (C_C_D, name, 0, explicit);
+ tree expr;
+
+ /* All cleanups must be on the function_obstack. */
+ push_obstacks_nochange ();
+ resume_temporary_allocation ();
+
+ expr = build_component_ref (current_class_ref, name, NULL_TREE,
+ explicit);
expr = build_delete (type, expr, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
if (expr != error_mark_node)
- {
- start_protect ();
- *protect_list = tree_cons (NULL_TREE, expr, *protect_list);
- }
+ add_partial_entry (expr);
+
+ pop_obstacks ();
}
}
extern int warn_reorder;
/* Subroutine of emit_member_init. */
+
static tree
sort_member_init (t)
tree t;
{
- tree x, member, name, field, init;
+ tree x, member, name, field;
tree init_list = NULL_TREE;
- tree fields_to_unmark = NULL_TREE;
int last_pos = 0;
- tree last_field;
+ tree last_field = NULL_TREE;
for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member))
{
@@ -266,6 +290,8 @@ sort_member_init (t)
name = TREE_PURPOSE (x);
#if 0
+ /* This happens in templates, since the IDENTIFIER is replaced
+ with the COMPONENT_REF in tsubst_expr. */
field = (TREE_CODE (name) == COMPONENT_REF
? TREE_OPERAND (name, 1) : IDENTIFIER_CLASS_VALUE (name));
#else
@@ -353,10 +379,10 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
last = tree_cons (NULL_TREE, NULL_TREE, current_base_init_list);
for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))
{
- tree basename = TREE_PURPOSE (x);
- tree binfo;
+ tree basetype = TREE_PURPOSE (x);
+ tree binfo = NULL_TREE;
- if (basename == NULL_TREE)
+ if (basetype == NULL_TREE)
{
/* Initializer for single base class. Must not
use multiple inheritance or this is ambiguous. */
@@ -375,9 +401,9 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
}
binfo = TREE_VEC_ELT (binfos, 0);
}
- else if (is_aggr_typedef (basename, 1))
+ else if (is_aggr_type (basetype, 1))
{
- binfo = binfo_or_else (IDENTIFIER_TYPE_VALUE (basename), t);
+ binfo = binfo_or_else (basetype, t);
if (binfo == NULL_TREE)
continue;
@@ -402,8 +428,7 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
if (i < 0)
{
cp_error ("`%T' is not an immediate base class of `%T'",
- IDENTIFIER_TYPE_VALUE (basename),
- current_class_type);
+ basetype, current_class_type);
continue;
}
}
@@ -468,17 +493,14 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
}
/* Perform partial cleanups for a base for exception handling. */
+
static tree
build_partial_cleanup_for (binfo)
tree binfo;
{
- tree expr = convert_pointer_to_real (binfo,
- build_unary_op (ADDR_EXPR, C_C_D, 0));
-
- return build_delete (TREE_TYPE (expr),
- expr,
- integer_zero_node,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
+ return build_scoped_method_call
+ (current_class_ref, binfo, dtor_identifier,
+ build_expr_list (NULL_TREE, integer_zero_node));
}
/* Perform whatever initializations have yet to be done on the base
@@ -506,9 +528,7 @@ emit_base_init (t, immediately)
tree t;
int immediately;
{
- extern tree in_charge_identifier;
-
- tree member, x;
+ tree member;
tree mem_init_list;
tree rbase_init_list, vbase_init_list;
tree t_binfo = TYPE_BINFO (t);
@@ -516,8 +536,6 @@ emit_base_init (t, immediately)
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree expr = NULL_TREE;
- my_friendly_assert (protect_list == NULL_TREE, 999);
-
if (! immediately)
{
int momentary;
@@ -549,7 +567,7 @@ emit_base_init (t, immediately)
tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
expand_start_cond (first_arg, 0);
- expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl,
+ expand_aggr_vbase_init (t_binfo, current_class_ref, current_class_ptr,
vbase_init_list);
expand_end_cond ();
}
@@ -557,7 +575,6 @@ emit_base_init (t, immediately)
/* Now, perform initialization of non-virtual base classes. */
for (i = 0; i < n_baseclasses; i++)
{
- tree base = current_class_decl;
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree init = void_list_node;
@@ -565,7 +582,7 @@ emit_base_init (t, immediately)
continue;
#if 0 /* Once unsharing happens soon enough. */
- my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo);
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo, 999);
#else
BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo;
#endif
@@ -573,36 +590,49 @@ emit_base_init (t, immediately)
if (TREE_PURPOSE (rbase_init_list))
init = TREE_VALUE (rbase_init_list);
else if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
- init = NULL_TREE;
+ {
+ init = NULL_TREE;
+ if (extra_warnings && copy_args_p (current_function_decl))
+ cp_warning ("base class `%#T' should be explicitly initialized in the copy constructor",
+ BINFO_TYPE (base_binfo));
+ }
if (init != void_list_node)
{
- member = convert_pointer_to_real (base_binfo, current_class_decl);
- expand_aggr_init_1 (base_binfo, 0,
+ expand_start_target_temps ();
+
+ member = convert_pointer_to_real (base_binfo, current_class_ptr);
+ expand_aggr_init_1 (base_binfo, NULL_TREE,
build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
- expand_cleanups_to (NULL_TREE);
+
+ expand_end_target_temps ();
+ free_temp_slots ();
}
if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
{
- start_protect ();
- protect_list = tree_cons (NULL_TREE,
- build_partial_cleanup_for (base_binfo),
- protect_list);
+ tree expr;
+
+ /* All cleanups must be on the function_obstack. */
+ push_obstacks_nochange ();
+ resume_temporary_allocation ();
+ expr = build_partial_cleanup_for (base_binfo);
+ pop_obstacks ();
+ add_partial_entry (expr);
}
rbase_init_list = TREE_CHAIN (rbase_init_list);
}
/* Initialize all the virtual function table fields that
- do come from virtual base classes. */
+ do come from virtual base classes. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
- expand_indirect_vtbls_init (t_binfo, C_C_D, current_class_decl, 0);
+ expand_indirect_vtbls_init (t_binfo, current_class_ref, current_class_ptr);
/* Initialize all the virtual function table fields that
do not come from virtual base classes. */
- expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_decl);
+ expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_ptr);
for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
{
@@ -622,10 +652,15 @@ emit_base_init (t, immediately)
init = TREE_VALUE (mem_init_list);
from_init_list = 1;
+#if 0
+ if (TREE_CODE (name) == COMPONENT_REF)
+ name = DECL_NAME (TREE_OPERAND (name, 1));
+#else
/* Also see if it's ever a COMPONENT_REF here. If it is, we
need to do `expand_assignment (name, init, 0, 0);' and
a continue. */
my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 349);
+#endif
}
else
{
@@ -633,9 +668,15 @@ emit_base_init (t, immediately)
init = DECL_INITIAL (member);
from_init_list = 0;
+
+ /* Effective C++ rule 12. */
+ if (warn_ecpp && init == NULL_TREE
+ && !DECL_ARTIFICIAL (member)
+ && TREE_CODE (TREE_TYPE (member)) != ARRAY_TYPE)
+ cp_warning ("`%D' should be initialized in the member initialization list", member);
}
- perform_member_init (member, name, init, from_init_list, &protect_list);
+ perform_member_init (member, name, init, from_init_list);
mem_init_list = TREE_CHAIN (mem_init_list);
}
@@ -673,7 +714,7 @@ emit_base_init (t, immediately)
my_friendly_assert (DECL_FIELD_CONTEXT (field) != t, 351);
#endif
- perform_member_init (field, name, init, 1, &protect_list);
+ perform_member_init (field, name, init, 1);
}
mem_init_list = TREE_CHAIN (mem_init_list);
}
@@ -697,6 +738,7 @@ emit_base_init (t, immediately)
/* Check that all fields are properly initialized after
an assignment to `this'. */
+
void
check_base_init (t)
tree t;
@@ -713,6 +755,7 @@ check_base_init (t)
BINFO is the exact type that DECL is supposed to be. In
multiple inheritance, this might mean "C's A" if C : A, B. */
+
static void
expand_virtual_init (binfo, decl)
tree binfo, decl;
@@ -743,23 +786,30 @@ expand_virtual_init (binfo, decl)
/* Subroutine of `expand_aggr_vbase_init'.
BINFO is the binfo of the type that is being initialized.
INIT_LIST is the list of initializers for the virtual baseclass. */
+
static void
expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
tree binfo, exp, addr, init_list;
{
tree init = purpose_member (binfo, init_list);
tree ref = build_indirect_ref (addr, NULL_PTR);
+
+ expand_start_target_temps ();
+
if (init)
init = TREE_VALUE (init);
/* Call constructors, but don't set up vtables. */
expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN);
- expand_cleanups_to (NULL_TREE);
+
+ expand_end_target_temps ();
+ free_temp_slots ();
}
/* Initialize this object's virtual base class pointers. This must be
done only at the top-level of the object being constructed.
INIT_LIST is list of initialization for constructor to perform. */
+
static void
expand_aggr_vbase_init (binfo, exp, addr, init_list)
tree binfo;
@@ -788,38 +838,25 @@ expand_aggr_vbase_init (binfo, exp, addr, init_list)
}
}
-/* Subroutine to perform parser actions for member initialization.
- S_ID is the scoped identifier.
- NAME is the name of the member.
- INIT is the initializer, or `void_type_node' if none. */
-void
-do_member_init (s_id, name, init)
- tree s_id, name, init;
-{
- tree binfo, base;
+/* Find the context in which this FIELD can be initialized. */
- if (current_class_type == NULL_TREE
- || ! is_aggr_typedef (s_id, 1))
- return;
- binfo = get_binfo (IDENTIFIER_TYPE_VALUE (s_id),
- current_class_type, 1);
- if (binfo == error_mark_node)
- return;
- if (binfo == 0)
- {
- error_not_base_type (IDENTIFIER_TYPE_VALUE (s_id), current_class_type);
- return;
- }
+static tree
+initializing_context (field)
+ tree field;
+{
+ tree t = DECL_CONTEXT (field);
- base = convert_pointer_to (binfo, current_class_decl);
- expand_member_init (build_indirect_ref (base, NULL_PTR), name, init);
+ /* Anonymous union members can be initialized in the first enclosing
+ non-anonymous union context. */
+ while (t && ANON_UNION_TYPE_P (t))
+ t = TYPE_CONTEXT (t);
+ return t;
}
/* Function to give error message if member initialization specification
is erroneous. FIELD is the member we decided to initialize.
TYPE is the type for which the initialization is being performed.
- FIELD must be a member of TYPE, or the base type from which FIELD
- comes must not need a constructor.
+ FIELD must be a member of TYPE.
MEMBER_NAME is the name of the member. */
@@ -831,23 +868,12 @@ member_init_ok_or_else (field, type, member_name)
{
if (field == error_mark_node)
return 0;
- if (field == NULL_TREE)
+ if (field == NULL_TREE || initializing_context (field) != type)
{
cp_error ("class `%T' does not have any field named `%s'", type,
member_name);
return 0;
}
- if (DECL_CONTEXT (field) != type
- && TYPE_NEEDS_CONSTRUCTING (DECL_CONTEXT (field)))
- {
- if (current_function_decl && DECL_CONSTRUCTOR_P (current_function_decl))
- cp_error ("initialization of `%D' inside constructor for `%T'",
- field, type);
- else
- cp_error ("member `%D' comes from base class needing constructor",
- field);
- return 0;
- }
if (TREE_STATIC (field))
{
cp_error ("field `%#D' is static; only point of initialization is its declaration",
@@ -873,22 +899,25 @@ member_init_ok_or_else (field, type, member_name)
If INIT is non-NULL, then it the initialization should
be placed in `current_base_init_list', where it will be processed
by `emit_base_init'. */
+
void
expand_member_init (exp, name, init)
tree exp, name, init;
{
- extern tree ptr_type_node; /* should be in tree.h */
-
tree basetype = NULL_TREE, field;
- tree parm;
- tree rval, type;
- tree actual_name;
+ tree type;
if (exp == NULL_TREE)
return; /* complain about this later */
type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+ if (name && TREE_CODE (name) == TYPE_DECL)
+ {
+ basetype = TREE_TYPE (name);
+ name = DECL_NAME (name);
+ }
+
if (name == NULL_TREE && IS_AGGR_TYPE (type))
switch (CLASSTYPE_N_BASECLASSES (type))
{
@@ -904,169 +933,84 @@ expand_member_init (exp, name, init)
return;
}
- if (init)
- {
- /* The grammar should not allow fields which have names
- that are TYPENAMEs. Therefore, if the field has
- a non-NULL TREE_TYPE, we may assume that this is an
- attempt to initialize a base class member of the current
- type. Otherwise, it is an attempt to initialize a
- member field. */
-
- if (init == void_type_node)
- init = NULL_TREE;
+ my_friendly_assert (init != NULL_TREE, 0);
- if (name == NULL_TREE || IDENTIFIER_HAS_TYPE_VALUE (name))
- {
- tree base_init;
+ /* The grammar should not allow fields which have names that are
+ TYPENAMEs. Therefore, if the field has a non-NULL TREE_TYPE, we
+ may assume that this is an attempt to initialize a base class
+ member of the current type. Otherwise, it is an attempt to
+ initialize a member field. */
- if (name == NULL_TREE)
- {
-/*
- if (basetype)
- name = TYPE_IDENTIFIER (basetype);
- else
- {
- error ("no base class to initialize");
- return;
- }
-*/
- }
- else
- {
- basetype = IDENTIFIER_TYPE_VALUE (name);
- if (basetype != type
- && ! binfo_member (basetype, TYPE_BINFO (type))
- && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
- {
- if (IDENTIFIER_CLASS_VALUE (name))
- goto try_member;
- if (TYPE_USES_VIRTUAL_BASECLASSES (type))
- error ("type `%s' is not an immediate or virtual basetype for `%s'",
- IDENTIFIER_POINTER (name),
- TYPE_NAME_STRING (type));
- else
- error ("type `%s' is not an immediate basetype for `%s'",
- IDENTIFIER_POINTER (name),
- TYPE_NAME_STRING (type));
- return;
- }
- }
+ if (init == void_type_node)
+ init = NULL_TREE;
- if (purpose_member (name, current_base_init_list))
- {
- error ("base class `%s' already initialized",
- IDENTIFIER_POINTER (name));
- return;
- }
+ if (name == NULL_TREE || basetype)
+ {
+ tree base_init;
- base_init = build_tree_list (name, init);
- TREE_TYPE (base_init) = basetype;
- current_base_init_list = chainon (current_base_init_list, base_init);
- }
- else
+ if (name == NULL_TREE)
{
- tree member_init;
-
- try_member:
- field = lookup_field (type, name, 1, 0);
-
- if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
- return;
-
- if (purpose_member (name, current_member_init_list))
+#if 0
+ if (basetype)
+ name = TYPE_IDENTIFIER (basetype);
+ else
{
- error ("field `%s' already initialized", IDENTIFIER_POINTER (name));
+ error ("no base class to initialize");
return;
}
-
- member_init = build_tree_list (name, init);
- TREE_TYPE (member_init) = TREE_TYPE (field);
- current_member_init_list = chainon (current_member_init_list, member_init);
+#endif
}
- return;
- }
- else if (name == NULL_TREE)
- {
- compiler_error ("expand_member_init: name == NULL_TREE");
- return;
- }
-
- basetype = type;
- field = lookup_field (basetype, name, 0, 0);
-
- if (! member_init_ok_or_else (field, basetype, IDENTIFIER_POINTER (name)))
- return;
-
- /* now see if there is a constructor for this type
- which will take these args. */
-
- if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (field)))
- {
- tree parmtypes, fndecl;
-
- if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
- {
- /* just know that we've seen something for this node */
- DECL_INITIAL (exp) = error_mark_node;
- TREE_USED (exp) = 1;
+ else if (basetype != type
+ && ! current_template_parms
+ && ! vec_binfo_member (basetype,
+ TYPE_BINFO_BASETYPES (type))
+ && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
+ {
+ if (IDENTIFIER_CLASS_VALUE (name))
+ goto try_member;
+ if (TYPE_USES_VIRTUAL_BASECLASSES (type))
+ cp_error ("type `%T' is not an immediate or virtual basetype for `%T'",
+ basetype, type);
+ else
+ cp_error ("type `%T' is not an immediate basetype for `%T'",
+ basetype, type);
+ return;
}
- type = TYPE_MAIN_VARIANT (TREE_TYPE (field));
- actual_name = TYPE_IDENTIFIER (type);
- parm = build_component_ref (exp, name, 0, 0);
-
- /* Now get to the constructor. */
- fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
- /* Get past destructor, if any. */
- if (TYPE_HAS_DESTRUCTOR (type))
- fndecl = DECL_CHAIN (fndecl);
-
- if (fndecl)
- my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 209);
-
- /* If the field is unique, we can use the parameter
- types to guide possible type instantiation. */
- if (DECL_CHAIN (fndecl) == NULL_TREE)
+
+ if (purpose_member (basetype, current_base_init_list))
{
- /* There was a confusion here between
- FIELD and FNDECL. The following code
- should be correct, but abort is here
- to make sure. */
- my_friendly_abort (48);
- parmtypes = FUNCTION_ARG_CHAIN (fndecl);
+ cp_error ("base class `%T' already initialized", basetype);
+ return;
}
- else
+
+ if (warn_reorder && current_member_init_list)
{
- parmtypes = NULL_TREE;
- fndecl = NULL_TREE;
+ cp_warning ("base initializer for `%T'", basetype);
+ warning (" will be re-ordered to precede member initializations");
}
- init = convert_arguments (parm, parmtypes, NULL_TREE, fndecl, LOOKUP_NORMAL);
- if (init == NULL_TREE || TREE_TYPE (init) != error_mark_node)
- rval = build_method_call (NULL_TREE, actual_name, init, NULL_TREE, LOOKUP_NORMAL);
- else
+ base_init = build_tree_list (basetype, init);
+ current_base_init_list = chainon (current_base_init_list, base_init);
+ }
+ else
+ {
+ tree member_init;
+
+ try_member:
+ field = lookup_field (type, name, 1, 0);
+
+ if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
return;
- if (rval != error_mark_node)
+ if (purpose_member (name, current_member_init_list))
{
- /* Now, fill in the first parm with our guy */
- TREE_VALUE (TREE_OPERAND (rval, 1))
- = build_unary_op (ADDR_EXPR, parm, 0);
- TREE_TYPE (rval) = ptr_type_node;
- TREE_SIDE_EFFECTS (rval) = 1;
+ cp_error ("field `%D' already initialized", field);
+ return;
}
- }
- else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
- {
- parm = build_component_ref (exp, name, 0, 0);
- expand_aggr_init (parm, NULL_TREE, 0, 0);
- rval = error_mark_node;
- }
- /* Now initialize the member. It does not have to
- be of aggregate type to receive initialization. */
- if (rval != error_mark_node)
- expand_expr_stmt (rval);
+ member_init = build_tree_list (name, init);
+ current_member_init_list = chainon (current_member_init_list, member_init);
+ }
}
/* This is like `expand_member_init', only it stores one aggregate
@@ -1083,8 +1027,9 @@ expand_member_init (exp, name, init)
explaining that such initializations are invalid.
ALIAS_THIS is nonzero iff we are initializing something which is
- essentially an alias for C_C_D. In this case, the base constructor
- may move it on us, and we must keep track of such deviations.
+ essentially an alias for current_class_ref. In this case, the base
+ constructor may move it on us, and we must keep track of such
+ deviations.
If INIT resolves to a CALL_EXPR which happens to return
something of the type we are looking for, then we know
@@ -1104,8 +1049,7 @@ expand_member_init (exp, name, init)
initialization.
A constructor or a conversion operator may have to be used to
- perform the initialization, but not both, as it would be ambiguous.
- */
+ perform the initialization, but not both, as it would be ambiguous. */
void
expand_aggr_init (exp, init, alias_this, flags)
@@ -1186,14 +1130,15 @@ expand_aggr_init (exp, init, alias_this, flags)
}
static void
-expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
+expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
tree binfo;
tree true_exp, exp;
- tree type;
tree init;
int alias_this;
int flags;
{
+ tree type = TREE_TYPE (exp);
+
/* It fails because there may not be a constructor which takes
its own type as the first (or only parameter), but which does
take other types via a conversion. So, if the thing initializing
@@ -1203,6 +1148,37 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
tree rval;
tree parms;
+ if (init && TREE_CODE (init) != TREE_LIST
+ && (flags & LOOKUP_ONLYCONVERTING))
+ {
+ /* Base subobjects should only get direct-initialization. */
+ if (true_exp != exp)
+ abort ();
+
+ /* We special-case TARGET_EXPRs here to avoid an error about
+ private copy constructors for temporaries bound to reference vars.
+ If the TARGET_EXPR represents a call to a function that has
+ permission to create such objects, a reference can bind directly
+ to the return value. An object variable must be initialized
+ via the copy constructor, even if the call is elided. */
+ if (! (TREE_CODE (exp) == VAR_DECL && DECL_ARTIFICIAL (exp)
+ && TREE_CODE (init) == TARGET_EXPR && TREE_TYPE (init) == type))
+ init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
+
+ if (TREE_CODE (init) == TRY_CATCH_EXPR)
+ /* We need to protect the initialization of a catch parm
+ with a call to terminate(), which shows up as a TRY_CATCH_EXPR
+ around the TARGET_EXPR for the copy constructor. See
+ expand_start_catch_block. */
+ TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp,
+ TREE_OPERAND (init, 0));
+ else
+ init = build (INIT_EXPR, TREE_TYPE (exp), exp, init);
+ TREE_SIDE_EFFECTS (init) = 1;
+ expand_expr_stmt (init);
+ return;
+ }
+
if (init == NULL_TREE
|| (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init)))
{
@@ -1210,64 +1186,22 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
if (parms)
init = TREE_VALUE (parms);
}
- else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)
- && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
- {
- rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0);
- TREE_USED (rval) = 1;
- expand_expr_stmt (rval);
- return;
- }
else
- parms = build_tree_list (NULL_TREE, init);
+ parms = build_expr_list (NULL_TREE, init);
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
if (true_exp == exp)
- parms = tree_cons (NULL_TREE, integer_one_node, parms);
+ parms = expr_tree_cons (NULL_TREE, integer_one_node, parms);
else
- parms = tree_cons (NULL_TREE, integer_zero_node, parms);
+ parms = expr_tree_cons (NULL_TREE, integer_zero_node, parms);
flags |= LOOKUP_HAS_IN_CHARGE;
}
- if (init && TREE_CHAIN (parms) == NULL_TREE
- && TYPE_HAS_TRIVIAL_INIT_REF (type)
- && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
- {
- rval = build (INIT_EXPR, type, exp, init);
- TREE_SIDE_EFFECTS (rval) = 1;
- expand_expr_stmt (rval);
- }
- else
- {
- if (flags & LOOKUP_ONLYCONVERTING)
- flags |= LOOKUP_NO_CONVERSION;
- rval = build_method_call (exp, constructor_name_full (type),
- parms, binfo, flags);
-
- /* Private, protected, or otherwise unavailable. */
- if (rval == error_mark_node)
- {
- if (flags & LOOKUP_COMPLAIN)
- cp_error ("in base initialization for %sclass `%T'",
- TREE_VIA_VIRTUAL (binfo) ? "virtual base " : "",
- binfo);
- }
- else if (rval == NULL_TREE)
- my_friendly_abort (361);
- else
- {
- /* p. 222: if the base class assigns to `this', then that
- value is used in the derived class. */
- if ((flag_this_is_variable & 1) && alias_this)
- {
- TREE_TYPE (rval) = TREE_TYPE (current_class_decl);
- expand_assignment (current_class_decl, rval, 0, 0);
- }
- else
- expand_expr_stmt (rval);
- }
- }
+ rval = build_method_call (exp, ctor_identifier,
+ parms, binfo, flags);
+ if (TREE_SIDE_EFFECTS (rval))
+ expand_expr_stmt (rval);
}
/* This function is responsible for initializing EXP with INIT
@@ -1301,7 +1235,6 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
int flags;
{
tree type = TREE_TYPE (exp);
- tree init_type = NULL_TREE;
my_friendly_assert (init != error_mark_node && type != error_mark_node, 211);
@@ -1310,357 +1243,31 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
NULL_TREE, know that it was meant for us--just slide exp on
in and expand the constructor. Constructors now come
as TARGET_EXPRs. */
- if (init)
- {
- tree init_list = NULL_TREE;
-
- if (TREE_CODE (init) == TREE_LIST)
- {
- init_list = init;
- if (TREE_CHAIN (init) == NULL_TREE)
- init = TREE_VALUE (init);
- }
-
- init_type = TREE_TYPE (init);
-
- if (TREE_CODE (init) != TREE_LIST)
- {
- if (TREE_CODE (init_type) == ERROR_MARK)
- return;
-
-#if 0
- /* These lines are found troublesome 5/11/89. */
- if (TREE_CODE (init_type) == REFERENCE_TYPE)
- init_type = TREE_TYPE (init_type);
-#endif
- /* This happens when we use C++'s functional cast notation.
- If the types match, then just use the TARGET_EXPR
- directly. Otherwise, we need to create the initializer
- separately from the object being initialized. */
- if (TREE_CODE (init) == TARGET_EXPR)
- {
- if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type))
- {
- if (TREE_CODE (exp) == VAR_DECL
- || TREE_CODE (exp) == RESULT_DECL)
- /* Unify the initialization targets. */
- DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp);
- else
- DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, NULL_RTX, 0, 0);
-
- expand_expr_stmt (init);
- return;
- }
- else
- {
- init = TREE_OPERAND (init, 1);
- init = build (CALL_EXPR, init_type,
- TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);
- TREE_SIDE_EFFECTS (init) = 1;
- if (init_list)
- TREE_VALUE (init_list) = init;
- }
- }
-
- if (init_type == type && TREE_CODE (init) == CALL_EXPR
-#if 0
- /* It is valid to directly initialize from a CALL_EXPR
- without going through X(X&), apparently. */
- && ! TYPE_GETS_INIT_REF (type)
-#endif
- )
- {
- /* A CALL_EXPR is a legitimate form of initialization, so
- we should not print this warning message. */
-#if 0
- /* Should have gone away due to 5/11/89 change. */
- if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
- init = convert_from_reference (init);
-#endif
- expand_assignment (exp, init, 0, 0);
- if (exp == DECL_RESULT (current_function_decl))
- {
- /* Failing this assertion means that the return value
- from receives multiple initializations. */
- my_friendly_assert (DECL_INITIAL (exp) == NULL_TREE
- || DECL_INITIAL (exp) == error_mark_node,
- 212);
- DECL_INITIAL (exp) = init;
- }
- return;
- }
- else if (init_type == type
- && TREE_CODE (init) == COND_EXPR)
- {
- /* Push value to be initialized into the cond, where possible.
- Avoid spurious warning messages when initializing the
- result of this function. */
- TREE_OPERAND (init, 1)
- = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 1));
- if (exp == DECL_RESULT (current_function_decl))
- DECL_INITIAL (exp) = NULL_TREE;
- TREE_OPERAND (init, 2)
- = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 2));
- if (exp == DECL_RESULT (current_function_decl))
- DECL_INITIAL (exp) = init;
- TREE_SIDE_EFFECTS (init) = 1;
- expand_expr (init, const0_rtx, VOIDmode, 0);
- free_temp_slots ();
- return;
- }
- }
-
- /* We did not know what we were initializing before. Now we do. */
- if (TREE_CODE (init) == TARGET_EXPR)
- {
- tree tmp = TREE_OPERAND (TREE_OPERAND (init, 1), 1);
-
- if (TREE_CODE (TREE_VALUE (tmp)) == NOP_EXPR
- && TREE_OPERAND (TREE_VALUE (tmp), 0) == integer_zero_node)
- {
- /* In order for this to work for RESULT_DECLs, if their
- type has a constructor, then they must be BLKmode
- so that they will be meaningfully addressable. */
- tree arg = build_unary_op (ADDR_EXPR, exp, 0);
- init = TREE_OPERAND (init, 1);
- init = build (CALL_EXPR, build_pointer_type (TREE_TYPE (init)),
- TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);
- TREE_SIDE_EFFECTS (init) = 1;
- TREE_VALUE (TREE_OPERAND (init, 1))
- = convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg);
-
- if (alias_this)
- {
- expand_assignment (current_function_decl, init, 0, 0);
- return;
- }
- if (exp == DECL_RESULT (current_function_decl))
- {
- if (DECL_INITIAL (DECL_RESULT (current_function_decl)))
- fatal ("return value from function receives multiple initializations");
- DECL_INITIAL (exp) = init;
- }
- expand_expr_stmt (init);
- return;
- }
- }
-
- if (TREE_CODE (exp) == VAR_DECL
- && TREE_CODE (init) == CONSTRUCTOR
- && TREE_HAS_CONSTRUCTOR (init))
- {
- tree t = store_init_value (exp, init);
- if (!t)
- {
- expand_decl_init (exp);
- return;
- }
- t = build (INIT_EXPR, type, exp, init);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr_stmt (t);
- return;
- }
-
- /* Handle this case: when calling a constructor: xyzzy foo(bar);
- which really means: xyzzy foo = bar; Ugh!
-
- More useful for this case: xyzzy *foo = new xyzzy (bar); */
-
- if (! TYPE_NEEDS_CONSTRUCTING (type) && ! IS_AGGR_TYPE (type))
- {
- if (init_list && TREE_CHAIN (init_list))
- {
- warning ("initializer list being treated as compound expression");
- init = convert (type, build_compound_expr (init_list));
- if (init == error_mark_node)
- return;
- }
-
- expand_assignment (exp, init, 0, 0);
-
- return;
- }
- /* See whether we can go through a type conversion operator.
- This wins over going through a non-existent constructor. If
- there is a constructor, it is ambiguous. */
- if (TREE_CODE (init) != TREE_LIST)
- {
- tree ttype = TREE_CODE (init_type) == REFERENCE_TYPE
- ? TREE_TYPE (init_type) : init_type;
-
- if (ttype != type && IS_AGGR_TYPE (ttype))
- {
- tree rval = build_type_conversion (CONVERT_EXPR, type, init, 0);
-
- if (rval)
- {
- /* See if there is a constructor for``type'' that takes a
- ``ttype''-typed object. */
- tree parms = build_tree_list (NULL_TREE, init);
- tree as_cons = NULL_TREE;
- if (TYPE_HAS_CONSTRUCTOR (type))
- as_cons = build_method_call (exp, constructor_name_full (type),
- parms, binfo,
- LOOKUP_SPECULATIVELY|LOOKUP_NO_CONVERSION);
- if (as_cons != NULL_TREE && as_cons != error_mark_node)
- /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */
- cp_error ("ambiguity between conversion to `%T' and constructor",
- type);
- else
- expand_assignment (exp, rval, 0, 0);
- return;
- }
- }
- }
- }
-
- /* Handle default copy constructors here, does not matter if there is
- a constructor or not. */
- if (type == init_type && IS_AGGR_TYPE (type)
- && init && TREE_CODE (init) != TREE_LIST)
- expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags);
- /* Not sure why this is here... */
- else if (TYPE_HAS_CONSTRUCTOR (type))
- expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags);
- else if (TREE_CODE (type) == ARRAY_TYPE)
- {
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
- expand_vec_init (exp, exp, array_type_nelts (type), init, 0);
- else if (TYPE_VIRTUAL_P (TREE_TYPE (type)))
- sorry ("arrays of objects with virtual functions but no constructors");
- }
- else
- expand_recursive_init (binfo, true_exp, exp, init,
- CLASSTYPE_BASE_INIT_LIST (type), alias_this);
-}
-
-/* A pointer which holds the initializer. First call to
- expand_aggr_init gets this value pointed to, and sets it to init_null. */
-static tree *init_ptr, init_null;
-
-/* Subroutine of expand_recursive_init:
-
- ADDR is the address of the expression being initialized.
- INIT_LIST is the cons-list of initializations to be performed.
- ALIAS_THIS is its same, lovable self. */
-static void
-expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this)
- tree binfo, true_exp, addr;
- tree init_list;
- int alias_this;
-{
- while (init_list)
+ if (init && TREE_CODE (exp) == VAR_DECL
+ && TREE_CODE (init) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (init))
{
- if (TREE_PURPOSE (init_list))
- {
- if (TREE_CODE (TREE_PURPOSE (init_list)) == FIELD_DECL)
- {
- tree member = TREE_PURPOSE (init_list);
- tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), NULL_PTR);
- tree member_base = build (COMPONENT_REF, TREE_TYPE (member), subexp, member);
- if (IS_AGGR_TYPE (TREE_TYPE (member)))
- expand_aggr_init (member_base, DECL_INITIAL (member), 0, 0);
- else if (TREE_CODE (TREE_TYPE (member)) == ARRAY_TYPE
- && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (member)))
- {
- member_base = save_expr (default_conversion (member_base));
- expand_vec_init (member, member_base,
- array_type_nelts (TREE_TYPE (member)),
- DECL_INITIAL (member), 0);
- }
- else
- expand_expr_stmt (build_modify_expr (member_base, INIT_EXPR, DECL_INITIAL (member)));
- }
- else if (TREE_CODE (TREE_PURPOSE (init_list)) == TREE_LIST)
- {
- expand_recursive_init_1 (binfo, true_exp, addr, TREE_PURPOSE (init_list), alias_this);
- expand_recursive_init_1 (binfo, true_exp, addr, TREE_VALUE (init_list), alias_this);
- }
- else if (TREE_CODE (TREE_PURPOSE (init_list)) == ERROR_MARK)
- {
- /* Only initialize the virtual function tables if we
- are initializing the ultimate users of those vtables. */
- if (TREE_VALUE (init_list))
- {
- /* We have to ensure that the first argment to
- expand_virtual_init is in binfo's hierarchy. */
- /* Is it the case that this is exactly the right binfo? */
- /* If it is ok, then fixup expand_virtual_init, to make
- it much simpler. */
- expand_virtual_init (get_binfo (TREE_VALUE (init_list), binfo, 0),
- addr);
- if (TREE_VALUE (init_list) == binfo
- && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
- expand_indirect_vtbls_init (binfo, true_exp, addr, 1);
- }
- }
- else
- my_friendly_abort (49);
- }
- else if (TREE_VALUE (init_list)
- && TREE_CODE (TREE_VALUE (init_list)) == TREE_VEC)
+ tree t = store_init_value (exp, init);
+ if (!t)
{
- tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), NULL_PTR);
- expand_aggr_init_1 (binfo, true_exp, subexp, *init_ptr,
- alias_this && BINFO_OFFSET_ZEROP (TREE_VALUE (init_list)),
- LOOKUP_COMPLAIN);
-
- /* INIT_PTR is used up. */
- init_ptr = &init_null;
+ expand_decl_init (exp);
+ return;
}
- else
- my_friendly_abort (50);
- init_list = TREE_CHAIN (init_list);
- }
-}
-
-/* Initialize EXP with INIT. Type EXP does not have a constructor,
- but it has a baseclass with a constructor or a virtual function
- table which needs initializing.
-
- INIT_LIST is a cons-list describing what parts of EXP actually
- need to be initialized. INIT is given to the *unique*, first
- constructor within INIT_LIST. If there are multiple first
- constructors, such as with multiple inheritance, INIT must
- be zero or an ambiguity error is reported.
-
- ALIAS_THIS is passed from `expand_aggr_init'. See comments
- there. */
-
-static void
-expand_recursive_init (binfo, true_exp, exp, init, init_list, alias_this)
- tree binfo, true_exp, exp, init;
- tree init_list;
- int alias_this;
-{
- tree *old_init_ptr = init_ptr;
- tree addr = build_unary_op (ADDR_EXPR, exp, 0);
- init_ptr = &init;
-
- if (true_exp == exp && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
- {
- expand_aggr_vbase_init (binfo, exp, addr, init_list);
- expand_indirect_vtbls_init (binfo, true_exp, addr, 1);
+ t = build (INIT_EXPR, type, exp, init);
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr_stmt (t);
+ return;
}
- expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this);
-
- if (*init_ptr)
- {
- tree type = TREE_TYPE (exp);
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
- if (IS_AGGR_TYPE (type))
- cp_error ("unexpected argument to constructor `%T'", type);
- else
- error ("unexpected argument to constructor");
- }
- init_ptr = old_init_ptr;
+ /* We know that expand_default_init can handle everything we want
+ at this point. */
+ expand_default_init (binfo, true_exp, exp, init, alias_this, flags);
}
/* Report an error if NAME is not the name of a user-defined,
aggregate type. If OR_ELSE is nonzero, give an error message. */
+
int
is_aggr_typedef (name, or_else)
tree name;
@@ -1681,7 +1288,30 @@ is_aggr_typedef (name, or_else)
}
if (! IS_AGGR_TYPE (type)
- && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
+ && TREE_CODE (type) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
+ {
+ if (or_else)
+ cp_error ("`%T' is not an aggregate type", type);
+ return 0;
+ }
+ return 1;
+}
+
+/* Report an error if TYPE is not a user-defined, aggregate type. If
+ OR_ELSE is nonzero, give an error message. */
+
+int
+is_aggr_type (type, or_else)
+ tree type;
+ int or_else;
+{
+ if (type == error_mark_node)
+ return 0;
+
+ if (! IS_AGGR_TYPE (type)
+ && TREE_CODE (type) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
{
if (or_else)
cp_error ("`%T' is not an aggregate type", type);
@@ -1691,6 +1321,7 @@ is_aggr_typedef (name, or_else)
}
/* Like is_aggr_typedef, but returns typedef if successful. */
+
tree
get_aggr_from_typedef (name, or_else)
tree name;
@@ -1711,7 +1342,8 @@ get_aggr_from_typedef (name, or_else)
}
if (! IS_AGGR_TYPE (type)
- && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
+ && TREE_CODE (type) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
{
if (or_else)
cp_error ("type `%T' is of non-aggregate type", type);
@@ -1737,40 +1369,59 @@ get_type_value (name)
/* This code could just as well go in `class.c', but is placed here for
modularity. */
-/* For an expression of the form CNAME :: NAME (PARMLIST), build
+/* For an expression of the form TYPE :: NAME (PARMLIST), build
the appropriate function call. */
+
tree
-build_member_call (cname, name, parmlist)
- tree cname, name, parmlist;
+build_member_call (type, name, parmlist)
+ tree type, name, parmlist;
{
- tree type, t;
- tree method_name = name;
+ tree t;
+ tree method_name;
int dtor = 0;
int dont_use_this = 0;
tree basetype_path, decl;
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR
+ && TREE_CODE (type) == NAMESPACE_DECL)
+ {
+ /* 'name' already refers to the decls from the namespace, since we
+ hit do_identifier for template_ids. */
+ my_friendly_assert (is_overloaded_fn (TREE_OPERAND (name, 0)), 980519);
+ return build_x_function_call (name, parmlist, current_class_ref);
+ }
+
+ if (type == std_node)
+ return build_x_function_call (do_scoped_id (name, 0), parmlist,
+ current_class_ref);
+ if (TREE_CODE (type) == NAMESPACE_DECL)
+ return build_x_function_call (lookup_namespace_name (type, name),
+ parmlist, current_class_ref);
+
+ if (TREE_CODE (name) != TEMPLATE_ID_EXPR)
+ method_name = name;
+ else
+ method_name = TREE_OPERAND (name, 0);
+
if (TREE_CODE (method_name) == BIT_NOT_EXPR)
{
method_name = TREE_OPERAND (method_name, 0);
dtor = 1;
}
- if (TREE_CODE (cname) == SCOPE_REF)
- cname = resolve_scope_to_name (NULL_TREE, cname);
-
/* This shouldn't be here, and build_member_call shouldn't appear in
parse.y! (mrs) */
- if (cname && get_aggr_from_typedef (cname, 0) == 0
- && TREE_CODE (cname) == IDENTIFIER_NODE)
+ if (type && TREE_CODE (type) == IDENTIFIER_NODE
+ && get_aggr_from_typedef (type, 0) == 0)
{
- tree ns = lookup_name (cname, 0);
+ tree ns = lookup_name (type, 0);
if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
{
- return build_x_function_call (build_offset_ref (cname, name), parmlist, current_class_decl);
+ return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_ref);
}
}
- if (cname == NULL_TREE || ! (type = get_aggr_from_typedef (cname, 1)))
+ if (type == NULL_TREE || ! is_aggr_type (type, 1))
return error_mark_node;
/* An operator we did not like. */
@@ -1779,12 +1430,6 @@ build_member_call (cname, name, parmlist)
if (dtor)
{
-#if 0
- /* Everything can explicitly call a destructor; see 12.4 */
- if (! TYPE_HAS_DESTRUCTOR (type))
- cp_error ("type `%#T' does not have a destructor", type);
- else
-#endif
cp_error ("cannot call destructor `%T::~%T' without object", type,
method_name);
return error_mark_node;
@@ -1801,14 +1446,14 @@ build_member_call (cname, name, parmlist)
basetype_path = TYPE_BINFO (type);
decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
}
- else if (current_class_decl == 0)
+ else if (current_class_ptr == 0)
{
dont_use_this = 1;
decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
}
else
{
- tree olddecl = current_class_decl;
+ tree olddecl = current_class_ptr;
tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
if (oldtype != type)
{
@@ -1825,8 +1470,11 @@ build_member_call (cname, name, parmlist)
if (method_name == constructor_name (type)
|| method_name == constructor_name_full (type))
return build_functional_cast (type, parmlist);
- if (t = lookup_fnfields (basetype_path, method_name, 0))
- return build_method_call (decl, method_name, parmlist, basetype_path,
+ if ((t = lookup_fnfields (basetype_path, method_name, 0)))
+ return build_method_call (decl,
+ TREE_CODE (name) == TEMPLATE_ID_EXPR
+ ? name : method_name,
+ parmlist, basetype_path,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
if (TREE_CODE (name) == IDENTIFIER_NODE
&& ((t = lookup_field (TYPE_BINFO (type), name, 1, 0))))
@@ -1849,9 +1497,9 @@ build_member_call (cname, name, parmlist)
cp_error ("invalid use of member `%D'", t);
return error_mark_node;
}
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl))
- && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (decl)))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl, parmlist, NULL_TREE);
+ if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)))
+ return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl,
+ parmlist, NULL_TREE);
return build_function_call (decl, parmlist);
}
else
@@ -1863,54 +1511,77 @@ build_member_call (cname, name, parmlist)
/* Build a reference to a member of an aggregate. This is not a
C++ `&', but really something which can have its address taken,
- and then act as a pointer to member, for example CNAME :: FIELD
- can have its address taken by saying & CNAME :: FIELD.
+ and then act as a pointer to member, for example TYPE :: FIELD
+ can have its address taken by saying & TYPE :: FIELD.
@@ Prints out lousy diagnostics for operator <typename>
@@ fields.
@@ This function should be rewritten and placed in search.c. */
+
tree
-build_offset_ref (cname, name)
- tree cname, name;
+build_offset_ref (type, name)
+ tree type, name;
{
- tree decl, type, fnfields, fields, t = error_mark_node;
- tree basetypes = NULL_TREE;
- int dtor = 0;
+ tree decl, fnfields, fields, t = error_mark_node;
+ tree basebinfo = NULL_TREE;
+ tree orig_name = name;
- if (TREE_CODE (cname) == SCOPE_REF)
- cname = resolve_scope_to_name (NULL_TREE, cname);
+ /* class templates can come in as TEMPLATE_DECLs here. */
+ if (TREE_CODE (name) == TEMPLATE_DECL)
+ return name;
+
+ if (type == std_node)
+ return do_scoped_id (name, 0);
+
+ if (processing_template_decl || uses_template_parms (type))
+ return build_min_nt (SCOPE_REF, type, name);
/* Handle namespace names fully here. */
- if (TREE_CODE (cname) == IDENTIFIER_NODE
- && get_aggr_from_typedef (cname, 0) == 0)
+ if (TREE_CODE (type) == NAMESPACE_DECL)
{
- tree ns = lookup_name (cname, 0);
- tree val;
- if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
+ t = lookup_namespace_name (type, name);
+ if (! type_unknown_p (t))
{
- val = lookup_namespace_name (ns, name);
- if (val)
- return val;
- cp_error ("namespace `%D' has no member named `%D'", ns, name);
- return error_mark_node;
+ mark_used (t);
+ t = convert_from_reference (t);
}
+ return t;
}
- if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1))
+ if (type == NULL_TREE || ! is_aggr_type (type, 1))
return error_mark_node;
- type = IDENTIFIER_TYPE_VALUE (cname);
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ /* If the NAME is a TEMPLATE_ID_EXPR, we are looking at
+ something like `a.template f<int>' or the like. For the most
+ part, we treat this just like a.f. We do remember, however,
+ the template-id that was used. */
+ name = TREE_OPERAND (orig_name, 0);
+ my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
+ }
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
- dtor = 1;
- name = TREE_OPERAND (name, 0);
+ if (! check_dtor_name (type, name))
+ cp_error ("qualified type `%T' does not match destructor name `~%T'",
+ type, TREE_OPERAND (name, 0));
+ name = dtor_identifier;
}
+#if 0
+ /* I think this is wrong, but the draft is unclear. --jason 6/15/98 */
+ else if (name == constructor_name_full (type)
+ || name == constructor_name (type))
+ name = ctor_identifier;
+#endif
- if (TYPE_SIZE (type) == 0)
+ if (TYPE_SIZE (complete_type (type)) == 0)
{
- t = IDENTIFIER_CLASS_VALUE (name);
+ if (type == current_class_type)
+ t = IDENTIFIER_CLASS_VALUE (name);
+ else
+ t = NULL_TREE;
if (t == 0)
{
cp_error ("incomplete type `%T' does not have member `%D'", type,
@@ -1920,7 +1591,7 @@ build_offset_ref (cname, name)
if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL
|| TREE_CODE (t) == CONST_DECL)
{
- TREE_USED (t) = 1;
+ mark_used (t);
return t;
}
if (TREE_CODE (t) == FIELD_DECL)
@@ -1932,125 +1603,104 @@ build_offset_ref (cname, name)
return error_mark_node;
}
-#if 0
- if (TREE_CODE (name) == TYPE_EXPR)
- /* Pass a TYPE_DECL to build_component_type_expr. */
- return build_component_type_expr (TYPE_NAME (TREE_TYPE (cname)),
- name, NULL_TREE, 1);
-#endif
-
if (current_class_type == 0
- || get_base_distance (type, current_class_type, 0, &basetypes) == -1)
+ || get_base_distance (type, current_class_type, 0, &basebinfo) == -1)
{
- basetypes = TYPE_BINFO (type);
- decl = build1 (NOP_EXPR,
- IDENTIFIER_TYPE_VALUE (cname),
- error_mark_node);
+ basebinfo = TYPE_BINFO (type);
+ decl = build1 (NOP_EXPR, type, error_mark_node);
}
- else if (current_class_decl == 0)
- decl = build1 (NOP_EXPR, IDENTIFIER_TYPE_VALUE (cname),
- error_mark_node);
+ else if (current_class_ptr == 0)
+ decl = build1 (NOP_EXPR, type, error_mark_node);
else
- decl = C_C_D;
+ decl = current_class_ref;
- fnfields = lookup_fnfields (basetypes, name, 1);
- fields = lookup_field (basetypes, name, 0, 0);
+ fnfields = lookup_fnfields (basebinfo, name, 1);
+ fields = lookup_field (basebinfo, name, 0, 0);
if (fields == error_mark_node || fnfields == error_mark_node)
return error_mark_node;
/* A lot of this logic is now handled in lookup_field and
- lookup_fnfield. */
+ lookup_fnfield. */
if (fnfields)
{
- basetypes = TREE_PURPOSE (fnfields);
+ extern int flag_save_memoized_contexts;
/* Go from the TREE_BASELINK to the member function info. */
t = TREE_VALUE (fnfields);
- if (fields)
+ if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
{
- if (DECL_FIELD_CONTEXT (fields) == DECL_FIELD_CONTEXT (t))
+ /* The FNFIELDS are going to contain functions that aren't
+ necessarily templates, and templates that don't
+ necessarily match the explicit template parameters. We
+ save all the functions, and the explicit parameters, and
+ then figure out exactly what to instantiate with what
+ arguments in instantiate_type. */
+
+ if (TREE_CODE (t) != OVERLOAD)
+ /* The code in instantiate_type which will process this
+ expects to encounter OVERLOADs, not raw functions. */
+ t = ovl_cons (t, NULL_TREE);
+
+ return build (OFFSET_REF,
+ build_offset_type (type, unknown_type_node),
+ decl,
+ build (TEMPLATE_ID_EXPR,
+ TREE_TYPE (t),
+ t,
+ TREE_OPERAND (orig_name, 1)));
+ }
+
+ if (!really_overloaded_fn (t))
+ {
+ tree access;
+
+ /* Get rid of a potential OVERLOAD around it */
+ t = OVL_CURRENT (t);
+
+ /* unique functions are handled easily. */
+ basebinfo = TREE_PURPOSE (fnfields);
+ access = compute_access (basebinfo, t);
+ if (access == access_protected_node)
{
- error ("ambiguous member reference: member `%s' defined as both field and function",
- IDENTIFIER_POINTER (name));
+ cp_error_at ("member function `%#D' is protected", t);
+ error ("in this context");
return error_mark_node;
}
- if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (fields), DECL_FIELD_CONTEXT (t)))
- ;
- else if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (t), DECL_FIELD_CONTEXT (fields)))
- t = fields;
- else
+ if (access == access_private_node)
{
- error ("ambiguous member reference: member `%s' derives from distinct classes in multiple inheritance lattice");
+ cp_error_at ("member function `%#D' is private", t);
+ error ("in this context");
return error_mark_node;
}
+ mark_used (t);
+ return build (OFFSET_REF, TREE_TYPE (t), decl, t);
}
- if (t == TREE_VALUE (fnfields))
- {
- extern int flag_save_memoized_contexts;
-
- if (DECL_CHAIN (t) == NULL_TREE || dtor)
- {
- enum access_type access;
+ /* FNFIELDS is most likely allocated on the search_obstack,
+ which will go away after this class scope. If we need
+ to save this value for later (either for memoization
+ or for use as an initializer for a static variable), then
+ do so here.
- /* unique functions are handled easily. */
- unique:
- access = compute_access (basetypes, t);
- if (access == access_protected)
- {
- cp_error_at ("member function `%#D' is protected", t);
- error ("in this context");
- return error_mark_node;
- }
- if (access == access_private)
- {
- cp_error_at ("member function `%#D' is private", t);
- error ("in this context");
- return error_mark_node;
- }
- assemble_external (t);
- return build (OFFSET_REF, TREE_TYPE (t), decl, t);
- }
+ ??? The smart thing to do for the case of saving initializers
+ is to resolve them before we're done with this scope. */
+ if (!TREE_PERMANENT (fnfields)
+ && ((flag_save_memoized_contexts && toplevel_bindings_p ())
+ || ! allocation_temporary_p ()))
+ fnfields = copy_list (fnfields);
- /* overloaded functions may need more work. */
- if (cname == name)
- {
- if (TYPE_HAS_DESTRUCTOR (type)
- && DECL_CHAIN (DECL_CHAIN (t)) == NULL_TREE)
- {
- t = DECL_CHAIN (t);
- goto unique;
- }
- }
- /* FNFIELDS is most likely allocated on the search_obstack,
- which will go away after this class scope. If we need
- to save this value for later (either for memoization
- or for use as an initializer for a static variable), then
- do so here.
-
- ??? The smart thing to do for the case of saving initializers
- is to resolve them before we're done with this scope. */
- if (!TREE_PERMANENT (fnfields)
- && ((flag_save_memoized_contexts && global_bindings_p ())
- || ! allocation_temporary_p ()))
- fnfields = copy_list (fnfields);
-
- for (t = TREE_VALUE (fnfields); t; t = DECL_CHAIN (t))
- assemble_external (t);
-
- t = build_tree_list (error_mark_node, fnfields);
- TREE_TYPE (t) = build_offset_type (type, unknown_type_node);
- return t;
- }
+ t = build_tree_list (error_mark_node, fnfields);
+ TREE_TYPE (t) = build_offset_type (type, unknown_type_node);
+ return t;
}
/* Now that we know we are looking for a field, see if we
have access to that field. Lookup_field will give us the
error message. */
- t = lookup_field (basetypes, name, 1, 0);
+ t = lookup_field (basebinfo, name, 1, 0);
if (t == error_mark_node)
return error_mark_node;
@@ -2070,9 +1720,8 @@ build_offset_ref (cname, name)
values can be returned without further ado. */
if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL)
{
- assemble_external (t);
- TREE_USED (t) = 1;
- return t;
+ mark_used (t);
+ return convert_from_reference (t);
}
if (TREE_CODE (t) == FIELD_DECL && DECL_BIT_FIELD (t))
@@ -2082,80 +1731,16 @@ build_offset_ref (cname, name)
}
/* static class functions too. */
- if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
+ if (TREE_CODE (t) == FUNCTION_DECL
+ && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
my_friendly_abort (53);
- /* In member functions, the form `cname::name' is no longer
- equivalent to `this->cname::name'. */
+ /* In member functions, the form `type::name' is no longer
+ equivalent to `this->type::name', at least not until
+ resolve_offset_ref. */
return build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t);
}
-/* Given an object EXP and a member function reference MEMBER,
- return the address of the actual member function. */
-tree
-get_member_function (exp_addr_ptr, exp, member)
- tree *exp_addr_ptr;
- tree exp, member;
-{
- tree ctype = TREE_TYPE (exp);
- tree function = save_expr (build_unary_op (ADDR_EXPR, member, 0));
-
- if (TYPE_VIRTUAL_P (ctype)
- || (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (ctype)))
- {
- tree e0, e1, e3;
- tree exp_addr;
-
- /* Save away the unadulterated `this' pointer. */
- exp_addr = save_expr (*exp_addr_ptr);
-
- /* Cast function to signed integer. */
- e0 = build1 (NOP_EXPR, integer_type_node, function);
-
- /* There is a hack here that takes advantage of
- twos complement arithmetic, and the fact that
- there are more than one UNITS to the WORD.
- If the high bit is set for the `function',
- then we pretend it is a virtual function,
- and the array indexing will knock this bit
- out the top, leaving a valid index. */
- if (UNITS_PER_WORD <= 1)
- my_friendly_abort (54);
-
- e1 = build (GT_EXPR, boolean_type_node, e0, integer_zero_node);
- e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr,
- build_tree_list (NULL_TREE, e1)));
- e1 = save_expr (e1);
-
- if (TREE_SIDE_EFFECTS (*exp_addr_ptr))
- {
- exp = build_indirect_ref (exp_addr, NULL_PTR);
- *exp_addr_ptr = exp_addr;
- }
-
- /* This is really hairy: if the function pointer is a pointer
- to a non-virtual member function, then we can't go mucking
- with the `this' pointer (any more than we already have to
- this point). If it is a pointer to a virtual member function,
- then we have to adjust the `this' pointer according to
- what the virtual function table tells us. */
-
- e3 = build_vfn_ref (exp_addr_ptr, exp, e0);
- my_friendly_assert (e3 != error_mark_node, 213);
-
- /* Change this pointer type from `void *' to the
- type it is really supposed to be. */
- TREE_TYPE (e3) = TREE_TYPE (function);
-
- /* If non-virtual, use what we had originally. Otherwise,
- use the value we get from the virtual function table. */
- *exp_addr_ptr = build_conditional_expr (e1, exp_addr, *exp_addr_ptr);
-
- function = build_conditional_expr (e1, function, e3);
- }
- return build_indirect_ref (function, NULL_PTR);
-}
-
/* If a OFFSET_REF made it through to here, then it did
not have its address taken. */
@@ -2169,9 +1754,17 @@ resolve_offset_ref (exp)
tree basetype, addr;
if (TREE_CODE (exp) == TREE_LIST)
- return build_unary_op (ADDR_EXPR, exp, 0);
+ {
+ cp_pedwarn ("assuming & on overloaded member function");
+ return build_unary_op (ADDR_EXPR, exp, 0);
+ }
- if (TREE_CODE (exp) != OFFSET_REF)
+ if (TREE_CODE (exp) == OFFSET_REF)
+ {
+ member = TREE_OPERAND (exp, 1);
+ base = TREE_OPERAND (exp, 0);
+ }
+ else
{
my_friendly_assert (TREE_CODE (type) == OFFSET_TYPE, 214);
if (TYPE_OFFSET_BASETYPE (type) != current_class_type)
@@ -2181,17 +1774,13 @@ resolve_offset_ref (exp)
}
member = exp;
type = TREE_TYPE (type);
- base = C_C_D;
- }
- else
- {
- member = TREE_OPERAND (exp, 1);
- base = TREE_OPERAND (exp, 0);
+ base = current_class_ref;
}
if ((TREE_CODE (member) == VAR_DECL
&& ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member)))
- || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE)
+ || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
{
/* These were static members. */
if (mark_addressable (member) == 0)
@@ -2199,9 +1788,13 @@ resolve_offset_ref (exp)
return member;
}
+ if (TREE_CODE (TREE_TYPE (member)) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (member))) == METHOD_TYPE)
+ return member;
+
/* Syntax error can cause a member which should
have been seen as static to be grok'd as non-static. */
- if (TREE_CODE (member) == FIELD_DECL && C_C_D == NULL_TREE)
+ if (TREE_CODE (member) == FIELD_DECL && current_class_ref == NULL_TREE)
{
if (TREE_ADDRESSABLE (member) == 0)
{
@@ -2215,37 +1808,38 @@ resolve_offset_ref (exp)
/* The first case is really just a reference to a member of `this'. */
if (TREE_CODE (member) == FIELD_DECL
- && (base == C_C_D
+ && (base == current_class_ref
|| (TREE_CODE (base) == NOP_EXPR
&& TREE_OPERAND (base, 0) == error_mark_node)))
{
- tree basetype_path;
- enum access_type access;
+ tree basetype_path, access;
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
basetype = TYPE_OFFSET_BASETYPE (type);
else
basetype = DECL_CONTEXT (member);
- base = current_class_decl;
+ base = current_class_ptr;
if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0)
{
error_not_base_type (basetype, TREE_TYPE (TREE_TYPE (base)));
return error_mark_node;
}
- addr = convert_pointer_to (basetype, base);
+ /* Kludge: we need to use basetype_path now, because
+ convert_pointer_to will bash it. */
access = compute_access (basetype_path, member);
- if (access == access_public)
+ addr = convert_pointer_to (basetype, base);
+ if (access == access_public_node)
return build (COMPONENT_REF, TREE_TYPE (member),
build_indirect_ref (addr, NULL_PTR), member);
- if (access == access_protected)
+ if (access == access_protected_node)
{
cp_error_at ("member `%D' is protected", member);
error ("in this context");
return error_mark_node;
}
- if (access == access_private)
+ if (access == access_private_node)
{
cp_error_at ("member `%D' is private", member);
error ("in this context");
@@ -2254,24 +1848,39 @@ resolve_offset_ref (exp)
my_friendly_abort (55);
}
- /* If this is a reference to a member function, then return
- the address of the member function (which may involve going
- through the object's vtable), otherwise, return an expression
- for the dereferenced pointer-to-member construct. */
- addr = build_unary_op (ADDR_EXPR, base, 0);
-
- if (TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
+ /* Ensure that we have an object. */
+ if (TREE_CODE (base) == NOP_EXPR
+ && TREE_OPERAND (base, 0) == error_mark_node)
+ addr = error_mark_node;
+ else
{
- basetype = DECL_CLASS_CONTEXT (member);
- addr = convert_pointer_to (basetype, addr);
- return build_unary_op (ADDR_EXPR, get_member_function (&addr, build_indirect_ref (addr, NULL_PTR), member), 0);
+ /* If this is a reference to a member function, then return the
+ address of the member function (which may involve going
+ through the object's vtable), otherwise, return an expression
+ for the dereferenced pointer-to-member construct. */
+ addr = build_unary_op (ADDR_EXPR, base, 0);
}
- else if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE)
+
+ if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE)
{
+ if (addr == error_mark_node)
+ {
+ cp_error ("object missing in `%E'", exp);
+ return error_mark_node;
+ }
+
basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member));
addr = convert_pointer_to (basetype, addr);
- member = convert (ptrdiff_type_node,
- build_unary_op (ADDR_EXPR, member, 0));
+ member = cp_convert (ptrdiff_type_node,
+ build_unary_op (ADDR_EXPR, member, 0));
+
+ /* Pointer to data members are offset by one, so that a null
+ pointer with a real value of 0 is distinguishable from an
+ offset of the first member of a structure. */
+ member = build_binary_op (MINUS_EXPR, member,
+ cp_convert (ptrdiff_type_node, integer_one_node),
+ 0);
+
return build1 (INDIRECT_REF, type,
build (PLUS_EXPR, build_pointer_type (type),
addr, member));
@@ -2300,7 +1909,7 @@ decl_constant_value (decl)
&& ! pedantic
#endif /* 0 */
&& DECL_INITIAL (decl) != 0
- && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
+ && DECL_INITIAL (decl) != error_mark_node
/* This is invalid if initial value is not constant.
If it has either a function call, a memory reference,
or a variable, then re-evaluating it could give different results. */
@@ -2318,499 +1927,18 @@ decl_constant_value (decl)
return decl;
}
-/* Friend handling routines. */
-/* Friend data structures:
-
- Lists of friend functions come from TYPE_DECL nodes. Since all
- aggregate types are automatically typedef'd, these nodes are guaranteed
- to exist.
-
- The TREE_PURPOSE of a friend list is the name of the friend,
- and its TREE_VALUE is another list.
-
- For each element of that list, either the TREE_VALUE or the TREE_PURPOSE
- will be filled in, but not both. The TREE_VALUE of that list is an
- individual function which is a friend. The TREE_PURPOSE of that list
- indicates a type in which all functions by that name are friends.
-
- Lists of friend classes come from _TYPE nodes. Love that consistency
- thang. */
-
-int
-is_friend_type (type1, type2)
- tree type1, type2;
-{
- return is_friend (type1, type2);
-}
-
-int
-is_friend (type, supplicant)
- tree type, supplicant;
-{
- int declp;
- register tree list;
-
- if (supplicant == NULL_TREE || type == NULL_TREE)
- return 0;
-
- declp = (TREE_CODE_CLASS (TREE_CODE (supplicant)) == 'd');
-
- if (declp)
- /* It's a function decl. */
- {
- tree list = DECL_FRIENDLIST (TYPE_NAME (type));
- tree name = DECL_NAME (supplicant);
- tree ctype;
-
- if (DECL_FUNCTION_MEMBER_P (supplicant))
- ctype = DECL_CLASS_CONTEXT (supplicant);
- else
- ctype = NULL_TREE;
-
- for (; list ; list = TREE_CHAIN (list))
- {
- if (name == TREE_PURPOSE (list))
- {
- tree friends = TREE_VALUE (list);
- name = DECL_ASSEMBLER_NAME (supplicant);
- for (; friends ; friends = TREE_CHAIN (friends))
- {
- if (ctype == TREE_PURPOSE (friends))
- return 1;
- if (name == DECL_ASSEMBLER_NAME (TREE_VALUE (friends)))
- return 1;
- }
- break;
- }
- }
- }
- else
- /* It's a type. */
- {
- if (type == supplicant)
- return 1;
-
- list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_NAME (type)));
- for (; list ; list = TREE_CHAIN (list))
- if (supplicant == TREE_VALUE (list))
- return 1;
- }
-
- {
- tree context;
-
- if (! declp)
- context = DECL_CONTEXT (TYPE_NAME (supplicant));
- else if (DECL_FUNCTION_MEMBER_P (supplicant))
- context = DECL_CLASS_CONTEXT (supplicant);
- else
- context = NULL_TREE;
-
- if (context)
- return is_friend (type, context);
- }
-
- return 0;
-}
-
-/* Add a new friend to the friends of the aggregate type TYPE.
- DECL is the FUNCTION_DECL of the friend being added. */
-static void
-add_friend (type, decl)
- tree type, decl;
-{
- tree typedecl = TYPE_NAME (type);
- tree list = DECL_FRIENDLIST (typedecl);
- tree name = DECL_NAME (decl);
-
- while (list)
- {
- if (name == TREE_PURPOSE (list))
- {
- tree friends = TREE_VALUE (list);
- for (; friends ; friends = TREE_CHAIN (friends))
- {
- if (decl == TREE_VALUE (friends))
- {
- cp_warning ("`%D' is already a friend of class `%T'",
- decl, type);
- cp_warning_at ("previous friend declaration of `%D'",
- TREE_VALUE (friends));
- return;
- }
- }
- TREE_VALUE (list) = tree_cons (error_mark_node, decl,
- TREE_VALUE (list));
- return;
- }
- list = TREE_CHAIN (list);
- }
- DECL_FRIENDLIST (typedecl)
- = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
- DECL_FRIENDLIST (typedecl));
- if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR])
- {
- tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
- TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
- if (parmtypes && TREE_CHAIN (parmtypes))
- {
- tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes));
- if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl))
- TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1;
- }
- }
-}
-
-/* Declare that every member function NAME in FRIEND_TYPE
- (which may be NULL_TREE) is a friend of type TYPE. */
-static void
-add_friends (type, name, friend_type)
- tree type, name, friend_type;
-{
- tree typedecl = TYPE_NAME (type);
- tree list = DECL_FRIENDLIST (typedecl);
-
- while (list)
- {
- if (name == TREE_PURPOSE (list))
- {
- tree friends = TREE_VALUE (list);
- while (friends && TREE_PURPOSE (friends) != friend_type)
- friends = TREE_CHAIN (friends);
- if (friends)
- if (friend_type)
- warning ("method `%s::%s' is already a friend of class",
- TYPE_NAME_STRING (friend_type),
- IDENTIFIER_POINTER (name));
- else
- warning ("function `%s' is already a friend of class `%s'",
- IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (DECL_NAME (typedecl)));
- else
- TREE_VALUE (list) = tree_cons (friend_type, NULL_TREE,
- TREE_VALUE (list));
- return;
- }
- list = TREE_CHAIN (list);
- }
- DECL_FRIENDLIST (typedecl) =
- tree_cons (name,
- build_tree_list (friend_type, NULL_TREE),
- DECL_FRIENDLIST (typedecl));
- if (! strncmp (IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]),
- strlen (IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]))))
- {
- TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
- sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists");
- }
-}
-
-/* Set up a cross reference so that type TYPE will make member function
- CTYPE::DECL a friend when CTYPE is finally defined. For more than
- one, set up a cross reference so that functions with the name DECL
- and type CTYPE know that they are friends of TYPE. */
-static void
-xref_friend (type, decl, ctype)
- tree type, decl, ctype;
-{
- tree friend_decl = TYPE_NAME (ctype);
-#if 0
- tree typedecl = TYPE_NAME (type);
- tree t = tree_cons (NULL_TREE, ctype, DECL_UNDEFINED_FRIENDS (typedecl));
-
- DECL_UNDEFINED_FRIENDS (typedecl) = t;
-#else
- tree t = 0;
-#endif
- SET_DECL_WAITING_FRIENDS (friend_decl,
- tree_cons (type, t,
- DECL_WAITING_FRIENDS (friend_decl)));
- TREE_TYPE (DECL_WAITING_FRIENDS (friend_decl)) = decl;
-}
-
-/* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already
- been defined, we make all of its member functions friends of
- TYPE. If not, we make it a pending friend, which can later be added
- when its definition is seen. If a type is defined, then its TYPE_DECL's
- DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend
- classes that are not defined. If a type has not yet been defined,
- then the DECL_WAITING_FRIENDS contains a list of types
- waiting to make it their friend. Note that these two can both
- be in use at the same time! */
-void
-make_friend_class (type, friend_type)
- tree type, friend_type;
-{
- tree classes;
-
- if (IS_SIGNATURE (type))
- {
- error ("`friend' declaration in signature definition");
- return;
- }
- if (IS_SIGNATURE (friend_type))
- {
- error ("signature type `%s' declared `friend'",
- IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (friend_type))));
- return;
- }
- if (type == friend_type)
- {
- pedwarn ("class `%s' is implicitly friends with itself",
- TYPE_NAME_STRING (type));
- return;
- }
-
- GNU_xref_hier (TYPE_NAME_STRING (type),
- TYPE_NAME_STRING (friend_type), 0, 0, 1);
-
- classes = CLASSTYPE_FRIEND_CLASSES (type);
- while (classes && TREE_VALUE (classes) != friend_type)
- classes = TREE_CHAIN (classes);
- if (classes)
- warning ("class `%s' is already friends with class `%s'",
- TYPE_NAME_STRING (TREE_VALUE (classes)), TYPE_NAME_STRING (type));
- else
- {
- CLASSTYPE_FRIEND_CLASSES (type)
- = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
- }
-}
-
-/* Main friend processor. This is large, and for modularity purposes,
- has been removed from grokdeclarator. It returns `void_type_node'
- to indicate that something happened, though a FIELD_DECL is
- not returned.
-
- CTYPE is the class this friend belongs to.
-
- DECLARATOR is the name of the friend.
-
- DECL is the FUNCTION_DECL that the friend is.
-
- In case we are parsing a friend which is part of an inline
- definition, we will need to store PARM_DECL chain that comes
- with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL.
-
- FLAGS is just used for `grokclassfn'.
-
- QUALS say what special qualifies should apply to the object
- pointed to by `this'. */
-tree
-do_friend (ctype, declarator, decl, parmdecls, flags, quals)
- tree ctype, declarator, decl, parmdecls;
- enum overload_flags flags;
- tree quals;
-{
- /* Every decl that gets here is a friend of something. */
- DECL_FRIEND_P (decl) = 1;
-
- if (ctype)
- {
- tree cname = TYPE_NAME (ctype);
- if (TREE_CODE (cname) == TYPE_DECL)
- cname = DECL_NAME (cname);
-
- /* A method friend. */
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- if (flags == NO_SPECIAL && ctype && declarator == cname)
- DECL_CONSTRUCTOR_P (decl) = 1;
-
- /* This will set up DECL_ARGUMENTS for us. */
- grokclassfn (ctype, cname, decl, flags, quals);
- if (TYPE_SIZE (ctype) != 0)
- check_classfn (ctype, cname, decl);
-
- if (TREE_TYPE (decl) != error_mark_node)
- {
- if (TYPE_SIZE (ctype))
- {
- /* We don't call pushdecl here yet, or ever on this
- actual FUNCTION_DECL. We must preserve its TREE_CHAIN
- until the end. */
- make_decl_rtl (decl, NULL_PTR, 1);
- add_friend (current_class_type, decl);
- }
- else
- {
- register char *classname
- = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (ctype)));
-
- error ("member declared as friend before type `%s' defined",
- classname);
- }
- }
- }
- else
- {
- /* Possibly a bunch of method friends. */
-
- /* Get the class they belong to. */
- tree ctype = IDENTIFIER_TYPE_VALUE (cname);
-
- /* This class is defined, use its methods now. */
- if (TYPE_SIZE (ctype))
- {
- tree fields = lookup_fnfields (TYPE_BINFO (ctype), declarator, 0);
- if (fields)
- add_friends (current_class_type, declarator, ctype);
- else
- error ("method `%s' is not a member of class `%s'",
- IDENTIFIER_POINTER (declarator),
- IDENTIFIER_POINTER (cname));
- }
- else
- /* Note: DECLARATOR actually has more than one; in this
- case, we're making sure that fns with the name DECLARATOR
- and type CTYPE know they are friends of the current
- class type. */
- xref_friend (current_class_type, declarator, ctype);
- decl = void_type_node;
- }
- }
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && ((IDENTIFIER_LENGTH (declarator) == 4
- && IDENTIFIER_POINTER (declarator)[0] == 'm'
- && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
- || (IDENTIFIER_LENGTH (declarator) > 10
- && IDENTIFIER_POINTER (declarator)[0] == '_'
- && IDENTIFIER_POINTER (declarator)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (declarator)+2,
- "builtin_", 8) == 0)))
- {
- /* raw "main", and builtin functions never gets overloaded,
- but they can become friends. */
- add_friend (current_class_type, decl);
- DECL_FRIEND_P (decl) = 1;
- decl = void_type_node;
- }
- /* A global friend.
- @@ or possibly a friend from a base class ?!? */
- else if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- /* Friends must all go through the overload machinery,
- even though they may not technically be overloaded.
-
- Note that because classes all wind up being top-level
- in their scope, their friend wind up in top-level scope as well. */
- DECL_ASSEMBLER_NAME (decl)
- = build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)),
- TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
- DECL_ARGUMENTS (decl) = parmdecls;
- DECL_CLASS_CONTEXT (decl) = current_class_type;
-
- /* We can call pushdecl here, because the TREE_CHAIN of this
- FUNCTION_DECL is not needed for other purposes. */
- decl = pushdecl (decl);
-
- make_decl_rtl (decl, NULL_PTR, 1);
- add_friend (current_class_type, decl);
-
- DECL_FRIEND_P (decl) = 1;
-#if 0
- TREE_OVERLOADED (declarator) = 1;
-#endif
- }
- else
- {
- /* @@ Should be able to ingest later definitions of this function
- before use. */
- tree decl = lookup_name_nonclass (declarator);
- if (decl == NULL_TREE)
- {
- warning ("implicitly declaring `%s' as struct",
- IDENTIFIER_POINTER (declarator));
- decl = xref_tag (record_type_node, declarator, NULL_TREE, 1);
- decl = TYPE_NAME (decl);
- }
-
- /* Allow abbreviated declarations of overloaded functions,
- but not if those functions are really class names. */
- if (TREE_CODE (decl) == TREE_LIST && TREE_TYPE (TREE_PURPOSE (decl)))
- {
- warning ("`friend %s' archaic, use `friend class %s' instead",
- IDENTIFIER_POINTER (declarator),
- IDENTIFIER_POINTER (declarator));
- decl = TREE_TYPE (TREE_PURPOSE (decl));
- }
-
- if (TREE_CODE (decl) == TREE_LIST)
- add_friends (current_class_type, TREE_PURPOSE (decl), NULL_TREE);
- else
- make_friend_class (current_class_type, TREE_TYPE (decl));
- decl = void_type_node;
- }
- return decl;
-}
-
-/* TYPE has now been defined. It may, however, have a number of things
- waiting make make it their friend. We resolve these references
- here. */
-void
-embrace_waiting_friends (type)
- tree type;
-{
- tree decl = TYPE_NAME (type);
- tree waiters;
-
- if (TREE_CODE (decl) != TYPE_DECL)
- return;
-
- for (waiters = DECL_WAITING_FRIENDS (decl); waiters;
- waiters = TREE_CHAIN (waiters))
- {
- tree waiter = TREE_PURPOSE (waiters);
-#if 0
- tree waiter_prev = TREE_VALUE (waiters);
-#endif
- tree decl = TREE_TYPE (waiters);
- tree name = decl ? (TREE_CODE (decl) == IDENTIFIER_NODE
- ? decl : DECL_NAME (decl)) : NULL_TREE;
- if (name)
- {
- /* @@ There may be work to be done since we have not verified
- @@ consistency between original and friend declarations
- @@ of the functions waiting to become friends. */
- tree field = lookup_fnfields (TYPE_BINFO (type), name, 0);
- if (field)
- if (decl == name)
- add_friends (waiter, name, type);
- else
- add_friend (waiter, decl);
- else
- error_with_file_and_line (DECL_SOURCE_FILE (TYPE_NAME (waiter)),
- DECL_SOURCE_LINE (TYPE_NAME (waiter)),
- "no method `%s' defined in class `%s' to be friend",
- IDENTIFIER_POINTER (DECL_NAME (TREE_TYPE (waiters))),
- TYPE_NAME_STRING (type));
- }
- else
- make_friend_class (type, waiter);
-
-#if 0
- if (TREE_CHAIN (waiter_prev))
- TREE_CHAIN (waiter_prev) = TREE_CHAIN (TREE_CHAIN (waiter_prev));
- else
- DECL_UNDEFINED_FRIENDS (TYPE_NAME (waiter)) = NULL_TREE;
-#endif
- }
-}
-
/* Common subroutines of build_new and build_vec_delete. */
/* Common interface for calling "builtin" functions that are not
really builtin. */
-tree
+static tree
build_builtin_call (type, node, arglist)
tree type;
tree node;
tree arglist;
{
- tree rval = build (CALL_EXPR, type, node, arglist, 0);
+ tree rval = build (CALL_EXPR, type, node, arglist, NULL_TREE);
TREE_SIDE_EFFECTS (rval) = 1;
assemble_external (TREE_OPERAND (node, 0));
TREE_USED (TREE_OPERAND (node, 0)) = 1;
@@ -2851,11 +1979,9 @@ build_new (placement, decl, init, use_global_new)
tree decl, init;
int use_global_new;
{
- tree type, true_type, size, rval;
- tree nelts;
- tree alloc_expr, alloc_temp;
+ tree type, rval;
+ tree nelts = NULL_TREE, t;
int has_array = 0;
- enum tree_code code = NEW_EXPR;
tree pending_sizes = NULL_TREE;
@@ -2866,7 +1992,7 @@ build_new (placement, decl, init, use_global_new)
{
tree absdcl = TREE_VALUE (decl);
tree last_absdcl = NULL_TREE;
- int old_immediate_size_expand;
+ int old_immediate_size_expand = 0;
if (current_function_decl
&& DECL_CONSTRUCTOR_P (current_function_decl))
@@ -2903,9 +2029,14 @@ build_new (placement, decl, init, use_global_new)
{
if (this_nelts == NULL_TREE)
error ("new of array type fails to specify size");
+ else if (processing_template_decl)
+ {
+ nelts = this_nelts;
+ absdcl = TREE_OPERAND (absdcl, 0);
+ }
else
{
- this_nelts = save_expr (convert (sizetype, this_nelts));
+ this_nelts = save_expr (cp_convert (sizetype, this_nelts));
absdcl = TREE_OPERAND (absdcl, 0);
if (this_nelts == integer_zero_node)
{
@@ -2925,7 +2056,7 @@ build_new (placement, decl, init, use_global_new)
else
TREE_VALUE (decl) = absdcl;
- type = true_type = groktypename (decl);
+ type = groktypename (decl);
if (! type || type == error_mark_node)
{
immediate_size_expand = old_immediate_size_expand;
@@ -2945,7 +2076,7 @@ build_new (placement, decl, init, use_global_new)
{
/* An aggregate type. */
type = IDENTIFIER_TYPE_VALUE (decl);
- decl = TYPE_NAME (type);
+ decl = TYPE_MAIN_DECL (type);
}
else
{
@@ -2954,18 +2085,29 @@ build_new (placement, decl, init, use_global_new)
my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 215);
type = TREE_TYPE (decl);
}
- true_type = type;
}
else if (TREE_CODE (decl) == TYPE_DECL)
{
type = TREE_TYPE (decl);
- true_type = type;
}
else
{
type = decl;
- true_type = type;
- decl = TYPE_NAME (type);
+ decl = TYPE_MAIN_DECL (type);
+ }
+
+ if (processing_template_decl)
+ {
+ if (has_array)
+ t = min_tree_cons (min_tree_cons (NULL_TREE, type, NULL_TREE),
+ build_min_nt (ARRAY_REF, NULL_TREE, nelts),
+ NULL_TREE);
+ else
+ t = type;
+
+ rval = build_min_nt (NEW_EXPR, placement, t, init);
+ NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
+ return rval;
}
/* ``A reference cannot be created by the new operator. A reference
@@ -2974,7 +2116,7 @@ build_new (placement, decl, init, use_global_new)
if (TREE_CODE (type) == REFERENCE_TYPE)
{
error ("new cannot be applied to a reference type");
- type = true_type = TREE_TYPE (type);
+ type = TREE_TYPE (type);
}
if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -2990,9 +2132,58 @@ build_new (placement, decl, init, use_global_new)
{
nelts = array_type_nelts_top (type);
has_array = 1;
- type = true_type = TREE_TYPE (type);
+ type = TREE_TYPE (type);
}
+ if (has_array)
+ t = build_nt (ARRAY_REF, type, nelts);
+ else
+ t = type;
+
+ rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init);
+ NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
+ TREE_SIDE_EFFECTS (rval) = 1;
+
+ /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */
+ rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
+ TREE_NO_UNUSED_WARNING (rval) = 1;
+
+ if (pending_sizes)
+ rval = build_compound_expr (chainon (pending_sizes,
+ build_expr_list (NULL_TREE, rval)));
+
+ return rval;
+}
+
+/* Called from cplus_expand_expr when expanding a NEW_EXPR. The return
+ value is immediately handed to expand_expr. */
+
+tree
+build_new_1 (exp)
+ tree exp;
+{
+ tree placement, init;
+ tree type, true_type, size, rval;
+ tree nelts = NULL_TREE;
+ tree alloc_expr, alloc_node = NULL_TREE;
+ int has_array = 0;
+ enum tree_code code = NEW_EXPR;
+ int use_cookie, nothrow, check_new;
+ int use_global_new;
+
+ placement = TREE_OPERAND (exp, 0);
+ type = TREE_OPERAND (exp, 1);
+ init = TREE_OPERAND (exp, 2);
+ use_global_new = NEW_EXPR_USE_GLOBAL (exp);
+
+ if (TREE_CODE (type) == ARRAY_REF)
+ {
+ has_array = 1;
+ nelts = TREE_OPERAND (type, 1);
+ type = TREE_OPERAND (type, 0);
+ }
+ true_type = type;
+
if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
type = TYPE_MAIN_VARIANT (type);
@@ -3004,24 +2195,22 @@ build_new (placement, decl, init, use_global_new)
nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
true_type = TREE_TYPE (true_type);
}
+
+ if (!complete_type_or_else (true_type))
+ return error_mark_node;
+
if (has_array)
size = fold (build_binary_op (MULT_EXPR, size_in_bytes (true_type),
nelts, 1));
else
size = size_in_bytes (type);
- if (true_type == void_type_node)
+ if (TREE_CODE (true_type) == VOID_TYPE)
{
error ("invalid type `void' for new");
return error_mark_node;
}
- if (TYPE_SIZE (true_type) == 0)
- {
- incomplete_type_error (0, true_type);
- return error_mark_node;
- }
-
if (TYPE_LANG_SPECIFIC (true_type)
&& CLASSTYPE_ABSTRACT_VIRTUALS (true_type))
{
@@ -3035,9 +2224,22 @@ build_new (placement, decl, init, use_global_new)
return error_mark_node;
}
+#if 1
+ /* Get a little extra space to store a couple of things before the new'ed
+ array, if this isn't the default placement new. */
+
+ use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)
+ && ! (placement && ! TREE_CHAIN (placement)
+ && TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
+#else
/* Get a little extra space to store a couple of things before the new'ed
- array. */
- if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
+ array, if this is either non-placement new or new (nothrow). */
+
+ use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)
+ && (! placement || nothrow));
+#endif
+
+ if (use_cookie)
{
tree extra = BI_header_size;
@@ -3045,21 +2247,17 @@ build_new (placement, decl, init, use_global_new)
}
if (has_array)
- code = VEC_NEW_EXPR;
-
- /* Allocate the object. */
- if (! use_global_new && TYPE_LANG_SPECIFIC (true_type)
- && (TYPE_GETS_NEW (true_type) & (1 << has_array)))
- rval = build_opfncall (code, LOOKUP_NORMAL,
- build_pointer_type (true_type), size, placement);
- else if (placement)
{
- rval = build_opfncall (code, LOOKUP_GLOBAL|LOOKUP_COMPLAIN,
- ptr_type_node, size, placement);
- rval = convert (build_pointer_type (true_type), rval);
+ code = VEC_NEW_EXPR;
+
+ if (init && pedantic)
+ cp_pedwarn ("initialization in array new");
}
- else if (! has_array && flag_this_is_variable > 0
- && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node)
+
+ /* Allocate the object. */
+
+ if (! has_array && ! placement && flag_this_is_variable > 0
+ && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node)
{
if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
rval = NULL_TREE;
@@ -3071,33 +2269,50 @@ build_new (placement, decl, init, use_global_new)
}
else
{
- rval = build_builtin_call (build_pointer_type (true_type),
- has_array ? BIVN : BIN,
- build_tree_list (NULL_TREE, size));
-#if 0
- /* See comment above as to why this is disabled. */
- if (alignment)
- {
- rval = build (PLUS_EXPR, build_pointer_type (true_type), rval,
- alignment);
- rval = build (BIT_AND_EXPR, build_pointer_type (true_type),
- rval, build1 (BIT_NOT_EXPR, integer_type_node,
- alignment));
- }
-#endif
- TREE_CALLS_NEW (rval) = 1;
+ int susp;
+
+ if (flag_exceptions)
+ /* We will use RVAL when generating an exception handler for
+ this new-expression, so we must save it. */
+ susp = suspend_momentary ();
+
+ rval = build_op_new_call
+ (code, true_type, expr_tree_cons (NULL_TREE, size, placement),
+ LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL));
+ rval = cp_convert (build_pointer_type (true_type), rval);
+
+ if (flag_exceptions)
+ resume_momentary (susp);
+ }
+
+ /* unless an allocation function is declared with an empty excep-
+ tion-specification (_except.spec_), throw(), it indicates failure to
+ allocate storage by throwing a bad_alloc exception (clause _except_,
+ _lib.bad.alloc_); it returns a non-null pointer otherwise If the allo-
+ cation function is declared with an empty exception-specification,
+ throw(), it returns null to indicate failure to allocate storage and a
+ non-null pointer otherwise.
+
+ So check for a null exception spec on the op new we just called. */
+
+ nothrow = 0;
+ if (rval)
+ {
+ /* The CALL_EXPR. */
+ tree t = TREE_OPERAND (rval, 0);
+ /* The function. */
+ t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+ t = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (t));
+
+ if (t && TREE_VALUE (t) == NULL_TREE)
+ nothrow = 1;
}
+ check_new = flag_check_new || nothrow;
- if (flag_check_new && rval)
+ if ((check_new || flag_exceptions) && rval)
{
- /* For array new, we need to make sure that the call to new is
- not expanded as part of the RTL_EXPR for the initialization,
- so we can't just use save_expr here. */
-
- alloc_temp = get_temp_name (TREE_TYPE (rval), 0);
- alloc_expr = build (MODIFY_EXPR, TREE_TYPE (rval), alloc_temp, rval);
- TREE_SIDE_EFFECTS (alloc_expr) = 1;
- rval = alloc_temp;
+ alloc_expr = get_target_expr (rval);
+ alloc_node = rval = TREE_OPERAND (alloc_expr, 0);
}
else
alloc_expr = NULL_TREE;
@@ -3106,25 +2321,25 @@ build_new (placement, decl, init, use_global_new)
sure we have some extra bytes in that case for the BI_header_size
cookies? And how does that interact with the code below? (mrs) */
/* Finish up some magic for new'ed arrays */
- if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type) && rval != NULL_TREE)
+ if (use_cookie && rval != NULL_TREE)
{
tree extra = BI_header_size;
tree cookie, exp1;
- rval = convert (ptr_type_node, rval); /* convert to void * first */
- rval = convert (string_type_node, rval); /* lets not add void* and ints */
+ rval = convert (string_type_node, rval); /* for ptr arithmetic */
rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra, 1));
/* Store header info. */
- cookie = build_indirect_ref (build (MINUS_EXPR, build_pointer_type (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),
+ build_component_ref (cookie, nc_nelts_field_id,
+ NULL_TREE, 0),
nelts);
TREE_SIDE_EFFECTS (exp1) = 1;
- rval = convert (build_pointer_type (true_type), rval);
- TREE_CALLS_NEW (rval) = 1;
- TREE_SIDE_EFFECTS (rval) = 1;
- rval = build_compound_expr (tree_cons (NULL_TREE, exp1,
- build_tree_list (NULL_TREE, rval)));
+ rval = cp_convert (build_pointer_type (true_type), rval);
+ rval = build_compound_expr
+ (expr_tree_cons (NULL_TREE, exp1,
+ build_expr_list (NULL_TREE, rval)));
}
if (rval == error_mark_node)
@@ -3163,7 +2378,6 @@ build_new (placement, decl, init, use_global_new)
rval);
TREE_NO_UNUSED_WARNING (rval) = 1;
TREE_SIDE_EFFECTS (rval) = 1;
- TREE_CALLS_NEW (rval) = 1;
}
else if (! has_array)
{
@@ -3175,7 +2389,7 @@ build_new (placement, decl, init, use_global_new)
if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
{
- init = tree_cons (NULL_TREE, integer_one_node, init);
+ init = expr_tree_cons (NULL_TREE, integer_one_node, init);
flags |= LOOKUP_HAS_IN_CHARGE;
}
@@ -3184,96 +2398,90 @@ build_new (placement, decl, init, use_global_new)
if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE)
newrval = build_indirect_ref (newrval, NULL_PTR);
- newrval = build_method_call (newrval, constructor_name_full (true_type),
- init, NULL_TREE, flags);
+ newrval = build_method_call (newrval, ctor_identifier,
+ init, TYPE_BINFO (true_type), flags);
- if (newrval)
- {
- rval = newrval;
- TREE_HAS_CONSTRUCTOR (rval) = 1;
- }
- else
- rval = error_mark_node;
- }
- else if (current_function_decl == NULL_TREE)
- {
- extern tree static_aggregates;
+ if (newrval == NULL_TREE || newrval == error_mark_node)
+ return error_mark_node;
- /* In case of static initialization, SAVE_EXPR is good enough. */
- rval = save_expr (rval);
- 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);
+ rval = newrval;
+ TREE_HAS_CONSTRUCTOR (rval) = 1;
}
else
+ rval = build (VEC_INIT_EXPR, TREE_TYPE (rval),
+ save_expr (rval), init, nelts);
+
+ /* If any part of the object initialization terminates by throwing
+ an exception and the new-expression does not contain a
+ new-placement, then the deallocation function is called to free
+ the memory in which the object was being constructed. */
+ if (flag_exceptions && alloc_expr)
{
- /* Have to wrap this in RTL_EXPR for two cases:
- in base or member initialization and if we
- are a branch of a ?: operator. Since we
- can't easily know the latter, just do it always. */
- tree xval = make_node (RTL_EXPR);
-
- /* If we want to check the value of the allocation expression,
- and the number of elements in the array is not a constant, we
- *must* expand the SAVE_EXPR for nelts in alloc_expr before we
- expand it in the actual initialization. So we need to build up
- an RTL_EXPR for alloc_expr. Sigh. */
- if (alloc_expr && ! TREE_CONSTANT (nelts))
+ enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
+ tree cleanup, fn = NULL_TREE;
+ int flags = LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL);
+
+ /* All cleanups must last longer than normal. */
+ int yes = suspend_momentary ();
+
+ if (placement)
{
- tree xval = make_node (RTL_EXPR);
- rtx rtxval;
- TREE_TYPE (xval) = TREE_TYPE (alloc_expr);
- do_pending_stack_adjust ();
- start_sequence_for_rtl_expr (xval);
- emit_note (0, -1);
- rtxval = expand_expr (alloc_expr, NULL, VOIDmode, 0);
- do_pending_stack_adjust ();
- TREE_SIDE_EFFECTS (xval) = 1;
- RTL_EXPR_SEQUENCE (xval) = get_insns ();
- end_sequence ();
- RTL_EXPR_RTL (xval) = rtxval;
- TREE_TYPE (xval) = TREE_TYPE (alloc_expr);
- alloc_expr = xval;
- }
+ flags |= LOOKUP_SPECULATIVELY;
- TREE_TYPE (xval) = TREE_TYPE (rval);
- do_pending_stack_adjust ();
- start_sequence_for_rtl_expr (xval);
+ /* We expect alloc_expr to look like a TARGET_EXPR around
+ a NOP_EXPR around the CALL_EXPR we want. */
+ fn = TREE_OPERAND (alloc_expr, 1);
+ fn = TREE_OPERAND (fn, 0);
+ }
- /* As a matter of principle, `start_sequence' should do this. */
- emit_note (0, -1);
+ /* Copy size to the saveable obstack. */
+ size = copy_node (size);
- rval = save_expr (rval);
- rval = expand_vec_init (decl, rval,
- build_binary_op (MINUS_EXPR, nelts,
- integer_one_node, 1),
- init, 0);
+ cleanup = build_op_delete_call (dcode, alloc_node, size, flags, fn);
- do_pending_stack_adjust ();
+ resume_momentary (yes);
- TREE_SIDE_EFFECTS (xval) = 1;
- TREE_CALLS_NEW (xval) = 1;
- RTL_EXPR_SEQUENCE (xval) = get_insns ();
- end_sequence ();
+ /* Ack! First we allocate the memory. Then we set our sentry
+ variable to true, and expand a cleanup that deletes the memory
+ if sentry is true. Then we run the constructor and store the
+ returned pointer in buf. Then we clear sentry and return buf. */
- if (TREE_CODE (rval) == SAVE_EXPR)
- {
- /* Errors may cause this to not get evaluated. */
- if (SAVE_EXPR_RTL (rval) == 0)
- SAVE_EXPR_RTL (rval) = const0_rtx;
- RTL_EXPR_RTL (xval) = SAVE_EXPR_RTL (rval);
- }
- else
+ if (cleanup)
{
- my_friendly_assert (TREE_CODE (rval) == VAR_DECL, 217);
- RTL_EXPR_RTL (xval) = DECL_RTL (rval);
+#if 0
+ /* Disable this until flow is fixed so that it doesn't
+ think the initialization of sentry is a dead write. */
+ tree end, sentry, begin, buf, t = TREE_TYPE (rval);
+
+ begin = get_target_expr (boolean_true_node);
+ sentry = TREE_OPERAND (begin, 0);
+
+ yes = suspend_momentary ();
+ TREE_OPERAND (begin, 2)
+ = build (COND_EXPR, void_type_node, sentry,
+ cleanup, void_zero_node);
+ resume_momentary (yes);
+
+ rval = get_target_expr (rval);
+
+ end = build (MODIFY_EXPR, TREE_TYPE (sentry),
+ sentry, boolean_false_node);
+ TREE_SIDE_EFFECTS (end) = 1;
+
+ buf = TREE_OPERAND (rval, 0);
+
+ rval = build (COMPOUND_EXPR, t, begin,
+ build (COMPOUND_EXPR, t, rval,
+ build (COMPOUND_EXPR, t, end, buf)));
+#else
+ /* FIXME: this is a workaround for a crash due to overlapping
+ exception regions. Cleanups shouldn't really happen here. */
+ rval = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (rval), rval);
+
+ rval = build (TRY_CATCH_EXPR, TREE_TYPE (rval), rval, cleanup);
+ rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
+#endif
}
- rval = xval;
}
}
else if (TYPE_READONLY (true_type))
@@ -3281,45 +2489,27 @@ build_new (placement, decl, init, use_global_new)
done:
- if (alloc_expr)
+ if (alloc_expr && rval == alloc_node)
{
- /* Did we modify the storage? */
- if (rval != alloc_temp)
- {
- tree ifexp = build_binary_op (NE_EXPR, alloc_expr,
- integer_zero_node, 1);
- rval = build_conditional_expr (ifexp, rval, alloc_temp);
- }
- else
- rval = alloc_expr;
+ rval = TREE_OPERAND (alloc_expr, 1);
+ alloc_expr = NULL_TREE;
}
- if (rval && TREE_TYPE (rval) != build_pointer_type (type))
+ if (check_new && alloc_expr)
{
- /* The type of new int [3][3] is not int *, but int [3] * */
- rval = build_c_cast (build_pointer_type (type), rval, 0);
+ /* Did we modify the storage? */
+ tree ifexp = build_binary_op (NE_EXPR, alloc_node,
+ integer_zero_node, 1);
+ rval = build_conditional_expr (ifexp, rval, alloc_node);
}
- if (pending_sizes)
- rval = build_compound_expr (chainon (pending_sizes,
- build_tree_list (NULL_TREE, rval)));
+ if (alloc_expr)
+ rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
- if (flag_gc)
+ if (rval && TREE_TYPE (rval) != build_pointer_type (type))
{
- extern tree gc_visible;
- tree objbits;
- tree update_expr;
-
- rval = save_expr (rval);
- /* We don't need a `headof' operation to do this because
- we know where the object starts. */
- objbits = build1 (INDIRECT_REF, unsigned_type_node,
- build (MINUS_EXPR, ptr_type_node,
- rval, c_sizeof_nowarn (unsigned_type_node)));
- update_expr = build_modify_expr (objbits, BIT_IOR_EXPR, gc_visible);
- rval = build_compound_expr (tree_cons (NULL_TREE, rval,
- tree_cons (NULL_TREE, update_expr,
- build_tree_list (NULL_TREE, rval))));
+ /* The type of new int [3][3] is not int *, but int [3] * */
+ rval = build_c_cast (build_pointer_type (type), rval);
}
return rval;
@@ -3333,7 +2523,7 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
int use_global_delete;
{
tree virtual_size;
- tree ptype = build_pointer_type (type);
+ tree ptype = build_pointer_type (type = complete_type (type));
tree size_exp = size_in_bytes (type);
/* Temporary variables used by the loop. */
@@ -3355,9 +2545,6 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
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;
@@ -3373,22 +2560,20 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
base,
virtual_size)));
DECL_REGISTER (tbase) = 1;
- controller = build (BIND_EXPR, void_type_node, tbase, 0, 0);
+ controller = build (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE);
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));
+ tree base_tbd = cp_convert (ptype,
+ build_binary_op (MINUS_EXPR,
+ cp_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,
+ body = build_expr_list (NULL_TREE,
build_x_delete (ptype, base_tbd,
2 | use_global_delete,
virtual_size));
@@ -3400,24 +2585,24 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
else
body = NULL_TREE;
- body = tree_cons (NULL_TREE,
+ body = expr_tree_cons (NULL_TREE,
build_delete (ptype, tbase, auto_delete,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
body);
- body = tree_cons (NULL_TREE,
+ body = expr_tree_cons (NULL_TREE,
build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)),
body);
- body = tree_cons (NULL_TREE,
+ body = expr_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 = expr_tree_cons (NULL_TREE, tbase_init,
+ expr_tree_cons (NULL_TREE, loop, NULL_TREE));
loop = build_compound_expr (loop);
no_destructor:
@@ -3438,12 +2623,12 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
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. */
+ base_tbd = cp_convert (ptype,
+ build_binary_op (MINUS_EXPR,
+ cp_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,
@@ -3458,8 +2643,8 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
if (loop && deallocate_expr != integer_zero_node)
{
- body = tree_cons (NULL_TREE, loop,
- tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
+ body = expr_tree_cons (NULL_TREE, loop,
+ expr_tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
body = build_compound_expr (body);
}
else
@@ -3477,13 +2662,14 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
return controller;
}
else
- return convert (void_type_node, body);
+ return cp_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;
@@ -3520,7 +2706,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
tree type = TREE_TYPE (TREE_TYPE (base));
tree size;
- maxindex = convert (integer_type_node, maxindex);
+ maxindex = cp_convert (ptrdiff_type_node, maxindex);
if (maxindex == error_mark_node)
return error_mark_node;
@@ -3538,15 +2724,15 @@ 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 (build_pointer_type (type),
- convert (build_pointer_type (type), null_pointer_node));
+ cp_convert (build_pointer_type (type), null_pointer_node));
base = default_conversion (base);
- base = convert (build_pointer_type (type), base);
+ base = cp_convert (build_pointer_type (type), base);
expand_assignment (rval, base, 0, 0);
base = get_temp_regvar (build_pointer_type (type), base);
if (init != NULL_TREE
&& TREE_CODE (init) == CONSTRUCTOR
- && TREE_TYPE (init) == TREE_TYPE (decl))
+ && (! decl || TREE_TYPE (init) == TREE_TYPE (decl)))
{
/* Initialization of array from {...}. */
tree elts = CONSTRUCTOR_ELTS (init);
@@ -3574,7 +2760,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
goto done_init;
}
- iterator = get_temp_regvar (integer_type_node,
+ iterator = get_temp_regvar (ptrdiff_type_node,
build_int_2 (host_i, 0));
init = NULL_TREE;
goto init_by_default;
@@ -3596,9 +2782,10 @@ expand_vec_init (decl, base, maxindex, init, from_array)
{
tree itype;
- iterator = get_temp_regvar (integer_type_node, maxindex);
+ iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
init_by_default:
+ itype = NULL_TREE;
/* If initializing one array from another,
initialize element by element. */
@@ -3629,9 +2816,12 @@ 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_eh_region_start ();
expand_start_loop_continue_elsewhere (1);
+ /* The initialization of each array element is a full-expression. */
+ expand_start_target_temps ();
+
if (from_array)
{
tree to = build1 (INDIRECT_REF, type, base);
@@ -3667,9 +2857,13 @@ expand_vec_init (decl, base, maxindex, init, from_array)
if (base2)
expand_assignment (base2,
build (PLUS_EXPR, build_pointer_type (type), base2, size), 0, 0);
+
+ /* Cleanup any temporaries needed for the initial value. */
+ expand_end_target_temps ();
+
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));
+ build (PREDECREMENT_EXPR, ptrdiff_type_node, iterator, integer_one_node), minus_one));
if (obey_regdecls)
{
@@ -3678,13 +2872,35 @@ 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));
+ if (TYPE_NEEDS_DESTRUCTOR (type) && flag_exceptions)
+ {
+ /* We have to ensure that this can live to the cleanup
+ expansion time, since we know it is only ever needed
+ once, generate code now. */
+ push_obstacks_nochange ();
+ resume_temporary_allocation ();
+ {
+ tree e1, cleanup = make_node (RTL_EXPR);
+ TREE_TYPE (cleanup) = void_type_node;
+ RTL_EXPR_RTL (cleanup) = const0_rtx;
+ TREE_SIDE_EFFECTS (cleanup) = 1;
+ do_pending_stack_adjust ();
+ start_sequence_for_rtl_expr (cleanup);
+
+ e1 = build_array_eh_cleanup
+ (rval,
+ build_binary_op (MINUS_EXPR, maxindex, iterator, 1),
+ type);
+ expand_expr (e1, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ do_pending_stack_adjust ();
+ RTL_EXPR_SEQUENCE (cleanup) = get_insns ();
+ end_sequence ();
+
+ cleanup = protect_with_terminate (cleanup);
+ expand_eh_region_end (cleanup);
+ }
+ pop_obstacks ();
+ }
expand_end_cond ();
if (obey_regdecls)
use_variable (DECL_RTL (iterator));
@@ -3709,6 +2925,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
static object, see Free Store 12.5 ANSI C++ WP.
This does not call any destructors. */
+
tree
build_x_delete (type, addr, which_delete, virtual_size)
tree type, addr;
@@ -3717,16 +2934,10 @@ build_x_delete (type, addr, which_delete, virtual_size)
{
int use_global_delete = which_delete & 1;
int use_vec_delete = !!(which_delete & 2);
- tree rval;
enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR;
+ int flags = LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL);
- if (! use_global_delete && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
- && (TYPE_GETS_DELETE (TREE_TYPE (type)) & (1 << use_vec_delete)))
- rval = build_opfncall (code, LOOKUP_NORMAL, addr, virtual_size, NULL_TREE);
- else
- rval = build_builtin_call (void_type_node, use_vec_delete ? BIVD : BID,
- build_tree_list (NULL_TREE, addr));
- return rval;
+ return build_op_delete_call (code, addr, virtual_size, flags, NULL_TREE);
}
/* Generate a call to a destructor. TYPE is the type to cast ADDR to.
@@ -3740,6 +2951,7 @@ build_x_delete (type, addr, which_delete, virtual_size)
flags. See cp-tree.h for more info.
This function does not delete an object's virtual base classes. */
+
tree
build_delete (type, addr, auto_delete, flags, use_global_delete)
tree type, addr;
@@ -3747,11 +2959,9 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
int flags;
int use_global_delete;
{
- tree function, parms;
tree member;
tree expr;
tree ref;
- int ptr;
if (addr == error_mark_node)
return error_mark_node;
@@ -3766,18 +2976,15 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
if (TREE_CODE (type) == POINTER_TYPE)
{
type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- if (TYPE_SIZE (type) == 0)
- {
- incomplete_type_error (0, type);
- return error_mark_node;
- }
+ if (!complete_type_or_else (type))
+ return error_mark_node;
if (TREE_CODE (type) == ARRAY_TYPE)
goto handle_array;
if (! IS_AGGR_TYPE (type))
{
/* Call the builtin operator delete. */
return build_builtin_call (void_type_node, BID,
- build_tree_list (NULL_TREE, addr));
+ build_expr_list (NULL_TREE, addr));
}
if (TREE_SIDE_EFFECTS (addr))
addr = save_expr (addr);
@@ -3785,7 +2992,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
/* throw away const and volatile on target type of addr */
addr = convert_force (build_pointer_type (type), addr, 0);
ref = build_indirect_ref (addr, NULL_PTR);
- ptr = 1;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
@@ -3798,7 +3004,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
return error_mark_node;
}
return build_vec_delete (addr, array_type_nelts (type),
- c_sizeof_nowarn (TREE_TYPE (type)),
auto_delete, integer_two_node,
use_global_delete);
}
@@ -3816,12 +3021,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
else
addr = convert_force (build_pointer_type (type), addr, 0);
- if (TREE_CODE (addr) == NOP_EXPR
- && TREE_OPERAND (addr, 0) == current_class_decl)
- ref = C_C_D;
- else
- ref = build_indirect_ref (addr, NULL_PTR);
- ptr = 0;
+ ref = build_indirect_ref (addr, NULL_PTR);
}
my_friendly_assert (IS_AGGR_TYPE (type), 220);
@@ -3831,37 +3031,27 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
if (auto_delete == integer_zero_node)
return void_zero_node;
- /* Pass the size of the object down to the operator delete() in
- addition to the ADDR. */
- if (TYPE_GETS_REG_DELETE (type) && !use_global_delete)
- {
- tree virtual_size = c_sizeof_nowarn (type);
- return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr,
- virtual_size, NULL_TREE);
- }
-
- /* Call the builtin operator delete. */
- return build_builtin_call (void_type_node, BID,
- build_tree_list (NULL_TREE, addr));
+ return build_op_delete_call
+ (DELETE_EXPR, addr, c_sizeof_nowarn (type),
+ LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL),
+ NULL_TREE);
}
- parms = build_tree_list (NULL_TREE, addr);
/* Below, we will reverse the order in which these calls are made.
If we have a destructor, then that destructor will take care
of the base classes; otherwise, we must do that here. */
if (TYPE_HAS_DESTRUCTOR (type))
{
- tree dtor = DECL_MAIN_VARIANT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0));
- tree basetypes = TYPE_BINFO (type);
tree passed_auto_delete;
tree do_delete = NULL_TREE;
+ tree ifexp;
if (use_global_delete)
{
tree cond = fold (build (BIT_AND_EXPR, integer_type_node,
auto_delete, integer_one_node));
tree call = build_builtin_call
- (void_type_node, BID, build_tree_list (NULL_TREE, addr));
+ (void_type_node, BID, build_expr_list (NULL_TREE, addr));
cond = fold (build (COND_EXPR, void_type_node, cond,
call, void_zero_node));
@@ -3874,106 +3064,29 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
else
passed_auto_delete = auto_delete;
- if (flags & LOOKUP_PROTECT)
- {
- enum access_type access = compute_access (basetypes, dtor);
-
- if (access == access_private)
- {
- if (flags & LOOKUP_COMPLAIN)
- cp_error ("destructor for type `%T' is private in this scope", type);
- return error_mark_node;
- }
- else if (access == access_protected)
- {
- if (flags & LOOKUP_COMPLAIN)
- cp_error ("destructor for type `%T' is protected in this scope", type);
- return error_mark_node;
- }
- }
+ expr = build_method_call
+ (ref, dtor_identifier, build_expr_list (NULL_TREE, passed_auto_delete),
+ NULL_TREE, flags);
- /* Once we are in a destructor, try not going through
- the virtual function table to find the next destructor. */
- if (DECL_VINDEX (dtor)
- && ! (flags & LOOKUP_NONVIRTUAL)
- && TREE_CODE (auto_delete) != PARM_DECL
- && (ptr == 1 || ! resolves_to_fixed_type_p (ref, 0)))
- {
- tree binfo, basetype;
- /* The code below is probably all broken. See call.c for the
- complete right way to do this. this offsets may not be right
- in the below. (mrs) */
- /* This destructor must be called via virtual function table. */
- dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (DECL_CONTEXT (dtor)), 0);
- basetype = DECL_CLASS_CONTEXT (dtor);
- binfo = get_binfo (basetype,
- TREE_TYPE (TREE_TYPE (TREE_VALUE (parms))),
- 0);
- expr = convert_pointer_to_real (binfo, TREE_VALUE (parms));
- if (expr != TREE_VALUE (parms))
- {
- expr = fold (expr);
- ref = build_indirect_ref (expr, NULL_PTR);
- TREE_VALUE (parms) = expr;
- }
- function = build_vfn_ref (&TREE_VALUE (parms), ref, DECL_VINDEX (dtor));
- if (function == error_mark_node)
- return error_mark_node;
- TREE_TYPE (function) = build_pointer_type (TREE_TYPE (dtor));
- TREE_CHAIN (parms) = build_tree_list (NULL_TREE, passed_auto_delete);
- expr = build_function_call (function, parms);
- if (do_delete)
- expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
- if (ptr && (flags & LOOKUP_DESTRUCTOR) == 0)
- {
- /* Handle the case where a virtual destructor is
- being called on an item that is 0.
+ if (do_delete)
+ expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
- @@ Does this really need to be done? */
- tree ifexp = build_binary_op(NE_EXPR, addr, integer_zero_node,1);
-#if 0
- if (TREE_CODE (ref) == VAR_DECL
- || TREE_CODE (ref) == COMPONENT_REF)
- warning ("losing in build_delete");
-#endif
- expr = build (COND_EXPR, void_type_node,
- ifexp, expr, void_zero_node);
- }
- }
+ if (flags & LOOKUP_DESTRUCTOR)
+ /* Explicit destructor call; don't check for null pointer. */
+ ifexp = integer_one_node;
else
- {
- tree ifexp;
-
- if ((flags & LOOKUP_DESTRUCTOR)
- || TREE_CODE (ref) == VAR_DECL
- || TREE_CODE (ref) == PARM_DECL
- || TREE_CODE (ref) == COMPONENT_REF
- || TREE_CODE (ref) == ARRAY_REF)
- /* These can't be 0. */
- ifexp = integer_one_node;
- else
- /* Handle the case where a non-virtual destructor is
- being called on an item that is 0. */
- ifexp = build_binary_op (NE_EXPR, addr, integer_zero_node, 1);
-
- /* Used to mean that this destructor was known to be empty,
- but that's now obsolete. */
- my_friendly_assert (DECL_INITIAL (dtor) != void_type_node, 221);
-
- TREE_CHAIN (parms) = build_tree_list (NULL_TREE, passed_auto_delete);
- expr = build_function_call (dtor, parms);
- if (do_delete)
- expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
-
- if (ifexp != integer_one_node)
- expr = build (COND_EXPR, void_type_node,
- ifexp, expr, void_zero_node);
- }
+ /* Handle deleting a null pointer. */
+ ifexp = fold (build_binary_op (NE_EXPR, addr, integer_zero_node, 1));
+
+ if (ifexp != integer_one_node)
+ expr = build (COND_EXPR, void_type_node,
+ ifexp, expr, void_zero_node);
+
return expr;
}
else
{
- /* This can get visibilities wrong. */
+ /* We only get here from finish_function for a destructor. */
tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE;
@@ -3981,57 +3094,24 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
tree parent_auto_delete = auto_delete;
tree cond;
- /* If this type does not have a destructor, but does have
- operator delete, call the parent parent destructor (if any),
- but let this node do the deleting. Otherwise, it is ok
- to let the parent destructor do the deleting. */
- if (TYPE_GETS_REG_DELETE (type) && !use_global_delete)
- {
- parent_auto_delete = integer_zero_node;
- if (auto_delete == integer_zero_node)
- cond = NULL_TREE;
- else
- {
- tree virtual_size;
-
- /* This is probably wrong. It should be the size of the
- virtual object being deleted. */
- virtual_size = c_sizeof_nowarn (type);
-
- expr = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr,
- virtual_size, NULL_TREE);
- if (expr == error_mark_node)
- return error_mark_node;
- if (auto_delete != integer_one_node)
- cond = build (COND_EXPR, void_type_node,
- build (BIT_AND_EXPR, integer_type_node,
- auto_delete, integer_one_node),
- expr, void_zero_node);
- else
- cond = expr;
- }
- }
+ /* If we have member delete or vbases, we call delete in
+ finish_function. */
+ if (auto_delete == integer_zero_node)
+ cond = NULL_TREE;
else if (base_binfo == NULL_TREE
- || (TREE_VIA_VIRTUAL (base_binfo) == 0
- && ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))))
+ || ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
{
- tree virtual_size;
-
- /* This is probably wrong. It should be the size of the virtual
- object being deleted. */
- virtual_size = c_sizeof_nowarn (type);
-
cond = build (COND_EXPR, void_type_node,
build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node),
build_builtin_call (void_type_node, BID,
- build_tree_list (NULL_TREE, addr)),
+ build_expr_list (NULL_TREE, addr)),
void_zero_node);
}
else
cond = NULL_TREE;
if (cond)
- exprstmt = build_tree_list (NULL_TREE, cond);
+ exprstmt = build_expr_list (NULL_TREE, cond);
if (base_binfo
&& ! TREE_VIA_VIRTUAL (base_binfo)
@@ -4044,9 +3124,10 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
else
this_auto_delete = integer_zero_node;
- expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), addr,
- this_auto_delete, flags, 0);
- exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
+ expr = build_scoped_method_call
+ (ref, base_binfo, dtor_identifier,
+ build_expr_list (NULL_TREE, this_auto_delete));
+ exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
}
/* Take care of the remaining baseclasses. */
@@ -4057,15 +3138,11 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
|| TREE_VIA_VIRTUAL (base_binfo))
continue;
- /* May be zero offset if other baseclasses are virtual. */
- expr = fold (build (PLUS_EXPR, build_pointer_type (BINFO_TYPE (base_binfo)),
- addr, BINFO_OFFSET (base_binfo)));
+ expr = build_scoped_method_call
+ (ref, base_binfo, dtor_identifier,
+ build_expr_list (NULL_TREE, integer_zero_node));
- expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), expr,
- integer_zero_node,
- flags, 0);
-
- exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
+ exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
}
for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member))
@@ -4074,10 +3151,10 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
continue;
if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (member)))
{
- tree this_member = build_component_ref (ref, DECL_NAME (member), 0, 0);
+ tree this_member = build_component_ref (ref, DECL_NAME (member), NULL_TREE, 0);
tree this_type = TREE_TYPE (member);
expr = build_delete (this_type, this_member, integer_two_node, flags, 0);
- exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
+ exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
}
}
@@ -4104,7 +3181,7 @@ build_vbase_delete (type, decl)
{
tree this_addr = convert_force (build_pointer_type (BINFO_TYPE (vbases)),
addr, 0);
- result = tree_cons (NULL_TREE,
+ result = expr_tree_cons (NULL_TREE,
build_delete (TREE_TYPE (this_addr), this_addr,
integer_zero_node,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0),
@@ -4130,10 +3207,11 @@ build_vbase_delete (type, decl)
values we'd have to extract. (We could use MAXINDEX with pointers to
confirm the size, and trap if the numbers differ; not clear that it'd
be worth bothering.) */
+
tree
-build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
+build_vec_delete (base, maxindex, auto_delete_vec, auto_delete,
use_global_delete)
- tree base, maxindex, elt_size;
+ tree base, maxindex;
tree auto_delete_vec, auto_delete;
int use_global_delete;
{
@@ -4146,7 +3224,7 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
base = stabilize_reference (base);
- /* Since we can use base many times, save_expr it. */
+ /* Since we can use base many times, save_expr it. */
if (TREE_SIDE_EFFECTS (base))
base = save_expr (base);
@@ -4156,7 +3234,7 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
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);
+ maxindex = build_component_ref (cookie, nc_nelts_field_id, NULL_TREE, 0);
do
type = TREE_TYPE (type);
while (TREE_CODE (type) == ARRAY_TYPE);
@@ -4171,7 +3249,8 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
}
else
{
- error ("type to vector delete is neither pointer or array type");
+ if (base != error_mark_node)
+ error ("type to vector delete is neither pointer or array type");
return error_mark_node;
}
diff --git a/contrib/gcc/cp/input.c b/contrib/gcc/cp/input.c
index 77a6468..5a73fea 100644
--- a/contrib/gcc/cp/input.c
+++ b/contrib/gcc/cp/input.c
@@ -29,22 +29,16 @@ Boston, MA 02111-1307, USA. */
lex.c for very minor efficiency gains (primarily in function
inlining). */
-#include <stdio.h>
-#include "obstack.h"
+#include "system.h"
extern FILE *finput;
-struct pending_input *save_pending_input ();
-void restore_pending_input ();
-
struct input_source {
/* saved string */
char *str;
int length;
/* current position, when reading as input */
int offset;
- /* obstack to free this input string from when finished, if any */
- struct obstack *obstack;
/* linked list maintenance */
struct input_source *next;
/* values to restore after reading all of current string */
@@ -65,6 +59,25 @@ extern int lineno;
#define inline
#endif
+#if USE_CPPLIB
+extern unsigned char *yy_cur, *yy_lim;
+extern int yy_get_token ();
+#define GETC() (yy_cur < yy_lim ? *yy_cur++ : yy_get_token ())
+#else
+#define GETC() getc (finput)
+#endif
+
+extern void feed_input PROTO((char *, int));
+extern void put_input PROTO((int));
+extern void put_back PROTO((int));
+extern int getch PROTO((void));
+extern int input_redirected PROTO((void));
+
+static inline struct input_source * allocate_input PROTO((void));
+static inline void free_input PROTO((struct input_source *));
+static inline void end_input PROTO((void));
+static inline int sub_getch PROTO((void));
+
static inline struct input_source *
allocate_input ()
{
@@ -78,7 +91,6 @@ allocate_input ()
}
inp = (struct input_source *) xmalloc (sizeof (struct input_source));
inp->next = 0;
- inp->obstack = 0;
return inp;
}
@@ -86,9 +98,6 @@ static inline void
free_input (inp)
struct input_source *inp;
{
- if (inp->obstack)
- obstack_free (inp->obstack, inp->str);
- inp->obstack = 0;
inp->str = 0;
inp->length = 0;
inp->next = free_inputs;
@@ -102,10 +111,9 @@ static int putback_char = -1;
inline
void
-feed_input (str, len, delete)
+feed_input (str, len)
char *str;
int len;
- struct obstack *delete;
{
struct input_source *inp = allocate_input ();
@@ -115,7 +123,6 @@ feed_input (str, len, delete)
inp->str = str;
inp->length = len;
- inp->obstack = delete;
inp->offset = 0;
inp->next = input;
inp->filename = input_filename;
@@ -129,6 +136,22 @@ feed_input (str, len, delete)
struct pending_input *to_be_restored; /* XXX */
extern int end_of_file;
+static inline void
+end_input ()
+{
+ struct input_source *inp = input;
+
+ end_of_file = 0;
+ input = inp->next;
+ input_filename = inp->filename;
+ lineno = inp->lineno;
+ /* Get interface/implementation back in sync. */
+ extract_interface_info ();
+ putback_char = inp->putback_char;
+ restore_pending_input (inp->input);
+ free_input (inp);
+}
+
static inline int
sub_getch ()
{
@@ -140,32 +163,20 @@ sub_getch ()
}
if (input)
{
- if (input->offset == input->length)
+ if (input->offset >= input->length)
{
- struct input_source *inp = input;
my_friendly_assert (putback_char == -1, 223);
- to_be_restored = inp->input;
- input->offset++;
- return EOF;
- }
- else if (input->offset > input->length)
- {
- struct input_source *inp = input;
-
- end_of_file = 0;
- input = inp->next;
- input_filename = inp->filename;
- lineno = inp->lineno;
- /* Get interface/implementation back in sync. */
- extract_interface_info ();
- putback_char = inp->putback_char;
- free_input (inp);
+ ++(input->offset);
+ if (input->offset - input->length < 64)
+ return EOF;
+
+ /* We must be stuck in an error-handling rule; give up. */
+ end_input ();
return getch ();
}
- if (input)
- return input->str[input->offset++];
+ return (unsigned char)input->str[input->offset++];
}
- return getc (finput);
+ return GETC ();
}
inline
diff --git a/contrib/gcc/cp/lang-options.h b/contrib/gcc/cp/lang-options.h
index d551357..5c50332 100644
--- a/contrib/gcc/cp/lang-options.h
+++ b/contrib/gcc/cp/lang-options.h
@@ -18,90 +18,106 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+DEFINE_LANG_NAME ("C++")
+
/* This is the contribution to the `lang_options' array in gcc.c for
g++. */
- "-+e0", /* gcc.c tacks the `-' on the front. */
- "-+e1",
- "-+e2",
- "-faccess-control",
- "-fno-access-control",
- "-fall-virtual",
- "-fno-all-virtual",
- "-falt-external-templates",
- "-fno-alt-external-templates",
- "-fansi-overloading",
- "-fno-ansi-overloading",
- "-fcadillac",
- "-fno-cadillac",
- "-fcheck-new",
- "-fno-check-new",
- "-fconserve-space",
- "-fno-conserve-space",
- "-fdefault-inline",
- "-fno-default-inline",
- "-frtti",
- "-fno-rtti",
- "-felide-constructors",
- "-fno-elide-constructors",
- "-fenum-int-equiv",
- "-fno-enum-int-equiv",
- "-fexternal-templates",
- "-fno-external-templates",
- "-ffor-scope",
- "-fno-for-scope",
- "-fgc",
- "-fno-gc",
- "-fgnu-keywords",
- "-fno-gnu-keywords",
- "-fhandle-exceptions",
- "-fno-handle-exceptions",
- "-fhandle-signatures",
- "-fno-handle-signatures",
- "-fhuge-objects",
- "-fno-huge-objects",
- "-fimplement-inlines",
- "-fno-implement-inlines",
- "-fimplicit-templates",
- "-fno-implicit-templates",
- "-flabels-ok",
- "-fno-labels-ok",
- "-fmemoize-lookups",
- "-fno-memoize-lookups",
- "-fnonnull-objects",
- "-fno-nonnull-objects",
- "-foperator-names",
- "-fno-operator-names",
- "-frepo",
- "-fno-repo",
- "-fsave-memoized",
- "-fno-save-memoized",
- "-fshort-temps",
- "-fno-short-temps",
- "-fstats",
- "-fno-stats",
- "-fstrict-prototype",
- "-fno-strict-prototype",
- "-fthis-is-variable",
- "-fno-this-is-variable",
- "-fvtable-thunks",
- "-fno-vtable-thunks",
- "-fxref",
- "-fno-xref",
+ { "-+e0", "" }, /* gcc.c tacks the `-' on the front. */
+ { "-+e1", "" },
+ { "-+e2", "" },
+ { "-faccess-control", "" },
+ { "-fno-access-control", "Do not obey access control semantics" },
+ { "-fall-virtual", "Make all member functions virtual" },
+ { "-fno-all-virtual", "" },
+ { "-falt-external-templates", "Change when template instances are emitted" },
+ { "-fno-alt-external-templates", "" },
+ { "-fansi-overloading", "" },
+ { "-fno-ansi-overloading", "" },
+ { "-fcheck-new", "Check the return value of new" },
+ { "-fno-check-new", "" },
+ { "-fconserve-space", "Reduce size of object files" },
+ { "-fno-conserve-space", "" },
+ { "-fdefault-inline", "" },
+ { "-fno-default-inline", "Do not inline mmeber functions be default"},
+ { "-frtti", "" },
+ { "-fno-rtti", "Do not generate run time type descriptor information" },
+ { "-felide-constructors", "" },
+ { "-fno-elide-constructors", "" },
+ { "-fenum-int-equiv", "" },
+ { "-fno-enum-int-equiv", "" },
+ { "-fexternal-templates", "" },
+ { "-fno-external-templates", "" },
+ { "-ffor-scope", "" },
+ { "-fno-for-scope", "Scope of for-init-statement vars extends outside" },
+ { "-fguiding-decls", "Implement guiding declarations" },
+ { "-fno-guiding-decls", "" },
+ { "-fgnu-keywords", "" },
+ { "-fno-gnu-keywords", "Do not recognise GNU defined keywords" },
+ { "-fhandle-exceptions", "Enable exception handling" },
+ { "-fno-handle-exceptions", "" },
+ { "-fhandle-signatures", "Handle signature language constructs" },
+ { "-fno-handle-signatures", "" },
+ { "-fhonor-std", "Do not ignore the namespace standard" },
+ { "-fno-honor-std", "" },
+ { "-fhuge-objects", "Enable support for huge objects" },
+ { "-fno-huge-objects", "" },
+ { "-fimplement-inlines", "" },
+ { "-fno-implement-inlines", "Export functions even if they can be inlined" },
+ { "-fimplicit-templates", "Emit implicit instatiations if needed" },
+ { "-fno-implicit-templates", "" },
+ { "-flabels-ok", "Labels can be used as first class objects" },
+ { "-fno-labels-ok", "" },
+ { "-fmemoize-lookups", "Enable caching of member function resolutions" },
+ { "-fno-memoize-lookups", "" },
+ { "-fname-mangling-version-", "Set the version of name mangling to use" },
+ { "-fnew-abi", "Enable experimental ABI changes" },
+ { "-fno-new-abi", "" },
+ { "-fnonnull-objects", "" },
+ { "-fno-nonnull-objects", "Do not assume that a reference is always valid" },
+ { "-foperator-names", "Recognise and/bitand/bitor/compl/not/or/xor" },
+ { "-fno-operator-names", "" },
+ { "-foptional-diags", "" },
+ { "-fno-optional-diags", "Disable optional diagnostics" },
+ { "-frepo", "Enable automatic template instantiation" },
+ { "-fno-repo", "" },
+ { "-fsave-memoized", "Save cache of member function resolutions" },
+ { "-fno-save-memoized", "" },
+ { "-fsquangle", "Enable squashed name mangling" },
+ { "-fno-squangle", "" },
+ { "-fstats", "Display statistics accumulated during compilation" },
+ { "-fno-stats", "" },
+ { "-fstrict-prototype", "" },
+ { "-fno-strict-prototype", "Do not assume that empty prototype means no args" },
+ { "-ftemplate-depth-", "Specify maximum template instantiation depth"},
+ { "-fthis-is-variable", "Make 'this' not be type '* const'" },
+ { "-fno-this-is-variable", "" },
+ { "-fvtable-thunks", "Implement vtables using thunks" },
+ { "-fno-vtable-thunks", "" },
+ { "-fweak", "Emit common-like symbols as weak symbols" },
+ { "-fno-weak", "" },
+ { "-fxref", "Emit cross referencing information" },
+ { "-fno-xref", "" },
- "-Wreturn-type",
- "-Wno-return-type",
- "-Woverloaded-virtual",
- "-Wno-overloaded-virtual",
- "-Wtemplate-debugging",
- "-Wno-template-debugging",
- "-Wctor-dtor-privacy",
- "-Wno-ctor-dtor-privacy",
- "-Wnon-virtual-dtor",
- "-Wno-non-virtual-dtor",
- "-Wextern-inline",
- "-Wno-extern-inline",
- "-Wreorder",
- "-Wno-reorder",
- "-Wsynth",
- "-Wno-synth",
+ { "-Wreturn-type", "Warn about inconsistent return types" },
+ { "-Wno-return-type", "" },
+ { "-Woverloaded-virtual", "Warn about overloaded virtual function names" },
+ { "-Wno-overloaded-virtual", "" },
+ { "-Wctor-dtor-privacy", "Warn when all ctors/dtors are private" },
+ { "-Wno-ctor-dtor-privacy", "" },
+ { "-Wnon-virtual-dtor", "Warn about non virtual destructors" },
+ { "-Wno-non-virtual-dtor", "" },
+ { "-Wextern-inline", "Warn when a function is declared extern, then inline" },
+ { "-Wno-extern-inline", "" },
+ { "-Wreorder", "Warn when the compiler reorders code" },
+ { "-Wno-reorder", "" },
+ { "-Wsynth", "Warn when synthesis behaviour differs from Cfront" },
+ { "-Wno-synth", "" },
+ { "-Wpmf-conversions", "Warn when type converting pointers to member functions" },
+ { "-Wno-pmf-conversions", "" },
+ { "-Weffc++", "Warn about violations of Effective C++ style rules" },
+ { "-Wno-effc++", "" },
+ { "-Wsign-promo", "Warn when overload promotes from unsigned to signed" },
+ { "-Wno-sign-promo", "" },
+ { "-Wold-style-cast", "Warn if a C style cast is used in a program" },
+ { "-Wno-old-style-cast", "" },
diff --git a/contrib/gcc/cp/lang-specs.h b/contrib/gcc/cp/lang-specs.h
index fbb72c9..b208ca1 100644
--- a/contrib/gcc/cp/lang-specs.h
+++ b/contrib/gcc/cp/lang-specs.h
@@ -21,39 +21,74 @@ Boston, MA 02111-1307, USA. */
/* This is the contribution to the `default_compilers' array in gcc.c for
g++. */
- {".cc", "@c++"},
- {".cxx", "@c++"},
- {".cpp", "@c++"},
- {".c++", "@c++"},
- {".C", "@c++"},
+ {".cc", {"@c++"}},
+ {".cp", {"@c++"}},
+ {".cxx", {"@c++"}},
+ {".cpp", {"@c++"}},
+ {".c++", {"@c++"}},
+ {".C", {"@c++"}},
{"@c++",
- "cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+#if USE_CPPLIB
+ {
+ "%{E|M|MM:cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
%{C:%{!E:%eGNU C++ does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
-undef -D__GNUC__=%v1 -D__GNUG__=%v1 -D__cplusplus -D__GNUC_MINOR__=%v2\
- %{ansi:-trigraphs -$ -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
- %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional} %{trigraphs}\
+ %{ansi:-trigraphs -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
+ %{!fno-exceptions:-D__EXCEPTIONS}\
+ %{fhonor-std:-D__HONOR_STD} %{fnew-abi:-D__HONOR_STD}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}} %{trigraphs}\
+ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
+ %i %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}\n}\
+ %{!E:%{!M:%{!MM:cc1plus %i %1 %2\
+ -lang-c++ %{nostdinc*} %{C} %{A*} %{I*} %{P} %I\
+ -undef -D__GNUC__=%v1 -D__GNUG__=%v1 -D__cplusplus\
+ -D__GNUC_MINOR__=%v2\
+ %{ansi:-trigraphs -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
+ %{!fno-exceptions:-D__EXCEPTIONS}\
+ %{fhonor-std:-D__HONOR_STD} %{fnew-abi:-D__HONOR_STD}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{trigraphs}\
+ %{!Q:-quiet} -dumpbase %b.cc %{d*} %{m*} %{a}\
+ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
+ %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
+ %{v:-version} %{pg:-p} %{p}\
+ %{f*} %{+e*} %{aux-info*}\
+ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
+ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}}|\n\
+ %{!S:as %a %Y\
+ %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
+ %{!pipe:%g.s} %A\n }}}}"}},
+#else /* ! USE_CPPLIB */
+ {"cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ %{C:%{!E:%eGNU C++ does not support -C without using -E}}\
+ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+ -undef -D__GNUC__=%v1 -D__GNUG__=%v1 -D__cplusplus -D__GNUC_MINOR__=%v2\
+ %{ansi:-trigraphs -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
+ %{!fno-exceptions:-D__EXCEPTIONS}\
+ %{fhonor-std:-D__HONOR_STD} %{fnew-abi:-D__HONOR_STD}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}} %{trigraphs}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %{!M:%{!MM:%{!E:%{!pipe:%g.ii}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
- "%{!M:%{!MM:%{!E:cc1plus %{!pipe:%g.ii} %1 %2\
+ "%{!M:%{!MM:%{!E:cc1plus %{!pipe:%g.ii} %1 %2\
%{!Q:-quiet} -dumpbase %b.cc %{d*} %{m*} %{a}\
%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
- %{traditional} %{v:-version} %{pg:-p} %{p}\
+ %{v:-version} %{pg:-p} %{p}\
%{f*} %{+e*} %{aux-info*}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}}|\n\
%{!S:as %a %Y\
%{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"},
- {".ii", "@c++-cpp-output"},
+ %{!pipe:%g.s} %A\n }}}}"}},
+#endif /* ! USE_CPPLIB */
+ {".ii", {"@c++-cpp-output"}},
{"@c++-cpp-output",
- "%{!M:%{!MM:%{!E:cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\
+ {"%{!M:%{!MM:%{!E:cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\
%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
- %{traditional} %{v:-version} %{pg:-p} %{p}\
+ %{v:-version} %{pg:-p} %{p}\
%{f*} %{+e*} %{aux-info*}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
%{!S:as %a %Y\
%{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"},
+ %{!pipe:%g.s} %A\n }}}}"}},
diff --git a/contrib/gcc/cp/lex.c b/contrib/gcc/cp/lex.c
index 9e51883..57639ad 100644
--- a/contrib/gcc/cp/lex.c
+++ b/contrib/gcc/cp/lex.c
@@ -1,5 +1,5 @@
/* Separate lexical analyzer for GNU C++.
- Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -25,64 +25,100 @@ Boston, MA 02111-1307, USA. */
/* Cause the `yydebug' variable to be defined. */
#define YYDEBUG 1
-#include <sys/types.h>
-#include <stdio.h>
-#include <errno.h>
-#include <setjmp.h>
#include "config.h"
+#include "system.h"
+#include <setjmp.h>
#include "input.h"
#include "tree.h"
#include "lex.h"
-#include "parse.h"
#include "cp-tree.h"
+#include "parse.h"
#include "flags.h"
#include "obstack.h"
#include "c-pragma.h"
+#include "toplev.h"
+#include "output.h"
+
+/* MULTIBYTE_CHARS support only works for native compilers.
+ ??? Ideally what we want is to model widechar support after
+ the current floating point support. */
+#ifdef CROSS_COMPILE
+#undef MULTIBYTE_CHARS
+#endif
#ifdef MULTIBYTE_CHARS
-#include <stdlib.h>
#include <locale.h>
#endif
-#ifndef errno
-extern int errno; /* needed for VAX. */
-#endif
-extern jmp_buf toplevel;
-
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-extern struct obstack *expression_obstack, permanent_obstack;
-extern struct obstack *current_obstack, *saveable_obstack;
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
-extern double atof ();
+extern struct obstack permanent_obstack;
+extern struct obstack *current_obstack, *saveable_obstack;
-extern char *get_directive_line (); /* In c-common.c */
+extern void yyprint PROTO((FILE *, int, YYSTYPE));
+extern void compiler_error PROTO((char *, HOST_WIDE_INT,
+ HOST_WIDE_INT));
+
+static tree get_time_identifier PROTO((char *));
+static int check_newline PROTO((void));
+static int skip_white_space PROTO((int));
+static void finish_defarg PROTO((void));
+static int my_get_run_time PROTO((void));
+static int get_last_nonwhite_on_line PROTO((void));
+static int interface_strcmp PROTO((char *));
+static int readescape PROTO((int *));
+static char *extend_token_buffer PROTO((char *));
+static void consume_string PROTO((struct obstack *, int));
+static void set_typedecl_interface_info PROTO((tree, tree));
+static void feed_defarg PROTO((tree, tree));
+static int set_vardecl_interface_info PROTO((tree, tree));
+static void store_pending_inline PROTO((tree, struct pending_inline *));
+static void reinit_parse_for_expr PROTO((struct obstack *));
+static int *init_cpp_parse PROTO((void));
+static int handle_cp_pragma PROTO((char *));
+#ifdef HANDLE_SYSV_PRAGMA
+static int handle_sysv_pragma PROTO((int));
+#endif
+#ifdef GATHER_STATISTICS
+#ifdef REDUCE_LENGTH
+static int reduce_cmp PROTO((int *, int *));
+static int token_cmp PROTO((int *, int *));
+#endif
+#endif
/* Given a file name X, return the nondirectory portion.
Keep in mind that X can be computed more than once. */
-#ifndef FILE_NAME_NONDIRECTORY
-#define FILE_NAME_NONDIRECTORY(X) \
- (rindex (X, '/') != 0 ? rindex (X, '/') + 1 : X)
-#endif
-
-extern char *index ();
-extern char *rindex ();
-
-void extract_interface_info ();
-void yyerror ();
+char *
+file_name_nondirectory (x)
+ char *x;
+{
+ char *tmp = (char *) rindex (x, '/');
+ if (DIR_SEPARATOR != '/' && ! tmp)
+ tmp = (char *) rindex (x, DIR_SEPARATOR);
+ if (tmp)
+ return (char *) (tmp + 1);
+ else
+ return x;
+}
/* This obstack is needed to hold text. It is not safe to use
TOKEN_BUFFER because `check_newline' calls `yylex'. */
struct obstack inline_text_obstack;
-static char *inline_text_firstobj;
-
-/* This obstack is used to hold information about methods to be
- synthesized. It should go away when synthesized methods are handled
- properly (i.e. only when needed). */
-struct obstack synth_obstack;
-static char *synth_firstobj;
+char *inline_text_firstobj;
+#if USE_CPPLIB
+#include "cpplib.h"
+extern cpp_reader parse_in;
+extern cpp_options parse_options;
+extern unsigned char *yy_cur, *yy_lim;
+#else
+FILE *finput;
+#endif
int end_of_file;
/* Pending language change.
@@ -101,7 +137,7 @@ extern struct obstack token_obstack;
#else
extern void put_back (/* int */);
extern int input_redirected ();
-extern void feed_input (/* char *, int, struct obstack * */);
+extern void feed_input (/* char *, int */);
#endif
/* Holds translations from TREE_CODEs to operator name strings,
@@ -132,52 +168,43 @@ tree ridpointers[(int) RID_MAX];
/* We may keep statistics about how long which files took to compile. */
static int header_time, body_time;
-static tree get_time_identifier ();
static tree filename_times;
static tree this_filename_time;
-/* For implementing #pragma unit. */
-tree current_unit_name;
-tree current_unit_language;
-
/* Array for holding counts of the numbers of tokens seen. */
extern int *token_count;
-
-/* Textual definition used for default functions. */
-static void default_copy_constructor_body ();
-static void default_assign_ref_body ();
/* Return something to represent absolute declarators containing a *.
TARGET is the absolute declarator that the * contains.
- TYPE_QUALS is a list of modifiers such as const or volatile
+ CV_QUALIFIERS is a list of modifiers such as const or volatile
to apply to the pointer type, represented as identifiers.
We return an INDIRECT_REF whose "contents" are TARGET
and whose type is the modifier list. */
tree
-make_pointer_declarator (type_quals, target)
- tree type_quals, target;
+make_pointer_declarator (cv_qualifiers, target)
+ tree cv_qualifiers, target;
{
if (target && TREE_CODE (target) == IDENTIFIER_NODE
&& ANON_AGGRNAME_P (target))
error ("type name expected before `*'");
target = build_parse_node (INDIRECT_REF, target);
- TREE_TYPE (target) = type_quals;
+ TREE_TYPE (target) = cv_qualifiers;
return target;
}
/* Return something to represent absolute declarators containing a &.
TARGET is the absolute declarator that the & contains.
- TYPE_QUALS is a list of modifiers such as const or volatile
+ CV_QUALIFIERS is a list of modifiers such as const or volatile
to apply to the reference type, represented as identifiers.
We return an ADDR_EXPR whose "contents" are TARGET
and whose type is the modifier list. */
tree
-make_reference_declarator (type_quals, target)
- tree type_quals, target;
+make_reference_declarator (cv_qualifiers, target)
+ tree cv_qualifiers, target;
{
if (target)
{
@@ -195,9 +222,26 @@ make_reference_declarator (type_quals, target)
error ("type name expected before `&'");
}
target = build_parse_node (ADDR_EXPR, target);
- TREE_TYPE (target) = type_quals;
+ TREE_TYPE (target) = cv_qualifiers;
+ return target;
+}
+
+tree
+make_call_declarator (target, parms, cv_qualifiers, exception_specification)
+ tree target, parms, cv_qualifiers, exception_specification;
+{
+ target = build_parse_node (CALL_EXPR, target, parms, cv_qualifiers);
+ TREE_TYPE (target) = exception_specification;
return target;
}
+
+void
+set_quals_and_spec (call_declarator, cv_qualifiers, exception_specification)
+ tree call_declarator, cv_qualifiers, exception_specification;
+{
+ TREE_OPERAND (call_declarator, 2) = cv_qualifiers;
+ TREE_TYPE (call_declarator) = exception_specification;
+}
/* Build names and nodes for overloaded operators. */
@@ -252,9 +296,6 @@ int interface_unknown; /* whether or not we know this class
/* lexical analyzer */
-/* File used for outputting assembler code. */
-extern FILE *asm_out_file;
-
#ifndef WCHAR_TYPE_SIZE
#ifdef INT_TYPE_SIZE
#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
@@ -272,13 +313,10 @@ char *token_buffer; /* Pointer to token buffer.
#include "hash.h"
-int check_newline ();
/* Nonzero tells yylex to ignore \ in string constants. */
static int ignore_escape_flag = 0;
-static int skip_white_space ();
-
static tree
get_time_identifier (name)
char *name;
@@ -296,7 +334,7 @@ get_time_identifier (name)
end_temporary_allocation ();
IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
- IDENTIFIER_GLOBAL_VALUE (time_identifier) = filename_times;
+ SET_IDENTIFIER_GLOBAL_VALUE (time_identifier, filename_times);
filename_times = time_identifier;
pop_obstacks ();
}
@@ -319,13 +357,13 @@ my_get_run_time ()
/* Table indexed by tree code giving a string containing a character
classifying the tree code. Possibilities are
- t, d, s, c, r, <, 1 and 2. See cp/tree.def for details. */
+ t, d, s, c, r, <, 1 and 2. See cp/cp-tree.def for details. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
-char *cplus_tree_code_type[] = {
- "x",
-#include "tree.def"
+char cplus_tree_code_type[] = {
+ 'x',
+#include "cp-tree.def"
};
#undef DEFTREECODE
@@ -337,7 +375,7 @@ char *cplus_tree_code_type[] = {
int cplus_tree_code_length[] = {
0,
-#include "tree.def"
+#include "cp-tree.def"
};
#undef DEFTREECODE
@@ -347,22 +385,28 @@ int cplus_tree_code_length[] = {
char *cplus_tree_code_name[] = {
"@@dummy",
-#include "tree.def"
+#include "cp-tree.def"
};
#undef DEFTREECODE
/* toplev.c needs to call these. */
void
+lang_init_options ()
+{
+ /* Default exceptions on. */
+ flag_exceptions = 1;
+}
+
+void
lang_init ()
{
+#if ! USE_CPPLIB
/* the beginning of the file is a new line; check for # */
/* With luck, we discover the real source file's name from that
and put it in input_filename. */
put_back (check_newline ());
-
- if (flag_cadillac)
- cadillac_start ();
+#endif
if (flag_gnu_xref) GNU_xref_begin (input_filename);
init_repo (input_filename);
}
@@ -394,23 +438,66 @@ init_filename_times ()
/* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989.
Stuck this hack in to get the files open correctly; this is called
- in place of init_lex if we are an unexec'd binary. */
+ in place of init_parse if we are an unexec'd binary. */
+
+#if 0
void
reinit_lang_specific ()
{
init_filename_times ();
reinit_search_statistics ();
}
+#endif
-void
-init_lex ()
+static int *
+init_cpp_parse ()
+{
+#ifdef GATHER_STATISTICS
+#ifdef REDUCE_LENGTH
+ reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1));
+ bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1));
+ reduce_count += 1;
+ token_count = (int *)malloc (sizeof (int) * (TOKEN_LENGTH + 1));
+ bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1));
+ token_count += 1;
+#endif
+#endif
+ return token_count;
+}
+
+char *
+init_parse (filename)
+ char *filename;
{
- extern char *(*decl_printable_name) ();
extern int flag_no_gnu_keywords;
extern int flag_operator_names;
int i;
+#if USE_CPPLIB
+ yy_cur = "\n";
+ yy_lim = yy_cur + 1;
+
+ parse_in.show_column = 1;
+ if (! cpp_start_read (&parse_in, filename))
+ abort ();
+#else
+ /* Open input file. */
+ if (filename == 0 || !strcmp (filename, "-"))
+ {
+ finput = stdin;
+ filename = "stdin";
+ }
+ else
+ finput = fopen (filename, "r");
+ if (finput == 0)
+ pfatal_with_name (filename);
+
+#ifdef IO_BUFFER_SIZE
+ setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
+#endif
+#endif /* !USE_CPPLIB */
+
/* Initialize the lookahead machinery. */
init_spew ();
@@ -420,18 +507,9 @@ init_lex ()
init_cplus_expand ();
- tree_code_type
- = (char **) realloc (tree_code_type,
- sizeof (char *) * LAST_CPLUS_TREE_CODE);
- tree_code_length
- = (int *) realloc (tree_code_length,
- sizeof (int) * LAST_CPLUS_TREE_CODE);
- tree_code_name
- = (char **) realloc (tree_code_name,
- sizeof (char *) * LAST_CPLUS_TREE_CODE);
- bcopy ((char *)cplus_tree_code_type,
- (char *)(tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE),
- (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
+ bcopy (cplus_tree_code_type,
+ tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
+ (int)LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE);
bcopy ((char *)cplus_tree_code_length,
(char *)(tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE),
(LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
@@ -568,15 +646,13 @@ init_lex ()
IDENTIFIER_OPNAME_P (ansi_opname[(int) MAX_EXPR]) = 1;
ansi_opname[(int) COND_EXPR] = get_identifier ("__cn");
IDENTIFIER_OPNAME_P (ansi_opname[(int) COND_EXPR]) = 1;
- ansi_opname[(int) METHOD_CALL_EXPR] = get_identifier ("__wr");
- IDENTIFIER_OPNAME_P (ansi_opname[(int) METHOD_CALL_EXPR]) = 1;
+ ansi_opname[(int) SIZEOF_EXPR] = get_identifier ("__sz");
+ IDENTIFIER_OPNAME_P (ansi_opname[(int) SIZEOF_EXPR]) = 1;
init_method ();
init_error ();
gcc_obstack_init (&inline_text_obstack);
inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
- gcc_obstack_init (&synth_obstack);
- synth_firstobj = (char *) obstack_alloc (&synth_obstack, 0);
/* Start it at 0, because check_newline is called at the very beginning
and will increment it to 1. */
@@ -641,8 +717,11 @@ init_lex ()
ridpointers[(int) RID_REGISTER] = get_identifier ("register");
SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_REGISTER],
build_tree_list (NULL_TREE, ridpointers[(int) RID_REGISTER]));
+ ridpointers[(int) RID_COMPLEX] = get_identifier ("__complex");
+ SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_COMPLEX],
+ build_tree_list (NULL_TREE, ridpointers[(int) RID_COMPLEX]));
- /* C++ extensions. These are probably not correctly named. */
+ /* C++ extensions. These are probably not correctly named. */
ridpointers[(int) RID_WCHAR] = get_identifier ("__wchar_t");
SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_WCHAR],
build_tree_list (NULL_TREE, ridpointers[(int) RID_WCHAR]));
@@ -684,7 +763,7 @@ init_lex ()
ridpointers[(int) RID_TEMPLATE] = get_identifier ("template");
SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TEMPLATE],
build_tree_list (NULL_TREE, ridpointers[(int) RID_TEMPLATE]));
- /* This is for ANSI C++. */
+ /* This is for ANSI C++. */
ridpointers[(int) RID_MUTABLE] = get_identifier ("mutable");
SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_MUTABLE],
build_tree_list (NULL_TREE, ridpointers[(int) RID_MUTABLE]));
@@ -694,17 +773,19 @@ init_lex ()
TREE_TYPE (signature_type_node) = signature_type_node;
ridpointers[(int) RID_SIGNATURE] = signature_type_node;
+ null_node = build_int_2 (0, 0);
+ ridpointers[RID_NULL] = null_node;
+
opname_tab[(int) COMPONENT_REF] = "->";
opname_tab[(int) MEMBER_REF] = "->*";
- opname_tab[(int) METHOD_CALL_EXPR] = "->()";
- opname_tab[(int) INDIRECT_REF] = "(unary *)";
+ opname_tab[(int) INDIRECT_REF] = "*";
opname_tab[(int) ARRAY_REF] = "[]";
opname_tab[(int) MODIFY_EXPR] = "=";
opname_tab[(int) NEW_EXPR] = "new";
opname_tab[(int) DELETE_EXPR] = "delete";
opname_tab[(int) VEC_NEW_EXPR] = "new []";
opname_tab[(int) VEC_DELETE_EXPR] = "delete []";
- opname_tab[(int) COND_EXPR] = "... ? ... : ...";
+ opname_tab[(int) COND_EXPR] = "?:";
opname_tab[(int) CALL_EXPR] = "()";
opname_tab[(int) PLUS_EXPR] = "+";
opname_tab[(int) MINUS_EXPR] = "-";
@@ -741,9 +822,9 @@ init_lex ()
opname_tab[(int) EQ_EXPR] = "==";
opname_tab[(int) NE_EXPR] = "!=";
opname_tab[(int) IN_EXPR] = "in";
- opname_tab[(int) RANGE_EXPR] = "..";
- opname_tab[(int) CONVERT_EXPR] = "(unary +)";
- opname_tab[(int) ADDR_EXPR] = "(unary &)";
+ opname_tab[(int) RANGE_EXPR] = "...";
+ opname_tab[(int) CONVERT_EXPR] = "+";
+ opname_tab[(int) ADDR_EXPR] = "&";
opname_tab[(int) PREDECREMENT_EXPR] = "--";
opname_tab[(int) PREINCREMENT_EXPR] = "++";
opname_tab[(int) POSTDECREMENT_EXPR] = "--";
@@ -785,7 +866,7 @@ init_lex ()
#if 0
/* let's parse things, and if they use it, then give them an error. */
- if (!flag_handle_exceptions)
+ if (!flag_exceptions)
{
UNSET_RESERVED_WORD ("throw");
UNSET_RESERVED_WORD ("try");
@@ -793,11 +874,12 @@ init_lex ()
}
#endif
- if (! (flag_gc || flag_rtti) || flag_no_gnu_keywords)
+ if (!flag_rtti || flag_no_gnu_keywords)
{
UNSET_RESERVED_WORD ("classof");
UNSET_RESERVED_WORD ("headof");
}
+
if (! flag_handle_signatures || flag_no_gnu_keywords)
{
/* Easiest way to not recognize signature
@@ -822,11 +904,21 @@ init_lex ()
UNSET_RESERVED_WORD ("xor");
UNSET_RESERVED_WORD ("xor_eq");
}
- if (! flag_traditional)
- UNSET_RESERVED_WORD ("overload");
- token_count = init_parse ();
+ token_count = init_cpp_parse ();
interface_unknown = 1;
+
+ return filename;
+}
+
+void
+finish_parse ()
+{
+#if USE_CPPLIB
+ cpp_finish (&parse_in);
+#else
+ fclose (finput);
+#endif
}
void
@@ -855,10 +947,14 @@ yyprint (file, yychar, yylval)
case IDENTIFIER_DEFN:
case TYPENAME_DEFN:
case PTYPENAME_DEFN:
- case TYPENAME_ELLIPSIS:
case SCSPEC:
case PRE_PARSED_CLASS_DECL:
t = yylval.ttype;
+ if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == TEMPLATE_DECL)
+ {
+ fprintf (file, " `%s'", IDENTIFIER_POINTER (DECL_NAME (t)));
+ break;
+ }
my_friendly_assert (TREE_CODE (t) == IDENTIFIER_NODE, 224);
if (IDENTIFIER_POINTER (t))
fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
@@ -880,27 +976,19 @@ yyprint (file, yychar, yylval)
}
}
+#if defined(GATHER_STATISTICS) && defined(REDUCE_LENGTH)
static int *reduce_count;
+#endif
+
int *token_count;
+#if 0
#define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))
#define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))
-
-int *
-init_parse ()
-{
-#ifdef GATHER_STATISTICS
- reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1));
- bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1));
- reduce_count += 1;
- token_count = (int *)malloc (sizeof (int) * (TOKEN_LENGTH + 1));
- bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1));
- token_count += 1;
#endif
- return token_count;
-}
#ifdef GATHER_STATISTICS
+#ifdef REDUCE_LENGTH
void
yyhook (yyn)
int yyn;
@@ -922,11 +1010,13 @@ token_cmp (p, q)
return token_count[*q] - token_count[*p];
}
#endif
+#endif
void
print_parse_statistics ()
{
#ifdef GATHER_STATISTICS
+#ifdef REDUCE_LENGTH
#if YYDEBUG != 0
int i;
int maxlen = REDUCE_LENGTH;
@@ -944,13 +1034,13 @@ print_parse_statistics ()
qsort (sorted, TOKEN_LENGTH, sizeof (int), token_cmp);
for (i = 0; i < TOKEN_LENGTH; i++)
{
- int index = sorted[i];
- if (token_count[index] == 0)
+ int idx = sorted[i];
+ if (token_count[idx] == 0)
break;
- if (token_count[index] < token_count[-1])
+ if (token_count[idx] < token_count[-1])
break;
fprintf (stderr, "token %d, `%s', count = %d\n",
- index, yytname[YYTRANSLATE (index)], token_count[index]);
+ idx, yytname[YYTRANSLATE (idx)], token_count[idx]);
}
fprintf (stderr, "\n");
for (i = 0; i < REDUCE_LENGTH; i++)
@@ -958,22 +1048,24 @@ print_parse_statistics ()
qsort (sorted, REDUCE_LENGTH, sizeof (int), reduce_cmp);
for (i = 0; i < REDUCE_LENGTH; i++)
{
- int index = sorted[i];
- if (reduce_count[index] == 0)
+ int idx = sorted[i];
+ if (reduce_count[idx] == 0)
break;
- if (reduce_count[index] < reduce_count[-1])
+ if (reduce_count[idx] < reduce_count[-1])
break;
fprintf (stderr, "rule %d, line %d, count = %d\n",
- index, yyrline[index], reduce_count[index]);
+ idx, yyrline[idx], reduce_count[idx]);
}
fprintf (stderr, "\n");
#endif
#endif
+#endif
}
/* Sets the value of the 'yydebug' variable to VALUE.
This is a function so we don't have to have YYDEBUG defined
in order to build the compiler. */
+
void
set_yydebug (value)
int value;
@@ -1016,6 +1108,7 @@ static struct impl_files *impl_file_chain;
/* Helper function to load global variables with interface
information. */
+
void
extract_interface_info ()
{
@@ -1032,12 +1125,12 @@ extract_interface_info ()
fileinfo = get_time_identifier (input_filename);
fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
interface_only = TREE_INT_CST_LOW (fileinfo);
- if (!processing_template_defn || flag_external_templates)
- interface_unknown = TREE_INT_CST_HIGH (fileinfo);
+ interface_unknown = TREE_INT_CST_HIGH (fileinfo);
}
/* Return nonzero if S is not considered part of an
INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */
+
static int
interface_strcmp (s)
char *s;
@@ -1076,7 +1169,7 @@ interface_strcmp (s)
return 1;
}
-void
+static void
set_typedecl_interface_info (prev, vars)
tree prev, vars;
{
@@ -1085,10 +1178,10 @@ set_typedecl_interface_info (prev, vars)
tree type = TREE_TYPE (vars);
CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
- = interface_strcmp (FILE_NAME_NONDIRECTORY (DECL_SOURCE_FILE (vars)));
+ = interface_strcmp (file_name_nondirectory (DECL_SOURCE_FILE (vars)));
}
-void
+static int
set_vardecl_interface_info (prev, vars)
tree prev, vars;
{
@@ -1097,22 +1190,26 @@ set_vardecl_interface_info (prev, vars)
if (CLASSTYPE_INTERFACE_KNOWN (type))
{
if (CLASSTYPE_INTERFACE_ONLY (type))
- set_typedecl_interface_info (prev, TYPE_NAME (type));
+ set_typedecl_interface_info (prev, TYPE_MAIN_DECL (type));
else
CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
TREE_PUBLIC (vars) = 1;
+ return 1;
}
+ return 0;
}
/* Called from the top level: if there are any pending inlines to
do, set up to process them now. This function sets up the first function
to be parsed; after it has been, the rule for fndef in parse.y will
call process_next_inline to start working on the next one. */
+
void
do_pending_inlines ()
{
struct pending_inline *t;
+ tree context;
/* Oops, we're still dealing with the last batch. */
if (yychar == PRE_PARSED_FUNCTION_DECL)
@@ -1121,7 +1218,7 @@ do_pending_inlines ()
/* Reverse the pending inline functions, since
they were cons'd instead of appended. */
{
- struct pending_inline *prev = 0, *tail, *bottom = 0;
+ struct pending_inline *prev = 0, *tail;
t = pending_inlines;
pending_inlines = 0;
@@ -1132,33 +1229,6 @@ do_pending_inlines ()
t->deja_vu = 1;
prev = t;
}
-
- /* This kludge should go away when synthesized methods are handled
- properly, i.e. only when needed. */
- for (t = prev; t; t = t->next)
- {
- if (t->lineno <= 0)
- {
- tree f = t->fndecl;
- DECL_PENDING_INLINE_INFO (f) = 0;
- interface_unknown = t->interface == 1;
- interface_only = t->interface == 0;
- synthesize_method (f);
- if (tail)
- tail->next = t->next;
- else
- prev = t->next;
- if (! bottom)
- bottom = t;
- }
- else
- tail = t;
- }
- if (bottom)
- {
- obstack_free (&synth_obstack, bottom);
- extract_interface_info ();
- }
t = prev;
}
@@ -1166,13 +1236,13 @@ do_pending_inlines ()
return;
/* Now start processing the first inline function. */
- my_friendly_assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE),
- 226);
- if (t->parm_vec)
- push_template_decls (t->parm_vec, t->bindings, 0);
+ context = hack_decl_function_context (t->fndecl);
+ if (context)
+ push_cp_function_context (context);
+ maybe_begin_member_template_processing (t->fndecl);
if (t->len > 0)
{
- feed_input (t->buf, t->len, t->can_free ? &inline_text_obstack : 0);
+ feed_input (t->buf, t->len);
lineno = t->lineno;
#if 0
if (input_filename != t->filename)
@@ -1191,68 +1261,51 @@ do_pending_inlines ()
/* Pass back a handle on the rest of the inline functions, so that they
can be processed later. */
yylval.ttype = build_tree_list ((tree) t, t->fndecl);
-#if 0
- if (flag_default_inline && t->fndecl
- /* If we're working from a template, don't change
- the `inline' state. */
- && t->parm_vec == NULL_TREE)
- DECL_INLINE (t->fndecl) = 1;
-#endif
DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
}
-extern struct pending_input *to_be_restored;
static int nextchar = -1;
/* Called from the fndecl rule in the parser when the function just parsed
was declared using a PRE_PARSED_FUNCTION_DECL (i.e. came from
do_pending_inlines). */
+
void
process_next_inline (t)
tree t;
{
+ tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
- my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
- 227);
- if (i->parm_vec)
- pop_template_decls (i->parm_vec, i->bindings, 0);
+ context = hack_decl_function_context (i->fndecl);
+ maybe_end_member_template_processing (i->fndecl);
+ if (context)
+ pop_cp_function_context (context);
i = i->next;
if (yychar == YYEMPTY)
yychar = yylex ();
if (yychar != END_OF_SAVED_INPUT)
{
error ("parse error at end of saved function text");
+
/* restore_pending_input will abort unless yychar is either
- * END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
- * hosed, feed back YYEMPTY.
- * We also need to discard nextchar, since that may have gotten
- * set as well.
- */
+ END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
+ hosed, feed back YYEMPTY. We also need to discard nextchar,
+ since that may have gotten set as well. */
nextchar = -1;
}
yychar = YYEMPTY;
- if (to_be_restored == 0)
- my_friendly_abort (123);
- restore_pending_input (to_be_restored);
- to_be_restored = 0;
+ end_input ();
if (i && i->fndecl != NULL_TREE)
{
- my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
- 228);
- if (i->parm_vec)
- push_template_decls (i->parm_vec, i->bindings, 0);
- feed_input (i->buf, i->len, i->can_free ? &inline_text_obstack : 0);
+ context = hack_decl_function_context (i->fndecl);
+ if (context)
+ push_cp_function_context (context);
+ maybe_begin_member_template_processing (i->fndecl);
+ feed_input (i->buf, i->len);
lineno = i->lineno;
input_filename = i->filename;
yychar = PRE_PARSED_FUNCTION_DECL;
yylval.ttype = build_tree_list ((tree) i, i->fndecl);
-#if 0
- if (flag_default_inline
- /* If we're working from a template, don't change
- the `inline' state. */
- && i->parm_vec == NULL_TREE)
- DECL_INLINE (i->fndecl) = 1;
-#endif
DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
}
if (i)
@@ -1367,25 +1420,10 @@ restore_pending_input (p)
free (p);
}
-/* Return next non-whitespace input character, which may come
- from `finput', or from `nextchar'. */
-static int
-yynextch ()
-{
- int c;
-
- if (nextchar >= 0)
- {
- c = nextchar;
- nextchar = -1;
- }
- else c = getch ();
- return skip_white_space (c);
-}
-
/* Unget character CH from the input stream.
If RESCAN is non-zero, then we want to `see' this
character as the next input token. */
+
void
yyungetc (ch, rescan)
int ch;
@@ -1407,106 +1445,30 @@ yyungetc (ch, rescan)
}
}
+void
+clear_inline_text_obstack ()
+{
+ obstack_free (&inline_text_obstack, inline_text_firstobj);
+}
+
/* This function stores away the text for an inline function that should
be processed later. It decides how much later, and may need to move
the info between obstacks; therefore, the caller should not refer to
- the T parameter after calling this function.
-
- This function also stores the list of template-parameter bindings that
- will be needed for expanding the template, if any. */
+ the T parameter after calling this function. */
static void
store_pending_inline (decl, t)
tree decl;
struct pending_inline *t;
{
- extern int processing_template_defn;
- int delay_to_eof = 0;
- struct pending_inline **inlines;
-
t->fndecl = decl;
- /* Default: compile right away, and no extra bindings are needed. */
- t->parm_vec = t->bindings = 0;
- if (processing_template_defn)
- {
- tree type = current_class_type;
- /* Assumption: In this (possibly) nested class sequence, only
- one name will have template parms. */
- while (type && TREE_CODE_CLASS (TREE_CODE (type)) == 't')
- {
- tree decl = TYPE_NAME (type);
- tree tmpl = IDENTIFIER_TEMPLATE (DECL_NAME (decl));
- if (tmpl)
- {
- t->parm_vec = DECL_TEMPLATE_INFO (TREE_PURPOSE (tmpl))->parm_vec;
- t->bindings = TREE_VALUE (tmpl);
- }
- type = DECL_CONTEXT (decl);
- }
- if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
- || TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
- {
- if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- my_friendly_assert (TYPE_MAX_VALUE (TREE_TYPE (decl)) == current_class_type,
- 233);
-
- /* Inline functions can be compiled immediately. Other functions
- will be output separately, so if we're in interface-only mode,
- punt them now, or output them now if we're doing implementations
- and we know no overrides will exist. Otherwise, we delay until
- end-of-file, to see if the definition is really required. */
- if (DECL_THIS_INLINE (decl))
- /* delay_to_eof == 0 */;
- else if (current_class_type && !interface_unknown)
- {
- if (interface_only)
- {
-#if 0
- print_node_brief (stderr, "\ndiscarding text for ", decl, 0);
-#endif
- if (t->can_free)
- obstack_free (&inline_text_obstack, t->buf);
- DECL_PENDING_INLINE_INFO (decl) = 0;
- return;
- }
- }
- /* Don't delay the processing of virtual functions. */
- else if (DECL_VINDEX (decl) == NULL_TREE)
- delay_to_eof = 1;
- }
- else
- my_friendly_abort (58);
- }
-
- if (delay_to_eof)
- {
- extern struct pending_inline *pending_template_expansions;
-
- if (t->can_free)
- {
- char *free_to = t->buf;
- t->buf = (char *) obstack_copy (&permanent_obstack, t->buf,
- t->len + 1);
- t = (struct pending_inline *) obstack_copy (&permanent_obstack,
- (char *)t, sizeof (*t));
- obstack_free (&inline_text_obstack, free_to);
- }
- inlines = &pending_template_expansions;
- t->can_free = 0;
- }
- else
- {
- inlines = &pending_inlines;
- DECL_PENDING_INLINE_INFO (decl) = t;
- }
+ DECL_PENDING_INLINE_INFO (decl) = t;
/* Because we use obstacks, we must process these in precise order. */
- t->next = *inlines;
- *inlines = t;
+ t->next = pending_inlines;
+ pending_inlines = t;
}
-void reinit_parse_for_block ();
-
void
reinit_parse_for_method (yychar, decl)
int yychar;
@@ -1516,7 +1478,7 @@ reinit_parse_for_method (yychar, decl)
int starting_lineno = lineno;
char *starting_filename = input_filename;
- reinit_parse_for_block (yychar, &inline_text_obstack, 0);
+ reinit_parse_for_block (yychar, &inline_text_obstack);
len = obstack_object_size (&inline_text_obstack);
current_base_init_list = NULL_TREE;
@@ -1543,26 +1505,23 @@ reinit_parse_for_method (yychar, decl)
t->token_value = 0;
t->buf = buf;
t->len = len;
- t->can_free = 1;
t->deja_vu = 0;
+#if 0
if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
warn_if_unknown_interface (decl);
+#endif
t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
store_pending_inline (decl, t);
}
}
-/* Consume a block -- actually, a method or template definition beginning
- with `:' or `{' -- and save it away on the specified obstack.
+/* Consume a block -- actually, a method beginning
+ with `:' or `{' -- and save it away on the specified obstack. */
- Argument IS_TEMPLATE indicates which set of error messages should be
- output if something goes wrong. This should really be cleaned up somehow,
- without loss of clarity. */
void
-reinit_parse_for_block (pyychar, obstackp, is_template)
+reinit_parse_for_block (pyychar, obstackp)
int pyychar;
struct obstack *obstackp;
- int is_template;
{
register int c = 0;
int blev = 1;
@@ -1582,13 +1541,13 @@ reinit_parse_for_block (pyychar, obstackp, is_template)
look_for_lbrac = 1;
blev = 0;
}
- else if (pyychar == RETURN && !is_template)
+ else if (pyychar == RETURN)
{
obstack_grow (obstackp, "return", 6);
look_for_lbrac = 1;
blev = 0;
}
- else if (pyychar == TRY && !is_template)
+ else if (pyychar == TRY)
{
obstack_grow (obstackp, "try", 3);
look_for_lbrac = 1;
@@ -1596,9 +1555,7 @@ reinit_parse_for_block (pyychar, obstackp, is_template)
}
else
{
- yyerror (is_template
- ? "parse error in template specification"
- : "parse error in method specification");
+ yyerror ("parse error in method specification");
obstack_1grow (obstackp, '{');
}
@@ -1695,9 +1652,7 @@ reinit_parse_for_block (pyychar, obstackp, is_template)
{
if (look_for_lbrac)
{
- error (is_template
- ? "template body missing"
- : "function body for constructor missing");
+ error ("function body for constructor missing");
obstack_1grow (obstackp, '{');
obstack_1grow (obstackp, '}');
len += 2;
@@ -1726,6 +1681,262 @@ reinit_parse_for_block (pyychar, obstackp, is_template)
obstack_1grow (obstackp, '\0');
}
+/* Consume a no-commas expression -- actually, a default argument -- and
+ save it away on the specified obstack. */
+
+static void
+reinit_parse_for_expr (obstackp)
+ struct obstack *obstackp;
+{
+ register int c = 0;
+ int starting_lineno = lineno;
+ char *starting_filename = input_filename;
+ int len;
+ int plev = 0;
+
+ if (nextchar != EOF)
+ {
+ c = nextchar;
+ nextchar = EOF;
+ }
+ else
+ c = getch ();
+
+ while (c != EOF)
+ {
+ int this_lineno = lineno;
+
+ c = skip_white_space (c);
+
+ /* Don't lose our cool if there are lots of comments. */
+ if (lineno == this_lineno + 1)
+ obstack_1grow (obstackp, '\n');
+ else if (lineno == this_lineno)
+ ;
+ else if (lineno - this_lineno < 10)
+ {
+ int i;
+ for (i = lineno - this_lineno; i > 0; --i)
+ obstack_1grow (obstackp, '\n');
+ }
+ else
+ {
+ char buf[16];
+ sprintf (buf, "\n# %d \"", lineno);
+ len = strlen (buf);
+ obstack_grow (obstackp, buf, len);
+
+ len = strlen (input_filename);
+ obstack_grow (obstackp, input_filename, len);
+ obstack_1grow (obstackp, '\"');
+ obstack_1grow (obstackp, '\n');
+ }
+
+ while (c > ' ') /* ASCII dependent... */
+ {
+ if (plev <= 0 && (c == ')' || c == ','))
+ {
+ put_back (c);
+ goto done;
+ }
+ obstack_1grow (obstackp, c);
+ if (c == '(' || c == '[')
+ ++plev;
+ else if (c == ']' || c == ')')
+ --plev;
+ else if (c == '\\')
+ {
+ /* Don't act on the next character...e.g, doing an escaped
+ double-quote. */
+ c = getch ();
+ if (c == EOF)
+ {
+ error_with_file_and_line (starting_filename,
+ starting_lineno,
+ "end of file read inside definition");
+ goto done;
+ }
+ obstack_1grow (obstackp, c);
+ }
+ else if (c == '\"')
+ consume_string (obstackp, c);
+ else if (c == '\'')
+ consume_string (obstackp, c);
+ c = getch ();
+ }
+
+ if (c == EOF)
+ {
+ error_with_file_and_line (starting_filename,
+ starting_lineno,
+ "end of file read inside definition");
+ goto done;
+ }
+ else if (c != '\n')
+ {
+ obstack_1grow (obstackp, c);
+ c = getch ();
+ }
+ }
+ done:
+ obstack_1grow (obstackp, '\0');
+}
+
+int do_snarf_defarg;
+
+/* Decide whether the default argument we are about to see should be
+ gobbled up as text for later parsing. */
+
+void
+maybe_snarf_defarg ()
+{
+ if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
+ do_snarf_defarg = 1;
+}
+
+/* When we see a default argument in a method declaration, we snarf it as
+ text using snarf_defarg. When we get up to namespace scope, we then go
+ through and parse all of them using do_pending_defargs. Since yacc
+ parsers are not reentrant, we retain defargs state in these two
+ variables so that subsequent calls to do_pending_defargs can resume
+ where the previous call left off. */
+
+tree defarg_fns;
+tree defarg_parm;
+
+tree
+snarf_defarg ()
+{
+ int len;
+ char *buf;
+ tree arg;
+
+ reinit_parse_for_expr (&inline_text_obstack);
+ len = obstack_object_size (&inline_text_obstack);
+ buf = obstack_finish (&inline_text_obstack);
+
+ push_obstacks (&inline_text_obstack, &inline_text_obstack);
+ arg = make_node (DEFAULT_ARG);
+ DEFARG_LENGTH (arg) = len - 1;
+ DEFARG_POINTER (arg) = buf;
+ pop_obstacks ();
+
+ return arg;
+}
+
+/* Called from grokfndecl to note a function decl with unparsed default
+ arguments for later processing. Also called from grokdeclarator
+ for function types with unparsed defargs; the call from grokfndecl
+ will always come second, so we can overwrite the entry from the type. */
+
+void
+add_defarg_fn (decl)
+ tree decl;
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ TREE_VALUE (defarg_fns) = decl;
+ else
+ {
+ push_obstacks (&inline_text_obstack, &inline_text_obstack);
+ defarg_fns = tree_cons (current_class_type, decl, defarg_fns);
+ pop_obstacks ();
+ }
+}
+
+/* Helper for do_pending_defargs. Starts the parsing of a default arg. */
+
+static void
+feed_defarg (f, p)
+ tree f, p;
+{
+ tree d = TREE_PURPOSE (p);
+ feed_input (DEFARG_POINTER (d), DEFARG_LENGTH (d));
+ if (TREE_CODE (f) == FUNCTION_DECL)
+ {
+ lineno = DECL_SOURCE_LINE (f);
+ input_filename = DECL_SOURCE_FILE (f);
+ }
+ yychar = DEFARG_MARKER;
+ yylval.ttype = p;
+}
+
+/* Helper for do_pending_defargs. Ends the parsing of a default arg. */
+
+static void
+finish_defarg ()
+{
+ if (yychar == YYEMPTY)
+ yychar = yylex ();
+ if (yychar != END_OF_SAVED_INPUT)
+ {
+ error ("parse error at end of saved function text");
+
+ /* restore_pending_input will abort unless yychar is either
+ END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
+ hosed, feed back YYEMPTY. We also need to discard nextchar,
+ since that may have gotten set as well. */
+ nextchar = -1;
+ }
+ yychar = YYEMPTY;
+ end_input ();
+}
+
+/* Main function for deferred parsing of default arguments. Called from
+ the parser. */
+
+void
+do_pending_defargs ()
+{
+ if (defarg_parm)
+ finish_defarg ();
+
+ for (; defarg_fns; defarg_fns = TREE_CHAIN (defarg_fns))
+ {
+ tree defarg_fn = TREE_VALUE (defarg_fns);
+ if (defarg_parm == NULL_TREE)
+ {
+ push_nested_class (TREE_PURPOSE (defarg_fns), 1);
+ pushlevel (0);
+ if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
+ maybe_begin_member_template_processing (defarg_fn);
+
+ if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
+ {
+#if 0
+ tree p;
+ for (p = DECL_ARGUMENTS (defarg_fn); p; p = TREE_CHAIN (p))
+ pushdecl (copy_node (p));
+#endif
+ defarg_parm = TYPE_ARG_TYPES (TREE_TYPE (defarg_fn));
+ }
+ else
+ defarg_parm = TYPE_ARG_TYPES (defarg_fn);
+ }
+ else
+ defarg_parm = TREE_CHAIN (defarg_parm);
+
+ for (; defarg_parm; defarg_parm = TREE_CHAIN (defarg_parm))
+ if (TREE_PURPOSE (defarg_parm)
+ && TREE_CODE (TREE_PURPOSE (defarg_parm)) == DEFAULT_ARG)
+ {
+ feed_defarg (defarg_fn, defarg_parm);
+
+ /* Return to the parser, which will process this defarg
+ and call us again. */
+ return;
+ }
+
+ if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
+ {
+ maybe_end_member_template_processing (defarg_fn);
+ check_default_args (defarg_fn);
+ }
+
+ poplevel (0, 0, 0);
+ pop_nested_class (1);
+ }
+}
+
/* Build a default function named NAME for type TYPE.
KIND says what to build.
@@ -1743,13 +1954,10 @@ cons_up_default_function (type, full_name, kind)
int kind;
{
extern tree void_list_node;
- char *func_buf = NULL;
- int func_len = 0;
tree declspecs = NULL_TREE;
- tree fn, args;
+ tree fn, args = NULL_TREE;
tree argtype;
int retref = 0;
- int complex = 0;
tree name = constructor_name (full_name);
switch (kind)
@@ -1766,7 +1974,6 @@ cons_up_default_function (type, full_name, kind)
case 2:
/* Default constructor. */
args = void_list_node;
- complex = TYPE_NEEDS_CONSTRUCTING (type);
break;
case 3:
@@ -1780,15 +1987,15 @@ cons_up_default_function (type, full_name, kind)
build_tree_list (hash_tree_chain (argtype, NULL_TREE),
get_identifier ("_ctor_arg")),
void_list_node);
- complex = TYPE_HAS_COMPLEX_INIT_REF (type);
break;
case 5:
- type = build_type_variant (type, 1, 0);
- /* Fall through... */
case 6:
retref = 1;
- declspecs = build_decl_list (NULL_TREE, full_name);
+ declspecs = build_decl_list (NULL_TREE, type);
+
+ if (kind == 5)
+ type = build_type_variant (type, 1, 0);
name = ansi_opname [(int) MODIFY_EXPR];
@@ -1797,7 +2004,6 @@ cons_up_default_function (type, full_name, kind)
build_tree_list (hash_tree_chain (argtype, NULL_TREE),
get_identifier ("_ctor_arg")),
void_list_node);
- complex = TYPE_HAS_COMPLEX_ASSIGN_REF (type);
break;
default:
@@ -1810,23 +2016,28 @@ cons_up_default_function (type, full_name, kind)
TREE_PARMLIST (args) = 1;
{
- tree declarator = build_parse_node (CALL_EXPR, name, args, NULL_TREE);
+ tree declarator = make_call_declarator (name, args, NULL_TREE, NULL_TREE);
if (retref)
declarator = build_parse_node (ADDR_EXPR, declarator);
-
- fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE,
- NULL_TREE, NULL_TREE);
+
+ fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
}
if (fn == void_type_node)
return fn;
+ if (kind > 2)
+ SET_DECL_ARTIFICIAL (TREE_CHAIN (DECL_ARGUMENTS (fn)));
+
+#if 0
if (processing_template_defn)
{
SET_DECL_IMPLICIT_INSTANTIATION (fn);
repo_template_used (fn);
}
+#endif
+#if 0
if (CLASSTYPE_INTERFACE_KNOWN (type))
{
DECL_INTERFACE_KNOWN (fn) = 1;
@@ -1834,29 +2045,10 @@ cons_up_default_function (type, full_name, kind)
&& flag_implement_inlines);
}
else
+#endif
DECL_NOT_REALLY_EXTERN (fn) = 1;
-#if 0
- /* When on-the-fly synthesis works properly, remove the second and third
- conditions here. */
- if (flag_keep_inline_functions
-#if 0
- || ! flag_no_inline
- || complex
-#endif
- || ! DECL_EXTERNAL (fn))
- {
- struct pending_inline *t;
- t = (struct pending_inline *)
- obstack_alloc (&synth_obstack, sizeof (struct pending_inline));
- t->lineno = -kind;
- t->can_free = 0;
- t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
- store_pending_inline (fn, t);
- }
- else
-#endif
- mark_inline_for_output (fn);
+ mark_inline_for_output (fn);
#ifdef DEBUG_DEFAULT_FUNCTIONS
{ char *fn_type = NULL;
@@ -1888,6 +2080,7 @@ cons_up_default_function (type, full_name, kind)
/* Heuristic to tell whether the user is missing a semicolon
after a struct or enum declaration. Emit an error message
if we know the user has blown it. */
+
void
check_for_missing_semicolon (type)
tree type;
@@ -1898,7 +2091,9 @@ check_for_missing_semicolon (type)
if ((yychar > 255
&& yychar != SCSPEC
&& yychar != IDENTIFIER
- && yychar != TYPENAME)
+ && yychar != TYPENAME
+ && yychar != CV_QUALIFIER
+ && yychar != SELFNAME)
|| end_of_file)
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
@@ -2020,7 +2215,9 @@ get_last_nonwhite_on_line ()
int linemode;
-int
+static int handle_cp_pragma PROTO((char *));
+
+static int
check_newline ()
{
register int c;
@@ -2064,254 +2261,35 @@ check_newline ()
&& getch () == 'm'
&& getch () == 'a')
{
- /* Read first nonwhite char after the `#pragma'. */
-
- do
- c = getch ();
- while (c == ' ' || c == '\t');
-
- if (c == 'v'
- && getch () == 't'
- && getch () == 'a'
- && getch () == 'b'
- && getch () == 'l'
- && getch () == 'e'
- && ((c = getch ()) == ' ' || c == '\t'))
- {
- extern tree pending_vtables;
-
- /* More follows: it must be a string constant (class name). */
- token = real_yylex ();
- if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid #pragma vtable");
- goto skipline;
- }
- if (write_virtuals != 2)
- {
- warning ("use `+e2' option to enable #pragma vtable");
- goto skipline;
- }
- pending_vtables = perm_tree_cons (NULL_TREE, get_identifier (TREE_STRING_POINTER (yylval.ttype)), pending_vtables);
- if (nextchar < 0)
- nextchar = getch ();
- c = nextchar;
- if (c != EOF)
- warning ("trailing characters ignored");
- }
- else if (c == 'u'
- && getch () == 'n'
- && getch () == 'i'
- && getch () == 't'
- && ((c = getch ()) == ' ' || c == '\t'))
+ token = real_yylex ();
+ if (token == IDENTIFIER
+ && TREE_CODE (yylval.ttype) == IDENTIFIER_NODE)
{
- /* More follows: it must be a string constant (unit name). */
- token = real_yylex ();
- if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid #pragma unit");
- goto skipline;
- }
- current_unit_name = get_identifier (TREE_STRING_POINTER (yylval.ttype));
- current_unit_language = current_lang_name;
- if (nextchar < 0)
- nextchar = getch ();
- c = nextchar;
- if (c != EOF)
- warning ("trailing characters ignored");
+ /* If this is 1, we handled it; if it's -1, it was one we
+ wanted but had something wrong with it. Only if it's
+ 0 was it not handled. */
+ if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype)))
+ goto skipline;
}
- else if (c == 'i')
- {
- tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
- c = getch ();
-
- if (c == 'n'
- && getch () == 't'
- && getch () == 'e'
- && getch () == 'r'
- && getch () == 'f'
- && getch () == 'a'
- && getch () == 'c'
- && getch () == 'e'
- && ((c = getch ()) == ' ' || c == '\t' || c == EOF))
- {
- int warned_already = 0;
- char *main_filename = input_filename;
-
- main_filename = FILE_NAME_NONDIRECTORY (main_filename);
- while (c == ' ' || c == '\t')
- c = getch ();
- if (c != EOF)
- {
- put_back (c);
- token = real_yylex ();
- if (token != STRING
- || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid `#pragma interface'");
- goto skipline;
- }
- main_filename = TREE_STRING_POINTER (yylval.ttype);
- c = getch();
- put_back (c);
- }
-
- while (c == ' ' || c == '\t')
- c = getch ();
-
- while (c != EOF)
- {
- if (!warned_already && extra_warnings
- && c != ' ' && c != '\t')
- {
- warning ("garbage after `#pragma interface' ignored");
- warned_already = 1;
- }
- c = getch ();
- }
-
- write_virtuals = 3;
-
- if (impl_file_chain == 0)
- {
- /* If this is zero at this point, then we are
- auto-implementing. */
- if (main_input_filename == 0)
- main_input_filename = input_filename;
-
-#ifdef AUTO_IMPLEMENT
- filename = FILE_NAME_NONDIRECTORY (main_input_filename);
- fi = get_time_identifier (filename);
- fi = IDENTIFIER_CLASS_VALUE (fi);
- TREE_INT_CST_LOW (fi) = 0;
- TREE_INT_CST_HIGH (fi) = 1;
- /* Get default. */
- impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
- impl_file_chain->filename = filename;
- impl_file_chain->next = 0;
-#endif
- }
-
- interface_only = interface_strcmp (main_filename);
- interface_unknown = 0;
- TREE_INT_CST_LOW (fileinfo) = interface_only;
- TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
- }
- else if (c == 'm'
- && getch () == 'p'
- && getch () == 'l'
- && getch () == 'e'
- && getch () == 'm'
- && getch () == 'e'
- && getch () == 'n'
- && getch () == 't'
- && getch () == 'a'
- && getch () == 't'
- && getch () == 'i'
- && getch () == 'o'
- && getch () == 'n'
- && ((c = getch ()) == ' ' || c == '\t' || c == EOF))
- {
- int warned_already = 0;
- char *main_filename = main_input_filename ? main_input_filename : input_filename;
-
- main_filename = FILE_NAME_NONDIRECTORY (main_filename);
- while (c == ' ' || c == '\t')
- c = getch ();
- if (c != EOF)
- {
- put_back (c);
- token = real_yylex ();
- if (token != STRING
- || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid `#pragma implementation'");
- goto skipline;
- }
- main_filename = TREE_STRING_POINTER (yylval.ttype);
- c = getch();
- put_back (c);
- }
-
- while (c == ' ' || c == '\t')
- c = getch ();
-
- while (c != EOF)
- {
- if (!warned_already && extra_warnings
- && c != ' ' && c != '\t')
- {
- warning ("garbage after `#pragma implementation' ignored");
- warned_already = 1;
- }
- c = getch ();
- }
+ else if (token == END_OF_LINE)
+ goto skipline;
- if (write_virtuals == 3)
- {
- struct impl_files *ifiles = impl_file_chain;
- while (ifiles)
- {
- if (! strcmp (ifiles->filename, main_filename))
- break;
- ifiles = ifiles->next;
- }
- if (ifiles == 0)
- {
- ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files));
- ifiles->filename = main_filename;
- ifiles->next = impl_file_chain;
- impl_file_chain = ifiles;
- }
- }
- else if ((main_input_filename != 0
- && ! strcmp (main_input_filename, input_filename))
- || ! strcmp (input_filename, main_filename))
- {
- write_virtuals = 3;
- if (impl_file_chain == 0)
- {
- impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files));
- impl_file_chain->filename = main_filename;
- impl_file_chain->next = 0;
- }
- }
- else
- error ("`#pragma implementation' can only appear at top-level");
- interface_only = 0;
-#if 1
- /* We make this non-zero so that we infer decl linkage
- in the impl file only for variables first declared
- in the interface file. */
- interface_unknown = 1;
-#else
- /* We make this zero so that templates in the impl
- file will be emitted properly. */
- interface_unknown = 0;
-#endif
- TREE_INT_CST_LOW (fileinfo) = interface_only;
- TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
- }
- }
#ifdef HANDLE_SYSV_PRAGMA
- else
- {
- put_back (c);
- handle_sysv_pragma ();
- }
+ if (handle_sysv_pragma (token))
+ goto skipline;
#else
#ifdef HANDLE_PRAGMA
- /* FIXME: This will break if we're doing any of the C++ input
- tricks. */
- else
- {
- ungetc (c, finput);
- HANDLE_PRAGMA (finput);
- }
+#if USE_CPPLIB
+ /* TODO: ??? */
+ goto skipline;
+#else
+ if (HANDLE_PRAGMA (finput, yylval.ttype))
+ goto skipline;
+#endif /* !USE_CPPLIB */
#endif
#endif
- goto skipline;
}
+ goto skipline;
}
else if (c == 'd')
{
@@ -2322,11 +2300,7 @@ check_newline ()
&& getch () == 'e'
&& ((c = getch ()) == ' ' || c == '\t'))
{
-#ifdef DWARF_DEBUGGING_INFO
- if ((debug_info_level == DINFO_LEVEL_VERBOSE)
- && (write_symbols == DWARF_DEBUG))
- dwarfout_define (lineno, get_directive_line (finput));
-#endif /* DWARF_DEBUGGING_INFO */
+ debug_define (lineno, GET_DIRECTIVE_LINE ());
goto skipline;
}
}
@@ -2338,11 +2312,7 @@ check_newline ()
&& getch () == 'f'
&& ((c = getch ()) == ' ' || c == '\t'))
{
-#ifdef DWARF_DEBUGGING_INFO
- if ((debug_info_level == DINFO_LEVEL_VERBOSE)
- && (write_symbols == DWARF_DEBUG))
- dwarfout_undef (lineno, get_directive_line (finput));
-#endif /* DWARF_DEBUGGING_INFO */
+ debug_undef (lineno, GET_DIRECTIVE_LINE ());
goto skipline;
}
}
@@ -2362,23 +2332,14 @@ check_newline ()
&& getch () == 't'
&& ((c = getch ()) == ' ' || c == '\t'))
{
-#ifdef ASM_OUTPUT_IDENT
- extern FILE *asm_out_file;
-#endif
/* #ident. The pedantic warning is now in cccp.c. */
/* Here we have just seen `#ident '.
A string constant should follow. */
- while (c == ' ' || c == '\t')
- c = getch ();
-
- /* If no argument, ignore the line. */
- if (c == EOF)
- goto skipline;
-
- put_back (c);
token = real_yylex ();
+ if (token == END_OF_LINE)
+ goto skipline;
if (token != STRING
|| TREE_CODE (yylval.ttype) != STRING_CST)
{
@@ -2483,9 +2444,6 @@ linenum:
body_time = this_time;
}
- if (flag_cadillac)
- cadillac_note_source ();
-
input_filename
= (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
@@ -2500,7 +2458,7 @@ linenum:
{
while (ifiles->next)
ifiles = ifiles->next;
- ifiles->filename = FILE_NAME_NONDIRECTORY (input_filename);
+ ifiles->filename = file_name_nondirectory (input_filename);
}
main_input_filename = input_filename;
@@ -2590,13 +2548,7 @@ linenum:
p->name = input_filename;
input_file_stack = p;
input_file_stack_tick++;
-#ifdef DWARF_DEBUGGING_INFO
- if (debug_info_level == DINFO_LEVEL_VERBOSE
- && write_symbols == DWARF_DEBUG)
- dwarfout_start_new_source_file (input_filename);
-#endif /* DWARF_DEBUGGING_INFO */
- if (flag_cadillac)
- cadillac_push_source ();
+ debug_start_source_file (input_filename);
in_system_header = entering_system_header;
if (c_header_level)
++c_header_level;
@@ -2619,29 +2571,19 @@ linenum:
warning ("badly nested C headers from preprocessor");
--pending_lang_change;
}
- if (flag_cadillac)
- cadillac_pop_source ();
in_system_header = entering_system_header;
p = input_file_stack;
input_file_stack = p->next;
free (p);
input_file_stack_tick++;
-#ifdef DWARF_DEBUGGING_INFO
- if (debug_info_level == DINFO_LEVEL_VERBOSE
- && write_symbols == DWARF_DEBUG)
- dwarfout_resume_previous_source_file (input_file_stack->line);
-#endif /* DWARF_DEBUGGING_INFO */
+ debug_end_source_file (input_file_stack->line);
}
else
error ("#-lines for entering and leaving files don't match");
}
else
- {
- in_system_header = entering_system_header;
- if (flag_cadillac)
- cadillac_switch_source (-1);
- }
+ in_system_header = entering_system_header;
}
/* If NEXTCHAR is not end of line, we don't care what it is. */
@@ -2655,6 +2597,7 @@ linenum:
skipline:
linemode = 0;
end_of_file = 0;
+ nextchar = -1;
while ((c = getch ()) != EOF && c != '\n');
return c;
}
@@ -2668,13 +2611,6 @@ do_pending_lang_change ()
pop_lang_context ();
}
-#if 0
-#define isalnum(char) (char >= 'a' ? char <= 'z' : char >= '0' ? char <= '9' || (char >= 'A' && char <= 'Z') : 0)
-#define isdigit(char) (char >= '0' && char <= '9')
-#else
-#include <ctype.h>
-#endif
-
#define ENDFILE -1 /* token that represents end-of-file */
/* Read an escape sequence, returning its equivalent as a character,
@@ -2687,25 +2623,19 @@ readescape (ignore_ptr)
register int c = getch ();
register int code;
register unsigned count;
- unsigned firstdig;
+ unsigned firstdig = 0;
int nonnull;
switch (c)
{
case 'x':
- if (warn_traditional)
- warning ("the meaning of `\\x' varies with -traditional");
-
- if (flag_traditional)
- return c;
-
code = 0;
count = 0;
nonnull = 0;
while (1)
{
c = getch ();
- if (! isxdigit (c))
+ if (! ISXDIGIT (c))
{
put_back (c);
break;
@@ -2773,11 +2703,6 @@ readescape (ignore_ptr)
return TARGET_BS;
case 'a':
- if (warn_traditional)
- warning ("the meaning of `\\a' varies with -traditional");
-
- if (flag_traditional)
- return c;
return TARGET_BELL;
case 'v':
@@ -2812,46 +2737,47 @@ readescape (ignore_ptr)
/* Value is 1 (or 2) if we should try to make the next identifier look like
a typename (when it may be a local variable or a class variable).
Value is 0 if we treat this name in a default fashion. */
-int looking_for_typename = 0;
-
-#if 0
-/* NO LONGER USED: Value is -1 if we must not see a type name. */
-void
-dont_see_typename ()
-{
- looking_for_typename = -1;
- if (yychar == TYPENAME || yychar == PTYPENAME)
- {
- yychar = IDENTIFIER;
- lastiddecl = 0;
- }
-}
-#endif
+int looking_for_typename;
#ifdef __GNUC__
-extern __inline int identifier_type ();
__inline
#endif
int
identifier_type (decl)
tree decl;
{
- if (TREE_CODE (decl) == TEMPLATE_DECL
- && DECL_TEMPLATE_IS_CLASS (decl))
- return PTYPENAME;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
+ return PTYPENAME;
+ else if (looking_for_template)
+ return PFUNCNAME;
+ }
+ if (looking_for_template && really_overloaded_fn (decl))
+ {
+ tree t;
+ for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t))
+ if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
+ return PFUNCNAME;
+ }
if (TREE_CODE (decl) == NAMESPACE_DECL)
return NSNAME;
if (TREE_CODE (decl) != TYPE_DECL)
return IDENTIFIER;
+ if (((got_scope && TREE_TYPE (decl) == got_scope)
+ || TREE_TYPE (decl) == current_class_type)
+ && DECL_ARTIFICIAL (decl))
+ return SELFNAME;
return TYPENAME;
}
void
see_typename ()
{
- looking_for_typename = 1;
+ /* Only types expected, not even namespaces. */
+ looking_for_typename = 2;
if (yychar < 0)
- if ((yychar = yylex()) < 0) yychar = 0;
+ if ((yychar = yylex ()) < 0) yychar = 0;
looking_for_typename = 0;
if (yychar == IDENTIFIER)
{
@@ -2866,20 +2792,44 @@ see_typename ()
}
}
+/* Return true if d is in a global scope. */
+
+static int
+is_global (d)
+ tree d;
+{
+ while (1)
+ switch (TREE_CODE (d))
+ {
+ case OVERLOAD: d = OVL_FUNCTION (d); continue;
+ case TREE_LIST: d = TREE_VALUE (d); continue;
+ default:
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (d)) == 'd', 980629);
+ d = CP_DECL_CONTEXT (d);
+ return TREE_CODE (d) == NAMESPACE_DECL;
+ }
+}
+
tree
-do_identifier (token)
+do_identifier (token, parsing, args)
register tree token;
+ int parsing;
+ tree args;
{
- register tree id = lastiddecl;
+ register tree id;
+ int lexing = (parsing == 1);
+ int in_call = (parsing == 2);
+
+ if (! lexing || IDENTIFIER_OPNAME_P (token))
+ id = lookup_name (token, 0);
+ else
+ id = lastiddecl;
- if (yychar == YYEMPTY)
- yychar = yylex ();
/* Scope class declarations before global
declarations. */
- if (id == IDENTIFIER_GLOBAL_VALUE (token)
+ if ((!id || is_global (id))
&& current_class_type != 0
- && TYPE_SIZE (current_class_type) == 0
- && TREE_CODE (current_class_type) != UNINSTANTIATED_P_TYPE)
+ && TYPE_SIZE (current_class_type) == 0)
{
/* Could be from one of the base classes. */
tree field = lookup_field (current_class_type, token, 1, 0);
@@ -2890,7 +2840,8 @@ do_identifier (token)
But we still want to return this value. */
id = lookup_field (current_class_type, token, 0, 0);
else if (TREE_CODE (field) == VAR_DECL
- || TREE_CODE (field) == CONST_DECL)
+ || TREE_CODE (field) == CONST_DECL
+ || TREE_CODE (field) == TEMPLATE_DECL)
id = field;
else if (TREE_CODE (field) != FIELD_DECL)
my_friendly_abort (61);
@@ -2903,11 +2854,25 @@ do_identifier (token)
}
}
+ /* Do Koenig lookup if appropriate (inside templates we build lookup
+ expressions instead). */
+ if (args && !current_template_parms && (!id || is_global (id)))
+ {
+ /* If we have arguments and we only found global names,
+ do Koenig lookup. */
+ id = lookup_arg_dependent (token, id, args);
+ }
+
/* Remember that this name has been used in the class definition, as per
[class.scope0] */
- if (id && current_class_type
+ if (id && current_class_type && parsing
&& TYPE_BEING_DEFINED (current_class_type)
- && ! IDENTIFIER_CLASS_VALUE (token))
+ && ! IDENTIFIER_CLASS_VALUE (token)
+ /* Avoid breaking if we get called for a default argument that
+ refers to an overloaded method. Eventually this will not be
+ necessary, since default arguments shouldn't be parsed until
+ after the class is complete. (jason 3/12/97) */
+ && TREE_CODE (id) != OVERLOAD)
pushdecl_class_level (id);
if (!id || id == error_mark_node)
@@ -2920,7 +2885,16 @@ do_identifier (token)
if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node)
return id;
}
- if (yychar == '(' || yychar == LEFT_RIGHT)
+
+ if (current_template_parms)
+ return build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
+ else if (IDENTIFIER_OPNAME_P (token))
+ {
+ if (token != ansi_opname[ERROR_MARK])
+ cp_error ("`%D' not defined", token);
+ id = error_mark_node;
+ }
+ else if (in_call)
{
id = implicitly_declare (token);
}
@@ -2931,7 +2905,7 @@ do_identifier (token)
}
else
{
- if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node
+ if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node
|| IDENTIFIER_ERROR_LOCUS (token) != current_function_decl)
{
static int undeclared_variable_notice;
@@ -2947,7 +2921,7 @@ do_identifier (token)
}
id = error_mark_node;
/* Prevent repeated error messages. */
- IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node;
+ SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node);
SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
}
}
@@ -2955,6 +2929,11 @@ do_identifier (token)
if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id))
{
tree shadowed = DECL_SHADOWED_FOR_VAR (id);
+ while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL
+ && DECL_DEAD_FOR_LOCAL (shadowed))
+ shadowed = DECL_SHADOWED_FOR_VAR (shadowed);
+ if (!shadowed)
+ shadowed = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (id));
if (shadowed)
{
if (!DECL_ERROR_REPORTED (id))
@@ -2992,20 +2971,109 @@ do_identifier (token)
if (IDENTIFIER_CLASS_VALUE (token) == id)
{
/* Check access. */
- enum access_type access
- = compute_access (TYPE_BINFO (current_class_type), id);
- if (access == access_private)
+ tree access = compute_access (TYPE_BINFO (current_class_type), id);
+ if (access == access_private_node)
cp_error ("enum `%D' is private", id);
/* protected is OK, since it's an enum of `this'. */
}
- id = DECL_INITIAL (id);
+ if (! processing_template_decl
+ || (DECL_INITIAL (id)
+ && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
+ id = DECL_INITIAL (id);
}
else
- id = hack_identifier (id, token, yychar);
+ id = hack_identifier (id, token);
+
+ if (current_template_parms)
+ {
+ if (is_overloaded_fn (id))
+ {
+ tree t = build_min (LOOKUP_EXPR, unknown_type_node,
+ token, get_first_fn (id));
+ if (id != IDENTIFIER_NAMESPACE_VALUE (token))
+ TREE_OPERAND (t, 1) = error_mark_node;
+ id = t;
+ }
+ else if (! TREE_PERMANENT (id) || TREE_CODE (id) == PARM_DECL
+ || TREE_CODE (id) == USING_DECL)
+ id = build_min (LOOKUP_EXPR, TREE_TYPE (id), token, error_mark_node);
+ /* else just use the decl */
+ }
+
return id;
}
tree
+do_scoped_id (token, parsing)
+ tree token;
+ int parsing;
+{
+ tree id;
+ /* during parsing, this is ::name. Otherwise, it is black magic. */
+ if (parsing)
+ {
+ struct tree_binding _b;
+ id = binding_init (&_b);
+ if (!qualified_lookup_using_namespace (token, global_namespace, id, 0))
+ id = NULL_TREE;
+ else
+ id = BINDING_VALUE (id);
+ }
+ else
+ id = IDENTIFIER_GLOBAL_VALUE (token);
+ if (parsing && yychar == YYEMPTY)
+ yychar = yylex ();
+ if (! id)
+ {
+ if (processing_template_decl)
+ {
+ id = build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
+ LOOKUP_EXPR_GLOBAL (id) = 1;
+ return id;
+ }
+ if (parsing && (yychar == '(' || yychar == LEFT_RIGHT))
+ id = implicitly_declare (token);
+ else
+ {
+ if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node)
+ error ("undeclared variable `%s' (first use here)",
+ IDENTIFIER_POINTER (token));
+ id = error_mark_node;
+ /* Prevent repeated error messages. */
+ SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node);
+ }
+ }
+ else
+ {
+ if (TREE_CODE (id) == ADDR_EXPR)
+ mark_used (TREE_OPERAND (id, 0));
+ else if (TREE_CODE (id) != OVERLOAD)
+ mark_used (id);
+ }
+ if (TREE_CODE (id) == CONST_DECL && ! processing_template_decl)
+ {
+ /* XXX CHS - should we set TREE_USED of the constant? */
+ id = DECL_INITIAL (id);
+ /* This is to prevent an enum whose value is 0
+ from being considered a null pointer constant. */
+ id = build1 (NOP_EXPR, TREE_TYPE (id), id);
+ TREE_CONSTANT (id) = 1;
+ }
+
+ if (processing_template_decl)
+ {
+ if (is_overloaded_fn (id))
+ {
+ id = build_min (LOOKUP_EXPR, unknown_type_node,
+ token, get_first_fn (id));
+ LOOKUP_EXPR_GLOBAL (id) = 1;
+ }
+ /* else just use the decl */
+ }
+ return convert_from_reference (id);
+}
+
+tree
identifier_typedecl_value (node)
tree node;
{
@@ -3021,35 +3089,17 @@ identifier_typedecl_value (node)
}
do (IDENTIFIER_LOCAL_VALUE (node));
do (IDENTIFIER_CLASS_VALUE (node));
- do (IDENTIFIER_GLOBAL_VALUE (node));
+ do (IDENTIFIER_NAMESPACE_VALUE (node));
#undef do
/* Will this one ever happen? */
- if (TYPE_NAME (type))
- return TYPE_NAME (type);
+ if (TYPE_MAIN_DECL (type))
+ return TYPE_MAIN_DECL (type);
/* We used to do an internal error of 62 here, but instead we will
handle the return of a null appropriately in the callers. */
return NULL_TREE;
}
-struct try_type
-{
- tree *node_var;
- char unsigned_flag;
- char long_flag;
- char long_long_flag;
-};
-
-struct try_type type_sequence[] =
-{
- { &integer_type_node, 0, 0, 0},
- { &unsigned_type_node, 1, 0, 0},
- { &long_integer_type_node, 0, 1, 0},
- { &long_unsigned_type_node, 1, 1, 0},
- { &long_long_integer_type_node, 0, 1, 1},
- { &long_long_unsigned_type_node, 1, 1, 1}
-};
-
int
real_yylex ()
{
@@ -3103,21 +3153,17 @@ real_yylex ()
value = END_OF_SAVED_INPUT;
else if (linemode)
value = END_OF_LINE;
- else if (do_pending_expansions ())
- /* this will set yychar for us */
- return yychar;
else
value = ENDFILE;
break;
case '$':
- if (dollars_in_ident)
- {
- dollar_seen = 1;
- goto letter;
- }
- value = '$';
- goto done;
+ if (! dollars_in_ident)
+ error ("`$' in identifier");
+ else if (pedantic)
+ pedwarn ("`$' in identifier");
+ dollar_seen = 1;
+ goto letter;
case 'L':
/* Capital L may start a wide-string or wide-character constant. */
@@ -3166,15 +3212,21 @@ real_yylex ()
/* Make this run fast. We know that we are reading straight
from FINPUT in this case (since identifiers cannot straddle
input sources. */
- while (isalnum (c) || (c == '_') || c == '$')
+ while (ISALNUM (c) || (c == '_') || c == '$')
{
- if (c == '$' && ! dollars_in_ident)
- break;
+ if (c == '$')
+ {
+ if (! dollars_in_ident)
+ error ("`$' in identifier");
+ else if (pedantic)
+ pedwarn ("`$' in identifier");
+ }
+
if (p >= token_buffer + maxtoken)
p = extend_token_buffer (p);
*p++ = c;
- c = getc (finput);
+ c = getch ();
}
if (linemode && c == '\n')
@@ -3190,10 +3242,16 @@ real_yylex ()
*p++ = c;
c = getch ();
- while (isalnum (c) || (c == '_') || c == '$')
+ while (ISALNUM (c) || (c == '_') || c == '$')
{
- if (c == '$' && ! dollars_in_ident)
- break;
+ if (c == '$')
+ {
+ if (! dollars_in_ident)
+ error ("`$' in identifier");
+ else if (pedantic)
+ pedwarn ("`$' in identifier");
+ }
+
if (p >= token_buffer + maxtoken)
p = extend_token_buffer (p);
@@ -3213,7 +3271,7 @@ real_yylex ()
{
register struct resword *ptr;
- if (ptr = is_reserved_word (token_buffer, p - token_buffer))
+ if ((ptr = is_reserved_word (token_buffer, p - token_buffer)))
{
if (ptr->rid)
{
@@ -3226,7 +3284,7 @@ real_yylex ()
&& TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL)
looking_for_typename = 0;
else if (ptr->token == AGGR || ptr->token == ENUM)
- looking_for_typename = 1;
+ looking_for_typename = 2;
/* Check if this is a language-type declaration.
Just glimpse the next non-white character. */
@@ -3253,13 +3311,13 @@ real_yylex ()
switch (ptr->rid)
{
case RID_PUBLIC:
- yylval.itype = access_public;
+ yylval.ttype = access_public_node;
break;
case RID_PRIVATE:
- yylval.itype = access_private;
+ yylval.ttype = access_private_node;
break;
case RID_PROTECTED:
- yylval.itype = access_protected;
+ yylval.ttype = access_protected_node;
break;
default:
my_friendly_abort (63);
@@ -3313,14 +3371,6 @@ real_yylex ()
token_buffer[0] = '^';
token_buffer[1] = 0;
}
- else if (ptr->token == NAMESPACE)
- {
- static int warned;
- if (! warned)
- warning ("namespaces are mostly broken in this version of g++");
-
- warned = 1;
- }
value = (int) ptr->token;
}
@@ -3329,18 +3379,6 @@ real_yylex ()
/* If we did not find a keyword, look for an identifier
(or a typename). */
- if (strcmp ("catch", token_buffer) == 0
- || strcmp ("throw", token_buffer) == 0
- || strcmp ("try", token_buffer) == 0)
- {
- static int did_warn = 0;
- if (! did_warn && ! flag_handle_exceptions)
- {
- pedwarn ("`catch', `throw', and `try' are all C++ reserved words");
- did_warn = 1;
- }
- }
-
if (value == IDENTIFIER || value == TYPESPEC)
GNU_xref_ref (current_function_decl, token_buffer);
@@ -3365,30 +3403,6 @@ real_yylex ()
#endif
yylval.ttype = tmp;
-
- /* A user-invisible read-only initialized variable
- should be replaced by its value. We only handle strings
- since that's the only case used in C (and C++). */
- /* Note we go right after the local value for the identifier
- (e.g., __FUNCTION__ or __PRETTY_FUNCTION__). We used to
- call lookup_name, but that could result in an error about
- ambiguities. */
- tmp = IDENTIFIER_LOCAL_VALUE (yylval.ttype);
- if (tmp != NULL_TREE
- && TREE_CODE (tmp) == VAR_DECL
- && DECL_IGNORED_P (tmp)
- && TREE_READONLY (tmp)
- && DECL_INITIAL (tmp) != NULL_TREE
- && TREE_CODE (DECL_INITIAL (tmp)) == STRING_CST)
- {
- tree stringval = DECL_INITIAL (tmp);
-
- /* Copy the string value so that we won't clobber anything
- if we put something in the TREE_CHAIN of this one. */
- yylval.ttype = build_string (TREE_STRING_LENGTH (stringval),
- TREE_STRING_POINTER (stringval));
- value = STRING;
- }
}
if (value == NEW && ! global_bindings_p ())
{
@@ -3421,7 +3435,7 @@ real_yylex ()
}
error ("parse error at `..'");
}
- if (isdigit (c1))
+ if (ISDIGIT (c1))
{
put_back (c1);
goto resume_numerical_scan;
@@ -3435,7 +3449,7 @@ real_yylex ()
/* Optimize for most frequent case. */
{
register int c1 = getch ();
- if (! isalnum (c1) && c1 != '.')
+ if (! ISALNUM (c1) && c1 != '.')
{
/* Terminate string. */
token_buffer[0] = c;
@@ -3450,7 +3464,7 @@ real_yylex ()
}
put_back (c1);
}
- /* fall through... */
+ /* fall through... */
case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
resume_numerical_scan:
@@ -3473,12 +3487,12 @@ real_yylex ()
enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
= NOT_FLOAT;
- p = token_buffer;
- *p++ = c;
-
for (count = 0; count < TOTAL_PARTS; count++)
parts[count] = 0;
+ p = token_buffer;
+ *p++ = c;
+
if (c == '0')
{
*p++ = (c = getch ());
@@ -3500,18 +3514,25 @@ real_yylex ()
/* Read all the digits-and-decimal-points. */
while (c == '.'
- || (isalnum (c) && (c != 'l') && (c != 'L')
+ || (ISALNUM (c) && (c != 'l') && (c != 'L')
&& (c != 'u') && (c != 'U')
+ && c != 'i' && c != 'I' && c != 'j' && c != 'J'
&& (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
{
if (c == '.')
{
if (base == 16)
error ("floating constant may not be in radix 16");
- if (floatflag == AFTER_POINT)
+ if (floatflag == TOO_MANY_POINTS)
+ /* We have already emitted an error. Don't need another. */
+ ;
+ else if (floatflag == AFTER_POINT)
{
error ("malformed floating constant");
floatflag = TOO_MANY_POINTS;
+ /* Avoid another error from atof by forcing all characters
+ from here on to be ignored. */
+ p[-1] = '\0';
}
else
floatflag = AFTER_POINT;
@@ -3522,7 +3543,7 @@ real_yylex ()
only when it is followed by a digit.
Otherwise, unread the following non-digit
and use the '.' as a structural token. */
- if (p == token_buffer + 2 && !isdigit (c))
+ if (p == token_buffer + 2 && !ISDIGIT (c))
{
if (c == '.')
{
@@ -3547,7 +3568,7 @@ real_yylex ()
/* It is not a decimal point.
It should be a digit (perhaps a hex digit). */
- if (isdigit (c))
+ if (ISDIGIT (c))
{
c = c - '0';
}
@@ -3611,9 +3632,8 @@ real_yylex ()
if (floatflag != NOT_FLOAT)
{
tree type = double_type_node;
- char f_seen = 0;
- char l_seen = 0;
- int garbage_chars = 0;
+ int exceeds_double = 0;
+ int imag = 0;
REAL_VALUE_TYPE value;
jmp_buf handler;
@@ -3630,9 +3650,9 @@ real_yylex ()
*p++ = c;
c = getch ();
}
- if (! isdigit (c))
+ if (! ISDIGIT (c))
error ("floating constant exponent has no digits");
- while (isdigit (c))
+ while (ISDIGIT (c))
{
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
@@ -3652,76 +3672,117 @@ real_yylex ()
}
else
{
+ int fflag = 0, lflag = 0;
+ /* Copy token_buffer now, while it has just the number
+ and not the suffixes; once we add `f' or `i',
+ REAL_VALUE_ATOF may not work any more. */
+ char *copy = (char *) alloca (p - token_buffer + 1);
+ bcopy (token_buffer, copy, p - token_buffer + 1);
+
set_float_handler (handler);
- /* The second argument, machine_mode, of REAL_VALUE_ATOF
- tells the desired precision of the binary result of
- decimal-to-binary conversion. */
- /* Read the suffixes to choose a data type. */
- switch (c)
+ while (1)
{
- case 'f': case 'F':
- type = float_type_node;
- value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
- garbage_chars = -1;
- break;
+ int lose = 0;
- case 'l': case 'L':
- type = long_double_type_node;
- value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
- garbage_chars = -1;
- break;
+ /* Read the suffixes to choose a data type. */
+ switch (c)
+ {
+ case 'f': case 'F':
+ if (fflag)
+ error ("more than one `f' in numeric constant");
+ fflag = 1;
+ break;
+
+ case 'l': case 'L':
+ if (lflag)
+ error ("more than one `l' in numeric constant");
+ lflag = 1;
+ break;
+
+ case 'i': case 'I':
+ if (imag)
+ error ("more than one `i' or `j' in numeric constant");
+ else if (pedantic)
+ pedwarn ("ANSI C++ forbids imaginary numeric constants");
+ imag = 1;
+ break;
+
+ default:
+ lose = 1;
+ }
+
+ if (lose)
+ break;
+
+ if (p >= token_buffer + maxtoken - 3)
+ p = extend_token_buffer (p);
+ *p++ = c;
+ *p = 0;
+ c = getch ();
+ }
+
+ /* The second argument, machine_mode, of REAL_VALUE_ATOF
+ tells the desired precision of the binary result
+ of decimal-to-binary conversion. */
- default:
- value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
+ if (fflag)
+ {
+ if (lflag)
+ error ("both `f' and `l' in floating constant");
+
+ type = float_type_node;
+ value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+ /* A diagnostic is required here by some ANSI C testsuites.
+ This is not pedwarn, become some people don't want
+ an error for this. */
+ if (REAL_VALUE_ISINF (value) && pedantic)
+ warning ("floating point number exceeds range of `float'");
+ }
+ else if (lflag)
+ {
+ type = long_double_type_node;
+ value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+ if (REAL_VALUE_ISINF (value) && pedantic)
+ warning ("floating point number exceeds range of `long double'");
}
+ else
+ {
+ value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+ if (REAL_VALUE_ISINF (value) && pedantic)
+ warning ("floating point number exceeds range of `double'");
+ }
+
set_float_handler (NULL_PTR);
}
- if (pedantic
- && (REAL_VALUE_ISINF (value)
#ifdef ERANGE
- || (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- && errno == ERANGE
- /* ERANGE is also reported for underflow, so test the
- value to distinguish overflow from that. */
- && (REAL_VALUES_LESS (dconst1, value)
- || REAL_VALUES_LESS (value, dconstm1)))
-#endif
- ))
- {
- pedwarn ("floating point number exceeds range of `%s'",
- IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
- }
- /* Note: garbage_chars is -1 if first char is *not* garbage. */
- while (isalnum (c))
+ if (errno == ERANGE && pedantic)
{
- if (c == 'f' || c == 'F')
- {
- if (f_seen)
- error ("two `f's in floating constant");
- f_seen = 1;
- }
- if (c == 'l' || c == 'L')
+ /* ERANGE is also reported for underflow,
+ so test the value to distinguish overflow from that. */
+ if (REAL_VALUES_LESS (dconst1, value)
+ || REAL_VALUES_LESS (value, dconstm1))
{
- if (l_seen)
- error ("two `l's in floating constant");
- l_seen = 1;
+ pedwarn ("floating point number exceeds range of `%s'",
+ IDENTIFIER_POINTER (TYPE_IDENTIFIER (type)));
+ exceeds_double = 1;
}
- if (p >= token_buffer + maxtoken - 3)
- p = extend_token_buffer (p);
- *p++ = c;
- c = getch ();
- garbage_chars++;
}
+#endif
- if (garbage_chars > 0)
- error ("garbage at end of number");
+ /* If the result is not a number, assume it must have been
+ due to some error message above, so silently convert
+ it to a zero. */
+ if (REAL_VALUE_ISNAN (value))
+ value = dconst0;
/* Create a node with determined type and value. */
- yylval.ttype = build_real (type, value);
-
- put_back (c);
- *p = 0;
+ if (imag)
+ yylval.ttype = build_complex (NULL_TREE,
+ cp_convert (type, integer_zero_node),
+ build_real (type, value));
+ else
+ yylval.ttype = build_real (type, value);
}
else
{
@@ -3730,6 +3791,7 @@ real_yylex ()
int spec_unsigned = 0;
int spec_long = 0;
int spec_long_long = 0;
+ int spec_imag = 0;
int bytes, warn;
while (1)
@@ -3752,29 +3814,22 @@ real_yylex ()
}
spec_long = 1;
}
- else
+ else if (c == 'i' || c == 'j' || c == 'I' || c == 'J')
{
- if (isalnum (c))
- {
- error ("garbage at end of number");
- while (isalnum (c))
- {
- if (p >= token_buffer + maxtoken - 3)
- p = extend_token_buffer (p);
- *p++ = c;
- c = getch ();
- }
- }
- break;
+ if (spec_imag)
+ error ("more than one `i' or `j' in numeric constant");
+ else if (pedantic)
+ pedwarn ("ANSI C++ forbids imaginary numeric constants");
+ spec_imag = 1;
}
+ else
+ break;
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
*p++ = c;
c = getch ();
}
- put_back (c);
-
/* If the constant is not long long and it won't fit in an
unsigned long, or if the constant is long long and won't fit
in an unsigned long long, then warn that the constant is out
@@ -3813,145 +3868,52 @@ real_yylex ()
yylval.ttype = build_int_2 (low, high);
TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;
-#if 0
- /* Find the first allowable type that the value fits in. */
- type = 0;
- for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
- i++)
- if (!(spec_long && !type_sequence[i].long_flag)
- && !(spec_long_long && !type_sequence[i].long_long_flag)
- && !(spec_unsigned && !type_sequence[i].unsigned_flag)
- /* A hex or octal constant traditionally is unsigned. */
- && !(base != 10 && flag_traditional
- && !type_sequence[i].unsigned_flag)
- /* A decimal constant can't be unsigned int
- unless explicitly specified. */
- && !(base == 10 && !spec_unsigned
- && *type_sequence[i].node_var == unsigned_type_node))
- if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
- {
- type = *type_sequence[i].node_var;
- break;
- }
- if (flag_traditional && type == long_unsigned_type_node
- && !spec_unsigned)
- type = long_integer_type_node;
-
- if (type == 0)
- {
- type = long_long_integer_type_node;
- warning ("integer constant out of range");
- }
-
- /* Warn about some cases where the type of a given constant
- changes from traditional C to ANSI C. */
- if (warn_traditional)
- {
- tree other_type = 0;
-
- /* This computation is the same as the previous one
- except that flag_traditional is used backwards. */
- for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
- i++)
- if (!(spec_long && !type_sequence[i].long_flag)
- && !(spec_long_long && !type_sequence[i].long_long_flag)
- && !(spec_unsigned && !type_sequence[i].unsigned_flag)
- /* A hex or octal constant traditionally is unsigned. */
- && !(base != 10 && !flag_traditional
- && !type_sequence[i].unsigned_flag)
- /* A decimal constant can't be unsigned int
- unless explicitly specified. */
- && !(base == 10 && !spec_unsigned
- && *type_sequence[i].node_var == unsigned_type_node))
- if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
- {
- other_type = *type_sequence[i].node_var;
- break;
- }
- if (!flag_traditional && type == long_unsigned_type_node
- && !spec_unsigned)
- type = long_integer_type_node;
-
- if (other_type != 0 && other_type != type)
- {
- if (flag_traditional)
- warning ("type of integer constant would be different without -traditional");
- else
- warning ("type of integer constant would be different with -traditional");
- }
- }
-
-#else /* 1 */
+ /* Calculate the ANSI type. */
if (!spec_long && !spec_unsigned
- && !(flag_traditional && base != 10)
&& int_fits_type_p (yylval.ttype, integer_type_node))
- {
-#if 0
- if (warn_traditional && base != 10)
- warning ("small nondecimal constant becomes signed in ANSI C++");
-#endif
- type = integer_type_node;
- }
+ type = integer_type_node;
else if (!spec_long && (base != 10 || spec_unsigned)
&& int_fits_type_p (yylval.ttype, unsigned_type_node))
- {
- /* Nondecimal constants try unsigned even in traditional C. */
- type = unsigned_type_node;
- }
-
+ /* Nondecimal constants try unsigned even in traditional C. */
+ type = unsigned_type_node;
else if (!spec_unsigned && !spec_long_long
&& int_fits_type_p (yylval.ttype, long_integer_type_node))
type = long_integer_type_node;
-
- else if (! spec_long_long
- && int_fits_type_p (yylval.ttype,
- long_unsigned_type_node))
- {
-#if 0
- if (warn_traditional && !spec_unsigned)
- warning ("large integer constant becomes unsigned in ANSI C++");
-#endif
- if (flag_traditional && !spec_unsigned)
- type = long_integer_type_node;
- else
- type = long_unsigned_type_node;
- }
-
+ else if (! spec_long_long)
+ type = long_unsigned_type_node;
else if (! spec_unsigned
/* Verify value does not overflow into sign bit. */
&& TREE_INT_CST_HIGH (yylval.ttype) >= 0
&& int_fits_type_p (yylval.ttype,
long_long_integer_type_node))
type = long_long_integer_type_node;
+ else
+ type = long_long_unsigned_type_node;
- else if (int_fits_type_p (yylval.ttype,
- long_long_unsigned_type_node))
- {
-#if 0
- if (warn_traditional && !spec_unsigned)
- warning ("large nondecimal constant is unsigned in ANSI C++");
-#endif
+ if (!int_fits_type_p (yylval.ttype, type) && !warn)
+ pedwarn ("integer constant out of range");
- if (flag_traditional && !spec_unsigned)
- type = long_long_integer_type_node;
- else
- type = long_long_unsigned_type_node;
- }
+ if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
+ warning ("decimal integer constant is so large that it is unsigned");
- else
+ if (spec_imag)
{
- type = long_long_integer_type_node;
- warning ("integer constant out of range");
-
- if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
- warning ("decimal integer constant is so large that it is unsigned");
+ if (TYPE_PRECISION (type)
+ <= TYPE_PRECISION (integer_type_node))
+ yylval.ttype
+ = build_complex (NULL_TREE, integer_zero_node,
+ cp_convert (integer_type_node,
+ yylval.ttype));
+ else
+ error ("complex integer constant is too wide for `__complex int'");
}
-#endif
-
- TREE_TYPE (yylval.ttype) = type;
- *p = 0;
+ else
+ TREE_TYPE (yylval.ttype) = type;
}
+ put_back (c);
+ *p = 0;
+
value = CONSTANT; break;
}
@@ -3994,7 +3956,7 @@ real_yylex ()
&& (unsigned) c >= (1 << width))
warning ("escape sequence out of range for character");
#ifdef MAP_CHARACTER
- if (isprint (c))
+ if (ISPRINT (c))
c = MAP_CHARACTER (c);
#endif
}
@@ -4037,7 +3999,7 @@ real_yylex ()
num_chars = max_chars;
error ("character constant too long");
}
- else if (num_chars != 1 && ! flag_traditional)
+ else if (num_chars != 1 && warn_multichar)
warning ("multi-character character constant");
/* If char type is signed, sign-extend the constant. */
@@ -4125,7 +4087,7 @@ real_yylex ()
skipnewline:
c = getch ();
if (c == EOF) {
- error("Unterminated string");
+ error ("Unterminated string");
break;
}
}
@@ -4151,27 +4113,29 @@ real_yylex ()
bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);
#else
{
- union { long l; char c[sizeof (long)]; } u;
- int big_endian;
char *wp, *cp;
- /* Determine whether host is little or big endian. */
- u.l = 1;
- big_endian = u.c[sizeof (long) - 1];
- wp = widep + (big_endian ? WCHAR_BYTES - 1 : 0);
-
+ wp = widep + (BYTES_BIG_ENDIAN ? WCHAR_BYTES - 1 : 0);
bzero (widep, (p - token_buffer) * WCHAR_BYTES);
for (cp = token_buffer + 1; cp < p; cp++)
*wp = *cp, wp += WCHAR_BYTES;
len = p - token_buffer - 1;
}
#endif
+ if (processing_template_decl)
+ push_obstacks (&permanent_obstack, &permanent_obstack);
yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep);
+ if (processing_template_decl)
+ pop_obstacks ();
TREE_TYPE (yylval.ttype) = wchar_array_type_node;
}
else
{
+ if (processing_template_decl)
+ push_obstacks (&permanent_obstack, &permanent_obstack);
yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
+ if (processing_template_decl)
+ pop_obstacks ();
TREE_TYPE (yylval.ttype) = char_array_type_node;
}
@@ -4373,21 +4337,49 @@ real_yylex ()
done:
/* yylloc.last_line = lineno; */
#ifdef GATHER_STATISTICS
+#ifdef REDUCE_LENGTH
token_count[value] += 1;
#endif
+#endif
return value;
}
+int
+is_rid (t)
+ tree t;
+{
+ return !!is_reserved_word (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t));
+}
+
+#ifdef GATHER_STATISTICS
+/* The original for tree_node_kind is in the toplevel tree.c; changes there
+ need to be brought into here, unless this were actually put into a header
+ instead. */
+/* Statistics-gathering stuff. */
typedef enum
{
- d_kind, t_kind, s_kind, r_kind, e_kind, c_kind,
- id_kind, op_id_kind, perm_list_kind, temp_list_kind,
- vec_kind, x_kind, lang_decl, lang_type, all_kinds
+ d_kind,
+ t_kind,
+ b_kind,
+ s_kind,
+ r_kind,
+ e_kind,
+ c_kind,
+ id_kind,
+ op_id_kind,
+ perm_list_kind,
+ temp_list_kind,
+ vec_kind,
+ x_kind,
+ lang_decl,
+ lang_type,
+ all_kinds
} tree_node_kind;
+
extern int tree_node_counts[];
extern int tree_node_sizes[];
-extern char *tree_node_kind_names[];
+#endif
/* Place to save freed lang_decls which were allocated on the
permanent_obstack. @@ Not currently used. */
@@ -4428,24 +4420,11 @@ build_lang_decl (code, name, type)
== TREE_PERMANENT (t), 234);
DECL_MAIN_VARIANT (t) = t;
if (current_lang_name == lang_name_cplusplus)
- {
- DECL_LANGUAGE (t) = lang_cplusplus;
-#if 0
-#ifndef NO_AUTO_OVERLOAD
- if (code == FUNCTION_DECL && name != 0
- && ! (IDENTIFIER_LENGTH (name) == 4
- && IDENTIFIER_POINTER (name)[0] == 'm'
- && strcmp (IDENTIFIER_POINTER (name), "main") == 0)
- && ! (IDENTIFIER_LENGTH (name) > 10
- && IDENTIFIER_POINTER (name)[0] == '_'
- && IDENTIFIER_POINTER (name)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0))
- TREE_OVERLOADED (name) = 1;
-#endif
-#endif
- }
+ DECL_LANGUAGE (t) = lang_cplusplus;
else if (current_lang_name == lang_name_c)
DECL_LANGUAGE (t) = lang_c;
+ else if (current_lang_name == lang_name_java)
+ DECL_LANGUAGE (t) = lang_java;
else my_friendly_abort (64);
#if 0 /* not yet, should get fixed properly later */
@@ -4459,7 +4438,7 @@ build_lang_decl (code, name, type)
#endif
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_decl] += 1;
- tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
+ tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
#endif
return t;
@@ -4506,6 +4485,9 @@ copy_lang_decl (node)
int size;
int *pi;
+ if (! DECL_LANG_SPECIFIC (node))
+ return;
+
if (TREE_CODE (node) == FIELD_DECL)
size = sizeof (struct lang_decl_flags);
else
@@ -4538,10 +4520,9 @@ make_lang_type (code)
pi[--i] = 0;
TYPE_LANG_SPECIFIC (t) = (struct lang_type *) pi;
- CLASSTYPE_AS_LIST (t) = build_tree_list (NULL_TREE, t);
+ CLASSTYPE_AS_LIST (t) = build_expr_list (NULL_TREE, t);
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- CLASSTYPE_VBASE_SIZE (t) = integer_zero_node;
TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE,
NULL_TREE);
CLASSTYPE_BINFO_AS_LIST (t) = build_tree_list (NULL_TREE, TYPE_BINFO (t));
@@ -4553,40 +4534,13 @@ make_lang_type (code)
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_type] += 1;
- tree_node_sizes[(int)lang_type] += sizeof(struct lang_type);
+ tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
#endif
return t;
}
void
-copy_decl_lang_specific (decl)
- tree decl;
-{
- extern struct obstack *current_obstack, *saveable_obstack;
- register int *old = (int *)DECL_LANG_SPECIFIC (decl);
- struct obstack *obstack = current_obstack;
- register int i = sizeof (struct lang_decl) / sizeof (int);
- register int *pi;
-
- if (! TREE_PERMANENT (decl))
- obstack = saveable_obstack;
- else
- my_friendly_assert (obstack == &permanent_obstack, 237);
-
- pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
- while (i-- > 0)
- pi[i] = old[i];
-
- DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) pi;
-
-#ifdef GATHER_STATISTICS
- tree_node_counts[(int)lang_decl] += 1;
- tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
-#endif
-}
-
-void
dump_time_statistics ()
{
register tree prev = 0, decl, next;
@@ -4604,7 +4558,7 @@ dump_time_statistics ()
for (decl = filename_times; decl; decl = next)
{
next = IDENTIFIER_GLOBAL_VALUE (decl);
- IDENTIFIER_GLOBAL_VALUE (decl) = prev;
+ SET_IDENTIFIER_GLOBAL_VALUE (decl, prev);
prev = decl;
}
@@ -4622,32 +4576,6 @@ compiler_error (s, v, v2)
sprintf (buf, s, v, v2);
error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
}
-
-void
-compiler_error_with_decl (decl, s)
- tree decl;
- char *s;
-{
- char *name;
- count_error (0);
-
- report_error_function (0);
-
- if (TREE_CODE (decl) == PARM_DECL)
- fprintf (stderr, "%s:%d: ",
- DECL_SOURCE_FILE (DECL_CONTEXT (decl)),
- DECL_SOURCE_LINE (DECL_CONTEXT (decl)));
- else
- fprintf (stderr, "%s:%d: ",
- DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
-
- name = lang_printable_name (decl);
- if (name)
- fprintf (stderr, s, name);
- else
- fprintf (stderr, s, "((anonymous))");
- fprintf (stderr, " (compiler error)\n");
-}
void
yyerror (string)
@@ -4679,6 +4607,182 @@ yyerror (string)
error (buf, token_buffer);
}
+static int
+handle_cp_pragma (pname)
+ char *pname;
+{
+ register int token;
+
+ if (! strcmp (pname, "vtable"))
+ {
+ extern tree pending_vtables;
+
+ /* More follows: it must be a string constant (class name). */
+ token = real_yylex ();
+ if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid #pragma vtable");
+ return -1;
+ }
+
+ if (write_virtuals != 2)
+ {
+ warning ("use `+e2' option to enable #pragma vtable");
+ return -1;
+ }
+ pending_vtables
+ = perm_tree_cons (NULL_TREE,
+ get_identifier (TREE_STRING_POINTER (yylval.ttype)),
+ pending_vtables);
+ token = real_yylex ();
+ if (token != END_OF_LINE)
+ warning ("trailing characters ignored");
+ return 1;
+ }
+ else if (! strcmp (pname, "unit"))
+ {
+ /* More follows: it must be a string constant (unit name). */
+ token = real_yylex ();
+ if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid #pragma unit");
+ return -1;
+ }
+ token = real_yylex ();
+ if (token != END_OF_LINE)
+ warning ("trailing characters ignored");
+ return 1;
+ }
+ else if (! strcmp (pname, "interface"))
+ {
+ tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+ char *main_filename = input_filename;
+
+ main_filename = file_name_nondirectory (main_filename);
+
+ token = real_yylex ();
+
+ if (token != END_OF_LINE)
+ {
+ if (token != STRING
+ || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid `#pragma interface'");
+ return -1;
+ }
+ main_filename = TREE_STRING_POINTER (yylval.ttype);
+ token = real_yylex ();
+ }
+
+ if (token != END_OF_LINE)
+ warning ("garbage after `#pragma interface' ignored");
+
+#ifndef NO_LINKAGE_HEURISTICS
+ write_virtuals = 3;
+
+ if (impl_file_chain == 0)
+ {
+ /* If this is zero at this point, then we are
+ auto-implementing. */
+ if (main_input_filename == 0)
+ main_input_filename = input_filename;
+
+#ifdef AUTO_IMPLEMENT
+ filename = file_name_nondirectory (main_input_filename);
+ fi = get_time_identifier (filename);
+ fi = IDENTIFIER_CLASS_VALUE (fi);
+ TREE_INT_CST_LOW (fi) = 0;
+ TREE_INT_CST_HIGH (fi) = 1;
+ /* Get default. */
+ impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
+ impl_file_chain->filename = filename;
+ impl_file_chain->next = 0;
+#endif
+ }
+
+ interface_only = interface_strcmp (main_filename);
+ interface_unknown = 0;
+ TREE_INT_CST_LOW (fileinfo) = interface_only;
+ TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
+#endif /* NO_LINKAGE_HEURISTICS */
+
+ return 1;
+ }
+ else if (! strcmp (pname, "implementation"))
+ {
+ tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+ char *main_filename = main_input_filename ? main_input_filename : input_filename;
+
+ main_filename = file_name_nondirectory (main_filename);
+ token = real_yylex ();
+ if (token != END_OF_LINE)
+ {
+ if (token != STRING
+ || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid `#pragma implementation'");
+ return -1;
+ }
+ main_filename = TREE_STRING_POINTER (yylval.ttype);
+ token = real_yylex ();
+ }
+
+ if (token != END_OF_LINE)
+ warning ("garbage after `#pragma implementation' ignored");
+
+#ifndef NO_LINKAGE_HEURISTICS
+ if (write_virtuals == 3)
+ {
+ struct impl_files *ifiles = impl_file_chain;
+ while (ifiles)
+ {
+ if (! strcmp (ifiles->filename, main_filename))
+ break;
+ ifiles = ifiles->next;
+ }
+ if (ifiles == 0)
+ {
+ ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files));
+ ifiles->filename = main_filename;
+ ifiles->next = impl_file_chain;
+ impl_file_chain = ifiles;
+ }
+ }
+ else if ((main_input_filename != 0
+ && ! strcmp (main_input_filename, input_filename))
+ || ! strcmp (input_filename, main_filename))
+ {
+ write_virtuals = 3;
+ if (impl_file_chain == 0)
+ {
+ impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files));
+ impl_file_chain->filename = main_filename;
+ impl_file_chain->next = 0;
+ }
+ }
+ else
+ error ("`#pragma implementation' can only appear at top-level");
+ interface_only = 0;
+#if 1
+ /* We make this non-zero so that we infer decl linkage
+ in the impl file only for variables first declared
+ in the interface file. */
+ interface_unknown = 1;
+#else
+ /* We make this zero so that templates in the impl
+ file will be emitted properly. */
+ interface_unknown = 0;
+#endif
+ TREE_INT_CST_LOW (fileinfo) = interface_only;
+ TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
+#endif /* NO_LINKAGE_HEURISTICS */
+
+ return 1;
+ }
+
+ return 0;
+}
+
#ifdef HANDLE_SYSV_PRAGMA
/* Handle a #pragma directive. INPUT is the current input stream,
@@ -4688,11 +4792,13 @@ yyerror (string)
/* This function has to be in this file, in order to get at
the token types. */
-handle_sysv_pragma ()
+static int
+handle_sysv_pragma (token)
+ register int token;
{
for (;;)
{
- switch (yylex ())
+ switch (token)
{
case IDENTIFIER:
case TYPENAME:
@@ -4717,14 +4823,11 @@ handle_sysv_pragma ()
handle_pragma_token (")", NULL_TREE);
break;
case END_OF_LINE:
- handle_pragma_token (NULL_PTR, NULL_TREE);
- return;
default:
handle_pragma_token (NULL_PTR, NULL_TREE);
- while (yylex () != END_OF_LINE)
- /* continue */;
- return;
+ return 1;
}
+ token = real_yylex ();
}
}
#endif /* HANDLE_SYSV_PRAGMA */
diff --git a/contrib/gcc/cp/lex.h b/contrib/gcc/cp/lex.h
index 1cf5687..8df6b76 100644
--- a/contrib/gcc/cp/lex.h
+++ b/contrib/gcc/cp/lex.h
@@ -62,8 +62,10 @@ enum rid
RID_SIGNED,
RID_AUTO,
RID_MUTABLE,
+ RID_COMPLEX,
- /* This is where grokdeclarator ends its search when setting the specbits. */
+ /* This is where grokdeclarator ends its search when setting the
+ specbits. */
RID_PUBLIC,
RID_PRIVATE,
@@ -71,22 +73,23 @@ enum rid
RID_EXCEPTION,
RID_TEMPLATE,
RID_SIGNATURE,
+ RID_NULL,
/* Before adding enough to get up to 64, the RIDBIT_* macros
- will have to be changed a little. */
+ will have to be changed a little. */
RID_MAX
};
#define NORID RID_UNUSED
#define RID_FIRST_MODIFIER RID_EXTERN
-#define RID_LAST_MODIFIER RID_MUTABLE
+#define RID_LAST_MODIFIER RID_COMPLEX
/* The type that can represent all values of RIDBIT. */
-/* We assume that we can stick in at least 32 bits into this. */
+/* We assume that we can stick in at least 32 bits into this. */
typedef struct { unsigned long idata[2]; }
RID_BIT_TYPE;
-/* Be careful, all these modify N twice. */
+/* Be careful, all these modify N twice. */
#define RIDBIT_SETP(N, V) (((unsigned long)1 << (int) ((N)%32)) \
& (V).idata[(N)/32])
#define RIDBIT_NOTSETP(NN, VV) (! RIDBIT_SETP (NN, VV))
@@ -129,7 +132,4 @@ extern tree got_object;
Positive is push count, negative is pop count. */
extern int pending_lang_change;
-extern tree make_pointer_declarator (), make_reference_declarator ();
-extern void reinit_parse_for_function ();
-extern void reinit_parse_for_method ();
-extern int yylex ();
+extern int yylex PROTO((void));
diff --git a/contrib/gcc/cp/method.c b/contrib/gcc/cp/method.c
index a0e1527..29b31c4 100644
--- a/contrib/gcc/cp/method.c
+++ b/contrib/gcc/cp/method.c
@@ -1,9 +1,9 @@
/* Handle the hair of processing (but not expanding) inline functions.
Also manage function and variable name overloading.
- Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
- This file is part of GNU CC.
+This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,28 +21,33 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#ifndef __GNUC__
+#define __inline
+#endif
+
#ifndef PARM_CAN_BE_ARRAY_TYPE
#define PARM_CAN_BE_ARRAY_TYPE 1
#endif
/* Handle method declarations. */
-#include <stdio.h>
#include "config.h"
+#include "system.h"
#include "tree.h"
#include "cp-tree.h"
-#include "class.h"
#include "obstack.h"
-#include <ctype.h>
#include "rtl.h"
#include "expr.h"
#include "output.h"
#include "hard-reg-set.h"
#include "flags.h"
+#include "toplev.h"
/* TREE_LIST of the current inline functions that need to be
processed. */
struct pending_inline *pending_inlines;
+int static_labelno;
+
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -50,6 +55,38 @@ struct pending_inline *pending_inlines;
static struct obstack scratch_obstack;
static char *scratch_firstobj;
+static void icat PROTO((HOST_WIDE_INT));
+static void dicat PROTO((HOST_WIDE_INT, HOST_WIDE_INT));
+static void flush_repeats PROTO((int, tree));
+static void build_overload_identifier PROTO((tree));
+static void build_overload_nested_name PROTO((tree));
+static void build_overload_int PROTO((tree, int));
+static void build_overload_identifier PROTO((tree));
+static void build_qualified_name PROTO((tree));
+static void build_overload_value PROTO((tree, tree, int));
+static void issue_nrepeats PROTO((int, tree));
+static char *build_mangled_name PROTO((tree,int,int));
+static void process_modifiers PROTO((tree));
+static void process_overload_item PROTO((tree,int));
+static void do_build_assign_ref PROTO((tree));
+static void do_build_copy_constructor PROTO((tree));
+static tree largest_union_member PROTO((tree));
+static tree build_decl_overload_real PROTO((tree, tree, tree, tree,
+ tree, int));
+static void build_template_template_parm_names PROTO((tree));
+static void build_template_parm_names PROTO((tree, tree));
+static void build_underscore_int PROTO((int));
+static void start_squangling PROTO((void));
+static void end_squangling PROTO((void));
+static int check_ktype PROTO((tree, int));
+static int issue_ktype PROTO((tree));
+static void build_overload_scope_ref PROTO((tree));
+static void build_mangled_template_parm_index PROTO((char *, tree));
+static int is_back_referenceable_type PROTO((tree));
+static int check_btype PROTO((tree));
+static void build_mangled_name_for_type PROTO((tree));
+static void build_mangled_name_for_type_with_Gcode PROTO((tree, int));
+
# define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
# define OB_PUTC2(C1,C2) \
@@ -62,10 +99,6 @@ static char *scratch_firstobj;
# define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
# define OB_LAST() (obstack_next_free (&scratch_obstack)[-1])
-#ifdef NO_AUTO_OVERLOAD
-int is_overloaded ();
-#endif
-
void
init_method ()
{
@@ -91,10 +124,12 @@ do_inline_function_hair (type, friend_list)
if (method && TREE_CODE (method) == TREE_VEC)
{
- if (TREE_VEC_ELT (method, 0))
+ if (TREE_VEC_ELT (method, 1))
+ method = TREE_VEC_ELT (method, 1);
+ else if (TREE_VEC_ELT (method, 0))
method = TREE_VEC_ELT (method, 0);
else
- method = TREE_VEC_ELT (method, 1);
+ method = TREE_VEC_ELT (method, 2);
}
while (method)
@@ -112,11 +147,6 @@ do_inline_function_hair (type, friend_list)
DECL_CONTEXT (args) = method;
args = TREE_CHAIN (args);
}
-
- /* Allow this decl to be seen in global scope. Don't do this for
- local class methods, though. */
- if (! current_function_decl)
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (method)) = method;
}
method = TREE_CHAIN (method);
}
@@ -135,157 +165,142 @@ do_inline_function_hair (type, friend_list)
DECL_CONTEXT (args) = fndecl;
args = TREE_CHAIN (args);
}
-
- /* Allow this decl to be seen in global scope */
- if (! current_function_decl)
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (fndecl)) = fndecl;
}
friend_list = TREE_CHAIN (friend_list);
}
}
-/* Report an argument type mismatch between the best declared function
- we could find and the current argument list that we have. */
-void
-report_type_mismatch (cp, parmtypes, name_kind)
- struct candidate *cp;
- tree parmtypes;
- char *name_kind;
-{
- int i = cp->u.bad_arg;
- tree ttf, tta;
- char *tmp_firstobj;
-
- switch (i)
- {
- case -4:
- my_friendly_assert (TREE_CODE (cp->function) == TEMPLATE_DECL, 240);
- cp_error ("type unification failed for function template `%#D'",
- cp->function);
- return;
-
- case -2:
- cp_error ("too few arguments for %s `%#D'", name_kind, cp->function);
- return;
- case -1:
- cp_error ("too many arguments for %s `%#D'", name_kind, cp->function);
- return;
- case 0:
- 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));
- tta = parmtypes;
-
- while (i-- > 0)
- {
- ttf = TREE_CHAIN (ttf);
- tta = TREE_CHAIN (tta);
- }
+/* Here is where overload code starts. */
- OB_INIT ();
- OB_PUTS ("bad argument ");
- sprintf (digit_buffer, "%d", cp->u.bad_arg
- - (TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE)
- + 1);
- OB_PUTCP (digit_buffer);
-
- OB_PUTS (" for function `");
- OB_PUTCP (decl_as_string (cp->function, 1));
- OB_PUTS ("' (type was ");
-
- /* Reset `i' so that type printing routines do the right thing. */
- if (tta)
- {
- enum tree_code code = TREE_CODE (TREE_TYPE (TREE_VALUE (tta)));
- if (code == ERROR_MARK)
- OB_PUTS ("(failed type instantiation)");
- else
- {
- i = (code == FUNCTION_TYPE || code == METHOD_TYPE);
- OB_PUTCP (type_as_string (TREE_TYPE (TREE_VALUE (tta)), 1));
- }
- }
- else OB_PUTS ("void");
- OB_PUTC (')');
- OB_FINISH ();
+/* type tables for K and B type compression */
+static tree *btypelist = NULL;
+static tree *ktypelist = NULL;
+static int maxbsize = 0;
+static int maxksize = 0;
- tmp_firstobj = (char *)alloca (obstack_object_size (&scratch_obstack));
- bcopy (obstack_base (&scratch_obstack), tmp_firstobj,
- obstack_object_size (&scratch_obstack));
- error (tmp_firstobj);
-}
-
-/* Here is where overload code starts. */
+/* number of each type seen */
+static int maxbtype = 0;
+static int maxktype = 0;
-/* Array of types seen so far in top-level call to `build_overload_name'.
+/* Array of types seen so far in top-level call to `build_mangled_name'.
Allocated and deallocated by caller. */
-static tree *typevec;
-
-/* Number of types interned by `build_overload_name' so far. */
-static int maxtype;
+static tree *typevec = NULL;
+static int typevec_size;
-/* Number of occurrences of last type seen. */
-static int nrepeats;
+/* Number of types interned by `build_mangled_name' so far. */
+static int maxtype = 0;
/* Nonzero if we should not try folding parameter types. */
static int nofold;
-#define ALLOCATE_TYPEVEC(PARMTYPES) \
- do { maxtype = 0, nrepeats = 0; \
- typevec = (tree *)alloca (list_length (PARMTYPES) * sizeof (tree)); } while (0)
+/* This appears to be set to true if an underscore is required to be
+ comcatenated before another number can be outputed. */
+static int numeric_output_need_bar;
-#define DEALLOCATE_TYPEVEC(PARMTYPES) \
- do { tree t = (PARMTYPES); \
- while (t) { TREE_USED (TREE_VALUE (t)) = 0; t = TREE_CHAIN (t); } \
- } while (0)
+static __inline void
+start_squangling ()
+{
+ if (flag_do_squangling)
+ {
+ nofold = 0;
+ maxbtype = 0;
+ maxktype = 0;
+ maxbsize = 50;
+ maxksize = 50;
+ btypelist = (tree *)xmalloc (sizeof (tree) * maxbsize);
+ ktypelist = (tree *)xmalloc (sizeof (tree) * maxksize);
+ }
+}
+
+static __inline void
+end_squangling ()
+{
+ if (flag_do_squangling)
+ {
+ if (ktypelist)
+ free (ktypelist);
+ if (btypelist)
+ free (btypelist);
+ maxbsize = 0;
+ maxksize = 0;
+ maxbtype = 0;
+ maxktype = 0;
+ ktypelist = NULL;
+ btypelist = NULL;
+ }
+}
/* Code to concatenate an asciified integer to a string. */
-static
-#ifdef __GNUC__
-__inline
-#endif
-void
+
+static __inline void
icat (i)
- int i;
+ HOST_WIDE_INT i;
{
+ unsigned HOST_WIDE_INT ui;
+
/* Handle this case first, to go really quickly. For many common values,
- the result of i/10 below is 1. */
+ the result of ui/10 below is 1. */
if (i == 1)
{
OB_PUTC ('1');
return;
}
- if (i < 0)
+ if (i >= 0)
+ ui = i;
+ else
{
OB_PUTC ('m');
- i = -i;
+ ui = -i;
+ }
+
+ if (ui >= 10)
+ icat (ui / 10);
+
+ OB_PUTC ('0' + (ui % 10));
+}
+
+static void
+dicat (lo, hi)
+ HOST_WIDE_INT lo, hi;
+{
+ unsigned HOST_WIDE_INT ulo, uhi, qlo, qhi;
+
+ if (hi >= 0)
+ {
+ uhi = hi;
+ ulo = lo;
}
- if (i < 10)
- OB_PUTC ('0' + i);
else
{
- icat (i / 10);
- OB_PUTC ('0' + (i % 10));
+ uhi = (lo == 0 ? -hi : -hi-1);
+ ulo = -lo;
}
+ if (uhi == 0
+ && ulo < ((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)))
+ {
+ icat (ulo);
+ return;
+ }
+ /* Divide 2^HOST_WIDE_INT*uhi+ulo by 10. */
+ qhi = uhi / 10;
+ uhi = uhi % 10;
+ qlo = uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) / 5);
+ qlo += ulo / 10;
+ ulo = ulo % 10;
+ ulo += uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) % 5)
+ * 2;
+ qlo += ulo / 10;
+ ulo = ulo % 10;
+ /* Quotient is 2^HOST_WIDE_INT*qhi+qlo, remainder is ulo. */
+ dicat (qlo, qhi);
+ OB_PUTC ('0' + ulo);
}
-static
-#ifdef __GNUC__
-__inline
-#endif
-void
-flush_repeats (type)
+static __inline void
+flush_repeats (nrepeats, type)
+ int nrepeats;
tree type;
{
int tindex = 0;
@@ -302,86 +317,327 @@ flush_repeats (type)
}
else
OB_PUTC ('T');
- nrepeats = 0;
icat (tindex);
if (tindex > 9)
OB_PUTC ('_');
}
-static int numeric_output_need_bar;
-static void build_overload_identifier ();
+/* Returns nonzero iff this is a type to which we will want to make
+ back-references (using the `B' code). */
+
+int
+is_back_referenceable_type (type)
+ tree type;
+{
+ if (btypelist == NULL)
+ /* We're not generating any back-references. */
+ return 0;
+
+ switch (TREE_CODE (type))
+ {
+ case INTEGER_TYPE:
+ case REAL_TYPE:
+ case VOID_TYPE:
+ case BOOLEAN_TYPE:
+ /* These types have single-character manglings, so there's no
+ point in generating back-references. */
+ return 0;
+
+ case TEMPLATE_TYPE_PARM:
+ /* It would be a bit complex to demangle signatures correctly if
+ we generated back-references to these, and the manglings of
+ type parameters are short. */
+ return 0;
+
+ default:
+ return 1;
+ }
+}
+
+/* Issue the squangling code indicating NREPEATS repetitions of TYPE,
+ which was the last parameter type output. */
+
+static void
+issue_nrepeats (nrepeats, type)
+ int nrepeats;
+ tree type;
+{
+ if (nrepeats == 1 && !is_back_referenceable_type (type))
+ /* For types whose manglings are short, don't bother using the
+ repetition code if there's only one repetition, since the
+ repetition code will be about as long as the ordinary mangling. */
+ build_mangled_name_for_type (type);
+ else
+ {
+ OB_PUTC ('n');
+ icat (nrepeats);
+ if (nrepeats > 9)
+ OB_PUTC ('_');
+ }
+}
+
+/* Check to see if a tree node has been entered into the Kcode typelist */
+/* if not, add it. Return -1 if it isn't found, otherwise return the index */
+static int
+check_ktype (node, add)
+ tree node;
+ int add;
+{
+ int x;
+ tree localnode = node;
+
+ if (ktypelist == NULL)
+ return -1;
+
+ if (TREE_CODE (node) == TYPE_DECL)
+ localnode = TREE_TYPE (node);
+
+ for (x=0; x < maxktype; x++)
+ {
+ if (localnode == ktypelist[x])
+ return x ;
+ }
+ /* Didn't find it, so add it here */
+ if (add)
+ {
+ if (maxksize <= maxktype)
+ {
+ maxksize = maxksize* 3 / 2;
+ ktypelist = (tree *)xrealloc (ktypelist, sizeof (tree) * maxksize);
+ }
+ ktypelist[maxktype++] = localnode;
+ }
+ return -1;
+}
+
+
+static __inline int
+issue_ktype (decl)
+ tree decl;
+{
+ int kindex;
+ kindex = check_ktype (decl, FALSE);
+ if (kindex != -1)
+ {
+ OB_PUTC ('K');
+ icat (kindex);
+ if (kindex > 9)
+ OB_PUTC ('_');
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Build a representation for DECL, which may be an entity not at
+ global scope. If so, a marker indicating that the name is
+ qualified has already been output, but the qualifying context has
+ not. */
static void
build_overload_nested_name (decl)
tree decl;
{
- if (DECL_CONTEXT (decl))
+ tree context;
+
+ if (ktypelist && issue_ktype (decl))
+ return;
+
+ if (decl == global_namespace)
+ return;
+
+ context = CP_DECL_CONTEXT (decl);
+
+ /* try to issue a K type, and if we can't continue the normal path */
+ if (!(ktypelist && issue_ktype (context)))
+ {
+ /* For a template type parameter, we want to output an 'Xn'
+ rather than 'T' or some such. */
+ if (TREE_CODE (context) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM)
+ build_mangled_name_for_type (context);
+ else
{
- tree context = DECL_CONTEXT (decl);
if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
- context = TYPE_MAIN_DECL (context);
+ context = TYPE_NAME (context);
build_overload_nested_name (context);
}
+ }
if (TREE_CODE (decl) == FUNCTION_DECL)
{
tree name = DECL_ASSEMBLER_NAME (decl);
char *label;
- extern int var_labelno;
- ASM_FORMAT_PRIVATE_NAME (label, IDENTIFIER_POINTER (name), var_labelno);
- var_labelno++;
+ ASM_FORMAT_PRIVATE_NAME (label, IDENTIFIER_POINTER (name), static_labelno);
+ static_labelno++;
if (numeric_output_need_bar)
- {
- OB_PUTC ('_');
- numeric_output_need_bar = 0;
- }
+ OB_PUTC ('_');
icat (strlen (label));
OB_PUTCP (label);
+ numeric_output_need_bar = 1;
}
+ else if (TREE_CODE (decl) == NAMESPACE_DECL)
+ build_overload_identifier (DECL_NAME (decl));
else /* TYPE_DECL */
- {
- tree name = DECL_NAME (decl);
- build_overload_identifier (name);
- }
+ build_overload_identifier (decl);
}
-/* Encoding for an INTEGER_CST value. */
+/* Output the decimal representation of I. If I > 9, the decimal
+ representation is preceeded and followed by an underscore. */
+
static void
-build_overload_int (value)
+build_underscore_int (i)
+ int i;
+{
+ if (i > 9)
+ OB_PUTC ('_');
+ icat (i);
+ if (i > 9)
+ OB_PUTC ('_');
+}
+
+static void
+build_overload_scope_ref (value)
tree value;
{
- my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243);
- if (TYPE_PRECISION (value) == 2 * HOST_BITS_PER_WIDE_INT)
+ OB_PUTC2 ('Q', '2');
+ numeric_output_need_bar = 0;
+ build_mangled_name_for_type (TREE_OPERAND (value, 0));
+ build_overload_identifier (TREE_OPERAND (value, 1));
+}
+
+/* Encoding for an INTEGER_CST value. */
+
+static void
+build_overload_int (value, in_template)
+ tree value;
+ int in_template;
+{
+ if (in_template && TREE_CODE (value) != INTEGER_CST)
{
- if (tree_int_cst_lt (value, integer_zero_node))
+ if (TREE_CODE (value) == SCOPE_REF)
+ {
+ build_overload_scope_ref (value);
+ return;
+ }
+
+ OB_PUTC ('E');
+ numeric_output_need_bar = 0;
+
+ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (value))))
+ {
+ int i;
+ int operands = tree_code_length[(int) TREE_CODE (value)];
+ tree id;
+ char* name;
+
+ id = ansi_opname [(int) TREE_CODE (value)];
+ my_friendly_assert (id != NULL_TREE, 0);
+ name = IDENTIFIER_POINTER (id);
+ if (name[0] != '_' || name[1] != '_')
+ /* On some erroneous inputs, we can get here with VALUE a
+ LOOKUP_EXPR. In that case, the NAME will be the
+ identifier for "<invalid operator>". We must survive
+ this routine in order to issue a sensible error
+ message, so we fall through to the case below. */
+ goto bad_value;
+
+ for (i = 0; i < operands; ++i)
+ {
+ tree operand;
+ enum tree_code tc;
+
+ /* We just outputted either the `E' or the name of the
+ operator. */
+ numeric_output_need_bar = 0;
+
+ if (i != 0)
+ /* Skip the leading underscores. */
+ OB_PUTCP (name + 2);
+
+ operand = TREE_OPERAND (value, i);
+ tc = TREE_CODE (operand);
+
+ if (TREE_CODE_CLASS (tc) == 't')
+ /* We can get here with sizeof, e.g.:
+
+ template <class T> void f(A<sizeof(T)>); */
+ build_mangled_name_for_type (operand);
+ else if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc)))
+ build_overload_int (operand, in_template);
+ else
+ build_overload_value (TREE_TYPE (operand),
+ operand,
+ in_template);
+ }
+ }
+ else
{
- OB_PUTC ('m');
- value = build_int_2 (~ TREE_INT_CST_LOW (value),
- - TREE_INT_CST_HIGH (value));
+ /* We don't ever want this output, but it's
+ inconvenient not to be able to build the string.
+ This should cause assembler errors we'll notice. */
+
+ static int n;
+ bad_value:
+ sprintf (digit_buffer, " *%d", n++);
+ OB_PUTCP (digit_buffer);
}
+
+ OB_PUTC ('W');
+ numeric_output_need_bar = 0;
+ return;
+ }
+
+ my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243);
+ if (TYPE_PRECISION (TREE_TYPE (value)) == 2 * HOST_BITS_PER_WIDE_INT)
+ {
if (TREE_INT_CST_HIGH (value)
!= (TREE_INT_CST_LOW (value) >> (HOST_BITS_PER_WIDE_INT - 1)))
{
/* need to print a DImode value in decimal */
- sorry ("conversion of long long as PT parameter");
+ dicat (TREE_INT_CST_LOW (value), TREE_INT_CST_HIGH (value));
+ numeric_output_need_bar = 1;
+ return;
}
/* else fall through to print in smaller mode */
}
/* Wordsize or smaller */
icat (TREE_INT_CST_LOW (value));
+ numeric_output_need_bar = 1;
}
+
+/* Output S followed by a representation of the TEMPLATE_PARM_INDEX
+ supplied in INDEX. */
+
+static void
+build_mangled_template_parm_index (s, index)
+ char* s;
+ tree index;
+{
+ OB_PUTCP (s);
+ build_underscore_int (TEMPLATE_PARM_IDX (index));
+ /* We use the LEVEL, not the ORIG_LEVEL, because the mangling is a
+ representation of the function from the point of view of its
+ type. */
+ build_underscore_int (TEMPLATE_PARM_LEVEL (index));
+}
+
+
static void
-build_overload_value (type, value)
+build_overload_value (type, value, in_template)
tree type, value;
+ int in_template;
{
while (TREE_CODE (value) == NON_LVALUE_EXPR
|| TREE_CODE (value) == NOP_EXPR)
value = TREE_OPERAND (value, 0);
- my_friendly_assert (TREE_CODE (type) == PARM_DECL, 242);
- type = TREE_TYPE (type);
+
+ if (TREE_CODE (type) == PARM_DECL)
+ type = TREE_TYPE (type);
+
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0);
if (numeric_output_need_bar)
{
@@ -389,6 +645,12 @@ build_overload_value (type, value)
numeric_output_need_bar = 0;
}
+ if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
+ {
+ build_mangled_template_parm_index ("Y", value);
+ return;
+ }
+
if (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
{
@@ -411,65 +673,82 @@ build_overload_value (type, value)
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
{
- build_overload_int (value);
- numeric_output_need_bar = 1;
+ build_overload_int (value, in_template);
return;
}
-#ifndef REAL_IS_NOT_DOUBLE
case REAL_TYPE:
{
REAL_VALUE_TYPE val;
char *bufp = digit_buffer;
- extern char *index ();
+
+ pedwarn ("ANSI C++ forbids floating-point template arguments");
my_friendly_assert (TREE_CODE (value) == REAL_CST, 244);
val = TREE_REAL_CST (value);
- if (val < 0)
+ if (REAL_VALUE_ISNAN (val))
{
- val = -val;
- *bufp++ = 'm';
+ sprintf (bufp, "NaN");
}
- sprintf (bufp, "%e", val);
- bufp = (char *) index (bufp, 'e');
- if (!bufp)
- strcat (digit_buffer, "e0");
else
{
- char *p;
- bufp++;
- if (*bufp == '-')
+ if (REAL_VALUE_NEGATIVE (val))
{
+ val = REAL_VALUE_NEGATE (val);
*bufp++ = 'm';
}
- p = bufp;
- if (*p == '+')
- p++;
- while (*p == '0')
- p++;
- if (*p == 0)
+ if (REAL_VALUE_ISINF (val))
{
- *bufp++ = '0';
- *bufp = 0;
+ sprintf (bufp, "Infinity");
}
- else if (p != bufp)
+ else
{
- while (*p)
- *bufp++ = *p++;
- *bufp = 0;
+ REAL_VALUE_TO_DECIMAL (val, "%.20e", bufp);
+ bufp = (char *) index (bufp, 'e');
+ if (!bufp)
+ strcat (digit_buffer, "e0");
+ else
+ {
+ char *p;
+ bufp++;
+ if (*bufp == '-')
+ {
+ *bufp++ = 'm';
+ }
+ p = bufp;
+ if (*p == '+')
+ p++;
+ while (*p == '0')
+ p++;
+ if (*p == 0)
+ {
+ *bufp++ = '0';
+ *bufp = 0;
+ }
+ else if (p != bufp)
+ {
+ while (*p)
+ *bufp++ = *p++;
+ *bufp = 0;
+ }
+ }
+#ifdef NO_DOT_IN_LABEL
+ bufp = (char *) index (bufp, '.');
+ if (bufp)
+ *bufp = '_';
+#endif
}
}
OB_PUTCP (digit_buffer);
numeric_output_need_bar = 1;
return;
}
-#endif
case POINTER_TYPE:
if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE
&& TREE_CODE (value) != ADDR_EXPR)
{
if (TREE_CODE (value) == CONSTRUCTOR)
{
- /* This is dangerous code, crack built up pointer to members. */
+ /* This is dangerous code, crack built up pointer to members. */
tree args = CONSTRUCTOR_ELTS (value);
tree a1 = TREE_VALUE (args);
tree a2 = TREE_VALUE (TREE_CHAIN (args));
@@ -479,9 +758,9 @@ build_overload_value (type, value)
if (TREE_CODE (a1) == INTEGER_CST
&& TREE_CODE (a2) == INTEGER_CST)
{
- build_overload_int (a1);
+ build_overload_int (a1, in_template);
OB_PUTC ('_');
- build_overload_int (a2);
+ build_overload_int (a2, in_template);
OB_PUTC ('_');
if (TREE_CODE (a3) == ADDR_EXPR)
{
@@ -496,8 +775,7 @@ build_overload_value (type, value)
else if (TREE_CODE (a3) == INTEGER_CST)
{
OB_PUTC ('i');
- build_overload_int (a3);
- numeric_output_need_bar = 1;
+ build_overload_int (a3, in_template);
return;
}
}
@@ -507,23 +785,31 @@ build_overload_value (type, value)
}
if (TREE_CODE (value) == INTEGER_CST)
{
- build_overload_int (value);
+ build_overload_int (value, in_template);
+ return;
+ }
+ else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
+ {
+ build_mangled_template_parm_index ("", value);
numeric_output_need_bar = 1;
return;
}
+
value = TREE_OPERAND (value, 0);
if (TREE_CODE (value) == VAR_DECL)
{
my_friendly_assert (DECL_NAME (value) != 0, 245);
- build_overload_identifier (DECL_NAME (value));
+ build_overload_identifier (DECL_ASSEMBLER_NAME (value));
return;
}
else if (TREE_CODE (value) == FUNCTION_DECL)
{
my_friendly_assert (DECL_NAME (value) != 0, 246);
- build_overload_identifier (DECL_NAME (value));
+ build_overload_identifier (DECL_ASSEMBLER_NAME (value));
return;
}
+ else if (TREE_CODE (value) == SCOPE_REF)
+ build_overload_scope_ref (value);
else
my_friendly_abort (71);
break; /* not really needed */
@@ -535,46 +821,120 @@ build_overload_value (type, value)
}
}
+
+/* Add encodings for the declaration of template template parameters.
+ PARMLIST must be a TREE_VEC */
+
+static void
+build_template_template_parm_names (parmlist)
+ tree parmlist;
+{
+ int i, nparms;
+
+ my_friendly_assert (TREE_CODE (parmlist) == TREE_VEC, 246.5);
+ nparms = TREE_VEC_LENGTH (parmlist);
+ icat (nparms);
+ for (i = 0; i < nparms; i++)
+ {
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
+ if (TREE_CODE (parm) == TYPE_DECL)
+ {
+ /* This parameter is a type. */
+ OB_PUTC ('Z');
+ }
+ else if (TREE_CODE (parm) == TEMPLATE_DECL)
+ {
+ /* This parameter is a template. */
+ OB_PUTC ('z');
+ build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm));
+ }
+ else
+ /* It's a PARM_DECL. */
+ build_mangled_name_for_type (TREE_TYPE (parm));
+ }
+}
+
+
+/* Add encodings for the vector of template parameters in PARMLIST,
+ given the vector of arguments to be substituted in ARGLIST. */
+
+static void
+build_template_parm_names (parmlist, arglist)
+ tree parmlist;
+ tree arglist;
+{
+ int i, nparms;
+
+ nparms = TREE_VEC_LENGTH (parmlist);
+ icat (nparms);
+ for (i = 0; i < nparms; i++)
+ {
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
+ tree arg = TREE_VEC_ELT (arglist, i);
+ if (TREE_CODE (parm) == TYPE_DECL)
+ {
+ /* This parameter is a type. */
+ OB_PUTC ('Z');
+ build_mangled_name_for_type (arg);
+ }
+ else if (TREE_CODE (parm) == TEMPLATE_DECL)
+ {
+ /* This parameter is a template. */
+ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ /* Output parameter declaration, argument index and level */
+ build_mangled_name_for_type (arg);
+ else
+ {
+ /* A TEMPLATE_DECL node, output the parameter declaration
+ and template name */
+
+ OB_PUTC ('z');
+ build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm));
+ icat (IDENTIFIER_LENGTH (DECL_NAME (arg)));
+ OB_PUTID (DECL_NAME (arg));
+ }
+ }
+ else
+ {
+ parm = tsubst (parm, arglist, NULL_TREE);
+ /* It's a PARM_DECL. */
+ build_mangled_name_for_type (TREE_TYPE (parm));
+ build_overload_value (parm, arg, uses_template_parms (arglist));
+ }
+ }
+ }
+
+/* Output the representation for NAME, which is either a TYPE_DECL or
+ an IDENTIFIER. */
+
static void
build_overload_identifier (name)
tree name;
{
- if (IDENTIFIER_TEMPLATE (name))
- {
+ if (TREE_CODE (name) == TYPE_DECL
+ && IS_AGGR_TYPE (TREE_TYPE (name))
+ && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name))
+ && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name)))
+ || (TREE_CODE (DECL_CONTEXT (CLASSTYPE_TI_TEMPLATE
+ (TREE_TYPE (name))))
+ == FUNCTION_DECL)))
+ {
+ /* NAME is the TYPE_DECL for a template specialization. */
tree template, parmlist, arglist, tname;
- int i, nparms;
- template = IDENTIFIER_TEMPLATE (name);
- arglist = TREE_VALUE (template);
+ template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
+ arglist = innermost_args (TREE_VALUE (template), 0);
template = TREE_PURPOSE (template);
tname = DECL_NAME (template);
- parmlist = DECL_ARGUMENTS (template);
- nparms = TREE_VEC_LENGTH (parmlist);
+ parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
OB_PUTC ('t');
icat (IDENTIFIER_LENGTH (tname));
OB_PUTID (tname);
- icat (nparms);
- for (i = 0; i < nparms; i++)
- {
- tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
- tree arg = TREE_VEC_ELT (arglist, i);
- if (TREE_CODE (parm) == TYPE_DECL)
- {
- /* This parameter is a type. */
- OB_PUTC ('Z');
- build_overload_name (arg, 0, 0);
- }
- else
- {
- parm = tsubst (parm, &TREE_VEC_ELT (arglist, 0),
- TREE_VEC_LENGTH (arglist), NULL_TREE);
- /* It's a PARM_DECL. */
- build_overload_name (TREE_TYPE (parm), 0, 0);
- build_overload_value (parm, arg);
- }
- }
+ build_template_parm_names (parmlist, arglist);
}
else
{
+ if (TREE_CODE (name) == TYPE_DECL)
+ name = DECL_NAME (name);
if (numeric_output_need_bar)
{
OB_PUTC ('_');
@@ -585,6 +945,81 @@ build_overload_identifier (name)
}
}
+/* Given DECL, either a class TYPE, TYPE_DECL or FUNCTION_DECL, produce
+ the mangling for it. Used by build_mangled_name and build_static_name. */
+
+static void
+build_qualified_name (decl)
+ tree decl;
+{
+ tree context;
+ int i = 1;
+
+ if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't')
+ decl = TYPE_NAME (decl);
+
+ /* If DECL_ASSEMBLER_NAME has been set properly, use it. */
+ if (TREE_CODE (decl) == TYPE_DECL
+ && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !flag_do_squangling)
+ {
+ tree id = DECL_ASSEMBLER_NAME (decl);
+ OB_PUTID (id);
+ if (ISDIGIT (IDENTIFIER_POINTER (id) [IDENTIFIER_LENGTH (id) - 1]))
+ numeric_output_need_bar = 1;
+ return;
+ }
+
+ context = decl;
+ /* if we can't find a Ktype, do it the hard way */
+ if (check_ktype (context, FALSE) == -1)
+ {
+ /* count type and namespace scopes */
+ while (DECL_CONTEXT (context) && DECL_CONTEXT (context) != global_namespace)
+ {
+ i += 1;
+ context = DECL_CONTEXT (context);
+ if (check_ktype (context, FALSE) != -1) /* found it! */
+ break;
+ if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
+ context = TYPE_NAME (context);
+ }
+ }
+
+ if (i > 1)
+ {
+ OB_PUTC ('Q');
+ build_underscore_int (i);
+ numeric_output_need_bar = 0;
+ }
+ build_overload_nested_name (decl);
+}
+
+/* Output the mangled representation for TYPE. If EXTRA_GCODE is
+ non-zero, mangled names for structure/union types are intentionally
+ mangled differently from the method described in the ARM. */
+
+void
+build_mangled_name_for_type_with_Gcode (type, extra_Gcode)
+ tree type;
+ int extra_Gcode;
+{
+ if (TYPE_PTRMEMFUNC_P (type))
+ type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+ type = canonical_type_variant (type);
+ process_modifiers (type);
+ process_overload_item (type, extra_Gcode);
+}
+
+/* Like build_mangled_name_for_type_with_Gcode, but never outputs the
+ `G'. */
+
+void
+build_mangled_name_for_type (type)
+ tree type;
+{
+ build_mangled_name_for_type_with_Gcode (type, 0);
+}
+
/* Given a list of parameters in PARMTYPES, create an unambiguous
overload string. Should distinguish any type that C (or C++) can
distinguish. I.e., pointers to functions are treated correctly.
@@ -602,375 +1037,495 @@ build_overload_name (parmtypes, begin, end)
tree parmtypes;
int begin, end;
{
- int just_one;
- tree parmtype;
+ char *ret;
+ start_squangling ();
+ ret = build_mangled_name (parmtypes, begin, end);
+ end_squangling ();
+ return ret ;
+}
- if (begin) OB_INIT ();
- numeric_output_need_bar = 0;
+/* Output the mangled representation for PARMTYPES. If PARMTYPES is a
+ TREE_LIST, then it is a list of parameter types. Otherwise,
+ PARMTYPES must be a single type. */
- if ((just_one = (TREE_CODE (parmtypes) != TREE_LIST)))
- {
- parmtype = parmtypes;
- goto only_one;
- }
+static char *
+build_mangled_name (parmtypes, begin, end)
+ tree parmtypes;
+ int begin, end;
+{
+ if (begin)
+ OB_INIT ();
- while (parmtypes)
+ if (TREE_CODE (parmtypes) != TREE_LIST)
+ /* There is only one type. */
+ build_mangled_name_for_type (parmtypes);
+ else
{
- parmtype = TREE_VALUE (parmtypes);
-
- only_one:
+ /* There are several types in a parameter list. */
+ int nrepeats = 0;
+ int old_style_repeats = !flag_do_squangling && !nofold && typevec;
+ tree last_type = NULL_TREE;
- if (! nofold && ! just_one)
+ for (; parmtypes && parmtypes != void_list_node;
+ parmtypes = TREE_CHAIN (parmtypes))
{
- /* Every argument gets counted. */
- typevec[maxtype++] = parmtype;
+ tree parmtype = canonical_type_variant (TREE_VALUE (parmtypes));
- if (TREE_USED (parmtype) && parmtype == typevec[maxtype-2])
+ if (old_style_repeats)
{
- nrepeats++;
- goto next;
+ /* Every argument gets counted. */
+ my_friendly_assert (maxtype < typevec_size, 387);
+ typevec[maxtype++] = parmtype;
}
- if (nrepeats)
- flush_repeats (typevec[maxtype-2]);
+ if (parmtype == last_type)
+ {
+ if (flag_do_squangling
+ || (old_style_repeats && TREE_USED (parmtype)
+ && !TYPE_FOR_JAVA (parmtype)))
+ {
+ /* The next type is the same as this one. Keep
+ track of the repetition, and output the repeat
+ count later. */
+ nrepeats++;
+ continue;
+ }
+ }
+ else if (nrepeats != 0)
+ {
+ /* Indicate how many times the previous parameter was
+ repeated. */
+ if (old_style_repeats)
+ flush_repeats (nrepeats, last_type);
+ else
+ issue_nrepeats (nrepeats, last_type);
+ nrepeats = 0;
+ }
+
+ last_type = parmtype;
- if (TREE_USED (parmtype))
+ if (old_style_repeats)
{
- flush_repeats (parmtype);
- goto next;
+ if (nrepeats)
+ {
+ flush_repeats (nrepeats, last_type);
+ nrepeats = 0;
+ }
+
+ if (TREE_USED (parmtype))
+ {
+#if 0
+ /* We can turn this on at some point when we want
+ improved symbol mangling. */
+ nrepeats++;
+#else
+ /* This is bug compatible with 2.7.x */
+ flush_repeats (nrepeats, parmtype);
+#endif
+ nrepeats = 0;
+ continue;
+ }
+
+ /* Only cache types which take more than one character. */
+ if ((parmtype != TYPE_MAIN_VARIANT (parmtype)
+ || (TREE_CODE (parmtype) != INTEGER_TYPE
+ && TREE_CODE (parmtype) != REAL_TYPE))
+ && ! TYPE_FOR_JAVA (parmtype))
+ TREE_USED (parmtype) = 1;
}
- /* Only cache types which take more than one character. */
- if (parmtype != TYPE_MAIN_VARIANT (parmtype)
- || (TREE_CODE (parmtype) != INTEGER_TYPE
- && TREE_CODE (parmtype) != REAL_TYPE))
- TREE_USED (parmtype) = 1;
+ /* Output the PARMTYPE. */
+ build_mangled_name_for_type_with_Gcode (parmtype, 1);
}
- if (TYPE_PTRMEMFUNC_P (parmtype))
- parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype);
+ /* Output the repeat count for the last parameter, if
+ necessary. */
+ if (nrepeats != 0)
+ {
+ if (old_style_repeats)
+ flush_repeats (nrepeats, last_type);
+ else
+ issue_nrepeats (nrepeats, last_type);
+ nrepeats = 0;
+ }
- if (TREE_READONLY (parmtype))
- OB_PUTC ('C');
- if (TREE_CODE (parmtype) == INTEGER_TYPE
- && TYPE_MAIN_VARIANT (parmtype) == unsigned_type (TYPE_MAIN_VARIANT (parmtype)))
- OB_PUTC ('U');
- if (TYPE_VOLATILE (parmtype))
- OB_PUTC ('V');
+ if (!parmtypes)
+ /* The parameter list ends in an ellipsis. */
+ OB_PUTC ('e');
+ }
- switch (TREE_CODE (parmtype))
- {
- case OFFSET_TYPE:
- OB_PUTC ('O');
- build_overload_name (TYPE_OFFSET_BASETYPE (parmtype), 0, 0);
+ if (end)
+ OB_FINISH ();
+ return (char *)obstack_base (&scratch_obstack);
+}
+
+/* handles emitting modifiers such as Constant, read-only, and volatile */
+void
+process_modifiers (parmtype)
+ tree parmtype;
+{
+ if (TREE_READONLY (parmtype))
+ OB_PUTC ('C');
+ if (TREE_CODE (parmtype) == INTEGER_TYPE
+ && (TYPE_MAIN_VARIANT (parmtype)
+ == unsigned_type (TYPE_MAIN_VARIANT (parmtype)))
+ && ! TYPE_FOR_JAVA (parmtype))
+ OB_PUTC ('U');
+ if (TYPE_VOLATILE (parmtype))
+ OB_PUTC ('V');
+}
+
+/* Check to see if TYPE has been entered into the Bcode typelist. If
+ so, return 1 and emit a backreference to TYPE. Otherwise, add TYPE
+ to the list of back-referenceable types and return 0. */
+
+int
+check_btype (type)
+ tree type;
+{
+ int x;
+
+ if (btypelist == NULL)
+ return 0;
+
+ if (!is_back_referenceable_type (type))
+ return 0;
+
+ /* We assume that our caller has put out any necessary
+ qualifiers. */
+ type = TYPE_MAIN_VARIANT (type);
+
+ for (x = 0; x < maxbtype; x++)
+ if (type == btypelist[x])
+ {
+ OB_PUTC ('B');
+ icat (x);
+ if (x > 9)
OB_PUTC ('_');
- build_overload_name (TREE_TYPE (parmtype), 0, 0);
- break;
+ return 1 ;
+ }
+
+ if (maxbsize <= maxbtype)
+ {
+ /* Enlarge the table. */
+ maxbsize = maxbsize * 3 / 2;
+ btypelist = (tree *)xrealloc (btypelist, sizeof (tree) * maxbsize);
+ }
+
+ /* Register the TYPE. */
+ btypelist[maxbtype++] = type;
- case REFERENCE_TYPE:
- OB_PUTC ('R');
- goto more;
+ return 0;
+}
- case ARRAY_TYPE:
+/* handle emitting the correct code for various node types */
+static void
+process_overload_item (parmtype, extra_Gcode)
+ tree parmtype;
+ int extra_Gcode;
+{
+ numeric_output_need_bar = 0;
+
+ /* These tree types are considered modifiers for B code squangling , */
+ /* and therefore should not get entries in the Btypelist */
+ /* they are, however, repeatable types */
+
+ switch (TREE_CODE (parmtype))
+ {
+ case REFERENCE_TYPE:
+ OB_PUTC ('R');
+ goto more;
+
+ case ARRAY_TYPE:
#if PARM_CAN_BE_ARRAY_TYPE
- {
- tree length;
+ {
+ tree length;
- OB_PUTC ('A');
- if (TYPE_DOMAIN (parmtype) == NULL_TREE)
- error ("pointer or reference to array of unknown bound in parm type");
- else
+ OB_PUTC ('A');
+ if (TYPE_DOMAIN (parmtype) == NULL_TREE)
+ error("pointer/reference to array of unknown bound in parm type");
+ else
+ {
+ tree length = array_type_nelts (parmtype);
+ if (TREE_CODE (length) != INTEGER_CST || flag_do_squangling)
{
- length = array_type_nelts (parmtype);
- if (TREE_CODE (length) == INTEGER_CST)
- icat (TREE_INT_CST_LOW (length) + 1);
+ length = fold (build (PLUS_EXPR, TREE_TYPE (length),
+ length, integer_one_node));
+ STRIP_NOPS (length);
}
- OB_PUTC ('_');
- goto more;
+ build_overload_value (sizetype, length, 1);
}
+ if (numeric_output_need_bar && ! flag_do_squangling)
+ OB_PUTC ('_');
+ goto more;
+ }
#else
- OB_PUTC ('P');
- goto more;
+ OB_PUTC ('P');
+ goto more;
#endif
- case POINTER_TYPE:
- OB_PUTC ('P');
- more:
- build_overload_name (TREE_TYPE (parmtype), 0, 0);
- break;
+ case POINTER_TYPE:
+ OB_PUTC ('P');
+ more:
+ build_mangled_name_for_type (TREE_TYPE (parmtype));
+ return;
+ break;
- case FUNCTION_TYPE:
- case METHOD_TYPE:
- {
- tree firstarg = TYPE_ARG_TYPES (parmtype);
- /* Otherwise have to implement reentrant typevecs,
- unmark and remark types, etc. */
- int old_nofold = nofold;
- nofold = 1;
-
- if (nrepeats)
- flush_repeats (typevec[maxtype-1]);
-
- /* @@ It may be possible to pass a function type in
- which is not preceded by a 'P'. */
- if (TREE_CODE (parmtype) == FUNCTION_TYPE)
- {
- OB_PUTC ('F');
- if (firstarg == NULL_TREE)
- OB_PUTC ('e');
- else if (firstarg == void_list_node)
- OB_PUTC ('v');
- else
- build_overload_name (firstarg, 0, 0);
- }
- else
- {
- int constp = TYPE_READONLY (TREE_TYPE (TREE_VALUE (firstarg)));
- int volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (firstarg)));
- OB_PUTC ('M');
- firstarg = TREE_CHAIN (firstarg);
-
- build_overload_name (TYPE_METHOD_BASETYPE (parmtype), 0, 0);
- if (constp)
- OB_PUTC ('C');
- if (volatilep)
- OB_PUTC ('V');
-
- /* For cfront 2.0 compatibility. */
- OB_PUTC ('F');
-
- if (firstarg == NULL_TREE)
- OB_PUTC ('e');
- else if (firstarg == void_list_node)
- OB_PUTC ('v');
- else
- build_overload_name (firstarg, 0, 0);
- }
+ default:
+ break;
+ }
+
+ if (flag_do_squangling && check_btype (parmtype))
+ /* If PARMTYPE is already in the list of back-referenceable types,
+ then check_btype will output the appropriate reference, and
+ there's nothing more to do. */
+ return;
- /* Separate args from return type. */
- OB_PUTC ('_');
- build_overload_name (TREE_TYPE (parmtype), 0, 0);
- nofold = old_nofold;
- break;
+ switch (TREE_CODE (parmtype))
+ {
+ case OFFSET_TYPE:
+ OB_PUTC ('O');
+ build_mangled_name_for_type (TYPE_OFFSET_BASETYPE (parmtype));
+ OB_PUTC ('_');
+ build_mangled_name_for_type (TREE_TYPE (parmtype));
+ break;
+
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ {
+ tree parms = TYPE_ARG_TYPES (parmtype);
+
+ /* Rather than implementing a reentrant TYPEVEC, we turn off
+ repeat codes here, unless we're squangling. Squangling
+ doesn't make use of the TYPEVEC, so there's no reentrancy
+ problem. */
+ int old_nofold = nofold;
+ if (!flag_do_squangling)
+ nofold = 1;
+
+ if (TREE_CODE (parmtype) == METHOD_TYPE)
+ {
+ /* Mark this as a method. */
+ OB_PUTC ('M');
+ /* Output the class of which this method is a member. */
+ build_mangled_name_for_type (TYPE_METHOD_BASETYPE (parmtype));
+ /* Output any qualifiers for the `this' parameter. */
+ process_modifiers (TREE_TYPE (TREE_VALUE (parms)));
}
- case INTEGER_TYPE:
- parmtype = TYPE_MAIN_VARIANT (parmtype);
- if (parmtype == integer_type_node
- || parmtype == unsigned_type_node)
- OB_PUTC ('i');
- else if (parmtype == long_integer_type_node
- || parmtype == long_unsigned_type_node)
- OB_PUTC ('l');
- else if (parmtype == short_integer_type_node
- || parmtype == short_unsigned_type_node)
- OB_PUTC ('s');
- else if (parmtype == signed_char_type_node)
- {
- OB_PUTC ('S');
- OB_PUTC ('c');
- }
- else if (parmtype == char_type_node
- || parmtype == unsigned_char_type_node)
- OB_PUTC ('c');
- else if (parmtype == wchar_type_node)
- OB_PUTC ('w');
- else if (parmtype == long_long_integer_type_node
- || parmtype == long_long_unsigned_type_node)
- OB_PUTC ('x');
+ /* Output the parameter types. */
+ OB_PUTC ('F');
+ if (parms == NULL_TREE)
+ OB_PUTC ('e');
+ else if (parms == void_list_node)
+ OB_PUTC ('v');
+ else
+ build_mangled_name (parms, 0, 0);
+
+ /* Output the return type. */
+ OB_PUTC ('_');
+ build_mangled_name_for_type (TREE_TYPE (parmtype));
+
+ nofold = old_nofold;
+ break;
+ }
+
+ case INTEGER_TYPE:
+ parmtype = TYPE_MAIN_VARIANT (parmtype);
+ if (parmtype == integer_type_node
+ || parmtype == unsigned_type_node
+ || parmtype == java_int_type_node)
+ OB_PUTC ('i');
+ else if (parmtype == long_integer_type_node
+ || parmtype == long_unsigned_type_node)
+ OB_PUTC ('l');
+ else if (parmtype == short_integer_type_node
+ || parmtype == short_unsigned_type_node
+ || parmtype == java_short_type_node)
+ OB_PUTC ('s');
+ else if (parmtype == signed_char_type_node)
+ {
+ OB_PUTC ('S');
+ OB_PUTC ('c');
+ }
+ else if (parmtype == char_type_node
+ || parmtype == unsigned_char_type_node
+ || parmtype == java_byte_type_node)
+ OB_PUTC ('c');
+ else if (parmtype == wchar_type_node
+ || parmtype == java_char_type_node)
+ OB_PUTC ('w');
+ else if (parmtype == long_long_integer_type_node
+ || parmtype == long_long_unsigned_type_node
+ || parmtype == java_long_type_node)
+ OB_PUTC ('x');
#if 0
- /* it would seem there is no way to enter these in source code,
- yet. (mrs) */
- else if (parmtype == long_long_long_integer_type_node
- || parmtype == long_long_long_unsigned_type_node)
- OB_PUTC ('q');
+ /* it would seem there is no way to enter these in source code,
+ yet. (mrs) */
+ else if (parmtype == long_long_long_integer_type_node
+ || parmtype == long_long_long_unsigned_type_node)
+ OB_PUTC ('q');
#endif
- else
- my_friendly_abort (73);
- break;
-
- case BOOLEAN_TYPE:
- OB_PUTC ('b');
- break;
-
- case REAL_TYPE:
- parmtype = TYPE_MAIN_VARIANT (parmtype);
- if (parmtype == long_double_type_node)
- OB_PUTC ('r');
- else if (parmtype == double_type_node)
- OB_PUTC ('d');
- else if (parmtype == float_type_node)
- OB_PUTC ('f');
- else my_friendly_abort (74);
- break;
-
- case VOID_TYPE:
- if (! just_one)
- {
-#if 0
- extern tree void_list_node;
+ else if (parmtype == java_boolean_type_node)
+ OB_PUTC ('b');
+ else
+ my_friendly_abort (73);
+ break;
- /* See if anybody is wasting memory. */
- my_friendly_assert (parmtypes == void_list_node, 247);
-#endif
- /* This is the end of a parameter list. */
- if (end) OB_FINISH ();
- return (char *)obstack_base (&scratch_obstack);
- }
- OB_PUTC ('v');
- break;
-
- case ERROR_MARK: /* not right, but nothing is anyway */
- break;
-
- /* have to do these */
- case UNION_TYPE:
- case RECORD_TYPE:
- if (! just_one)
- /* Make this type signature look incompatible
- with AT&T. */
- OB_PUTC ('G');
- goto common;
- case ENUMERAL_TYPE:
- common:
- {
- tree name = TYPE_NAME (parmtype);
- int i = 1;
+ case BOOLEAN_TYPE:
+ OB_PUTC ('b');
+ break;
- if (TREE_CODE (name) == TYPE_DECL)
- {
- tree context = name;
+ case REAL_TYPE:
+ parmtype = TYPE_MAIN_VARIANT (parmtype);
+ if (parmtype == long_double_type_node)
+ OB_PUTC ('r');
+ else if (parmtype == double_type_node
+ || parmtype == java_double_type_node)
+ OB_PUTC ('d');
+ else if (parmtype == float_type_node
+ || parmtype == java_float_type_node)
+ OB_PUTC ('f');
+ else my_friendly_abort (74);
+ break;
- /* If DECL_ASSEMBLER_NAME has been set properly, use it. */
- if (DECL_ASSEMBLER_NAME (context) != DECL_NAME (context))
- {
- OB_PUTID (DECL_ASSEMBLER_NAME (context));
- break;
- }
- while (DECL_CONTEXT (context))
- {
- i += 1;
- context = DECL_CONTEXT (context);
- if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
- context = TYPE_NAME (context);
- }
- name = DECL_NAME (name);
- }
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 248);
- if (i > 1)
- {
- OB_PUTC ('Q');
- if (i > 9)
- OB_PUTC ('_');
- icat (i);
- if (i > 9)
- OB_PUTC ('_');
- numeric_output_need_bar = 0;
- build_overload_nested_name (TYPE_MAIN_DECL (parmtype));
- }
- else
- build_overload_identifier (name);
- break;
- }
+ case COMPLEX_TYPE:
+ OB_PUTC ('J');
+ build_mangled_name_for_type (TREE_TYPE (parmtype));
+ break;
- case UNKNOWN_TYPE:
- /* This will take some work. */
- OB_PUTC ('?');
- break;
-
- case TEMPLATE_TYPE_PARM:
- case TEMPLATE_CONST_PARM:
- case UNINSTANTIATED_P_TYPE:
- /* We don't ever want this output, but it's inconvenient not to
- be able to build the string. This should cause assembler
- errors we'll notice. */
- {
- static int n;
- sprintf (digit_buffer, " *%d", n++);
- OB_PUTCP (digit_buffer);
- }
- break;
+ case VOID_TYPE:
+ OB_PUTC ('v');
+ break;
- default:
- my_friendly_abort (75);
- }
+ case ERROR_MARK: /* not right, but nothing is anyway */
+ break;
- next:
- if (just_one) break;
- parmtypes = TREE_CHAIN (parmtypes);
- }
- if (! just_one)
- {
- if (nrepeats)
- flush_repeats (typevec[maxtype-1]);
+ /* have to do these */
+ case UNION_TYPE:
+ case RECORD_TYPE:
+ {
+ if (extra_Gcode)
+ OB_PUTC ('G'); /* make it look incompatible with AT&T */
+ /* drop through into next case */
+ }
+ case ENUMERAL_TYPE:
+ {
+ tree name = TYPE_NAME (parmtype);
+
+ if (TREE_CODE (name) == IDENTIFIER_NODE)
+ {
+ build_overload_identifier (TYPE_NAME (parmtype));
+ break;
+ }
+ my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 248);
+
+ build_qualified_name (name);
+ break;
+ }
+
+ case UNKNOWN_TYPE:
+ /* This will take some work. */
+ OB_PUTC ('?');
+ break;
- /* To get here, parms must end with `...'. */
- OB_PUTC ('e');
+ case TEMPLATE_TEMPLATE_PARM:
+ /* Find and output the original template parameter
+ declaration. */
+ if (CLASSTYPE_TEMPLATE_INFO (parmtype))
+ {
+ build_mangled_template_parm_index ("tzX",
+ TEMPLATE_TYPE_PARM_INDEX
+ (parmtype));
+ build_template_parm_names
+ (DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (parmtype)),
+ CLASSTYPE_TI_ARGS (parmtype));
+ }
+ else
+ {
+ build_mangled_template_parm_index ("ZzX",
+ TEMPLATE_TYPE_PARM_INDEX
+ (parmtype));
+ build_template_template_parm_names
+ (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype)));
+ }
+ break;
+
+ case TEMPLATE_TYPE_PARM:
+ build_mangled_template_parm_index ("X",
+ TEMPLATE_TYPE_PARM_INDEX
+ (parmtype));
+ break;
+
+ case TYPENAME_TYPE:
+ /* When mangling the type of a function template whose
+ declaration looks like:
+
+ template <class T> void foo(typename T::U)
+
+ we have to mangle these. */
+ build_qualified_name (parmtype);
+ break;
+
+ default:
+ my_friendly_abort (75);
}
- if (end) OB_FINISH ();
- return (char *)obstack_base (&scratch_obstack);
}
-tree
-build_static_name (basetype, name)
- tree basetype, name;
-{
- char *basename = build_overload_name (basetype, 1, 1);
- char *buf = (char *) alloca (IDENTIFIER_LENGTH (name)
- + sizeof (STATIC_NAME_FORMAT)
- + strlen (basename));
- sprintf (buf, STATIC_NAME_FORMAT, basename, IDENTIFIER_POINTER (name));
- return get_identifier (buf);
-}
-
-/* Generate an identifier that encodes the (ANSI) exception TYPE. */
-
-/* This should be part of `ansi_opname', or at least be defined by the std. */
-#define EXCEPTION_NAME_PREFIX "__ex"
-#define EXCEPTION_NAME_LENGTH 4
+/* Produce the mangling for a variable named NAME in CONTEXT, which can
+ be either a class TYPE or a FUNCTION_DECL. */
tree
-cplus_exception_name (type)
- tree type;
+build_static_name (context, name)
+ tree context, name;
{
OB_INIT ();
- OB_PUTS (EXCEPTION_NAME_PREFIX);
- return get_identifier (build_overload_name (type, 0, 1));
+ numeric_output_need_bar = 0;
+ start_squangling ();
+#ifdef JOINER
+ OB_PUTC ('_');
+ build_qualified_name (context);
+ OB_PUTC (JOINER);
+#else
+ OB_PUTS ("__static_");
+ build_qualified_name (context);
+ OB_PUTC ('_');
+#endif
+ OB_PUTID (name);
+ OB_FINISH ();
+ end_squangling ();
+
+ return get_identifier ((char *)obstack_base (&scratch_obstack));
}
-/* Change the name of a function definition so that it may be
- overloaded. NAME is the name of the function to overload,
- PARMS is the parameter list (which determines what name the
- final function obtains).
-
- FOR_METHOD is 1 if this overload is being performed
- for a method, rather than a function type. It is 2 if
- this overload is being performed for a constructor. */
-tree
-build_decl_overload (dname, parms, for_method)
+static tree
+build_decl_overload_real (dname, parms, ret_type, tparms, targs,
+ for_method)
tree dname;
tree parms;
+ tree ret_type;
+ tree tparms;
+ tree targs;
int for_method;
{
char *name = IDENTIFIER_POINTER (dname);
/* member operators new and delete look like methods at this point. */
- if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST)
+ if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST
+ && TREE_CHAIN (parms) == void_list_node)
{
if (dname == ansi_opname[(int) DELETE_EXPR])
return get_identifier ("__builtin_delete");
else if (dname == ansi_opname[(int) VEC_DELETE_EXPR])
return get_identifier ("__builtin_vec_delete");
- else if (TREE_CHAIN (parms) == void_list_node)
- {
- if (dname == ansi_opname[(int) NEW_EXPR])
- return get_identifier ("__builtin_new");
- else if (dname == ansi_opname[(int) VEC_NEW_EXPR])
- return get_identifier ("__builtin_vec_new");
- }
+ if (dname == ansi_opname[(int) NEW_EXPR])
+ return get_identifier ("__builtin_new");
+ else if (dname == ansi_opname[(int) VEC_NEW_EXPR])
+ return get_identifier ("__builtin_vec_new");
}
+ start_squangling ();
OB_INIT ();
if (for_method != 2)
OB_PUTCP (name);
@@ -978,50 +1533,107 @@ build_decl_overload (dname, parms, for_method)
and figure out its name without any extra encoding. */
OB_PUTC2 ('_', '_');
- if (for_method)
- {
-#if 0
- /* We can get away without doing this. */
- OB_PUTC ('M');
-#endif
- {
- tree this_type = TREE_VALUE (parms);
+ numeric_output_need_bar = 0;
- if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */
- parms = temp_tree_cons (NULL_TREE, SIGNATURE_TYPE (this_type),
- TREE_CHAIN (parms));
- else
- parms = temp_tree_cons (NULL_TREE, TREE_TYPE (this_type),
- TREE_CHAIN (parms));
- }
+ if (tparms)
+ {
+ OB_PUTC ('H');
+ build_template_parm_names (tparms, targs);
+ OB_PUTC ('_');
}
- else
+ else if (!for_method && current_namespace == global_namespace)
+ /* XXX this works only if we call this in the same namespace
+ as the declaration. Unfortunately, we don't have the _DECL,
+ only its name */
OB_PUTC ('F');
+ if (!for_method && current_namespace != global_namespace)
+ /* qualify with namespace */
+ build_qualified_name (current_namespace);
+
if (parms == NULL_TREE)
- OB_PUTC2 ('e', '\0');
+ OB_PUTC ('e');
else if (parms == void_list_node)
- OB_PUTC2 ('v', '\0');
+ OB_PUTC ('v');
else
{
- ALLOCATE_TYPEVEC (parms);
+ if (!flag_do_squangling) /* Allocate typevec array. */
+ {
+ maxtype = 0;
+ typevec_size = list_length (parms);
+ if (!for_method && current_namespace != global_namespace)
+ /* the namespace of a global function needs one slot */
+ typevec_size++;
+ typevec = (tree *)alloca (typevec_size * sizeof (tree));
+ }
nofold = 0;
+
if (for_method)
{
- build_overload_name (TREE_VALUE (parms), 0, 0);
+ tree this_type = TREE_VALUE (parms);
+
+ if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */
+ this_type = SIGNATURE_TYPE (this_type);
+ else
+ this_type = TREE_TYPE (this_type);
- typevec[maxtype++] = TREE_VALUE (parms);
- TREE_USED (TREE_VALUE (parms)) = 1;
+ build_mangled_name_for_type (this_type);
+
+ if (!flag_do_squangling)
+ {
+ my_friendly_assert (maxtype < typevec_size, 387);
+ typevec[maxtype++] = this_type;
+ TREE_USED (this_type) = 1;
+
+ /* By setting up PARMS in this way, the loop below will
+ automatically clear TREE_USED on THIS_TYPE. */
+ parms = temp_tree_cons (NULL_TREE, this_type,
+ TREE_CHAIN (parms));
+ }
if (TREE_CHAIN (parms))
- build_overload_name (TREE_CHAIN (parms), 0, 1);
+ build_mangled_name (TREE_CHAIN (parms), 0, 0);
else
- OB_PUTC2 ('e', '\0');
+ OB_PUTC ('e');
}
else
- build_overload_name (parms, 0, 1);
- DEALLOCATE_TYPEVEC (parms);
+ {
+ /* the namespace qualifier for a global function
+ will count as type */
+ if (current_namespace != global_namespace
+ && !flag_do_squangling)
+ {
+ my_friendly_assert (maxtype < typevec_size, 387);
+ typevec[maxtype++] = current_namespace;
+ }
+ build_mangled_name (parms, 0, 0);
+ }
+
+ if (!flag_do_squangling) /* Deallocate typevec array */
+ {
+ tree t = parms;
+ typevec = NULL;
+ while (t)
+ {
+ tree temp = TREE_VALUE (t);
+ TREE_USED (temp) = 0;
+ /* clear out the type variant in case we used it */
+ temp = canonical_type_variant (temp);
+ TREE_USED (temp) = 0;
+ t = TREE_CHAIN (t);
+ }
+ }
+ }
+
+ if (ret_type != NULL_TREE && for_method != 2)
+ {
+ /* Add the return type. */
+ OB_PUTC ('_');
+ build_mangled_name_for_type (ret_type);
}
+
+ OB_FINISH ();
+ end_squangling ();
{
tree n = get_identifier (obstack_base (&scratch_obstack));
if (IDENTIFIER_OPNAME_P (dname))
@@ -1030,7 +1642,59 @@ build_decl_overload (dname, parms, for_method)
}
}
+/* Change the name of a function definition so that it may be
+ overloaded. NAME is the name of the function to overload,
+ PARMS is the parameter list (which determines what name the
+ final function obtains).
+
+ FOR_METHOD is 1 if this overload is being performed
+ for a method, rather than a function type. It is 2 if
+ this overload is being performed for a constructor. */
+
+tree
+build_decl_overload (dname, parms, for_method)
+ tree dname;
+ tree parms;
+ int for_method;
+{
+ return build_decl_overload_real (dname, parms, NULL_TREE, NULL_TREE,
+ NULL_TREE, for_method);
+}
+
+
+/* Like build_decl_overload, but for template functions. */
+
+tree
+build_template_decl_overload (decl, parms, ret_type, tparms, targs,
+ for_method)
+ tree decl;
+ tree parms;
+ tree ret_type;
+ tree tparms;
+ tree targs;
+ int for_method;
+{
+ tree res, saved_ctx;
+
+ /* If the template is in a namespace, we need to put that into the
+ mangled name. Unfortunately, build_decl_overload_real does not
+ get the decl to mangle, so it relies on the current
+ namespace. Therefore, we set that here temporarily. */
+
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702);
+ saved_ctx = current_namespace;
+ current_namespace = CP_DECL_CONTEXT (decl);
+
+ res = build_decl_overload_real (DECL_NAME (decl), parms, ret_type,
+ tparms, targs, for_method);
+
+ current_namespace = saved_ctx;
+ return res;
+}
+
+
/* Build an overload name for the type expression TYPE. */
+
tree
build_typename_overload (type)
tree type;
@@ -1040,111 +1704,53 @@ build_typename_overload (type)
OB_INIT ();
OB_PUTID (ansi_opname[(int) TYPE_EXPR]);
nofold = 1;
- build_overload_name (type, 0, 1);
+ start_squangling ();
+ build_mangled_name (type, 0, 1);
id = get_identifier (obstack_base (&scratch_obstack));
IDENTIFIER_OPNAME_P (id) = 1;
#if 0
- IDENTIFIER_GLOBAL_VALUE (id) = TYPE_NAME (type);
+ IDENTIFIER_GLOBAL_VALUE (id) = TYPE_MAIN_DECL (type);
#endif
TREE_TYPE (id) = type;
+ end_squangling ();
return id;
}
-#ifndef NO_DOLLAR_IN_LABEL
-#define T_DESC_FORMAT "TD$"
-#define I_DESC_FORMAT "ID$"
-#define M_DESC_FORMAT "MD$"
-#else
-#if !defined(NO_DOT_IN_LABEL)
-#define T_DESC_FORMAT "TD."
-#define I_DESC_FORMAT "ID."
-#define M_DESC_FORMAT "MD."
-#else
-#define T_DESC_FORMAT "__t_desc_"
-#define I_DESC_FORMAT "__i_desc_"
-#define M_DESC_FORMAT "__m_desc_"
-#endif
-#endif
-
-/* Build an overload name for the type expression TYPE. */
tree
-build_t_desc_overload (type)
- tree type;
+build_overload_with_type (name, type)
+ tree name, type;
{
OB_INIT ();
- OB_PUTS (T_DESC_FORMAT);
+ OB_PUTID (name);
nofold = 1;
-#if 0
- /* Use a different format if the type isn't defined yet. */
- if (TYPE_SIZE (type) == NULL_TREE)
- {
- char *p;
- int changed;
-
- for (p = tname; *p; p++)
- if (isupper (*p))
- {
- changed = 1;
- *p = tolower (*p);
- }
- /* If there's no change, we have an inappropriate T_DESC_FORMAT. */
- my_friendly_assert (changed != 0, 249);
- }
-#endif
-
- build_overload_name (type, 0, 1);
+ start_squangling ();
+ build_mangled_name (type, 0, 1);
+ end_squangling ();
return get_identifier (obstack_base (&scratch_obstack));
}
-/* Top-level interface to explicit overload requests. Allow NAME
- to be overloaded. Error if NAME is already declared for the current
- scope. Warning if function is redundantly overloaded. */
-
-void
-declare_overloaded (name)
- tree name;
+tree
+get_id_2 (name, name2)
+ char *name;
+ tree name2;
{
-#ifdef NO_AUTO_OVERLOAD
- if (is_overloaded (name))
- warning ("function `%s' already declared overloaded",
- IDENTIFIER_POINTER (name));
- else if (IDENTIFIER_GLOBAL_VALUE (name))
- error ("overloading function `%s' that is already defined",
- IDENTIFIER_POINTER (name));
- else
- {
- TREE_OVERLOADED (name) = 1;
- IDENTIFIER_GLOBAL_VALUE (name) = build_tree_list (name, NULL_TREE);
- TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)) = unknown_type_node;
- }
-#else
- if (current_lang_name == lang_name_cplusplus)
- {
- if (0)
- warning ("functions are implicitly overloaded in C++");
- }
- else if (current_lang_name == lang_name_c)
- error ("overloading function `%s' cannot be done in C language context");
- else
- my_friendly_abort (76);
-#endif
+ OB_INIT ();
+ OB_PUTCP (name);
+ OB_PUTID (name2);
+ OB_FINISH ();
+ return get_identifier (obstack_base (&scratch_obstack));
}
-#ifdef NO_AUTO_OVERLOAD
-/* Check to see if NAME is overloaded. For first approximation,
- check to see if its TREE_OVERLOADED is set. This is used on
- IDENTIFIER nodes. */
-int
-is_overloaded (name)
- tree name;
+/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. */
+
+tree
+build_destructor_name (type)
+ tree type;
{
- /* @@ */
- return (TREE_OVERLOADED (name)
- && (! IDENTIFIER_CLASS_VALUE (name) || current_class_type == 0)
- && ! IDENTIFIER_LOCAL_VALUE (name));
+ return build_overload_with_type (get_identifier (DESTRUCTOR_DECL_PREFIX),
+ type);
}
-#endif
/* Given a tree_code CODE, and some arguments (at least one),
attempt to use an overloaded operator on the arguments.
@@ -1175,296 +1781,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
int flags;
tree xarg1, xarg2, arg3;
{
- tree rval = 0;
- tree arg1, arg2;
- tree type1, type2, fnname;
- tree fields1 = 0, parms = 0;
- tree global_fn;
- int try_second;
- int binary_is_unary;
-
- if (xarg1 == error_mark_node)
- return error_mark_node;
-
- if (code == COND_EXPR)
- {
- if (TREE_CODE (xarg2) == ERROR_MARK
- || TREE_CODE (arg3) == ERROR_MARK)
- return error_mark_node;
- }
- if (code == COMPONENT_REF)
- if (TREE_CODE (TREE_TYPE (xarg1)) == POINTER_TYPE)
- return rval;
-
- /* First, see if we can work with the first argument */
- type1 = TREE_TYPE (xarg1);
-
- /* Some tree codes have length > 1, but we really only want to
- overload them if their first argument has a user defined type. */
- switch (code)
- {
- case PREINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- case COMPONENT_REF:
- binary_is_unary = 1;
- try_second = 0;
- break;
-
- /* ARRAY_REFs and CALL_EXPRs must overload successfully.
- If they do not, return error_mark_node instead of NULL_TREE. */
- case ARRAY_REF:
- if (xarg2 == error_mark_node)
- return error_mark_node;
- case CALL_EXPR:
- rval = error_mark_node;
- binary_is_unary = 0;
- try_second = 0;
- break;
-
- case VEC_NEW_EXPR:
- case NEW_EXPR:
- {
- tree args = tree_cons (NULL_TREE, xarg2, arg3);
- fnname = ansi_opname[(int) code];
- if (flags & LOOKUP_GLOBAL)
- return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN,
- (struct candidate *)0);
-
- rval = build_method_call
- (build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node),
- "new"),
- fnname, args, NULL_TREE, flags);
- if (rval == error_mark_node)
- /* User might declare fancy operator new, but invoke it
- like standard one. */
- return rval;
-
- TREE_TYPE (rval) = xarg1;
- TREE_CALLS_NEW (rval) = 1;
- return rval;
- }
- break;
-
- case VEC_DELETE_EXPR:
- case DELETE_EXPR:
- {
- fnname = ansi_opname[(int) code];
- if (flags & LOOKUP_GLOBAL)
- return build_overload_call (fnname,
- build_tree_list (NULL_TREE, xarg1),
- flags & LOOKUP_COMPLAIN,
- (struct candidate *)0);
-
- rval = build_method_call
- (build_indirect_ref (build1 (NOP_EXPR, TREE_TYPE (xarg1),
- error_mark_node),
- NULL_PTR),
- fnname, tree_cons (NULL_TREE, xarg1,
- build_tree_list (NULL_TREE, xarg2)),
- NULL_TREE, flags);
-#if 0
- /* This can happen when operator delete is protected. */
- my_friendly_assert (rval != error_mark_node, 250);
- TREE_TYPE (rval) = void_type_node;
-#endif
- return rval;
- }
- break;
-
- default:
- binary_is_unary = 0;
- try_second = tree_code_length [(int) code] == 2;
- if (try_second && xarg2 == error_mark_node)
- return error_mark_node;
- break;
- }
-
- if (try_second && xarg2 == error_mark_node)
- return error_mark_node;
-
- /* What ever it was, we do not know how to deal with it. */
- if (type1 == NULL_TREE)
- return rval;
-
- if (TREE_CODE (type1) == OFFSET_TYPE)
- type1 = TREE_TYPE (type1);
-
- if (TREE_CODE (type1) == REFERENCE_TYPE)
- {
- arg1 = convert_from_reference (xarg1);
- type1 = TREE_TYPE (arg1);
- }
- else
- {
- arg1 = xarg1;
- }
-
- if (!IS_AGGR_TYPE (type1) || TYPE_PTRMEMFUNC_P (type1))
- {
- /* Try to fail. First, fail if unary */
- if (! try_second)
- return rval;
- /* Second, see if second argument is non-aggregate. */
- type2 = TREE_TYPE (xarg2);
- if (TREE_CODE (type2) == OFFSET_TYPE)
- type2 = TREE_TYPE (type2);
- if (TREE_CODE (type2) == REFERENCE_TYPE)
- {
- arg2 = convert_from_reference (xarg2);
- type2 = TREE_TYPE (arg2);
- }
- else
- {
- arg2 = xarg2;
- }
-
- if (!IS_AGGR_TYPE (type2))
- return rval;
- try_second = 0;
- }
-
- if (try_second)
- {
- /* First arg may succeed; see whether second should. */
- type2 = TREE_TYPE (xarg2);
- if (TREE_CODE (type2) == OFFSET_TYPE)
- type2 = TREE_TYPE (type2);
- if (TREE_CODE (type2) == REFERENCE_TYPE)
- {
- arg2 = convert_from_reference (xarg2);
- type2 = TREE_TYPE (arg2);
- }
- else
- {
- arg2 = xarg2;
- }
-
- if (! IS_AGGR_TYPE (type2))
- try_second = 0;
- }
-
- if (type1 == unknown_type_node
- || (try_second && TREE_TYPE (xarg2) == unknown_type_node))
- {
- /* This will not be implemented in the foreseeable future. */
- return rval;
- }
-
- if (code == MODIFY_EXPR)
- fnname = ansi_assopname[(int) TREE_CODE (arg3)];
- else
- fnname = ansi_opname[(int) code];
-
- global_fn = lookup_name_nonclass (fnname);
-
- /* This is the last point where we will accept failure. This
- may be too eager if we wish an overloaded operator not to match,
- but would rather a normal operator be called on a type-converted
- argument. */
-
- if (IS_AGGR_TYPE (type1))
- {
- fields1 = lookup_fnfields (TYPE_BINFO (type1), fnname, 0);
- /* ARM $13.4.7, prefix/postfix ++/--. */
- if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
- {
- xarg2 = integer_zero_node;
- binary_is_unary = 0;
-
- if (fields1)
- {
- tree t, t2;
- int have_postfix = 0;
-
- /* Look for an `operator++ (int)'. If they didn't have
- one, then we fall back to the old way of doing things. */
- for (t = TREE_VALUE (fields1); t ; t = DECL_CHAIN (t))
- {
- t2 = TYPE_ARG_TYPES (TREE_TYPE (t));
- if (TREE_CHAIN (t2) != NULL_TREE
- && TREE_VALUE (TREE_CHAIN (t2)) == integer_type_node)
- {
- have_postfix = 1;
- break;
- }
- }
-
- if (! have_postfix)
- {
- char *op = POSTINCREMENT_EXPR ? "++" : "--";
-
- /* There's probably a LOT of code in the world that
- relies upon this old behavior. */
- if (! flag_traditional)
- pedwarn ("no `operator%s (int)' declared for postfix `%s', using prefix operator instead",
- op, op);
- xarg2 = NULL_TREE;
- binary_is_unary = 1;
- }
- }
- }
- }
-
- if (fields1 == NULL_TREE && global_fn == NULL_TREE)
- return rval;
-
- /* If RVAL winds up being `error_mark_node', we will return
- that... There is no way that normal semantics of these
- operators will succeed. */
-
- /* This argument may be an uncommitted OFFSET_REF. This is
- the case for example when dealing with static class members
- which are referenced from their class name rather than
- from a class instance. */
- if (TREE_CODE (xarg1) == OFFSET_REF
- && TREE_CODE (TREE_OPERAND (xarg1, 1)) == VAR_DECL)
- xarg1 = TREE_OPERAND (xarg1, 1);
- if (try_second && xarg2 && TREE_CODE (xarg2) == OFFSET_REF
- && TREE_CODE (TREE_OPERAND (xarg2, 1)) == VAR_DECL)
- xarg2 = TREE_OPERAND (xarg2, 1);
-
- if (global_fn)
- flags |= LOOKUP_GLOBAL;
-
- if (code == CALL_EXPR)
- {
- /* This can only be a member function. */
- return build_method_call (xarg1, fnname, xarg2,
- NULL_TREE, LOOKUP_NORMAL);
- }
- else if (tree_code_length[(int) code] == 1 || binary_is_unary)
- {
- parms = NULL_TREE;
- rval = build_method_call (xarg1, fnname, NULL_TREE, NULL_TREE, flags);
- }
- else if (code == COND_EXPR)
- {
- parms = tree_cons (0, xarg2, build_tree_list (NULL_TREE, arg3));
- rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags);
- }
- else if (code == METHOD_CALL_EXPR)
- {
- /* must be a member function. */
- parms = tree_cons (NULL_TREE, xarg2, arg3);
- return build_method_call (xarg1, fnname, parms, NULL_TREE,
- LOOKUP_NORMAL);
- }
- else if (fields1)
- {
- parms = build_tree_list (NULL_TREE, xarg2);
- rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags);
- }
- else
- {
- parms = tree_cons (NULL_TREE, xarg1,
- build_tree_list (NULL_TREE, xarg2));
- rval = build_overload_call (fnname, parms, flags,
- (struct candidate *)0);
- }
-
- return rval;
+ return build_new_op (code, flags, xarg1, xarg2, arg3);
}
/* This function takes an identifier, ID, and attempts to figure out what
@@ -1478,7 +1795,6 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
NAME is $1 from the bison rule. It is an IDENTIFIER_NODE.
VALUE is $$ from the bison rule. It is the value returned by lookup_name ($1)
- yychar is the pending input character (suitably encoded :-).
As a last ditch, try to look up the name as a label and return that
address.
@@ -1488,13 +1804,12 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
compiler faster). */
tree
-hack_identifier (value, name, yychar)
+hack_identifier (value, name)
tree value, name;
- int yychar;
{
tree type;
- if (TREE_CODE (value) == ERROR_MARK)
+ if (value == error_mark_node)
{
if (current_class_name)
{
@@ -1507,6 +1822,9 @@ hack_identifier (value, name, yychar)
fndecl = TREE_VALUE (fields);
my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 251);
+ /* I could not trigger this code. MvL */
+ my_friendly_abort (980325);
+#ifdef DEAD
if (DECL_CHAIN (fndecl) == NULL_TREE)
{
warning ("methods cannot be converted to function pointers");
@@ -1518,6 +1836,7 @@ hack_identifier (value, name, yychar)
IDENTIFIER_POINTER (name));
return error_mark_node;
}
+#endif
}
}
if (flag_labels_ok && IDENTIFIER_LABEL_VALUE (name))
@@ -1530,23 +1849,27 @@ hack_identifier (value, name, yychar)
type = TREE_TYPE (value);
if (TREE_CODE (value) == FIELD_DECL)
{
- if (current_class_decl == NULL_TREE)
+ if (current_class_ptr == NULL_TREE)
{
error ("request for member `%s' in static member function",
IDENTIFIER_POINTER (DECL_NAME (value)));
return error_mark_node;
}
- TREE_USED (current_class_decl) = 1;
+ TREE_USED (current_class_ptr) = 1;
/* Mark so that if we are in a constructor, and then find that
this field was initialized by a base initializer,
we can emit an error message. */
TREE_USED (value) = 1;
- return build_component_ref (C_C_D, name, 0, 1);
+ value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
}
-
- if (really_overloaded_fn (value))
+ else if (TREE_CODE (value) == FUNCTION_DECL
+ && DECL_FUNCTION_MEMBER_P (value))
+ /* This is a placeholder; don't mark it used. */
+ return value;
+ else if (really_overloaded_fn (value))
{
+#if 0
tree t = get_first_fn (value);
for (; t; t = DECL_CHAIN (t))
{
@@ -1556,21 +1879,46 @@ hack_identifier (value, name, yychar)
assemble_external (t);
TREE_USED (t) = 1;
}
+#endif
}
+ else if (TREE_CODE (value) == OVERLOAD)
+ /* not really overloaded function */
+ mark_used (OVL_FUNCTION (value));
else if (TREE_CODE (value) == TREE_LIST)
{
+ /* Ambiguous reference to base members, possibly other cases?. */
tree t = value;
while (t && TREE_CODE (t) == TREE_LIST)
{
- assemble_external (TREE_VALUE (t));
- TREE_USED (t) = 1;
+ mark_used (TREE_VALUE (t));
t = TREE_CHAIN (t);
}
}
+ else if (TREE_CODE (value) == NAMESPACE_DECL)
+ {
+ cp_error ("use of namespace `%D' as expression", value);
+ return error_mark_node;
+ }
+ else if (DECL_CLASS_TEMPLATE_P (value))
+ {
+ cp_error ("use of class template `%T' as expression", value);
+ return error_mark_node;
+ }
else
+ mark_used (value);
+
+ if (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL)
{
- assemble_external (value);
- TREE_USED (value) = 1;
+ tree context = decl_function_context (value);
+ if (context != NULL_TREE && context != current_function_decl
+ && ! TREE_STATIC (value))
+ {
+ cp_error ("use of %s from containing function",
+ (TREE_CODE (value) == VAR_DECL
+ ? "`auto' variable" : "parameter"));
+ cp_error_at (" `%#D' declared here", value);
+ value = error_mark_node;
+ }
}
if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value))
@@ -1578,8 +1926,7 @@ hack_identifier (value, name, yychar)
if (DECL_LANG_SPECIFIC (value)
&& DECL_CLASS_CONTEXT (value) != current_class_type)
{
- tree path;
- enum access_type access;
+ tree path, access;
register tree context
= (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value))
? DECL_CLASS_CONTEXT (value)
@@ -1589,13 +1936,13 @@ hack_identifier (value, name, yychar)
if (path)
{
access = compute_access (path, value);
- if (access != access_public)
+ if (access != access_public_node)
{
if (TREE_CODE (value) == VAR_DECL)
error ("static member `%s' is %s",
IDENTIFIER_POINTER (name),
- TREE_PRIVATE (value) ? "private" :
- "from a private base class");
+ TREE_PRIVATE (value) ? "private"
+ : "from a private base class");
else
error ("enum `%s' is from private base class",
IDENTIFIER_POINTER (name));
@@ -1603,9 +1950,8 @@ hack_identifier (value, name, yychar)
}
}
}
- return value;
}
- if (TREE_CODE (value) == TREE_LIST && TREE_NONLOCAL_FLAG (value))
+ else if (TREE_CODE (value) == TREE_LIST && TREE_NONLOCAL_FLAG (value))
{
if (type == 0)
{
@@ -1617,437 +1963,167 @@ hack_identifier (value, name, yychar)
return value;
}
- if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- my_friendly_assert (TREE_CODE (value) == VAR_DECL
- || TREE_CODE (value) == PARM_DECL
- || TREE_CODE (value) == RESULT_DECL, 252);
- return convert_from_reference (value);
- }
+ if (TREE_CODE (type) == REFERENCE_TYPE && ! processing_template_decl)
+ value = convert_from_reference (value);
return value;
}
-#if 0
-/* Given an object OF, and a type conversion operator COMPONENT
- build a call to the conversion operator, if a call is requested,
- or return the address (as a pointer to member function) if one is not.
-
- OF can be a TYPE_DECL or any kind of datum that would normally
- be passed to `build_component_ref'. It may also be NULL_TREE,
- in which case `current_class_type' and `current_class_decl'
- provide default values.
-
- BASETYPE_PATH, if non-null, is the path of basetypes
- to go through before we get the the instance of interest.
-
- PROTECT says whether we apply C++ scoping rules or not. */
-tree
-build_component_type_expr (of, component, basetype_path, protect)
- tree of, component, basetype_path;
- int protect;
-{
- tree cname = NULL_TREE;
- tree tmp, last;
- tree name;
- int flags = protect ? LOOKUP_NORMAL : LOOKUP_COMPLAIN;
-
- if (of)
- my_friendly_assert (IS_AGGR_TYPE (TREE_TYPE (of)), 253);
- my_friendly_assert (TREE_CODE (component) == TYPE_EXPR, 254);
-
- tmp = TREE_OPERAND (component, 0);
- last = NULL_TREE;
-
- while (tmp)
- {
- switch (TREE_CODE (tmp))
- {
- case CALL_EXPR:
- if (last)
- TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0);
- else
- TREE_OPERAND (component, 0) = TREE_OPERAND (tmp, 0);
-
- last = groktypename (build_tree_list (TREE_TYPE (component),
- TREE_OPERAND (component, 0)));
- name = build_typename_overload (last);
- TREE_TYPE (name) = last;
-
- if (TREE_OPERAND (tmp, 0)
- && TREE_OPERAND (tmp, 0) != void_list_node)
- {
- cp_error ("`operator %T' requires empty parameter list", last);
- TREE_OPERAND (tmp, 0) = NULL_TREE;
- }
-
- if (of && TREE_CODE (of) != TYPE_DECL)
- return build_method_call (of, name, NULL_TREE, NULL_TREE, flags);
- else if (of)
- {
- tree this_this;
-
- if (current_class_decl == NULL_TREE)
- {
- cp_error ("object required for `operator %T' call",
- TREE_TYPE (name));
- return error_mark_node;
- }
-
- this_this = convert_pointer_to (TREE_TYPE (of),
- current_class_decl);
- this_this = build_indirect_ref (this_this, NULL_PTR);
- return build_method_call (this_this, name, NULL_TREE,
- NULL_TREE, flags | LOOKUP_NONVIRTUAL);
- }
- else if (current_class_decl)
- return build_method_call (tmp, name, NULL_TREE, NULL_TREE, flags);
-
- cp_error ("object required for `operator %T' call",
- TREE_TYPE (name));
- return error_mark_node;
-
- case INDIRECT_REF:
- case ADDR_EXPR:
- case ARRAY_REF:
- break;
-
- case SCOPE_REF:
- my_friendly_assert (cname == 0, 255);
- cname = TREE_OPERAND (tmp, 0);
- tmp = TREE_OPERAND (tmp, 1);
- break;
-
- default:
- my_friendly_abort (77);
- }
- last = tmp;
- tmp = TREE_OPERAND (tmp, 0);
- }
-
- last = groktypename (build_tree_list (TREE_TYPE (component), TREE_OPERAND (component, 0)));
- name = build_typename_overload (last);
- TREE_TYPE (name) = last;
- if (of && TREE_CODE (of) == TYPE_DECL)
- {
- if (cname == NULL_TREE)
- {
- cname = DECL_NAME (of);
- of = NULL_TREE;
- }
- else my_friendly_assert (cname == DECL_NAME (of), 256);
- }
-
- if (of)
- {
- tree this_this;
-
- if (current_class_decl == NULL_TREE)
- {
- cp_error ("object required for `operator %T' call",
- TREE_TYPE (name));
- return error_mark_node;
- }
-
- this_this = convert_pointer_to (TREE_TYPE (of), current_class_decl);
- return build_component_ref (this_this, name, 0, protect);
- }
- else if (cname)
- return build_offset_ref (cname, name);
- else if (current_class_name)
- return build_offset_ref (current_class_name, name);
-
- cp_error ("object required for `operator %T' member reference",
- TREE_TYPE (name));
- return error_mark_node;
-}
-#endif
-
-static char *
-thunk_printable_name (decl)
- tree decl;
-{
- return "<thunk function>";
-}
-
tree
make_thunk (function, delta)
tree function;
int delta;
{
- char buffer[250];
- tree thunk_fndecl, thunk_id;
+ tree thunk_id;
tree thunk;
- char *func_name;
- static int thunk_number = 0;
tree func_decl;
+
if (TREE_CODE (function) != ADDR_EXPR)
abort ();
func_decl = TREE_OPERAND (function, 0);
if (TREE_CODE (func_decl) != FUNCTION_DECL)
abort ();
- func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func_decl));
- if (delta<=0)
- sprintf (buffer, "__thunk_%d_%s", -delta, func_name);
+
+ OB_INIT ();
+ OB_PUTS ("__thunk_");
+ if (delta > 0)
+ {
+ OB_PUTC ('n');
+ icat (delta);
+ }
else
- sprintf (buffer, "__thunk_n%d_%s", delta, func_name);
- thunk_id = get_identifier (buffer);
+ icat (-delta);
+ OB_PUTC ('_');
+ OB_PUTID (DECL_ASSEMBLER_NAME (func_decl));
+ OB_FINISH ();
+ thunk_id = get_identifier (obstack_base (&scratch_obstack));
+
thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
if (thunk && TREE_CODE (thunk) != THUNK_DECL)
{
- error_with_decl ("implementation-reserved name `%s' used");
- IDENTIFIER_GLOBAL_VALUE (thunk_id) = thunk = NULL_TREE;
+ cp_error ("implementation-reserved name `%D' used", thunk_id);
+ thunk = NULL_TREE;
+ SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk);
}
if (thunk == NULL_TREE)
{
- thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl));
- DECL_RESULT (thunk)
- = 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);
+ thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));
+ TREE_READONLY (thunk) = TREE_READONLY (func_decl);
+ TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl);
+ comdat_linkage (thunk);
+ TREE_SET_CODE (thunk, THUNK_DECL);
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta;
+ DECL_EXTERNAL (thunk) = 1;
+ DECL_ARTIFICIAL (thunk) = 1;
/* So that finish_file can write out any thunks that need to be: */
pushdecl_top_level (thunk);
}
return thunk;
}
+/* Emit the definition of a C++ multiple inheritance vtable thunk. */
+
void
emit_thunk (thunk_fndecl)
- tree thunk_fndecl;
+ tree thunk_fndecl;
{
- rtx insns;
- char *fnname;
- char buffer[250];
- tree argp;
- struct args_size stack_args_size;
tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0);
int delta = THUNK_DELTA (thunk_fndecl);
- int tem;
- int failure = 0;
- int current_call_is_indirect = 0; /* needed for HPPA FUNCTION_ARG */
-
- /* Used to remember which regs we need to emit a USE rtx for. */
- rtx need_use[FIRST_PSEUDO_REGISTER];
- int need_use_count = 0;
-
- /* rtx for the 'this' parameter. */
- rtx this_rtx = 0, this_reg_rtx = 0, fixed_this_rtx;
-
- char *(*save_decl_printable_name) () = decl_printable_name;
- /* Data on reg parms scanned so far. */
- CUMULATIVE_ARGS args_so_far;
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
- if (TREE_PUBLIC (function))
- {
- TREE_PUBLIC (thunk_fndecl) = 1;
- if (DECL_EXTERNAL (function))
- {
- DECL_EXTERNAL (thunk_fndecl) = 1;
- assemble_external (thunk_fndecl);
- return;
- }
- }
+ TREE_ADDRESSABLE (function) = 1;
+ mark_used (function);
- decl_printable_name = thunk_printable_name;
if (current_function_decl)
abort ();
- current_function_decl = thunk_fndecl;
- init_function_start (thunk_fndecl, input_filename, lineno);
- pushlevel (0);
- expand_start_bindings (1);
-
- /* Start updating where the next arg would go. */
- INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (function), NULL_RTX);
- stack_args_size.constant = 0;
- stack_args_size.var = 0;
- /* SETUP for possible structure return address FIXME */
-
- /* Now look through all the parameters, make sure that we
- don't clobber any registers used for parameters.
- Also, pick up an rtx for the first "this" parameter. */
- for (argp = TYPE_ARG_TYPES (TREE_TYPE (function));
- argp != NULL_TREE;
- argp = TREE_CHAIN (argp))
- {
- tree passed_type = TREE_VALUE (argp);
- register rtx entry_parm;
- int named = 1; /* FIXME */
- struct args_size stack_offset;
- struct args_size arg_size;
-
- if (passed_type == void_type_node)
- break;
-
- if ((TREE_CODE (TYPE_SIZE (passed_type)) != INTEGER_CST
- && contains_placeholder_p (TYPE_SIZE (passed_type)))
-#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
- || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far,
- TYPE_MODE (passed_type),
- passed_type, named)
-#endif
- )
- passed_type = build_pointer_type (passed_type);
-
- entry_parm = FUNCTION_ARG (args_so_far,
- TYPE_MODE (passed_type),
- passed_type,
- named);
- if (entry_parm != 0)
- need_use[need_use_count++] = entry_parm;
-
- locate_and_pad_parm (TYPE_MODE (passed_type), passed_type,
-#ifdef STACK_PARMS_IN_REG_PARM_AREA
- 1,
-#else
- entry_parm != 0,
-#endif
- thunk_fndecl,
- &stack_args_size, &stack_offset, &arg_size);
-
-/* REGNO (entry_parm);*/
- if (this_rtx == 0)
- {
- this_reg_rtx = entry_parm;
- if (!entry_parm)
- {
- rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
-
- rtx internal_arg_pointer, stack_parm;
-
- if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
- || ! (fixed_regs[ARG_POINTER_REGNUM]
- || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM)))
- internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx);
- else
- internal_arg_pointer = virtual_incoming_args_rtx;
-
- if (offset_rtx == const0_rtx)
- entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type),
- internal_arg_pointer);
- else
- entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type),
- gen_rtx (PLUS, Pmode,
- internal_arg_pointer,
- offset_rtx));
- }
-
- this_rtx = entry_parm;
- }
-
- FUNCTION_ARG_ADVANCE (args_so_far,
- TYPE_MODE (passed_type),
- passed_type,
- named);
- }
-
- fixed_this_rtx = plus_constant (this_rtx, delta);
- if (this_rtx != fixed_this_rtx)
- emit_move_insn (this_rtx, fixed_this_rtx);
-
- if (this_reg_rtx)
- emit_insn (gen_rtx (USE, VOIDmode, this_reg_rtx));
-
- emit_indirect_jump (XEXP (DECL_RTL (function), 0));
-
- while (need_use_count > 0)
- emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count]));
-
- expand_end_bindings (NULL, 1, 0);
- poplevel (0, 0, 1);
-
- /* From now on, allocate rtl in current_obstack, not in saveable_obstack.
- Note that that may have been done above, in save_for_inline_copying.
- The call to resume_temporary_allocation near the end of this function
- goes back to the usual state of affairs. */
-
- rtl_in_current_obstack ();
-
- insns = get_insns ();
-
- /* Copy any shared structure that should not be shared. */
-
- unshare_all_rtl (insns);
-
- /* Instantiate all virtual registers. */
-
- instantiate_virtual_regs (current_function_decl, get_insns ());
-
- /* We are no longer anticipating cse in this function, at least. */
-
- cse_not_expected = 1;
-
- /* Now we choose between stupid (pcc-like) register allocation
- (if we got the -noreg switch and not -opt)
- and smart register allocation. */
-
- if (optimize > 0) /* Stupid allocation probably won't work */
- obey_regdecls = 0; /* if optimizations being done. */
-
- regclass_init ();
-
- regclass (insns, max_reg_num ());
- if (obey_regdecls)
- {
- stupid_life_analysis (insns, max_reg_num (), NULL);
- failure = reload (insns, 0, NULL);
- }
- else
- {
- /* Do control and data flow analysis,
- and write some of the results to dump file. */
-
- flow_analysis (insns, max_reg_num (), NULL);
- local_alloc ();
- failure = global_alloc (NULL);
- }
-
- reload_completed = 1;
-
-#ifdef LEAF_REGISTERS
- leaf_function = 0;
- if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ())
- leaf_function = 1;
-#endif
-
- /* If a machine dependent reorganization is needed, call it. */
-#ifdef MACHINE_DEPENDENT_REORG
- MACHINE_DEPENDENT_REORG (insns);
-#endif
-
- /* Now turn the rtl into assembler code. */
-
- {
- char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
- assemble_start_function (thunk_fndecl, fnname);
- final (insns, asm_out_file, optimize, 0);
- assemble_end_function (thunk_fndecl, fnname);
- };
-
- exit_rest_of_compilation:
+ TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL);
- reload_completed = 0;
-
- /* Cancel the effect of rtl_in_current_obstack. */
-
- resume_temporary_allocation ();
+ {
+#ifdef ASM_OUTPUT_MI_THUNK
+ char *fnname;
+ current_function_decl = thunk_fndecl;
+ /* Make sure we build up its RTL before we go onto the
+ temporary obstack. */
+ make_function_rtl (thunk_fndecl);
+ temporary_allocation ();
+ DECL_RESULT (thunk_fndecl)
+ = build_decl (RESULT_DECL, 0, integer_type_node);
+ fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
+ init_function_start (thunk_fndecl, input_filename, lineno);
+ current_function_is_thunk = 1;
+ assemble_start_function (thunk_fndecl, fnname);
+ ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
+ assemble_end_function (thunk_fndecl, fnname);
+ permanent_allocation (1);
+ current_function_decl = 0;
+#else /* ASM_OUTPUT_MI_THUNK */
+ /* If we don't have the necessary macro for efficient thunks, generate a
+ thunk function that just makes a call to the real function.
+ Unfortunately, this doesn't work for varargs. */
+
+ tree a, t;
+
+ if (varargs_function_p (function))
+ cp_error ("generic thunk code fails for method `%#D' which uses `...'",
+ function);
+
+ /* Set up clone argument trees for the thunk. */
+ t = NULL_TREE;
+ for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
+ {
+ tree x = copy_node (a);
+ TREE_CHAIN (x) = t;
+ DECL_CONTEXT (x) = thunk_fndecl;
+ t = x;
+ }
+ a = nreverse (t);
+ DECL_ARGUMENTS (thunk_fndecl) = a;
+ DECL_RESULT (thunk_fndecl) = NULL_TREE;
+ DECL_LANG_SPECIFIC (thunk_fndecl) = DECL_LANG_SPECIFIC (function);
+ copy_lang_decl (thunk_fndecl);
+ DECL_INTERFACE_KNOWN (thunk_fndecl) = 1;
+ DECL_NOT_REALLY_EXTERN (thunk_fndecl) = 1;
+
+ start_function (NULL_TREE, thunk_fndecl, NULL_TREE, 1);
+ store_parm_decls ();
+ current_function_is_thunk = 1;
+
+ /* Build up the call to the real function. */
+ t = build_int_2 (delta, -1 * (delta < 0));
+ TREE_TYPE (t) = signed_type (sizetype);
+ t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t));
+ t = expr_tree_cons (NULL_TREE, t, NULL_TREE);
+ for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
+ t = expr_tree_cons (NULL_TREE, a, t);
+ t = nreverse (t);
+ t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t);
+ c_expand_return (t);
+
+ finish_function (lineno, 0, 0);
+
+ /* Don't let the backend defer this function. */
+ if (DECL_DEFER_OUTPUT (thunk_fndecl))
+ {
+ output_inline_function (thunk_fndecl);
+ permanent_allocation (1);
+ }
+#endif /* ASM_OUTPUT_MI_THUNK */
+ }
- decl_printable_name = save_decl_printable_name;
- current_function_decl = 0;
+ TREE_SET_CODE (thunk_fndecl, THUNK_DECL);
}
/* Code for synthesizing methods which have default semantics defined. */
/* For the anonymous union in TYPE, return the member that is at least as
large as the rest of the members, so we can copy it. */
+
static tree
largest_union_member (type)
tree type;
@@ -2064,7 +2140,8 @@ largest_union_member (type)
}
/* Generate code for default X(X&) constructor. */
-void
+
+static void
do_build_copy_constructor (fndecl)
tree fndecl;
{
@@ -2078,9 +2155,13 @@ do_build_copy_constructor (fndecl)
parm = TREE_CHAIN (parm);
parm = convert_from_reference (parm);
- if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
+ if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)
+ && is_empty_class (current_class_type))
+ /* Don't copy the padding byte; it might not have been allocated
+ if *this is a base subobject. */;
+ else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
{
- t = build (INIT_EXPR, void_type_node, C_C_D, parm);
+ t = build (INIT_EXPR, void_type_node, current_class_ref, parm);
TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t);
}
@@ -2099,8 +2180,12 @@ do_build_copy_constructor (fndecl)
(build_reference_type (basetype), parm,
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
p = convert_from_reference (p);
- current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
- p, current_base_init_list);
+
+ if (p == error_mark_node)
+ cp_error ("in default copy constructor");
+ else
+ current_base_init_list = tree_cons (basetype,
+ p, current_base_init_list);
}
for (i = 0; i < n_bases; ++i)
@@ -2113,17 +2198,25 @@ do_build_copy_constructor (fndecl)
p = convert_to_reference
(build_reference_type (basetype), parm,
CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
- p = convert_from_reference (p);
- current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
- p, current_base_init_list);
+
+ if (p == error_mark_node)
+ cp_error ("in default copy constructor");
+ else
+ {
+ p = convert_from_reference (p);
+ current_base_init_list = tree_cons (basetype,
+ p, current_base_init_list);
+ }
}
for (; fields; fields = TREE_CHAIN (fields))
{
- tree name, init, t;
+ tree init, t;
tree field = fields;
if (TREE_CODE (field) != FIELD_DECL)
continue;
+
+ init = parm;
if (DECL_NAME (field))
{
if (VFIELD_NAME_P (DECL_NAME (field)))
@@ -2136,14 +2229,22 @@ do_build_copy_constructor (fndecl)
continue;
}
else if ((t = TREE_TYPE (field)) != NULL_TREE
- && TREE_CODE (t) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+ && ANON_UNION_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE)
- field = largest_union_member (t);
+ {
+ do
+ {
+ init = build (COMPONENT_REF, t, init, field);
+ field = largest_union_member (t);
+ }
+ while ((t = TREE_TYPE (field)) != NULL_TREE
+ && ANON_UNION_TYPE_P (t)
+ && TYPE_FIELDS (t) != NULL_TREE);
+ }
else
continue;
- init = build (COMPONENT_REF, TREE_TYPE (field), parm, field);
+ init = build (COMPONENT_REF, TREE_TYPE (field), init, field);
init = build_tree_list (NULL_TREE, init);
current_member_init_list
@@ -2157,7 +2258,7 @@ do_build_copy_constructor (fndecl)
pop_momentary ();
}
-void
+static void
do_build_assign_ref (fndecl)
tree fndecl;
{
@@ -2168,9 +2269,13 @@ do_build_assign_ref (fndecl)
parm = convert_from_reference (parm);
- if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
+ if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)
+ && is_empty_class (current_class_type))
+ /* Don't copy the padding byte; it might not have been allocated
+ if *this is a base subobject. */;
+ else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
{
- tree t = build (MODIFY_EXPR, void_type_node, C_C_D, parm);
+ tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm);
TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t);
}
@@ -2184,17 +2289,13 @@ do_build_assign_ref (fndecl)
for (i = 0; i < n_bases; ++i)
{
tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
- if (TYPE_HAS_ASSIGN_REF (basetype))
- {
- tree p = convert_to_reference
- (build_reference_type (basetype), parm,
- CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
- p = convert_from_reference (p);
- p = build_member_call (TYPE_NESTED_NAME (basetype),
- ansi_opname [MODIFY_EXPR],
- build_tree_list (NULL_TREE, p));
- expand_expr_stmt (p);
- }
+ tree p = convert_to_reference
+ (build_reference_type (basetype), parm,
+ CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
+ p = convert_from_reference (p);
+ p = build_member_call (basetype, ansi_opname [MODIFY_EXPR],
+ build_expr_list (NULL_TREE, p));
+ expand_expr_stmt (p);
}
for (; fields; fields = TREE_CHAIN (fields))
{
@@ -2203,6 +2304,27 @@ do_build_assign_ref (fndecl)
if (TREE_CODE (field) != FIELD_DECL)
continue;
+
+ if (TREE_READONLY (field))
+ {
+ if (DECL_NAME (field))
+ cp_error ("non-static const member `%#D', can't use default assignment operator", field);
+ else
+ cp_error ("non-static const member in type `%T', can't use default assignment operator", current_class_type);
+ continue;
+ }
+ else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
+ {
+ if (DECL_NAME (field))
+ cp_error ("non-static reference member `%#D', can't use default assignment operator", field);
+ else
+ cp_error ("non-static reference member in type `%T', can't use default assignment operator", current_class_type);
+ continue;
+ }
+
+ comp = current_class_ref;
+ init = parm;
+
if (DECL_NAME (field))
{
if (VFIELD_NAME_P (DECL_NAME (field)))
@@ -2215,42 +2337,49 @@ do_build_assign_ref (fndecl)
continue;
}
else if ((t = TREE_TYPE (field)) != NULL_TREE
- && TREE_CODE (t) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+ && ANON_UNION_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE)
- field = largest_union_member (t);
+ {
+ do
+ {
+ comp = build (COMPONENT_REF, t, comp, field);
+ init = build (COMPONENT_REF, t, init, field);
+ field = largest_union_member (t);
+ }
+ while ((t = TREE_TYPE (field)) != NULL_TREE
+ && ANON_UNION_TYPE_P (t)
+ && TYPE_FIELDS (t) != NULL_TREE);
+ }
else
continue;
- comp = build (COMPONENT_REF, TREE_TYPE (field), C_C_D, field);
- init = build (COMPONENT_REF, TREE_TYPE (field), parm, field);
+ comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field);
+ init = build (COMPONENT_REF, TREE_TYPE (field), init, field);
expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
}
}
- c_expand_return (C_C_D);
+ c_expand_return (current_class_ref);
pop_momentary ();
}
-void push_cp_function_context ();
-void pop_cp_function_context ();
-
void
synthesize_method (fndecl)
tree fndecl;
{
int nested = (current_function_decl != NULL_TREE);
- tree context = decl_function_context (fndecl);
- char *f = input_filename;
- tree base = DECL_CLASS_CONTEXT (fndecl);
+ tree context = hack_decl_function_context (fndecl);
+
+ if (at_eof)
+ import_export_decl (fndecl);
- if (nested)
+ if (! context)
+ push_to_top_level ();
+ else if (nested)
push_cp_function_context (context);
- 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, NULL_TREE, 1);
+ interface_unknown = 1;
+ start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR])
@@ -2270,18 +2399,9 @@ synthesize_method (fndecl)
finish_function (lineno, 0, nested);
- /* Do we really *want* to inline this function? */
- if (DECL_INLINE (fndecl))
- {
- /* Turn off DECL_INLINE for the moment so function_cannot_inline_p
- will check our size. */
- DECL_INLINE (fndecl) = 0;
- if (function_cannot_inline_p (fndecl) == 0)
- DECL_INLINE (fndecl) = 1;
- }
-
- input_filename = f;
extract_interface_info ();
- if (nested)
+ if (! context)
+ pop_from_top_level ();
+ else if (nested)
pop_cp_function_context (context);
}
diff --git a/contrib/gcc/cp/mpw-config.in b/contrib/gcc/cp/mpw-config.in
new file mode 100644
index 0000000..88dd85f
--- /dev/null
+++ b/contrib/gcc/cp/mpw-config.in
@@ -0,0 +1,11 @@
+# Configuration fragment for G++.
+# Most of the real configuration work happens in the main GCC configure.
+
+# We need to join some lines in the Makefile.in before the sed
+# process will work properly. The funky little sed script works by
+# recognizing lines with a trailing '$@ \', adding the next line to
+# its "pattern space", editing out the backslash and line, then
+# putting the result out.
+
+sed -e '/$@ \\/{N;s/$@ \\./$@ /;P;D;}' \Option-d
+ "{srcdir}"Makefile.in >"{o}"hacked_Makefile.in
diff --git a/contrib/gcc/cp/mpw-make.sed b/contrib/gcc/cp/mpw-make.sed
new file mode 100644
index 0000000..120b5a1
--- /dev/null
+++ b/contrib/gcc/cp/mpw-make.sed
@@ -0,0 +1,112 @@
+# Sed commands to finish translating the G++ Unix makefile into MPW syntax.
+
+# Remove control-Ls, they upset MPW make.
+s/ //g
+
+# Remove references to always-empty variables used to mark things.
+/CYGNUS-LOCAL-/s/{CYGNUS-LOCAL-[a-z0-9]*}//g
+
+# Add a bunch of definitions, mostly empty.
+/^# Variables that exist for you to override.$/a\
+\
+xmake_file = \
+tmake_file = \
+build_xm_file = \
+MALLOC = \
+MD_DEPS = \
+REAL_H = \
+HOST_CC_LD = {CC_LD}\
+ALL_CCLDFLAGS = \
+HOST_CCLDFLAGS = \
+CONFIG_H = \
+LIBDEPS = \
+
+# The "target" variable is special to MPW make, avoid it.
+/{target}/s/{target}/{target_canonical}/g
+
+# Suppress the suppression of smart makes.
+/^\.y\.c/d
+
+# Whack out "..." assignments.
+/\.\.\./s/^\([a-z_]*= \.\.\.\)/#\1/
+
+# Previous edits go a little overboard, undo.
+/^objext = /s/"{o}"//
+
+# Always link in low-level MPW functions.
+/^LIBDEPS=/s/$/ ::strerror.c.o ::mpwlib.c.o/
+/{CLIB}/s/{CLIB}/ ::strerror.c.o ::mpwlib.c.o {CLIB}/
+
+# Don't get tricky about finding various .o file, point at dir above.
+/^SUBDIR_OBSTACK/s/`.*`/::obstack.c.o/
+/^SUBDIR_USE_ALLOCA/s/`.*`/::alloca.c.o/
+/^SUBDIR_MALLOC/s/`.*`//
+
+# Point includes at parent directly correctly.
+/^INCLUDES = /s/:\./::/g
+/^INCLUDES = /s/"{srcdir}"\.\./"{topsrcdir}"gcc:/g
+/^INCLUDES = /s,"{srcdir}"/\.\.,"{topsrcdir}"gcc:,g
+/^INCLUDES = /s,"{srcdir}":config,"{topsrcdir}"gcc:config:,g
+
+# Add the special MPW include dirs.
+/^INCLUDES = /s/$/ -i "{topsrcdir}"include:mpw: -i :::extra-include:/
+
+# A nasty hack to reduce confusion.
+/true/s/ ; @true$//
+
+# (should be in common translation?)
+/{CC_LD} /s/$/ {EXTRALIBS}/
+
+# Don't use general compiler flags (which may include definitions
+# and other compiler-only bits) with linking commands.
+/{CC_LD} /s/ALL_CFLAGS/ALL_CCLDFLAGS/
+
+# Whack out build rules that are not useful.
+/^Makefile \\Option-f /,/^$/d
+/^config.status \\Option-f /,/^$/d
+# (Note that MPW make is not case sensitive, and so this name
+# is considered the same as "md_file".)
+/^{MD_FILE} \\Option-f/,/^$/d
+
+# Depending on config.status is not useful for us.
+/config.status/s/ config.status//
+
+# Repeat of stuff from generic edit.
+/{s}/s/"{s}""{s}"/"{s}"/g
+/{s}/s/"{s}""{srcdir}"/"{s}"/g
+/{s}/s/"{srcdir}""{s}"/"{s}"/g
+
+# Fix references to C frontend files in main dir.
+/::c-/s/"{o}"::c-/"{o}":c-/g
+
+# Fix pathnames to generated files in the objdir.
+/parse/s/"{s}"parse\.\([chy]\)/"{o}"parse.\1/g
+/parse/s/^parse\.\([chy]\)/"{o}"parse.\1/
+/y.tab.c/s/"{s}"y\.tab\.c/"{o}"y.tab.c/g
+/y.tab.c/s/^y\.tab\.c/"{o}"y.tab.c/
+/y.tab.h/s/"{s}"y\.tab\.h/"{o}"y.tab.h/g
+/y.tab.h/s/^y\.tab\.h/"{o}"y.tab.h/
+
+# Put in the definition of YYEMPTY directly.
+/grep/s/grep .* >>/Echo '#define YYEMPTY -1' >>/
+
+# If the dates are wrong, then this tries to run gperf, which we don't
+# really want.
+/^"{srcdir}"hash.h/,/hash.h$/d
+
+# Sed the object file list instead of using cat (meow).
+/cat/s/`cat /`sed -e 's,:,::,g' -e 's,{objext},.o,g' /
+
+# Simplify dependencies of generated parser files.
+/^{PARSE_C}/s/^/#/
+/^stamp-parse/s/^stamp-parse/{PARSE_C}/
+
+# Fix the compile line for the generated parser.
+/{CC} -c/,/echo {PARSE_C}/c\
+ {CC} @DASH_C_FLAG@ {ALL_CFLAGS} {ALL_CPPFLAGS} {INCLUDES} {BIG_SWITCHFLAG} "{o}"parse.c -o "{o}"parse.c.o\
+
+# Change all Rez commands to use mac-gcc.r.
+/{REZ}/s/"{s}"[-a-zA-Z{}]*\.r/"{topsrcdir}"gcc:mac-gcc.r/
+
+# Remove pathname junk from the container name.
+/{REZ}/s/'"'::cc1plus'"'/'"'cc1plus'"'/
diff --git a/contrib/gcc/cp/new.cc b/contrib/gcc/cp/new.cc
new file mode 100644
index 0000000..28187a4
--- /dev/null
+++ b/contrib/gcc/cp/new.cc
@@ -0,0 +1,42 @@
+// Implementation file for the -*- C++ -*- dynamic memory management header.
+// Copyright (C) 1996 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#pragma implementation "new"
+#include "new"
+
+const std::nothrow_t std::nothrow = { };
+
+using std::new_handler;
+new_handler __new_handler;
+
+new_handler
+set_new_handler (new_handler handler)
+{
+ new_handler prev_handler = __new_handler;
+ __new_handler = handler;
+ return prev_handler;
+}
diff --git a/contrib/gcc/cp/new1.cc b/contrib/gcc/cp/new1.cc
new file mode 100644
index 0000000..5bb85c9
--- /dev/null
+++ b/contrib/gcc/cp/new1.cc
@@ -0,0 +1,89 @@
+// Support routines for the -*- C++ -*- dynamic memory management.
+// Copyright (C) 1997 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#include "new"
+using std::new_handler;
+using std::bad_alloc;
+
+extern "C" void *malloc (size_t);
+extern new_handler __new_handler;
+
+#define WEAK(x) \
+ x __attribute__ ((weak)); \
+ x
+
+#ifdef L_op_newnt
+WEAK (void * operator new (size_t sz, const std::nothrow_t&) throw())
+{
+ void *p;
+
+ /* malloc (0) is unpredictable; avoid it. */
+ if (sz == 0)
+ sz = 1;
+ p = (void *) malloc (sz);
+ while (p == 0)
+ {
+ new_handler handler = __new_handler;
+ if (! handler)
+ return 0;
+ try
+ {
+ handler ();
+ }
+ catch (bad_alloc &)
+ {
+ return 0;
+ }
+
+ p = (void *) malloc (sz);
+ }
+
+ return p;
+}
+#endif
+
+#ifdef L_op_new
+WEAK (void * operator new (size_t sz) throw (std::bad_alloc))
+{
+ void *p;
+
+ /* malloc (0) is unpredictable; avoid it. */
+ if (sz == 0)
+ sz = 1;
+ p = (void *) malloc (sz);
+ while (p == 0)
+ {
+ new_handler handler = __new_handler;
+ if (! handler)
+ throw bad_alloc ();
+ handler ();
+ p = (void *) malloc (sz);
+ }
+
+ return p;
+}
+#endif
diff --git a/contrib/gcc/cp/new2.cc b/contrib/gcc/cp/new2.cc
new file mode 100644
index 0000000..0be1c0d
--- /dev/null
+++ b/contrib/gcc/cp/new2.cc
@@ -0,0 +1,80 @@
+// Boilerplate support routines for -*- C++ -*- dynamic memory management.
+// Copyright (C) 1997 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#include "new"
+
+extern "C" void free (void *);
+
+#define WEAK(x) \
+ x __attribute__ ((weak)); \
+ x
+
+#ifdef L_op_vnew
+WEAK(void * operator new[] (size_t sz) throw (std::bad_alloc))
+{
+ return ::operator new(sz);
+}
+#endif
+
+#ifdef L_op_vnewnt
+WEAK(void *operator new[] (size_t sz, const std::nothrow_t& nothrow) throw())
+{
+ return ::operator new(sz, nothrow);
+}
+#endif
+
+#ifdef L_op_delete
+WEAK (void operator delete (void *ptr) throw ())
+{
+ if (ptr)
+ free (ptr);
+}
+#endif
+
+#ifdef L_op_vdel
+WEAK (void operator delete[] (void *ptr) throw ())
+{
+ if (ptr)
+ free (ptr);
+}
+#endif
+
+#ifdef L_op_delnt
+WEAK (void operator delete (void *ptr, const std::nothrow_t&) throw ())
+{
+ if (ptr)
+ free (ptr);
+}
+#endif
+
+#ifdef L_op_vdelnt
+WEAK (void operator delete[] (void *ptr, const std::nothrow_t&) throw ())
+{
+ if (ptr)
+ free (ptr);
+}
+#endif
diff --git a/contrib/gcc/cp/parse.y b/contrib/gcc/cp/parse.y
index fd034af..279cec3 100644
--- a/contrib/gcc/cp/parse.y
+++ b/contrib/gcc/cp/parse.y
@@ -1,5 +1,5 @@
/* YACC parser for C++ syntax.
- Copyright (C) 1988, 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 89, 93, 94, 95, 1996 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -32,8 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
-#include <stdio.h>
-#include <errno.h>
+#include "system.h"
#include "tree.h"
#include "input.h"
@@ -41,6 +40,8 @@ Boston, MA 02111-1307, USA. */
#include "lex.h"
#include "cp-tree.h"
#include "output.h"
+#include "except.h"
+#include "toplev.h"
/* Since parsers are distinct for each language, put the language string
definition here. (fnf) */
@@ -49,18 +50,7 @@ char *language_string = "GNU C++";
extern tree void_list_node;
extern struct obstack permanent_obstack;
-#ifndef errno
-extern int errno;
-#endif
-
extern int end_of_file;
-extern int current_class_depth;
-
-/* FSF LOCAL dje prefix attributes */
-extern tree strip_attrs PROTO((tree));
-/* END FSF LOCAL */
-
-void yyerror ();
/* Like YYERROR but do call yyerror. */
#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
@@ -72,12 +62,12 @@ void yyerror ();
error message if the user supplies an empty conditional expression. */
static char *cond_stmt_keyword;
+static tree empty_parms PROTO((void));
+
/* Nonzero if we have an `extern "C"' acting as an extern specifier. */
int have_extern_spec;
int used_extern_spec;
-void yyhook ();
-
/* Cons up an empty parameter list. */
#ifdef __GNUC__
__inline
@@ -87,17 +77,19 @@ empty_parms ()
{
tree parms;
- if (strict_prototype)
+ if (strict_prototype
+ || current_class_type != NULL)
parms = void_list_node;
else
parms = NULL_TREE;
return parms;
}
+
%}
%start program
-%union {long itype; tree ttype; char *strtype; enum tree_code code; }
+%union {long itype; tree ttype; char *strtype; enum tree_code code; flagged_type_tree ftype; }
/* All identifiers that are not reserved words
and are not declared typedefs in the current block */
@@ -107,6 +99,10 @@ empty_parms ()
In some contexts, they are treated just like IDENTIFIER,
but they can also serve as typespecs in declarations. */
%token TYPENAME
+%token SELFNAME
+
+/* A template function. */
+%token PFUNCNAME
/* Reserved words that specify storage class.
yylval contains an IDENTIFIER_NODE which indicates which one. */
@@ -118,7 +114,7 @@ empty_parms ()
/* Reserved words that qualify type: "const" or "volatile".
yylval contains an IDENTIFIER_NODE which indicates which one. */
-%token TYPE_QUAL
+%token CV_QUALIFIER
/* Character or numeric constants.
yylval is the node for the constant. */
@@ -132,16 +128,17 @@ empty_parms ()
%token ELLIPSIS
/* the reserved words */
-/* SCO include files test "ASM", so use something else. */
+/* 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 BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF
%token SIGOF
%token ATTRIBUTE EXTENSION LABEL
+%token REALPART IMAGPART
/* the reserved words... C++ extensions */
%token <ttype> AGGR
-%token <itype> VISSPEC
-%token DELETE NEW OVERLOAD THIS OPERATOR CXX_TRUE CXX_FALSE
+%token <ttype> VISSPEC
+%token DELETE NEW THIS OPERATOR CXX_TRUE CXX_FALSE
%token NAMESPACE TYPENAME_KEYWORD USING
%token LEFT_RIGHT TEMPLATE
%token TYPEID DYNAMIC_CAST STATIC_CAST REINTERPRET_CAST CONST_CAST
@@ -159,7 +156,7 @@ empty_parms ()
%nonassoc IF
%nonassoc ELSE
-%left IDENTIFIER TYPENAME PTYPENAME SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR ELLIPSIS TYPEOF SIGOF OPERATOR NSNAME TYPENAME_KEYWORD
+%left IDENTIFIER PFUNCNAME TYPENAME SELFNAME PTYPENAME SCSPEC TYPESPEC CV_QUALIFIER ENUM AGGR ELLIPSIS TYPEOF SIGOF OPERATOR NSNAME TYPENAME_KEYWORD
%left '{' ',' ';'
@@ -190,14 +187,15 @@ empty_parms ()
%type <code> unop
%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist
-%type <ttype> paren_expr_or_null nontrivial_exprlist
+%type <ttype> PFUNCNAME maybe_identifier
+%type <ttype> paren_expr_or_null nontrivial_exprlist SELFNAME
%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
-%type <ttype> typed_declspecs reserved_declspecs boolean.literal
-%type <ttype> typed_typespecs reserved_typespecquals
-%type <ttype> declmods typespec typespecqual_reserved
-%type <ttype> SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual
+%type <ttype> reserved_declspecs boolean.literal
+%type <ttype> reserved_typespecquals
+%type <ttype> declmods
+%type <ttype> SCSPEC TYPESPEC CV_QUALIFIER maybe_cv_qualifier
%type <itype> initdecls notype_initdecls initdcl /* C++ modification */
-%type <ttype> init initlist maybeasm maybe_init
+%type <ttype> init initlist maybeasm maybe_init defarg defarg1
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
%type <ttype> any_word
@@ -207,77 +205,84 @@ empty_parms ()
%type <ttype> declarator notype_declarator after_type_declarator
%type <ttype> direct_notype_declarator direct_after_type_declarator
-%type <ttype> structsp opt.component_decl_list component_decl_list
+%type <ttype> opt.component_decl_list component_decl_list
%type <ttype> component_decl component_decl_1 components notype_components
-%type <ttype> component_declarator component_declarator0
+%type <ttype> component_declarator component_declarator0 self_reference
%type <ttype> notype_component_declarator notype_component_declarator0
%type <ttype> after_type_component_declarator after_type_component_declarator0
%type <ttype> enumlist enumerator
-%type <ttype> type_id absdcl type_quals
+%type <ttype> absdcl cv_qualifiers
%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> new_declarator direct_new_declarator
+%type <ttype> xexpr parmlist parms bad_parm
%type <ttype> identifiers_or_typenames
%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> template_id do_id object_template_id notype_template_declarator
%type <ttype> overqualified_id notype_qualified_id any_id
%type <ttype> complex_direct_notype_declarator functional_cast
-%type <ttype> named_parm complex_parmlist typed_declspecs1 parms_comma
+%type <ttype> complex_parmlist parms_comma
+%type <ttype> namespace_qualifier namespace_using_decl
+
+%type <ftype> type_id new_type_id typed_typespecs typespec typed_declspecs
+%type <ftype> typed_declspecs1 type_specifier_seq nonempty_cv_qualifiers
+%type <ftype> structsp typespecqual_reserved parm named_parm full_parm
/* C++ extensions */
-%token <ttype> TYPENAME_ELLIPSIS PTYPENAME
+%token <ttype> PTYPENAME
%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
-%token <ttype> PRE_PARSED_CLASS_DECL
-%type <ttype> fn.def1 /* Not really! */
-%type <ttype> fn.def2 return_id
+%token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
+%type <ttype> component_constructor_declarator
+%type <ttype> fn.def2 return_id fn.defpen constructor_declarator
%type <itype> ctor_initializer_opt
%type <ttype> named_class_head named_class_head_sans_basetype
%type <ttype> named_complex_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_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> operator_name
%type <ttype> object aggr
-%type <itype> new delete
+%type <itype> new delete .begin_new_placement
/* %type <ttype> primary_no_id */
%type <ttype> nonmomentary_expr maybe_parmlist
-%type <itype> initdcl0 notype_initdcl0 member_init_list
+%type <itype> initdcl0 notype_initdcl0 member_init_list initdcl0_innards
%type <ttype> template_header template_parm_list template_parm
-%type <ttype> template_type_parm
-%type <ttype> template_type template_arg_list template_arg
-%type <ttype> template_instantiation template_type_name tmpl.2
-%type <ttype> template_instantiate_once template_instantiate_some
-%type <itype> fn_tmpl_end
-/* %type <itype> try_for_typename */
+%type <ttype> template_type_parm template_template_parm
+%type <code> template_close_bracket
+%type <ttype> template_type template_arg_list template_arg_list_opt
+%type <ttype> template_arg
%type <ttype> condition xcond paren_cond_or_null
%type <ttype> type_name nested_name_specifier nested_type ptr_to_mem
-%type <ttype> qualified_type_name complete_type_name notype_identifier
+%type <ttype> complete_type_name notype_identifier nonnested_type
%type <ttype> complex_type_name nested_name_specifier_1
-%type <itype> nomods_initdecls nomods_initdcl0
-%type <ttype> new_initializer new_placement specialization type_specifier_seq
-%type <ttype> using_decl .poplevel
-
-/* in order to recognize aggr tags as defining and thus shadowing. */
+%type <ttype> new_initializer new_placement
+%type <ttype> using_decl
+%type <ttype> typename_sub typename_sub0 typename_sub1 typename_sub2
+%type <ttype> explicit_template_type
+/* in order to recognize aggr tags as defining and thus shadowing. */
%token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
-%type <ttype> named_class_head_sans_basetype_defn
+%type <ttype> named_class_head_sans_basetype_defn
%type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
+%type <ttype> self_template_type
+
%token NSNAME
%type <ttype> NSNAME
/* Used in lex.c for parsing pragmas. */
%token END_OF_LINE
-/* lex.c and pt.c depends on this being the last token. Define
+/* lex.c and pt.c depend on this being the last token. Define
any new tokens before this one! */
%token END_OF_SAVED_INPUT
%{
/* List of types and structure classes of the current declaration. */
static tree current_declspecs;
+
/* 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. */
@@ -291,28 +296,51 @@ static tree current_aggr;
/* Tell yyparse how to print a token's value, if yydebug is set. */
#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
-extern void yyprint ();
+extern void yyprint PROTO((FILE *, int, YYSTYPE));
extern tree combine_strings PROTO((tree));
+
+static int
+parse_decl(declarator, specs_attrs, attributes, initialized, decl)
+ tree declarator;
+ tree specs_attrs;
+ tree attributes;
+ int initialized;
+ tree* decl;
+{
+ int sm;
+
+ split_specs_attrs (specs_attrs, &current_declspecs, &prefix_attributes);
+ if (current_declspecs
+ && TREE_CODE (current_declspecs) != TREE_LIST)
+ current_declspecs = get_decl_list (current_declspecs);
+ if (have_extern_spec && !used_extern_spec)
+ {
+ current_declspecs = decl_tree_cons (NULL_TREE,
+ get_identifier ("extern"),
+ current_declspecs);
+ used_extern_spec = 1;
+ }
+ sm = suspend_momentary ();
+ *decl = start_decl (declarator, current_declspecs, initialized,
+ attributes, prefix_attributes);
+ return sm;
+}
%}
%%
-program: /* empty */
+program:
+ /* empty */
| extdefs
- {
- /* In case there were missing closebraces,
- get us back to the global binding level. */
- while (! global_bindings_p ())
- poplevel (0, 0, 0);
- finish_file ();
- }
+ { finish_translation_unit (); }
;
/* the reason for the strange actions in this rule
is so that notype_initdecls when reached via datadef
- can find a valid list of type and sc specs in $0. */
+ can find a valid list of type and sc specs in $0. */
extdefs:
- { $<ttype>$ = NULL_TREE; } lang_extdef
+ { $<ttype>$ = NULL_TREE; }
+ lang_extdef
{ $<ttype>$ = NULL_TREE; }
| extdefs lang_extdef
{ $<ttype>$ = NULL_TREE; }
@@ -332,32 +360,36 @@ extdefs_opt:
{ have_extern_spec = 0; }
;
+extension:
+ EXTENSION
+ { $<itype>$ = pedantic;
+ pedantic = 0; }
+ ;
+
asm_keyword:
ASM_KEYWORD
- | GCC_ASM_KEYWORD
;
lang_extdef:
- { if (pending_lang_change) do_pending_lang_change(); }
+ { if (pending_lang_change) do_pending_lang_change(); }
extdef
- { if (! toplevel_bindings_p () && ! pseudo_global_level_p())
- pop_everything (); }
+ { if (! toplevel_bindings_p () && ! pseudo_global_level_p())
+ pop_everything (); }
;
extdef:
- fndef
+ fndef eat_saved_input
{ if (pending_inlines) do_pending_inlines (); }
| datadef
{ if (pending_inlines) do_pending_inlines (); }
| template_def
{ if (pending_inlines) do_pending_inlines (); }
- | overloaddef
| asm_keyword '(' string ')' ';'
{ if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
assemble_asm ($3); }
| extern_lang_string '{' extdefs_opt '}'
{ pop_lang_context (); }
- | extern_lang_string .hush_warning fndef .warning_ok
+ | extern_lang_string .hush_warning fndef .warning_ok eat_saved_input
{ if (pending_inlines) do_pending_inlines ();
pop_lang_context (); }
| extern_lang_string .hush_warning datadef .warning_ok
@@ -371,12 +403,24 @@ extdef:
{ push_namespace (NULL_TREE); }
extdefs_opt '}'
{ pop_namespace (); }
- | NAMESPACE identifier '=' any_id ';'
- { do_namespace_alias ($2, $4); }
+ | namespace_alias
| using_decl ';'
{ do_toplevel_using_decl ($1); }
- | USING NAMESPACE any_id ';'
- { do_using_directive ($3); }
+ | using_directive
+ | extension extdef
+ { pedantic = $<itype>1; }
+ ;
+
+namespace_alias:
+ NAMESPACE identifier '='
+ { begin_only_namespace_names (); }
+ any_id ';'
+ {
+ end_only_namespace_names ();
+ if (lastiddecl)
+ $5 = lastiddecl;
+ do_namespace_alias ($2, $5);
+ }
;
using_decl:
@@ -388,6 +432,45 @@ using_decl:
{ $$ = $3; }
;
+namespace_using_decl:
+ USING namespace_qualifier identifier
+ { $$ = build_parse_node (SCOPE_REF, $2, $3); }
+ | USING global_scope identifier
+ { $$ = build_parse_node (SCOPE_REF, global_namespace, $3); }
+ | USING global_scope namespace_qualifier identifier
+ { $$ = build_parse_node (SCOPE_REF, $3, $4); }
+ ;
+
+using_directive:
+ USING NAMESPACE
+ { begin_only_namespace_names (); }
+ any_id ';'
+ {
+ end_only_namespace_names ();
+ /* If no declaration was found, the using-directive is
+ invalid. Since that was not reported, we need the
+ identifier for the error message. */
+ if (TREE_CODE ($4) == IDENTIFIER_NODE && lastiddecl)
+ $4 = lastiddecl;
+ do_using_directive ($4);
+ }
+ ;
+
+namespace_qualifier:
+ NSNAME SCOPE
+ {
+ if (TREE_CODE ($$) == IDENTIFIER_NODE)
+ $$ = lastiddecl;
+ got_scope = $$;
+ }
+ | namespace_qualifier NSNAME SCOPE
+ {
+ $$ = $2;
+ if (TREE_CODE ($$) == IDENTIFIER_NODE)
+ $$ = lastiddecl;
+ got_scope = $$;
+ }
+
any_id:
unqualified_id
| qualified_id
@@ -411,6 +494,9 @@ template_header:
{ begin_template_parm_list (); }
template_parm_list '>'
{ $$ = end_template_parm_list ($4); }
+ | TEMPLATE '<' '>'
+ { begin_specialization();
+ $$ = NULL_TREE; }
;
template_parm_list:
@@ -420,22 +506,22 @@ template_parm_list:
{ $$ = process_template_parm ($1, $3); }
;
+maybe_identifier:
+ identifier
+ { $$ = $1; }
+ | /* empty */
+ { $$ = NULL_TREE; }
+
template_type_parm:
- aggr
- {
- $$ = build_tree_list ($1, NULL_TREE);
- ttpa:
- if (TREE_PURPOSE ($$) == signature_type_node)
- sorry ("signature as template type parameter");
- else if (TREE_PURPOSE ($$) != class_type_node)
- pedwarn ("template type parameters must use the keyword `class'");
- }
- | 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); }
+ aggr maybe_identifier
+ { $$ = finish_template_type_parm ($1, $2); }
+ | TYPENAME_KEYWORD maybe_identifier
+ { $$ = finish_template_type_parm (class_type_node, $2); }
+ ;
+
+template_template_parm:
+ template_header aggr maybe_identifier
+ { $$ = finish_template_template_parm ($2, $3); }
;
template_parm:
@@ -447,169 +533,65 @@ template_parm:
their match before considering them nameless parameter
declarations. */
template_type_parm
- { $$ = build_tree_list (NULL_TREE, $$); }
- | template_type_parm '=' typespec
- { $$ = build_tree_list ($3, $$); }
- | full_parm
- ;
-
-overloaddef:
- OVERLOAD ov_identifiers ';'
- { warning ("use of `overload' is an anachronism"); }
- ;
-
-ov_identifiers: IDENTIFIER
- { declare_overloaded ($1); }
- | ov_identifiers ',' IDENTIFIER
- { declare_overloaded ($3); }
- ;
-
-template_def:
- /* Class template declarations go here; they aren't normal class
- declarations, because we can't process the bodies yet. */
- template_header named_class_head_sans_basetype '{'
- { yychar = '{'; goto template1; }
- ';'
- | template_header named_class_head_sans_basetype_defn '{'
- { yychar = '{'; goto template1; }
- ';'
- | template_header named_class_head_sans_basetype ':'
- { yychar = ':'; goto template1; }
- ';'
- | template_header named_class_head_sans_basetype_defn ':'
- {
- yychar = ':';
- template1:
- if (current_aggr == signature_type_node)
- sorry ("template type defining a signature");
- /* Maybe pedantic warning for union?
- How about an enum? :-) */
- end_template_decl ($1, $2, current_aggr, 1);
- reinit_parse_for_template (yychar, $1, $2);
- yychar = YYEMPTY;
- }
- ';'
- | template_header named_class_head_sans_basetype ';'
- {
- end_template_decl ($1, $2, current_aggr, 0);
- /* declare $2 as template name with $1 parm list */
- }
- | template_header named_class_head_sans_basetype_defn ';'
- {
- end_template_decl ($1, $2, current_aggr, 0);
- /* declare $2 as template name with $1 parm list */
- }
- | template_header /* notype_initdcl0 ';' */
- notype_declarator exception_specification_opt maybeasm maybe_attribute
- fn_tmpl_end
+ { $$ = build_tree_list (NULL_TREE, $1); }
+ | template_type_parm '=' type_id
+ { $$ = build_tree_list (groktypename ($3.t), $1); }
+ | parm
+ { $$ = build_tree_list (NULL_TREE, $1.t); }
+ | parm '=' expr_no_commas %prec ARITHCOMPARE
+ { $$ = build_tree_list ($3, $1.t); }
+ | template_template_parm
+ { $$ = build_tree_list (NULL_TREE, $1); }
+ | template_template_parm '=' template_arg
{
- tree d;
- int momentary;
- int def = ($6 != ';');
- momentary = suspend_momentary ();
- d = start_decl ($<ttype>2, /*current_declspecs*/NULL_TREE, 0,
- $3);
- cplus_decl_attributes (d, $5, /*prefix_attributes*/NULL_TREE);
- cp_finish_decl (d, NULL_TREE, $4, 0, 0);
- end_template_decl ($1, d, 0, def);
- if (def)
- reinit_parse_for_template ((int) $6, $1, d);
- resume_momentary (momentary);
- }
- | template_header typed_declspecs /*initdcl0*/
- declarator exception_specification_opt maybeasm maybe_attribute
- fn_tmpl_end
- {
- tree d, specs, attrs;
- int momentary;
- int def = ($7 != ';');
- split_specs_attrs ($2, &specs, &attrs);
- momentary = suspend_momentary ();
- d = start_decl ($<ttype>3, specs, 0, $<ttype>4);
- cplus_decl_attributes (d, $6, attrs);
- cp_finish_decl (d, NULL_TREE, $5, 0, 0);
- end_template_decl ($1, d, 0, def);
- if (def)
+ if (TREE_CODE ($3) != TEMPLATE_DECL
+ && TREE_CODE ($3) != TEMPLATE_TEMPLATE_PARM
+ && TREE_CODE ($3) != TYPE_DECL)
{
- reinit_parse_for_template ((int) $7, $1, d);
- yychar = YYEMPTY;
+ error ("invalid default template argument");
+ $3 = error_mark_node;
}
- note_list_got_semicolon ($<ttype>2);
- resume_momentary (momentary);
- }
- | template_header declmods notype_declarator fn_tmpl_end
- {
- tree d, specs, attrs;
- int def = ($4 != ';');
- split_specs_attrs ($2, &specs, &attrs);
- d = start_decl ($<ttype>3, specs, 0, NULL_TREE);
- cplus_decl_attributes (d, NULL_TREE, attrs);
- cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
- end_template_decl ($1, d, 0, def);
- if (def)
- reinit_parse_for_template ((int) $4, $1, d);
+ $$ = build_tree_list ($3, $1);
}
- /* Try to recover from syntax errors in templates. */
- | template_header error '}' { end_template_decl ($1, 0, 0, 0); }
- | template_header error ';' { end_template_decl ($1, 0, 0, 0); }
;
-fn_tmpl_end: '{' { $$ = '{'; }
- | ':' { $$ = ':'; }
- | ';' { $$ = ';'; }
- | '=' { $$ = '='; }
- | RETURN { $$ = RETURN; }
+template_def:
+ template_header
+ extdef
+ {
+ if ($1)
+ end_template_decl ();
+ else
+ end_specialization ();
+ }
+ | template_header
+ error %prec EMPTY
+ {
+ if ($1)
+ end_template_decl ();
+ else
+ end_specialization ();
+ }
;
datadef:
nomods_initdecls ';'
- {}
| declmods notype_initdecls ';'
{}
- /* Normal case to make fast: "const i;". */
- | declmods notype_declarator ';'
- { 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 ';'
{
- note_list_got_semicolon ($<ttype>$);
- }
- /* Normal case: make this fast. */
- | typed_declspecs declarator ';'
- { 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>$);
+ note_list_got_semicolon ($1.t);
}
| declmods ';'
- { pedwarn ("empty declaration"); }
+ { pedwarn ("empty declaration"); }
| explicit_instantiation ';'
| typed_declspecs ';'
- {
- tree t, attrs;
- split_specs_attrs ($1, &t, &attrs);
- shadow_tag (t);
- if (TREE_CODE (t) == TREE_LIST
- && TREE_PURPOSE (t) == NULL_TREE)
- {
- t = TREE_VALUE (t);
- if (IS_AGGR_TYPE (t)
- && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (t)))
- {
- if (CLASSTYPE_USE_TEMPLATE (t) == 0)
- SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
- else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
- error ("override declaration for already-expanded template");
- }
- }
- note_list_got_semicolon ($<ttype>$);
- }
+ {
+ tree t, attrs;
+ split_specs_attrs ($1.t, &t, &attrs);
+ shadow_tag (t);
+ note_list_got_semicolon ($1.t);
+ }
| error ';'
| error '}'
| ';'
@@ -635,79 +617,108 @@ eat_saved_input:
fndef:
fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
- {
- finish_function (lineno, (int)$3, 0);
- if ($<ttype>$) process_next_inline ($<ttype>$);
- }
+ { finish_function (lineno, (int)$3, 0); }
| fn.def1 maybe_return_init function_try_block
- {
- if ($<ttype>$) process_next_inline ($<ttype>$);
+ { }
+ | fn.def1 maybe_return_init error
+ { }
+ ;
+
+constructor_declarator:
+ nested_name_specifier SELFNAME '('
+ { $$ = begin_constructor_declarator ($1, $2); }
+ parmlist ')' cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($<ttype>4, $5, $7, $8); }
+ | nested_name_specifier SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt
+ { $$ = begin_constructor_declarator ($1, $2);
+ $$ = make_call_declarator ($$, empty_parms (), $4, $5);
+ }
+ | global_scope nested_name_specifier SELFNAME '('
+ { $$ = begin_constructor_declarator ($2, $3); }
+ parmlist ')' cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($<ttype>5, $6, $8, $9); }
+ | global_scope nested_name_specifier SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt
+ { $$ = begin_constructor_declarator ($2, $3);
+ $$ = make_call_declarator ($$, empty_parms (), $5, $6);
+ }
+ | nested_name_specifier self_template_type '('
+ { $$ = begin_constructor_declarator ($1, $2); }
+ parmlist ')' cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($<ttype>4, $5, $7, $8); }
+ | nested_name_specifier self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt
+ { $$ = begin_constructor_declarator ($1, $2);
+ $$ = make_call_declarator ($$, empty_parms (), $4, $5);
+ }
+ | global_scope nested_name_specifier self_template_type '('
+ { $$ = begin_constructor_declarator ($2, $3); }
+ parmlist ')' cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($<ttype>5, $6, $8, $9); }
+ | global_scope nested_name_specifier self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt
+ { $$ = begin_constructor_declarator ($2, $3);
+ $$ = make_call_declarator ($$, empty_parms (), $5, $6);
}
- eat_saved_input
- | typed_declspecs declarator error
- {}
- | declmods notype_declarator error
- {}
- | notype_declarator error
- {}
;
fn.def1:
- typed_declspecs declarator exception_specification_opt
- { 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
- { 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, NULL_TREE, 0))
- YYERROR1;
- reinit_parse_for_function ();
- $$ = NULL_TREE; }
- | PRE_PARSED_FUNCTION_DECL
- { start_function (NULL_TREE, TREE_VALUE ($$),
- NULL_TREE, NULL_TREE, 1);
- reinit_parse_for_function (); }
+ typed_declspecs declarator
+ { if (!begin_function_definition ($1.t, $2))
+ YYERROR1; }
+ | declmods notype_declarator
+ { if (!begin_function_definition ($1, $2))
+ YYERROR1; }
+ | notype_declarator
+ { if (!begin_function_definition (NULL_TREE, $1))
+ YYERROR1; }
+ | declmods constructor_declarator
+ { if (!begin_function_definition ($1, $2))
+ YYERROR1; }
+ | constructor_declarator
+ { if (!begin_function_definition (NULL_TREE, $1))
+ YYERROR1; }
+ ;
+
+component_constructor_declarator:
+ SELFNAME '(' parmlist ')' cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($1, $3, $5, $6); }
+ | SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($1, empty_parms (), $3, $4); }
+ | self_template_type '(' parmlist ')' cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($1, $3, $5, $6); }
+ | self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($1, empty_parms (), $3, $4); }
;
/* more C++ complexity. See component_decl for a comment on the
reduce/reduce conflict introduced by these rules. */
fn.def2:
- typed_declspecs '(' parmlist ')' type_quals exception_specification_opt
+ declmods component_constructor_declarator
{ tree specs = strip_attrs ($1);
- $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), $3, $5);
- $$ = start_method (TREE_CHAIN (specs), $$, $6);
+ $$ = start_method (specs, $2);
rest_of_mdef:
if (! $$)
YYERROR1;
if (yychar == YYEMPTY)
yychar = YYLEX;
reinit_parse_for_method (yychar, $$); }
- | typed_declspecs LEFT_RIGHT type_quals exception_specification_opt
- { tree specs = strip_attrs ($1);
- $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
- empty_parms (), $3);
- $$ = start_method (TREE_CHAIN (specs), $$, $4);
- goto rest_of_mdef;
- }
- | typed_declspecs declarator exception_specification_opt
+ | component_constructor_declarator
+ { $$ = start_method (NULL_TREE, $1); goto rest_of_mdef; }
+ | typed_declspecs declarator
+ { tree specs = strip_attrs ($1.t);
+ $$ = start_method (specs, $2); goto rest_of_mdef; }
+ | declmods notype_declarator
{ tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2, $3); goto rest_of_mdef; }
- | declmods notype_declarator exception_specification_opt
+ $$ = start_method (specs, $2); goto rest_of_mdef; }
+ | notype_declarator
+ { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
+ | declmods constructor_declarator
{ 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; }
+ $$ = start_method (specs, $2); goto rest_of_mdef; }
+ | constructor_declarator
+ { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
;
-return_id: RETURN IDENTIFIER
+return_id:
+ RETURN IDENTIFIER
{
if (! current_function_parms_stored)
store_parm_decls ();
@@ -715,7 +726,8 @@ return_id: RETURN IDENTIFIER
}
;
-return_init: return_id maybe_init
+return_init:
+ return_id maybe_init
{ store_return_init ($<ttype>$, $2); }
| return_id '(' nonnull_exprlist ')'
{ store_return_init ($<ttype>$, $3); }
@@ -737,7 +749,7 @@ base_init:
;
.set_base_init:
- /* empty */
+ /* empty */
{
if (! current_function_parms_stored)
store_parm_decls ();
@@ -765,40 +777,39 @@ member_init_list:
| member_init_list error
;
-member_init: '(' nonnull_exprlist ')'
+member_init:
+ '(' nonnull_exprlist ')'
{
- if (current_class_name && !flag_traditional)
+ if (current_class_name)
pedwarn ("anachronistic old style base class initializer");
- expand_member_init (C_C_D, NULL_TREE, $2);
+ expand_member_init (current_class_ref, NULL_TREE, $2);
}
| LEFT_RIGHT
{
- if (current_class_name && !flag_traditional)
+ if (current_class_name)
pedwarn ("anachronistic old style base class initializer");
- expand_member_init (C_C_D, NULL_TREE, void_type_node);
+ expand_member_init (current_class_ref, NULL_TREE, void_type_node);
}
| notype_identifier '(' nonnull_exprlist ')'
- { expand_member_init (C_C_D, $<ttype>$, $3); }
+ { expand_member_init (current_class_ref, $1, $3); }
| notype_identifier LEFT_RIGHT
- { expand_member_init (C_C_D, $<ttype>$, void_type_node); }
- | complete_type_name '(' nonnull_exprlist ')'
- { expand_member_init (C_C_D, $<ttype>$, $3); }
- | complete_type_name LEFT_RIGHT
- { expand_member_init (C_C_D, $<ttype>$, void_type_node); }
- /* GNU extension */
- | notype_qualified_id '(' nonnull_exprlist ')'
- {
- do_member_init (OP0 ($1), OP1 ($1), $3);
- }
- | notype_qualified_id LEFT_RIGHT
- {
- do_member_init (OP0 ($1), OP1 ($1), void_type_node);
- }
+ { expand_member_init (current_class_ref, $1, void_type_node); }
+ | nonnested_type '(' nonnull_exprlist ')'
+ { expand_member_init (current_class_ref, $1, $3); }
+ | nonnested_type LEFT_RIGHT
+ { expand_member_init (current_class_ref, $1, void_type_node); }
+ | typename_sub '(' nonnull_exprlist ')'
+ { expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1),
+ $3); }
+ | typename_sub LEFT_RIGHT
+ { expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1),
+ void_type_node); }
;
identifier:
IDENTIFIER
| TYPENAME
+ | SELFNAME
| PTYPENAME
| NSNAME
;
@@ -806,7 +817,7 @@ identifier:
notype_identifier:
IDENTIFIER
| PTYPENAME
- | NSNAME %prec EMPTY
+ | NSNAME %prec EMPTY
;
identifier_defn:
@@ -816,43 +827,90 @@ identifier_defn:
;
explicit_instantiation:
- TEMPLATE specialization template_instantiation
- { do_type_instantiation ($3 ? $3 : $2, NULL_TREE); }
- | TEMPLATE typed_declspecs declarator
- { tree specs = strip_attrs ($2);
- do_function_instantiation (specs, $3, NULL_TREE); }
- | TEMPLATE notype_declarator
- { do_function_instantiation (NULL_TREE, $2, NULL_TREE); }
- | SCSPEC TEMPLATE specialization template_instantiation
- { do_type_instantiation ($4 ? $4 : $3, $1); }
- | SCSPEC TEMPLATE typed_declspecs declarator
- { tree specs = strip_attrs ($3);
- do_function_instantiation (specs, $4, $1); }
- | SCSPEC TEMPLATE notype_declarator
- { do_function_instantiation (NULL_TREE, $3, $1); }
- ;
+ TEMPLATE begin_explicit_instantiation typespec ';'
+ { do_type_instantiation ($3.t, NULL_TREE);
+ yyungetc (';', 1); }
+ end_explicit_instantiation
+ | TEMPLATE begin_explicit_instantiation typed_declspecs declarator
+ { tree specs = strip_attrs ($3.t);
+ do_decl_instantiation (specs, $4, NULL_TREE); }
+ end_explicit_instantiation
+ | TEMPLATE begin_explicit_instantiation notype_declarator
+ { do_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
+ end_explicit_instantiation
+ | TEMPLATE begin_explicit_instantiation constructor_declarator
+ { do_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
+ end_explicit_instantiation
+ | SCSPEC TEMPLATE begin_explicit_instantiation typespec ';'
+ { do_type_instantiation ($4.t, $1);
+ yyungetc (';', 1); }
+ end_explicit_instantiation
+ | SCSPEC TEMPLATE begin_explicit_instantiation typed_declspecs
+ declarator
+ { tree specs = strip_attrs ($4.t);
+ do_decl_instantiation (specs, $5, $1); }
+ end_explicit_instantiation
+ | SCSPEC TEMPLATE begin_explicit_instantiation notype_declarator
+ { do_decl_instantiation (NULL_TREE, $4, $1); }
+ end_explicit_instantiation
+ | SCSPEC TEMPLATE begin_explicit_instantiation constructor_declarator
+ { do_decl_instantiation (NULL_TREE, $4, $1); }
+ end_explicit_instantiation
+ ;
+
+begin_explicit_instantiation:
+ { begin_explicit_instantiation(); }
+
+end_explicit_instantiation:
+ { end_explicit_instantiation(); }
+
+/* The TYPENAME expansions are to deal with use of a template class name as
+ a template within the class itself, where the template decl is hidden by
+ a type decl. Got all that? */
template_type:
- template_type_name tmpl.2 template_instantiation
- { if ($3) $$ = $3; }
+ PTYPENAME '<' template_arg_list_opt template_close_bracket
+ {
+ $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
+ if ($$ != error_mark_node)
+ $$ = TYPE_STUB_DECL ($$);
+ }
+ | TYPENAME '<' template_arg_list_opt template_close_bracket
+ {
+ $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
+ if ($$ != error_mark_node)
+ $$ = TYPE_STUB_DECL ($$);
+ }
+ | self_template_type
;
-template_type_name:
- PTYPENAME '<' template_arg_list '>'
- { $$ = lookup_template_class ($$, $3, NULL_TREE); }
- | PTYPENAME '<' '>'
- { $$ = lookup_template_class ($$, NULL_TREE, NULL_TREE); }
- | TYPENAME '<' template_arg_list '>'
- { $$ = lookup_template_class ($$, $3, NULL_TREE); }
+self_template_type:
+ SELFNAME '<' template_arg_list_opt template_close_bracket
+ {
+ $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
+ if ($$ != error_mark_node)
+ $$ = TYPE_STUB_DECL ($$);
+ }
;
-tmpl.2:
- /* empty */ %prec EMPTY
- { $$ = instantiate_class_template ($<ttype>0, 1); }
+template_close_bracket:
+ '>'
+ | RSHIFT
+ {
+ /* Handle `Class<Class<Type>>' without space in the `>>' */
+ pedwarn ("`>>' should be `> >' in template class name");
+ yyungetc ('>', 1);
+ }
;
+template_arg_list_opt:
+ /* empty */
+ { $$ = NULL_TREE; }
+ | template_arg_list
+ ;
+
template_arg_list:
- template_arg
+ template_arg
{ $$ = build_tree_list (NULL_TREE, $$); }
| template_arg_list ',' template_arg
{ $$ = chainon ($$, build_tree_list (NULL_TREE, $3)); }
@@ -860,77 +918,14 @@ template_arg_list:
template_arg:
type_id
- { $$ = groktypename ($$); }
- | expr_no_commas %prec UNARY
- ;
-
-template_instantiate_once:
- PRE_PARSED_CLASS_DECL maybe_base_class_list
- {
- tree t, decl, tmpl;
-
- tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE ($1));
- t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, $1, $2, 0);
- set_current_level_tags_transparency (1);
- my_friendly_assert (TREE_CODE (t) == RECORD_TYPE
- || TREE_CODE (t) == UNION_TYPE, 257);
- $<ttype>$ = t;
-
- /* Now, put a copy of the decl in global scope, to avoid
- recursive expansion. */
- decl = IDENTIFIER_LOCAL_VALUE ($1);
- if (!decl)
- decl = IDENTIFIER_CLASS_VALUE ($1);
- /* Now, put a copy of the decl in global scope, to avoid
- recursive expansion. */
- if (decl)
- {
- /* Need to copy it to clear the chain pointer,
- and need to get it into permanent storage. */
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 258);
- push_obstacks (&permanent_obstack, &permanent_obstack);
- decl = copy_node (decl);
- if (DECL_LANG_SPECIFIC (decl))
- copy_lang_decl (decl);
- pop_obstacks ();
- pushdecl_top_level (decl);
- }
- /* Kludge; see instantiate_class_template. */
- TYPE_BEING_DEFINED (t) = 0;
- }
- left_curly opt.component_decl_list '}'
- {
- tree t = finish_struct ($<ttype>3, $5, 0);
-
- pop_obstacks ();
- end_template_instantiation ($1);
-
- repo_template_used (t);
-
- /* Now go after the methods & class data. */
- instantiate_member_templates ($1);
-
- pop_tinst_level();
-
- CLASSTYPE_GOT_SEMICOLON (t) = 1;
- }
+ { $$ = groktypename ($1.t); }
+ | PTYPENAME
+ { $$ = lastiddecl; }
+ | expr_no_commas %prec ARITHCOMPARE
;
-template_instantiation:
- /* empty */
- { $$ = NULL_TREE; }
- | template_instantiate_once
- { $$ = $1; }
- ;
-
-template_instantiate_some:
- /* empty */
- { $$ = NULL_TREE; /* never used from here... */}
- | template_instantiate_once template_instantiate_some
- { $$ = $1; /*???*/ }
- ;
-
-unop: '-'
+unop:
+ '-'
{ $$ = NEGATE_EXPR; }
| '+'
{ $$ = CONVERT_EXPR; }
@@ -942,7 +937,8 @@ unop: '-'
{ $$ = TRUTH_NOT_EXPR; }
;
-expr: nontrivial_exprlist
+expr:
+ nontrivial_exprlist
{ $$ = build_x_compound_expr ($$); }
| expr_no_commas
;
@@ -953,7 +949,7 @@ paren_expr_or_null:
cond_stmt_keyword);
$$ = integer_zero_node; }
| '(' expr ')'
- { $$ = condition_conversion ($2); }
+ { $$ = $2; }
;
paren_cond_or_null:
@@ -962,20 +958,19 @@ paren_cond_or_null:
cond_stmt_keyword);
$$ = integer_zero_node; }
| '(' condition ')'
- { $$ = condition_conversion ($2); }
+ { $$ = $2; }
;
xcond:
- /* empty */
+ /* empty */
{ $$ = NULL_TREE; }
| condition
- { $$ = condition_conversion ($$); }
| error
{ $$ = NULL_TREE; }
;
condition:
- type_specifier_seq declarator exception_specification_opt maybeasm maybe_attribute '='
+ type_specifier_seq declarator maybeasm maybe_attribute '='
{ {
tree d;
for (d = getdecls (); d; d = TREE_CHAIN (d))
@@ -987,17 +982,16 @@ condition:
cp_error ("definition of enum `%T' in condition", s);
}
}
- current_declspecs = $1;
- $<itype>6 = suspend_momentary ();
- $<ttype>$ = start_decl ($<ttype>2, current_declspecs, 1, $3);
- cplus_decl_attributes ($<ttype>$, $5,
- /*prefix_attributes*/ NULL_TREE);
+ current_declspecs = $1.t;
+ $<itype>5 = suspend_momentary ();
+ $<ttype>$ = start_decl ($<ttype>2, current_declspecs, 1,
+ $4, /*prefix_attributes*/ NULL_TREE);
}
- init
+ init
{
- cp_finish_decl ($<ttype>7, $8, $5, 0, LOOKUP_ONLYCONVERTING);
- resume_momentary ($<itype>6);
- $$ = $<ttype>7;
+ cp_finish_decl ($<ttype>6, $7, $4, 1, LOOKUP_ONLYCONVERTING);
+ resume_momentary ($<itype>5);
+ $$ = convert_from_reference ($<ttype>6);
if (TREE_CODE (TREE_TYPE ($$)) == ARRAY_TYPE)
cp_error ("definition of array `%#D' in condition", $$);
}
@@ -1012,45 +1006,39 @@ compstmtend:
;
already_scoped_stmt:
- '{' compstmtend
- { finish_stmt (); }
+ '{'
+ { $<ttype>$ = begin_compound_stmt (1); }
+ compstmtend
+ { finish_compound_stmt (1, $<ttype>2); }
| simple_stmt
;
nontrivial_exprlist:
expr_no_commas ',' expr_no_commas
- { $$ = tree_cons (NULL_TREE, $$,
- build_tree_list (NULL_TREE, $3)); }
+ { $$ = expr_tree_cons (NULL_TREE, $$,
+ build_expr_list (NULL_TREE, $3)); }
| expr_no_commas ',' error
- { $$ = tree_cons (NULL_TREE, $$,
- build_tree_list (NULL_TREE, error_mark_node)); }
+ { $$ = expr_tree_cons (NULL_TREE, $$,
+ build_expr_list (NULL_TREE, error_mark_node)); }
| nontrivial_exprlist ',' expr_no_commas
- { chainon ($$, build_tree_list (NULL_TREE, $3)); }
+ { chainon ($$, build_expr_list (NULL_TREE, $3)); }
| nontrivial_exprlist ',' error
- { chainon ($$, build_tree_list (NULL_TREE, error_mark_node)); }
+ { chainon ($$, build_expr_list (NULL_TREE, error_mark_node)); }
;
nonnull_exprlist:
expr_no_commas
- { $$ = build_tree_list (NULL_TREE, $$); }
+ { $$ = build_expr_list (NULL_TREE, $$); }
| nontrivial_exprlist
;
unary_expr:
- primary %prec UNARY
- {
-#if 0
- if (TREE_CODE ($$) == TYPE_EXPR)
- $$ = build_component_type_expr (C_C_D, $$, NULL_TREE, 1);
-#endif
- }
+ primary %prec UNARY
+ { $$ = $1; }
/* __extension__ turns off -pedantic for following primary. */
- | EXTENSION
- { $<itype>1 = pedantic;
- pedantic = 0; }
- cast_expr %prec UNARY
- { $$ = $3;
+ | extension cast_expr %prec UNARY
+ { $$ = $2;
pedantic = $<itype>1; }
| '*' cast_expr %prec UNARY
{ $$ = build_x_indirect_ref ($2, "unary *"); }
@@ -1059,71 +1047,62 @@ unary_expr:
| '~' cast_expr
{ $$ = build_x_unary_op (BIT_NOT_EXPR, $2); }
| unop cast_expr %prec UNARY
- { $$ = build_x_unary_op ($1, $2);
- if ($1 == NEGATE_EXPR && TREE_CODE ($2) == INTEGER_CST)
- TREE_NEGATED_INT ($$) = 1;
- overflow_warning ($$);
- }
+ { $$ = finish_unary_op_expr ($1, $2); }
/* Refer to the address of a label as a pointer. */
| ANDAND identifier
- { tree label = lookup_label ($2);
- if (label == NULL_TREE)
- $$ = null_pointer_node;
- else
- {
- TREE_USED (label) = 1;
- $$ = build1 (ADDR_EXPR, ptr_type_node, label);
- TREE_CONSTANT ($$) = 1;
- }
- }
+ { if (pedantic)
+ pedwarn ("ANSI C++ forbids `&&'");
+ $$ = finish_label_address_expr ($2); }
| SIZEOF unary_expr %prec UNARY
- { if (TREE_CODE ($2) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND ($2, 1)))
- error ("sizeof applied to a bit-field");
- /* ANSI says arrays and functions are converted inside comma.
- But we can't really convert them in build_compound_expr
- because that would break commas in lvalues.
- So do the conversion here if operand was a comma. */
- if (TREE_CODE ($2) == COMPOUND_EXPR
- && (TREE_CODE (TREE_TYPE ($2)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE ($2)) == FUNCTION_TYPE))
- $2 = default_conversion ($2);
- else if (TREE_CODE ($2) == TREE_LIST)
- {
- tree t = TREE_VALUE ($2);
- if (t != NULL_TREE
- && ((TREE_TYPE (t)
- && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
- || is_overloaded_fn (t)))
- pedwarn ("ANSI C++ forbids taking the sizeof a function type");
- }
- $$ = c_sizeof (TREE_TYPE ($2)); }
+ { $$ = expr_sizeof ($2); }
| SIZEOF '(' type_id ')' %prec HYPERUNARY
- { $$ = c_sizeof (groktypename ($3)); }
+ { $$ = c_sizeof (groktypename ($3.t)); }
| ALIGNOF unary_expr %prec UNARY
{ $$ = grok_alignof ($2); }
| ALIGNOF '(' type_id ')' %prec HYPERUNARY
- { $$ = c_alignof (groktypename ($3)); }
+ { $$ = c_alignof (groktypename ($3.t));
+ check_for_new_type ("alignof", $3); }
/* The %prec EMPTY's here are required by the = init initializer
syntax extension; see below. */
- | new new_type_id %prec EMPTY
- { $$ = build_new (NULL_TREE, $2, NULL_TREE, $1); }
+ | new new_type_id %prec EMPTY
+ { $$ = build_new (NULL_TREE, $2.t, NULL_TREE, $1);
+ check_for_new_type ("new", $2); }
| new new_type_id new_initializer
- { $$ = build_new (NULL_TREE, $2, $3, $1); }
- | new new_placement new_type_id %prec EMPTY
- { $$ = build_new ($2, $3, NULL_TREE, $1); }
+ { $$ = build_new (NULL_TREE, $2.t, $3, $1);
+ check_for_new_type ("new", $2); }
+ | new new_placement new_type_id %prec EMPTY
+ { $$ = build_new ($2, $3.t, NULL_TREE, $1);
+ check_for_new_type ("new", $3); }
| new new_placement new_type_id new_initializer
- { $$ = build_new ($2, $3, $4, $1); }
- | new '(' type_id ')' %prec EMPTY
- { $$ = build_new (NULL_TREE, groktypename($3),
- NULL_TREE, $1); }
- | new '(' type_id ')' new_initializer
- { $$ = build_new (NULL_TREE, groktypename($3), $5, $1); }
- | new new_placement '(' type_id ')' %prec EMPTY
- { $$ = build_new ($2, groktypename($4), NULL_TREE, $1); }
- | new new_placement '(' type_id ')' new_initializer
- { $$ = build_new ($2, groktypename($4), $6, $1); }
+ { $$ = build_new ($2, $3.t, $4, $1);
+ check_for_new_type ("new", $3); }
+ /* The .begin_new_placement in the following rules is
+ necessary to avoid shift/reduce conflicts that lead to
+ mis-parsing some expressions. Of course, these constructs
+ are not really new-placement and it is bogus to call
+ begin_new_placement. But, the parser cannot always tell at this
+ point whether the next thing is an expression or a type-id,
+ so there is nothing we can do. Fortunately,
+ begin_new_placement does nothing harmful. When we rewrite
+ the parser, this lossage should be removed, of course. */
+ | new '(' .begin_new_placement type_id .finish_new_placement
+ %prec EMPTY
+ { $$ = build_new (NULL_TREE, groktypename($4.t),
+ NULL_TREE, $1);
+ check_for_new_type ("new", $4); }
+ | new '(' .begin_new_placement type_id .finish_new_placement
+ new_initializer
+ { $$ = build_new (NULL_TREE, groktypename($4.t), $6, $1);
+ check_for_new_type ("new", $4); }
+ | new new_placement '(' .begin_new_placement type_id
+ .finish_new_placement %prec EMPTY
+ { $$ = build_new ($2, groktypename($5.t), NULL_TREE, $1);
+ check_for_new_type ("new", $5); }
+ | new new_placement '(' .begin_new_placement type_id
+ .finish_new_placement new_initializer
+ { $$ = build_new ($2, groktypename($5.t), $7, $1);
+ check_for_new_type ("new", $5); }
| delete cast_expr %prec UNARY
{ $$ = delete_sanity ($2, NULL_TREE, 0, $1); }
@@ -1131,20 +1110,34 @@ unary_expr:
{ $$ = delete_sanity ($4, NULL_TREE, 1, $1);
if (yychar == YYEMPTY)
yychar = YYLEX; }
- | delete '[' expr ']' cast_expr %prec UNARY
+ | delete '[' expr ']' cast_expr %prec UNARY
{ $$ = delete_sanity ($5, $3, 2, $1);
if (yychar == YYEMPTY)
yychar = YYLEX; }
+ | REALPART cast_expr %prec UNARY
+ { $$ = build_x_unary_op (REALPART_EXPR, $2); }
+ | IMAGPART cast_expr %prec UNARY
+ { $$ = build_x_unary_op (IMAGPART_EXPR, $2); }
;
+ /* Note this rule is not suitable for use in new_placement
+ since it uses NULL_TREE as the argument to
+ finish_new_placement. This rule serves only to avoid
+ reduce/reduce conflicts in unary_expr. See the comments
+ there on the use of begin/finish_new_placement. */
+.finish_new_placement:
+ ')'
+ { finish_new_placement (NULL_TREE, $<itype>-1); }
+
+.begin_new_placement:
+ { $$ = begin_new_placement (); }
+
new_placement:
- '(' nonnull_exprlist ')'
- { $$ = $2; }
- | '{' nonnull_exprlist '}'
- {
- $$ = $2;
- pedwarn ("old style placement syntax, use () instead");
- }
+ '(' .begin_new_placement nonnull_exprlist ')'
+ { $$ = finish_new_placement ($3, $2); }
+ | '{' .begin_new_placement nonnull_exprlist '}'
+ { cp_pedwarn ("old style placement syntax, use () instead");
+ $$ = finish_new_placement ($3, $2); }
;
new_initializer:
@@ -1154,7 +1147,7 @@ new_initializer:
{ $$ = NULL_TREE; }
| '(' typespec ')'
{
- cp_error ("`%T' is not a valid expression", $2);
+ cp_error ("`%T' is not a valid expression", $2.t);
$$ = error_mark_node;
}
/* GNU extension so people can use initializer lists. Note that
@@ -1164,21 +1157,24 @@ new_initializer:
{
if (pedantic)
pedwarn ("ANSI C++ forbids initialization of new expression with `='");
- $$ = $2;
+ if (TREE_CODE ($2) != TREE_LIST
+ && TREE_CODE ($2) != CONSTRUCTOR)
+ $$ = build_expr_list (NULL_TREE, $2);
+ else
+ $$ = $2;
}
;
/* This is necessary to postpone reduction of `int ((int)(int)(int))'. */
regcast_or_absdcl:
- '(' type_id ')' %prec EMPTY
- { $2 = tree_cons (NULL_TREE, $2, void_list_node);
- TREE_PARMLIST ($2) = 1;
- $$ = build_parse_node (CALL_EXPR, NULL_TREE, $2,
- NULL_TREE); }
- | regcast_or_absdcl '(' type_id ')' %prec EMPTY
- { $3 = tree_cons (NULL_TREE, $3, void_list_node);
- TREE_PARMLIST ($3) = 1;
- $$ = build_parse_node (CALL_EXPR, $$, $3, NULL_TREE); }
+ '(' type_id ')' %prec EMPTY
+ { $2.t = finish_parmlist (build_tree_list (NULL_TREE, $2.t), 0);
+ $$ = make_call_declarator (NULL_TREE, $2.t, NULL_TREE, NULL_TREE);
+ check_for_new_type ("cast", $2); }
+ | regcast_or_absdcl '(' type_id ')' %prec EMPTY
+ { $3.t = finish_parmlist (build_tree_list (NULL_TREE, $3.t), 0);
+ $$ = make_call_declarator ($$, $3.t, NULL_TREE, NULL_TREE);
+ check_for_new_type ("cast", $3); }
;
cast_expr:
@@ -1242,15 +1238,11 @@ expr_no_commas:
| expr_no_commas '?' xexpr ':' expr_no_commas
{ $$ = build_x_conditional_expr ($$, $3, $5); }
| expr_no_commas '=' expr_no_commas
- { $$ = build_modify_expr ($$, NOP_EXPR, $3);
- C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
+ { $$ = build_x_modify_expr ($$, NOP_EXPR, $3);
+ if ($$ != error_mark_node)
+ C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
| expr_no_commas ASSIGN expr_no_commas
- { register tree rval;
- if ((rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3,
- make_node ($2))))
- $$ = rval;
- else
- $$ = build_modify_expr ($$, $2, $3); }
+ { $$ = build_x_modify_expr ($$, $2, $3); }
| THROW
{ $$ = build_throw (NULL_TREE); }
| THROW expr_no_commas
@@ -1258,13 +1250,13 @@ expr_no_commas:
/* These extensions are not defined. The second arg to build_m_component_ref
is old, build_m_component_ref now does an implicit
build_indirect_ref (x, NULL_PTR) on the second argument.
- | object '&' expr_no_commas %prec UNARY
+ | object '&' expr_no_commas %prec UNARY
{ $$ = build_m_component_ref ($$, build_x_unary_op (ADDR_EXPR, $3)); }
| object unop expr_no_commas %prec UNARY
{ $$ = build_m_component_ref ($$, build_x_unary_op ($2, $3)); }
| object '(' type_id ')' expr_no_commas %prec UNARY
- { tree type = groktypename ($3);
- $$ = build_m_component_ref ($$, build_c_cast (type, $5, 0)); }
+ { tree type = groktypename ($3.t);
+ $$ = build_m_component_ref ($$, build_c_cast (type, $5)); }
| object primary_no_id %prec UNARY
{ $$ = build_m_component_ref ($$, $2); }
*/
@@ -1273,30 +1265,62 @@ expr_no_commas:
notype_unqualified_id:
'~' see_typename identifier
{ $$ = build_parse_node (BIT_NOT_EXPR, $3); }
+ | template_id
| operator_name
| IDENTIFIER
| PTYPENAME
- | NSNAME %prec EMPTY
+ | NSNAME %prec EMPTY
;
+do_id:
+ { $$ = do_identifier ($<ttype>-1, 1, NULL_TREE); }
+
+template_id:
+ PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
+ { $$ = lookup_template_function ($3, $4); }
+ | operator_name '<' do_id template_arg_list_opt template_close_bracket
+ { $$ = lookup_template_function ($3, $4); }
+ ;
+
+object_template_id:
+ TEMPLATE identifier '<' template_arg_list_opt template_close_bracket
+ { $$ = lookup_template_function ($2, $4); }
+ | TEMPLATE PFUNCNAME '<' template_arg_list_opt template_close_bracket
+ { $$ = lookup_template_function ($2, $4); }
+ | TEMPLATE operator_name '<' template_arg_list_opt
+ template_close_bracket
+ { $$ = lookup_template_function ($2, $4); }
+ ;
+
unqualified_id:
notype_unqualified_id
| TYPENAME
+ | SELFNAME
;
expr_or_declarator:
notype_unqualified_id
- | '*' expr_or_declarator %prec UNARY
+ | '*' expr_or_declarator %prec UNARY
{ $$ = build_parse_node (INDIRECT_REF, $2); }
- | '&' expr_or_declarator %prec UNARY
+ | '&' expr_or_declarator %prec UNARY
{ $$ = build_parse_node (ADDR_EXPR, $2); }
| '(' expr_or_declarator ')'
{ $$ = $2; }
;
+notype_template_declarator:
+ IDENTIFIER '<' template_arg_list_opt template_close_bracket
+ { $$ = lookup_template_function ($1, $3); }
+ | NSNAME '<' template_arg_list template_close_bracket
+ { $$ = lookup_template_function ($1, $3); }
+ ;
+
direct_notype_declarator:
complex_direct_notype_declarator
- | notype_unqualified_id
+ /* This precedence declaration is to prefer this reduce
+ to the Koenig lookup shift in primary, below. I hate yacc. */
+ | notype_unqualified_id %prec '('
+ | notype_template_declarator
| '(' expr_or_declarator ')'
{ $$ = finish_decl_parsing ($2); }
;
@@ -1304,43 +1328,26 @@ direct_notype_declarator:
primary:
notype_unqualified_id
{
- if (TREE_CODE ($$) == BIT_NOT_EXPR)
- $$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($$, 0));
- else if (IDENTIFIER_OPNAME_P ($$))
- {
- tree op = $$;
- $$ = lookup_name (op, 0);
- if ($$ == NULL_TREE)
- {
- if (op != ansi_opname[ERROR_MARK])
- error ("operator %s not defined",
- operator_name_string (op));
- $$ = error_mark_node;
- }
- }
- else
- $$ = do_identifier ($$);
+ if (TREE_CODE ($1) == BIT_NOT_EXPR)
+ $$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($1, 0));
+ else
+ $$ = finish_id_expr ($1);
}
| CONSTANT
| boolean.literal
| string
- { $$ = combine_strings ($$); }
+ {
+ if (processing_template_decl)
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ $$ = combine_strings ($$);
+ if (processing_template_decl)
+ pop_obstacks ();
+ }
| '(' expr ')'
- { char class;
- $$ = $2;
- class = TREE_CODE_CLASS (TREE_CODE ($$));
- if (class == 'e' || class == '1'
- || class == '2' || class == '<')
- /* This inhibits warnings in truthvalue_conversion. */
- C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); }
+ { $$ = finish_parenthesized_expr ($2); }
| '(' expr_or_declarator ')'
- { char class;
- $$ = reparse_decl_as_expr (NULL_TREE, $2);
- class = TREE_CODE_CLASS (TREE_CODE ($$));
- if (class == 'e' || class == '1'
- || class == '2' || class == '<')
- /* This inhibits warnings in truthvalue_conversion. */
- C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); }
+ { $2 = reparse_decl_as_expr (NULL_TREE, $2);
+ $$ = finish_parenthesized_expr ($2); }
| '(' error ')'
{ $$ = error_mark_node; }
| '('
@@ -1349,90 +1356,35 @@ primary:
error ("braced-group within expression allowed only inside a function");
YYERROR;
}
- keep_next_level ();
- $<ttype>$ = expand_start_stmt_expr (); }
- compstmt ')'
- { tree rtl_exp;
if (pedantic)
- pedwarn ("ANSI C++ forbids braced-groups within expressions");
- rtl_exp = expand_end_stmt_expr ($<ttype>2);
- /* The statements have side effects, so the group does. */
- TREE_SIDE_EFFECTS (rtl_exp) = 1;
-
- if (TREE_CODE ($3) == BLOCK)
- {
- /* Make a BIND_EXPR for the BLOCK already made. */
- $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp),
- NULL_TREE, rtl_exp, $3);
- /* Remove the block from the tree at this point.
- It gets put back at the proper place
- when the BIND_EXPR is expanded. */
- delete_block ($3);
- }
- else
- $$ = $3;
+ pedwarn ("ANSI C++ forbids braced-groups within expressions");
+ $<ttype>$ = begin_stmt_expr ();
}
+ compstmt ')'
+ { $$ = finish_stmt_expr ($<ttype>2, $3); }
+ /* Koenig lookup support
+ We could store lastiddecl in $1 to avoid another lookup,
+ but that would result in many additional reduce/reduce conflicts. */
+ | notype_unqualified_id '(' nonnull_exprlist ')'
+ { $$ = finish_call_expr ($1, $3, 1); }
+ | notype_unqualified_id LEFT_RIGHT
+ { $$ = finish_call_expr ($1, NULL_TREE, 1); }
| primary '(' nonnull_exprlist ')'
- { /* [eichin:19911016.1902EST] */
- $<ttype>$ = build_x_function_call ($1, $3, current_class_decl);
- /* here we instantiate_class_template as needed... */
- do_pending_templates ();
- } template_instantiate_some {
- if (TREE_CODE ($<ttype>5) == CALL_EXPR
- && TREE_TYPE ($<ttype>5) != void_type_node)
- $$ = require_complete_type ($<ttype>5);
- else
- $$ = $<ttype>5;
- }
+ { $$ = finish_call_expr ($1, $3, 0); }
| primary LEFT_RIGHT
- {
- $$ = build_x_function_call ($$, NULL_TREE, current_class_decl);
- if (TREE_CODE ($$) == CALL_EXPR
- && TREE_TYPE ($$) != void_type_node)
- $$ = require_complete_type ($$);
- }
+ { $$ = finish_call_expr ($1, NULL_TREE, 0); }
| primary '[' expr ']'
{ $$ = grok_array_decl ($$, $3); }
| primary PLUSPLUS
- { /* If we get an OFFSET_REF, turn it into what it really
- means (e.g., a COMPONENT_REF). This way if we've got,
- say, a reference to a static member that's being operated
- on, we don't end up trying to find a member operator for
- the class it's in. */
- if (TREE_CODE ($$) == OFFSET_REF)
- $$ = resolve_offset_ref ($$);
- $$ = build_x_unary_op (POSTINCREMENT_EXPR, $$); }
+ { $$ = finish_increment_expr ($1, POSTINCREMENT_EXPR); }
| primary MINUSMINUS
- { if (TREE_CODE ($$) == OFFSET_REF)
- $$ = resolve_offset_ref ($$);
- $$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); }
+ { $$ = finish_increment_expr ($1, POSTDECREMENT_EXPR); }
/* C++ extensions */
| THIS
- { if (current_class_decl)
- {
-#ifdef WARNING_ABOUT_CCD
- TREE_USED (current_class_decl) = 1;
-#endif
- $$ = current_class_decl;
- }
- else if (current_function_decl
- && DECL_STATIC_FUNCTION_P (current_function_decl))
- {
- error ("`this' is unavailable for static member functions");
- $$ = error_mark_node;
- }
- else
- {
- if (current_function_decl)
- error ("invalid use of `this' in non-member function");
- else
- error ("invalid use of `this' at top level");
- $$ = error_mark_node;
- }
- }
- | TYPE_QUAL '(' nonnull_exprlist ')'
+ { $$ = finish_this_expr (); }
+ | CV_QUALIFIER '(' nonnull_exprlist ')'
{
- tree type;
+ tree type = NULL_TREE;
tree id = $$;
/* This is a C cast in C++'s `functional' notation. */
@@ -1471,180 +1423,80 @@ primary:
}
#endif
else my_friendly_abort (79);
- $$ = build_c_cast (type, build_compound_expr ($3), 1);
+ $$ = build_c_cast (type, build_compound_expr ($3));
}
}
| functional_cast
- | DYNAMIC_CAST '<'
- { dont_allow_type_definitions = "inside dynamic_cast"; }
- type_id '>'
- { dont_allow_type_definitions = 0; }
- '(' expr ')'
- { tree type = groktypename ($4);
- $$ = build_dynamic_cast (type, $8); }
- | STATIC_CAST '<'
- { dont_allow_type_definitions = "inside static_cast"; }
- type_id '>'
- { dont_allow_type_definitions = 0; }
- '(' expr ')'
- { tree type = groktypename ($4);
- $$ = build_static_cast (type, $8); }
- | REINTERPRET_CAST '<'
- { dont_allow_type_definitions = "inside reinterpret_cast"; }
- type_id '>'
- { dont_allow_type_definitions = 0; }
- '(' expr ')'
- { tree type = groktypename ($4);
- $$ = build_reinterpret_cast (type, $8); }
- | CONST_CAST '<'
- { dont_allow_type_definitions = "inside const_cast"; }
- type_id '>'
- { dont_allow_type_definitions = 0; }
- '(' expr ')'
- { tree type = groktypename ($4);
- $$ = build_const_cast (type, $8); }
+ | DYNAMIC_CAST '<' type_id '>' '(' expr ')'
+ { tree type = groktypename ($3.t);
+ check_for_new_type ("dynamic_cast", $3);
+ $$ = build_dynamic_cast (type, $6); }
+ | STATIC_CAST '<' type_id '>' '(' expr ')'
+ { tree type = groktypename ($3.t);
+ check_for_new_type ("static_cast", $3);
+ $$ = build_static_cast (type, $6); }
+ | REINTERPRET_CAST '<' type_id '>' '(' expr ')'
+ { tree type = groktypename ($3.t);
+ check_for_new_type ("reinterpret_cast", $3);
+ $$ = build_reinterpret_cast (type, $6); }
+ | CONST_CAST '<' type_id '>' '(' expr ')'
+ { tree type = groktypename ($3.t);
+ check_for_new_type ("const_cast", $3);
+ $$ = build_const_cast (type, $6); }
| TYPEID '(' expr ')'
- { $$ = build_typeid ($3); }
+ { $$ = build_x_typeid ($3); }
| TYPEID '(' type_id ')'
- { tree type = groktypename ($3);
+ { tree type = groktypename ($3.t);
+ check_for_new_type ("typeid", $3);
$$ = get_typeid (TYPE_MAIN_VARIANT (type)); }
| global_scope IDENTIFIER
- {
- do_scoped_id:
- $$ = IDENTIFIER_GLOBAL_VALUE ($2);
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- if (! $$)
- {
- if (yychar == '(' || yychar == LEFT_RIGHT)
- $$ = implicitly_declare ($2);
- else
- {
- if (IDENTIFIER_GLOBAL_VALUE ($2) != error_mark_node)
- error ("undeclared variable `%s' (first use here)",
- IDENTIFIER_POINTER ($2));
- $$ = error_mark_node;
- /* Prevent repeated error messages. */
- IDENTIFIER_GLOBAL_VALUE ($2) = error_mark_node;
- }
- }
- else
- {
- if (TREE_CODE ($$) == ADDR_EXPR)
- assemble_external (TREE_OPERAND ($$, 0));
- else
- assemble_external ($$);
- TREE_USED ($$) = 1;
- }
- if (TREE_CODE ($$) == CONST_DECL)
- {
- /* XXX CHS - should we set TREE_USED of the constant? */
- $$ = DECL_INITIAL ($$);
- /* This is to prevent an enum whose value is 0
- from being considered a null pointer constant. */
- $$ = build1 (NOP_EXPR, TREE_TYPE ($$), $$);
- TREE_CONSTANT ($$) = 1;
- }
-
- }
+ { $$ = do_scoped_id ($2, 1); }
+ | global_scope template_id
+ { $$ = $2; }
| global_scope operator_name
{
got_scope = NULL_TREE;
if (TREE_CODE ($2) == IDENTIFIER_NODE)
- goto do_scoped_id;
- $$ = $2;
+ $$ = do_scoped_id ($2, 1);
+ else
+ $$ = $2;
}
- | overqualified_id %prec HYPERUNARY
+ | overqualified_id %prec HYPERUNARY
{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
| overqualified_id '(' nonnull_exprlist ')'
- { $$ = build_member_call (OP0 ($$), OP1 ($$), $3); }
+ { $$ = finish_globally_qualified_member_call_expr ($1, $3); }
| overqualified_id LEFT_RIGHT
- { $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
+ { $$ = finish_globally_qualified_member_call_expr ($1, NULL_TREE); }
+ | object object_template_id %prec UNARY
+ {
+ $$ = build_x_component_ref ($$, $2, NULL_TREE, 1);
+ }
+ | object object_template_id '(' nonnull_exprlist ')'
+ { $$ = finish_object_call_expr ($2, $1, $4); }
+ | object object_template_id LEFT_RIGHT
+ { $$ = finish_object_call_expr ($2, $1, NULL_TREE); }
| object unqualified_id %prec UNARY
- { got_object = NULL_TREE;
- $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
- | object overqualified_id %prec UNARY
- { got_object = NULL_TREE;
- $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
+ { $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); }
+ | object overqualified_id %prec UNARY
+ { if (processing_template_decl)
+ $$ = build_min_nt (COMPONENT_REF, $1, copy_to_permanent ($2));
+ else
+ $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
| object unqualified_id '(' nonnull_exprlist ')'
- {
- got_object = NULL_TREE;
-#if 0
- /* This is a future direction of this code, but because
- build_x_function_call cannot always undo what is done
- in build_component_ref entirely yet, we cannot do this. */
- $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), $4, $$);
- if (TREE_CODE ($$) == CALL_EXPR
- && TREE_TYPE ($$) != void_type_node)
- $$ = require_complete_type ($$);
-#else
- $$ = build_method_call ($$, $2, $4, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR));
-#endif
- }
+ { $$ = finish_object_call_expr ($2, $1, $4); }
| object unqualified_id LEFT_RIGHT
- {
- got_object = NULL_TREE;
-#if 0
- /* This is a future direction of this code, but because
- build_x_function_call cannot always undo what is done
- in build_component_ref entirely yet, we cannot do this. */
- $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), NULL_TREE, $$);
- if (TREE_CODE ($$) == CALL_EXPR
- && TREE_TYPE ($$) != void_type_node)
- $$ = require_complete_type ($$);
-#else
- $$ = build_method_call ($$, $2, NULL_TREE, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR));
-#endif
- }
+ { $$ = finish_object_call_expr ($2, $1, NULL_TREE); }
| object overqualified_id '(' nonnull_exprlist ')'
- {
- got_object = NULL_TREE;
- if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
- {
- warning ("signature name in scope resolution ignored");
- $$ = build_method_call ($$, OP1 ($2), $4, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR));
- }
- else
- $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4);
- }
+ { $$ = finish_qualified_object_call_expr ($2, $1, $4); }
| object overqualified_id LEFT_RIGHT
- {
- got_object = NULL_TREE;
- if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
- {
- warning ("signature name in scope resolution ignored");
- $$ = build_method_call ($$, OP1 ($2), NULL_TREE, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR));
- }
- else
- $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), NULL_TREE);
- }
+ { $$ = finish_qualified_object_call_expr ($2, $1, NULL_TREE); }
/* p->int::~int() is valid -- 12.4 */
| object '~' TYPESPEC LEFT_RIGHT
- {
- got_object = NULL_TREE;
- if (IDENTIFIER_GLOBAL_VALUE ($3)
- && (TREE_CODE (TREE_TYPE ($1))
- != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3)))))
- cp_error ("`%E' is not of type `%T'", $1, $3);
- $$ = convert (void_type_node, $1);
- }
+ { $$ = finish_pseudo_destructor_call_expr ($1, NULL_TREE, $3); }
| object TYPESPEC SCOPE '~' TYPESPEC LEFT_RIGHT
- {
- got_object = NULL_TREE;
- if ($2 != $5)
- cp_error ("destructor specifier `%T::~%T()' must have matching names", $2, $5);
- if (TREE_CODE (TREE_TYPE ($1))
- != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($2))))
- cp_error ("`%E' is not of type `%T'", $1, $2);
- $$ = convert (void_type_node, $1);
- }
+ { $$ = finish_pseudo_destructor_call_expr ($1, $2, $5); }
| object error
{
- got_object = NULL_TREE;
$$ = error_mark_node;
}
;
@@ -1668,9 +1520,9 @@ primary_no_id:
pedwarn ("ANSI C++ forbids braced-groups within expressions");
$$ = expand_end_stmt_expr ($<ttype>2); }
| primary_no_id '(' nonnull_exprlist ')'
- { $$ = build_x_function_call ($$, $3, current_class_decl); }
+ { $$ = build_x_function_call ($$, $3, current_class_ref); }
| primary_no_id LEFT_RIGHT
- { $$ = build_x_function_call ($$, NULL_TREE, current_class_decl); }
+ { $$ = build_x_function_call ($$, NULL_TREE, current_class_ref); }
| primary_no_id '[' expr ']'
{ goto do_array; }
| primary_no_id PLUSPLUS
@@ -1687,13 +1539,15 @@ primary_no_id:
;
*/
-new: NEW
+new:
+ NEW
{ $$ = 0; }
| global_scope NEW
{ got_scope = NULL_TREE; $$ = 1; }
;
-delete: DELETE
+delete:
+ DELETE
{ $$ = 0; }
| global_scope delete
{ got_scope = NULL_TREE; $$ = 1; }
@@ -1726,7 +1580,8 @@ nodecls:
}
;
-object: primary '.'
+object:
+ primary '.'
{ got_object = TREE_TYPE ($$); }
| primary POINTSAT
{
@@ -1736,79 +1591,65 @@ object: primary '.'
;
decl:
- /* Normal case: make this fast. */
- typespec declarator ';'
- { tree d = get_decl_list ($1);
- int yes = suspend_momentary ();
- d = start_decl ($2, d, 0, NULL_TREE);
- cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
- resume_momentary (yes);
- if (IS_AGGR_TYPE_CODE (TREE_CODE ($1)))
- note_got_semicolon ($1);
- }
- | typed_declspecs declarator ';'
- { 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);
- }
- | typespec initdecls ';'
+ typespec initdecls ';'
{
resume_momentary ($2);
- if (IS_AGGR_TYPE_CODE (TREE_CODE ($1)))
- note_got_semicolon ($1);
+ if ($1.t && IS_AGGR_TYPE_CODE (TREE_CODE ($1.t)))
+ note_got_semicolon ($1.t);
}
| typed_declspecs initdecls ';'
{
resume_momentary ($2);
- note_list_got_semicolon ($1);
+ note_list_got_semicolon ($1.t);
}
| declmods notype_initdecls ';'
{ resume_momentary ($2); }
| typed_declspecs ';'
{
- shadow_tag ($1);
- note_list_got_semicolon ($1);
+ shadow_tag ($1.t);
+ note_list_got_semicolon ($1.t);
}
| declmods ';'
{ warning ("empty declaration"); }
+ | extension decl
+ { pedantic = $<itype>1; }
;
/* Any kind of declarator (thus, all declarators allowed
after an explicit typespec). */
declarator:
- after_type_declarator %prec EMPTY
- | notype_declarator %prec EMPTY
+ after_type_declarator %prec EMPTY
+ | notype_declarator %prec EMPTY
;
/* This is necessary to postpone reduction of `int()()()()'. */
fcast_or_absdcl:
- LEFT_RIGHT %prec EMPTY
- { $$ = build_parse_node (CALL_EXPR, NULL_TREE, empty_parms (),
- NULL_TREE); }
- | fcast_or_absdcl LEFT_RIGHT %prec EMPTY
- { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (),
- NULL_TREE); }
+ LEFT_RIGHT %prec EMPTY
+ { $$ = make_call_declarator (NULL_TREE, empty_parms (),
+ NULL_TREE, NULL_TREE); }
+ | fcast_or_absdcl LEFT_RIGHT %prec EMPTY
+ { $$ = make_call_declarator ($$, empty_parms (), NULL_TREE,
+ NULL_TREE); }
;
/* ANSI type-id (8.1) */
type_id:
typed_typespecs absdcl
- { $$ = build_decl_list ($$, $2); }
- | nonempty_type_quals absdcl
- { $$ = build_decl_list ($$, $2); }
+ { $$.t = build_decl_list ($1.t, $2);
+ $$.new_type_flag = $1.new_type_flag; }
+ | nonempty_cv_qualifiers absdcl
+ { $$.t = build_decl_list ($1.t, $2);
+ $$.new_type_flag = $1.new_type_flag; }
| typespec absdcl
- { $$ = build_decl_list (get_decl_list ($$), $2); }
- | typed_typespecs %prec EMPTY
- { $$ = build_decl_list ($$, NULL_TREE); }
- | nonempty_type_quals %prec EMPTY
- { $$ = build_decl_list ($$, NULL_TREE); }
+ { $$.t = build_decl_list (get_decl_list ($1.t), $2);
+ $$.new_type_flag = $1.new_type_flag; }
+ | typed_typespecs %prec EMPTY
+ { $$.t = build_decl_list ($1.t, NULL_TREE);
+ $$.new_type_flag = $1.new_type_flag; }
+ | nonempty_cv_qualifiers %prec EMPTY
+ { $$.t = build_decl_list ($1.t, NULL_TREE);
+ $$.new_type_flag = $1.new_type_flag; }
;
/* Declspecs which contain at least one type specifier or typedef name.
@@ -1817,24 +1658,30 @@ type_id:
In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */
typed_declspecs:
- typed_typespecs %prec EMPTY
+ typed_typespecs %prec EMPTY
| typed_declspecs1
;
typed_declspecs1:
declmods typespec
- { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
- | typespec reserved_declspecs %prec HYPERUNARY
- { $$ = decl_tree_cons (NULL_TREE, $$, $2); }
+ { $$.t = decl_tree_cons (NULL_TREE, $2.t, $1);
+ $$.new_type_flag = $2.new_type_flag; }
+ | typespec reserved_declspecs %prec HYPERUNARY
+ { $$.t = decl_tree_cons (NULL_TREE, $1.t, $2);
+ $$.new_type_flag = $1.new_type_flag; }
| typespec reserved_typespecquals reserved_declspecs
- { $$ = decl_tree_cons (NULL_TREE, $$, chainon ($2, $3)); }
+ { $$.t = decl_tree_cons (NULL_TREE, $1.t, chainon ($2, $3));
+ $$.new_type_flag = $1.new_type_flag; }
| declmods typespec reserved_declspecs
- { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
+ { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1));
+ $$.new_type_flag = $2.new_type_flag; }
| declmods typespec reserved_typespecquals
- { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
+ { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1));
+ $$.new_type_flag = $2.new_type_flag; }
| declmods typespec reserved_typespecquals reserved_declspecs
- { $$ = decl_tree_cons (NULL_TREE, $2,
- chainon ($3, chainon ($4, $$))); }
+ { $$.t = decl_tree_cons (NULL_TREE, $2.t,
+ chainon ($3, chainon ($4, $1)));
+ $$.new_type_flag = $2.new_type_flag; }
;
reserved_declspecs:
@@ -1844,7 +1691,7 @@ reserved_declspecs:
IDENTIFIER_POINTER ($$));
$$ = build_decl_list (NULL_TREE, $$); }
| reserved_declspecs typespecqual_reserved
- { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
+ { $$ = decl_tree_cons (NULL_TREE, $2.t, $$); }
| reserved_declspecs SCSPEC
{ if (extra_warnings)
warning ("`%s' is not at beginning of declaration",
@@ -1862,11 +1709,11 @@ reserved_declspecs:
In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */
declmods:
- nonempty_type_quals %prec EMPTY
- { TREE_STATIC ($$) = 1; }
+ nonempty_cv_qualifiers %prec EMPTY
+ { $$ = $1.t; TREE_STATIC ($$) = 1; }
| SCSPEC
{ $$ = IDENTIFIER_AS_LIST ($$); }
- | declmods TYPE_QUAL
+ | declmods CV_QUALIFIER
{ $$ = decl_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = 1; }
| declmods SCSPEC
@@ -1889,71 +1736,81 @@ declmods:
typed_typespecs:
typespec %prec EMPTY
- { $$ = get_decl_list ($$); }
- | nonempty_type_quals typespec
- { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
+ { $$.t = get_decl_list ($1.t);
+ $$.new_type_flag = $1.new_type_flag; }
+ | nonempty_cv_qualifiers typespec
+ { $$.t = decl_tree_cons (NULL_TREE, $2.t, $1.t);
+ $$.new_type_flag = $2.new_type_flag; }
| typespec reserved_typespecquals
- { $$ = decl_tree_cons (NULL_TREE, $$, $2); }
- | nonempty_type_quals typespec reserved_typespecquals
- { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
+ { $$.t = decl_tree_cons (NULL_TREE, $1.t, $2);
+ $$.new_type_flag = $1.new_type_flag; }
+ | nonempty_cv_qualifiers typespec reserved_typespecquals
+ { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
+ $$.new_type_flag = $1.new_type_flag; }
;
reserved_typespecquals:
typespecqual_reserved
- { $$ = build_decl_list (NULL_TREE, $$); }
+ { $$ = build_decl_list (NULL_TREE, $1.t); }
| reserved_typespecquals typespecqual_reserved
- { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
+ { $$ = decl_tree_cons (NULL_TREE, $2.t, $1); }
;
/* A typespec (but not a type qualifier).
Once we have seen one of these in a declaration,
if a typedef name appears then it is being redeclared. */
-typespec: structsp
+typespec:
+ structsp
| TYPESPEC %prec EMPTY
+ { $$.t = $1; $$.new_type_flag = 0; }
| complete_type_name
+ { $$.t = $1; $$.new_type_flag = 0; }
| TYPEOF '(' expr ')'
- { $$ = TREE_TYPE ($3);
- if (pedantic && !in_system_header)
- pedwarn ("ANSI C++ forbids `typeof'"); }
+ { $$.t = TREE_TYPE ($3);
+ $$.new_type_flag = 0; }
| TYPEOF '(' type_id ')'
- { $$ = groktypename ($3);
- if (pedantic && !in_system_header)
- pedwarn ("ANSI C++ forbids `typeof'"); }
+ { $$.t = groktypename ($3.t);
+ $$.new_type_flag = 0; }
| SIGOF '(' expr ')'
{ tree type = TREE_TYPE ($3);
+ $$.new_type_flag = 0;
if (IS_AGGR_TYPE (type))
{
sorry ("sigof type specifier");
- $$ = type;
+ $$.t = type;
}
else
{
error ("`sigof' applied to non-aggregate expression");
- $$ = error_mark_node;
+ $$.t = error_mark_node;
}
}
| SIGOF '(' type_id ')'
- { tree type = groktypename ($3);
+ { tree type = groktypename ($3.t);
+ $$.new_type_flag = 0;
if (IS_AGGR_TYPE (type))
{
sorry ("sigof type specifier");
- $$ = type;
+ $$.t = type;
}
else
{
error("`sigof' applied to non-aggregate type");
- $$ = error_mark_node;
+ $$.t = error_mark_node;
}
}
;
/* A typespec that is a reserved word, or a type qualifier. */
-typespecqual_reserved: TYPESPEC
- | TYPE_QUAL
+typespecqual_reserved:
+ TYPESPEC
+ { $$.t = $1; $$.new_type_flag = 0; }
+ | CV_QUALIFIER
+ { $$.t = $1; $$.new_type_flag = 0; }
| structsp
;
@@ -1979,104 +1836,67 @@ maybeasm:
{ if (TREE_CHAIN ($3)) $3 = combine_strings ($3); $$ = $3; }
;
-initdcl0:
- declarator exception_specification_opt maybeasm maybe_attribute '='
- { 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)
- {
- current_declspecs = decl_tree_cons
- (NULL_TREE, get_identifier ("extern"),
- current_declspecs);
- used_extern_spec = 1;
- }
- $<itype>5 = suspend_momentary ();
- $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1, $2);
- cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); }
- init
-/* Note how the declaration of the variable is in effect while its init is parsed! */
- { cp_finish_decl ($<ttype>6, $7, $3, 0, LOOKUP_ONLYCONVERTING);
- $$ = $<itype>5; }
- | declarator exception_specification_opt maybeasm maybe_attribute
- { tree d;
- 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)
- {
- current_declspecs = decl_tree_cons
- (NULL_TREE, get_identifier ("extern"),
- current_declspecs);
- used_extern_spec = 1;
- }
- $$ = suspend_momentary ();
- d = start_decl ($<ttype>1, current_declspecs, 0, $2);
- cplus_decl_attributes (d, $4, prefix_attributes);
- cp_finish_decl (d, NULL_TREE, $3, 0, 0); }
- ;
-
initdcl:
- declarator exception_specification_opt maybeasm maybe_attribute '='
- { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1, $2);
- cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); }
+ declarator maybeasm maybe_attribute '='
+ { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1,
+ $3, prefix_attributes); }
init
/* Note how the declaration of the variable is in effect while its init is parsed! */
- { cp_finish_decl ($<ttype>6, $7, $3, 0, LOOKUP_ONLYCONVERTING); }
- | declarator exception_specification_opt maybeasm maybe_attribute
- { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0, $2);
- cplus_decl_attributes ($<ttype>$, $4, prefix_attributes);
- cp_finish_decl ($<ttype>$, NULL_TREE, $3, 0, 0); }
- ;
-
-notype_initdcl0:
- notype_declarator exception_specification_opt maybeasm maybe_attribute '='
- { 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); }
+ { cp_finish_decl ($<ttype>5, $6, $2, 1, LOOKUP_ONLYCONVERTING); }
+ | declarator maybeasm maybe_attribute
+ { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0,
+ $3, prefix_attributes);
+ cp_finish_decl ($<ttype>$, NULL_TREE, $2, 1, 0); }
+ ;
+
+ /* This rule assumes a certain configuration of the parser stack.
+ In particular, $0, the element directly before the beginning of
+ this rule on the stack, must be a maybeasm. $-1 must be a
+ declarator or notype_declarator. And $-2 must be some declmods
+ or declspecs. We can't move the maybeasm into this rule because
+ we need that reduce so we prefer fn.def1 when appropriate. */
+initdcl0_innards:
+ maybe_attribute '='
+ { $<itype>2 = parse_decl ($<ttype>-1, $<ttype>-2,
+ $1, 1, &$<ttype>$); }
+ /* Note how the declaration of the variable is in effect
+ while its init is parsed! */
init
-/* Note how the declaration of the variable is in effect while its init is parsed! */
- { cp_finish_decl ($<ttype>6, $7, $3, 0, LOOKUP_ONLYCONVERTING);
- $$ = $<itype>5; }
- | notype_declarator exception_specification_opt maybeasm maybe_attribute
+ { cp_finish_decl ($<ttype>3, $4, $<ttype>0, 1,
+ LOOKUP_ONLYCONVERTING);
+ $$ = $<itype>2; }
+ | maybe_attribute
{ tree d;
- 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);
- cp_finish_decl (d, NULL_TREE, $3, 0, 0); }
- ;
-
+ $$ = parse_decl ($<ttype>-1, $<ttype>-2, $1, 0, &d);
+ cp_finish_decl (d, NULL_TREE, $<ttype>0, 1, 0); }
+ ;
+
+initdcl0:
+ declarator maybeasm initdcl0_innards
+ { $$ = $3; }
+
+notype_initdcl0:
+ notype_declarator maybeasm initdcl0_innards
+ { $$ = $3; }
+ ;
+
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); }
- init
-/* Note how the declaration of the variable is in effect while its init is parsed! */
- { cp_finish_decl ($<ttype>6, $7, $3, 0, LOOKUP_ONLYCONVERTING);
- $$ = $<itype>5; }
- | notype_declarator exception_specification_opt maybeasm maybe_attribute
+ notype_declarator maybeasm
+ { /* Set things up as initdcl0_innards expects. */
+ $<ttype>2 = $1;
+ $1 = NULL_TREE; }
+ initdcl0_innards
+ {}
+ | constructor_declarator 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);
- cp_finish_decl (d, NULL_TREE, $3, 0, 0); }
+ parse_decl($1, NULL_TREE, $3, 0, &d);
+ cp_finish_decl (d, NULL_TREE, $2, 1, 0); }
;
/* the * rules are dummies to accept the Apollo extended syntax
- so that the header files compile. */
+ so that the header files compile. */
maybe_attribute:
- /* empty */
+ /* empty */
{ $$ = NULL_TREE; }
| attributes
{ $$ = $1; }
@@ -2102,7 +1922,7 @@ attribute_list:
;
attrib:
- /* empty */
+ /* empty */
{ $$ = NULL_TREE; }
| any_word
{ $$ = build_tree_list ($1, NULL_TREE); }
@@ -2121,25 +1941,28 @@ any_word:
identifier
| SCSPEC
| TYPESPEC
- | TYPE_QUAL
+ | CV_QUALIFIER
;
/* A nonempty list of identifiers, including typenames. */
identifiers_or_typenames:
- identifier
+ identifier
{ $$ = build_tree_list (NULL_TREE, $1); }
| identifiers_or_typenames ',' identifier
{ $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
;
maybe_init:
- %prec EMPTY /* empty */
+ /* empty */ %prec EMPTY
{ $$ = NULL_TREE; }
| '=' init
{ $$ = $2; }
+/* If we are processing a template, we don't want to expand this
+ initializer yet. */
+
init:
- expr_no_commas %prec '='
+ expr_no_commas %prec '='
| '{' '}'
{ $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE);
TREE_HAS_CONSTRUCTOR ($$) = 1; }
@@ -2159,101 +1982,126 @@ initlist:
init
{ $$ = build_tree_list (NULL_TREE, $$); }
| initlist ',' init
- { $$ = tree_cons (NULL_TREE, $3, $$); }
+ { $$ = expr_tree_cons (NULL_TREE, $3, $$); }
/* These are for labeled elements. */
| '[' expr_no_commas ']' init
- { $$ = build_tree_list ($2, $4); }
- | initlist ',' CASE expr_no_commas ':' init
- { $$ = tree_cons ($4, $6, $$); }
+ { $$ = build_expr_list ($2, $4); }
| identifier ':' init
- { $$ = build_tree_list ($$, $3); }
+ { $$ = build_expr_list ($$, $3); }
| initlist ',' identifier ':' init
- { $$ = tree_cons ($3, $5, $$); }
+ { $$ = expr_tree_cons ($3, $5, $$); }
+ ;
+
+fn.defpen:
+ PRE_PARSED_FUNCTION_DECL
+ { start_function (NULL_TREE, TREE_VALUE ($1),
+ NULL_TREE, 1);
+ reinit_parse_for_function (); }
+
+pending_inline:
+ fn.defpen maybe_return_init ctor_initializer_opt compstmt_or_error
+ {
+ int nested = (hack_decl_function_context
+ (current_function_decl) != NULL_TREE);
+ finish_function (lineno, (int)$3, nested);
+ process_next_inline ($1);
+ }
+ | fn.defpen maybe_return_init function_try_block
+ { process_next_inline ($1); }
+ | fn.defpen maybe_return_init error
+ { process_next_inline ($1); }
+ ;
+
+pending_inlines:
+ /* empty */
+ | pending_inlines pending_inline eat_saved_input
+ ;
+
+/* A regurgitated default argument. The value of DEFARG_MARKER will be
+ the TREE_LIST node for the parameter in question. */
+defarg_again:
+ DEFARG_MARKER expr_no_commas END_OF_SAVED_INPUT
+ { replace_defarg ($1, $2); }
+ | DEFARG_MARKER error END_OF_SAVED_INPUT
+ { replace_defarg ($1, error_mark_node); }
+
+pending_defargs:
+ /* empty */ %prec EMPTY
+ | pending_defargs defarg_again
+ { do_pending_defargs (); }
+ | pending_defargs error
+ { do_pending_defargs (); }
;
structsp:
ENUM identifier '{'
{ $<itype>3 = suspend_momentary ();
- $$ = start_enum ($2); }
+ $<ttype>$ = start_enum ($2); }
enumlist maybecomma_warn '}'
- { $$ = finish_enum ($<ttype>4, $5);
+ { $$.t = finish_enum ($<ttype>4, $5);
+ $$.new_type_flag = 1;
resume_momentary ((int) $<itype>3);
check_for_missing_semicolon ($<ttype>4); }
| ENUM identifier '{' '}'
- { $$ = finish_enum (start_enum ($2), NULL_TREE);
- check_for_missing_semicolon ($$); }
+ { $$.t = finish_enum (start_enum ($2), NULL_TREE);
+ $$.new_type_flag = 1;
+ check_for_missing_semicolon ($$.t); }
| ENUM '{'
{ $<itype>2 = suspend_momentary ();
- $$ = start_enum (make_anon_name ()); }
+ $<ttype>$ = start_enum (make_anon_name ()); }
enumlist maybecomma_warn '}'
- { $$ = finish_enum ($<ttype>3, $4);
+ { $$.t = finish_enum ($<ttype>3, $4);
resume_momentary ((int) $<itype>1);
- check_for_missing_semicolon ($<ttype>3); }
+ check_for_missing_semicolon ($<ttype>3);
+ $$.new_type_flag = 1; }
| ENUM '{' '}'
- { $$ = finish_enum (start_enum (make_anon_name()), NULL_TREE);
- check_for_missing_semicolon ($$); }
+ { $$.t = finish_enum (start_enum (make_anon_name()), NULL_TREE);
+ $$.new_type_flag = 1;
+ check_for_missing_semicolon ($$.t); }
| ENUM identifier
- { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); }
+ { $$.t = xref_tag (enum_type_node, $2, NULL_TREE, 1);
+ $$.new_type_flag = 0; }
| ENUM complex_type_name
- { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); }
- | TYPENAME_KEYWORD complex_type_name
- { $$ = $2; }
+ { $$.t = xref_tag (enum_type_node, $2, NULL_TREE, 1);
+ $$.new_type_flag = 0; }
+ | TYPENAME_KEYWORD typename_sub
+ { $$.t = $2;
+ $$.new_type_flag = 0; }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
- | class_head left_curly opt.component_decl_list '}'
- {
+ | class_head left_curly
+ opt.component_decl_list '}' maybe_attribute
+ {
int semi;
- tree id;
-#if 0
- /* Need to rework class nesting in the
- presence of nested classes, etc. */
- shadow_tag (CLASSTYPE_AS_LIST ($$)); */
-#endif
if (yychar == YYEMPTY)
yychar = YYLEX;
semi = yychar == ';';
- /* finish_struct nukes this anyway; if
- finish_exception does too, then it can go. */
- if (semi)
- note_got_semicolon ($$);
- if (TREE_CODE ($$) == ENUMERAL_TYPE)
- /* $$ = $1 from default rule. */;
- else
+ $<ttype>$ = finish_class_definition ($1, $3, $5, semi);
+ }
+ pending_defargs
+ { finish_default_args (); }
+ pending_inlines
+ { $$.t = $<ttype>6;
+ $$.new_type_flag = 1;
+ begin_inline_definitions (); }
+ | class_head %prec EMPTY
+ {
+ $$.new_type_flag = 0;
+ if (TYPE_BINFO ($1) == NULL_TREE)
{
- $$ = finish_struct ($$, $3, semi);
- if (semi) note_got_semicolon ($$);
- }
-
- pop_obstacks ();
-
- id = TYPE_IDENTIFIER ($$);
- if (id && IDENTIFIER_TEMPLATE (id))
+ cp_error ("%T is not a class type", $1);
+ $$.t = error_mark_node;
+ }
+ else
{
- tree decl;
-
- /* I don't know if the copying of this TYPE_DECL is
- * really needed. However, it's such a small per-
- * formance penalty that the extra safety is a bargain.
- * - niklas@appli.se
- */
- push_obstacks (&permanent_obstack, &permanent_obstack);
- decl = copy_node (lookup_name (id, 0));
- if (DECL_LANG_SPECIFIC (decl))
- copy_lang_decl (decl);
- pop_obstacks ();
- undo_template_name_overload (id, 0);
- pushdecl_top_level (decl);
+ $$.t = $1;
+ /* struct B: public A; is not accepted by the WP grammar. */
+ if (TYPE_BINFO_BASETYPES ($$.t) && !TYPE_SIZE ($$.t)
+ && ! TYPE_BEING_DEFINED ($$.t))
+ cp_error ("base clause without member specification for `%#T'",
+ $$.t);
}
- if (! semi)
- check_for_missing_semicolon ($$); }
- | class_head %prec EMPTY
- {
- /* struct B: public A; is not accepted by the WP grammar. */
- if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$)
- && ! TYPE_BEING_DEFINED ($$))
- cp_error ("base clause without member specification for `%#T'",
- $$);
}
;
@@ -2265,64 +2113,70 @@ maybecomma:
maybecomma_warn:
/* empty */
| ','
- { if (pedantic) pedwarn ("comma at end of enumerator list"); }
+ { if (pedantic && !in_system_header)
+ pedwarn ("comma at end of enumerator list"); }
;
-aggr: AGGR
+aggr:
+ AGGR
| aggr SCSPEC
{ error ("storage class specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); }
| aggr TYPESPEC
{ error ("type specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); }
- | aggr TYPE_QUAL
+ | aggr CV_QUALIFIER
{ error ("type qualifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); }
| aggr AGGR
{ error ("no body nor ';' separates two class, struct or union declarations"); }
- ;
-
-specialization:
- aggr template_type_name ';'
- {
- yyungetc (';', 1); current_aggr = $$; $$ = $2;
- if ($<ttype>0 == ridpointers[(int) RID_TEMPLATE])
- instantiate_class_template ($$, 2);
- }
+ | aggr attributes
+ { $$ = build_decl_list ($2, $1); }
;
named_class_head_sans_basetype:
aggr identifier
{ current_aggr = $$; $$ = $2; }
- | specialization
;
named_class_head_sans_basetype_defn:
- aggr identifier_defn %prec EMPTY
+ aggr identifier_defn %prec EMPTY
{ current_aggr = $$; $$ = $2; }
- | aggr template_type_name '{'
- { yyungetc ('{', 1);
- aggr2:
- current_aggr = $$;
- $$ = $2;
- overload_template_name ($$, 0); }
- | aggr template_type_name ':'
- { yyungetc (':', 1); goto aggr2; }
+ | named_class_head_sans_basetype '{'
+ { yyungetc ('{', 1); }
+ | named_class_head_sans_basetype ':'
+ { yyungetc (':', 1); }
;
named_complex_class_head_sans_basetype:
aggr nested_name_specifier identifier
- { current_aggr = $$; $$ = $3; }
- | aggr template_type %prec EMPTY
+ {
+ current_aggr = $1;
+ $$ = handle_class_head ($1, $2, $3);
+ }
+ | aggr global_scope nested_name_specifier identifier
+ {
+ current_aggr = $1;
+ $$ = handle_class_head ($1, $3, $4);
+ }
+ | aggr global_scope identifier
+ {
+ current_aggr = $1;
+ $$ = handle_class_head ($1, NULL_TREE, $3);
+ }
+ | aggr template_type
{ current_aggr = $$; $$ = $2; }
+ | aggr nested_name_specifier template_type
+ { current_aggr = $$; $$ = $3; }
;
-do_xref_defn: /* empty */ %prec EMPTY
- { $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 0); }
+do_xref_defn:
+ /* empty */ %prec EMPTY
+ { $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 0); }
;
named_class_head:
- named_class_head_sans_basetype %prec EMPTY
+ named_class_head_sans_basetype %prec EMPTY
{ $$ = xref_tag (current_aggr, $1, NULL_TREE, 1); }
| named_class_head_sans_basetype_defn do_xref_defn
- maybe_base_class_list %prec EMPTY
+ maybe_base_class_list %prec EMPTY
{
$$ = $<ttype>2;
if ($3)
@@ -2331,22 +2185,46 @@ named_class_head:
| named_complex_class_head_sans_basetype maybe_base_class_list
{
$$ = TREE_TYPE ($1);
+ if (TREE_INT_CST_LOW (current_aggr) == union_type
+ && TREE_CODE ($$) != UNION_TYPE)
+ cp_pedwarn ("`union' tag used in declaring `%#T'", $$);
+ else if (TREE_CODE ($$) == UNION_TYPE
+ && TREE_INT_CST_LOW (current_aggr) != union_type)
+ cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
if ($2)
- xref_basetypes (current_aggr, $1, TREE_TYPE ($1), $2);
+ {
+ if (IS_AGGR_TYPE ($$) && CLASSTYPE_USE_TEMPLATE ($$))
+ {
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION ($$)
+ && TYPE_SIZE ($$) == NULL_TREE)
+ {
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION ($$);
+ if (processing_template_decl)
+ push_template_decl (TYPE_MAIN_DECL ($$));
+ }
+ else if (CLASSTYPE_TEMPLATE_INSTANTIATION ($$))
+ cp_error ("specialization after instantiation of `%T'", $$);
+ }
+ xref_basetypes (current_aggr, $1, $$, $2);
+ }
}
;
-unnamed_class_head: aggr '{'
+unnamed_class_head:
+ aggr '{'
{ $$ = xref_tag ($$, make_anon_name (), NULL_TREE, 0);
yyungetc ('{', 1); }
;
-class_head: unnamed_class_head | named_class_head ;
+class_head:
+ unnamed_class_head
+ | named_class_head
+ ;
maybe_base_class_list:
- %prec EMPTY /* empty */
+ /* empty */ %prec EMPTY
{ $$ = NULL_TREE; }
- | ':' see_typename %prec EMPTY
+ | ':' see_typename %prec EMPTY
{ yyungetc(':', 1); $$ = NULL_TREE; }
| ':' see_typename base_class_list %prec EMPTY
{ $$ = $3; }
@@ -2362,8 +2240,14 @@ base_class:
base_class.1
{
tree type;
- type = IDENTIFIER_TYPE_VALUE ($$);
- if (! is_aggr_typedef ($$, 1))
+ if ($1 == NULL_TREE)
+ {
+ error ("invalid base class");
+ type = error_mark_node;
+ }
+ else
+ type = TREE_TYPE ($1);
+ if (! is_aggr_type (type, 1))
$$ = NULL_TREE;
else if (current_aggr == signature_type_node
&& (! type) && (! IS_SIGNATURE (type)))
@@ -2375,7 +2259,7 @@ base_class:
{
sorry ("signature inheritance, base type `%s' ignored",
IDENTIFIER_POINTER ($$));
- $$ = build_tree_list ((tree)access_public, $$);
+ $$ = build_tree_list (access_public_node, type);
}
else if (type && IS_SIGNATURE (type))
{
@@ -2383,15 +2267,21 @@ base_class:
$$ = NULL_TREE;
}
else
- $$ = build_tree_list ((tree)access_default, $$);
+ $$ = build_tree_list (access_default_node, type);
}
| base_class_access_list see_typename base_class.1
{
tree type;
- type = IDENTIFIER_TYPE_VALUE ($3);
+ if ($3 == NULL_TREE)
+ {
+ error ("invalid base class");
+ type = error_mark_node;
+ }
+ else
+ type = TREE_TYPE ($3);
if (current_aggr == signature_type_node)
error ("access and source specifiers not allowed in signature");
- if (! is_aggr_typedef ($3, 1))
+ if (! is_aggr_type (type, 1))
$$ = NULL_TREE;
else if (current_aggr == signature_type_node
&& (! type) && (! IS_SIGNATURE (type)))
@@ -2403,7 +2293,7 @@ base_class:
{
sorry ("signature inheritance, base type `%s' ignored",
IDENTIFIER_POINTER ($$));
- $$ = build_tree_list ((tree)access_public, $3);
+ $$ = build_tree_list (access_public_node, type);
}
else if (type && IS_SIGNATURE (type))
{
@@ -2411,12 +2301,14 @@ base_class:
$$ = NULL_TREE;
}
else
- $$ = build_tree_list ((tree) $$, $3);
+ $$ = build_tree_list ($$, type);
}
;
base_class.1:
- complete_type_name
+ typename_sub
+ { $$ = TYPE_MAIN_DECL ($1); }
+ | nonnested_type
| SIGOF '(' expr ')'
{
if (current_aggr == signature_type_node)
@@ -2424,8 +2316,7 @@ base_class.1:
if (IS_AGGR_TYPE (TREE_TYPE ($3)))
{
sorry ("`sigof' as base signature specifier");
- /* need to return some dummy signature identifier */
- $$ = $3;
+ $$ = TREE_TYPE ($3);
}
else
{
@@ -2443,11 +2334,10 @@ base_class.1:
{
if (current_aggr == signature_type_node)
{
- if (IS_AGGR_TYPE (groktypename ($3)))
+ if (IS_AGGR_TYPE (groktypename ($3.t)))
{
sorry ("`sigof' as base signature specifier");
- /* need to return some dummy signature identifier */
- $$ = $3;
+ $$ = groktypename ($3.t);
}
else
{
@@ -2466,128 +2356,65 @@ base_class.1:
base_class_access_list:
VISSPEC see_typename
| SCSPEC see_typename
- { if ($<ttype>$ != ridpointers[(int)RID_VIRTUAL])
- sorry ("non-virtual access");
- $$ = access_default_virtual; }
+ { if ($1 != ridpointers[(int)RID_VIRTUAL])
+ cp_error ("`%D' access", $1);
+ $$ = access_default_virtual_node; }
| base_class_access_list VISSPEC see_typename
- { int err = 0;
- if ($2 == access_protected)
- {
- warning ("`protected' access not implemented");
- $2 = access_public;
- err++;
- }
- else if ($2 == access_public)
- {
- if ($1 == access_private)
- {
- mixed:
- error ("base class cannot be public and private");
- }
- else if ($1 == access_default_virtual)
- $$ = access_public_virtual;
- }
- else /* $2 == access_private */
- {
- if ($1 == access_public)
- goto mixed;
- else if ($1 == access_default_virtual)
- $$ = access_private_virtual;
- }
+ {
+ if ($1 != access_default_virtual_node)
+ error ("multiple access specifiers");
+ else if ($2 == access_public_node)
+ $$ = access_public_virtual_node;
+ else if ($2 == access_protected_node)
+ $$ = access_protected_virtual_node;
+ else /* $2 == access_private_node */
+ $$ = access_private_virtual_node;
}
| base_class_access_list SCSPEC see_typename
{ if ($2 != ridpointers[(int)RID_VIRTUAL])
- sorry ("non-virtual access");
- if ($$ == access_public)
- $$ = access_public_virtual;
- else if ($$ == access_private)
- $$ = access_private_virtual; }
+ cp_error ("`%D' access", $2);
+ else if ($$ == access_public_node)
+ $$ = access_public_virtual_node;
+ else if ($$ == access_protected_node)
+ $$ = access_protected_virtual_node;
+ else if ($$ == access_private_node)
+ $$ = access_private_virtual_node;
+ else
+ error ("multiple `virtual' specifiers");
+ }
;
-left_curly: '{'
- { tree t = $<ttype>0;
- push_obstacks_nochange ();
- end_temporary_allocation ();
-
- if (! IS_AGGR_TYPE (t))
- {
- t = $<ttype>0 = make_lang_type (RECORD_TYPE);
- TYPE_NAME (t) = get_identifier ("erroneous type");
- }
- if (TYPE_SIZE (t))
- duplicate_tag_error (t);
- if (TYPE_SIZE (t) || TYPE_BEING_DEFINED (t))
- {
- t = make_lang_type (TREE_CODE (t));
- pushtag (TYPE_IDENTIFIER ($<ttype>0), t, 0);
- $<ttype>0 = t;
- }
- pushclass (t, 0);
- TYPE_BEING_DEFINED (t) = 1;
- /* Reset the interface data, at the earliest possible
- moment, as it might have been set via a class foo;
- before. */
- /* Don't change signatures. */
- if (! IS_SIGNATURE (t))
- {
- extern tree pending_vtables;
- int needs_writing;
- tree name = TYPE_IDENTIFIER (t);
-
- if (! ANON_AGGRNAME_P (name))
- {
- CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- SET_CLASSTYPE_INTERFACE_UNKNOWN_X
- (t, interface_unknown);
- }
+left_curly:
+ '{'
+ { $<ttype>0 = begin_class_definition ($<ttype>0); }
+ ;
- /* Record how to set the access of this class's
- virtual functions. If write_virtuals == 2 or 3, then
- inline virtuals are ``extern inline''. */
- switch (write_virtuals)
- {
- case 0:
- case 1:
- needs_writing = 1;
- break;
- case 2:
- needs_writing = !! value_member (name, pending_vtables);
- break;
- case 3:
- needs_writing = ! CLASSTYPE_INTERFACE_ONLY (t)
- && CLASSTYPE_INTERFACE_KNOWN (t);
- break;
- default:
- needs_writing = 0;
- }
- CLASSTYPE_VTABLE_NEEDS_WRITING (t) = needs_writing;
- }
-#if 0
- t = TYPE_IDENTIFIER ($<ttype>0);
- if (t && IDENTIFIER_TEMPLATE (t))
- overload_template_name (t, 1);
-#endif
+self_reference:
+ /* empty */
+ {
+ $$ = build_self_reference ();
}
;
opt.component_decl_list:
- /* empty */
- { $$ = NULL_TREE; }
- | component_decl_list
+ self_reference
+ { if ($$) $$ = build_tree_list (access_public_node, $$); }
+ | self_reference component_decl_list
{
if (current_aggr == signature_type_node)
- $$ = build_tree_list ((tree) access_public, $$);
+ $$ = build_tree_list (access_public_node, $2);
else
- $$ = build_tree_list ((tree) access_default, $$);
+ $$ = build_tree_list (access_default_node, $2);
+ if ($1) $$ = tree_cons (access_public_node, $1, $$);
}
| opt.component_decl_list VISSPEC ':' component_decl_list
{
- tree visspec = (tree) $2;
+ tree visspec = $2;
if (current_aggr == signature_type_node)
{
error ("access specifier not allowed in signature");
- visspec = (tree) access_public;
+ visspec = access_public_node;
}
$$ = chainon ($$, build_tree_list (visspec, $4));
}
@@ -2637,6 +2464,13 @@ component_decl:
{ $$ = finish_method ($$); }
| ';'
{ $$ = NULL_TREE; }
+ | extension component_decl
+ { $$ = $2;
+ pedantic = $<itype>1; }
+ | template_header component_decl
+ { $$ = finish_member_template_decl ($1, $2); }
+ | template_header typed_declspecs ';'
+ { $$ = finish_member_class_template ($1, $2.t); }
;
component_decl_1:
@@ -2644,12 +2478,15 @@ 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 ($1, $2); }
+ { $$ = grok_x_components ($1.t, $2); }
| declmods notype_components
{ $$ = grok_x_components ($1, $2); }
- | notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
- { $$ = grokfield ($$, NULL_TREE, $2, $5, $3,
- build_tree_list ($4, NULL_TREE)); }
+ | notype_declarator maybeasm maybe_attribute maybe_init
+ { $$ = grokfield ($$, NULL_TREE, $4, $2,
+ build_tree_list ($3, NULL_TREE)); }
+ | constructor_declarator maybeasm maybe_attribute maybe_init
+ { $$ = grokfield ($$, NULL_TREE, $4, $2,
+ build_tree_list ($3, NULL_TREE)); }
| ':' expr_no_commas
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
| error
@@ -2663,25 +2500,18 @@ component_decl_1:
should "A::foo" be declared as a function or "A::bar" as a data
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
- { tree specs, attrs;
- split_specs_attrs ($1, &specs, &attrs);
- $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
- $3, $5);
- $$ = 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
+ | declmods component_constructor_declarator maybeasm maybe_attribute maybe_init
{ tree specs, attrs;
split_specs_attrs ($1, &specs, &attrs);
- $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
- empty_parms (), $3);
- $$ = grokfield ($$, TREE_CHAIN (specs), $4, $7, $5,
- build_tree_list ($6, attrs)); }
+ $$ = grokfield ($2, specs, $5, $3,
+ build_tree_list ($4, attrs)); }
+ | component_constructor_declarator maybeasm maybe_attribute maybe_init
+ { $$ = grokfield ($$, NULL_TREE, $4, $2,
+ build_tree_list ($3, NULL_TREE)); }
| using_decl
{ $$ = do_class_using_decl ($1); }
- ;
-/* The case of exactly one component is handled directly by component_decl. */
+/* The case of exactly one component is handled directly by component_decl. */
/* ??? Huh? ^^^ */
components:
/* empty: possibly anonymous */
@@ -2724,12 +2554,12 @@ component_declarator:
;
after_type_component_declarator0:
- after_type_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
+ after_type_declarator maybeasm maybe_attribute maybe_init
{ 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)); }
+ $$ = grokfield ($$, current_declspecs, $4, $2,
+ build_tree_list ($3, prefix_attributes)); }
| TYPENAME ':' expr_no_commas maybe_attribute
{ split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
@@ -2739,12 +2569,18 @@ after_type_component_declarator0:
;
notype_component_declarator0:
- notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
+ notype_declarator maybeasm maybe_attribute maybe_init
+ { split_specs_attrs ($<ttype>0, &current_declspecs,
+ &prefix_attributes);
+ $<ttype>0 = current_declspecs;
+ $$ = grokfield ($$, current_declspecs, $4, $2,
+ build_tree_list ($3, prefix_attributes)); }
+ | constructor_declarator maybeasm maybe_attribute maybe_init
{ 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)); }
+ $$ = grokfield ($$, current_declspecs, $4, $2,
+ build_tree_list ($3, prefix_attributes)); }
| IDENTIFIER ':' expr_no_commas maybe_attribute
{ split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
@@ -2760,18 +2596,18 @@ notype_component_declarator0:
;
after_type_component_declarator:
- after_type_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
- { $$ = grokfield ($$, current_declspecs, $2, $5, $3,
- build_tree_list ($4, prefix_attributes)); }
+ after_type_declarator maybeasm maybe_attribute maybe_init
+ { $$ = grokfield ($$, current_declspecs, $4, $2,
+ build_tree_list ($3, prefix_attributes)); }
| TYPENAME ':' expr_no_commas maybe_attribute
{ $$ = grokbitfield ($$, current_declspecs, $3);
cplus_decl_attributes ($$, $4, prefix_attributes); }
;
notype_component_declarator:
- notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
- { $$ = grokfield ($$, current_declspecs, $2, $5, $3,
- build_tree_list ($4, prefix_attributes)); }
+ notype_declarator maybeasm maybe_attribute maybe_init
+ { $$ = grokfield ($$, current_declspecs, $4, $2,
+ build_tree_list ($3, prefix_attributes)); }
| IDENTIFIER ':' expr_no_commas maybe_attribute
{ $$ = grokbitfield ($$, current_declspecs, $3);
cplus_decl_attributes ($$, $4, prefix_attributes); }
@@ -2800,44 +2636,52 @@ enumerator:
/* ANSI new-type-id (5.3.4) */
new_type_id:
type_specifier_seq new_declarator
- { $$ = build_decl_list ($$, $2); }
- | type_specifier_seq %prec EMPTY
- { $$ = build_decl_list ($$, NULL_TREE); }
+ { $$.t = build_decl_list ($1.t, $2);
+ $$.new_type_flag = $1.new_type_flag; }
+ | type_specifier_seq %prec EMPTY
+ { $$.t = build_decl_list ($1.t, NULL_TREE);
+ $$.new_type_flag = $1.new_type_flag; }
/* GNU extension to allow arrays of arbitrary types with
- non-constant dimension. */
- | '(' type_id ')' '[' expr ']'
+ non-constant dimension. For the use of begin_new_placement
+ here, see the comments in unary_expr above. */
+ | '(' .begin_new_placement type_id .finish_new_placement
+ '[' expr ']'
{
if (pedantic)
pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new");
- $$ = build_parse_node (ARRAY_REF, TREE_VALUE ($2), $5);
- $$ = build_decl_list (TREE_PURPOSE ($2), $$);
+ $$.t = build_parse_node (ARRAY_REF, TREE_VALUE ($3.t), $6);
+ $$.t = build_decl_list (TREE_PURPOSE ($3.t), $$.t);
+ $$.new_type_flag = $3.new_type_flag;
}
;
-type_quals:
- /* empty */ %prec EMPTY
+cv_qualifiers:
+ /* empty */ %prec EMPTY
{ $$ = NULL_TREE; }
- | type_quals TYPE_QUAL
+ | cv_qualifiers CV_QUALIFIER
{ $$ = decl_tree_cons (NULL_TREE, $2, $$); }
;
-nonempty_type_quals:
- TYPE_QUAL
- { $$ = IDENTIFIER_AS_LIST ($$); }
- | nonempty_type_quals TYPE_QUAL
- { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
+nonempty_cv_qualifiers:
+ CV_QUALIFIER
+ { $$.t = IDENTIFIER_AS_LIST ($1);
+ $$.new_type_flag = 0; }
+ | nonempty_cv_qualifiers CV_QUALIFIER
+ { $$.t = decl_tree_cons (NULL_TREE, $2, $1.t);
+ $$.new_type_flag = $1.new_type_flag; }
;
/* These rules must follow the rules for function declarations
and component declarations. That way, longer rules are preferred. */
suspend_mom:
- { $<itype>$ = suspend_momentary (); }
+ /* empty */
+ { $<itype>$ = suspend_momentary (); }
/* An expression which will not live on the momentary obstack. */
nonmomentary_expr:
- suspend_mom expr
- { resume_momentary ((int) $<itype>1); $$ = $2; }
+ suspend_mom expr
+ { resume_momentary ((int) $<itype>1); $$ = $2; }
;
/* An expression which will not live on the momentary obstack. */
@@ -2855,72 +2699,90 @@ maybe_parmlist:
/* A declarator that is allowed only after an explicit typespec. */
/* may all be followed by prec '.' */
after_type_declarator:
- '*' nonempty_type_quals after_type_declarator %prec UNARY
- { $$ = make_pointer_declarator ($2, $3); }
- | '&' nonempty_type_quals after_type_declarator %prec UNARY
- { $$ = make_reference_declarator ($2, $3); }
+ '*' nonempty_cv_qualifiers after_type_declarator %prec UNARY
+ { $$ = make_pointer_declarator ($2.t, $3); }
+ | '&' nonempty_cv_qualifiers after_type_declarator %prec UNARY
+ { $$ = make_reference_declarator ($2.t, $3); }
| '*' after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
| '&' after_type_declarator %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | ptr_to_mem type_quals after_type_declarator
+ | ptr_to_mem cv_qualifiers after_type_declarator
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
| direct_after_type_declarator
;
-qualified_type_name:
- type_name %prec EMPTY
+nonnested_type:
+ type_name %prec EMPTY
{
- /* Remember that this name has been used in the class
- definition, as per [class.scope0] */
- if (current_class_type
- && TYPE_BEING_DEFINED (current_class_type)
- && ! IDENTIFIER_CLASS_VALUE ($$))
+ if (TREE_CODE ($1) == IDENTIFIER_NODE)
{
- tree t = lookup_name ($$, -2);
- if (t)
- pushdecl_class_level (t);
+ $$ = lookup_name ($1, 1);
+ if (current_class_type
+ && TYPE_BEING_DEFINED (current_class_type)
+ && ! IDENTIFIER_CLASS_VALUE ($1))
+ {
+ /* Remember that this name has been used in the class
+ definition, as per [class.scope0] */
+ pushdecl_class_level ($$);
+ }
}
+ else
+ $$ = $1;
}
+ | global_scope type_name
+ {
+ if (TREE_CODE ($2) == IDENTIFIER_NODE)
+ $$ = IDENTIFIER_GLOBAL_VALUE ($2);
+ else
+ $$ = $2;
+ got_scope = NULL_TREE;
+ }
+ ;
+
+complete_type_name:
+ nonnested_type
| nested_type
+ | global_scope nested_type
+ { $$ = $2; }
;
nested_type:
- nested_name_specifier type_name %prec EMPTY
- { $$ = $2; }
+ nested_name_specifier type_name %prec EMPTY
+ { $$ = get_type_decl ($2); }
;
direct_after_type_declarator:
- direct_after_type_declarator maybe_parmlist type_quals %prec '.'
- { $$ = build_parse_node (CALL_EXPR, $$, $2, $3); }
+ direct_after_type_declarator maybe_parmlist cv_qualifiers exception_specification_opt %prec '.'
+ { $$ = make_call_declarator ($$, $2, $3, $4); }
| direct_after_type_declarator '[' nonmomentary_expr ']'
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
| direct_after_type_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
| '(' after_type_declarator ')'
{ $$ = $2; }
- | nested_name_specifier type_name %prec EMPTY
- { push_nested_class (TREE_TYPE ($$), 3);
+ | nested_name_specifier type_name %prec EMPTY
+ { push_nested_class ($1, 3);
$$ = build_parse_node (SCOPE_REF, $$, $2);
TREE_COMPLEXITY ($$) = current_class_depth; }
- | type_name %prec EMPTY
+ | type_name %prec EMPTY
;
/* A declarator allowed whether or not there has been
an explicit typespec. These cannot redeclare a typedef-name. */
notype_declarator:
- '*' nonempty_type_quals notype_declarator %prec UNARY
- { $$ = make_pointer_declarator ($2, $3); }
- | '&' nonempty_type_quals notype_declarator %prec UNARY
- { $$ = make_reference_declarator ($2, $3); }
+ '*' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ { $$ = make_pointer_declarator ($2.t, $3); }
+ | '&' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ { $$ = make_reference_declarator ($2.t, $3); }
| '*' notype_declarator %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
| '&' notype_declarator %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | ptr_to_mem type_quals notype_declarator
+ | ptr_to_mem cv_qualifiers notype_declarator
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
@@ -2928,15 +2790,15 @@ notype_declarator:
;
complex_notype_declarator:
- '*' nonempty_type_quals notype_declarator %prec UNARY
- { $$ = make_pointer_declarator ($2, $3); }
- | '&' nonempty_type_quals notype_declarator %prec UNARY
- { $$ = make_reference_declarator ($2, $3); }
+ '*' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ { $$ = make_pointer_declarator ($2.t, $3); }
+ | '&' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ { $$ = make_reference_declarator ($2.t, $3); }
| '*' complex_notype_declarator %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
| '&' complex_notype_declarator %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | ptr_to_mem type_quals notype_declarator
+ | ptr_to_mem cv_qualifiers notype_declarator
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
@@ -2944,8 +2806,8 @@ complex_notype_declarator:
;
complex_direct_notype_declarator:
- direct_notype_declarator maybe_parmlist type_quals %prec '.'
- { $$ = build_parse_node (CALL_EXPR, $$, $2, $3); }
+ direct_notype_declarator maybe_parmlist cv_qualifiers exception_specification_opt %prec '.'
+ { $$ = make_call_declarator ($$, $2, $3, $4); }
| '(' complex_notype_declarator ')'
{ $$ = $2; }
| direct_notype_declarator '[' nonmomentary_expr ']'
@@ -2953,24 +2815,44 @@ complex_direct_notype_declarator:
| direct_notype_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
| notype_qualified_id
- { if (TREE_TYPE (OP0 ($$)) != current_class_type)
+ { if (TREE_CODE (OP0 ($1)) == NAMESPACE_DECL)
+ {
+ push_decl_namespace (OP0 ($1));
+ TREE_COMPLEXITY ($1) = -1;
+ }
+ else if (OP0 ($1) != current_class_type)
+ {
+ push_nested_class (OP0 ($1), 3);
+ TREE_COMPLEXITY ($1) = current_class_depth;
+ }
+ }
+ | nested_name_specifier notype_template_declarator
+ { got_scope = NULL_TREE;
+ $$ = build_parse_node (SCOPE_REF, $1, $2);
+ if ($1 != current_class_type)
{
- push_nested_class (TREE_TYPE (OP0 ($$)), 3);
+ push_nested_class ($1, 3);
TREE_COMPLEXITY ($$) = current_class_depth;
}
}
;
qualified_id:
- nested_name_specifier unqualified_id
+ nested_name_specifier unqualified_id
{ got_scope = NULL_TREE;
$$ = build_parse_node (SCOPE_REF, $$, $2); }
+ | nested_name_specifier object_template_id
+ { got_scope = NULL_TREE;
+ $$ = build_parse_node (SCOPE_REF, $1, $2); }
;
notype_qualified_id:
- nested_name_specifier notype_unqualified_id
+ nested_name_specifier notype_unqualified_id
{ got_scope = NULL_TREE;
$$ = build_parse_node (SCOPE_REF, $$, $2); }
+ | nested_name_specifier object_template_id
+ { got_scope = NULL_TREE;
+ $$ = build_parse_node (SCOPE_REF, $1, $2); }
;
overqualified_id:
@@ -2981,33 +2863,58 @@ overqualified_id:
functional_cast:
typespec '(' nonnull_exprlist ')'
- { $$ = build_functional_cast ($$, $3); }
+ { $$ = build_functional_cast ($1.t, $3); }
| typespec '(' expr_or_declarator ')'
- { $$ = reparse_decl_as_expr ($$, $3); }
- | typespec fcast_or_absdcl %prec EMPTY
- { $$ = reparse_absdcl_as_expr ($$, $2); }
+ { $$ = reparse_decl_as_expr ($1.t, $3); }
+ | typespec fcast_or_absdcl %prec EMPTY
+ { $$ = reparse_absdcl_as_expr ($1.t, $2); }
;
type_name:
TYPENAME
- | template_type %prec EMPTY
+ | SELFNAME
+ | template_type %prec EMPTY
;
nested_name_specifier:
nested_name_specifier_1
| nested_name_specifier nested_name_specifier_1
{ $$ = $2; }
+ | nested_name_specifier TEMPLATE explicit_template_type SCOPE
+ { got_scope = $$ = make_typename_type ($1, $3); }
;
/* Why the @#$%^& do type_name and notype_identifier need to be expanded
inline here?!? (jason) */
nested_name_specifier_1:
TYPENAME SCOPE
- { got_scope = TREE_TYPE ($$); }
+ {
+ if (TREE_CODE ($1) == IDENTIFIER_NODE)
+ {
+ $$ = lastiddecl;
+ /* Remember that this name has been used in the class
+ definition, as per [class.scope0] */
+ if (current_class_type
+ && TYPE_BEING_DEFINED (current_class_type)
+ && ! IDENTIFIER_CLASS_VALUE ($1))
+ pushdecl_class_level ($$);
+ }
+ got_scope = $$ = TYPE_MAIN_VARIANT (TREE_TYPE ($$));
+ }
+ | SELFNAME SCOPE
+ {
+ if (TREE_CODE ($1) == IDENTIFIER_NODE)
+ $$ = lastiddecl;
+ got_scope = $$ = TREE_TYPE ($$);
+ }
| NSNAME SCOPE
- { got_scope = $$; }
+ {
+ if (TREE_CODE ($$) == IDENTIFIER_NODE)
+ $$ = lastiddecl;
+ got_scope = $$;
+ }
| template_type SCOPE
- { got_scope = TREE_TYPE ($$); }
+ { got_scope = $$ = complete_type (TREE_TYPE ($1)); }
/* These break 'const i;'
| IDENTIFIER SCOPE
{
@@ -3020,15 +2927,106 @@ nested_name_specifier_1:
{ goto failed_scope; } */
;
-complete_type_name:
- qualified_type_name
- | global_scope qualified_type_name
+typename_sub:
+ typename_sub0
+ | global_scope typename_sub0
{ $$ = $2; }
;
+typename_sub0:
+ typename_sub1 identifier %prec EMPTY
+ {
+ if (TREE_CODE_CLASS (TREE_CODE ($1)) == 't')
+ $$ = make_typename_type ($1, $2);
+ else if (TREE_CODE ($2) == IDENTIFIER_NODE)
+ cp_error ("`%T' is not a class or namespace", $2);
+ else
+ {
+ $$ = $2;
+ if (TREE_CODE ($$) == TYPE_DECL)
+ $$ = TREE_TYPE ($$);
+ }
+ }
+ | typename_sub1 template_type %prec EMPTY
+ { $$ = TREE_TYPE ($2); }
+ | typename_sub1 explicit_template_type %prec EMPTY
+ { $$ = make_typename_type ($1, $2); }
+ | typename_sub1 TEMPLATE explicit_template_type %prec EMPTY
+ { $$ = make_typename_type ($1, $3); }
+ ;
+
+typename_sub1:
+ typename_sub2
+ {
+ if (TREE_CODE ($1) == IDENTIFIER_NODE)
+ cp_error ("`%T' is not a class or namespace", $1);
+ }
+ | typename_sub1 typename_sub2
+ {
+ if (TREE_CODE_CLASS (TREE_CODE ($1)) == 't')
+ $$ = make_typename_type ($1, $2);
+ else if (TREE_CODE ($2) == IDENTIFIER_NODE)
+ cp_error ("`%T' is not a class or namespace", $2);
+ else
+ {
+ $$ = $2;
+ if (TREE_CODE ($$) == TYPE_DECL)
+ $$ = TREE_TYPE ($$);
+ }
+ }
+ | typename_sub1 explicit_template_type SCOPE
+ { got_scope = $$ = make_typename_type ($1, $2); }
+ | typename_sub1 TEMPLATE explicit_template_type SCOPE
+ { got_scope = $$ = make_typename_type ($1, $3); }
+ ;
+
+typename_sub2:
+ TYPENAME SCOPE
+ {
+ if (TREE_CODE ($1) != IDENTIFIER_NODE)
+ $1 = lastiddecl;
+
+ /* Retrieve the type for the identifier, which might involve
+ some computation. */
+ got_scope = $$ = complete_type (IDENTIFIER_TYPE_VALUE ($1));
+
+ if ($$ == error_mark_node)
+ cp_error ("`%T' is not a class or namespace", $1);
+ }
+ | SELFNAME SCOPE
+ {
+ if (TREE_CODE ($1) != IDENTIFIER_NODE)
+ $$ = lastiddecl;
+ got_scope = $$ = complete_type (TREE_TYPE ($$));
+ }
+ | template_type SCOPE
+ { got_scope = $$ = complete_type (TREE_TYPE ($$)); }
+ | PTYPENAME SCOPE
+ | IDENTIFIER SCOPE
+ | NSNAME SCOPE
+ {
+ if (TREE_CODE ($$) == IDENTIFIER_NODE)
+ $$ = lastiddecl;
+ got_scope = $$;
+ }
+ ;
+
+explicit_template_type:
+ identifier '<' template_arg_list_opt template_close_bracket
+ { $$ = build_min_nt (TEMPLATE_ID_EXPR, $1, $3); }
+ ;
+
complex_type_name:
- nested_type
- | global_scope qualified_type_name
+ global_scope type_name
+ {
+ if (TREE_CODE ($2) == IDENTIFIER_NODE)
+ $$ = IDENTIFIER_GLOBAL_VALUE ($2);
+ else
+ $$ = $2;
+ got_scope = NULL_TREE;
+ }
+ | nested_type
+ | global_scope nested_type
{ $$ = $2; }
;
@@ -3040,7 +3038,7 @@ ptr_to_mem:
;
/* All uses of explicit global scope must go through this nonterminal so
- that got_scope will be set before yylex is called to get the next token. */
+ that got_scope will be set before yylex is called to get the next token. */
global_scope:
SCOPE
{ got_scope = void_type_node; }
@@ -3048,23 +3046,23 @@ global_scope:
/* ANSI new-declarator (5.3.4) */
new_declarator:
- '*' type_quals new_declarator
+ '*' cv_qualifiers new_declarator
{ $$ = make_pointer_declarator ($2, $3); }
- | '*' type_quals %prec EMPTY
+ | '*' cv_qualifiers %prec EMPTY
{ $$ = make_pointer_declarator ($2, NULL_TREE); }
- | '&' type_quals new_declarator %prec EMPTY
+ | '&' cv_qualifiers new_declarator %prec EMPTY
{ $$ = make_reference_declarator ($2, $3); }
- | '&' type_quals %prec EMPTY
+ | '&' cv_qualifiers %prec EMPTY
{ $$ = make_reference_declarator ($2, NULL_TREE); }
- | ptr_to_mem type_quals %prec EMPTY
+ | ptr_to_mem cv_qualifiers %prec EMPTY
{ tree arg = make_pointer_declarator ($2, NULL_TREE);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
- | ptr_to_mem type_quals new_declarator
+ | ptr_to_mem cv_qualifiers new_declarator
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
- | direct_new_declarator %prec EMPTY
+ | direct_new_declarator %prec EMPTY
;
/* ANSI direct-new-declarator (5.3.4) */
@@ -3077,31 +3075,31 @@ direct_new_declarator:
/* ANSI abstract-declarator (8.1) */
absdcl:
- '*' nonempty_type_quals absdcl
- { $$ = make_pointer_declarator ($2, $3); }
+ '*' nonempty_cv_qualifiers absdcl
+ { $$ = make_pointer_declarator ($2.t, $3); }
| '*' absdcl
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
- | '*' nonempty_type_quals %prec EMPTY
- { $$ = make_pointer_declarator ($2, NULL_TREE); }
- | '*' %prec EMPTY
+ | '*' nonempty_cv_qualifiers %prec EMPTY
+ { $$ = make_pointer_declarator ($2.t, NULL_TREE); }
+ | '*' %prec EMPTY
{ $$ = make_pointer_declarator (NULL_TREE, NULL_TREE); }
- | '&' nonempty_type_quals absdcl
- { $$ = make_reference_declarator ($2, $3); }
+ | '&' nonempty_cv_qualifiers absdcl
+ { $$ = make_reference_declarator ($2.t, $3); }
| '&' absdcl
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | '&' nonempty_type_quals %prec EMPTY
- { $$ = make_reference_declarator ($2, NULL_TREE); }
- | '&' %prec EMPTY
+ | '&' nonempty_cv_qualifiers %prec EMPTY
+ { $$ = make_reference_declarator ($2.t, NULL_TREE); }
+ | '&' %prec EMPTY
{ $$ = make_reference_declarator (NULL_TREE, NULL_TREE); }
- | ptr_to_mem type_quals %prec EMPTY
+ | ptr_to_mem cv_qualifiers %prec EMPTY
{ tree arg = make_pointer_declarator ($2, NULL_TREE);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
- | ptr_to_mem type_quals absdcl
+ | ptr_to_mem cv_qualifiers absdcl
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
- | direct_abstract_declarator %prec EMPTY
+ | direct_abstract_declarator %prec EMPTY
;
/* ANSI direct-abstract-declarator (8.1) */
@@ -3110,20 +3108,20 @@ direct_abstract_declarator:
{ $$ = $2; }
/* `(typedef)1' is `int'. */
| PAREN_STAR_PAREN
- | direct_abstract_declarator '(' parmlist ')' type_quals %prec '.'
- { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
- | direct_abstract_declarator LEFT_RIGHT type_quals %prec '.'
- { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $3); }
+ | direct_abstract_declarator '(' parmlist ')' cv_qualifiers exception_specification_opt %prec '.'
+ { $$ = make_call_declarator ($$, $3, $5, $6); }
+ | direct_abstract_declarator LEFT_RIGHT cv_qualifiers exception_specification_opt %prec '.'
+ { $$ = make_call_declarator ($$, empty_parms (), $3, $4); }
| direct_abstract_declarator '[' nonmomentary_expr ']' %prec '.'
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
| direct_abstract_declarator '[' ']' %prec '.'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
- | '(' complex_parmlist ')' type_quals %prec '.'
- { $$ = build_parse_node (CALL_EXPR, NULL_TREE, $2, $4); }
- | regcast_or_absdcl type_quals %prec '.'
- { TREE_OPERAND ($$, 2) = $2; }
- | fcast_or_absdcl type_quals %prec '.'
- { TREE_OPERAND ($$, 2) = $2; }
+ | '(' complex_parmlist ')' cv_qualifiers exception_specification_opt %prec '.'
+ { $$ = make_call_declarator (NULL_TREE, $2, $4, $5); }
+ | regcast_or_absdcl cv_qualifiers exception_specification_opt %prec '.'
+ { set_quals_and_spec ($$, $2, $3); }
+ | fcast_or_absdcl cv_qualifiers exception_specification_opt %prec '.'
+ { set_quals_and_spec ($$, $2, $3); }
| '[' nonmomentary_expr ']' %prec '.'
{ $$ = build_parse_node (ARRAY_REF, NULL_TREE, $2); }
| '[' ']' %prec '.'
@@ -3141,25 +3139,8 @@ stmts:
| stmts errstmt
;
-errstmt: error ';'
- ;
-
-/* build the LET_STMT node before parsing its contents,
- so that any LET_STMTs within the context can have their display pointers
- set up to point at this one. */
-
-.pushlevel: /* empty */
- { emit_line_note (input_filename, lineno);
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0); }
- ;
-
-.poplevel: /* empty */
- { expand_end_bindings (getdecls (), kept_level_p (), 1);
- $$ = poplevel (kept_level_p (), 1, 0);
- pop_momentary (); }
+errstmt:
+ error ';'
;
/* Read zero or more forward-declarations for labels
@@ -3196,29 +3177,35 @@ compstmt_or_error:
| error compstmt
;
-compstmt: '{' .pushlevel compstmtend .poplevel
- { $$ = $4; }
+compstmt:
+ '{'
+ { $<ttype>$ = begin_compound_stmt (0); }
+ compstmtend
+ { $$ = finish_compound_stmt (0, $<ttype>2); }
;
simple_if:
IF
- { cond_stmt_keyword = "if"; }
- .pushlevel paren_cond_or_null
- { emit_line_note (input_filename, lineno);
- expand_start_cond ($4, 0); }
- implicitly_scoped_stmt
+ {
+ $<ttype>$ = begin_if_stmt ();
+ cond_stmt_keyword = "if";
+ }
+ paren_cond_or_null
+ { finish_if_stmt_cond ($3, $<ttype>2); }
+ implicitly_scoped_stmt
+ { $<ttype>$ = finish_then_clause ($<ttype>2); }
;
implicitly_scoped_stmt:
compstmt
- { finish_stmt (); }
- | .pushlevel simple_stmt .poplevel
- { $$ = $3; }
+ | { $<ttype>$ = begin_compound_stmt (0); }
+ simple_stmt
+ { $$ = finish_compound_stmt (0, $<ttype>1); }
;
stmt:
compstmt
- { finish_stmt (); }
+ {}
| simple_stmt
;
@@ -3226,234 +3213,93 @@ simple_stmt:
decl
{ finish_stmt (); }
| expr ';'
- {
- tree expr = $1;
- emit_line_note (input_filename, lineno);
- /* Do default conversion if safe and possibly important,
- in case within ({...}). */
- if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
- && lvalue_p (expr))
- || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
- expr = default_conversion (expr);
- cplus_expand_expr_stmt (expr);
- clear_momentary ();
- finish_stmt (); }
+ { finish_expr_stmt ($1); }
| simple_if ELSE
- { expand_start_else (); }
+ { begin_else_clause (); }
implicitly_scoped_stmt
- { expand_end_cond (); }
- .poplevel
- { finish_stmt (); }
- | simple_if %prec IF
- { expand_end_cond ();
- expand_end_bindings (getdecls (), kept_level_p (), 1);
- poplevel (kept_level_p (), 1, 0);
- pop_momentary ();
- finish_stmt (); }
+ {
+ finish_else_clause ($<ttype>1);
+ finish_if_stmt ();
+ }
+ | simple_if %prec IF
+ { finish_if_stmt (); }
| WHILE
- { emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop (1);
- cond_stmt_keyword = "while"; }
- .pushlevel paren_cond_or_null
- { expand_exit_loop_if_false (0, $4); }
- already_scoped_stmt .poplevel
- { expand_end_loop ();
- finish_stmt (); }
+ {
+ $<ttype>$ = begin_while_stmt ();
+ cond_stmt_keyword = "while";
+ }
+ paren_cond_or_null
+ { finish_while_stmt_cond ($3, $<ttype>2); }
+ already_scoped_stmt
+ { finish_while_stmt ($<ttype>2); }
| DO
- { emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop_continue_elsewhere (1); }
+ { $<ttype>$ = begin_do_stmt (); }
implicitly_scoped_stmt WHILE
- { expand_loop_continue_here ();
- cond_stmt_keyword = "do"; }
+ {
+ finish_do_body ($<ttype>2);
+ cond_stmt_keyword = "do";
+ }
paren_expr_or_null ';'
- { emit_line_note (input_filename, lineno);
- expand_exit_loop_if_false (0, $6);
- expand_end_loop ();
- clear_momentary ();
- finish_stmt (); }
+ { finish_do_stmt ($6, $<ttype>2); }
| FOR
- { emit_line_note (input_filename, lineno);
- if (flag_new_for_scope > 0)
- {
- /* Conditionalize .pushlevel */
- pushlevel (0);
- note_level_for_for ();
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
- }
- }
+ { $<ttype>$ = begin_for_stmt (); }
'(' for.init.statement
- { emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop_continue_elsewhere (1); }
- .pushlevel xcond ';'
- { emit_line_note (input_filename, lineno);
- if ($7) expand_exit_loop_if_false (0, $7); }
+ { finish_for_init_stmt ($<ttype>2); }
+ xcond ';'
+ { finish_for_cond ($6, $<ttype>2); }
xexpr ')'
- /* Don't let the tree nodes for $10 be discarded
- by clear_momentary during the parsing of the next stmt. */
- { push_momentary (); }
- already_scoped_stmt .poplevel
- { emit_line_note (input_filename, lineno);
- expand_loop_continue_here ();
- if ($10) cplus_expand_expr_stmt ($10);
- pop_momentary ();
- expand_end_loop ();
- if (flag_new_for_scope > 0)
- {
- expand_end_bindings (getdecls (), kept_level_p (), 1);
- poplevel (kept_level_p (), 1, 0);
- pop_momentary ();
- }
- finish_stmt (); }
- | SWITCH .pushlevel '(' condition ')'
- { emit_line_note (input_filename, lineno);
- c_expand_start_case ($4);
- push_switch ();
- /* Don't let the tree nodes for $4 be discarded by
- clear_momentary during the parsing of the next stmt. */
- push_momentary (); }
+ { finish_for_expr ($9, $<ttype>2); }
+ already_scoped_stmt
+ { finish_for_stmt ($9, $<ttype>2); }
+ | SWITCH
+ { begin_switch_stmt (); }
+ '(' condition ')'
+ { $<ttype>$ = finish_switch_cond ($4); }
implicitly_scoped_stmt
- { expand_end_case ($4);
- pop_momentary ();
- pop_switch (); }
- .poplevel
- { finish_stmt (); }
+ { finish_switch_stmt ($4, $<ttype>6); }
| CASE expr_no_commas ':'
- { register tree value = check_cp_case_value ($2);
- register tree label
- = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- if (value != error_mark_node)
- {
- tree duplicate;
- int success = pushcase (value, convert_and_check,
- label, &duplicate);
- if (success == 1)
- cp_error ("case label `%E' not within a switch statement", $2);
- else if (success == 2)
- {
- cp_error ("duplicate case value `%E'", $2);
- cp_error_at ("previously used here", duplicate);
- }
- else if (success == 3)
- warning ("case value out of range");
- else if (success == 5)
- cp_error ("case label `%E' within scope of cleanup or variable array", $2);
- }
- define_case_label (label);
- }
+ { finish_case_label ($2, NULL_TREE); }
stmt
| CASE expr_no_commas ELLIPSIS expr_no_commas ':'
- { register tree value1 = check_cp_case_value ($2);
- register tree value2 = check_cp_case_value ($4);
- register tree label
- = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- if (pedantic)
- pedwarn ("ANSI C++ forbids range expressions in switch statement");
- if (value1 != error_mark_node
- && value2 != error_mark_node)
- {
- tree duplicate;
- int success = pushcase_range (value1, value2,
- convert_and_check, label,
- &duplicate);
- if (success == 1)
- error ("case label not within a switch statement");
- else if (success == 2)
- {
- error ("duplicate (or overlapping) case value");
- error_with_decl (duplicate, "this is the first entry overlapping that value");
- }
- else if (success == 3)
- warning ("case value out of range");
- else if (success == 4)
- warning ("empty range specified");
- else if (success == 5)
- error ("case label within scope of cleanup or variable array");
- }
- define_case_label (label);
- }
+ { finish_case_label ($2, $4); }
stmt
| DEFAULT ':'
- {
- tree duplicate;
- register tree label
- = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- int success = pushcase (NULL_TREE, 0, label, &duplicate);
- if (success == 1)
- error ("default label not within a switch statement");
- else if (success == 2)
- {
- error ("multiple default labels in one switch");
- error_with_decl (duplicate, "this is the first default label");
- }
- define_case_label (NULL_TREE);
- }
+ { finish_case_label (NULL_TREE, NULL_TREE); }
stmt
| BREAK ';'
- { emit_line_note (input_filename, lineno);
- if ( ! expand_exit_something ())
- error ("break statement not within loop or switch"); }
+ { finish_break_stmt (); }
| CONTINUE ';'
- { emit_line_note (input_filename, lineno);
- if (! expand_continue_loop (0))
- error ("continue statement not within a loop"); }
+ { finish_continue_stmt (); }
| RETURN ';'
- { emit_line_note (input_filename, lineno);
- c_expand_return (NULL_TREE); }
+ { finish_return_stmt (NULL_TREE); }
| RETURN expr ';'
- { emit_line_note (input_filename, lineno);
- c_expand_return ($2);
- finish_stmt ();
- }
- | asm_keyword maybe_type_qual '(' string ')' ';'
- { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
- emit_line_note (input_filename, lineno);
- expand_asm ($4);
- finish_stmt ();
+ { finish_return_stmt ($2); }
+ | asm_keyword maybe_cv_qualifier '(' string ')' ';'
+ {
+ finish_asm_stmt ($2, $4, NULL_TREE, NULL_TREE,
+ NULL_TREE);
}
/* This is the case with just output operands. */
- | asm_keyword maybe_type_qual '(' string ':' asm_operands ')' ';'
- { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
- emit_line_note (input_filename, lineno);
- c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE,
- $2 == ridpointers[(int)RID_VOLATILE],
- input_filename, lineno);
- finish_stmt ();
+ | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ')' ';'
+ {
+ finish_asm_stmt ($2, $4, $6, NULL_TREE,
+ NULL_TREE);
}
/* This is the case with input operands as well. */
- | asm_keyword maybe_type_qual '(' string ':' asm_operands ':' asm_operands ')' ';'
- { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
- emit_line_note (input_filename, lineno);
- c_expand_asm_operands ($4, $6, $8, NULL_TREE,
- $2 == ridpointers[(int)RID_VOLATILE],
- input_filename, lineno);
- finish_stmt ();
- }
+ | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':' asm_operands ')' ';'
+ { finish_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
/* This is the case with clobbered registers as well. */
- | asm_keyword maybe_type_qual '(' string ':' asm_operands ':'
+ | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':'
asm_operands ':' asm_clobbers ')' ';'
- { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
- emit_line_note (input_filename, lineno);
- c_expand_asm_operands ($4, $6, $8, $10,
- $2 == ridpointers[(int)RID_VOLATILE],
- input_filename, lineno);
- finish_stmt ();
- }
+ { finish_asm_stmt ($2, $4, $6, $8, $10); }
| GOTO '*' expr ';'
- { emit_line_note (input_filename, lineno);
- expand_computed_goto ($3); }
+ {
+ if (pedantic)
+ pedwarn ("ANSI C++ forbids computed gotos");
+ finish_goto_stmt ($3);
+ }
| GOTO identifier ';'
- { tree decl;
- emit_line_note (input_filename, lineno);
- decl = lookup_label ($2);
- TREE_USED (decl) = 1;
- expand_goto (decl); }
+ { finish_goto_stmt ($2); }
| label_colon stmt
{ finish_stmt (); }
| label_colon '}'
@@ -3463,6 +3309,10 @@ simple_stmt:
| ';'
{ finish_stmt (); }
| try_block
+ | using_directive
+ | namespace_using_decl
+ { do_local_using_decl ($1); }
+ | namespace_alias
;
function_try_block:
@@ -3472,40 +3322,45 @@ function_try_block:
store_parm_decls ();
expand_start_early_try_stmts ();
}
- ctor_initializer_opt compstmt_or_error
- { expand_end_try_stmts ();
- expand_start_all_catch (); }
+ ctor_initializer_opt compstmt
+ {
+ expand_start_all_catch ();
+ }
handler_seq
{
+ int nested = (hack_decl_function_context
+ (current_function_decl) != NULL_TREE);
expand_end_all_catch ();
- finish_function (lineno, (int)$3, 0);
+ finish_function (lineno, (int)$3, nested);
}
;
try_block:
TRY
- { expand_start_try_stmts (); }
+ { $<ttype>$ = begin_try_block (); }
compstmt
- { expand_end_try_stmts ();
- expand_start_all_catch (); }
+ { finish_try_block ($<ttype>2); }
handler_seq
- { expand_end_all_catch (); }
+ { finish_handler_sequence ($<ttype>2); }
;
handler_seq:
- /* empty */
- | handler_seq CATCH .pushlevel
- { dont_allow_type_definitions = "inside exception declarations"; }
- handler_args
- { dont_allow_type_definitions = 0; }
+ handler
+ | handler_seq handler
+ ;
+
+handler:
+ CATCH
+ { $<ttype>$ = begin_handler(); }
+ handler_args
+ { finish_handler_parms ($<ttype>2); }
compstmt
- { expand_end_catch_block (); }
- .poplevel
+ { finish_handler ($<ttype>2); }
;
type_specifier_seq:
- typed_typespecs %prec EMPTY
- | nonempty_type_quals %prec EMPTY
+ typed_typespecs %prec EMPTY
+ | nonempty_cv_qualifiers %prec EMPTY
;
handler_args:
@@ -3513,17 +3368,22 @@ handler_args:
{ expand_start_catch_block (NULL_TREE, NULL_TREE); }
/* This doesn't allow reference parameters, the below does.
| '(' type_specifier_seq absdcl ')'
- { expand_start_catch_block ($2, $3); }
+ { check_for_new_type ("inside exception declarations", $2);
+ expand_start_catch_block ($2.t, $3); }
| '(' type_specifier_seq ')'
- { expand_start_catch_block ($2, NULL_TREE); }
+ { check_for_new_type ("inside exception declarations", $2);
+ expand_start_catch_block ($2.t, NULL_TREE); }
| '(' type_specifier_seq notype_declarator ')'
- { expand_start_catch_block ($2, $3); }
+ { check_for_new_type ("inside exception declarations", $2);
+ expand_start_catch_block ($2.t, $3); }
| '(' typed_typespecs after_type_declarator ')'
- { expand_start_catch_block ($2, $3); }
- This allows reference parameters... */
+ { check_for_new_type ("inside exception declarations", $2);
+ expand_start_catch_block ($2.t, $3); }
+ This allows reference parameters... */
| '(' parm ')'
- { expand_start_catch_block (TREE_PURPOSE ($2),
- TREE_VALUE ($2)); }
+ { check_for_new_type ("inside exception declarations", $2);
+ expand_start_catch_block (TREE_PURPOSE ($2.t),
+ TREE_VALUE ($2.t)); }
;
label_colon:
@@ -3531,13 +3391,15 @@ label_colon:
{ tree label;
do_label:
label = define_label (input_filename, lineno, $1);
- if (label)
+ if (label && ! minimal_parse_mode)
expand_label (label);
}
| PTYPENAME ':'
{ goto do_label; }
| TYPENAME ':'
{ goto do_label; }
+ | SELFNAME ':'
+ { goto do_label; }
;
for.init.statement:
@@ -3545,20 +3407,23 @@ for.init.statement:
{ if ($1) cplus_expand_expr_stmt ($1); }
| decl
| '{' compstmtend
+ { if (pedantic)
+ pedwarn ("ANSI C++ forbids compound statements inside for initializations");
+ }
;
/* Either a type-qualifier or nothing. First thing in an `asm' statement. */
-maybe_type_qual:
- /* empty */
+maybe_cv_qualifier:
+ /* empty */
{ emit_line_note (input_filename, lineno);
$$ = NULL_TREE; }
- | TYPE_QUAL
+ | CV_QUALIFIER
{ emit_line_note (input_filename, lineno); }
;
xexpr:
- /* empty */
+ /* empty */
{ $$ = NULL_TREE; }
| expr
| error
@@ -3567,7 +3432,8 @@ xexpr:
/* These are the operands other than the first string and colon
in asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x)) */
-asm_operands: /* empty */
+asm_operands:
+ /* empty */
{ $$ = NULL_TREE; }
| nonnull_asm_operands
;
@@ -3596,69 +3462,39 @@ asm_clobbers:
In C++, declaring a function with no parameters
means that that function takes *no* parameters. */
-parmlist: /* empty */
+parmlist:
+ /* empty */
{
- if (strict_prototype)
- $$ = void_list_node;
- else
- $$ = NULL_TREE;
+ $$ = empty_parms();
}
| complex_parmlist
| type_id
- { $$ = tree_cons (NULL_TREE, $$, void_list_node);
- TREE_PARMLIST ($$) = 1; }
+ { $$ = finish_parmlist (build_tree_list (NULL_TREE, $1.t), 0);
+ check_for_new_type ("inside parameter list", $1); }
;
/* This nonterminal does not include the common sequence '(' type_id ')',
as it is ambiguous and must be disambiguated elsewhere. */
complex_parmlist:
parms
- {
- $$ = chainon ($$, void_list_node);
- TREE_PARMLIST ($$) = 1;
- }
+ { $$ = finish_parmlist ($$, 0); }
| parms_comma ELLIPSIS
- {
- TREE_PARMLIST ($$) = 1;
- }
+ { $$ = finish_parmlist ($1, 1); }
/* C++ allows an ellipsis without a separating ',' */
| parms ELLIPSIS
- {
- TREE_PARMLIST ($$) = 1;
- }
+ { $$ = finish_parmlist ($1, 1); }
| type_id ELLIPSIS
- {
- $$ = build_tree_list (NULL_TREE, $$);
- TREE_PARMLIST ($$) = 1;
- }
+ { $$ = finish_parmlist (build_tree_list (NULL_TREE,
+ $1.t), 1); }
| ELLIPSIS
- {
- /* ARM $8.2.5 has this as a boxed-off comment. */
- if (pedantic)
- warning ("use of `...' without a first argument is non-portable");
- $$ = NULL_TREE;
- }
- | TYPENAME_ELLIPSIS
- {
- TREE_PARMLIST ($$) = 1;
- }
- | parms TYPENAME_ELLIPSIS
- {
- TREE_PARMLIST ($$) = 1;
- }
- | type_id TYPENAME_ELLIPSIS
- {
- $$ = build_tree_list (NULL_TREE, $$);
- TREE_PARMLIST ($$) = 1;
- }
+ { $$ = finish_parmlist (NULL_TREE, 1); }
| parms ':'
{
/* This helps us recover from really nasty
parse errors, for example, a missing right
parenthesis. */
yyerror ("possibly missing ')'");
- $$ = chainon ($$, void_list_node);
- TREE_PARMLIST ($$) = 1;
+ $$ = finish_parmlist ($1, 0);
yyungetc (':', 0);
yychar = ')';
}
@@ -3668,21 +3504,37 @@ complex_parmlist:
parse errors, for example, a missing right
parenthesis. */
yyerror ("possibly missing ')'");
- $$ = tree_cons (NULL_TREE, $$, void_list_node);
- TREE_PARMLIST ($$) = 1;
+ $$ = finish_parmlist (build_tree_list (NULL_TREE,
+ $1.t), 0);
yyungetc (':', 0);
yychar = ')';
}
;
+/* A default argument to a */
+defarg:
+ '='
+ { maybe_snarf_defarg (); }
+ defarg1
+ { $$ = $3; }
+ ;
+
+defarg1:
+ DEFARG
+ | init
+ ;
+
/* A nonempty list of parameter declarations or type names. */
parms:
named_parm
- { $$ = build_tree_list (NULL_TREE, $$); }
- | parm '=' init
- { $$ = build_tree_list ($3, $$); }
+ { check_for_new_type ("in a parameter list", $1);
+ $$ = build_tree_list (NULL_TREE, $1.t); }
+ | parm defarg
+ { check_for_new_type ("in a parameter list", $1);
+ $$ = build_tree_list ($2, $1.t); }
| parms_comma full_parm
- { $$ = chainon ($$, $2); }
+ { check_for_new_type ("in a parameter list", $2);
+ $$ = chainon ($$, $2.t); }
| parms_comma bad_parm
{ $$ = chainon ($$, build_tree_list (NULL_TREE, $2)); }
| parms_comma bad_parm '=' init
@@ -3692,80 +3544,58 @@ parms:
parms_comma:
parms ','
| type_id ','
- { $$ = build_tree_list (NULL_TREE, $$); }
+ { check_for_new_type ("in a parameter list", $1);
+ $$ = build_tree_list (NULL_TREE, $1.t); }
;
/* A single parameter declaration or parameter type name,
- as found in a parmlist. The first four cases make up for 10%
- of the time spent parsing C++. We cannot use them because
- of `int id[]' which won't get parsed properly. */
+ as found in a parmlist. */
named_parm:
-/*
- typed_declspecs dont_see_typename '*' IDENTIFIER
- { tree specs = strip_attrs ($1);
- $$ = build_tree_list (specs, build_parse_node (INDIRECT_REF, $4));
- see_typename (); }
- | typed_declspecs dont_see_typename '&' IDENTIFIER
- { 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); }
- | TYPESPEC IDENTIFIER
- { $$ = build_tree_list (get_decl_list ($$), $2); }
- | */
/* Here we expand typed_declspecs inline to avoid mis-parsing of
TYPESPEC IDENTIFIER. */
typed_declspecs1 declarator
- { tree specs = strip_attrs ($1);
- $$ = build_tree_list (specs, $2); }
+ { tree specs = strip_attrs ($1.t);
+ $$.new_type_flag = $1.new_type_flag;
+ $$.t = build_tree_list (specs, $2); }
| typed_typespecs declarator
- { $$ = build_tree_list ($$, $2); }
+ { $$.t = build_tree_list ($1.t, $2);
+ $$.new_type_flag = $1.new_type_flag; }
| typespec declarator
- { $$ = build_tree_list (get_decl_list ($$), $2); }
+ { $$.t = build_tree_list (get_decl_list ($1.t), $2);
+ $$.new_type_flag = $1.new_type_flag; }
| typed_declspecs1 absdcl
- { tree specs = strip_attrs ($1);
- $$ = build_tree_list (specs, $2); }
- | typed_declspecs1 %prec EMPTY
- { tree specs = strip_attrs ($1);
- $$ = build_tree_list (specs, NULL_TREE); }
+ { tree specs = strip_attrs ($1.t);
+ $$.t = build_tree_list (specs, $2);
+ $$.new_type_flag = $1.new_type_flag; }
+ | typed_declspecs1 %prec EMPTY
+ { tree specs = strip_attrs ($1.t);
+ $$.t = build_tree_list (specs, NULL_TREE);
+ $$.new_type_flag = $1.new_type_flag; }
| declmods notype_declarator
{ tree specs = strip_attrs ($1);
- $$ = build_tree_list (specs, $2); }
+ $$.t = build_tree_list (specs, $2);
+ $$.new_type_flag = 0; }
;
full_parm:
- parm maybe_init
- { $$ = build_tree_list ($2, $$); }
+ parm
+ { $$.t = build_tree_list (NULL_TREE, $1.t);
+ $$.new_type_flag = $1.new_type_flag; }
+ | parm defarg
+ { $$.t = build_tree_list ($2, $1.t);
+ $$.new_type_flag = $1.new_type_flag; }
;
parm:
- named_parm
+ named_parm
| type_id
;
-see_typename: %prec EMPTY
- { see_typename (); }
+see_typename:
+ /* empty */ %prec EMPTY
+ { see_typename (); }
;
-/*
-dont_see_typename: %prec EMPTY
- { dont_see_typename (); }
- ;
-
-try_for_typename:
- {
- if ($<ttype>-1 == error_mark_node)
- $$ = 0;
- else
- {
- $$ = 1;
- pushclass ($<ttype>-1, 1);
- }
- }
- ;
-*/
-
bad_parm:
/* empty */ %prec EMPTY
{
@@ -3775,22 +3605,26 @@ bad_parm:
| notype_declarator
{
error ("type specifier omitted for parameter");
+ if (TREE_CODE ($$) == SCOPE_REF
+ && (TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TEMPLATE_PARM))
+ cp_error (" perhaps you want `typename %E' to make it a type", $$);
$$ = build_tree_list (integer_type_node, $$);
}
;
exception_specification_opt:
- %prec EMPTY /* empty */
+ /* empty */ %prec EMPTY
{ $$ = NULL_TREE; }
- | THROW '(' ansi_raise_identifiers ')' %prec EMPTY
+ | THROW '(' ansi_raise_identifiers ')' %prec EMPTY
{ $$ = $3; }
- | THROW LEFT_RIGHT %prec EMPTY
+ | THROW LEFT_RIGHT %prec EMPTY
{ $$ = build_decl_list (NULL_TREE, NULL_TREE); }
;
ansi_raise_identifier:
type_id
- { $$ = build_decl_list (NULL_TREE, groktypename($$)); }
+ { $$ = build_decl_list (NULL_TREE, groktypename($1.t)); }
;
ansi_raise_identifiers:
@@ -3803,19 +3637,20 @@ ansi_raise_identifiers:
;
conversion_declarator:
- /* empty */ %prec EMPTY
+ /* empty */ %prec EMPTY
{ $$ = NULL_TREE; }
- | '*' type_quals conversion_declarator
+ | '*' cv_qualifiers conversion_declarator
{ $$ = make_pointer_declarator ($2, $3); }
- | '&' type_quals conversion_declarator
+ | '&' cv_qualifiers conversion_declarator
{ $$ = make_reference_declarator ($2, $3); }
- | ptr_to_mem type_quals conversion_declarator
+ | ptr_to_mem cv_qualifiers conversion_declarator
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
;
-operator: OPERATOR
+operator:
+ OPERATOR
{ got_scope = NULL_TREE; }
;
@@ -3878,9 +3713,9 @@ operator_name:
{ $$ = ansi_opname[CALL_EXPR]; }
| operator '[' ']'
{ $$ = ansi_opname[ARRAY_REF]; }
- | operator NEW %prec EMPTY
+ | operator NEW %prec EMPTY
{ $$ = ansi_opname[NEW_EXPR]; }
- | operator DELETE %prec EMPTY
+ | operator DELETE %prec EMPTY
{ $$ = ansi_opname[DELETE_EXPR]; }
| operator NEW '[' ']'
{ $$ = ansi_opname[VEC_NEW_EXPR]; }
@@ -3888,7 +3723,7 @@ operator_name:
{ $$ = ansi_opname[VEC_DELETE_EXPR]; }
/* Names here should be looked up in class scope ALSO. */
| operator type_specifier_seq conversion_declarator
- { $$ = grokoptypename ($2, $3); }
+ { $$ = grokoptypename ($2.t, $3); }
| operator error
{ $$ = ansi_opname[ERROR_MARK]; }
;
diff --git a/contrib/gcc/cp/pt.c b/contrib/gcc/cp/pt.c
index 3ce0224..556b761 100644
--- a/contrib/gcc/cp/pt.c
+++ b/contrib/gcc/cp/pt.c
@@ -1,6 +1,7 @@
/* Handle parameterized types (templates) for GNU C++.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
+ Rewritten by Jason Merrill (jason@cygnus.com).
This file is part of GNU CC.
@@ -20,17 +21,12 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Known bugs or deficiencies include:
- * templates for class static data don't work (methods only)
- * duplicated method templates can crash the compiler
- * interface/impl data is taken from file defining the template
- * all methods must be provided in header files; can't use a source
- file that contains only the method templates and "just win"
- * method templates must be seen before the expansion of the
- class template is done
- */
+
+ all methods must be provided in header files; can't use a source
+ file that contains only the method templates and "just win". */
#include "config.h"
-#include <stdio.h>
+#include "system.h"
#include "obstack.h"
#include "tree.h"
@@ -41,6 +37,12 @@ Boston, MA 02111-1307, USA. */
#include "lex.h"
#include "output.h"
#include "defaults.h"
+#include "except.h"
+#include "toplev.h"
+
+/* The type of functions taking a tree, and some additional data, and
+ returning an int. */
+typedef int (*tree_fn_t) PROTO((tree, void*));
extern struct obstack permanent_obstack;
@@ -48,40 +50,1348 @@ extern int lineno;
extern char *input_filename;
struct pending_inline *pending_template_expansions;
-int processing_template_decl;
-int processing_template_defn;
+tree current_template_parms;
+HOST_WIDE_INT processing_template_decl;
+
+tree pending_templates;
+static tree *template_tail = &pending_templates;
+
+tree maybe_templates;
+static tree *maybe_template_tail = &maybe_templates;
+
+int minimal_parse_mode;
-/* This is a kludge to handle instantiation of template methods that are
- used before their definition. It should not be necessary after the
- template rewrite. */
-static tree template_classes;
+int processing_specialization;
+int processing_explicit_instantiation;
+int processing_template_parmlist;
+static int template_header_count;
+
+static tree saved_trees;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-static int unify ();
-static void add_pending_template ();
+#define UNIFY_ALLOW_NONE 0
+#define UNIFY_ALLOW_MORE_CV_QUAL 1
+#define UNIFY_ALLOW_LESS_CV_QUAL 2
+#define UNIFY_ALLOW_DERIVED 4
+
+static int unify PROTO((tree, tree, tree, tree, int, int*));
+static void add_pending_template PROTO((tree));
+static int push_tinst_level PROTO((tree));
+static tree classtype_mangled_name PROTO((tree));
+static char *mangle_class_name_for_template PROTO((char *, tree, tree, tree));
+static tree tsubst_expr_values PROTO((tree, tree));
+static int list_eq PROTO((tree, tree));
+static tree get_class_bindings PROTO((tree, tree, tree, tree));
+static tree coerce_template_parms PROTO((tree, tree, tree, int, int));
+static tree tsubst_enum PROTO((tree, tree, tree *));
+static tree add_to_template_args PROTO((tree, tree));
+static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*,
+ tree*));
+static int type_unification_real PROTO((tree, tree, tree, tree,
+ int, unification_kind_t, int, int*));
+static tree complete_template_args PROTO((tree, tree, int));
+static void note_template_header PROTO((int));
+static tree maybe_fold_nontype_arg PROTO((tree));
+static tree convert_nontype_argument PROTO((tree, tree));
+static tree get_bindings_overload PROTO((tree, tree, tree));
+static int for_each_template_parm PROTO((tree, tree_fn_t, void*));
+static tree build_template_parm_index PROTO((int, int, int, tree, tree));
+static tree original_template PROTO((tree));
+static int inline_needs_template_parms PROTO((tree));
+static void push_inline_template_parms_recursive PROTO((tree, int));
+static tree retrieve_specialization PROTO((tree, tree));
+static void register_specialization PROTO((tree, tree, tree));
+static void print_candidates PROTO((tree));
+static tree reduce_template_parm_level PROTO((tree, tree, int));
+static tree build_template_decl PROTO((tree, tree));
+static int mark_template_parm PROTO((tree, void *));
+static tree tsubst_friend_function PROTO((tree, tree));
+static tree tsubst_friend_class PROTO((tree, tree));
+static tree get_bindings_real PROTO((tree, tree, tree, int));
+static int template_decl_level PROTO((tree));
+static tree maybe_get_template_decl_from_type_decl PROTO((tree));
+static int check_cv_quals_for_unify PROTO((int, tree, tree));
+static tree tsubst_template_arg_vector PROTO((tree, tree));
+static void regenerate_decl_from_template PROTO((tree, tree));
+static int is_member_template_class PROTO((tree));
+
+/* Nonzero if ARGVEC contains multiple levels of template arguments. */
+#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
+ (NODE != NULL_TREE \
+ && TREE_CODE (NODE) == TREE_VEC \
+ && TREE_VEC_LENGTH (NODE) > 0 \
+ && TREE_VEC_ELT (NODE, 0) != NULL_TREE \
+ && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC)
+
+/* Do any processing required when DECL (a member template declaration
+ using TEMPLATE_PARAMETERS as its innermost parameter list) is
+ finished. Returns the TEMPLATE_DECL corresponding to DECL, unless
+ it is a specialization, in which case the DECL itself is returned. */
+
+tree
+finish_member_template_decl (template_parameters, decl)
+ tree template_parameters;
+ tree decl;
+{
+ if (template_parameters)
+ end_template_decl ();
+ else
+ end_specialization ();
+
+ if (decl == NULL_TREE || decl == void_type_node)
+ return NULL_TREE;
+ else if (TREE_CODE (decl) == TREE_LIST)
+ {
+ /* Assume that the class is the only declspec. */
+ decl = TREE_VALUE (decl);
+ if (IS_AGGR_TYPE (decl) && CLASSTYPE_TEMPLATE_INFO (decl)
+ && ! CLASSTYPE_TEMPLATE_SPECIALIZATION (decl))
+ {
+ tree tmpl = CLASSTYPE_TI_TEMPLATE (decl);
+ check_member_template (tmpl);
+ return tmpl;
+ }
+ return NULL_TREE;
+ }
+ else if (DECL_TEMPLATE_INFO (decl))
+ {
+ if (!DECL_TEMPLATE_SPECIALIZATION (decl))
+ {
+ check_member_template (DECL_TI_TEMPLATE (decl));
+ return DECL_TI_TEMPLATE (decl);
+ }
+ else
+ return decl;
+ }
+ else
+ cp_error ("invalid member template declaration `%D'", decl);
+
+
+ return error_mark_node;
+}
+
+/* Returns the template nesting level of the indicated class TYPE.
+
+ For example, in:
+ template <class T>
+ struct A
+ {
+ template <class U>
+ struct B {};
+ };
+
+ A<T>::B<U> has depth two, while A<T> has depth one. Also,
+ both A<T>::B<int> and A<int>::B<U> have depth one. */
+
+int
+template_class_depth (type)
+ tree type;
+{
+ int depth;
+
+ for (depth = 0;
+ type && TREE_CODE (type) != FUNCTION_DECL
+ && TREE_CODE (type) != NAMESPACE_DECL;
+ type = TYPE_CONTEXT (type))
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
+ && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+ ++depth;
+
+ return depth;
+}
+
+/* Return the original template for this decl, disregarding any
+ specializations. */
+
+static tree
+original_template (decl)
+ tree decl;
+{
+ while (DECL_TEMPLATE_INFO (decl))
+ decl = DECL_TI_TEMPLATE (decl);
+ return decl;
+}
+
+/* Returns 1 if processing DECL as part of do_pending_inlines
+ needs us to push template parms. */
-void overload_template_name (), pop_template_decls ();
+static int
+inline_needs_template_parms (decl)
+ tree decl;
+{
+ if (! DECL_TEMPLATE_INFO (decl))
+ return 0;
+
+ return (list_length (DECL_TEMPLATE_PARMS (original_template (decl)))
+ > (processing_template_decl + DECL_TEMPLATE_SPECIALIZATION (decl)));
+}
+
+/* Subroutine of maybe_begin_member_template_processing.
+ Push the template parms in PARMS, starting from LEVELS steps into the
+ chain, and ending at the beginning, since template parms are listed
+ innermost first. */
+
+static void
+push_inline_template_parms_recursive (parmlist, levels)
+ tree parmlist;
+ int levels;
+{
+ tree parms = TREE_VALUE (parmlist);
+ int i;
+
+ if (levels > 1)
+ push_inline_template_parms_recursive (TREE_CHAIN (parmlist), levels - 1);
+
+ ++processing_template_decl;
+ current_template_parms
+ = tree_cons (build_int_2 (0, processing_template_decl),
+ parms, current_template_parms);
+ TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1;
+
+ pushlevel (0);
+ for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
+ {
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (parm)) == 'd', 0);
+
+ switch (TREE_CODE (parm))
+ {
+ case TYPE_DECL:
+ case TEMPLATE_DECL:
+ pushdecl (parm);
+ break;
+
+ case PARM_DECL:
+ {
+ /* Make a CONST_DECL as is done in process_template_parm. */
+ tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
+ TREE_TYPE (parm));
+ DECL_INITIAL (decl) = DECL_INITIAL (parm);
+ pushdecl (decl);
+ }
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
+ }
+}
+
+/* Restore the template parameter context for a member template or
+ a friend template defined in a class definition. */
+
+void
+maybe_begin_member_template_processing (decl)
+ tree decl;
+{
+ tree parms;
+ int levels;
+
+ if (! inline_needs_template_parms (decl))
+ return;
+
+ parms = DECL_TEMPLATE_PARMS (original_template (decl));
+
+ levels = list_length (parms) - processing_template_decl;
+
+ if (DECL_TEMPLATE_SPECIALIZATION (decl))
+ {
+ --levels;
+ parms = TREE_CHAIN (parms);
+ }
+
+ push_inline_template_parms_recursive (parms, levels);
+}
+
+/* Undo the effects of begin_member_template_processing. */
+
+void
+maybe_end_member_template_processing (decl)
+ tree decl;
+{
+ if (! processing_template_decl)
+ return;
+
+ while (current_template_parms
+ && TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
+ {
+ --processing_template_decl;
+ current_template_parms = TREE_CHAIN (current_template_parms);
+ poplevel (0, 0, 0);
+ }
+}
+
+/* Returns non-zero iff T is a member template function. We must be
+ careful as in
+
+ template <class T> class C { void f(); }
+
+ Here, f is a template function, and a member, but not a member
+ template. This function does not concern itself with the origin of
+ T, only its present state. So if we have
+
+ template <class T> class C { template <class U> void f(U); }
+
+ then neither C<int>::f<char> nor C<T>::f<double> is considered
+ to be a member template. */
+
+int
+is_member_template (t)
+ tree t;
+{
+ if (TREE_CODE (t) != FUNCTION_DECL
+ && !DECL_FUNCTION_TEMPLATE_P (t))
+ /* Anything that isn't a function or a template function is
+ certainly not a member template. */
+ return 0;
+
+ /* A local class can't have member templates. */
+ if (hack_decl_function_context (t))
+ return 0;
+
+ if ((DECL_FUNCTION_MEMBER_P (t)
+ && !DECL_TEMPLATE_SPECIALIZATION (t))
+ || (TREE_CODE (t) == TEMPLATE_DECL
+ && DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))))
+ {
+ tree tmpl;
+
+ if (DECL_FUNCTION_TEMPLATE_P (t))
+ tmpl = t;
+ else if (DECL_TEMPLATE_INFO (t)
+ && DECL_FUNCTION_TEMPLATE_P (DECL_TI_TEMPLATE (t)))
+ tmpl = DECL_TI_TEMPLATE (t);
+ else
+ tmpl = NULL_TREE;
+
+ if (tmpl
+ /* If there are more levels of template parameters than
+ there are template classes surrounding the declaration,
+ then we have a member template. */
+ && (list_length (DECL_TEMPLATE_PARMS (tmpl)) >
+ template_class_depth (DECL_CLASS_CONTEXT (t))))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Returns non-zero iff T is a member template class. See
+ is_member_template for a description of what precisely constitutes
+ a member template. */
+
+int
+is_member_template_class (t)
+ tree t;
+{
+ if (!DECL_CLASS_TEMPLATE_P (t))
+ /* Anything that isn't a class template, is certainly not a member
+ template. */
+ return 0;
+
+ if (!DECL_CLASS_SCOPE_P (t))
+ /* Anything whose context isn't a class type is surely not a
+ member template. */
+ return 0;
+
+ /* If there are more levels of template parameters than there are
+ template classes surrounding the declaration, then we have a
+ member template. */
+ return (list_length (DECL_TEMPLATE_PARMS (t)) >
+ template_class_depth (DECL_CONTEXT (t)));
+}
+
+/* Return a new template argument vector which contains all of ARGS
+ for all outer templates TMPL is contained in, but has as its
+ innermost set of arguments the EXTRA_ARGS. If UNBOUND_ONLY, we
+ are only interested in unbound template arguments, not arguments from
+ enclosing templates that have been instantiated already. */
+
+static tree
+complete_template_args (tmpl, extra_args, unbound_only)
+ tree tmpl, extra_args;
+ int unbound_only;
+{
+ /* depth is the number of levels of enclosing args we're adding. */
+ int depth, i;
+ tree args, new_args, spec_args = NULL_TREE;
+ int extra_arg_depth;
+
+ my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+ my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0);
+
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (extra_args))
+ extra_arg_depth = TREE_VEC_LENGTH (extra_args);
+ else
+ extra_arg_depth = 1;
+
+ if (DECL_TEMPLATE_INFO (tmpl) && !unbound_only)
+ {
+ /* A specialization of a member template of a template class shows up
+ as a TEMPLATE_DECL with DECL_TEMPLATE_SPECIALIZATION set.
+ DECL_TI_ARGS is the specialization args, and DECL_TI_TEMPLATE
+ is the template being specialized. */
+ if (DECL_TEMPLATE_SPECIALIZATION (tmpl))
+ {
+ spec_args = DECL_TI_ARGS (tmpl);
+ tmpl = DECL_TI_TEMPLATE (tmpl);
+ }
+
+ if (DECL_TEMPLATE_INFO (tmpl))
+ {
+ /* A partial instantiation of a member template shows up as a
+ TEMPLATE_DECL with DECL_TEMPLATE_INFO. DECL_TI_ARGS is
+ all the bound template arguments. */
+ args = DECL_TI_ARGS (tmpl);
+ if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
+ depth = 1;
+ else
+ depth = TREE_VEC_LENGTH (args);
+ }
+ else
+ /* If we are a specialization, we might have no previously bound
+ template args. */
+ depth = 0;
+
+ new_args = make_tree_vec (depth + extra_arg_depth + (!!spec_args));
+
+ if (depth == 1)
+ TREE_VEC_ELT (new_args, 0) = args;
+ else
+ for (i = 0; i < depth; ++i)
+ TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i);
+ }
+ else
+ {
+ tree type;
+ int skip;
+
+ /* For unbound args, we have to do more work. We are getting bindings
+ for the innermost args from extra_args, so we start from our
+ context and work out until we've seen all the args. We need to
+ do it this way to handle partial specialization. */
+
+ depth = list_length (DECL_TEMPLATE_PARMS (tmpl)) - 1;
+ if (depth == 0)
+ return extra_args;
+
+ new_args = make_tree_vec (depth + extra_arg_depth);
+
+ /* If this isn't a member template, extra_args is for the innermost
+ template class, so skip over it. */
+ skip = (! is_member_template (tmpl));
+
+ if (depth > skip)
+ {
+ type = DECL_REAL_CONTEXT (tmpl);
+ for (i = depth; i; type = TYPE_CONTEXT (type))
+ if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type)))
+ {
+ if (skip)
+ skip = 0;
+ else
+ {
+ --i;
+ TREE_VEC_ELT (new_args, i) = CLASSTYPE_TI_ARGS (type);
+ }
+ }
+ }
+ }
+
+ if (extra_arg_depth == 1)
+ TREE_VEC_ELT (new_args, depth++) = extra_args;
+ else
+ for (i = 0; i < extra_arg_depth; ++i)
+ TREE_VEC_ELT (new_args, depth++) = TREE_VEC_ELT (extra_args, i);
+
+ if (spec_args)
+ TREE_VEC_ELT (new_args, depth) = spec_args;
+
+ return new_args;
+}
+
+/* Return a new template argument vector which contains all of ARGS,
+ but has as its innermost set of arguments the EXTRA_ARGS. */
+
+static tree
+add_to_template_args (args, extra_args)
+ tree args;
+ tree extra_args;
+{
+ tree new_args;
+
+ if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
+ {
+ new_args = make_tree_vec (2);
+ TREE_VEC_ELT (new_args, 0) = args;
+ }
+ else
+ {
+ int i;
+
+ new_args = make_tree_vec (TREE_VEC_LENGTH (args) + 1);
+
+ for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
+ TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i);
+ }
+
+ TREE_VEC_ELT (new_args,
+ TREE_VEC_LENGTH (new_args) - 1) = extra_args;
+
+ return new_args;
+}
+
+/* We've got a template header coming up; push to a new level for storing
+ the parms. */
-/* We've got a template header coming up; set obstacks up to save the
- nodes created permanently. (There might be cases with nested templates
- where we don't have to do this, but they aren't implemented, and it
- probably wouldn't be worth the effort.) */
void
begin_template_parm_list ()
{
+ /* We use a non-tag-transparent scope here, which causes pushtag to
+ put tags in this scope, rather than in the enclosing class or
+ namespace scope. This is the right thing, since we want
+ TEMPLATE_DECLS, and not TYPE_DECLS for template classes. For a
+ global template class, push_template_decl handles putting the
+ TEMPLATE_DECL into top-level scope. For a nested template class,
+ e.g.:
+
+ template <class T> struct S1 {
+ template <class T> struct S2 {};
+ };
+
+ pushtag contains special code to call pushdecl_with_scope on the
+ TEMPLATE_DECL for S2. */
pushlevel (0);
- push_obstacks (&permanent_obstack, &permanent_obstack);
- pushlevel (0);
+ declare_pseudo_global_level ();
+ ++processing_template_decl;
+ ++processing_template_parmlist;
+ note_template_header (0);
+}
+
+/* We've just seen template <>. */
+
+void
+begin_specialization ()
+{
+ note_template_header (1);
+}
+
+/* Called at then end of processing a declaration preceeded by
+ template<>. */
+
+void
+end_specialization ()
+{
+ reset_specialization ();
+}
+
+/* Any template <>'s that we have seen thus far are not referring to a
+ function specialization. */
+
+void
+reset_specialization ()
+{
+ processing_specialization = 0;
+ template_header_count = 0;
+}
+
+/* We've just seen a template header. If SPECIALIZATION is non-zero,
+ it was of the form template <>. */
+
+static void
+note_template_header (specialization)
+ int specialization;
+{
+ processing_specialization = specialization;
+ template_header_count++;
+}
+
+/* We're beginning an explicit instantiation. */
+
+void
+begin_explicit_instantiation ()
+{
+ ++processing_explicit_instantiation;
+}
+
+
+void
+end_explicit_instantiation ()
+{
+ my_friendly_assert(processing_explicit_instantiation > 0, 0);
+ --processing_explicit_instantiation;
+}
+
+/* Retrieve the specialization (in the sense of [temp.spec] - a
+ specialization is either an instantiation or an explicit
+ specialization) of TMPL for the given template ARGS. If there is
+ no such specialization, return NULL_TREE. The ARGS are a vector of
+ arguments, or a vector of vectors of arguments, in the case of
+ templates with more than one level of parameters. */
+
+static tree
+retrieve_specialization (tmpl, args)
+ tree tmpl;
+ tree args;
+{
+ tree s;
+
+ my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+
+ for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
+ s != NULL_TREE;
+ s = TREE_CHAIN (s))
+ if (comp_template_args (TREE_PURPOSE (s), args))
+ return TREE_VALUE (s);
+
+ return NULL_TREE;
+}
+
+/* Returns non-zero iff DECL is a specialization of TMPL. */
+
+int
+is_specialization_of (decl, tmpl)
+ tree decl;
+ tree tmpl;
+{
+ tree t;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ for (t = decl;
+ t != NULL_TREE;
+ t = DECL_TEMPLATE_INFO (t) ? DECL_TI_TEMPLATE (t) : NULL_TREE)
+ if (t == tmpl)
+ return 1;
+ }
+ else
+ {
+ my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 0);
+
+ for (t = TREE_TYPE (decl);
+ t != NULL_TREE;
+ t = CLASSTYPE_USE_TEMPLATE (t)
+ ? TREE_TYPE (CLASSTYPE_TI_TEMPLATE (t)) : NULL_TREE)
+ if (comptypes (TYPE_MAIN_VARIANT (t),
+ TYPE_MAIN_VARIANT (TREE_TYPE (tmpl)), 1))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Register the specialization SPEC as a specialization of TMPL with
+ the indicated ARGS. */
+
+static void
+register_specialization (spec, tmpl, args)
+ tree spec;
+ tree tmpl;
+ tree args;
+{
+ tree s;
+
+ my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+
+ if (TREE_CODE (spec) != TEMPLATE_DECL
+ && list_length (DECL_TEMPLATE_PARMS (tmpl)) > 1)
+ /* Avoid registering function declarations as
+ specializations of member templates, as would otherwise
+ happen with out-of-class specializations of member
+ templates. */
+ return;
+
+ for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
+ s != NULL_TREE;
+ s = TREE_CHAIN (s))
+ if (comp_template_args (TREE_PURPOSE (s), args))
+ {
+ tree fn = TREE_VALUE (s);
+
+ if (DECL_TEMPLATE_SPECIALIZATION (spec))
+ {
+ if (DECL_TEMPLATE_INSTANTIATION (fn))
+ {
+ if (TREE_USED (fn)
+ || DECL_EXPLICIT_INSTANTIATION (fn))
+ {
+ cp_error ("specialization of %D after instantiation",
+ fn);
+ return;
+ }
+ else
+ {
+ /* This situation should occur only if the first
+ specialization is an implicit instantiation,
+ the second is an explicit specialization, and
+ the implicit instantiation has not yet been
+ used. That situation can occur if we have
+ implicitly instantiated a member function of
+ class type, and then specialized it later. */
+ TREE_VALUE (s) = spec;
+ return;
+ }
+ }
+ else if (DECL_TEMPLATE_SPECIALIZATION (fn))
+ {
+ if (DECL_INITIAL (fn))
+ cp_error ("duplicate specialization of %D", fn);
+
+ TREE_VALUE (s) = spec;
+ return;
+ }
+ }
+ }
+
+ DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
+ = perm_tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+}
+
+/* Print the list of candidate FNS in an error message. */
+
+static void
+print_candidates (fns)
+ tree fns;
+{
+ tree fn;
+
+ char* str = "candidates are:";
+
+ for (fn = fns; fn != NULL_TREE; fn = TREE_CHAIN (fn))
+ {
+ cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
+ str = " ";
+ }
+}
+
+/* Returns the template (one of the functions given by TEMPLATE_ID)
+ which can be specialized to match the indicated DECL with the
+ explicit template args given in TEMPLATE_ID. If
+ NEED_MEMBER_TEMPLATE is true the function is a specialization of a
+ member template. The template args (those explicitly specified and
+ those deduced) are output in a newly created vector *TARGS_OUT. If
+ it is impossible to determine the result, an error message is
+ issued, unless COMPLAIN is 0. The DECL may be NULL_TREE if none is
+ available. */
+
+tree
+determine_specialization (template_id, decl, targs_out,
+ need_member_template,
+ complain)
+ tree template_id;
+ tree decl;
+ tree* targs_out;
+ int need_member_template;
+ int complain;
+{
+ tree fns, targs_in;
+ tree templates = NULL_TREE;
+ tree fn;
+ int i;
+
+ *targs_out = NULL_TREE;
+
+ if (template_id == error_mark_node)
+ return error_mark_node;
+
+ fns = TREE_OPERAND (template_id, 0);
+ targs_in = TREE_OPERAND (template_id, 1);
+
+ if (fns == error_mark_node)
+ return error_mark_node;
+
+ /* Check for baselinks. */
+ if (TREE_CODE (fns) == TREE_LIST)
+ fns = TREE_VALUE (fns);
+
+ for (; fns; fns = OVL_NEXT (fns))
+ {
+ tree tmpl;
+
+ fn = OVL_CURRENT (fns);
+ if (!need_member_template
+ && TREE_CODE (fn) == FUNCTION_DECL
+ && DECL_FUNCTION_MEMBER_P (fn)
+ && DECL_USE_TEMPLATE (fn)
+ && DECL_TI_TEMPLATE (fn))
+ /* We can get here when processing something like:
+ template <class T> class X { void f(); }
+ template <> void X<int>::f() {}
+ We're specializing a member function, but not a member
+ template. */
+ tmpl = DECL_TI_TEMPLATE (fn);
+ else if (TREE_CODE (fn) != TEMPLATE_DECL
+ || (need_member_template && !is_member_template (fn)))
+ continue;
+ else
+ tmpl = fn;
+
+ if (list_length (targs_in) > DECL_NTPARMS (tmpl))
+ continue;
+
+ if (decl == NULL_TREE)
+ {
+ tree targs = make_scratch_vec (DECL_NTPARMS (tmpl));
+
+ /* We allow incomplete unification here, because we are going to
+ check all the functions. */
+ i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
+ targs,
+ NULL_TREE,
+ NULL_TREE,
+ targs_in,
+ DEDUCE_EXACT, 1);
+
+ if (i == 0)
+ /* Unification was successful. */
+ templates = scratch_tree_cons (targs, tmpl, templates);
+ }
+ else
+ templates = scratch_tree_cons (NULL_TREE, tmpl, templates);
+ }
+
+ if (decl != NULL_TREE)
+ {
+ tree tmpl = most_specialized (templates, decl, targs_in);
+
+ if (tmpl == error_mark_node)
+ goto ambiguous;
+ else if (tmpl == NULL_TREE)
+ goto no_match;
+
+ *targs_out = get_bindings (tmpl, decl, targs_in);
+ return tmpl;
+ }
+
+ if (templates == NULL_TREE)
+ {
+ no_match:
+ if (complain)
+ {
+ cp_error_at ("template-id `%D' for `%+D' does not match any template declaration",
+ template_id, decl);
+ return error_mark_node;
+ }
+ return NULL_TREE;
+ }
+ else if (TREE_CHAIN (templates) != NULL_TREE)
+ {
+ ambiguous:
+ if (complain)
+ {
+ cp_error_at ("ambiguous template specialization `%D' for `%+D'",
+ template_id, decl);
+ print_candidates (templates);
+ return error_mark_node;
+ }
+ return NULL_TREE;
+ }
+
+ /* We have one, and exactly one, match. */
+ *targs_out = TREE_PURPOSE (templates);
+ return TREE_VALUE (templates);
+}
+
+/* Check to see if the function just declared, as indicated in
+ DECLARATOR, and in DECL, is a specialization of a function
+ template. We may also discover that the declaration is an explicit
+ instantiation at this point.
+
+ Returns DECL, or an equivalent declaration that should be used
+ instead.
+
+ FLAGS is a bitmask consisting of the following flags:
+
+ 1: We are being called by finish_struct. (We are unable to
+ determine what template is specialized by an in-class
+ declaration until the class definition is complete, so
+ finish_struct_methods calls this function again later to finish
+ the job.)
+ 2: The function has a definition.
+ 4: The function is a friend.
+ 8: The function is known to be a specialization of a member
+ template.
+
+ The TEMPLATE_COUNT is the number of references to qualifying
+ template classes that appeared in the name of the function. For
+ example, in
+
+ template <class T> struct S { void f(); };
+ void S<int>::f();
+
+ the TEMPLATE_COUNT would be 1. However, explicitly specialized
+ classes are not counted in the TEMPLATE_COUNT, so that in
+
+ template <class T> struct S {};
+ template <> struct S<int> { void f(); }
+ template <>
+ void S<int>::f();
+
+ the TEMPLATE_COUNT would be 0. (Note that this declaration is
+ illegal; there should be no template <>.)
+
+ If the function is a specialization, it is marked as such via
+ DECL_TEMPLATE_SPECIALIZATION. Furthermore, its DECL_TEMPLATE_INFO
+ is set up correctly, and it is added to the list of specializations
+ for that template. */
+
+tree
+check_explicit_specialization (declarator, decl, template_count, flags)
+ tree declarator;
+ tree decl;
+ int template_count;
+ int flags;
+{
+ int finish_member = flags & 1;
+ int have_def = flags & 2;
+ int is_friend = flags & 4;
+ int specialization = 0;
+ int explicit_instantiation = 0;
+ int member_specialization = flags & 8;
+
+ tree ctype = DECL_CLASS_CONTEXT (decl);
+ tree dname = DECL_NAME (decl);
+
+ if (!finish_member)
+ {
+ if (processing_specialization)
+ {
+ /* The last template header was of the form template <>. */
+
+ if (template_header_count > template_count)
+ {
+ /* There were more template headers than qualifying template
+ classes. */
+ if (template_header_count - template_count > 1)
+ /* There shouldn't be that many template parameter
+ lists. There can be at most one parameter list for
+ every qualifying class, plus one for the function
+ itself. */
+ cp_error ("too many template parameter lists in declaration of `%D'", decl);
+
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ if (ctype)
+ member_specialization = 1;
+ else
+ specialization = 1;
+ }
+ else if (template_header_count == template_count)
+ {
+ /* The counts are equal. So, this might be a
+ specialization, but it is not a specialization of a
+ member template. It might be something like
+
+ template <class T> struct S {
+ void f(int i);
+ };
+ template <>
+ void S<int>::f(int i) {} */
+ specialization = 1;
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ }
+ else
+ {
+ /* This cannot be an explicit specialization. There are not
+ enough headers for all of the qualifying classes. For
+ example, we might have:
+
+ template <>
+ void S<int>::T<char>::f();
+
+ But, we're missing another template <>. */
+ cp_error("too few template parameter lists in declaration of `%D'", decl);
+ return decl;
+ }
+ }
+ else if (processing_explicit_instantiation)
+ {
+ if (template_header_count)
+ cp_error ("template parameter list used in explicit instantiation");
+
+ if (have_def)
+ cp_error ("definition provided for explicit instantiation");
+
+ explicit_instantiation = 1;
+ }
+ else if (ctype != NULL_TREE
+ && !TYPE_BEING_DEFINED (ctype)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
+ {
+ /* This case catches outdated code that looks like this:
+
+ template <class T> struct S { void f(); };
+ void S<int>::f() {} // Missing template <>
+
+ We disable this check when the type is being defined to
+ avoid complaining about default compiler-generated
+ constructors, destructors, and assignment operators.
+ Since the type is an instantiation, not a specialization,
+ these are the only functions that can be defined before
+ the class is complete. */
+
+ /* If they said
+ template <class T> void S<int>::f() {}
+ that's bogus. */
+ if (template_header_count)
+ {
+ cp_error ("template parameters specified in specialization");
+ return decl;
+ }
+
+ if (pedantic)
+ cp_pedwarn
+ ("explicit specialization not preceded by `template <>'");
+ specialization = 1;
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ }
+ else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+ {
+ /* This case handles bogus declarations like
+ template <> template <class T>
+ void f<int>(); */
+
+ cp_error ("template-id `%D' in declaration of primary template",
+ declarator);
+ return decl;
+ }
+ }
+
+ if (specialization || member_specialization)
+ {
+ tree t = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ for (; t; t = TREE_CHAIN (t))
+ if (TREE_PURPOSE (t))
+ {
+ cp_pedwarn
+ ("default argument specified in explicit specialization");
+ break;
+ }
+ }
+
+ if (specialization || member_specialization || explicit_instantiation)
+ {
+ tree tmpl = NULL_TREE;
+ tree targs = NULL_TREE;
+
+ /* Make sure that the declarator is a TEMPLATE_ID_EXPR. */
+ if (TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
+ {
+ tree fns;
+
+ my_friendly_assert (TREE_CODE (declarator) == IDENTIFIER_NODE,
+ 0);
+ if (!ctype)
+ fns = IDENTIFIER_NAMESPACE_VALUE (dname);
+ else
+ fns = dname;
+
+ declarator =
+ lookup_template_function (fns, NULL_TREE);
+ }
+
+ if (declarator == error_mark_node)
+ return error_mark_node;
+
+ if (TREE_CODE (TREE_OPERAND (declarator, 0)) == LOOKUP_EXPR)
+ {
+ /* A friend declaration. We can't do much, because we don't
+ know what this resolves to, yet. */
+ my_friendly_assert (is_friend != 0, 0);
+ my_friendly_assert (!explicit_instantiation, 0);
+ SET_DECL_IMPLICIT_INSTANTIATION (decl);
+ return decl;
+ }
+
+ if (ctype != NULL_TREE && TYPE_BEING_DEFINED (ctype))
+ {
+ if (!explicit_instantiation)
+ {
+ /* Since finish_struct_1 has not been called yet, we
+ can't call lookup_fnfields. We note that this
+ template is a specialization, and proceed, letting
+ finish_struct fix this up later. */
+ tree ti = perm_tree_cons (NULL_TREE,
+ TREE_OPERAND (declarator, 1),
+ NULL_TREE);
+ TI_PENDING_SPECIALIZATION_FLAG (ti) = 1;
+ DECL_TEMPLATE_INFO (decl) = ti;
+ }
+ else
+ /* It's not legal to write an explicit instantiation in
+ class scope, e.g.:
+
+ class C { template void f(); }
+
+ This case is caught by the parser. However, on
+ something like:
+
+ template class C { void f(); };
+
+ (which is illegal) we can get here. The error will be
+ issued later. */
+ ;
+
+ return decl;
+ }
+ else if (ctype != NULL_TREE
+ && (TREE_CODE (TREE_OPERAND (declarator, 0)) ==
+ IDENTIFIER_NODE))
+ {
+ /* Find the list of functions in ctype that have the same
+ name as the declared function. */
+ tree name = TREE_OPERAND (declarator, 0);
+ tree fns;
+
+ if (name == constructor_name (ctype)
+ || name == constructor_name_full (ctype))
+ {
+ int is_constructor = DECL_CONSTRUCTOR_P (decl);
+
+ if (is_constructor ? !TYPE_HAS_CONSTRUCTOR (ctype)
+ : !TYPE_HAS_DESTRUCTOR (ctype))
+ {
+ /* From [temp.expl.spec]:
+
+ If such an explicit specialization for the member
+ of a class template names an implicitly-declared
+ special member function (clause _special_), the
+ program is ill-formed.
+
+ Similar language is found in [temp.explicit]. */
+ cp_error ("specialization of implicitly-declared special member function");
+
+ return decl;
+ }
+
+ name = is_constructor ? ctor_identifier : dtor_identifier;
+ }
+
+ fns = lookup_fnfields (TYPE_BINFO (ctype), name, 1);
+
+ if (fns == NULL_TREE)
+ {
+ cp_error ("no member function `%s' declared in `%T'",
+ IDENTIFIER_POINTER (name),
+ ctype);
+ return decl;
+ }
+ else
+ TREE_OPERAND (declarator, 0) = fns;
+ }
+
+ /* Figure out what exactly is being specialized at this point.
+ Note that for an explicit instantiation, even one for a
+ member function, we cannot tell apriori whether the
+ instantiation is for a member template, or just a member
+ function of a template class. In particular, even in if the
+ instantiation is for a member template, the template
+ arguments could be deduced from the declaration. */
+ tmpl = determine_specialization (declarator, decl,
+ &targs,
+ member_specialization,
+ 1);
+
+ if (tmpl && tmpl != error_mark_node)
+ {
+ if (explicit_instantiation)
+ {
+ decl = instantiate_template (tmpl, targs);
+ if (!DECL_TEMPLATE_SPECIALIZATION (decl))
+ /* There doesn't seem to be anything in the draft to
+ prevent a specialization from being explicitly
+ instantiated. We're careful not to destroy the
+ information indicating that this is a
+ specialization here. */
+ SET_DECL_EXPLICIT_INSTANTIATION (decl);
+ return decl;
+ }
+ else if (DECL_STATIC_FUNCTION_P (tmpl)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ {
+ revert_static_member_fn (&decl, 0, 0);
+ last_function_parms = TREE_CHAIN (last_function_parms);
+ }
+
+ /* Mangle the function name appropriately. Note that we do
+ not mangle specializations of non-template member
+ functions of template classes, e.g. with
+ template <class T> struct S { void f(); }
+ and given the specialization
+ template <> void S<int>::f() {}
+ we do not mangle S<int>::f() here. That's because it's
+ just an ordinary member function and doesn't need special
+ treatment. */
+ if ((is_member_template (tmpl) || ctype == NULL_TREE)
+ && name_mangling_version >= 1)
+ {
+ tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (tmpl));
+
+ if (ctype
+ && TREE_CODE (TREE_TYPE (tmpl)) == FUNCTION_TYPE)
+ arg_types =
+ hash_tree_chain (build_pointer_type (ctype),
+ arg_types);
+
+ DECL_ASSEMBLER_NAME (decl)
+ = build_template_decl_overload
+ (decl, arg_types, TREE_TYPE (TREE_TYPE (tmpl)),
+ DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
+ targs, ctype != NULL_TREE);
+ }
+
+ if (is_friend && !have_def)
+ {
+ /* This is not really a declaration of a specialization.
+ It's just the name of an instantiation. But, it's not
+ a request for an instantiation, either. */
+ SET_DECL_IMPLICIT_INSTANTIATION (decl);
+ DECL_TEMPLATE_INFO (decl)
+ = perm_tree_cons (tmpl, targs, NULL_TREE);
+ return decl;
+ }
+
+ /* If DECL_TI_TEMPLATE (decl), the decl is an
+ instantiation of a specialization of a member template.
+ (In other words, there was a member template, in a
+ class template. That member template was specialized.
+ We then instantiated the class, so there is now an
+ instance of that specialization.)
+
+ According to the CD2,
+
+ 14.7.3.13 [tmpl.expl.spec]
+
+ A specialization of a member function template or
+ member class template of a non-specialized class
+ template is itself a template.
+
+ So, we just leave the template info alone in this case. */
+ if (!(DECL_TEMPLATE_INFO (decl) && DECL_TI_TEMPLATE (decl)))
+ DECL_TEMPLATE_INFO (decl)
+ = perm_tree_cons (tmpl, targs, NULL_TREE);
+
+ register_specialization (decl, tmpl, targs);
+
+ return decl;
+ }
+ }
+
+ return decl;
+}
+
+/* Returns 1 iff PARMS1 and PARMS2 are identical sets of template
+ parameters. These are represented in the same format used for
+ DECL_TEMPLATE_PARMS. */
+
+int comp_template_parms (parms1, parms2)
+ tree parms1;
+ tree parms2;
+{
+ tree p1;
+ tree p2;
+
+ if (parms1 == parms2)
+ return 1;
+
+ for (p1 = parms1, p2 = parms2;
+ p1 != NULL_TREE && p2 != NULL_TREE;
+ p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2))
+ {
+ tree t1 = TREE_VALUE (p1);
+ tree t2 = TREE_VALUE (p2);
+ int i;
+
+ my_friendly_assert (TREE_CODE (t1) == TREE_VEC, 0);
+ my_friendly_assert (TREE_CODE (t2) == TREE_VEC, 0);
+
+ if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2))
+ return 0;
+
+ for (i = 0; i < TREE_VEC_LENGTH (t2); ++i)
+ {
+ tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
+ tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
+
+ if (TREE_CODE (parm1) != TREE_CODE (parm2))
+ return 0;
+
+ if (TREE_CODE (parm1) == TEMPLATE_TYPE_PARM)
+ continue;
+ else if (!comptypes (TREE_TYPE (parm1),
+ TREE_TYPE (parm2), 1))
+ return 0;
+ }
+ }
+
+ if ((p1 != NULL_TREE) != (p2 != NULL_TREE))
+ /* One set of parameters has more parameters lists than the
+ other. */
+ return 0;
+
+ return 1;
+}
+
+/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
+ ORIG_LEVEL, DECL, and TYPE. */
+
+static tree
+build_template_parm_index (index, level, orig_level, decl, type)
+ int index;
+ int level;
+ int orig_level;
+ tree decl;
+ tree type;
+{
+ tree t = make_node (TEMPLATE_PARM_INDEX);
+ TEMPLATE_PARM_IDX (t) = index;
+ TEMPLATE_PARM_LEVEL (t) = level;
+ TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level;
+ TEMPLATE_PARM_DECL (t) = decl;
+ TREE_TYPE (t) = type;
+
+ return t;
+}
+
+/* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose
+ TEMPLATE_PARM_LEVEL has been decreased by LEVELS. If such a
+ TEMPLATE_PARM_INDEX already exists, it is returned; otherwise, a
+ new one is created. */
+
+static tree
+reduce_template_parm_level (index, type, levels)
+ tree index;
+ tree type;
+ int levels;
+{
+ if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE
+ || (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index))
+ != TEMPLATE_PARM_LEVEL (index) - levels))
+ {
+ tree decl
+ = build_decl (TREE_CODE (TEMPLATE_PARM_DECL (index)),
+ DECL_NAME (TEMPLATE_PARM_DECL (index)),
+ type);
+ tree t
+ = build_template_parm_index (TEMPLATE_PARM_IDX (index),
+ TEMPLATE_PARM_LEVEL (index) - levels,
+ TEMPLATE_PARM_ORIG_LEVEL (index),
+ decl, type);
+ TEMPLATE_PARM_DESCENDANTS (index) = t;
+
+ /* Template template parameters need this. */
+ DECL_TEMPLATE_PARMS (decl)
+ = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index));
+ }
+
+ return TEMPLATE_PARM_DESCENDANTS (index);
}
/* Process information from new template parameter NEXT and append it to the
- LIST being built. The rules for use of a template parameter type name
- by later parameters are not well-defined for us just yet. However, the
- only way to avoid having to parse expressions of unknown complexity (and
- with tokens of unknown types) is to disallow it completely. So for now,
- that is what is assumed. */
+ LIST being built. */
+
tree
process_template_parm (list, next)
tree list, next;
@@ -89,51 +1399,92 @@ process_template_parm (list, next)
tree parm;
tree decl = 0;
tree defval;
- int is_type;
+ int is_type, idx;
+
parm = next;
my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
defval = TREE_PURPOSE (parm);
parm = TREE_VALUE (parm);
is_type = TREE_PURPOSE (parm) == class_type_node;
+
+ if (list)
+ {
+ tree p = TREE_VALUE (tree_last (list));
+
+ if (TREE_CODE (p) == TYPE_DECL)
+ idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
+ else if (TREE_CODE (p) == TEMPLATE_DECL)
+ idx = TEMPLATE_TYPE_IDX (TREE_TYPE (DECL_TEMPLATE_RESULT (p)));
+ else
+ idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p));
+ ++idx;
+ }
+ else
+ idx = 0;
+
if (!is_type)
{
- tree tinfo = 0;
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, NULL_TREE);
+ PARM, 0, NULL_TREE);
/* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1;
- if (IS_AGGR_TYPE (TREE_TYPE (parm)))
+ if (IS_AGGR_TYPE (TREE_TYPE (parm))
+ && TREE_CODE (TREE_TYPE (parm)) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (TREE_TYPE (parm)) != TYPENAME_TYPE)
{
- sorry ("aggregate template parameter types");
+ cp_error ("`%#T' is not a valid type for a template constant parameter",
+ TREE_TYPE (parm));
+ if (DECL_NAME (parm) == NULL_TREE)
+ error (" a template type parameter must begin with `class' or `typename'");
TREE_TYPE (parm) = void_type_node;
}
- tinfo = make_node (TEMPLATE_CONST_PARM);
- my_friendly_assert (TREE_PERMANENT (tinfo), 260.5);
+ else if (pedantic
+ && (TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE
+ || TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE))
+ cp_pedwarn ("`%T' is not a valid type for a template constant parameter",
+ TREE_TYPE (parm));
if (TREE_PERMANENT (parm) == 0)
{
parm = copy_node (parm);
TREE_PERMANENT (parm) = 1;
}
- TREE_TYPE (tinfo) = TREE_TYPE (parm);
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
- DECL_INITIAL (decl) = tinfo;
- DECL_INITIAL (parm) = tinfo;
+ DECL_INITIAL (parm) = DECL_INITIAL (decl)
+ = build_template_parm_index (idx, processing_template_decl,
+ processing_template_decl,
+ decl, TREE_TYPE (parm));
}
else
{
- tree t = make_node (TEMPLATE_TYPE_PARM);
- decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t);
- TYPE_MAIN_DECL (t) = decl;
- parm = decl;
- if (defval)
+ tree t;
+ parm = TREE_VALUE (parm);
+
+ if (parm && TREE_CODE (parm) == TEMPLATE_DECL)
{
- if (IDENTIFIER_HAS_TYPE_VALUE (defval))
- defval = IDENTIFIER_TYPE_VALUE (defval);
- else
- defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval));
+ t = make_lang_type (TEMPLATE_TEMPLATE_PARM);
+ /* This is for distinguishing between real templates and template
+ template parameters */
+ TREE_TYPE (parm) = t;
+ TREE_TYPE (DECL_TEMPLATE_RESULT (parm)) = t;
+ decl = parm;
}
+ else
+ {
+ t = make_lang_type (TEMPLATE_TYPE_PARM);
+ /* parm is either IDENTIFIER_NODE or NULL_TREE */
+ decl = build_decl (TYPE_DECL, parm, t);
+ }
+
+ CLASSTYPE_GOT_SEMICOLON (t) = 1;
+ TYPE_NAME (t) = decl;
+ TYPE_STUB_DECL (t) = decl;
+ parm = decl;
+ TEMPLATE_TYPE_PARM_INDEX (t)
+ = build_template_parm_index (idx, processing_template_decl,
+ processing_template_decl,
+ decl, TREE_TYPE (parm));
}
SET_DECL_ARTIFICIAL (decl);
pushdecl (decl);
@@ -150,196 +1501,965 @@ tree
end_template_parm_list (parms)
tree parms;
{
- int nparms = 0;
- int saw_default = 0;
- tree saved_parmlist;
+ int nparms;
tree parm;
- for (parm = parms; parm; parm = TREE_CHAIN (parm))
- nparms++;
- saved_parmlist = make_tree_vec (nparms);
+ tree saved_parmlist = make_tree_vec (list_length (parms));
+
+ current_template_parms
+ = tree_cons (build_int_2 (0, processing_template_decl),
+ saved_parmlist, current_template_parms);
for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
+ TREE_VEC_ELT (saved_parmlist, nparms) = parm;
+
+ --processing_template_parmlist;
+
+ return saved_parmlist;
+}
+
+/* end_template_decl is called after a template declaration is seen. */
+
+void
+end_template_decl ()
+{
+ reset_specialization ();
+
+ if (! processing_template_decl)
+ return;
+
+ /* This matches the pushlevel in begin_template_parm_list. */
+ poplevel (0, 0, 0);
+
+ --processing_template_decl;
+ current_template_parms = TREE_CHAIN (current_template_parms);
+ (void) get_pending_sizes (); /* Why? */
+}
+
+/* Generate a valid set of template args from current_template_parms. */
+
+tree
+current_template_args ()
+{
+ tree header = current_template_parms;
+ int length = list_length (header);
+ tree args = make_tree_vec (length);
+ int l = length;
+
+ while (header)
{
- tree p = TREE_VALUE (parm);
- if (TREE_PURPOSE (parm))
- saw_default = 1;
- else if (saw_default)
+ tree a = copy_node (TREE_VALUE (header));
+ int i = TREE_VEC_LENGTH (a);
+ TREE_TYPE (a) = NULL_TREE;
+ while (i--)
{
- error ("if a default argument is given for one template parameter");
- error ("default arguments must be given for all subsequent");
- error ("parameters as well");
+ tree t = TREE_VEC_ELT (a, i);
+
+ /* t will be a list if we are called from within a
+ begin/end_template_parm_list pair, but a vector directly
+ if within a begin/end_member_template_processing pair. */
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ t = TREE_VALUE (t);
+
+ if (TREE_CODE (t) == TYPE_DECL
+ || TREE_CODE (t) == TEMPLATE_DECL)
+ t = TREE_TYPE (t);
+ else
+ t = DECL_INITIAL (t);
+ }
+
+ TREE_VEC_ELT (a, i) = t;
}
+ TREE_VEC_ELT (args, --l) = a;
+ header = TREE_CHAIN (header);
+ }
- if (TREE_CODE (p) == TYPE_DECL)
+ return args;
+}
+
+
+/* Return a TEMPLATE_DECL corresponding to DECL, using the indicated
+ template PARMS. Used by push_template_decl below. */
+
+static tree
+build_template_decl (decl, parms)
+ tree decl;
+ tree parms;
+{
+ tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
+ DECL_TEMPLATE_PARMS (tmpl) = parms;
+ DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
+ if (DECL_LANG_SPECIFIC (decl))
+ {
+ DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl);
+ DECL_STATIC_FUNCTION_P (tmpl) =
+ DECL_STATIC_FUNCTION_P (decl);
+ }
+
+ return tmpl;
+}
+
+struct template_parm_data
+{
+ int level;
+ int* parms;
+};
+
+/* Subroutine of push_template_decl used to see if each template
+ parameter in a partial specialization is used in the explicit
+ argument list. If T is of the LEVEL given in DATA (which is
+ treated as a template_parm_data*), then DATA->PARMS is marked
+ appropriately. */
+
+static int
+mark_template_parm (t, data)
+ tree t;
+ void* data;
+{
+ int level;
+ int idx;
+ struct template_parm_data* tpd = (struct template_parm_data*) data;
+
+ if (TREE_CODE (t) == TEMPLATE_PARM_INDEX)
+ {
+ level = TEMPLATE_PARM_LEVEL (t);
+ idx = TEMPLATE_PARM_IDX (t);
+ }
+ else
+ {
+ level = TEMPLATE_TYPE_LEVEL (t);
+ idx = TEMPLATE_TYPE_IDX (t);
+ }
+
+ if (level == tpd->level)
+ tpd->parms[idx] = 1;
+
+ /* Return zero so that for_each_template_parm will continue the
+ traversal of the tree; we want to mark *every* template parm. */
+ return 0;
+}
+
+/* Creates a TEMPLATE_DECL for the indicated DECL using the template
+ parameters given by current_template_args, or reuses a
+ previously existing one, if appropriate. Returns the DECL, or an
+ equivalent one, if it is replaced via a call to duplicate_decls.
+
+ If IS_FRIEND is non-zero, DECL is a friend declaration. */
+
+tree
+push_template_decl_real (decl, is_friend)
+ tree decl;
+ int is_friend;
+{
+ tree tmpl;
+ tree args;
+ tree info;
+ tree ctx;
+ int primary;
+
+ is_friend |= (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl));
+
+ if (is_friend)
+ /* For a friend, we want the context of the friend function, not
+ the type of which it is a friend. */
+ ctx = DECL_CONTEXT (decl);
+ else if (DECL_REAL_CONTEXT (decl)
+ && TREE_CODE (DECL_REAL_CONTEXT (decl)) != NAMESPACE_DECL)
+ /* In the case of a virtual function, we want the class in which
+ it is defined. */
+ ctx = DECL_REAL_CONTEXT (decl);
+ else
+ /* Otherwise, if we're currently definining some class, the DECL
+ is assumed to be a member of the class. */
+ ctx = current_class_type;
+
+ if (ctx && TREE_CODE (ctx) == NAMESPACE_DECL)
+ ctx = NULL_TREE;
+
+ if (!DECL_CONTEXT (decl))
+ DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+
+ /* For determining whether this is a primary template or not, we're really
+ interested in the lexical context, not the true context. */
+ if (is_friend)
+ /* For a TYPE_DECL, there is no DECL_CLASS_CONTEXT. */
+ info = TREE_CODE (decl) == FUNCTION_DECL
+ ? DECL_CLASS_CONTEXT (decl) : current_class_type;
+ else
+ info = ctx;
+
+ if (info && TREE_CODE (info) == FUNCTION_DECL)
+ primary = 0;
+ /* Note that template_class_depth returns 0 if given NULL_TREE, so
+ this next line works even when we are at global scope. */
+ else if (processing_template_decl > template_class_depth (info))
+ primary = 1;
+ else
+ primary = 0;
+
+ if (primary)
+ {
+ if (current_lang_name == lang_name_c)
+ cp_error ("template with C linkage");
+ if (TREE_CODE (decl) == TYPE_DECL && ANON_AGGRNAME_P (DECL_NAME (decl)))
+ cp_error ("template class without a name");
+ }
+
+ /* Partial specialization. */
+ if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ {
+ tree type = TREE_TYPE (decl);
+ tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
+ tree mainargs = CLASSTYPE_TI_ARGS (type);
+ tree spec = DECL_TEMPLATE_SPECIALIZATIONS (maintmpl);
+
+ /* We check that each of the template parameters given in the
+ partial specialization is used in the argument list to the
+ specialization. For example:
+
+ template <class T> struct S;
+ template <class T> struct S<T*>;
+
+ The second declaration is OK because `T*' uses the template
+ parameter T, whereas
+
+ template <class T> struct S<int>;
+
+ is no good. Even trickier is:
+
+ template <class T>
+ struct S1
+ {
+ template <class U>
+ struct S2;
+ template <class U>
+ struct S2<T>;
+ };
+
+ The S2<T> declaration is actually illegal; it is a
+ full-specialization. Of course,
+
+ template <class U>
+ struct S2<T (*)(U)>;
+
+ or some such would have been OK. */
+ int i;
+ struct template_parm_data tpd;
+ int ntparms = TREE_VEC_LENGTH (TREE_VALUE (current_template_parms));
+ int did_error_intro = 0;
+
+ tpd.level = TREE_INT_CST_HIGH (TREE_PURPOSE (current_template_parms));
+ tpd.parms = alloca (sizeof (int) * ntparms);
+ for (i = 0; i < ntparms; ++i)
+ tpd.parms[i] = 0;
+ for (i = 0; i < TREE_VEC_LENGTH (mainargs); ++i)
+ for_each_template_parm (TREE_VEC_ELT (mainargs, i),
+ &mark_template_parm,
+ &tpd);
+ for (i = 0; i < ntparms; ++i)
+ if (tpd.parms[i] == 0)
+ {
+ /* One of the template parms was not used in the
+ specialization. */
+ if (!did_error_intro)
+ {
+ cp_error ("template parameters not used in partial specialization:");
+ did_error_intro = 1;
+ }
+
+ cp_error (" `%D'",
+ TREE_VALUE (TREE_VEC_ELT
+ (TREE_VALUE (current_template_parms),
+ i)));
+ }
+
+ for (; spec; spec = TREE_CHAIN (spec))
{
- tree t = TREE_TYPE (p);
- TEMPLATE_TYPE_SET_INFO (t, saved_parmlist, nparms);
+ /* purpose: args to main template
+ value: spec template */
+ if (comp_template_args (TREE_PURPOSE (spec), mainargs))
+ return decl;
}
+
+ DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type)
+ = perm_tree_cons (mainargs, TREE_VALUE (current_template_parms),
+ DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
+ TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
+ return decl;
+ }
+
+ args = current_template_args ();
+
+ if (!ctx
+ || TREE_CODE (ctx) == FUNCTION_DECL
+ || TYPE_BEING_DEFINED (ctx)
+ || (is_friend && !DECL_TEMPLATE_INFO (decl)))
+ {
+ if (DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INFO (decl)
+ && DECL_TI_TEMPLATE (decl))
+ tmpl = DECL_TI_TEMPLATE (decl);
else
{
- tree tinfo = DECL_INITIAL (p);
- DECL_INITIAL (p) = NULL_TREE;
- TEMPLATE_CONST_SET_INFO (tinfo, saved_parmlist, nparms);
+ tmpl = build_template_decl (decl, current_template_parms);
+
+ if (DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_SPECIALIZATION (decl))
+ {
+ /* A specialization of a member template of a template
+ class. */
+ SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
+ DECL_TEMPLATE_INFO (tmpl) = DECL_TEMPLATE_INFO (decl);
+ DECL_TEMPLATE_INFO (decl) = NULL_TREE;
+ }
}
- TREE_VEC_ELT (saved_parmlist, nparms) = parm;
}
- set_current_level_tags_transparency (1);
- processing_template_decl++;
- return saved_parmlist;
+ else
+ {
+ tree t;
+ tree a;
+
+ if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
+ cp_error ("must specialize `%#T' before defining member `%#D'",
+ ctx, decl);
+ if (TREE_CODE (decl) == TYPE_DECL)
+ {
+ if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
+ && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl))
+ && CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)))
+ tmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
+ else
+ {
+ cp_error ("`%D' does not declare a template type", decl);
+ return decl;
+ }
+ }
+ else if (! DECL_TEMPLATE_INFO (decl))
+ {
+ cp_error ("template definition of non-template `%#D'", decl);
+ return decl;
+ }
+ else
+ tmpl = DECL_TI_TEMPLATE (decl);
+
+ if (is_member_template (tmpl) || is_member_template_class (tmpl))
+ {
+ if (DECL_FUNCTION_TEMPLATE_P (tmpl)
+ && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
+ && DECL_TEMPLATE_SPECIALIZATION (decl))
+ {
+ tree new_tmpl;
+
+ /* The declaration is a specialization of a member
+ template, declared outside the class. Therefore, the
+ innermost template arguments will be NULL, so we
+ replace them with the arguments determined by the
+ earlier call to check_explicit_specialization. */
+ args = DECL_TI_ARGS (decl);
+
+ new_tmpl
+ = build_template_decl (decl, current_template_parms);
+ DECL_TEMPLATE_RESULT (new_tmpl) = decl;
+ TREE_TYPE (new_tmpl) = TREE_TYPE (decl);
+ DECL_TI_TEMPLATE (decl) = new_tmpl;
+ SET_DECL_TEMPLATE_SPECIALIZATION (new_tmpl);
+ DECL_TEMPLATE_INFO (new_tmpl) =
+ perm_tree_cons (tmpl, args, NULL_TREE);
+
+ register_specialization (new_tmpl, tmpl, args);
+ return decl;
+ }
+
+ a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+ t = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
+ if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
+ {
+ cp_error ("got %d template parameters for `%#D'",
+ TREE_VEC_LENGTH (a), decl);
+ cp_error (" but %d required", TREE_VEC_LENGTH (t));
+ }
+ if (TREE_VEC_LENGTH (args) > 1)
+ /* Get the template parameters for the enclosing template
+ class. */
+ a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 2);
+ else
+ a = NULL_TREE;
+ }
+ else
+ a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+
+ t = NULL_TREE;
+
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
+ {
+ /* When processing an inline member template of a
+ specialized class, there is no CLASSTYPE_TI_SPEC_INFO. */
+ if (CLASSTYPE_TI_SPEC_INFO (ctx))
+ t = TREE_VALUE (CLASSTYPE_TI_SPEC_INFO (ctx));
+ }
+ else if (CLASSTYPE_TEMPLATE_INFO (ctx))
+ t = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (ctx));
+
+ /* There should be template arguments if and only if there is a
+ template class. */
+ my_friendly_assert((a != NULL_TREE) == (t != NULL_TREE), 0);
+
+ if (t != NULL_TREE
+ && TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
+ {
+ cp_error ("got %d template parameters for `%#D'",
+ TREE_VEC_LENGTH (a), decl);
+ cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t));
+ }
+ }
+ /* Get the innermost set of template arguments. We don't do this
+ for a non-template member function of a nested template class
+ because there we will never get a `partial instantiation' of the
+ function containing the outer arguments, and so we must save all
+ of the arguments here. */
+ if (TREE_CODE (decl) != FUNCTION_DECL
+ || template_class_depth (ctx) <= 1
+ || primary)
+ args = innermost_args (args, 0);
+
+ DECL_TEMPLATE_RESULT (tmpl) = decl;
+ TREE_TYPE (tmpl) = TREE_TYPE (decl);
+
+ if (! ctx && !(is_friend && template_class_depth (info) > 0))
+ /* Note that we do not try to push a global template friend
+ declared in a template class; such a thing may well depend on
+ the template parameters of the class. */
+ tmpl = pushdecl_namespace_level (tmpl);
+
+ if (primary)
+ DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+
+ info = perm_tree_cons (tmpl, args, NULL_TREE);
+
+ if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+ {
+ CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info;
+ if (!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
+ DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
+ }
+ else if (! DECL_LANG_SPECIFIC (decl))
+ cp_error ("template declaration of `%#D'", decl);
+ else
+ DECL_TEMPLATE_INFO (decl) = info;
+
+ return DECL_TEMPLATE_RESULT (tmpl);
}
-/* end_template_decl is called after a template declaration is seen.
- D1 is template header; D2 is class_head_sans_basetype or a
- TEMPLATE_DECL with its DECL_RESULT field set. */
-void
-end_template_decl (d1, d2, is_class, defn)
- tree d1, d2, is_class;
- int defn;
+tree
+push_template_decl (decl)
+ tree decl;
{
- tree decl;
- struct template_info *tmpl;
+ return push_template_decl_real (decl, 0);
+}
- tmpl = (struct template_info *) obstack_alloc (&permanent_obstack,
- sizeof (struct template_info));
- tmpl->text = 0;
- tmpl->length = 0;
- tmpl->aggr = is_class;
+/* Called when a class template TYPE is redeclared with the indicated
+ template PARMS, e.g.:
- /* cloned from reinit_parse_for_template */
- tmpl->filename = input_filename;
- tmpl->lineno = lineno;
- tmpl->parm_vec = d1; /* [eichin:19911015.2306EST] */
+ template <class T> struct S;
+ template <class T> struct S {}; */
- if (d2 == NULL_TREE || d2 == error_mark_node)
+void
+redeclare_class_template (type, parms)
+ tree type;
+ tree parms;
+{
+ tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
+ tree tmpl_parms;
+ int i;
+
+ if (!PRIMARY_TEMPLATE_P (tmpl))
+ /* The type is nested in some template class. Nothing to worry
+ about here; there are no new template parameters for the nested
+ type. */
+ return;
+
+ parms = INNERMOST_TEMPLATE_PARMS (parms);
+ tmpl_parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
+
+ if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms))
{
- decl = 0;
- goto lose;
+ cp_error_at ("previous declaration `%D'", tmpl);
+ cp_error ("used %d template parameter%s instead of %d",
+ TREE_VEC_LENGTH (tmpl_parms),
+ TREE_VEC_LENGTH (tmpl_parms) == 1 ? "" : "s",
+ TREE_VEC_LENGTH (parms));
+ return;
}
- if (is_class)
+ for (i = 0; i < TREE_VEC_LENGTH (tmpl_parms); ++i)
{
- decl = build_lang_decl (TEMPLATE_DECL, d2, NULL_TREE);
- GNU_xref_decl (current_function_decl, decl);
+ tree tmpl_parm = TREE_VALUE (TREE_VEC_ELT (tmpl_parms, i));
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+ tree tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i));
+ tree parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
+
+ if (TREE_CODE (tmpl_parm) != TREE_CODE (parm))
+ {
+ cp_error_at ("template parameter `%#D'", tmpl_parm);
+ cp_error ("redeclared here as `%#D'", parm);
+ return;
+ }
+
+ if (tmpl_default != NULL_TREE && parm_default != NULL_TREE)
+ {
+ /* We have in [temp.param]:
+
+ A template-parameter may not be given default arguments
+ by two different declarations in the same scope. */
+ cp_error ("redefinition of default argument for `%#D'", parm);
+ cp_error_at (" original definition appeared here", tmpl_parm);
+ return;
+ }
+
+ if (parm_default != NULL_TREE)
+ /* Update the previous template parameters (which are the ones
+ that will really count) with the new default value. */
+ TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i)) = parm_default;
}
- else
+}
+
+/* Attempt to convert the non-type template parameter EXPR to the
+ indicated TYPE. If the conversion is successful, return the
+ converted value. If the conversion is unsuccesful, return
+ NULL_TREE if we issued an error message, or error_mark_node if we
+ did not. We issue error messages for out-and-out bad template
+ parameters, but not simply because the conversion failed, since we
+ might be just trying to do argument deduction. By the time this
+ function is called, neither TYPE nor EXPR may make use of template
+ parameters. */
+
+static tree
+convert_nontype_argument (type, expr)
+ tree type;
+ tree expr;
+{
+ tree expr_type = TREE_TYPE (expr);
+
+ /* A template-argument for a non-type, non-template
+ template-parameter shall be one of:
+
+ --an integral constant-expression of integral or enumeration
+ type; or
+
+ --the name of a non-type template-parameter; or
+
+ --the name of an object or function with external linkage,
+ including function templates and function template-ids but
+ excluding non-static class members, expressed as id-expression;
+ or
+
+ --the address of an object or function with external linkage,
+ including function templates and function template-ids but
+ excluding non-static class members, expressed as & id-expression
+ where the & is optional if the name refers to a function or
+ array; or
+
+ --a pointer to member expressed as described in _expr.unary.op_. */
+
+ /* An integral constant-expression can include const variables
+ or enumerators. */
+ if (INTEGRAL_TYPE_P (expr_type) && TREE_READONLY_DECL_P (expr))
+ expr = decl_constant_value (expr);
+
+ if (is_overloaded_fn (expr))
+ /* OK for now. We'll check that it has external linkage later.
+ Check this first since if expr_type is the unknown_type_node
+ we would otherwise complain below. */
+ ;
+ else if (INTEGRAL_TYPE_P (expr_type)
+ || TYPE_PTRMEM_P (expr_type)
+ || TYPE_PTRMEMFUNC_P (expr_type)
+ /* The next two are g++ extensions. */
+ || TREE_CODE (expr_type) == REAL_TYPE
+ || TREE_CODE (expr_type) == COMPLEX_TYPE)
{
- if (TREE_CODE (d2) == TEMPLATE_DECL)
- decl = d2;
- else
+ if (! TREE_CONSTANT (expr))
{
- /* Class destructor templates and operator templates are
- slipping past as non-template nodes. Process them here, since
- I haven't figured out where to catch them earlier. I could
- go do that, but it's a choice between getting that done and
- staying only N months behind schedule. Sorry.... */
- enum tree_code code;
- my_friendly_assert (TREE_CODE (d2) == CALL_EXPR, 263);
- code = TREE_CODE (TREE_OPERAND (d2, 0));
- my_friendly_assert (code == BIT_NOT_EXPR
- || code == OP_IDENTIFIER
- || code == SCOPE_REF, 264);
- d2 = grokdeclarator (d2, NULL_TREE, MEMFUNCDEF, 0, NULL_TREE, NULL_TREE);
- decl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (d2),
- TREE_TYPE (d2));
- DECL_TEMPLATE_RESULT (decl) = d2;
- DECL_CONTEXT (decl) = DECL_CONTEXT (d2);
- DECL_CLASS_CONTEXT (decl) = DECL_CLASS_CONTEXT (d2);
- DECL_NAME (decl) = DECL_NAME (d2);
- TREE_TYPE (decl) = TREE_TYPE (d2);
- if (interface_unknown && flag_external_templates
- && ! flag_alt_external_templates
- && ! DECL_IN_SYSTEM_HEADER (decl))
- warn_if_unknown_interface (decl);
- TREE_PUBLIC (decl) = TREE_PUBLIC (d2) = flag_external_templates && !interface_unknown;
- DECL_EXTERNAL (decl) = (DECL_EXTERNAL (d2)
- && !(DECL_CLASS_CONTEXT (d2)
- && !DECL_THIS_EXTERN (d2)));
- }
-
- /* All routines creating TEMPLATE_DECL nodes should now be using
- build_lang_decl, which will have set this up already. */
- my_friendly_assert (DECL_LANG_SPECIFIC (decl) != 0, 265);
-
- /* @@ Somewhere, permanent allocation isn't being used. */
- if (! DECL_TEMPLATE_IS_CLASS (decl)
- && TREE_CODE (DECL_TEMPLATE_RESULT (decl)) == FUNCTION_DECL)
- {
- tree result = DECL_TEMPLATE_RESULT (decl);
- /* Will do nothing if allocation was already permanent. */
- DECL_ARGUMENTS (result) = copy_to_permanent (DECL_ARGUMENTS (result));
- }
-
- /* If this is for a method, there's an extra binding level here. */
- if (DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
- {
- /* @@ Find out where this should be getting set! */
- tree r = DECL_TEMPLATE_RESULT (decl);
- if (DECL_LANG_SPECIFIC (r) && DECL_CLASS_CONTEXT (r) == NULL_TREE)
- DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
+ non_constant:
+ cp_error ("non-constant `%E' cannot be used as template argument",
+ expr);
+ return NULL_TREE;
}
}
- DECL_TEMPLATE_INFO (decl) = tmpl;
- DECL_TEMPLATE_PARMS (decl) = d1;
+ else if (TYPE_PTR_P (expr_type)
+ /* If expr is the address of an overloaded function, we
+ will get the unknown_type_node at this point. */
+ || expr_type == unknown_type_node)
+ {
+ tree referent;
+ tree e = expr;
+ STRIP_NOPS (e);
- /* So that duplicate_decls can do the right thing. */
- if (defn)
- DECL_INITIAL (decl) = error_mark_node;
-
- /* If context of decl is non-null (i.e., method template), add it
- to the appropriate class template, and pop the binding levels. */
- if (! is_class && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
- {
- tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl));
- tree tmpl, t;
- my_friendly_assert (TREE_CODE (ctx) == UNINSTANTIATED_P_TYPE, 266);
- tmpl = UPT_TEMPLATE (ctx);
- for (t = DECL_TEMPLATE_MEMBERS (tmpl); t; t = TREE_CHAIN (t))
- if (TREE_PURPOSE (t) == DECL_NAME (decl)
- && duplicate_decls (decl, TREE_VALUE (t)))
- goto already_there;
- DECL_TEMPLATE_MEMBERS (tmpl) =
- perm_tree_cons (DECL_NAME (decl), decl, DECL_TEMPLATE_MEMBERS (tmpl));
- already_there:
- poplevel (0, 0, 0);
- poplevel (0, 0, 0);
+ if (TREE_CODE (e) != ADDR_EXPR)
+ {
+ bad_argument:
+ cp_error ("`%E' is not a valid template argument", expr);
+ error ("it must be %s%s with external linkage",
+ TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
+ ? "a pointer to " : "",
+ TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == FUNCTION_TYPE
+ ? "a function" : "an object");
+ return NULL_TREE;
+ }
+
+ referent = TREE_OPERAND (e, 0);
+ STRIP_NOPS (referent);
+
+ if (TREE_CODE (referent) == STRING_CST)
+ {
+ cp_error ("string literal %E is not a valid template argument",
+ referent);
+ error ("because it is the address of an object with static linkage");
+ return NULL_TREE;
+ }
+
+ if (is_overloaded_fn (referent))
+ /* We'll check that it has external linkage later. */
+ ;
+ else if (TREE_CODE (referent) != VAR_DECL)
+ goto bad_argument;
+ else if (!TREE_PUBLIC (referent))
+ {
+ cp_error ("address of non-extern `%E' cannot be used as template argument", referent);
+ return error_mark_node;
+ }
}
- /* Otherwise, go back to top level first, and push the template decl
- again there. */
- else
+ else if (TREE_CODE (expr) == VAR_DECL)
{
- poplevel (0, 0, 0);
- poplevel (0, 0, 0);
- pushdecl (decl);
+ if (!TREE_PUBLIC (expr))
+ goto bad_argument;
+ }
+ else
+ {
+ cp_error ("object `%E' cannot be used as template argument", expr);
+ return NULL_TREE;
}
- lose:
-#if 0 /* It happens sometimes, with syntactic or semantic errors.
- One specific case:
- template <class A, int X, int Y> class Foo { ... };
- template <class A, int X, int y> Foo<X,Y>::method (Foo& x) { ... }
- Note the missing "A" in the class containing "method". */
- my_friendly_assert (global_bindings_p (), 267);
-#else
- while (! global_bindings_p ())
- poplevel (0, 0, 0);
-#endif
- pop_obstacks ();
- processing_template_decl--;
- (void) get_pending_sizes ();
+ switch (TREE_CODE (type))
+ {
+ case INTEGER_TYPE:
+ case BOOLEAN_TYPE:
+ case ENUMERAL_TYPE:
+ /* For a non-type template-parameter of integral or enumeration
+ type, integral promotions (_conv.prom_) and integral
+ conversions (_conv.integral_) are applied. */
+ if (!INTEGRAL_TYPE_P (expr_type))
+ return error_mark_node;
+
+ /* It's safe to call digest_init in this case; we know we're
+ just converting one integral constant expression to another. */
+ expr = digest_init (type, expr, (tree*) 0);
+
+ if (TREE_CODE (expr) != INTEGER_CST)
+ /* Curiously, some TREE_CONSTNAT integral expressions do not
+ simplify to integer constants. For example, `3 % 0',
+ remains a TRUNC_MOD_EXPR. */
+ goto non_constant;
+
+ return expr;
+
+ case REAL_TYPE:
+ case COMPLEX_TYPE:
+ /* These are g++ extensions. */
+ if (TREE_CODE (expr_type) != TREE_CODE (type))
+ return error_mark_node;
+
+ expr = digest_init (type, expr, (tree*) 0);
+
+ if (TREE_CODE (expr) != REAL_CST)
+ goto non_constant;
+
+ return expr;
+
+ case POINTER_TYPE:
+ {
+ tree type_pointed_to = TREE_TYPE (type);
+
+ if (TYPE_PTRMEM_P (type))
+ /* For a non-type template-parameter of type pointer to data
+ member, qualification conversions (_conv.qual_) are
+ applied. */
+ return perform_qualification_conversions (type, expr);
+ else if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE)
+ {
+ /* For a non-type template-parameter of type pointer to
+ function, only the function-to-pointer conversion
+ (_conv.func_) is applied. If the template-argument
+ represents a set of overloaded functions (or a pointer to
+ such), the matching function is selected from the set
+ (_over.over_). */
+ tree fns;
+ tree fn;
+
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ fns = TREE_OPERAND (expr, 0);
+ else
+ fns = expr;
+
+ fn = instantiate_type (type_pointed_to, fns, 0);
+
+ if (fn == error_mark_node)
+ return error_mark_node;
+
+ if (!TREE_PUBLIC (fn))
+ {
+ if (really_overloaded_fn (fns))
+ return error_mark_node;
+ else
+ goto bad_argument;
+ }
+
+ expr = build_unary_op (ADDR_EXPR, fn, 0);
+
+ my_friendly_assert (comptypes (type, TREE_TYPE (expr), 1),
+ 0);
+ return expr;
+ }
+ else
+ {
+ /* For a non-type template-parameter of type pointer to
+ object, qualification conversions (_conv.qual_) and the
+ array-to-pointer conversion (_conv.array_) are applied.
+ [Note: In particular, neither the null pointer conversion
+ (_conv.ptr_) nor the derived-to-base conversion
+ (_conv.ptr_) are applied. Although 0 is a valid
+ template-argument for a non-type template-parameter of
+ integral type, it is not a valid template-argument for a
+ non-type template-parameter of pointer type.]
+
+ The call to decay_conversion performs the
+ array-to-pointer conversion, if appropriate. */
+ expr = decay_conversion (expr);
+
+ if (expr == error_mark_node)
+ return error_mark_node;
+ else
+ return perform_qualification_conversions (type, expr);
+ }
+ }
+ break;
+
+ case REFERENCE_TYPE:
+ {
+ tree type_referred_to = TREE_TYPE (type);
+
+ if (TREE_CODE (type_referred_to) == FUNCTION_TYPE)
+ {
+ /* For a non-type template-parameter of type reference to
+ function, no conversions apply. If the
+ template-argument represents a set of overloaded
+ functions, the matching function is selected from the
+ set (_over.over_). */
+ tree fns = expr;
+ tree fn;
+
+ fn = instantiate_type (type_referred_to, fns, 0);
+
+ if (!TREE_PUBLIC (fn))
+ {
+ if (really_overloaded_fn (fns))
+ /* Don't issue an error here; we might get a different
+ function if the overloading had worked out
+ differently. */
+ return error_mark_node;
+ else
+ goto bad_argument;
+ }
+
+ if (fn == error_mark_node)
+ return error_mark_node;
+
+ my_friendly_assert (comptypes (type, TREE_TYPE (fn), 1),
+ 0);
+
+ return fn;
+ }
+ else
+ {
+ /* For a non-type template-parameter of type reference to
+ object, no conversions apply. The type referred to by the
+ reference may be more cv-qualified than the (otherwise
+ identical) type of the template-argument. The
+ template-parameter is bound directly to the
+ template-argument, which must be an lvalue. */
+ if (!comptypes (TYPE_MAIN_VARIANT (expr_type),
+ TYPE_MAIN_VARIANT (type), 1)
+ || (TYPE_READONLY (expr_type) >
+ TYPE_READONLY (type_referred_to))
+ || (TYPE_VOLATILE (expr_type) >
+ TYPE_VOLATILE (type_referred_to))
+ || !real_lvalue_p (expr))
+ return error_mark_node;
+ else
+ return expr;
+ }
+ }
+ break;
+
+ case RECORD_TYPE:
+ {
+ tree fns;
+ tree fn;
+
+ if (!TYPE_PTRMEMFUNC_P (type))
+ /* This handles templates like
+ template<class T, T t> void f();
+ when T is substituted with any class. The second template
+ parameter becomes invalid and the template candidate is
+ rejected. */
+ return error_mark_node;
+
+ /* For a non-type template-parameter of type pointer to member
+ function, no conversions apply. If the template-argument
+ represents a set of overloaded member functions, the
+ matching member function is selected from the set
+ (_over.over_). */
+
+ if (!TYPE_PTRMEMFUNC_P (expr_type) &&
+ expr_type != unknown_type_node)
+ return error_mark_node;
+
+ if (TREE_CODE (expr) == CONSTRUCTOR)
+ {
+ /* A ptr-to-member constant. */
+ if (!comptypes (type, expr_type, 1))
+ return error_mark_node;
+ else
+ return expr;
+ }
+
+ if (TREE_CODE (expr) != ADDR_EXPR)
+ return error_mark_node;
+
+ fns = TREE_OPERAND (expr, 0);
+
+ fn = instantiate_type (TREE_TYPE (TREE_TYPE (type)),
+ fns, 0);
+
+ if (fn == error_mark_node)
+ return error_mark_node;
+
+ expr = build_unary_op (ADDR_EXPR, fn, 0);
+
+ my_friendly_assert (comptypes (type, TREE_TYPE (expr), 1),
+ 0);
+ return expr;
+ }
+ break;
+
+ default:
+ /* All non-type parameters must have one of these types. */
+ my_friendly_abort (0);
+ break;
+ }
+
+ return error_mark_node;
}
-tree tsubst PROTO ((tree, tree*, int, tree));
+/* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for
+ template template parameters. Both PARM_PARMS and ARG_PARMS are
+ vectors of TREE_LIST nodes containing TYPE_DECL, TEMPLATE_DECL
+ or PARM_DECL.
+
+ ARG_PARMS may contain more parameters than PARM_PARMS. If this is
+ the case, then extra parameters must have default arguments.
+
+ Consider the example:
+ template <class T, class Allocator = allocator> class vector;
+ template<template <class U> class TT> class C;
+
+ C<vector> is a valid instantiation. PARM_PARMS for the above code
+ contains a TYPE_DECL (for U), ARG_PARMS contains two TYPE_DECLs (for
+ T and Allocator) and OUTER_ARGS contains the argument that is used to
+ substitute the TT parameter. */
+
+static int
+coerce_template_template_parms (parm_parms, arg_parms, in_decl, outer_args)
+ tree parm_parms, arg_parms, in_decl, outer_args;
+{
+ int nparms, nargs, i;
+ tree parm, arg;
+
+ my_friendly_assert (TREE_CODE (parm_parms) == TREE_VEC, 0);
+ my_friendly_assert (TREE_CODE (arg_parms) == TREE_VEC, 0);
+
+ nparms = TREE_VEC_LENGTH (parm_parms);
+ nargs = TREE_VEC_LENGTH (arg_parms);
+
+ /* The rule here is opposite of coerce_template_parms. */
+ if (nargs < nparms
+ || (nargs > nparms
+ && TREE_PURPOSE (TREE_VEC_ELT (arg_parms, nparms)) == NULL_TREE))
+ return 0;
+
+ for (i = 0; i < nparms; ++i)
+ {
+ parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
+ arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
+
+ if (arg == NULL_TREE || arg == error_mark_node
+ || parm == NULL_TREE || parm == error_mark_node)
+ return 0;
+
+ if (TREE_CODE (arg) != TREE_CODE (parm))
+ return 0;
+
+ switch (TREE_CODE (parm))
+ {
+ case TYPE_DECL:
+ break;
+
+ case TEMPLATE_DECL:
+ /* We encounter instantiations of templates like
+ template <template <template <class> class> class TT>
+ class C; */
+ sorry ("nested template template parameter");
+ return 0;
+
+ case PARM_DECL:
+ /* The tsubst call is used to handle cases such as
+ template <class T, template <T> class TT> class D;
+ i.e. the parameter list of TT depends on earlier parameters. */
+ if (!comptypes (tsubst (TREE_TYPE (parm), outer_args, in_decl),
+ TREE_TYPE (arg), 1))
+ return 0;
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
+ }
+ return 1;
+}
/* Convert all template arguments to their appropriate types, and return
a vector containing the resulting values. If any error occurs, return
- error_mark_node. */
+ error_mark_node, and, if COMPLAIN is non-zero, issue an error message.
+ Some error messages are issued even if COMPLAIN is zero; for
+ instance, if a template argument is composed from a local class.
+
+ If REQUIRE_ALL_ARGUMENTS is non-zero, all arguments must be
+ provided in ARGLIST, or else trailing parameters must have default
+ values. If REQUIRE_ALL_ARGUMENTS is zero, we will attempt argument
+ deduction for any unspecified trailing arguments. */
+
static tree
-coerce_template_parms (parms, arglist, in_decl)
+coerce_template_parms (parms, arglist, in_decl,
+ complain,
+ require_all_arguments)
tree parms, arglist;
tree in_decl;
+ int complain;
+ int require_all_arguments;
{
int nparms, nargs, i, lost = 0;
- tree vec;
+ tree vec = NULL_TREE;
if (arglist == NULL_TREE)
nargs = 0;
@@ -352,25 +2472,34 @@ coerce_template_parms (parms, arglist, in_decl)
if (nargs > nparms
|| (nargs < nparms
+ && require_all_arguments
&& TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE))
{
- error ("incorrect number of parameters (%d, should be %d)",
- nargs, nparms);
- if (in_decl)
- cp_error_at ("in template expansion for decl `%D'", in_decl);
+ if (complain)
+ {
+ error ("incorrect number of parameters (%d, should be %d)",
+ nargs, nparms);
+
+ if (in_decl)
+ cp_error_at ("in template expansion for decl `%D'",
+ in_decl);
+ }
+
return error_mark_node;
}
- if (arglist && TREE_CODE (arglist) == TREE_VEC)
+ if (arglist && TREE_CODE (arglist) == TREE_VEC && nargs == nparms)
vec = copy_node (arglist);
else
{
vec = make_tree_vec (nparms);
+
for (i = 0; i < nparms; i++)
{
tree arg;
+ tree parm = TREE_VEC_ELT (parms, i);
- if (arglist)
+ if (arglist && TREE_CODE (arglist) == TREE_LIST)
{
arg = arglist;
arglist = TREE_CHAIN (arglist);
@@ -380,8 +2509,21 @@ coerce_template_parms (parms, arglist, in_decl)
else
arg = TREE_VALUE (arg);
}
+ else if (i < nargs)
+ {
+ arg = TREE_VEC_ELT (arglist, i);
+ if (arg == error_mark_node)
+ lost++;
+ }
+ else if (TREE_PURPOSE (parm) == NULL_TREE)
+ {
+ my_friendly_assert (!require_all_arguments, 0);
+ break;
+ }
+ else if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
+ arg = tsubst (TREE_PURPOSE (parm), vec, in_decl);
else
- arg = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
+ arg = tsubst_expr (TREE_PURPOSE (parm), vec, in_decl);
TREE_VEC_ELT (vec, i) = arg;
}
@@ -391,77 +2533,184 @@ coerce_template_parms (parms, arglist, in_decl)
tree arg = TREE_VEC_ELT (vec, i);
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
tree val = 0;
- int is_type, requires_type;
+ int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
- is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
- requires_type = TREE_CODE (parm) == TYPE_DECL;
+ if (arg == NULL_TREE)
+ /* We're out of arguments. */
+ {
+ my_friendly_assert (!require_all_arguments, 0);
+ break;
+ }
+
+ if (arg == error_mark_node)
+ {
+ cp_error ("template argument %d is invalid", i + 1);
+ lost++;
+ continue;
+ }
+
+ if (TREE_CODE (arg) == TREE_LIST
+ && TREE_TYPE (arg) != NULL_TREE
+ && TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
+ {
+ /* The template argument was the name of some
+ member function. That's usually
+ illegal, but static members are OK. In any
+ case, grab the underlying fields/functions
+ and issue an error later if required. */
+ arg = TREE_VALUE (arg);
+ TREE_TYPE (arg) = unknown_type_node;
+ }
+
+ requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;
+ requires_type = TREE_CODE (parm) == TYPE_DECL
+ || requires_tmpl_type;
+
+ /* Check if it is a class template. If REQUIRES_TMPL_TYPE is true,
+ we also accept implicitly created TYPE_DECL as a valid argument.
+ This is necessary to handle the case where we pass a template name
+ to a template template parameter in a scope where we've derived from
+ in instantiation of that template, so the template name refers to that
+ instantiation. We really ought to handle this better. */
+ is_tmpl_type = (TREE_CODE (arg) == TEMPLATE_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
+ || (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ && !CLASSTYPE_TEMPLATE_INFO (arg))
+ || (TREE_CODE (arg) == RECORD_TYPE
+ && CLASSTYPE_TEMPLATE_INFO (arg)
+ && TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
+ && DECL_ARTIFICIAL (TYPE_NAME (arg))
+ && requires_tmpl_type
+ && current_class_type
+ /* FIXME what about nested types? */
+ && get_binfo (arg, current_class_type, 0));
+ if (is_tmpl_type && TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ arg = TYPE_STUB_DECL (arg);
+ else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
+ arg = CLASSTYPE_TI_TEMPLATE (arg);
+
+ is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't' || is_tmpl_type;
+
+ if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
+ && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
+ {
+ cp_pedwarn ("to refer to a type member of a template parameter,");
+ cp_pedwarn (" use `typename %E'", arg);
+
+ arg = make_typename_type (TREE_OPERAND (arg, 0),
+ TREE_OPERAND (arg, 1));
+ is_type = 1;
+ }
if (is_type != requires_type)
{
if (in_decl)
- cp_error ("type/value mismatch in template parameter list for `%D'",
- in_decl);
+ {
+ if (complain)
+ {
+ cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ i + 1, in_decl);
+ if (is_type)
+ cp_error (" expected a constant of type `%T', got `%T'",
+ TREE_TYPE (parm),
+ (is_tmpl_type ? DECL_NAME (arg) : arg));
+ else
+ cp_error (" expected a type, got `%E'", arg);
+ }
+ }
lost++;
TREE_VEC_ELT (vec, i) = error_mark_node;
continue;
}
- if (is_type)
- val = groktypename (arg);
- else
+ if (is_tmpl_type ^ requires_tmpl_type)
{
- tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0),
- TREE_VEC_LENGTH (vec), in_decl);
- val = digest_init (t, arg, (tree *) 0);
-
- if (val == error_mark_node)
- ;
-
- /* 14.2: Other template-arguments must be constant-expressions,
- addresses of objects or functions with external linkage, or of
- static class members. */
- else if (!TREE_CONSTANT (val))
+ if (in_decl && complain)
{
- cp_error ("non-const `%E' cannot be used as template argument",
- arg);
- val = error_mark_node;
+ cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ i + 1, in_decl);
+ if (is_tmpl_type)
+ cp_error (" expected a type, got `%T'", DECL_NAME (arg));
+ else
+ cp_error (" expected a class template, got `%T'", arg);
}
- 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)
+ lost++;
+ TREE_VEC_ELT (vec, i) = error_mark_node;
+ continue;
+ }
+
+ if (is_type)
+ {
+ if (requires_tmpl_type)
{
- t = val;
- STRIP_NOPS (t);
- if (TREE_CODE (t) == ADDR_EXPR)
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ if (coerce_template_template_parms (parmparm, argparm,
+ in_decl, vec))
{
- 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;
- }
+ val = arg;
+
+ /* TEMPLATE_TEMPLATE_PARM node is preferred over
+ TEMPLATE_DECL. */
+ if (val != error_mark_node
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
+ val = TREE_TYPE (val);
}
else
{
- 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");
+ if (in_decl && complain)
+ {
+ cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ i + 1, in_decl);
+ cp_error (" expected a template of type `%D', got `%D'", parm, arg);
+ }
+
val = error_mark_node;
}
}
+ else
+ {
+ val = groktypename (arg);
+ if (! processing_template_decl)
+ {
+ tree t = target_type (val);
+ if (((IS_AGGR_TYPE (t) && TREE_CODE (t) != TYPENAME_TYPE)
+ || TREE_CODE (t) == ENUMERAL_TYPE)
+ && decl_function_context (TYPE_MAIN_DECL (t)))
+ {
+ cp_error ("type `%T' composed from a local type is not a valid template-argument",
+ val);
+ return error_mark_node;
+ }
+ }
+ }
+ }
+ else
+ {
+ tree t = tsubst (TREE_TYPE (parm), vec, in_decl);
+
+ if (processing_template_decl)
+ arg = maybe_fold_nontype_arg (arg);
+
+ if (!uses_template_parms (arg) && !uses_template_parms (t))
+ /* We used to call digest_init here. However, digest_init
+ will report errors, which we don't want when complain
+ is zero. More importantly, digest_init will try too
+ hard to convert things: for example, `0' should not be
+ converted to pointer type at this point according to
+ the standard. Accepting this is not merely an
+ extension, since deciding whether or not these
+ conversions can occur is part of determining which
+ function template to call, or whether a given epxlicit
+ argument specification is legal. */
+ val = convert_nontype_argument (t, arg);
+ else
+ val = arg;
+
+ if (val == NULL_TREE)
+ val = error_mark_node;
+ else if (val == error_mark_node && complain)
+ cp_error ("could not convert template argument `%E' to `%T'",
+ arg, t);
}
if (val == error_mark_node)
@@ -474,24 +2723,63 @@ coerce_template_parms (parms, arglist, in_decl)
return vec;
}
+/* Renturns 1 iff the OLDARGS and NEWARGS are in fact identical sets
+ of template arguments. Returns 0 otherwise. */
+
+int
+comp_template_args (oldargs, newargs)
+ tree oldargs, newargs;
+{
+ int i;
+
+ if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
+ return 0;
+
+ for (i = 0; i < TREE_VEC_LENGTH (oldargs); ++i)
+ {
+ tree nt = TREE_VEC_ELT (newargs, i);
+ tree ot = TREE_VEC_ELT (oldargs, i);
+
+ if (nt == ot)
+ continue;
+ if (TREE_CODE (nt) != TREE_CODE (ot))
+ return 0;
+ if (TREE_CODE (nt) == TREE_VEC)
+ {
+ /* For member templates */
+ if (comp_template_args (nt, ot))
+ continue;
+ }
+ else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
+ {
+ if (comptypes (ot, nt, 1))
+ continue;
+ }
+ else if (cp_tree_equal (ot, nt) > 0)
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
/* Given class template name and parameter list, produce a user-friendly name
for the instantiation. */
+
static char *
-mangle_class_name_for_template (name, parms, arglist)
+mangle_class_name_for_template (name, parms, arglist, ctx)
char *name;
tree parms, arglist;
+ tree ctx;
{
static struct obstack scratch_obstack;
static char *scratch_firstobj;
int i, nparms;
if (!scratch_firstobj)
- {
- gcc_obstack_init (&scratch_obstack);
- scratch_firstobj = obstack_alloc (&scratch_obstack, 1);
- }
+ gcc_obstack_init (&scratch_obstack);
else
obstack_free (&scratch_obstack, scratch_firstobj);
+ scratch_firstobj = obstack_alloc (&scratch_obstack, 1);
#if 0
#define buflen sizeof(buf)
@@ -506,6 +2794,21 @@ mangle_class_name_for_template (name, parms, arglist)
#define cat(s) obstack_grow (&scratch_obstack, (s), strlen (s))
#endif
+ if (ctx && ctx != global_namespace)
+ {
+ char* s;
+
+ if (TREE_CODE (ctx) == FUNCTION_DECL)
+ s = fndecl_as_string (ctx, 0);
+ else if (TREE_CODE_CLASS (TREE_CODE (ctx)) == 't')
+ s = type_as_string_real (ctx, 0, 1);
+ else if (TREE_CODE (ctx) == NAMESPACE_DECL)
+ s = decl_as_string (ctx, 0);
+ else
+ my_friendly_abort (0);
+ cat (s);
+ cat ("::");
+ }
cat (name);
ccat ('<');
nparms = TREE_VEC_LENGTH (parms);
@@ -520,7 +2823,27 @@ mangle_class_name_for_template (name, parms, arglist)
if (TREE_CODE (parm) == TYPE_DECL)
{
- cat (type_as_string (arg, 0));
+ cat (type_as_string_real (arg, 0, 1));
+ continue;
+ }
+ else if (TREE_CODE (parm) == TEMPLATE_DECL)
+ {
+ if (TREE_CODE (arg) == TEMPLATE_DECL)
+ {
+ /* Already substituted with real template. Just output
+ the template name here */
+ tree context = DECL_CONTEXT (arg);
+ if (context)
+ {
+ my_friendly_assert (TREE_CODE (context) == NAMESPACE_DECL, 980422);
+ cat(decl_as_string (DECL_CONTEXT (arg), 0));
+ cat("::");
+ }
+ cat (IDENTIFIER_POINTER (DECL_NAME (arg)));
+ }
+ else
+ /* Output the parameter declaration */
+ cat (type_as_string_real (arg, 0, 1));
continue;
}
else
@@ -560,6 +2883,100 @@ mangle_class_name_for_template (name, parms, arglist)
return NULL;
}
+static tree
+classtype_mangled_name (t)
+ tree t;
+{
+ if (CLASSTYPE_TEMPLATE_INFO (t)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
+ {
+ tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
+ /* We do not pass in the context here since that is only needed
+ when mangling the name of instantiations, not the primary
+ template declaration. In reality, it should not be needed
+ then either, but the way lookup_template_class operates
+ requires the context for the moment. In the long run,
+ lookup_template_class should not be looking for existing
+ instantiations by matching mangled names, but rather by
+ matching the templates, and then scanning the instantiation
+ list. */
+ char *mangled_name = mangle_class_name_for_template
+ (IDENTIFIER_POINTER (name),
+ DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
+ CLASSTYPE_TI_ARGS (t), NULL_TREE);
+ tree id = get_identifier (mangled_name);
+ IDENTIFIER_TEMPLATE (id) = name;
+ return id;
+ }
+ else
+ return TYPE_IDENTIFIER (t);
+}
+
+static void
+add_pending_template (d)
+ tree d;
+{
+ tree ti;
+
+ if (TREE_CODE_CLASS (TREE_CODE (d)) == 't')
+ ti = CLASSTYPE_TEMPLATE_INFO (d);
+ else
+ ti = DECL_TEMPLATE_INFO (d);
+
+ if (TI_PENDING_TEMPLATE_FLAG (ti))
+ return;
+
+ *template_tail = perm_tree_cons
+ (build_srcloc_here (), d, NULL_TREE);
+ template_tail = &TREE_CHAIN (*template_tail);
+ TI_PENDING_TEMPLATE_FLAG (ti) = 1;
+}
+
+
+/* Return a TEMPLATE_ID_EXPR corresponding to the indicated FNS (which
+ may be either a _DECL or an overloaded function or an
+ IDENTIFIER_NODE), and ARGLIST. */
+
+tree
+lookup_template_function (fns, arglist)
+ tree fns, arglist;
+{
+ tree type;
+
+ if (fns == NULL_TREE)
+ {
+ cp_error ("non-template used as template");
+ return error_mark_node;
+ }
+
+ if (arglist != NULL_TREE && !TREE_PERMANENT (arglist))
+ copy_to_permanent (arglist);
+
+ type = TREE_TYPE (fns);
+ if (TREE_CODE (fns) == OVERLOAD || !type)
+ type = unknown_type_node;
+
+ return build_min (TEMPLATE_ID_EXPR, type, fns, arglist);
+}
+
+/* Within the scope of a template class S<T>, the name S gets bound
+ (in build_self_reference) to a TYPE_DECL for the class, not a
+ TEMPLATE_DECL. If DECL is a TYPE_DECL for current_class_type,
+ or one of its enclosing classes, and that type is a template,
+ return the associated TEMPLATE_DECL. Otherwise, the original
+ DECL is returned. */
+
+tree
+maybe_get_template_decl_from_type_decl (decl)
+ tree decl;
+{
+ return (decl != NULL_TREE
+ && TREE_CODE (decl) == TYPE_DECL
+ && DECL_ARTIFICIAL (decl)
+ && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
+ ? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl;
+}
+
/* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of
parameters, find the desired type.
@@ -568,26 +2985,75 @@ mangle_class_name_for_template (name, parms, arglist)
to keep it from being reclaimed when the decl storage is reclaimed.
IN_DECL, if non-NULL, is the template declaration we are trying to
- instantiate. */
+ instantiate.
+
+ If the template class is really a local class in a template
+ function, then the FUNCTION_CONTEXT is the function in which it is
+ being instantiated. */
+
tree
-lookup_template_class (d1, arglist, in_decl)
+lookup_template_class (d1, arglist, in_decl, context)
tree d1, arglist;
tree in_decl;
+ tree context;
{
- tree template, parmlist;
+ tree template = NULL_TREE, parmlist;
char *mangled_name;
- tree id;
+ tree id, t;
+
+ if (TREE_CODE (d1) == IDENTIFIER_NODE)
+ {
+ if (IDENTIFIER_LOCAL_VALUE (d1)
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_LOCAL_VALUE (d1)))
+ template = IDENTIFIER_LOCAL_VALUE (d1);
+ else
+ {
+ if (context)
+ push_decl_namespace (context);
+ if (current_class_type != NULL_TREE)
+ template =
+ maybe_get_template_decl_from_type_decl
+ (IDENTIFIER_CLASS_VALUE (d1));
+ if (template == NULL_TREE)
+ template = lookup_name_nonclass (d1);
+ if (context)
+ pop_decl_namespace ();
+ }
+ if (template)
+ context = DECL_CONTEXT (template);
+ }
+ else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
+ {
+ if (CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (d1)) == NULL_TREE)
+ return error_mark_node;
+ template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1));
+ d1 = DECL_NAME (template);
+ }
+ else if (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' && IS_AGGR_TYPE (d1))
+ {
+ template = CLASSTYPE_TI_TEMPLATE (d1);
+ d1 = DECL_NAME (template);
+ }
+ else if (TREE_CODE (d1) == TEMPLATE_DECL
+ && TREE_CODE (DECL_RESULT (d1)) == TYPE_DECL)
+ {
+ template = d1;
+ d1 = DECL_NAME (template);
+ context = DECL_CONTEXT (template);
+ }
+ else
+ my_friendly_abort (272);
- my_friendly_assert (TREE_CODE (d1) == IDENTIFIER_NODE, 272);
- template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */
- if (! template)
- template = IDENTIFIER_CLASS_VALUE (d1);
/* With something like `template <class T> class X class X { ... };'
we could end up with D1 having nothing but an IDENTIFIER_LOCAL_VALUE.
We don't want to do that, but we have to deal with the situation, so
let's give them some syntax errors to chew on instead of a crash. */
if (! template)
return error_mark_node;
+
+ if (context == NULL_TREE)
+ context = global_namespace;
+
if (TREE_CODE (template) != TEMPLATE_DECL)
{
cp_error ("non-template type `%T' used as a template", d1);
@@ -595,123 +3061,205 @@ lookup_template_class (d1, arglist, in_decl)
cp_error_at ("for template declaration `%D'", in_decl);
return error_mark_node;
}
- parmlist = DECL_TEMPLATE_PARMS (template);
- arglist = coerce_template_parms (parmlist, arglist, template);
- if (arglist == error_mark_node)
- return error_mark_node;
- if (uses_template_parms (arglist))
- {
- tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
- tree d;
- id = make_anon_name ();
- d = build_decl (TYPE_DECL, id, t);
- TYPE_NAME (t) = d;
- TYPE_VALUES (t) = build_tree_list (template, arglist);
- pushdecl_top_level (d);
- }
- else
- {
- mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
- parmlist, arglist);
- id = get_identifier (mangled_name);
- }
- if (!IDENTIFIER_TEMPLATE (id))
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
{
- arglist = copy_to_permanent (arglist);
- IDENTIFIER_TEMPLATE (id) = perm_tree_cons (template, arglist, NULL_TREE);
- }
- return id;
-}
-
-void
-push_template_decls (parmlist, arglist, class_level)
- tree parmlist, arglist;
- int class_level;
-{
- int i, nparms;
+ /* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
+ template arguments */
- /* Don't want to push values into global context. */
- if (!class_level)
- {
- pushlevel (1);
- declare_pseudo_global_level ();
- }
+ tree parm = copy_template_template_parm (TREE_TYPE (template));
+ tree template2 = TYPE_STUB_DECL (parm);
+ tree arglist2;
- nparms = TREE_VEC_LENGTH (parmlist);
+ CLASSTYPE_GOT_SEMICOLON (parm) = 1;
+ parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
- for (i = 0; i < nparms; i++)
+ arglist2 = coerce_template_parms (parmlist, arglist, template, 1, 1);
+ if (arglist2 == error_mark_node)
+ return error_mark_node;
+
+ arglist2 = copy_to_permanent (arglist2);
+ CLASSTYPE_TEMPLATE_INFO (parm)
+ = perm_tree_cons (template2, arglist2, NULL_TREE);
+ TYPE_SIZE (parm) = 0;
+ return parm;
+ }
+ else if (PRIMARY_TEMPLATE_P (template)
+ || (TREE_CODE (TYPE_CONTEXT (TREE_TYPE (template)))
+ == FUNCTION_DECL))
{
- int requires_type, is_type;
- tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
- tree arg = TREE_VEC_ELT (arglist, i);
- tree decl = 0;
+ tree arglist_for_mangling;
- requires_type = TREE_CODE (parm) == TYPE_DECL;
- is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
- if (is_type)
+ parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
+
+ if (/* ARGLIST can be NULL_TREE if there are default arguments. */
+ arglist != NULL_TREE
+ && TREE_CODE (arglist) == TREE_VEC
+ && TREE_VEC_LENGTH (arglist) > 1
+ && list_length (DECL_TEMPLATE_PARMS (template)) > 1)
{
- /* add typename to namespace */
- if (!requires_type)
- {
- error ("template use error: type provided where value needed");
- continue;
- }
- decl = arg;
- my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273);
- decl = build_decl (TYPE_DECL, DECL_NAME (parm), decl);
+ /* We have multiple levels of arguments to coerce, at once. */
+ tree new_args =
+ make_tree_vec (list_length (DECL_TEMPLATE_PARMS (template)));
+ int i;
+
+ for (i = TREE_VEC_LENGTH (arglist) - 1,
+ t = DECL_TEMPLATE_PARMS (template);
+ i >= 0 && t != NULL_TREE;
+ --i, t = TREE_CHAIN (t))
+ TREE_VEC_ELT (new_args, i) =
+ coerce_template_parms (TREE_VALUE (t),
+ TREE_VEC_ELT (arglist, i),
+ template, 1, 1);
+ arglist = new_args;
}
else
+ arglist = coerce_template_parms (parmlist,
+ innermost_args (arglist, 0),
+ template, 1, 1);
+ if (arglist == error_mark_node)
+ return error_mark_node;
+ if (uses_template_parms (arglist))
{
- /* add const decl to namespace */
- tree val;
- tree parmtype;
- if (requires_type)
+ tree found;
+ if (comp_template_args
+ (CLASSTYPE_TI_ARGS (TREE_TYPE (template)), arglist))
+ found = TREE_TYPE (template);
+ else
{
- error ("template use error: value provided where type needed");
- continue;
+ for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+ found; found = TREE_CHAIN (found))
+ {
+ if (TI_USES_TEMPLATE_PARMS (found)
+ && comp_template_args (TREE_PURPOSE (found), arglist))
+ break;
+ }
+ if (found)
+ found = TREE_VALUE (found);
}
- parmtype = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (arglist, 0),
- TREE_VEC_LENGTH (arglist), NULL_TREE);
- val = digest_init (parmtype, arg, (tree *) 0);
- if (val != error_mark_node)
+
+ if (found)
{
- decl = build_decl (CONST_DECL, DECL_NAME (parm),
- parmtype);
- DECL_INITIAL (decl) = val;
- TREE_READONLY (decl) = 1;
+ if (can_free (&permanent_obstack, arglist))
+ obstack_free (&permanent_obstack, arglist);
+ return found;
}
}
- if (decl != 0)
+
+ if (TREE_CODE (arglist) == TREE_VEC)
+ arglist_for_mangling = innermost_args (arglist, 0);
+ else
+ arglist_for_mangling = arglist;
+
+ /* FIXME avoid duplication. */
+ mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
+ parmlist,
+ arglist_for_mangling,
+ context);
+ id = get_identifier (mangled_name);
+ IDENTIFIER_TEMPLATE (id) = d1;
+
+ maybe_push_to_top_level (uses_template_parms (arglist));
+ t = xref_tag_from_type (TREE_TYPE (template), id, 1);
+
+ if (context != NULL_TREE)
{
- SET_DECL_ARTIFICIAL (decl);
- layout_decl (decl, 0);
- if (class_level)
- pushdecl_class_level (decl);
- else
- pushdecl (decl);
+ /* Set up the context for the type_decl correctly. Note
+ that we must clear DECL_ASSEMBLER_NAME to fool
+ build_overload_name into creating a new name. */
+ tree type_decl = TYPE_STUB_DECL (t);
+
+ TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+ DECL_CONTEXT (type_decl) = FROB_CONTEXT (context);
+ DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
+ DECL_ASSEMBLER_NAME (type_decl) =
+ get_identifier (build_overload_name (t, 1, 1));
+ }
+
+ pop_from_top_level ();
+ }
+ else
+ {
+ tree type_ctx = TYPE_CONTEXT (TREE_TYPE (template));
+ tree args = tsubst (CLASSTYPE_TI_ARGS (type_ctx), arglist, in_decl);
+ tree ctx = lookup_template_class (type_ctx, args,
+ in_decl, NULL_TREE);
+ id = d1;
+ arglist = CLASSTYPE_TI_ARGS (ctx);
+
+ if (TYPE_BEING_DEFINED (ctx) && ctx == current_class_type)
+ {
+ int save_temp = processing_template_decl;
+ processing_template_decl = 0;
+ t = xref_tag_from_type (TREE_TYPE (template), id, 0);
+ processing_template_decl = save_temp;
+ }
+ else
+ {
+ t = lookup_nested_type_by_name (ctx, id);
+ my_friendly_assert (t != NULL_TREE, 42);
}
}
-}
-void
-pop_template_decls (parmlist, arglist, class_level)
- tree parmlist, arglist;
- int class_level;
-{
- if (!class_level)
- poplevel (0, 0, 0);
+ /* Seems to be wanted. */
+ CLASSTYPE_GOT_SEMICOLON (t) = 1;
+
+ if (! CLASSTYPE_TEMPLATE_INFO (t))
+ {
+ arglist = copy_to_permanent (arglist);
+ CLASSTYPE_TEMPLATE_INFO (t)
+ = perm_tree_cons (template, arglist, NULL_TREE);
+ DECL_TEMPLATE_INSTANTIATIONS (template) = perm_tree_cons
+ (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (template));
+ TI_USES_TEMPLATE_PARMS (DECL_TEMPLATE_INSTANTIATIONS (template))
+ = uses_template_parms (arglist);
+
+ SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
+
+ /* We need to set this again after CLASSTYPE_TEMPLATE_INFO is set up. */
+ DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t)) = id;
+ if (! uses_template_parms (arglist))
+ DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t))
+ = get_identifier (build_overload_name (t, 1, 1));
+
+ if (flag_external_templates && ! uses_template_parms (arglist)
+ && CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template))
+ && ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template)))
+ add_pending_template (t);
+
+ if (uses_template_parms (arglist))
+ /* If the type makes use of template parameters, the
+ code that generates debugging information will crash. */
+ DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
+ }
+
+ return t;
}
/* Should be defined in parse.h. */
extern int yychar;
+/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or
+ TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA.
+ If FN returns non-zero, the iteration is terminated, and
+ for_each_template_parm returns 1. Otherwise, the iteration
+ continues. If FN never returns a non-zero value, the value
+ returned by for_each_template_parm is 0. If FN is NULL, it is
+ considered to be the function which always returns 1. */
+
int
-uses_template_parms (t)
+for_each_template_parm (t, fn, data)
tree t;
+ tree_fn_t fn;
+ void* data;
{
if (!t)
return 0;
+
+ if (TREE_CODE_CLASS (TREE_CODE (t)) == 't'
+ && for_each_template_parm (TYPE_CONTEXT (t), fn, data))
+ return 1;
+
switch (TREE_CODE (t))
{
case INDIRECT_REF:
@@ -719,101 +3267,137 @@ uses_template_parms (t)
/* We assume that the object must be instantiated in order to build
the COMPONENT_REF, so we test only whether the type of the
COMPONENT_REF uses template parms. */
- return uses_template_parms (TREE_TYPE (t));
+ return for_each_template_parm (TREE_TYPE (t), fn, data);
case IDENTIFIER_NODE:
if (!IDENTIFIER_TEMPLATE (t))
return 0;
- return uses_template_parms (TREE_VALUE (IDENTIFIER_TEMPLATE (t)));
+ my_friendly_abort (42);
/* aggregates of tree nodes */
case TREE_VEC:
{
int i = TREE_VEC_LENGTH (t);
while (i--)
- if (uses_template_parms (TREE_VEC_ELT (t, i)))
+ if (for_each_template_parm (TREE_VEC_ELT (t, i), fn, data))
return 1;
return 0;
}
case TREE_LIST:
- if (uses_template_parms (TREE_PURPOSE (t))
- || uses_template_parms (TREE_VALUE (t)))
+ if (for_each_template_parm (TREE_PURPOSE (t), fn, data)
+ || for_each_template_parm (TREE_VALUE (t), fn, data))
+ return 1;
+ return for_each_template_parm (TREE_CHAIN (t), fn, data);
+
+ case OVERLOAD:
+ if (for_each_template_parm (OVL_FUNCTION (t), fn, data))
return 1;
- return uses_template_parms (TREE_CHAIN (t));
+ return for_each_template_parm (OVL_CHAIN (t), fn, data);
/* constructed type nodes */
case POINTER_TYPE:
case REFERENCE_TYPE:
- return uses_template_parms (TREE_TYPE (t));
+ return for_each_template_parm (TREE_TYPE (t), fn, data);
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (t))
- return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (t));
+ return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE (t),
+ fn, data);
case UNION_TYPE:
- if (!TYPE_NAME (t))
- return 0;
- if (!TYPE_IDENTIFIER (t))
+ if (! CLASSTYPE_TEMPLATE_INFO (t))
return 0;
- return uses_template_parms (TYPE_IDENTIFIER (t));
+ return for_each_template_parm (TREE_VALUE
+ (CLASSTYPE_TEMPLATE_INFO (t)),
+ fn, data);
case FUNCTION_TYPE:
- if (uses_template_parms (TYPE_ARG_TYPES (t)))
+ if (for_each_template_parm (TYPE_ARG_TYPES (t), fn, data))
return 1;
- return uses_template_parms (TREE_TYPE (t));
+ return for_each_template_parm (TREE_TYPE (t), fn, data);
case ARRAY_TYPE:
- if (uses_template_parms (TYPE_DOMAIN (t)))
+ if (for_each_template_parm (TYPE_DOMAIN (t), fn, data))
return 1;
- return uses_template_parms (TREE_TYPE (t));
+ return for_each_template_parm (TREE_TYPE (t), fn, data);
case OFFSET_TYPE:
- if (uses_template_parms (TYPE_OFFSET_BASETYPE (t)))
+ if (for_each_template_parm (TYPE_OFFSET_BASETYPE (t), fn, data))
return 1;
- return uses_template_parms (TREE_TYPE (t));
+ return for_each_template_parm (TREE_TYPE (t), fn, data);
case METHOD_TYPE:
- if (uses_template_parms (TYPE_METHOD_BASETYPE (t)))
+ if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data))
return 1;
- if (uses_template_parms (TYPE_ARG_TYPES (t)))
+ if (for_each_template_parm (TYPE_ARG_TYPES (t), fn, data))
return 1;
- return uses_template_parms (TREE_TYPE (t));
+ return for_each_template_parm (TREE_TYPE (t), fn, data);
/* decl nodes */
case TYPE_DECL:
- return uses_template_parms (DECL_NAME (t));
+ return for_each_template_parm (TREE_TYPE (t), fn, data);
+
+ case TEMPLATE_DECL:
+ /* A template template parameter is encountered */
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
+ return for_each_template_parm (TREE_TYPE (t), fn, data);
+ /* Already substituted template template parameter */
+ return 0;
+
+ case CONST_DECL:
+ if (for_each_template_parm (DECL_INITIAL (t), fn, data))
+ return 1;
+ goto check_type_and_context;
+
case FUNCTION_DECL:
- if (uses_template_parms (TREE_TYPE (t)))
+ case VAR_DECL:
+ /* ??? What about FIELD_DECLs? */
+ if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
+ && for_each_template_parm (DECL_TI_ARGS (t), fn, data))
return 1;
/* fall through */
- case VAR_DECL:
case PARM_DECL:
- /* ??? What about FIELD_DECLs? */
- /* The type of a decl can't use template parms if the name of the
- variable doesn't, because it's impossible to resolve them. So
- ignore the type field for now. */
- if (DECL_CONTEXT (t) && uses_template_parms (DECL_CONTEXT (t)))
+ check_type_and_context:
+ if (for_each_template_parm (TREE_TYPE (t), fn, data))
+ return 1;
+ if (DECL_CONTEXT (t)
+ && for_each_template_parm (DECL_CONTEXT (t), fn, data))
return 1;
- if (uses_template_parms (TREE_TYPE (t)))
- {
- error ("template parms used where they can't be resolved");
- }
return 0;
case CALL_EXPR:
- return uses_template_parms (TREE_TYPE (t));
+ return for_each_template_parm (TREE_TYPE (t), fn, data);
case ADDR_EXPR:
- return uses_template_parms (TREE_OPERAND (t, 0));
+ return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
/* template parm nodes */
+ case TEMPLATE_TEMPLATE_PARM:
+ /* Record template parameters such as `T' inside `TT<T>'. */
+ if (CLASSTYPE_TEMPLATE_INFO (t)
+ && for_each_template_parm (CLASSTYPE_TI_ARGS (t), fn, data))
+ return 1;
case TEMPLATE_TYPE_PARM:
- case TEMPLATE_CONST_PARM:
- return 1;
+ case TEMPLATE_PARM_INDEX:
+ if (fn)
+ return (*fn)(t, data);
+ else
+ return 1;
/* simple type nodes */
case INTEGER_TYPE:
- if (uses_template_parms (TYPE_MIN_VALUE (t)))
+ if (for_each_template_parm (TYPE_MIN_VALUE (t), fn, data))
return 1;
- return uses_template_parms (TYPE_MAX_VALUE (t));
+ return for_each_template_parm (TYPE_MAX_VALUE (t), fn, data);
case REAL_TYPE:
+ case COMPLEX_TYPE:
case VOID_TYPE:
- case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
+ case NAMESPACE_DECL:
+ return 0;
+
+ case ENUMERAL_TYPE:
+ {
+ tree v;
+
+ for (v = TYPE_VALUES (t); v != NULL_TREE; v = TREE_CHAIN (v))
+ if (for_each_template_parm (TREE_VALUE (v), fn, data))
+ return 1;
+ }
return 0;
/* constants */
@@ -828,25 +3412,45 @@ uses_template_parms (t)
/* NOTREACHED */
return 0;
- case UNINSTANTIATED_P_TYPE:
+ case LOOKUP_EXPR:
+ case TYPENAME_TYPE:
return 1;
+ case SCOPE_REF:
+ return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
+
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
- return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
- /* else fall through */
+ return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
+ (TREE_TYPE (t)), fn, data);
+ return for_each_template_parm (TREE_OPERAND (t, 1), fn, data);
+
+ case MODOP_EXPR:
+ case CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case DYNAMIC_CAST_EXPR:
+ case ARROW_EXPR:
+ case DOTSTAR_EXPR:
+ case TYPEID_EXPR:
+ return 1;
+
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
default:
switch (TREE_CODE_CLASS (TREE_CODE (t)))
{
case '1':
case '2':
- case '3':
+ case 'e':
case '<':
{
int i;
- for (i = tree_code_length[(int) TREE_CODE (t)]; --i >= 0;)
- if (uses_template_parms (TREE_OPERAND (t, i)))
+ for (i = first_rtl_op (TREE_CODE (t)); --i >= 0;)
+ if (for_each_template_parm (TREE_OPERAND (t, i), fn, data))
return 1;
return 0;
}
@@ -861,77 +3465,99 @@ uses_template_parms (t)
}
}
-void
-instantiate_member_templates (classname)
- tree classname;
+int
+uses_template_parms (t)
+ tree t;
{
- tree t;
- tree id = classname;
- tree members = DECL_TEMPLATE_MEMBERS (TREE_PURPOSE (IDENTIFIER_TEMPLATE (id)));
-
- for (t = members; t; t = TREE_CHAIN (t))
- {
- tree parmvec, type, classparms, tdecl, t2;
- int nparms, xxx = 0, i;
-
- my_friendly_assert (TREE_VALUE (t) != NULL_TREE, 275);
- my_friendly_assert (TREE_CODE (TREE_VALUE (t)) == TEMPLATE_DECL, 276);
- /* @@ Should verify that class parm list is a list of
- distinct template parameters, and covers all the template
- parameters. */
- tdecl = TREE_VALUE (t);
- type = DECL_CONTEXT (DECL_TEMPLATE_RESULT (tdecl));
- classparms = UPT_PARMS (type);
- nparms = TREE_VEC_LENGTH (classparms);
- parmvec = make_tree_vec (nparms);
- for (i = 0; i < nparms; i++)
- TREE_VEC_ELT (parmvec, i) = NULL_TREE;
- switch (unify (DECL_TEMPLATE_PARMS (tdecl),
- &TREE_VEC_ELT (parmvec, 0), nparms,
- type, IDENTIFIER_TYPE_VALUE (classname),
- &xxx))
- {
- case 0:
- /* Success -- well, no inconsistency, at least. */
- for (i = 0; i < nparms; i++)
- if (TREE_VEC_ELT (parmvec, i) == NULL_TREE)
- goto failure;
- t2 = instantiate_template (tdecl,
- &TREE_VEC_ELT (parmvec, 0));
- type = IDENTIFIER_TYPE_VALUE (id);
- my_friendly_assert (type != 0, 277);
- break;
- case 1:
- /* Failure. */
- failure:
- cp_error_at ("type unification error instantiating `%D'", tdecl);
- cp_error ("while instantiating members of `%T'", classname);
+ return for_each_template_parm (t, 0, 0);
+}
- continue /* loop of members */;
- default:
- /* Eek, a bug. */
- my_friendly_abort (83);
+static struct tinst_level *current_tinst_level;
+static struct tinst_level *free_tinst_level;
+static int tinst_depth;
+extern int max_tinst_depth;
+#ifdef GATHER_STATISTICS
+int depth_reached;
+#endif
+int tinst_level_tick;
+int last_template_error_tick;
+
+/* Print out all the template instantiations that we are currently
+ working on. If ERR, we are being called from cp_thing, so do
+ the right thing for an error message. */
+
+static void
+print_template_context (err)
+ int err;
+{
+ struct tinst_level *p = current_tinst_level;
+ int line = lineno;
+ char *file = input_filename;
+
+ if (err)
+ {
+ if (current_function_decl == p->decl)
+ /* Avoid redundancy with the the "In function" line. */;
+ else if (current_function_decl == NULL_TREE)
+ fprintf (stderr, "%s: In instantiation of `%s':\n",
+ file, decl_as_string (p->decl, 0));
+ else
+ my_friendly_abort (980521);
+
+ if (p)
+ {
+ line = p->line;
+ file = p->file;
+ p = p->next;
}
}
+
+ next:
+ for (; p; p = p->next)
+ {
+ fprintf (stderr, "%s:%d: instantiated from `%s'\n", file, line,
+ decl_as_string (p->decl, 0));
+ line = p->line;
+ file = p->file;
+ }
+ fprintf (stderr, "%s:%d: instantiated from here\n", file, line);
}
-static struct tinst_level *current_tinst_level = 0;
-static struct tinst_level *free_tinst_level = 0;
-static int tinst_depth = 0;
-int max_tinst_depth = 17;
+/* Called from cp_thing to print the template context for an error. */
-int
-push_tinst_level (name)
- tree name;
+void
+maybe_print_template_context ()
+{
+ if (last_template_error_tick == tinst_level_tick
+ || current_tinst_level == 0)
+ return;
+
+ last_template_error_tick = tinst_level_tick;
+ print_template_context (1);
+}
+
+static int
+push_tinst_level (d)
+ tree d;
{
struct tinst_level *new;
- tree global = IDENTIFIER_GLOBAL_VALUE (name);
if (tinst_depth >= max_tinst_depth)
{
+ /* If the instantiation in question still has unbound template parms,
+ we don't really care if we can't instantiate it, so just return.
+ This happens with base instantiation for implicit `typename'. */
+ if (uses_template_parms (d))
+ return 0;
+
+ last_template_error_tick = tinst_level_tick;
error ("template instantiation depth exceeds maximum of %d",
max_tinst_depth);
- cp_error (" instantiating `%D'", name);
+ error (" (use -ftemplate-depth-NN to increase the maximum)");
+ cp_error (" instantiating `%D'", d);
+
+ print_template_context (0);
+
return 0;
}
@@ -943,20 +3569,19 @@ push_tinst_level (name)
else
new = (struct tinst_level *) xmalloc (sizeof (struct tinst_level));
- new->classname = name;
- if (global)
- {
- new->line = DECL_SOURCE_LINE (global);
- new->file = DECL_SOURCE_FILE (global);
- }
- else
- {
- new->line = lineno;
- new->file = input_filename;
- }
+ new->decl = d;
+ new->line = lineno;
+ new->file = input_filename;
new->next = current_tinst_level;
current_tinst_level = new;
+
++tinst_depth;
+#ifdef GATHER_STATISTICS
+ if (tinst_depth > depth_reached)
+ depth_reached = tinst_depth;
+#endif
+
+ ++tinst_level_tick;
return 1;
}
@@ -969,6 +3594,7 @@ pop_tinst_level ()
old->next = free_tinst_level;
free_tinst_level = old;
--tinst_depth;
+ ++tinst_level_tick;
}
struct tinst_level *
@@ -982,119 +3608,485 @@ tinst_for_decl ()
return p;
}
+/* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL. ARGS is the
+ vector of template arguments, as for tsubst.
+
+ Returns an appropriate tsbust'd friend declaration. */
+
+static tree
+tsubst_friend_function (decl, args)
+ tree decl;
+ tree args;
+{
+ tree new_friend;
+ int line = lineno;
+ char *file = input_filename;
+
+ lineno = DECL_SOURCE_LINE (decl);
+ input_filename = DECL_SOURCE_FILE (decl);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_TEMPLATE_INSTANTIATION (decl)
+ && TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
+ /* This was a friend declared with an explicit template
+ argument list, e.g.:
+
+ friend void f<>(T);
+
+ to indicate that f was a template instantiation, not a new
+ function declaration. Now, we have to figure out what
+ instantiation of what template. */
+ {
+ tree template_id;
+ tree new_args;
+ tree tmpl;
+ tree tinfo;
+
+ template_id
+ = lookup_template_function (tsubst_expr (DECL_TI_TEMPLATE (decl),
+ args, NULL_TREE),
+ tsubst (DECL_TI_ARGS (decl),
+ args, NULL_TREE));
+
+ /* Temporarily remove the DECL_TEMPLATE_INFO so as not to
+ confuse tsubst. */
+ tinfo = DECL_TEMPLATE_INFO (decl);
+ DECL_TEMPLATE_INFO (decl) = NULL_TREE;
+ new_friend = tsubst (decl, args, NULL_TREE);
+ DECL_TEMPLATE_INFO (decl) = tinfo;
+
+ tmpl = determine_specialization (template_id,
+ new_friend,
+ &new_args,
+ 0, 1);
+ new_friend = instantiate_template (tmpl, new_args);
+ goto done;
+ }
+ else
+ new_friend = tsubst (decl, args, NULL_TREE);
+
+ /* The new_friend will look like an instantiation, to the
+ compiler, but is not an instantiation from the point of view of
+ the language. For example, we might have had:
+
+ template <class T> struct S {
+ template <class U> friend void f(T, U);
+ };
+
+ Then, in S<int>, template <class U> void f(int, U) is not an
+ instantiation of anything. */
+ DECL_USE_TEMPLATE (new_friend) = 0;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
+
+ if (DECL_NAMESPACE_SCOPE_P (new_friend))
+ {
+ if (TREE_CODE (new_friend) == TEMPLATE_DECL)
+ /* This declaration is a `primary' template. */
+ TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (new_friend))
+ = new_friend;
+
+ new_friend = pushdecl_namespace_level (new_friend);
+ }
+ else if (TYPE_SIZE (DECL_CONTEXT (new_friend)))
+ {
+ /* Check to see that the declaration is really present, and,
+ possibly obtain an improved declaration. */
+ tree fn = check_classfn (DECL_CONTEXT (new_friend),
+ new_friend);
+
+ if (fn)
+ new_friend = fn;
+ }
+
+ done:
+ lineno = line;
+ input_filename = file;
+ return new_friend;
+}
+
+/* FRIEND_TMPL is a friend TEMPLATE_DECL. ARGS is the vector of
+ template arguments, as for tsubst.
+
+ Returns an appropriate tsbust'd friend type. */
+
+static tree
+tsubst_friend_class (friend_tmpl, args)
+ tree friend_tmpl;
+ tree args;
+{
+ tree friend_type;
+ tree tmpl = lookup_name (DECL_NAME (friend_tmpl), 1);
+
+ tmpl = maybe_get_template_decl_from_type_decl (tmpl);
+
+ if (tmpl != NULL_TREE && DECL_CLASS_TEMPLATE_P (tmpl))
+ {
+ /* The friend template has already been declared. Just
+ check to see that the declarations match. */
+ redeclare_class_template (TREE_TYPE (tmpl),
+ DECL_TEMPLATE_PARMS (friend_tmpl));
+ friend_type = TREE_TYPE (tmpl);
+ }
+ else
+ {
+ /* The friend template has not already been declared. In this
+ case, the instantiation of the template class will cause the
+ injection of this template into the global scope. */
+ tmpl = tsubst (friend_tmpl, args, NULL_TREE);
+
+ /* The new TMPL is not an instantiation of anything, so we
+ forget its origins. We don't reset CLASSTYPE_TI_TEMPLATE for
+ the new type because that is supposed to be the corresponding
+ template decl, i.e., TMPL. */
+ DECL_USE_TEMPLATE (tmpl) = 0;
+ DECL_TEMPLATE_INFO (tmpl) = NULL_TREE;
+ CLASSTYPE_USE_TEMPLATE (TREE_TYPE (tmpl)) = 0;
+
+ /* Inject this template into the global scope. */
+ friend_type = TREE_TYPE (pushdecl_top_level (tmpl));
+ }
+
+ return friend_type;
+}
+
tree
-instantiate_class_template (classname, setup_parse)
- tree classname;
- int setup_parse;
+instantiate_class_template (type)
+ tree type;
{
- struct template_info *template_info;
- tree template, t1;
+ tree template, template_info, args, pattern, t, *field_chain;
+ tree typedecl, outer_args;
- if (classname == error_mark_node)
+ if (type == error_mark_node)
return error_mark_node;
- my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 278);
- template = IDENTIFIER_TEMPLATE (classname);
+ template_info = CLASSTYPE_TEMPLATE_INFO (type);
+
+ if (TYPE_BEING_DEFINED (type) || TYPE_SIZE (type))
+ return type;
- if (IDENTIFIER_HAS_TYPE_VALUE (classname))
+ template = TI_TEMPLATE (template_info);
+ my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
+ args = TI_ARGS (template_info);
+
+ if (DECL_TEMPLATE_INFO (template))
{
- tree type = IDENTIFIER_TYPE_VALUE (classname);
- if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
- return type;
- if (TYPE_BEING_DEFINED (type)
- || TYPE_SIZE (type)
- || CLASSTYPE_USE_TEMPLATE (type) != 0)
- return type;
+ outer_args = DECL_TI_ARGS (template);
+ while (DECL_TEMPLATE_INFO (template))
+ template = DECL_TI_TEMPLATE (template);
}
+ else
+ outer_args = NULL_TREE;
- /* If IDENTIFIER_LOCAL_VALUE is already set on this template classname
- (it's something like `foo<int>'), that means we're already working on
- the instantiation for it. Normally, a classname comes in with nothing
- but its IDENTIFIER_TEMPLATE slot set. If we were to try to instantiate
- this again, we'd get a redeclaration error. Since we're already working
- on it, we'll pass back this classname's TYPE_DECL (it's the value of
- the classname's IDENTIFIER_LOCAL_VALUE). Only do this if we're setting
- things up for the parser, though---if we're just trying to instantiate
- it (e.g., via tsubst) we can trip up cuz it may not have an
- IDENTIFIER_TYPE_VALUE when it will need one. */
- if (setup_parse && IDENTIFIER_LOCAL_VALUE (classname))
- return IDENTIFIER_LOCAL_VALUE (classname);
+ t = most_specialized_class
+ (DECL_TEMPLATE_SPECIALIZATIONS (template), args, outer_args);
- if (uses_template_parms (classname))
+ if (t == error_mark_node)
{
- if (!TREE_TYPE (classname))
+ char *str = "candidates are:";
+ cp_error ("ambiguous class template instantiation for `%#T'", type);
+ for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t))
{
- tree t = make_lang_type (RECORD_TYPE);
- tree d = build_decl (TYPE_DECL, classname, t);
- DECL_NAME (d) = classname;
- TYPE_NAME (t) = d;
- pushdecl (d);
+ if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+ args, outer_args))
+ {
+ cp_error_at ("%s %+#T", str, TREE_TYPE (t));
+ str = " ";
+ }
}
- return NULL_TREE;
+ TYPE_BEING_DEFINED (type) = 1;
+ return error_mark_node;
}
+ else if (t)
+ pattern = TREE_TYPE (t);
+ else
+ pattern = TREE_TYPE (template);
- t1 = TREE_PURPOSE (template);
- my_friendly_assert (TREE_CODE (t1) == TEMPLATE_DECL, 279);
+ if (TYPE_SIZE (pattern) == NULL_TREE)
+ return type;
- /* If a template is declared but not defined, accept it; don't crash.
- Later uses requiring the definition will be flagged as errors by
- other code. Thanks to niklas@appli.se for this bug fix. */
- if (DECL_TEMPLATE_INFO (t1)->text == 0)
- setup_parse = 0;
+ if (t)
+ args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+ args, outer_args);
- push_to_top_level ();
- template_info = DECL_TEMPLATE_INFO (t1);
- if (setup_parse && push_tinst_level (classname))
- {
- push_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (template)),
- TREE_VALUE (template), 0);
- set_current_level_tags_transparency (1);
- feed_input (template_info->text, template_info->length, (struct obstack *)0);
- lineno = template_info->lineno;
- input_filename = template_info->filename;
- /* Get interface/implementation back in sync. */
- extract_interface_info ();
- overload_template_name (classname, 0);
- /* Kludge so that we don't get screwed by our own base classes. */
- TYPE_BEING_DEFINED (TREE_TYPE (classname)) = 1;
- yychar = PRE_PARSED_CLASS_DECL;
- yylval.ttype = classname;
- processing_template_defn++;
- if (!flag_external_templates)
- interface_unknown++;
- template_classes
- = perm_tree_cons (classname, NULL_TREE, template_classes);
+ if (pedantic && uses_template_parms (args))
+ /* If there are still template parameters amongst the args, then
+ we can't instantiate the type; there's no telling whether or not one
+ of the template parameters might eventually be instantiated to some
+ value that results in a specialization being used. */
+ return type;
+
+ /* We must copy the arguments to the permanent obstack since
+ during the tsubst'ing below they may wind up in the
+ DECL_TI_ARGS of some instantiated member template. */
+ args = copy_to_permanent (args);
+
+ TYPE_BEING_DEFINED (type) = 1;
+
+ if (! push_tinst_level (type))
+ return type;
+
+ maybe_push_to_top_level (uses_template_parms (type));
+ pushclass (type, 0);
+
+ if (outer_args)
+ args = add_to_template_args (outer_args, args);
+
+ if (flag_external_templates)
+ {
+ if (flag_alt_external_templates)
+ {
+ CLASSTYPE_INTERFACE_ONLY (type) = interface_only;
+ SET_CLASSTYPE_INTERFACE_UNKNOWN_X (type, interface_unknown);
+ CLASSTYPE_VTABLE_NEEDS_WRITING (type)
+ = (! CLASSTYPE_INTERFACE_ONLY (type)
+ && CLASSTYPE_INTERFACE_KNOWN (type));
+ }
+ else
+ {
+ CLASSTYPE_INTERFACE_ONLY (type) = CLASSTYPE_INTERFACE_ONLY (pattern);
+ SET_CLASSTYPE_INTERFACE_UNKNOWN_X
+ (type, CLASSTYPE_INTERFACE_UNKNOWN (pattern));
+ CLASSTYPE_VTABLE_NEEDS_WRITING (type)
+ = (! CLASSTYPE_INTERFACE_ONLY (type)
+ && CLASSTYPE_INTERFACE_KNOWN (type));
+ }
}
else
{
- tree t, decl, id, tmpl;
-
- id = classname;
- tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE (id));
- t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, id, NULL_TREE, 0);
- my_friendly_assert (TREE_CODE (t) == RECORD_TYPE
- || TREE_CODE (t) == UNION_TYPE, 280);
-
- /* Now, put a copy of the decl in global scope, to avoid
- * recursive expansion. */
- decl = IDENTIFIER_LOCAL_VALUE (id);
- if (!decl)
- decl = IDENTIFIER_CLASS_VALUE (id);
- if (decl)
- {
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 281);
- /* We'd better make sure we're on the permanent obstack or else
- * we'll get a "friendly" abort 124 in pushdecl. Perhaps a
- * copy_to_permanent would be sufficient here, but then a
- * sharing problem might occur. I don't know -- niklas@appli.se */
- push_obstacks (&permanent_obstack, &permanent_obstack);
- pushdecl_top_level (copy_node (decl));
- pop_obstacks ();
+ SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
+ CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
+ }
+
+ TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
+ TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (pattern);
+ TYPE_HAS_ASSIGNMENT (type) = TYPE_HAS_ASSIGNMENT (pattern);
+ TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
+ TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
+ TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern);
+ TYPE_GETS_NEW (type) = TYPE_GETS_NEW (pattern);
+ TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
+ TYPE_VEC_DELETE_TAKES_SIZE (type) = TYPE_VEC_DELETE_TAKES_SIZE (pattern);
+ TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
+ TYPE_HAS_CONST_ASSIGN_REF (type) = TYPE_HAS_CONST_ASSIGN_REF (pattern);
+ TYPE_HAS_ABSTRACT_ASSIGN_REF (type) = TYPE_HAS_ABSTRACT_ASSIGN_REF (pattern);
+ TYPE_HAS_INIT_REF (type) = TYPE_HAS_INIT_REF (pattern);
+ TYPE_HAS_CONST_INIT_REF (type) = TYPE_HAS_CONST_INIT_REF (pattern);
+ TYPE_HAS_DEFAULT_CONSTRUCTOR (type) = TYPE_HAS_DEFAULT_CONSTRUCTOR (pattern);
+ TYPE_HAS_CONVERSION (type) = TYPE_HAS_CONVERSION (pattern);
+ TYPE_USES_COMPLEX_INHERITANCE (type)
+ = TYPE_USES_COMPLEX_INHERITANCE (pattern);
+ TYPE_USES_MULTIPLE_INHERITANCE (type)
+ = TYPE_USES_MULTIPLE_INHERITANCE (pattern);
+ TYPE_USES_VIRTUAL_BASECLASSES (type)
+ = TYPE_USES_VIRTUAL_BASECLASSES (pattern);
+ TYPE_PACKED (type) = TYPE_PACKED (pattern);
+ TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
+ TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */
+
+ CLASSTYPE_LOCAL_TYPEDECLS (type) = CLASSTYPE_LOCAL_TYPEDECLS (pattern);
+
+ /* If this is a partial instantiation, don't tsubst anything. We will
+ only use this type for implicit typename, so the actual contents don't
+ matter. All that matters is whether a particular name is a type. */
+ if (uses_template_parms (type))
+ {
+ TYPE_BINFO_BASETYPES (type) = TYPE_BINFO_BASETYPES (pattern);
+ TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
+ TYPE_METHODS (type) = TYPE_METHODS (pattern);
+ CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern);
+ TYPE_SIZE (type) = integer_zero_node;
+ goto end;
+ }
+
+ {
+ tree binfo = TYPE_BINFO (type);
+ tree pbases = TYPE_BINFO_BASETYPES (pattern);
+
+ if (pbases)
+ {
+ tree bases;
+ int i;
+ int len = TREE_VEC_LENGTH (pbases);
+ bases = make_tree_vec (len);
+ for (i = 0; i < len; ++i)
+ {
+ tree elt, basetype;
+
+ TREE_VEC_ELT (bases, i) = elt
+ = tsubst (TREE_VEC_ELT (pbases, i), args, NULL_TREE);
+ BINFO_INHERITANCE_CHAIN (elt) = binfo;
+
+ basetype = TREE_TYPE (elt);
+
+ if (! IS_AGGR_TYPE (basetype))
+ cp_error
+ ("base type `%T' of `%T' fails to be a struct or class type",
+ basetype, type);
+ else if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE)
+ cp_error ("base class `%T' of `%T' has incomplete type",
+ basetype, type);
+
+ /* These are set up in xref_basetypes for normal classes, so
+ we have to handle them here for template bases. */
+ if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+ {
+ TYPE_USES_VIRTUAL_BASECLASSES (type) = 1;
+ TYPE_USES_COMPLEX_INHERITANCE (type) = 1;
+ }
+ TYPE_GETS_NEW (type) |= TYPE_GETS_NEW (basetype);
+ TYPE_GETS_DELETE (type) |= TYPE_GETS_DELETE (basetype);
+ CLASSTYPE_LOCAL_TYPEDECLS (type)
+ |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
+ }
+ /* Don't initialize this until the vector is filled out, or
+ lookups will crash. */
+ BINFO_BASETYPES (binfo) = bases;
+ }
+ }
+
+ field_chain = &TYPE_FIELDS (type);
+
+ for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
+ {
+ tree tag = TREE_VALUE (t);
+
+ /* These will add themselves to CLASSTYPE_TAGS for the new type. */
+ if (TREE_CODE (tag) == ENUMERAL_TYPE)
+ {
+ (void) tsubst_enum (tag, args, field_chain);
+ while (*field_chain)
+ {
+ DECL_FIELD_CONTEXT (*field_chain) = type;
+ field_chain = &TREE_CHAIN (*field_chain);
+ }
}
- pop_from_top_level ();
+ else
+ tsubst (tag, args, NULL_TREE);
}
- return NULL_TREE;
+ /* Don't replace enum constants here. */
+ for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
+ if (TREE_CODE (t) != CONST_DECL)
+ {
+ tree r = tsubst (t, args, NULL_TREE);
+ if (TREE_CODE (r) == VAR_DECL)
+ {
+ pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics);
+ /* Perhaps we should do more of grokfield here. */
+ start_decl_1 (r);
+ DECL_IN_AGGR_P (r) = 1;
+ DECL_EXTERNAL (r) = 1;
+ cp_finish_decl (r, DECL_INITIAL (r), NULL_TREE, 0, 0);
+ }
+
+ *field_chain = r;
+ field_chain = &TREE_CHAIN (r);
+ }
+
+ TYPE_METHODS (type) = tsubst_chain (TYPE_METHODS (pattern), args);
+
+ /* Construct the DECL_FRIENDLIST for the new class type. */
+ typedecl = TYPE_MAIN_DECL (type);
+ for (t = DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern));
+ t != NULL_TREE;
+ t = TREE_CHAIN (t))
+ {
+ tree friends;
+
+ DECL_FRIENDLIST (typedecl)
+ = tree_cons (TREE_PURPOSE (t), NULL_TREE,
+ DECL_FRIENDLIST (typedecl));
+
+ for (friends = TREE_VALUE (t);
+ friends != NULL_TREE;
+ friends = TREE_CHAIN (friends))
+ {
+ if (TREE_PURPOSE (friends) == error_mark_node)
+ {
+ TREE_VALUE (DECL_FRIENDLIST (typedecl))
+ = tree_cons (error_mark_node,
+ tsubst_friend_function (TREE_VALUE (friends),
+ args),
+ TREE_VALUE (DECL_FRIENDLIST (typedecl)));
+ }
+ else
+ {
+ TREE_VALUE (DECL_FRIENDLIST (typedecl))
+ = tree_cons (tsubst (TREE_PURPOSE (friends), args, NULL_TREE),
+ NULL_TREE,
+ TREE_VALUE (DECL_FRIENDLIST (typedecl)));
+
+ }
+ }
+ }
+
+ for (t = CLASSTYPE_FRIEND_CLASSES (pattern);
+ t != NULL_TREE;
+ t = TREE_CHAIN (t))
+ {
+ tree friend_type = TREE_VALUE (t);
+ tree new_friend_type;
+
+ if (TREE_CODE (friend_type) != TEMPLATE_DECL)
+ /* The call to xref_tag_from_type does injection for friend
+ classes. */
+ new_friend_type =
+ xref_tag_from_type (tsubst (friend_type, args, NULL_TREE),
+ NULL_TREE, 1);
+ else
+ new_friend_type = tsubst_friend_class (friend_type, args);
+
+ if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ /* Trick make_friend_class into realizing that the friend
+ we're adding is a template, not an ordinary class. It's
+ important that we use make_friend_class since it will
+ perform some error-checking and output cross-reference
+ information. */
+ ++processing_template_decl;
+
+ make_friend_class (type, new_friend_type);
+
+ if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ --processing_template_decl;
+ }
+
+ /* This does injection for friend functions. */
+ if (!processing_template_decl)
+ {
+ t = tsubst (DECL_TEMPLATE_INJECT (template), args, NULL_TREE);
+
+ for (; t; t = TREE_CHAIN (t))
+ {
+ tree d = TREE_VALUE (t);
+
+ if (TREE_CODE (d) == TYPE_DECL)
+ /* Already injected. */;
+ else
+ pushdecl (d);
+ }
+ }
+
+ for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
+ if (TREE_CODE (t) == FIELD_DECL)
+ {
+ TREE_TYPE (t) = complete_type (TREE_TYPE (t));
+ require_complete_type (t);
+ }
+
+ type = finish_struct_1 (type, 0);
+ CLASSTYPE_GOT_SEMICOLON (type) = 1;
+
+ repo_template_used (type);
+
+ end:
+ TYPE_BEING_DEFINED (type) = 0;
+ popclass (0);
+
+ pop_from_top_level ();
+ pop_tinst_level ();
+
+ return type;
}
static int
@@ -1113,77 +4105,209 @@ list_eq (t1, t2)
return list_eq (TREE_CHAIN (t1), TREE_CHAIN (t2));
}
-static tree
+tree
lookup_nested_type_by_name (ctype, name)
tree ctype, name;
{
tree t;
+ complete_type (ctype);
+
for (t = CLASSTYPE_TAGS (ctype); t; t = TREE_CHAIN (t))
{
- if (name == TREE_PURPOSE (t))
+ if (name == TREE_PURPOSE (t)
+ /* this catches typedef enum { foo } bar; */
+ || name == TYPE_IDENTIFIER (TREE_VALUE (t)))
return TREE_VALUE (t);
}
return NULL_TREE;
}
+/* If arg is a non-type template parameter that does not depend on template
+ arguments, fold it like we weren't in the body of a template. */
+
static tree
-search_nested_type_in_tmpl (tmpl, type)
- tree tmpl, type;
+maybe_fold_nontype_arg (arg)
+ tree arg;
{
- tree t;
+ if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't'
+ && !uses_template_parms (arg))
+ {
+ /* Sometimes, one of the args was an expression involving a
+ template constant parameter, like N - 1. Now that we've
+ tsubst'd, we might have something like 2 - 1. This will
+ confuse lookup_template_class, so we do constant folding
+ here. We have to unset processing_template_decl, to
+ fool build_expr_from_tree() into building an actual
+ tree. */
+
+ int saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
+ arg = fold (build_expr_from_tree (arg));
+ processing_template_decl = saved_processing_template_decl;
+ }
+ return arg;
+}
+
+/* Return the TREE_VEC with the arguments for the innermost template header,
+ where ARGS is either that or the VEC of VECs for all the arguments.
- if (tmpl == NULL || TYPE_CONTEXT(type) == NULL)
- return tmpl;
- t = search_nested_type_in_tmpl (tmpl, TYPE_CONTEXT(type));
- if (t == NULL) return t;
- t = lookup_nested_type_by_name(t, DECL_NAME(TYPE_NAME(type)));
+ If is_spec, then we are dealing with a specialization of a member
+ template, and want the second-innermost args, the innermost ones that
+ are instantiated. */
+
+tree
+innermost_args (args, is_spec)
+ tree args;
+ int is_spec;
+{
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
+ return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec);
+ return args;
+}
+
+/* Substitute ARGS into the vector of template arguments T. */
+
+tree
+tsubst_template_arg_vector (t, args)
+ tree t;
+ tree args;
+{
+ int len = TREE_VEC_LENGTH (t), need_new = 0, i;
+ tree *elts = (tree *) alloca (len * sizeof (tree));
+
+ bzero ((char *) elts, len * sizeof (tree));
+
+ for (i = 0; i < len; i++)
+ {
+ if (TREE_VEC_ELT (t, i) != NULL_TREE
+ && TREE_CODE (TREE_VEC_ELT (t, i)) == TREE_VEC)
+ elts[i] = tsubst_template_arg_vector (TREE_VEC_ELT (t, i), args);
+ else
+ elts[i] = maybe_fold_nontype_arg
+ (tsubst_expr (TREE_VEC_ELT (t, i), args, NULL_TREE));
+
+ if (elts[i] != TREE_VEC_ELT (t, i))
+ need_new = 1;
+ }
+
+ if (!need_new)
+ return t;
+
+ t = make_tree_vec (len);
+ for (i = 0; i < len; i++)
+ TREE_VEC_ELT (t, i) = elts[i];
+
return t;
}
+/* Take the tree structure T and replace template parameters used therein
+ with the argument vector ARGS. IN_DECL is an associated decl for
+ diagnostics.
+
+ tsubst is used for dealing with types, decls and the like; for
+ expressions, use tsubst_expr or tsubst_copy. */
+
tree
-tsubst (t, args, nargs, in_decl)
- tree t, *args;
- int nargs;
+tsubst (t, args, in_decl)
+ tree t, args;
tree in_decl;
{
tree type;
- if (t == NULL_TREE || t == error_mark_node)
+ if (t == NULL_TREE || t == error_mark_node
+ || t == integer_type_node
+ || t == void_type_node
+ || t == char_type_node
+ || TREE_CODE (t) == NAMESPACE_DECL)
return t;
- type = TREE_TYPE (t);
- if (type
- /* Minor optimization.
- ?? Are these really the most frequent cases? Is the savings
- significant? */
- && type != integer_type_node
- && type != void_type_node
- && type != char_type_node)
- type = tsubst (type, args, nargs, in_decl);
+ if (TREE_CODE (t) == IDENTIFIER_NODE)
+ type = IDENTIFIER_TYPE_VALUE (t);
+ else
+ type = TREE_TYPE (t);
+ if (type == unknown_type_node)
+ my_friendly_abort (42);
+
+ if (type && TREE_CODE (t) != FUNCTION_DECL
+ && TREE_CODE (t) != TYPENAME_TYPE
+ && TREE_CODE (t) != TEMPLATE_DECL
+ && TREE_CODE (t) != IDENTIFIER_NODE)
+ type = tsubst (type, args, in_decl);
switch (TREE_CODE (t))
{
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
- return build_ptrmemfunc_type
- (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, nargs, in_decl));
-
+ {
+ tree r = build_ptrmemfunc_type
+ (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, in_decl));
+ return cp_build_type_variant (r, TYPE_READONLY (t),
+ TYPE_VOLATILE (t));
+ }
+
/* else fall through */
+ case UNION_TYPE:
+ if (uses_template_parms (t))
+ {
+ tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
+ tree context;
+ tree r;
+ if (TYPE_CONTEXT (t) != NULL_TREE)
+ {
+ context = tsubst (TYPE_CONTEXT (t), args, in_decl);
+
+ if (TREE_CODE (context) != FUNCTION_DECL
+ && TREE_CODE (context) != NAMESPACE_DECL)
+ {
+ /* For a member class template, we need all the
+ template arguments. */
+ if (CLASSTYPE_IS_TEMPLATE (TYPE_CONTEXT (t)))
+ argvec =
+ add_to_template_args (CLASSTYPE_TI_ARGS (context),
+ argvec);
+
+ if (CLASSTYPE_TEMPLATE_INFO (context))
+ argvec =
+ complete_template_args (CLASSTYPE_TI_TEMPLATE (context),
+ argvec, 0);
+ }
+ }
+ else
+ context = NULL_TREE;
+
+ r = lookup_template_class (t, argvec, in_decl, context);
+
+ return cp_build_type_variant (r, TYPE_READONLY (t),
+ TYPE_VOLATILE (t));
+ }
+
+ /* else fall through */
case ERROR_MARK:
case IDENTIFIER_NODE:
case OP_IDENTIFIER:
case VOID_TYPE:
case REAL_TYPE:
- case ENUMERAL_TYPE:
+ case COMPLEX_TYPE:
case BOOLEAN_TYPE:
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
- case UNION_TYPE:
+ case NAMESPACE_DECL:
return t;
+ case ENUMERAL_TYPE:
+ {
+ tree ctx = tsubst (TYPE_CONTEXT (t), args, in_decl);
+ if (ctx == NULL_TREE || TREE_CODE (ctx) == NAMESPACE_DECL)
+ return t;
+ else if (ctx == current_function_decl)
+ return lookup_name (TYPE_IDENTIFIER (t), 1);
+ else
+ return lookup_nested_type_by_name (ctx, TYPE_IDENTIFIER (t));
+ }
+
case INTEGER_TYPE:
if (t == integer_type_node)
return t;
@@ -1191,296 +4315,526 @@ tsubst (t, args, nargs, in_decl)
if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
&& TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
return t;
- return build_index_2_type
- (tsubst (TYPE_MIN_VALUE (t), args, nargs, in_decl),
- tsubst (TYPE_MAX_VALUE (t), args, nargs, in_decl));
- case TEMPLATE_TYPE_PARM:
{
- tree arg = args[TEMPLATE_TYPE_IDX (t)];
- return cp_build_type_variant
- (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
- TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
- }
+ tree max = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
+ max = tsubst_expr (max, args, in_decl);
+ if (processing_template_decl)
+ {
+ tree itype = make_node (INTEGER_TYPE);
+ TYPE_MIN_VALUE (itype) = size_zero_node;
+ TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max,
+ integer_one_node);
+ return itype;
+ }
- case TEMPLATE_CONST_PARM:
- return args[TEMPLATE_CONST_IDX (t)];
+ max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1));
+ return build_index_2_type (size_zero_node, max);
+ }
- case FUNCTION_DECL:
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
+ case TEMPLATE_PARM_INDEX:
{
- tree r;
- tree fnargs, result;
-
- if (type == TREE_TYPE (t)
- && (DECL_CONTEXT (t) == NULL_TREE
- || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't'))
- return t;
- fnargs = tsubst (DECL_ARGUMENTS (t), args, nargs, t);
- result = tsubst (DECL_RESULT (t), args, nargs, t);
- if (DECL_CONTEXT (t) != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't')
+ int idx;
+ int level;
+ int levels;
+ tree r = NULL_TREE;
+
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
{
- /* Look it up in that class, and return the decl node there,
- instead of creating a new one. */
- tree ctx, methods, name, method;
- int n_methods;
- int i, found = 0;
-
- name = DECL_NAME (t);
- ctx = tsubst (DECL_CONTEXT (t), args, nargs, t);
- methods = CLASSTYPE_METHOD_VEC (ctx);
- if (methods == NULL_TREE)
- /* No methods at all -- no way this one can match. */
- goto no_match;
- n_methods = TREE_VEC_LENGTH (methods);
-
- r = NULL_TREE;
-
- if (!strncmp (OPERATOR_TYPENAME_FORMAT,
- IDENTIFIER_POINTER (name),
- sizeof (OPERATOR_TYPENAME_FORMAT) - 1))
- {
- /* Type-conversion operator. Reconstruct the name, in
- case it's the name of one of the template's parameters. */
- name = build_typename_overload (TREE_TYPE (type));
- }
+ idx = TEMPLATE_TYPE_IDX (t);
+ level = TEMPLATE_TYPE_LEVEL (t);
+ }
+ else
+ {
+ idx = TEMPLATE_PARM_IDX (t);
+ level = TEMPLATE_PARM_LEVEL (t);
+ }
- if (DECL_CONTEXT (t) != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'
- && constructor_name (DECL_CONTEXT (t)) == DECL_NAME (t))
- name = constructor_name (ctx);
+ if (TREE_VEC_LENGTH (args) > 0)
+ {
+ tree arg = NULL_TREE;
- if (DECL_CONSTRUCTOR_P (t) && TYPE_USES_VIRTUAL_BASECLASSES (ctx))
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
{
- /* Since we didn't know that this class had virtual bases until after
- we instantiated it, we have to recreate the arguments to this
- constructor, as otherwise it would miss the __in_chrg parameter. */
- tree newtype, parm;
- tree parms = TREE_CHAIN (TYPE_ARG_TYPES (type));
- parms = hash_tree_chain (integer_type_node, parms);
- newtype = build_cplus_method_type (ctx,
- TREE_TYPE (type),
- parms);
- newtype = build_type_variant (newtype,
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- type = newtype;
-
- fnargs = copy_node (DECL_ARGUMENTS (t));
- TREE_CHAIN (fnargs) = TREE_CHAIN (DECL_ARGUMENTS (t));
-
- /* In this case we need "in-charge" flag saying whether
- this constructor is responsible for initialization
- of virtual baseclasses or not. */
- parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
- /* Mark the artificial `__in_chrg' parameter as "artificial". */
- SET_DECL_ARTIFICIAL (parm);
- DECL_ARG_TYPE (parm) = integer_type_node;
- DECL_REGISTER (parm) = 1;
- TREE_CHAIN (parm) = TREE_CHAIN (fnargs);
- TREE_CHAIN (fnargs) = parm;
-
- fnargs = tsubst (fnargs, args, nargs, t);
+ levels = TREE_VEC_LENGTH (args);
+ if (level <= levels)
+ arg = TREE_VEC_ELT
+ (TREE_VEC_ELT (args, level - 1), idx);
}
-#if 0
- fprintf (stderr, "\nfor function %s in class %s:\n",
- IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));
-#endif
- for (i = 0; i < n_methods; i++)
+ else
{
- int pass;
-
- method = TREE_VEC_ELT (methods, i);
- if (method == NULL_TREE || DECL_NAME (method) != name)
- continue;
+ levels = 1;
+ if (level == 1)
+ arg = TREE_VEC_ELT (args, idx);
+ }
- pass = 0;
- maybe_error:
- for (; method; method = DECL_CHAIN (method))
+ if (arg != NULL_TREE)
+ {
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ return cp_build_type_variant
+ (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
+ TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
+ else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
{
- my_friendly_assert (TREE_CODE (method) == FUNCTION_DECL,
- 282);
- if (! comptypes (type, TREE_TYPE (method), 1))
+ if (CLASSTYPE_TEMPLATE_INFO (t))
{
- tree mtype = TREE_TYPE (method);
- tree t1, t2;
-
- /* Keep looking for a method that matches
- perfectly. This takes care of the problem
- where destructors (which have implicit int args)
- look like constructors which have an int arg. */
- if (pass == 0)
- continue;
-
- t1 = TYPE_ARG_TYPES (mtype);
- t2 = TYPE_ARG_TYPES (type);
- if (TREE_CODE (mtype) == FUNCTION_TYPE)
- t2 = TREE_CHAIN (t2);
-
- if (list_eq (t1, t2))
- {
- if (TREE_CODE (mtype) == FUNCTION_TYPE)
- {
- tree newtype;
- newtype = build_function_type (TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
- newtype = build_type_variant (newtype,
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- type = newtype;
- if (TREE_TYPE (type) != TREE_TYPE (mtype))
- goto maybe_bad_return_type;
- }
- else if (TYPE_METHOD_BASETYPE (mtype)
- == TYPE_METHOD_BASETYPE (type))
- {
- /* Types didn't match, but arg types and
- `this' do match, so the return type is
- all that should be messing it up. */
- maybe_bad_return_type:
- if (TREE_TYPE (type) != TREE_TYPE (mtype))
- error ("inconsistent return types for method `%s' in class `%s'",
- IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));
- }
- r = method;
- break;
- }
- found = 1;
- continue;
+ /* We are processing a type constructed from
+ a template template parameter */
+ tree argvec = tsubst (CLASSTYPE_TI_ARGS (t),
+ args, in_decl);
+ tree r;
+
+ /* We can get a TEMPLATE_TEMPLATE_PARM here when
+ we are resolving nested-types in the signature of
+ a member function templates.
+ Otherwise ARG is a TEMPLATE_DECL and is the real
+ template to be instantiated. */
+ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ arg = TYPE_NAME (arg);
+
+ r = lookup_template_class (DECL_NAME (arg),
+ argvec, in_decl,
+ DECL_CONTEXT (arg));
+ return cp_build_type_variant (r, TYPE_READONLY (t),
+ TYPE_VOLATILE (t));
}
-#if 0
- fprintf (stderr, "\tfound %s\n\n",
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method)));
-#endif
- if (DECL_ARTIFICIAL (method))
- {
- cp_error ("template for method `%D' which has default implementation in class `%T'", name, ctx);
- if (in_decl)
- cp_error_at ("in attempt to instantiate `%D' declared at this point in file", in_decl);
- return error_mark_node;
- }
-
- if (DECL_ARGUMENTS (method)
- && ! TREE_PERMANENT (DECL_ARGUMENTS (method)))
- /* @@ Is this early enough? Might we want to do
- this instead while processing the expansion? */
- DECL_ARGUMENTS (method)
- = tsubst (DECL_ARGUMENTS (t), args, nargs, t);
- r = method;
- break;
- }
- if (r == NULL_TREE && pass == 0)
- {
- pass = 1;
- method = TREE_VEC_ELT (methods, i);
- goto maybe_error;
+ else
+ /* We are processing a template argument list. */
+ return arg;
}
+ else
+ return arg;
}
- if (r == NULL_TREE)
+ }
+
+ if (level == 1)
+ /* This can happen during the attempted tsubst'ing in
+ unify. This means that we don't yet have any information
+ about the template parameter in question. */
+ return t;
+
+ /* If we get here, we must have been looking at a parm for a
+ more deeply nested template. Make a new version of this
+ template parameter, but with a lower level. */
+ switch (TREE_CODE (t))
+ {
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
+ r = copy_node (t);
+ TEMPLATE_TYPE_PARM_INDEX (r)
+ = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
+ r, levels);
+ TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
+ TYPE_MAIN_VARIANT (r) = r;
+ TYPE_POINTER_TO (r) = NULL_TREE;
+ TYPE_REFERENCE_TO (r) = NULL_TREE;
+
+ if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
+ && CLASSTYPE_TEMPLATE_INFO (t))
{
- no_match:
- cp_error
- (found
- ? "template for method `%D' doesn't match any in class `%T'"
- : "method `%D' not found in class `%T'", name, ctx);
- if (in_decl)
- cp_error_at ("in attempt to instantiate `%D' declared at this point in file", in_decl);
- return error_mark_node;
+ tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
+ CLASSTYPE_TEMPLATE_INFO (r)
+ = perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
}
+ break;
+
+ case TEMPLATE_PARM_INDEX:
+ r = reduce_template_parm_level (t, type, levels);
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
+
+ return r;
+ }
+
+ case TEMPLATE_DECL:
+ {
+ /* We can get here when processing a member template function
+ of a template class. */
+ tree tmpl;
+ tree decl = DECL_TEMPLATE_RESULT (t);
+ tree parms;
+ tree* new_parms;
+ tree spec;
+ int is_template_template_parm = DECL_TEMPLATE_TEMPLATE_PARM_P (t);
+
+ if (!is_template_template_parm)
+ {
+ /* We might already have an instance of this template. */
+ spec = retrieve_specialization (t, args);
+ if (spec != NULL_TREE)
+ return spec;
+ }
+
+ /* Make a new template decl. It will be similar to the
+ original, but will record the current template arguments.
+ We also create a new function declaration, which is just
+ like the old one, but points to this new template, rather
+ than the old one. */
+ tmpl = copy_node (t);
+ copy_lang_decl (tmpl);
+ my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0);
+ TREE_CHAIN (tmpl) = NULL_TREE;
+
+ if (is_template_template_parm)
+ {
+ tree new_decl = tsubst (decl, args, in_decl);
+ DECL_RESULT (tmpl) = new_decl;
+ TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
+ return tmpl;
+ }
+
+ DECL_CONTEXT (tmpl) = tsubst (DECL_CONTEXT (t),
+ args, in_decl);
+ DECL_CLASS_CONTEXT (tmpl) = tsubst (DECL_CLASS_CONTEXT (t),
+ args, in_decl);
+ DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args);
+
+ if (TREE_CODE (decl) == TYPE_DECL)
+ {
+ tree new_type = tsubst (TREE_TYPE (t), args, in_decl);
+ TREE_TYPE (tmpl) = new_type;
+ CLASSTYPE_TI_TEMPLATE (new_type) = tmpl;
+ DECL_RESULT (tmpl) = TYPE_MAIN_DECL (new_type);
}
else
{
- r = DECL_NAME (t);
- {
- tree decls;
- int got_it = 0;
-
- decls = lookup_name_nonclass (r);
- if (decls == NULL_TREE)
- /* no match */;
- else if (TREE_CODE (decls) == TREE_LIST)
- for (decls = TREE_VALUE (decls); decls ;
- decls = DECL_CHAIN (decls))
- {
- if (TREE_CODE (decls) == FUNCTION_DECL
- && TREE_TYPE (decls) == type)
- {
- got_it = 1;
- r = decls;
- break;
- }
- }
- else
- {
- tree val = decls;
- decls = NULL_TREE;
- if (TREE_CODE (val) == FUNCTION_DECL
- && TREE_TYPE (val) == type)
- {
- got_it = 1;
- r = val;
- }
- }
+ tree new_decl = tsubst (decl, args, in_decl);
+ DECL_RESULT (tmpl) = new_decl;
+ DECL_TI_TEMPLATE (new_decl) = tmpl;
+ TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
+ }
- if (!got_it)
- {
- tree a = build_decl_overload (r, TYPE_VALUES (type),
- DECL_CONTEXT (t) != NULL_TREE);
- r = build_lang_decl (FUNCTION_DECL, r, type);
- DECL_ASSEMBLER_NAME (r) = a;
- }
- else if (TREE_STATIC (r))
- {
- /* This overrides the template version, use it. */
- return r;
- }
- }
+ DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE;
+ SET_DECL_IMPLICIT_INSTANTIATION (tmpl);
+
+ /* The template parameters for this new template are all the
+ template parameters for the old template, except the
+ outermost level of parameters. */
+ for (new_parms = &DECL_TEMPLATE_PARMS (tmpl),
+ parms = DECL_TEMPLATE_PARMS (t);
+ TREE_CHAIN (parms) != NULL_TREE;
+ new_parms = &(TREE_CHAIN (*new_parms)),
+ parms = TREE_CHAIN (parms))
+ {
+ tree new_vec =
+ make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms)));
+ int i;
+
+ for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
+ {
+ tree default_value =
+ TREE_PURPOSE (TREE_VEC_ELT (TREE_VALUE (parms), i));
+ tree parm_decl =
+ TREE_VALUE (TREE_VEC_ELT (TREE_VALUE (parms), i));
+
+ TREE_VEC_ELT (new_vec, i)
+ = build_tree_list (tsubst (default_value, args, in_decl),
+ tsubst (parm_decl, args, in_decl));
+
+ }
+
+ *new_parms =
+ tree_cons (build_int_2 (0,
+ TREE_INT_CST_HIGH
+ (TREE_PURPOSE (parms)) - 1),
+ new_vec,
+ NULL_TREE);
}
- TREE_PUBLIC (r) = 1;
- DECL_EXTERNAL (r) = 1;
+
+ if (PRIMARY_TEMPLATE_P (t))
+ DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+
+ /* We don't partially instantiate partial specializations. */
+ if (TREE_CODE (decl) == TYPE_DECL)
+ return tmpl;
+
+ /* What should we do with the specializations of this member
+ template? Are they specializations of this new template,
+ or instantiations of the templates they previously were?
+ this new template? And where should their
+ DECL_TI_TEMPLATES point? */
+ DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = NULL_TREE;
+ for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
+ spec != NULL_TREE;
+ spec = TREE_CHAIN (spec))
+ {
+ /* It helps to consider example here. Consider:
+
+ template <class T>
+ struct S {
+ template <class U>
+ void f(U u);
+
+ template <>
+ void f(T* t) {}
+ };
+
+ Now, for example, we are instantiating S<int>::f(U u).
+ We want to make a template:
+
+ template <class U>
+ void S<int>::f(U);
+
+ It will have a specialization, for the case U = int*, of
+ the form:
+
+ template <>
+ void S<int>::f<int*>(int*);
+
+ This specialization will be an instantiation of
+ the specialization given in the declaration of S, with
+ argument list int*. */
+
+ tree fn = TREE_VALUE (spec);
+ tree spec_args;
+ tree new_fn;
+
+ if (!DECL_TEMPLATE_SPECIALIZATION (fn))
+ /* Instantiations are on the same list, but they're of
+ no concern to us. */
+ continue;
+
+ spec_args = tsubst (DECL_TI_ARGS (fn), args,
+ in_decl);
+ new_fn = tsubst (DECL_RESULT (fn), args,
+ in_decl);
+ DECL_TEMPLATE_SPECIALIZATIONS (tmpl) =
+ perm_tree_cons (spec_args, new_fn,
+ DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+ }
+
+ /* Record this partial instantiation. */
+ register_specialization (tmpl, t, args);
+
+ return tmpl;
+ }
+
+ case FUNCTION_DECL:
+ {
+ tree r = NULL_TREE;
+ tree ctx;
+ tree argvec;
+ tree tmpl = NULL_TREE;
+ int member;
+
+ if (DECL_CLASS_SCOPE_P (t))
+ {
+ if (DECL_NAME (t) == constructor_name (DECL_CONTEXT (t)))
+ member = 2;
+ else
+ member = 1;
+ ctx = tsubst (DECL_CLASS_CONTEXT (t), args, t);
+ }
+ else
+ {
+ member = 0;
+ ctx = NULL_TREE;
+ }
+ type = tsubst (type, args, in_decl);
+
+ /* If we are instantiating a specialization, get the other args. */
+ if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
+ {
+ tree spec;
+
+ tmpl = DECL_TI_TEMPLATE (t);
+
+ /* Start by getting the innermost args. */
+ if (DECL_TEMPLATE_SPECIALIZATION (tmpl))
+ argvec = args;
+ else
+ argvec = tsubst (DECL_TI_ARGS (t), args, in_decl);
+
+ if (DECL_TEMPLATE_INFO (tmpl))
+ argvec = complete_template_args (tmpl, argvec, 0);
+
+ /* Do we already have this instantiation? */
+ spec = retrieve_specialization (tmpl, argvec);
+ if (spec)
+ return spec;
+ }
+
+ /* We do NOT check for matching decls pushed separately at this
+ point, as they may not represent instantiations of this
+ template, and in any case are considered separate under the
+ discrete model. Instead, see add_maybe_template. */
+
+ r = copy_node (t);
+ copy_lang_decl (r);
+ DECL_USE_TEMPLATE (r) = 0;
+ TREE_TYPE (r) = type;
+
+ DECL_CONTEXT (r)
+ = tsubst (DECL_CONTEXT (t), args, t);
+ DECL_CLASS_CONTEXT (r) = ctx;
+
+ if (member && !strncmp (OPERATOR_TYPENAME_FORMAT,
+ IDENTIFIER_POINTER (DECL_NAME (r)),
+ sizeof (OPERATOR_TYPENAME_FORMAT) - 1))
+ {
+ /* Type-conversion operator. Reconstruct the name, in
+ case it's the name of one of the template's parameters. */
+ DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
+ }
+
+ DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t);
+ DECL_MAIN_VARIANT (r) = r;
+ DECL_RESULT (r) = NULL_TREE;
+ DECL_INITIAL (r) = NULL_TREE;
+
TREE_STATIC (r) = 0;
+ TREE_PUBLIC (r) = TREE_PUBLIC (t);
+ DECL_EXTERNAL (r) = 1;
DECL_INTERFACE_KNOWN (r) = 0;
- DECL_INLINE (r) = DECL_INLINE (t);
- DECL_THIS_INLINE (r) = DECL_THIS_INLINE (t);
- TREE_READONLY (r) = TREE_READONLY (t);
- TREE_THIS_VOLATILE (r) = TREE_THIS_VOLATILE (t);
- {
-#if 0 /* Maybe later. -jason */
- struct tinst_level *til = tinst_for_decl();
+ DECL_DEFER_OUTPUT (r) = 0;
+ TREE_CHAIN (r) = NULL_TREE;
+ DECL_PENDING_INLINE_INFO (r) = 0;
+ TREE_USED (r) = 0;
- /* should always be true under new approach */
- if (til)
- {
- DECL_SOURCE_FILE (r) = til->file;
- DECL_SOURCE_LINE (r) = til->line;
- }
- else
-#endif
- {
- DECL_SOURCE_FILE (r) = DECL_SOURCE_FILE (t);
- DECL_SOURCE_LINE (r) = DECL_SOURCE_LINE (t);
- }
- }
- DECL_CLASS_CONTEXT (r) = tsubst (DECL_CLASS_CONTEXT (t), args, nargs, t);
+ if (DECL_CONSTRUCTOR_P (r))
+ {
+ maybe_retrofit_in_chrg (r);
+ grok_ctor_properties (ctx, r);
+ }
+ if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
+ grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
+
+ if (DECL_DESTRUCTOR_P (t))
+ DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
+ else
+ {
+ /* Instantiations of template functions must be mangled
+ specially, in order to conform to 14.5.5.1
+ [temp.over.link]. We use in_decl below rather than
+ DECL_TI_TEMPLATE (r) because the latter is set to
+ NULL_TREE in instantiate_decl. */
+ tree tmpl;
+ tree arg_types;
+
+ if (DECL_TEMPLATE_INFO (r))
+ tmpl = DECL_TI_TEMPLATE (r);
+ else
+ tmpl = in_decl;
+
+ /* tmpl will be NULL if this is a specialization of a
+ member function of a template class. */
+ if (name_mangling_version < 1
+ || tmpl == NULL_TREE
+ || (member && !is_member_template (tmpl)
+ && !DECL_TEMPLATE_INFO (tmpl)))
+ {
+ arg_types = TYPE_ARG_TYPES (type);
+ if (member && TREE_CODE (type) == FUNCTION_TYPE)
+ arg_types = hash_tree_chain
+ (build_pointer_type (DECL_CONTEXT (r)),
+ arg_types);
+
+ DECL_ASSEMBLER_NAME (r)
+ = build_decl_overload (DECL_NAME (r), arg_types,
+ member);
+ }
+ else
+ {
+ tree tparms;
+ tree targs;
+
+ if (!DECL_TEMPLATE_SPECIALIZATION (tmpl))
+ {
+ /* We pass the outermost template parameters to
+ build_template_decl_overload, since the innermost
+ template parameters are still just template
+ parameters; there are no corresponding subsitution
+ arguments. Levels of parms that have been bound
+ before are not represented in DECL_TEMPLATE_PARMS. */
+ tparms = DECL_TEMPLATE_PARMS (tmpl);
+ while (tparms && TREE_CHAIN (tparms) != NULL_TREE)
+ tparms = TREE_CHAIN (tparms);
+
+ targs = innermost_args (args, 0);
+ }
+ else
+ {
+ /* If the template is a specialization, then it is
+ a member template specialization. We have
+ something like:
+
+ template <class T> struct S {
+ template <int i> void f();
+ template <> void f<7>();
+ };
+
+ and now we are forming S<double>::f<7>.
+ Therefore, the template parameters of interest
+ are those that are specialized by the template
+ (i.e., the int), not those we are using to
+ instantiate the template, i.e. the double. */
+ tparms = DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (tmpl));
+ targs = DECL_TI_ARGS (tmpl);
+ }
+
+ my_friendly_assert (tparms != NULL_TREE
+ && TREE_CODE (tparms) == TREE_LIST,
+ 0);
+ tparms = TREE_VALUE (tparms);
+
+ arg_types = TYPE_ARG_TYPES (TREE_TYPE (tmpl));
+ if (member && TREE_CODE (type) == FUNCTION_TYPE)
+ arg_types = hash_tree_chain
+ (build_pointer_type (DECL_CONTEXT (r)),
+ arg_types);
+
+ DECL_ASSEMBLER_NAME (r)
+ = build_template_decl_overload
+ (r, arg_types, TREE_TYPE (TREE_TYPE (tmpl)),
+ tparms, targs, member);
+ }
+ }
+ DECL_RTL (r) = 0;
make_decl_rtl (r, NULL_PTR, 1);
- DECL_ARGUMENTS (r) = fnargs;
- DECL_RESULT (r) = result;
-#if 0
- if (DECL_CONTEXT (t) == NULL_TREE
- || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't')
- push_overloaded_decl_top_level (r, 0);
-#endif
+
+ if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
+ {
+ DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
+
+ /* If we're not using ANSI overloading, then we might have
+ called duplicate_decls above, and gotten back an
+ preexisting version of this function. We treat such a
+ function as a specialization. Otherwise, we cleared
+ both TREE_STATIC and DECL_TEMPLATE_SPECIALIZATION, so
+ this condition will be false. */
+ if (TREE_STATIC (r) || DECL_TEMPLATE_SPECIALIZATION (r))
+ SET_DECL_TEMPLATE_SPECIALIZATION (r);
+ else
+ SET_DECL_IMPLICIT_INSTANTIATION (r);
+
+ register_specialization (r, tmpl, argvec);
+ }
+
+ /* Like grokfndecl. If we don't do this, pushdecl will mess up our
+ TREE_CHAIN because it doesn't find a previous decl. Sigh. */
+ if (member
+ && IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r)) == NULL_TREE)
+ SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
+
return r;
}
case PARM_DECL:
{
- tree r;
- r = build_decl (PARM_DECL, DECL_NAME (t), type);
- DECL_INITIAL (r) = TREE_TYPE (r);
- DECL_ARTIFICIAL (r) = DECL_ARTIFICIAL (t);
+ tree r = copy_node (t);
+ TREE_TYPE (r) = type;
+ if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
+ DECL_INITIAL (r) = TREE_TYPE (r);
+ else
+ DECL_INITIAL (r) = tsubst (DECL_INITIAL (r), args, in_decl);
+
+ DECL_CONTEXT (r) = NULL_TREE;
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
@@ -1488,10 +4842,98 @@ tsubst (t, args, nargs, in_decl)
DECL_ARG_TYPE (r) = integer_type_node;
#endif
if (TREE_CHAIN (t))
- TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, nargs, TREE_CHAIN (t));
+ TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (t));
+ return r;
+ }
+
+ case FIELD_DECL:
+ {
+ tree r = copy_node (t);
+ TREE_TYPE (r) = type;
+ copy_lang_decl (r);
+#if 0
+ DECL_FIELD_CONTEXT (r) = tsubst (DECL_FIELD_CONTEXT (t), args, in_decl);
+#endif
+ DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args, in_decl);
+ TREE_CHAIN (r) = NULL_TREE;
+ if (TREE_CODE (type) == VOID_TYPE)
+ cp_error_at ("instantiation of `%D' as type void", r);
+ return r;
+ }
+
+ case USING_DECL:
+ {
+ tree r = copy_node (t);
+ DECL_INITIAL (r)
+ = tsubst_copy (DECL_INITIAL (t), args, in_decl);
+ TREE_CHAIN (r) = NULL_TREE;
+ return r;
+ }
+
+ case VAR_DECL:
+ {
+ tree r;
+ tree ctx = tsubst_copy (DECL_CONTEXT (t), args, in_decl);
+
+ /* Do we already have this instantiation? */
+ if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
+ {
+ tree tmpl = DECL_TI_TEMPLATE (t);
+ tree decls = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+
+ for (; decls; decls = TREE_CHAIN (decls))
+ if (DECL_CONTEXT (TREE_VALUE (decls)) == ctx)
+ return TREE_VALUE (decls);
+ }
+
+ r = copy_node (t);
+ TREE_TYPE (r) = type;
+ DECL_CONTEXT (r) = ctx;
+ if (TREE_STATIC (r))
+ DECL_ASSEMBLER_NAME (r)
+ = build_static_name (DECL_CONTEXT (r), DECL_NAME (r));
+
+ /* Don't try to expand the initializer until someone tries to use
+ this variable; otherwise we run into circular dependencies. */
+ DECL_INITIAL (r) = NULL_TREE;
+
+ DECL_RTL (r) = 0;
+ DECL_SIZE (r) = 0;
+
+ if (DECL_LANG_SPECIFIC (r))
+ {
+ copy_lang_decl (r);
+ DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
+ }
+
+ if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
+ {
+ tree tmpl = DECL_TI_TEMPLATE (t);
+ tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+ tree argvec = tsubst (DECL_TI_ARGS (t), args, in_decl);
+
+ DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
+ *declsp = perm_tree_cons (argvec, r, *declsp);
+ SET_DECL_IMPLICIT_INSTANTIATION (r);
+ }
+ TREE_CHAIN (r) = NULL_TREE;
+ if (TREE_CODE (type) == VOID_TYPE)
+ cp_error_at ("instantiation of `%D' as type void", r);
return r;
}
+ case TYPE_DECL:
+ if (t == TYPE_NAME (TREE_TYPE (t)))
+ return TYPE_NAME (type);
+
+ {
+ tree r = copy_node (t);
+ TREE_TYPE (r) = type;
+ DECL_CONTEXT (r) = current_class_type;
+ TREE_CHAIN (r) = NULL_TREE;
+ return r;
+ }
+
case TREE_LIST:
{
tree purpose, value, chain, result;
@@ -1506,13 +4948,13 @@ tsubst (t, args, nargs, in_decl)
purpose = TREE_PURPOSE (t);
if (purpose)
- purpose = tsubst (purpose, args, nargs, in_decl);
+ purpose = tsubst (purpose, args, in_decl);
value = TREE_VALUE (t);
if (value)
- value = tsubst (value, args, nargs, in_decl);
+ value = tsubst (value, args, in_decl);
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
- chain = tsubst (chain, args, nargs, in_decl);
+ chain = tsubst (chain, args, in_decl);
if (purpose == TREE_PURPOSE (t)
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
@@ -1523,59 +4965,119 @@ tsubst (t, args, nargs, in_decl)
return result;
}
case TREE_VEC:
- {
- int len = TREE_VEC_LENGTH (t), need_new = 0, i;
- tree *elts = (tree *) alloca (len * sizeof (tree));
- bzero ((char *) elts, len * sizeof (tree));
+ if (type != NULL_TREE)
+ {
+ /* A binfo node. We always need to make a copy, of the node
+ itself and of its BINFO_BASETYPES. */
- for (i = 0; i < len; i++)
- {
- elts[i] = tsubst (TREE_VEC_ELT (t, i), args, nargs, in_decl);
- if (elts[i] != TREE_VEC_ELT (t, i))
- need_new = 1;
- }
+ t = copy_node (t);
- if (!need_new)
+ /* Make sure type isn't a typedef copy. */
+ type = BINFO_TYPE (TYPE_BINFO (type));
+
+ TREE_TYPE (t) = complete_type (type);
+ if (IS_AGGR_TYPE (type))
+ {
+ BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (type);
+ BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (type);
+ if (TYPE_BINFO_BASETYPES (type) != NULL_TREE)
+ BINFO_BASETYPES (t) = copy_node (TYPE_BINFO_BASETYPES (type));
+ }
return t;
+ }
+
+ /* Otherwise, a vector of template arguments. */
+ return tsubst_template_arg_vector (t, args);
- t = make_tree_vec (len);
- for (i = 0; i < len; i++)
- TREE_VEC_ELT (t, i) = elts[i];
- return t;
- }
case POINTER_TYPE:
case REFERENCE_TYPE:
{
tree r;
enum tree_code code;
+
if (type == TREE_TYPE (t))
return t;
code = TREE_CODE (t);
- if (code == POINTER_TYPE)
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ static int last_line = 0;
+ static char* last_file = 0;
+
+ /* We keep track of the last time we issued this error
+ message to avoid spewing a ton of messages during a
+ single bad template instantiation. */
+ if (last_line != lineno ||
+ last_file != input_filename)
+ {
+ cp_error ("cannot form type %s to reference type %T during template instantiation",
+ (code == POINTER_TYPE) ? "pointer" : "reference",
+ type);
+ last_line = lineno;
+ last_file = input_filename;
+ }
+
+ /* Use the underlying type in an attempt at error
+ recovery; maybe the user meant vector<int> and wrote
+ vector<int&>, or some such. */
+ if (code == REFERENCE_TYPE)
+ r = type;
+ else
+ r = build_pointer_type (TREE_TYPE (type));
+ }
+ else if (code == POINTER_TYPE)
r = build_pointer_type (type);
else
r = build_reference_type (type);
r = cp_build_type_variant (r, TYPE_READONLY (t), TYPE_VOLATILE (t));
+
/* Will this ever be needed for TYPE_..._TO values? */
layout_type (r);
return r;
}
case OFFSET_TYPE:
return build_offset_type
- (tsubst (TYPE_OFFSET_BASETYPE (t), args, nargs, in_decl), type);
+ (tsubst (TYPE_OFFSET_BASETYPE (t), args, in_decl), type);
case FUNCTION_TYPE:
case METHOD_TYPE:
{
tree values = TYPE_ARG_TYPES (t);
tree context = TYPE_CONTEXT (t);
- tree new_value;
+ tree raises = TYPE_RAISES_EXCEPTIONS (t);
+ tree fntype;
/* Don't bother recursing if we know it won't change anything. */
if (values != void_list_node)
- values = tsubst (values, args, nargs, in_decl);
+ {
+ /* This should probably be rewritten to use hash_tree_cons for
+ the memory savings. */
+ tree first = NULL_TREE;
+ tree last = NULL_TREE;
+
+ for (; values && values != void_list_node;
+ values = TREE_CHAIN (values))
+ {
+ tree value = TYPE_MAIN_VARIANT (type_decays_to
+ (tsubst (TREE_VALUE (values), args, in_decl)));
+ /* Don't instantiate default args unless they are used.
+ Handle it in build_over_call instead. */
+ tree purpose = TREE_PURPOSE (values);
+ tree x = build_tree_list (purpose, value);
+
+ if (first)
+ TREE_CHAIN (last) = x;
+ else
+ first = x;
+ last = x;
+ }
+
+ if (values == void_list_node)
+ TREE_CHAIN (last) = void_list_node;
+
+ values = first;
+ }
if (context)
- context = tsubst (context, args, nargs, in_decl);
+ context = tsubst (context, args, in_decl);
/* Could also optimize cases where return value and
values have common elements (e.g., T min(const &T, const T&). */
@@ -1589,38 +5091,43 @@ tsubst (t, args, nargs, in_decl)
if (TREE_CODE (t) == FUNCTION_TYPE
&& context == NULL_TREE)
{
- new_value = build_function_type (type, values);
+ fntype = build_function_type (type, values);
}
else if (context == NULL_TREE)
{
tree base = tsubst (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))),
- args, nargs, in_decl);
- new_value = build_cplus_method_type (base, type,
- TREE_CHAIN (values));
+ args, in_decl);
+ fntype = build_cplus_method_type (base, type,
+ TREE_CHAIN (values));
}
else
{
- new_value = make_node (TREE_CODE (t));
- TREE_TYPE (new_value) = type;
- TYPE_CONTEXT (new_value) = context;
- TYPE_VALUES (new_value) = values;
- TYPE_SIZE (new_value) = TYPE_SIZE (t);
- TYPE_ALIGN (new_value) = TYPE_ALIGN (t);
- TYPE_MODE (new_value) = TYPE_MODE (t);
+ fntype = make_node (TREE_CODE (t));
+ TREE_TYPE (fntype) = type;
+ TYPE_CONTEXT (fntype) = FROB_CONTEXT (context);
+ TYPE_VALUES (fntype) = values;
+ TYPE_SIZE (fntype) = TYPE_SIZE (t);
+ TYPE_ALIGN (fntype) = TYPE_ALIGN (t);
+ TYPE_MODE (fntype) = TYPE_MODE (t);
if (TYPE_METHOD_BASETYPE (t))
- TYPE_METHOD_BASETYPE (new_value) = tsubst (TYPE_METHOD_BASETYPE (t),
- args, nargs, in_decl);
+ TYPE_METHOD_BASETYPE (fntype) = tsubst (TYPE_METHOD_BASETYPE (t),
+ args, in_decl);
/* Need to generate hash value. */
my_friendly_abort (84);
}
- new_value = build_type_variant (new_value,
- TYPE_READONLY (t),
- TYPE_VOLATILE (t));
- return new_value;
+ fntype = build_type_variant (fntype,
+ TYPE_READONLY (t),
+ TYPE_VOLATILE (t));
+ if (raises)
+ {
+ raises = tsubst (raises, args, in_decl);
+ fntype = build_exception_variant (fntype, raises);
+ }
+ return fntype;
}
case ARRAY_TYPE:
{
- tree domain = tsubst (TYPE_DOMAIN (t), args, nargs, in_decl);
+ tree domain = tsubst (TYPE_DOMAIN (t), args, in_decl);
tree r;
if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t))
return t;
@@ -1628,421 +5135,932 @@ tsubst (t, args, nargs, in_decl)
return r;
}
- case UNINSTANTIATED_P_TYPE:
- {
- int nparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (UPT_TEMPLATE (t)));
- tree argvec = make_tree_vec (nparms);
- tree parmvec = UPT_PARMS (t);
- int i;
- tree id, rt;
- for (i = 0; i < nparms; i++)
- TREE_VEC_ELT (argvec, i) = tsubst (TREE_VEC_ELT (parmvec, i),
- args, nargs, in_decl);
- id = lookup_template_class (DECL_NAME (UPT_TEMPLATE (t)), argvec, NULL_TREE);
- if (! IDENTIFIER_HAS_TYPE_VALUE (id)) {
- instantiate_class_template(id, 0);
- /* set up pending_classes */
- add_pending_template (id);
-
- TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (id)) =
- IDENTIFIER_TYPE_VALUE (id);
- }
- rt = IDENTIFIER_TYPE_VALUE (id);
-
- /* kung: this part handles nested type in template definition */
-
- if ( !ANON_AGGRNAME_P (DECL_NAME(TYPE_NAME(t))))
- {
- rt = search_nested_type_in_tmpl (rt, t);
- }
-
- return build_type_variant (rt, TYPE_READONLY (t), TYPE_VOLATILE (t));
- }
-
- case MINUS_EXPR:
case PLUS_EXPR:
+ case MINUS_EXPR:
return fold (build (TREE_CODE (t), TREE_TYPE (t),
- tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl),
- tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl)));
+ tsubst (TREE_OPERAND (t, 0), args, in_decl),
+ tsubst (TREE_OPERAND (t, 1), args, in_decl)));
case NEGATE_EXPR:
case NOP_EXPR:
return fold (build1 (TREE_CODE (t), TREE_TYPE (t),
- tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl)));
+ tsubst (TREE_OPERAND (t, 0), args, in_decl)));
+
+ case TYPENAME_TYPE:
+ {
+ tree ctx = tsubst (TYPE_CONTEXT (t), args, in_decl);
+ tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args, in_decl);
+ f = make_typename_type (ctx, f);
+ return cp_build_type_variant
+ (f, TYPE_READONLY (f) || TYPE_READONLY (t),
+ TYPE_VOLATILE (f) || TYPE_VOLATILE (t));
+ }
+
+ case INDIRECT_REF:
+ return make_pointer_declarator
+ (type, tsubst (TREE_OPERAND (t, 0), args, in_decl));
+
+ case ADDR_EXPR:
+ return make_reference_declarator
+ (type, tsubst (TREE_OPERAND (t, 0), args, in_decl));
+
+ case ARRAY_REF:
+ return build_parse_node
+ (ARRAY_REF, tsubst (TREE_OPERAND (t, 0), args, in_decl),
+ tsubst_expr (TREE_OPERAND (t, 1), args, in_decl));
+
+ case CALL_EXPR:
+ return make_call_declarator
+ (tsubst (TREE_OPERAND (t, 0), args, in_decl),
+ tsubst (TREE_OPERAND (t, 1), args, in_decl),
+ TREE_OPERAND (t, 2),
+ tsubst (TREE_TYPE (t), args, in_decl));
+
+ case SCOPE_REF:
+ return build_parse_node
+ (TREE_CODE (t), tsubst (TREE_OPERAND (t, 0), args, in_decl),
+ tsubst (TREE_OPERAND (t, 1), args, in_decl));
default:
- sorry ("use of `%s' in function template",
+ sorry ("use of `%s' in template",
tree_code_name [(int) TREE_CODE (t)]);
return error_mark_node;
}
}
+void
+do_pushlevel ()
+{
+ emit_line_note (input_filename, lineno);
+ pushlevel (0);
+ clear_last_expr ();
+ push_momentary ();
+ expand_start_bindings (0);
+}
+
tree
-instantiate_template (tmpl, targ_ptr)
- tree tmpl, *targ_ptr;
+do_poplevel ()
{
- tree targs, fndecl;
- int i, len;
- struct pending_inline *p;
- struct template_info *t;
- struct obstack *old_fmp_obstack;
- extern struct obstack *function_maybepermanent_obstack;
+ tree t;
+ int saved_warn_unused = 0;
- push_obstacks (&permanent_obstack, &permanent_obstack);
- old_fmp_obstack = function_maybepermanent_obstack;
- function_maybepermanent_obstack = &permanent_obstack;
+ if (processing_template_decl)
+ {
+ saved_warn_unused = warn_unused;
+ warn_unused = 0;
+ }
+ expand_end_bindings (getdecls (), kept_level_p (), 0);
+ if (processing_template_decl)
+ warn_unused = saved_warn_unused;
+ t = poplevel (kept_level_p (), 1, 0);
+ pop_momentary ();
+ return t;
+}
- my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
- len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
+/* Like tsubst, but deals with expressions. This function just replaces
+ template parms; to finish processing the resultant expression, use
+ tsubst_expr. */
- i = len;
- while (i--)
- targ_ptr[i] = copy_to_permanent (targ_ptr[i]);
+tree
+tsubst_copy (t, args, in_decl)
+ tree t, args;
+ tree in_decl;
+{
+ enum tree_code code;
- for (fndecl = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
- fndecl; fndecl = TREE_CHAIN (fndecl))
+ if (t == NULL_TREE || t == error_mark_node)
+ return t;
+
+ code = TREE_CODE (t);
+
+ switch (code)
{
- tree *t1 = &TREE_VEC_ELT (TREE_PURPOSE (fndecl), 0);
- for (i = len - 1; i >= 0; i--)
- if (simple_cst_equal (t1[i], targ_ptr[i]) <= 0)
- goto no_match;
+ case PARM_DECL:
+ return do_identifier (DECL_NAME (t), 0, NULL_TREE);
- /* Here, we have a match. */
- fndecl = TREE_VALUE (fndecl);
- goto exit;
+ case CONST_DECL:
+ case FIELD_DECL:
+ if (DECL_CONTEXT (t))
+ {
+ tree ctx;
+ if (TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
+ return lookup_name (DECL_NAME (t), 0);
- no_match:
- ;
- }
+ ctx = tsubst (DECL_CONTEXT (t), args, in_decl);
+ if (ctx != DECL_CONTEXT (t))
+ return lookup_field (ctx, DECL_NAME (t), 0, 0);
+ }
+ return t;
- targs = make_tree_vec (len);
- i = len;
- while (i--)
- TREE_VEC_ELT (targs, i) = targ_ptr[i];
+ case VAR_DECL:
+ case FUNCTION_DECL:
+ if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
+ t = tsubst (t, args, in_decl);
+ mark_used (t);
+ return t;
- /* substitute template parameters */
- fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr,
- TREE_VEC_LENGTH (targs), tmpl);
+ case TEMPLATE_DECL:
+ if (is_member_template (t))
+ return tsubst (t, args, in_decl);
+ else
+ return t;
+
+#if 0
+ case IDENTIFIER_NODE:
+ return do_identifier (t, 0);
+#endif
+
+ case CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case DYNAMIC_CAST_EXPR:
+ return build1
+ (code, tsubst (TREE_TYPE (t), args, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 0), args, in_decl));
- if (fndecl == error_mark_node)
- goto exit;
+ case INDIRECT_REF:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case NEGATE_EXPR:
+ case TRUTH_NOT_EXPR:
+ case BIT_NOT_EXPR:
+ case ADDR_EXPR:
+ case CONVERT_EXPR: /* Unary + */
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ case ARROW_EXPR:
+ case THROW_EXPR:
+ case TYPEID_EXPR:
+ return build1
+ (code, NULL_TREE,
+ tsubst_copy (TREE_OPERAND (t, 0), args, in_decl));
- assemble_external (fndecl);
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case EXACT_DIV_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_ANDTC_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case TRUNC_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case RSHIFT_EXPR:
+ case LSHIFT_EXPR:
+ case RROTATE_EXPR:
+ case LROTATE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ case MAX_EXPR:
+ case MIN_EXPR:
+ case LE_EXPR:
+ case GE_EXPR:
+ case LT_EXPR:
+ case GT_EXPR:
+ case COMPONENT_REF:
+ case ARRAY_REF:
+ case COMPOUND_EXPR:
+ case SCOPE_REF:
+ case DOTSTAR_EXPR:
+ case MEMBER_REF:
+ return build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, in_decl));
- /* If it's a static member fn in the template, we need to change it
- into a FUNCTION_TYPE and chop off its this pointer. */
- if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE
- && DECL_STATIC_FUNCTION_P (fndecl))
- {
- revert_static_member_fn (&DECL_RESULT (tmpl), NULL, NULL);
- /* Chop off the this pointer that grokclassfn so kindly added
- for us (it didn't know yet if the fn was static or not). */
- DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
- }
-
- t = DECL_TEMPLATE_INFO (tmpl);
-
- /* If we have a preexisting version of this function, don't expand
- the template version, use the other instead. */
- if (TREE_STATIC (fndecl) || DECL_TEMPLATE_SPECIALIZATION (fndecl))
- {
- SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
- p = (struct pending_inline *)0;
- }
- else if (t->text)
- {
- SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
- repo_template_used (fndecl);
- p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));
- p->parm_vec = t->parm_vec;
- p->bindings = targs;
- p->can_free = 0;
- p->deja_vu = 0;
- p->buf = t->text;
- p->len = t->length;
- p->fndecl = fndecl;
+ case CALL_EXPR:
{
- int l = lineno;
- char * f = input_filename;
+ tree fn = TREE_OPERAND (t, 0);
+ if (is_overloaded_fn (fn))
+ fn = tsubst_copy (get_first_fn (fn), args, in_decl);
+ else
+ /* Sometimes FN is a LOOKUP_EXPR. */
+ fn = tsubst_copy (fn, args, in_decl);
+ return build_nt
+ (code, fn, tsubst_copy (TREE_OPERAND (t, 1), args, in_decl),
+ NULL_TREE);
+ }
- lineno = p->lineno = t->lineno;
- input_filename = p->filename = t->filename;
+ case METHOD_CALL_EXPR:
+ {
+ tree name = TREE_OPERAND (t, 0);
+ if (TREE_CODE (name) == BIT_NOT_EXPR)
+ {
+ name = tsubst_copy (TREE_OPERAND (name, 0), args, in_decl);
+ name = build1 (BIT_NOT_EXPR, NULL_TREE, name);
+ }
+ else if (TREE_CODE (name) == SCOPE_REF
+ && TREE_CODE (TREE_OPERAND (name, 1)) == BIT_NOT_EXPR)
+ {
+ tree base = tsubst_copy (TREE_OPERAND (name, 0), args, in_decl);
+ name = TREE_OPERAND (name, 1);
+ name = tsubst_copy (TREE_OPERAND (name, 0), args, in_decl);
+ name = build1 (BIT_NOT_EXPR, NULL_TREE, name);
+ name = build_nt (SCOPE_REF, base, name);
+ }
+ else
+ name = tsubst_copy (TREE_OPERAND (t, 0), args, in_decl);
+ return build_nt
+ (code, name, tsubst_copy (TREE_OPERAND (t, 1), args, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, in_decl),
+ NULL_TREE);
+ }
- extract_interface_info ();
+ case BIND_EXPR:
+ case COND_EXPR:
+ case MODOP_EXPR:
+ {
+ tree r = build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, in_decl));
- if (interface_unknown && flag_external_templates)
+ if (code == BIND_EXPR && !processing_template_decl)
{
- if (DECL_CLASS_CONTEXT (fndecl)
- && CLASSTYPE_INTERFACE_KNOWN (DECL_CLASS_CONTEXT (fndecl)))
- {
- interface_unknown = 0;
- interface_only
- = CLASSTYPE_INTERFACE_ONLY (DECL_CLASS_CONTEXT (fndecl));
- }
- else if (! DECL_IN_SYSTEM_HEADER (tmpl))
- warn_if_unknown_interface (tmpl);
+ /* This processing should really occur in tsubst_expr,
+ However, tsubst_expr does not recurse into expressions,
+ since it assumes that there aren't any statements
+ inside them. Instead, it simply calls
+ build_expr_from_tree. So, we need to expand the
+ BIND_EXPR here. */
+ tree rtl_expr = begin_stmt_expr ();
+ tree block = tsubst_expr (TREE_OPERAND (r, 1), args, in_decl);
+ r = finish_stmt_expr (rtl_expr, block);
}
- if (interface_unknown || ! flag_external_templates)
- p->interface = 1; /* unknown */
- else
- p->interface = interface_only ? 0 : 2;
+ return r;
+ }
- lineno = l;
- input_filename = f;
+ case NEW_EXPR:
+ {
+ tree r = build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, in_decl));
+ NEW_EXPR_USE_GLOBAL (r) = NEW_EXPR_USE_GLOBAL (t);
+ return r;
+ }
- extract_interface_info ();
+ case DELETE_EXPR:
+ {
+ tree r = build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, in_decl));
+ DELETE_EXPR_USE_GLOBAL (r) = DELETE_EXPR_USE_GLOBAL (t);
+ DELETE_EXPR_USE_VEC (r) = DELETE_EXPR_USE_VEC (t);
+ return r;
+ }
+
+ case TEMPLATE_ID_EXPR:
+ {
+ /* Substituted template arguments */
+ tree targs = tsubst_copy (TREE_OPERAND (t, 1), args, in_decl);
+ tree chain;
+ for (chain = targs; chain; chain = TREE_CHAIN (chain))
+ TREE_VALUE (chain) = maybe_fold_nontype_arg (TREE_VALUE (chain));
+
+ return lookup_template_function
+ (tsubst_copy (TREE_OPERAND (t, 0), args, in_decl), targs);
}
+
+ case TREE_LIST:
+ {
+ tree purpose, value, chain;
+
+ if (t == void_list_node)
+ return t;
+
+ purpose = TREE_PURPOSE (t);
+ if (purpose)
+ purpose = tsubst_copy (purpose, args, in_decl);
+ value = TREE_VALUE (t);
+ if (value)
+ value = tsubst_copy (value, args, in_decl);
+ chain = TREE_CHAIN (t);
+ if (chain && chain != void_type_node)
+ chain = tsubst_copy (chain, args, in_decl);
+ if (purpose == TREE_PURPOSE (t)
+ && value == TREE_VALUE (t)
+ && chain == TREE_CHAIN (t))
+ return t;
+ return tree_cons (purpose, value, chain);
+ }
+
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ case INTEGER_TYPE:
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
+ case TEMPLATE_PARM_INDEX:
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ case OFFSET_TYPE:
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ case ARRAY_TYPE:
+ case TYPENAME_TYPE:
+ case TYPE_DECL:
+ return tsubst (t, args, in_decl);
+
+ case IDENTIFIER_NODE:
+ if (IDENTIFIER_TYPENAME_P (t))
+ return build_typename_overload
+ (tsubst (TREE_TYPE (t), args, in_decl));
+ else
+ return t;
+
+ case CONSTRUCTOR:
+ return build
+ (CONSTRUCTOR, tsubst (TREE_TYPE (t), args, in_decl), NULL_TREE,
+ tsubst_copy (CONSTRUCTOR_ELTS (t), args, in_decl));
+
+ default:
+ return t;
}
- else
- p = (struct pending_inline *)0;
+}
- DECL_TEMPLATE_INSTANTIATIONS (tmpl) =
- tree_cons (targs, fndecl, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
+/* Like tsubst_copy, but also does semantic processing and RTL expansion. */
- if (p == (struct pending_inline *)0)
+tree
+tsubst_expr (t, args, in_decl)
+ tree t, args;
+ tree in_decl;
+{
+ if (t == NULL_TREE || t == error_mark_node)
+ return t;
+
+ if (processing_template_decl)
+ return tsubst_copy (t, args, in_decl);
+
+ switch (TREE_CODE (t))
{
- /* do nothing */
+ case RETURN_STMT:
+ lineno = TREE_COMPLEXITY (t);
+ finish_return_stmt (tsubst_expr (RETURN_EXPR (t),
+ args, in_decl));
+ break;
+
+ case EXPR_STMT:
+ lineno = TREE_COMPLEXITY (t);
+ finish_expr_stmt (tsubst_expr (EXPR_STMT_EXPR (t),
+ args, in_decl));
+ break;
+
+ case DECL_STMT:
+ {
+ int i = suspend_momentary ();
+ tree dcl, init;
+
+ lineno = TREE_COMPLEXITY (t);
+ emit_line_note (input_filename, lineno);
+ dcl = start_decl
+ (tsubst (TREE_OPERAND (t, 0), args, in_decl),
+ tsubst (TREE_OPERAND (t, 1), args, in_decl),
+ TREE_OPERAND (t, 2) != 0, NULL_TREE, NULL_TREE);
+ init = tsubst_expr (TREE_OPERAND (t, 2), args, in_decl);
+ cp_finish_decl
+ (dcl, init, NULL_TREE, 1, /*init ? LOOKUP_ONLYCONVERTING :*/ 0);
+ resume_momentary (i);
+ return dcl;
+ }
+
+ case FOR_STMT:
+ {
+ tree tmp;
+ lineno = TREE_COMPLEXITY (t);
+
+ begin_for_stmt ();
+ for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
+ tsubst_expr (tmp, args, in_decl);
+ finish_for_init_stmt (NULL_TREE);
+ finish_for_cond (tsubst_expr (FOR_COND (t), args,
+ in_decl),
+ NULL_TREE);
+ tmp = tsubst_expr (FOR_EXPR (t), args, in_decl);
+ finish_for_expr (tmp, NULL_TREE);
+ tsubst_expr (FOR_BODY (t), args, in_decl);
+ finish_for_stmt (tmp, NULL_TREE);
+ }
+ break;
+
+ case WHILE_STMT:
+ {
+ lineno = TREE_COMPLEXITY (t);
+ begin_while_stmt ();
+ finish_while_stmt_cond (tsubst_expr (WHILE_COND (t),
+ args, in_decl),
+ NULL_TREE);
+ tsubst_expr (WHILE_BODY (t), args, in_decl);
+ finish_while_stmt (NULL_TREE);
+ }
+ break;
+
+ case DO_STMT:
+ {
+ lineno = TREE_COMPLEXITY (t);
+ begin_do_stmt ();
+ tsubst_expr (DO_BODY (t), args, in_decl);
+ finish_do_body (NULL_TREE);
+ finish_do_stmt (tsubst_expr (DO_COND (t), args,
+ in_decl),
+ NULL_TREE);
+ }
+ break;
+
+ case IF_STMT:
+ {
+ tree tmp;
+
+ lineno = TREE_COMPLEXITY (t);
+ begin_if_stmt ();
+ finish_if_stmt_cond (tsubst_expr (IF_COND (t),
+ args, in_decl),
+ NULL_TREE);
+
+ if (tmp = THEN_CLAUSE (t), tmp)
+ {
+ tsubst_expr (tmp, args, in_decl);
+ finish_then_clause (NULL_TREE);
+ }
+
+ if (tmp = ELSE_CLAUSE (t), tmp)
+ {
+ begin_else_clause ();
+ tsubst_expr (tmp, args, in_decl);
+ finish_else_clause (NULL_TREE);
+ }
+
+ finish_if_stmt ();
+ }
+ break;
+
+ case COMPOUND_STMT:
+ {
+ tree substmt;
+
+ lineno = TREE_COMPLEXITY (t);
+ begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
+ for (substmt = COMPOUND_BODY (t);
+ substmt != NULL_TREE;
+ substmt = TREE_CHAIN (substmt))
+ tsubst_expr (substmt, args, in_decl);
+ return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
+ NULL_TREE);
+ }
+ break;
+
+ case BREAK_STMT:
+ lineno = TREE_COMPLEXITY (t);
+ finish_break_stmt ();
+ break;
+
+ case CONTINUE_STMT:
+ lineno = TREE_COMPLEXITY (t);
+ finish_continue_stmt ();
+ break;
+
+ case SWITCH_STMT:
+ {
+ tree val, tmp;
+
+ lineno = TREE_COMPLEXITY (t);
+ begin_switch_stmt ();
+ val = tsubst_expr (SWITCH_COND (t), args, in_decl);
+ finish_switch_cond (val);
+
+ if (tmp = TREE_OPERAND (t, 1), tmp)
+ tsubst_expr (tmp, args, in_decl);
+
+ finish_switch_stmt (val, NULL_TREE);
+ }
+ break;
+
+ case CASE_LABEL:
+ finish_case_label (tsubst_expr (CASE_LOW (t), args, in_decl),
+ tsubst_expr (CASE_HIGH (t), args, in_decl));
+ break;
+
+ case LABEL_DECL:
+ t = define_label (DECL_SOURCE_FILE (t), DECL_SOURCE_LINE (t),
+ DECL_NAME (t));
+ if (t)
+ expand_label (t);
+ break;
+
+ case GOTO_STMT:
+ lineno = TREE_COMPLEXITY (t);
+ t = GOTO_DESTINATION (t);
+ if (TREE_CODE (t) != IDENTIFIER_NODE)
+ /* Computed goto's must be tsubst'd into. On the other hand,
+ non-computed gotos must not be; the identifier in question
+ will have no binding. */
+ t = tsubst_expr (t, args, in_decl);
+ finish_goto_stmt (t);
+ break;
+
+ case ASM_STMT:
+ lineno = TREE_COMPLEXITY (t);
+ finish_asm_stmt (tsubst_expr (ASM_CV_QUAL (t), args, in_decl),
+ tsubst_expr (ASM_STRING (t), args, in_decl),
+ tsubst_expr (ASM_OUTPUTS (t), args, in_decl),
+ tsubst_expr (ASM_INPUTS (t), args, in_decl),
+ tsubst_expr (ASM_CLOBBERS (t), args, in_decl));
+ break;
+
+ case TRY_BLOCK:
+ lineno = TREE_COMPLEXITY (t);
+ begin_try_block ();
+ tsubst_expr (TRY_STMTS (t), args, in_decl);
+ finish_try_block (NULL_TREE);
+ {
+ tree handler = TRY_HANDLERS (t);
+ for (; handler; handler = TREE_CHAIN (handler))
+ tsubst_expr (handler, args, in_decl);
+ }
+ finish_handler_sequence (NULL_TREE);
+ break;
+
+ case HANDLER:
+ lineno = TREE_COMPLEXITY (t);
+ begin_handler ();
+ if (HANDLER_PARMS (t))
+ {
+ tree d = HANDLER_PARMS (t);
+ expand_start_catch_block
+ (tsubst (TREE_OPERAND (d, 1), args, in_decl),
+ tsubst (TREE_OPERAND (d, 0), args, in_decl));
+ }
+ else
+ expand_start_catch_block (NULL_TREE, NULL_TREE);
+ finish_handler_parms (NULL_TREE);
+ tsubst_expr (HANDLER_BODY (t), args, in_decl);
+ finish_handler (NULL_TREE);
+ break;
+
+ case TAG_DEFN:
+ lineno = TREE_COMPLEXITY (t);
+ t = TREE_TYPE (t);
+ if (TREE_CODE (t) == ENUMERAL_TYPE)
+ tsubst_enum (t, args, NULL);
+ break;
+
+ default:
+ return build_expr_from_tree (tsubst_copy (t, args, in_decl));
}
- else if (DECL_INLINE (fndecl))
+ return NULL_TREE;
+}
+
+tree
+instantiate_template (tmpl, targ_ptr)
+ tree tmpl, targ_ptr;
+{
+ tree fndecl;
+ int i, len;
+ struct obstack *old_fmp_obstack;
+ extern struct obstack *function_maybepermanent_obstack;
+
+ if (tmpl == error_mark_node)
+ return error_mark_node;
+
+ my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
+
+ /* Check to see if we already have this specialization. This does work
+ for member template specializations; the list is set up from the
+ tsubst TEMPLATE_DECL case when the containing class is instantiated. */
+ if (DECL_FUNCTION_TEMPLATE_P (tmpl))
{
- DECL_PENDING_INLINE_INFO (fndecl) = p;
- p->next = pending_inlines;
- pending_inlines = p;
+ tree spec = retrieve_specialization (tmpl, targ_ptr);
+
+ if (spec != NULL_TREE)
+ return spec;
}
- else
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ old_fmp_obstack = function_maybepermanent_obstack;
+ function_maybepermanent_obstack = &permanent_obstack;
+
+ len = DECL_NTPARMS (tmpl);
+
+ i = len;
+ while (i--)
{
- p->next = pending_template_expansions;
- pending_template_expansions = p;
+ tree t = TREE_VEC_ELT (targ_ptr, i);
+ if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+ {
+ tree nt = target_type (t);
+ if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_MAIN_DECL (nt)))
+ {
+ cp_error ("type `%T' composed from a local class is not a valid template-argument", t);
+ cp_error (" trying to instantiate `%D'", tmpl);
+ fndecl = error_mark_node;
+ goto out;
+ }
+ }
+ TREE_VEC_ELT (targ_ptr, i) = copy_to_permanent (t);
}
- exit:
+ targ_ptr = copy_to_permanent (targ_ptr);
+
+ /* substitute template parameters */
+ fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, tmpl);
+
+ if (flag_external_templates)
+ add_pending_template (fndecl);
+
+ out:
function_maybepermanent_obstack = old_fmp_obstack;
pop_obstacks ();
return fndecl;
}
-/* classlevel should now never be true. jason 4/12/94 */
+/* Push the name of the class template into the scope of the instantiation. */
+
void
-undo_template_name_overload (id, classlevel)
- tree id;
- int classlevel;
+overload_template_name (type)
+ tree type;
{
- tree template;
+ tree id = DECL_NAME (CLASSTYPE_TI_TEMPLATE (type));
+ tree decl;
- template = IDENTIFIER_TEMPLATE (id);
- if (!template)
+ if (IDENTIFIER_CLASS_VALUE (id)
+ && TREE_TYPE (IDENTIFIER_CLASS_VALUE (id)) == type)
return;
-#if 0 /* not yet, should get fixed properly later */
- poplevel (0, 0, 0);
-#endif
-#if 1 /* XXX */
- /* This was a botch... See `overload_template_name' just below. */
- if (!classlevel)
- poplevel (0, 0, 0);
-#endif
+ decl = build_decl (TYPE_DECL, id, type);
+ SET_DECL_ARTIFICIAL (decl);
+ pushdecl_class_level (decl);
}
-/* classlevel should now never be true. jason 4/12/94 */
-void
-overload_template_name (id, classlevel)
- tree id;
- int classlevel;
+/* Like type_unification but designed specially to handle conversion
+ operators.
+
+ The FN is a TEMPLATE_DECL for a function. The ARGS are the
+ arguments that are being used when calling it.
+
+ If FN is a conversion operator, RETURN_TYPE is the type desired as
+ the result of the conversion operator.
+
+ The EXTRA_FN_ARG, if any, is the type of an additional
+ parameter to be added to the beginning of FN's parameter list.
+
+ The other arguments are as for type_unification. */
+
+int
+fn_type_unification (fn, explicit_targs, targs, args, return_type,
+ strict, extra_fn_arg)
+ tree fn, explicit_targs, targs, args, return_type;
+ unification_kind_t strict;
+ tree extra_fn_arg;
{
- tree template, t, decl;
- struct template_info *tinfo;
+ tree parms;
- my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 284);
- template = IDENTIFIER_TEMPLATE (id);
- if (!template)
- return;
+ my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
- template = TREE_PURPOSE (template);
- tinfo = DECL_TEMPLATE_INFO (template);
- template = DECL_NAME (template);
- my_friendly_assert (template != NULL_TREE, 285);
+ parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
-#if 1 /* XXX */
- /* This was a botch... names of templates do not get their own private
- scopes. Rather, they should go into the binding level already created
- by push_template_decls. Except that there isn't one of those for
- specializations. */
- if (!classlevel)
+ if (IDENTIFIER_TYPENAME_P (DECL_NAME (fn)))
{
- pushlevel (1);
- declare_pseudo_global_level ();
+ /* This is a template conversion operator. Use the return types
+ as well as the argument types. */
+ parms = scratch_tree_cons (NULL_TREE,
+ TREE_TYPE (TREE_TYPE (fn)),
+ parms);
+ args = scratch_tree_cons (NULL_TREE, return_type, args);
}
-#endif
- t = xref_tag (tinfo->aggr, id, NULL_TREE, 1);
- my_friendly_assert (TREE_CODE (t) == RECORD_TYPE
- || TREE_CODE (t) == UNION_TYPE
- || TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286);
+ if (extra_fn_arg != NULL_TREE)
+ parms = scratch_tree_cons (NULL_TREE, extra_fn_arg, parms);
+
+ /* We allow incomplete unification without an error message here
+ because the standard doesn't seem to explicitly prohibit it. Our
+ callers must be ready to deal with unification failures in any
+ event. */
+ return type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ targs,
+ parms,
+ args,
+ explicit_targs,
+ strict, 1);
+}
- decl = build_decl (TYPE_DECL, template, t);
- SET_DECL_ARTIFICIAL (decl);
-#if 0 /* fix this later */
- /* We don't want to call here if the work has already been done. */
- t = (classlevel
- ? IDENTIFIER_CLASS_VALUE (template)
- : IDENTIFIER_LOCAL_VALUE (template));
- if (t
- && TREE_CODE (t) == TYPE_DECL
- && TREE_TYPE (t) == t)
- my_friendly_abort (85);
-#endif
+/* Type unification.
- if (classlevel)
- pushdecl_class_level (decl);
- else
- pushdecl (decl);
+ We have a function template signature with one or more references to
+ template parameters, and a parameter list we wish to fit to this
+ template. If possible, produce a list of parameters for the template
+ which will cause it to fit the supplied parameter list.
-#if 0 /* This seems bogus to me; if it isn't, explain why. (jason) */
- /* Fake this for now, just to make dwarfout.c happy. It will have to
- be done in a proper way later on. */
- DECL_CONTEXT (decl) = t;
-#endif
-}
+ Return zero for success, 2 for an incomplete match that doesn't resolve
+ all the types, and 1 for complete failure. An error message will be
+ printed only for an incomplete match.
-extern struct pending_input *to_be_restored;
+ TPARMS[NTPARMS] is an array of template parameter types.
-/* NAME is the IDENTIFIER value of a PRE_PARSED_CLASS_DECL. */
-void
-end_template_instantiation (name)
- tree name;
+ TARGS[NTPARMS] is the array into which the deduced template
+ parameter values are placed. PARMS is the function template's
+ signature (using TEMPLATE_PARM_IDX nodes), and ARGS is the argument
+ list we're trying to match against it.
+
+ The EXPLICIT_TARGS are explicit template arguments provided via a
+ template-id.
+
+ The parameter STRICT is one of:
+
+ DEDUCE_CALL:
+ We are deducing arguments for a function call, as in
+ [temp.deduct.call].
+
+ DEDUCE_CONV:
+ We are deducing arguments for a conversion function, as in
+ [temp.deduct.conv].
+
+ DEDUCE_EXACT:
+ We are deducing arguments when calculating the partial
+ ordering between specializations of function or class
+ templates, as in [temp.func.order] and [temp.class.order],
+ when doing an explicit instantiation as in [temp.explicit],
+ when determining an explicit specialization as in
+ [temp.expl.spec], or when taking the address of a function
+ template, as in [temp.deduct.funcaddr]. */
+
+int
+type_unification (tparms, targs, parms, args, explicit_targs,
+ strict, allow_incomplete)
+ tree tparms, targs, parms, args, explicit_targs;
+ unification_kind_t strict;
+ int allow_incomplete;
{
- tree t, decl;
+ int* explicit_mask;
+ int i;
- processing_template_defn--;
- if (!flag_external_templates)
- interface_unknown--;
+ for (i = 0; i < TREE_VEC_LENGTH (tparms); i++)
+ TREE_VEC_ELT (targs, i) = NULL_TREE;
- /* Restore the old parser input state. */
- if (yychar == YYEMPTY)
- yychar = yylex ();
- if (yychar != END_OF_SAVED_INPUT)
- error ("parse error at end of class template");
- else
+ if (explicit_targs != NULL_TREE)
{
- restore_pending_input (to_be_restored);
- to_be_restored = 0;
- }
-
- /* Our declarations didn't get stored in the global slot, since
- there was a (supposedly tags-transparent) scope in between. */
- t = IDENTIFIER_TYPE_VALUE (name);
- my_friendly_assert (t != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (t)) == 't',
- 287);
- SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
- /* Make methods of template classes static, unless
- -fexternal-templates is given. */
- if (!flag_external_templates)
- SET_CLASSTYPE_INTERFACE_UNKNOWN (t);
- decl = IDENTIFIER_GLOBAL_VALUE (name);
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 288);
-
- undo_template_name_overload (name, 0);
- t = IDENTIFIER_TEMPLATE (name);
- pop_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (t)), TREE_VALUE (t),
- 0);
- /* This will fix up the type-value field. */
- pushdecl (decl);
- pop_from_top_level ();
+ tree arg_vec;
+ arg_vec = coerce_template_parms (tparms, explicit_targs, NULL_TREE, 0,
+ 0);
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG && TREE_CODE (decl) == TYPE_DECL)
- {
- /* We just completed the definition of a new file-scope type,
- so we can go ahead and output debug-info for it now. */
- TYPE_STUB_DECL (TREE_TYPE (decl)) = decl;
- rest_of_type_compilation (TREE_TYPE (decl), 1);
+ if (arg_vec == error_mark_node)
+ return 1;
+
+ explicit_mask = alloca (sizeof (int) * TREE_VEC_LENGTH (targs));
+ bzero ((char *) explicit_mask, sizeof(int) * TREE_VEC_LENGTH (targs));
+
+ for (i = 0;
+ i < TREE_VEC_LENGTH (arg_vec)
+ && TREE_VEC_ELT (arg_vec, i) != NULL_TREE;
+ ++i)
+ {
+ TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (arg_vec, i);
+ /* Let unify know that this argument was explicit. */
+ explicit_mask [i] = 1;
+ }
}
-#endif /* DWARF_DEBUGGING_INFO */
+ else
+ explicit_mask = 0;
- /* Restore interface/implementation settings. */
- extract_interface_info ();
+ return
+ type_unification_real (tparms, targs, parms, args, 0,
+ strict, allow_incomplete, explicit_mask);
}
-
-/* Store away the text of an template. */
+
+/* Adjust types before performing type deduction, as described in
+ [temp.deduct.call] and [temp.deduct.conv]. The rules in these two
+ sections are symmetric. PARM is the type of a function parameter
+ or the return type of the conversion function. ARG is the type of
+ the argument passed to the call, or the type of the value
+ intialized with the result of the conversion function. */
void
-reinit_parse_for_template (yychar, d1, d2)
- int yychar;
- tree d1, d2;
+maybe_adjust_types_for_deduction (strict, parm, arg)
+ unification_kind_t strict;
+ tree* parm;
+ tree* arg;
{
- struct template_info *template_info;
- extern struct obstack inline_text_obstack; /* see comment in lex.c */
-
- if (d2 == NULL_TREE || d2 == error_mark_node)
+ switch (strict)
{
- lose:
- /* @@ Should use temp obstack, and discard results. */
- reinit_parse_for_block (yychar, &inline_text_obstack, 1);
+ case DEDUCE_CALL:
+ break;
+
+ case DEDUCE_CONV:
+ {
+ /* Swap PARM and ARG throughout the remainder of this
+ function; the handling is precisely symmetric since PARM
+ will initialize ARG rather than vice versa. */
+ tree* temp = parm;
+ parm = arg;
+ arg = temp;
+ break;
+ }
+
+ case DEDUCE_EXACT:
+ /* There is nothing to do in this case. */
return;
+
+ default:
+ my_friendly_abort (0);
}
- if (TREE_CODE (d2) == IDENTIFIER_NODE)
- d2 = IDENTIFIER_GLOBAL_VALUE (d2);
- if (!d2)
- goto lose;
- template_info = DECL_TEMPLATE_INFO (d2);
- if (!template_info)
+ if (TREE_CODE (*parm) != REFERENCE_TYPE)
{
- template_info = (struct template_info *) permalloc (sizeof (struct template_info));
- bzero ((char *) template_info, sizeof (struct template_info));
- DECL_TEMPLATE_INFO (d2) = template_info;
+ /* [temp.deduct.call]
+
+ If P is not a reference type:
+
+ --If A is an array type, the pointer type produced by the
+ array-to-pointer standard conversion (_conv.array_) is
+ used in place of A for type deduction; otherwise,
+
+ --If A is a function type, the pointer type produced by
+ the function-to-pointer standard conversion
+ (_conv.func_) is used in place of A for type deduction;
+ otherwise,
+
+ --If A is a cv-qualified type, the top level
+ cv-qualifiers of A's type are ignored for type
+ deduction. */
+ if (TREE_CODE (*arg) == ARRAY_TYPE)
+ *arg = build_pointer_type (TREE_TYPE (*arg));
+ else if (TREE_CODE (*arg) == FUNCTION_TYPE
+ || TREE_CODE (*arg) == METHOD_TYPE)
+ *arg = build_pointer_type (*arg);
+ else
+ *arg = TYPE_MAIN_VARIANT (*arg);
}
- template_info->filename = input_filename;
- template_info->lineno = lineno;
- reinit_parse_for_block (yychar, &inline_text_obstack, 1);
- template_info->text = obstack_base (&inline_text_obstack);
- template_info->length = obstack_object_size (&inline_text_obstack);
- obstack_finish (&inline_text_obstack);
- template_info->parm_vec = d1;
+
+ /* [temp.deduct.call]
+
+ If P is a cv-qualified type, the top level cv-qualifiers
+ of P's type are ignored for type deduction. If P is a
+ reference type, the type referred to by P is used for
+ type deduction. */
+ *parm = TYPE_MAIN_VARIANT (*parm);
+ if (TREE_CODE (*parm) == REFERENCE_TYPE)
+ *parm = TREE_TYPE (*parm);
}
-/* Type unification.
-
- We have a function template signature with one or more references to
- template parameters, and a parameter list we wish to fit to this
- template. If possible, produce a list of parameters for the template
- which will cause it to fit the supplied parameter list.
-
- Return zero for success, 2 for an incomplete match that doesn't resolve
- all the types, and 1 for complete failure. An error message will be
- printed only for an incomplete match.
-
- TPARMS[NTPARMS] is an array of template parameter types;
- TARGS[NTPARMS] is the array of template parameter values. PARMS is
- the function template's signature (using TEMPLATE_PARM_IDX nodes),
- and ARGS is the argument list we're trying to match against it.
+/* Like type_unfication. EXPLICIT_MASK, if non-NULL, is an array of
+ integers, with ones in positions corresponding to arguments in
+ targs that were provided explicitly, and zeros elsewhere.
- If SUBR is 1, we're being called recursively (to unify the arguments of
- a function or method parameter of a function template), so don't zero
- out targs and don't fail on an incomplete match. */
+ If SUBR is 1, we're being called recursively (to unify the
+ arguments of a function or method parameter of a function
+ template). */
-int
-type_unification (tparms, targs, parms, args, nsubsts, subr)
- tree tparms, *targs, parms, args;
- int *nsubsts, subr;
+static int
+type_unification_real (tparms, targs, parms, args, subr,
+ strict, allow_incomplete, explicit_mask)
+ tree tparms, targs, parms, args;
+ int subr;
+ unification_kind_t strict;
+ int allow_incomplete;
+ int* explicit_mask;
{
tree parm, arg;
int i;
int ntparms = TREE_VEC_LENGTH (tparms);
+ int sub_strict;
my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
- my_friendly_assert (TREE_CODE (parms) == TREE_LIST, 290);
+ my_friendly_assert (parms == NULL_TREE
+ || TREE_CODE (parms) == TREE_LIST, 290);
/* ARGS could be NULL (via a call from parse.y to
build_x_function_call). */
if (args)
my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);
my_friendly_assert (ntparms > 0, 292);
- if (!subr)
- bzero ((char *) targs, sizeof (tree) * ntparms);
+ switch (strict)
+ {
+ case DEDUCE_CALL:
+ sub_strict = UNIFY_ALLOW_MORE_CV_QUAL | UNIFY_ALLOW_DERIVED;
+ break;
+
+ case DEDUCE_CONV:
+ sub_strict = UNIFY_ALLOW_LESS_CV_QUAL;
+ break;
+
+ case DEDUCE_EXACT:
+ sub_strict = UNIFY_ALLOW_NONE;
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
while (parms
&& parms != void_list_node
@@ -2059,11 +6077,33 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
if (arg == unknown_type_node)
return 1;
- if (! uses_template_parms (parm)
- && TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
+ /* Conversions will be performed on a function argument that
+ corresponds with a function parameter that contains only
+ non-deducible template parameters and explicitly specified
+ template parameters. */
+ if (! uses_template_parms (parm))
{
- if (can_convert_arg (parm, TREE_TYPE (arg), arg))
+ tree type;
+
+ if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
+ type = TREE_TYPE (arg);
+ else
+ {
+ type = arg;
+ arg = NULL_TREE;
+ }
+
+ if (strict == DEDUCE_EXACT)
+ {
+ if (comptypes (parm, type, 1))
+ continue;
+ }
+ else
+ /* It might work; we shouldn't check now, because we might
+ get into infinite recursion. Overload resolution will
+ handle it. */
continue;
+
return 1;
}
@@ -2076,41 +6116,38 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
{
my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293);
- if (TREE_CODE (arg) == TREE_LIST
- && TREE_TYPE (arg) == unknown_type_node
- && TREE_CODE (TREE_VALUE (arg)) == TEMPLATE_DECL)
+ if (TREE_CODE (arg) == OVERLOAD
+ && TREE_CODE (OVL_FUNCTION (arg)) == TEMPLATE_DECL)
{
- int nsubsts, ntparms;
- tree *targs;
+ tree targs;
+ tree arg_type;
/* Have to back unify here */
- arg = TREE_VALUE (arg);
- nsubsts = 0;
- ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (arg));
- targs = (tree *) alloca (sizeof (tree) * ntparms);
- parm = tree_cons (NULL_TREE, parm, NULL_TREE);
- return type_unification (DECL_TEMPLATE_PARMS (arg), targs,
- TYPE_ARG_TYPES (TREE_TYPE (arg)),
- parm, &nsubsts, 0);
+ arg = OVL_FUNCTION (arg);
+ targs = make_scratch_vec (DECL_NTPARMS (arg));
+ arg_type = TREE_TYPE (arg);
+ maybe_adjust_types_for_deduction (strict, &parm, &arg_type);
+ parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE);
+ arg_type = scratch_tree_cons (NULL_TREE, arg_type, NULL_TREE);
+ return
+ type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
+ targs, arg_type, parm, NULL_TREE,
+ DEDUCE_EXACT, allow_incomplete);
}
arg = TREE_TYPE (arg);
}
#endif
- if (TREE_CODE (arg) == REFERENCE_TYPE)
- arg = TREE_TYPE (arg);
-
- if (TREE_CODE (parm) != REFERENCE_TYPE)
+ if (! flag_ansi && arg == TREE_TYPE (null_node))
{
- if (TREE_CODE (arg) == FUNCTION_TYPE
- || TREE_CODE (arg) == METHOD_TYPE)
- arg = build_pointer_type (arg);
- else if (TREE_CODE (arg) == ARRAY_TYPE)
- arg = build_pointer_type (TREE_TYPE (arg));
- else
- arg = TYPE_MAIN_VARIANT (arg);
+ warning ("using type void* for NULL");
+ arg = ptr_type_node;
}
- switch (unify (tparms, targs, ntparms, parm, arg, nsubsts))
+ if (!subr)
+ maybe_adjust_types_for_deduction (strict, &parm, &arg);
+
+ switch (unify (tparms, targs, parm, arg, sub_strict,
+ explicit_mask))
{
case 0:
break;
@@ -2129,21 +6166,78 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
return 1;
if (!subr)
for (i = 0; i < ntparms; i++)
- if (!targs[i])
+ if (TREE_VEC_ELT (targs, i) == NULL_TREE)
{
- error ("incomplete type unification");
+ if (!allow_incomplete)
+ error ("incomplete type unification");
return 2;
}
return 0;
}
-/* Tail recursion is your friend. */
-static int
-unify (tparms, targs, ntparms, parm, arg, nsubsts)
- tree tparms, *targs, parm, arg;
- int *nsubsts, ntparms;
+/* Returns the level of DECL, which declares a template parameter. */
+
+int
+template_decl_level (decl)
+ tree decl;
+{
+ switch (TREE_CODE (decl))
+ {
+ case TYPE_DECL:
+ case TEMPLATE_DECL:
+ return TEMPLATE_TYPE_LEVEL (TREE_TYPE (decl));
+
+ case PARM_DECL:
+ return TEMPLATE_PARM_LEVEL (DECL_INITIAL (decl));
+
+ default:
+ my_friendly_abort (0);
+ return 0;
+ }
+}
+
+/* Decide whether ARG can be unified with PARM, considering only the
+ cv-qualifiers of each type, given STRICT as documented for unify.
+ Returns non-zero iff the unification is OK on that basis.*/
+
+int
+check_cv_quals_for_unify (strict, arg, parm)
+ int strict;
+ tree arg;
+ tree parm;
+{
+ return !((!(strict & UNIFY_ALLOW_MORE_CV_QUAL)
+ && (TYPE_READONLY (arg) < TYPE_READONLY (parm)
+ || TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm)))
+ || (!(strict & UNIFY_ALLOW_LESS_CV_QUAL)
+ && (TYPE_READONLY (arg) > TYPE_READONLY (parm)
+ || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm))));
+}
+
+/* Takes parameters as for type_unification. Returns 0 if the
+ type deduction suceeds, 1 otherwise. The parameter STRICT is a
+ bitwise or of the following flags:
+
+ UNIFY_ALLOW_NONE:
+ Require an exact match between PARM and ARG.
+ UNIFY_ALLOW_MORE_CV_QUAL:
+ Allow the deduced ARG to be more cv-qualified than ARG.
+ UNIFY_ALLOW_LESS_CV_QUAL:
+ Allow the deduced ARG to be less cv-qualified than ARG.
+ UNIFY_ALLOW_DERIVED:
+ Allow the deduced ARG to be a template base class of ARG,
+ or a pointer to a template base class of the type pointed to by
+ ARG. */
+
+int
+unify (tparms, targs, parm, arg, strict, explicit_mask)
+ tree tparms, targs, parm, arg;
+ int strict;
+ int* explicit_mask;
{
int idx;
+ tree targ;
+ tree tparm;
/* I don't think this will do the right thing with respect to types.
But the only case I've seen it in so far has been array bounds, where
@@ -2156,133 +6250,264 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
return 1;
if (arg == unknown_type_node)
return 1;
- if (arg == parm)
+ /* If PARM uses template parameters, then we can't bail out here,
+ even in ARG == PARM, since we won't record unifications for the
+ template parameters. We might need them if we're trying to
+ figure out which of two things is more specialized. */
+ if (arg == parm && !uses_template_parms (parm))
return 0;
+ /* Immediately reject some pairs that won't unify because of
+ cv-qualification mismatches. */
+ if (TREE_CODE (arg) == TREE_CODE (parm)
+ && TREE_CODE_CLASS (TREE_CODE (arg)) == 't'
+ /* We check the cv-qualifiers when unifying with template type
+ parameters below. We want to allow ARG `const T' to unify with
+ PARM `T' for example, when computing which of two templates
+ is more specialized, for example. */
+ && TREE_CODE (arg) != TEMPLATE_TYPE_PARM
+ && !check_cv_quals_for_unify (strict, arg, parm))
+ return 1;
+
switch (TREE_CODE (parm))
{
+ case TYPENAME_TYPE:
+ /* In a type which contains a nested-name-specifier, template
+ argument values cannot be deduced for template parameters used
+ within the nested-name-specifier. */
+ return 0;
+
case TEMPLATE_TYPE_PARM:
- (*nsubsts)++;
- if (TEMPLATE_TYPE_TPARMLIST (parm) != tparms)
- {
- error ("mixed template headers?!");
- my_friendly_abort (86);
- return 1;
- }
+ case TEMPLATE_TEMPLATE_PARM:
+ tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
+
+ if (TEMPLATE_TYPE_LEVEL (parm)
+ != template_decl_level (tparm))
+ /* The PARM is not one we're trying to unify. Just check
+ to see if it matches ARG. */
+ return (TREE_CODE (arg) == TREE_CODE (parm)
+ && comptypes (parm, arg, 1)) ? 0 : 1;
idx = TEMPLATE_TYPE_IDX (parm);
-#if 0
- /* Template type parameters cannot contain cv-quals; i.e.
- template <class T> void f (T& a, T& b) will not generate
- void f (const int& a, const int& b). */
- if (TYPE_READONLY (arg) > TYPE_READONLY (parm)
- || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm))
- return 1;
- arg = TYPE_MAIN_VARIANT (arg);
-#else
- {
- int constp = TYPE_READONLY (arg) > TYPE_READONLY (parm);
- int volatilep = TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm);
- arg = cp_build_type_variant (arg, constp, volatilep);
- }
-#endif
- /* Simple cases: Value already set, does match or doesn't. */
- if (targs[idx] == arg)
- return 0;
- else if (targs[idx])
- return 1;
+ targ = TREE_VEC_ELT (targs, idx);
+ tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
+
/* Check for mixed types and values. */
- if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL)
+ if ((TREE_CODE (parm) == TEMPLATE_TYPE_PARM
+ && TREE_CODE (tparm) != TYPE_DECL)
+ || (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
+ && TREE_CODE (tparm) != TEMPLATE_DECL))
return 1;
- targs[idx] = arg;
- return 0;
- case TEMPLATE_CONST_PARM:
- (*nsubsts)++;
- idx = TEMPLATE_CONST_IDX (parm);
- if (targs[idx] == arg)
+
+ if (!strict && targ != NULL_TREE
+ && explicit_mask && explicit_mask[idx])
+ /* An explicit template argument. Don't even try to match
+ here; the overload resolution code will manage check to
+ see whether the call is legal. */
return 0;
- else if (targs[idx])
+
+ if (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
{
- tree t = targs[idx];
- if (TREE_CODE (t) == TREE_CODE (arg))
- switch (TREE_CODE (arg))
+ if (CLASSTYPE_TEMPLATE_INFO (parm))
+ {
+ /* We arrive here when PARM does not involve template
+ specialization. */
+
+ /* ARG must be constructed from a template class. */
+ if (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg))
+ return 1;
+
{
- case INTEGER_CST:
- if (tree_int_cst_equal (t, arg))
- return 0;
- break;
- case REAL_CST:
- if (REAL_VALUES_EQUAL (TREE_REAL_CST (t), TREE_REAL_CST (arg)))
- return 0;
- break;
- /* STRING_CST values are not valid template const parms. */
- default:
- ;
+ tree parmtmpl = CLASSTYPE_TI_TEMPLATE (parm);
+ tree parmvec = CLASSTYPE_TI_ARGS (parm);
+ tree argvec = CLASSTYPE_TI_ARGS (arg);
+ tree argtmplvec
+ = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (arg));
+ int i;
+
+ /* The parameter and argument roles have to be switched here
+ in order to handle default arguments properly. For example,
+ template<template <class> class TT> void f(TT<int>)
+ should be able to accept vector<int> which comes from
+ template <class T, class Allocator = allocator>
+ class vector. */
+
+ if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 1, 1)
+ == error_mark_node)
+ return 1;
+
+ /* Deduce arguments T, i from TT<T> or TT<i>. */
+ for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
+ {
+ tree t = TREE_VEC_ELT (parmvec, i);
+ if (TREE_CODE (t) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
+ && TREE_CODE (t) != TEMPLATE_PARM_INDEX)
+ continue;
+
+ /* This argument can be deduced. */
+
+ if (unify (tparms, targs, t,
+ TREE_VEC_ELT (argvec, i),
+ UNIFY_ALLOW_NONE, explicit_mask))
+ return 1;
+ }
}
- my_friendly_abort (87);
- return 1;
+ arg = CLASSTYPE_TI_TEMPLATE (arg);
+ }
+ }
+ else
+ {
+ /* If PARM is `const T' and ARG is only `int', we don't have
+ a match unless we are allowing additional qualification.
+ If ARG is `const int' and PARM is just `T' that's OK;
+ that binds `const int' to `T'. */
+ if (!check_cv_quals_for_unify (strict | UNIFY_ALLOW_LESS_CV_QUAL,
+ arg, parm))
+ return 1;
+
+ /* Consider the case where ARG is `const volatile int' and
+ PARM is `const T'. Then, T should be `volatile int'. */
+ arg =
+ cp_build_type_variant (arg,
+ TYPE_READONLY (arg) > TYPE_READONLY (parm),
+ TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm));
}
-/* else if (typeof arg != tparms[idx])
- return 1;*/
- targs[idx] = copy_to_permanent (arg);
+ /* Simple cases: Value already set, does match or doesn't. */
+ if (targ != NULL_TREE
+ && (comptypes (targ, arg, 1)
+ || (explicit_mask && explicit_mask[idx])))
+ return 0;
+ else if (targ)
+ return 1;
+ TREE_VEC_ELT (targs, idx) = arg;
+ return 0;
+
+ case TEMPLATE_PARM_INDEX:
+ tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
+
+ if (TEMPLATE_PARM_LEVEL (parm)
+ != template_decl_level (tparm))
+ /* The PARM is not one we're trying to unify. Just check
+ to see if it matches ARG. */
+ return (TREE_CODE (arg) == TREE_CODE (parm)
+ && cp_tree_equal (parm, arg) > 0) ? 0 : 1;
+
+ idx = TEMPLATE_PARM_IDX (parm);
+ targ = TREE_VEC_ELT (targs, idx);
+
+ if (targ)
+ {
+ int i = (cp_tree_equal (targ, arg) > 0);
+ if (i == 1)
+ return 0;
+ else if (i == 0)
+ return 1;
+ else
+ my_friendly_abort (42);
+ }
+
+ TREE_VEC_ELT (targs, idx) = copy_to_permanent (arg);
return 0;
case POINTER_TYPE:
- if (TREE_CODE (arg) != POINTER_TYPE)
- return 1;
- return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
- nsubsts);
+ {
+ int sub_strict;
+
+ if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg))
+ return (unify (tparms, targs, parm,
+ TYPE_PTRMEMFUNC_FN_TYPE (arg), strict,
+ explicit_mask));
+
+ if (TREE_CODE (arg) != POINTER_TYPE)
+ return 1;
+
+ /* [temp.deduct.call]
+
+ A can be another pointer or pointer to member type that can
+ be converted to the deduced A via a qualification
+ conversion (_conv.qual_).
+
+ We pass down STRICT here rather than UNIFY_ALLOW_NONE.
+ This will allow for additional cv-qualification of the
+ pointed-to types if appropriate. In general, this is a bit
+ too generous; we are only supposed to allow qualification
+ conversions and this method will allow an ARG of char** and
+ a deduced ARG of const char**. However, overload
+ resolution will subsequently invalidate the candidate, so
+ this is probably OK. */
+ sub_strict = strict;
+
+ if (TREE_CODE (TREE_TYPE (arg)) != RECORD_TYPE
+ || TYPE_PTRMEMFUNC_FLAG (TREE_TYPE (arg)))
+ /* The derived-to-base conversion only persists through one
+ level of pointers. */
+ sub_strict &= ~UNIFY_ALLOW_DERIVED;
+
+ return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE
+ (arg), sub_strict, explicit_mask);
+ }
case REFERENCE_TYPE:
- if (TREE_CODE (arg) == REFERENCE_TYPE)
- arg = TREE_TYPE (arg);
- return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg, nsubsts);
+ if (TREE_CODE (arg) != REFERENCE_TYPE)
+ return 1;
+ return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
+ UNIFY_ALLOW_NONE, explicit_mask);
case ARRAY_TYPE:
if (TREE_CODE (arg) != ARRAY_TYPE)
return 1;
- if (unify (tparms, targs, ntparms, TYPE_DOMAIN (parm), TYPE_DOMAIN (arg),
- nsubsts) != 0)
+ if ((TYPE_DOMAIN (parm) == NULL_TREE)
+ != (TYPE_DOMAIN (arg) == NULL_TREE))
return 1;
- return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
- nsubsts);
+ if (TYPE_DOMAIN (parm) != NULL_TREE
+ && unify (tparms, targs, TYPE_DOMAIN (parm),
+ TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE, explicit_mask) != 0)
+ return 1;
+ return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
+ UNIFY_ALLOW_NONE, explicit_mask);
case REAL_TYPE:
+ case COMPLEX_TYPE:
case INTEGER_TYPE:
+ case BOOLEAN_TYPE:
+ case VOID_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
if (TREE_CODE (parm) == INTEGER_TYPE)
{
if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
- && unify (tparms, targs, ntparms,
- TYPE_MIN_VALUE (parm), TYPE_MIN_VALUE (arg), nsubsts))
+ && unify (tparms, targs, TYPE_MIN_VALUE (parm),
+ TYPE_MIN_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask))
return 1;
if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
- && unify (tparms, targs, ntparms,
- TYPE_MAX_VALUE (parm), TYPE_MAX_VALUE (arg), nsubsts))
+ && unify (tparms, targs, TYPE_MAX_VALUE (parm),
+ TYPE_MAX_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask))
return 1;
}
+ else if (TREE_CODE (parm) == REAL_TYPE
+ /* We use the TYPE_MAIN_VARIANT since we have already
+ checked cv-qualification at the top of the
+ function. */
+ && !comptypes (TYPE_MAIN_VARIANT (arg),
+ TYPE_MAIN_VARIANT (parm), 1))
+ return 1;
+
/* As far as unification is concerned, this wins. Later checks
will invalidate it if necessary. */
return 0;
/* Types INTEGER_CST and MINUS_EXPR can come from array bounds. */
+ /* Type INTEGER_CST can come from ordinary constant template args. */
case INTEGER_CST:
+ while (TREE_CODE (arg) == NOP_EXPR)
+ arg = TREE_OPERAND (arg, 0);
+
if (TREE_CODE (arg) != INTEGER_CST)
return 1;
return !tree_int_cst_equal (parm, arg);
- case MINUS_EXPR:
- {
- tree t1, t2;
- t1 = TREE_OPERAND (parm, 0);
- t2 = TREE_OPERAND (parm, 1);
- return unify (tparms, targs, ntparms, t1,
- fold (build (PLUS_EXPR, integer_type_node, arg, t2)),
- nsubsts);
- }
-
case TREE_VEC:
{
int i;
@@ -2291,282 +6516,487 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
return 1;
for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--)
- if (unify (tparms, targs, ntparms,
+ if (unify (tparms, targs,
TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
- nsubsts))
+ UNIFY_ALLOW_NONE, explicit_mask))
return 1;
return 0;
}
- case UNINSTANTIATED_P_TYPE:
- {
- tree a;
- /* Unification of something that is not a class fails. */
- if (! IS_AGGR_TYPE (arg))
- return 1;
- a = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (arg));
- if (a && UPT_TEMPLATE (parm) == TREE_PURPOSE (a))
- return unify (tparms, targs, ntparms, UPT_PARMS (parm),
- TREE_VALUE (a), nsubsts);
- /* FIXME: Should check base conversions here. */
- return 1;
- }
-
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (parm))
- return unify (tparms, targs, ntparms, TYPE_PTRMEMFUNC_FN_TYPE (parm),
- arg, nsubsts);
+ return unify (tparms, targs, TYPE_PTRMEMFUNC_FN_TYPE (parm),
+ arg, strict, explicit_mask);
- /* Allow trivial conversions. */
- if (TYPE_MAIN_VARIANT (parm) != TYPE_MAIN_VARIANT (arg)
- || TYPE_READONLY (parm) < TYPE_READONLY (arg)
- || TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg))
+ if (TREE_CODE (arg) != RECORD_TYPE)
return 1;
- return 0;
+
+ if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm))
+ {
+ tree t = NULL_TREE;
+ if (strict & UNIFY_ALLOW_DERIVED)
+ /* [temp.deduct.call]
+
+ If P is a class, and P has the form template-id, then A
+ can be a derived class of the deduced A. Likewise, if
+ P is a pointer to a class of the form template-id, A
+ can be a pointer to a derived class pointed to by the
+ deduced A. */
+ t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
+ else if
+ (CLASSTYPE_TEMPLATE_INFO (arg)
+ && CLASSTYPE_TI_TEMPLATE (parm) == CLASSTYPE_TI_TEMPLATE (arg))
+ t = arg;
+ if (! t || t == error_mark_node)
+ return 1;
- case METHOD_TYPE:
- if (TREE_CODE (arg) != METHOD_TYPE)
+ return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
+ CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE,
+ explicit_mask);
+ }
+ else if (!comptypes (TYPE_MAIN_VARIANT (parm),
+ TYPE_MAIN_VARIANT (arg), 1))
return 1;
- goto check_args;
+ return 0;
+ case METHOD_TYPE:
case FUNCTION_TYPE:
- if (TREE_CODE (arg) != FUNCTION_TYPE)
+ if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
- check_args:
- if (unify (tparms, targs, ntparms, TREE_TYPE (parm),
- TREE_TYPE (arg), nsubsts))
+
+ if (unify (tparms, targs, TREE_TYPE (parm),
+ TREE_TYPE (arg), UNIFY_ALLOW_NONE, explicit_mask))
return 1;
- return type_unification (tparms, targs, TYPE_ARG_TYPES (parm),
- TYPE_ARG_TYPES (arg), nsubsts, 1);
+ return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
+ TYPE_ARG_TYPES (arg), 1,
+ DEDUCE_EXACT, 0, explicit_mask);
case OFFSET_TYPE:
if (TREE_CODE (arg) != OFFSET_TYPE)
return 1;
- if (unify (tparms, targs, ntparms, TYPE_OFFSET_BASETYPE (parm),
- TYPE_OFFSET_BASETYPE (arg), nsubsts))
+ if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
+ TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE, explicit_mask))
return 1;
- return unify (tparms, targs, ntparms, TREE_TYPE (parm),
- TREE_TYPE (arg), nsubsts);
+ return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
+ UNIFY_ALLOW_NONE, explicit_mask);
+
+ case CONST_DECL:
+ if (arg != decl_constant_value (parm))
+ return 1;
+ return 0;
+
+ case TEMPLATE_DECL:
+ /* Matched cases are handled by the ARG == PARM test above. */
+ return 1;
+
+ case MINUS_EXPR:
+ if (TREE_CODE (TREE_OPERAND (parm, 1)) == INTEGER_CST)
+ {
+ /* We handle this case specially, since it comes up with
+ arrays. In particular, something like:
+
+ template <int N> void f(int (&x)[N]);
+
+ Here, we are trying to unify the range type, which
+ looks like [0 ... (N - 1)]. */
+ tree t, t1, t2;
+ t1 = TREE_OPERAND (parm, 0);
+ t2 = TREE_OPERAND (parm, 1);
+
+ /* Should this be a regular fold? */
+ t = maybe_fold_nontype_arg (build (PLUS_EXPR,
+ integer_type_node,
+ arg, t2));
+
+ return unify (tparms, targs, t1, t, UNIFY_ALLOW_NONE,
+ explicit_mask);
+ }
+ /* else fall through */
default:
- sorry ("use of `%s' in template type unification",
- tree_code_name [(int) TREE_CODE (parm)]);
+ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
+ {
+ /* We're looking at an expression. This can happen with
+ something like:
+
+ template <int I>
+ void foo(S<I>, S<I + 2>);
+
+ If the call looked like:
+
+ foo(S<2>(), S<4>());
+
+ we would have already matched `I' with `2'. Now, we'd
+ like to know if `4' matches `I + 2'. So, we substitute
+ into that expression, and fold constants, in the hope of
+ figuring it out. */
+ tree t =
+ maybe_fold_nontype_arg (tsubst_expr (parm, targs, NULL_TREE));
+ tree a = maybe_fold_nontype_arg (arg);
+
+ if (!IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t))))
+ /* Good, we mangaged to simplify the exression. */
+ return unify (tparms, targs, t, a, UNIFY_ALLOW_NONE,
+ explicit_mask);
+ else
+ /* Bad, we couldn't simplify this. Assume it doesn't
+ unify. */
+ return 1;
+ }
+ else
+ sorry ("use of `%s' in template type unification",
+ tree_code_name [(int) TREE_CODE (parm)]);
+
return 1;
}
}
-
-#undef DEBUG
+void
+mark_decl_instantiated (result, extern_p)
+ tree result;
+ int extern_p;
+{
+ if (DECL_TEMPLATE_INSTANTIATION (result))
+ SET_DECL_EXPLICIT_INSTANTIATION (result);
+
+ if (TREE_CODE (result) != FUNCTION_DECL)
+ /* The TREE_PUBLIC flag for function declarations will have been
+ set correctly by tsubst. */
+ TREE_PUBLIC (result) = 1;
+
+ if (! extern_p)
+ {
+ DECL_INTERFACE_KNOWN (result) = 1;
+ DECL_NOT_REALLY_EXTERN (result) = 1;
+ /* For WIN32 we also want to put explicit instantiations in
+ linkonce sections. */
+ if (TREE_PUBLIC (result))
+ maybe_make_one_only (result);
+ }
+ else if (TREE_CODE (result) == FUNCTION_DECL)
+ mark_inline_for_output (result);
+}
+
+/* Given two function templates PAT1 and PAT2, and explicit template
+ arguments EXPLICIT_ARGS return:
+
+ 1 if PAT1 is more specialized than PAT2 as described in [temp.func.order].
+ -1 if PAT2 is more specialized than PAT1.
+ 0 if neither is more specialized. */
+
int
-do_pending_expansions ()
+more_specialized (pat1, pat2, explicit_args)
+ tree pat1, pat2, explicit_args;
{
- struct pending_inline *i, *new_list = 0;
-
- {
- tree t;
- for (t = template_classes; t; t = TREE_CHAIN (t))
- instantiate_member_templates (TREE_PURPOSE (t));
- }
-
- if (!pending_template_expansions)
- return 0;
+ tree targs;
+ int winner = 0;
-#ifdef DEBUG
- fprintf (stderr, "\n\n\t\t IN DO_PENDING_EXPANSIONS\n\n");
-#endif
+ targs = get_bindings_overload (pat1, pat2, explicit_args);
+ if (targs)
+ {
+ --winner;
+ }
- i = pending_template_expansions;
- while (i)
+ targs = get_bindings_overload (pat2, pat1, explicit_args);
+ if (targs)
{
- tree context;
+ ++winner;
+ }
- struct pending_inline *next = i->next;
- tree t = i->fndecl;
+ return winner;
+}
- int decision = 0;
-#define DECIDE(N) do {decision=(N); goto decided;} while(0)
+/* Given two class template specialization list nodes PAT1 and PAT2, return:
- my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL
- || TREE_CODE (t) == VAR_DECL, 294);
- if (TREE_ASM_WRITTEN (t))
- DECIDE (0);
+ 1 if PAT1 is more specialized than PAT2 as described in [temp.class.order].
+ -1 if PAT2 is more specialized than PAT1.
+ 0 if neither is more specialized. */
+
+int
+more_specialized_class (pat1, pat2)
+ tree pat1, pat2;
+{
+ tree targs;
+ int winner = 0;
+
+ targs = get_class_bindings
+ (TREE_VALUE (pat1), TREE_PURPOSE (pat1),
+ TREE_PURPOSE (pat2), NULL_TREE);
+ if (targs)
+ --winner;
+
+ targs = get_class_bindings
+ (TREE_VALUE (pat2), TREE_PURPOSE (pat2),
+ TREE_PURPOSE (pat1), NULL_TREE);
+ if (targs)
+ ++winner;
+
+ return winner;
+}
- if (DECL_EXPLICIT_INSTANTIATION (t))
- DECIDE (DECL_NOT_REALLY_EXTERN (t));
- else if (! flag_implicit_templates)
- DECIDE (0);
+/* Return the template arguments that will produce the function signature
+ DECL from the function template FN, with the explicit template
+ arguments EXPLICIT_ARGS. If CHECK_RETTYPE is 1, the return type must
+ also match. */
- if (i->interface == 1)
- /* OK, it was an implicit instantiation. */
- {
- if (SUPPORTS_WEAK)
- DECL_WEAK (t) = 1;
- else
- TREE_PUBLIC (t) = 0;
- }
-
- /* If it's a method, let the class type decide it.
- @@ What if the method template is in a separate file?
- Maybe both file contexts should be taken into account?
- Maybe only do this if i->interface == 1 (unknown)? */
- context = DECL_CONTEXT (t);
- if (context != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (context)) == 't')
- {
- /* I'm interested in the context of this version of the function,
- not the original virtual declaration. */
- context = DECL_CLASS_CONTEXT (t);
-
- /* If `unknown', we might want a static copy.
- If `implementation', we want a global one.
- If `interface', ext ref. */
- if (CLASSTYPE_INTERFACE_KNOWN (context))
- DECIDE (!CLASSTYPE_INTERFACE_ONLY (context));
-#if 1 /* This doesn't get us stuff needed only by the file initializer. */
- DECIDE (TREE_USED (t));
-#else /* This compiles too much stuff, but that's probably better in
- most cases than never compiling the stuff we need. */
- DECIDE (1);
-#endif
- }
+static tree
+get_bindings_real (fn, decl, explicit_args, check_rettype)
+ tree fn, decl, explicit_args;
+ int check_rettype;
+{
+ int ntparms = DECL_NTPARMS (fn);
+ tree targs = make_scratch_vec (ntparms);
+ tree decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ tree extra_fn_arg = NULL_TREE;
+ int i;
- if (i->interface == 1)
- DECIDE (TREE_USED (t));
- else
- DECIDE (i->interface);
-
- decided:
-#ifdef DEBUG
- print_node_brief (stderr, decision ? "yes: " : "no: ", t, 0);
- fprintf (stderr, "\t%s\n",
- (DECL_ASSEMBLER_NAME (t)
- ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t))
- : ""));
-#endif
- if (decision)
- {
- i->next = pending_inlines;
- pending_inlines = i;
- }
+ if (DECL_STATIC_FUNCTION_P (fn)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ {
+ /* Sometimes we are trying to figure out what's being
+ specialized by a declaration that looks like a method, and it
+ turns out to be a static member function. */
+ if (CLASSTYPE_TEMPLATE_INFO (DECL_REAL_CONTEXT (fn))
+ && !is_member_template (fn))
+ /* The natural thing to do here seems to be to remove the
+ spurious `this' parameter from the DECL, but that prevents
+ unification from making use of the class type. So,
+ instead, we have fn_type_unification add to the parameters
+ for FN. */
+ extra_fn_arg = build_pointer_type (DECL_REAL_CONTEXT (fn));
else
- {
- i->next = new_list;
- new_list = i;
- }
- i = next;
+ /* In this case, though, adding the extra_fn_arg can confuse
+ things, so we remove from decl_arg_types instead. */
+ decl_arg_types = TREE_CHAIN (decl_arg_types);
}
- pending_template_expansions = new_list;
- if (!pending_inlines)
- return 0;
- do_pending_inlines ();
- return 1;
+
+ i = fn_type_unification (fn, explicit_args, targs,
+ decl_arg_types,
+ TREE_TYPE (TREE_TYPE (decl)),
+ DEDUCE_EXACT,
+ extra_fn_arg);
+
+ if (i != 0)
+ return NULL_TREE;
+
+ if (check_rettype)
+ {
+ /* Check to see that the resulting return type is also OK. */
+ tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)),
+ complete_template_args (fn, targs, 1),
+ NULL_TREE);
+
+ if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1))
+ return NULL_TREE;
+ }
+
+ return targs;
}
-
-struct pending_template {
- struct pending_template *next;
- tree id;
-};
+/* For most uses, we want to check the return type. */
-static struct pending_template* pending_templates;
+tree
+get_bindings (fn, decl, explicit_args)
+ tree fn, decl, explicit_args;
+{
+ return get_bindings_real (fn, decl, explicit_args, 1);
+}
-void
-do_pending_templates ()
+/* But for more_specialized, we only care about the parameter types. */
+
+static tree
+get_bindings_overload (fn, decl, explicit_args)
+ tree fn, decl, explicit_args;
{
- struct pending_template* t;
-
- for ( t = pending_templates; t; t = t->next)
+ return get_bindings_real (fn, decl, explicit_args, 0);
+}
+
+static tree
+get_class_bindings (tparms, parms, args, outer_args)
+ tree tparms, parms, args, outer_args;
+{
+ int i, ntparms = TREE_VEC_LENGTH (tparms);
+ tree vec = make_temp_vec (ntparms);
+
+ if (outer_args)
{
- instantiate_class_template (t->id, 1);
+ tparms = tsubst (tparms, outer_args, NULL_TREE);
+ parms = tsubst (parms, outer_args, NULL_TREE);
}
- for ( t = pending_templates; t; t = pending_templates)
+ for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
- pending_templates = t->next;
- free(t);
+ switch (unify (tparms, vec,
+ TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i),
+ UNIFY_ALLOW_NONE, 0))
+ {
+ case 0:
+ break;
+ case 1:
+ return NULL_TREE;
+ }
}
+
+ for (i = 0; i < ntparms; ++i)
+ if (! TREE_VEC_ELT (vec, i))
+ return NULL_TREE;
+
+ return vec;
}
-static void
-add_pending_template (pt)
- tree pt;
+/* Return the most specialized of the list of templates in FNS that can
+ produce an instantiation matching DECL, given the explicit template
+ arguments EXPLICIT_ARGS. */
+
+tree
+most_specialized (fns, decl, explicit_args)
+ tree fns, decl, explicit_args;
{
- struct pending_template *p;
-
- p = (struct pending_template *) malloc (sizeof (struct pending_template));
- p->next = pending_templates;
- pending_templates = p;
- p->id = pt;
+ tree fn, champ, args, *p;
+ int fate;
+
+ for (p = &fns; *p; )
+ {
+ args = get_bindings (TREE_VALUE (*p), decl, explicit_args);
+ if (args)
+ {
+ p = &TREE_CHAIN (*p);
+ }
+ else
+ *p = TREE_CHAIN (*p);
+ }
+
+ if (! fns)
+ return NULL_TREE;
+
+ fn = fns;
+ champ = TREE_VALUE (fn);
+ fn = TREE_CHAIN (fn);
+ for (; fn; fn = TREE_CHAIN (fn))
+ {
+ fate = more_specialized (champ, TREE_VALUE (fn), explicit_args);
+ if (fate == 1)
+ ;
+ else
+ {
+ if (fate == 0)
+ {
+ fn = TREE_CHAIN (fn);
+ if (! fn)
+ return error_mark_node;
+ }
+ champ = TREE_VALUE (fn);
+ }
+ }
+
+ for (fn = fns; fn && TREE_VALUE (fn) != champ; fn = TREE_CHAIN (fn))
+ {
+ fate = more_specialized (champ, TREE_VALUE (fn), explicit_args);
+ if (fate != 1)
+ return error_mark_node;
+ }
+
+ return champ;
}
-void
-mark_function_instantiated (result, extern_p)
- tree result;
- int extern_p;
+/* Return the most specialized of the class template specializations in
+ SPECS that can produce an instantiation matching ARGS. */
+
+tree
+most_specialized_class (specs, mainargs, outer_args)
+ tree specs, mainargs, outer_args;
{
- if (DECL_TEMPLATE_INSTANTIATION (result))
- SET_DECL_EXPLICIT_INSTANTIATION (result);
- TREE_PUBLIC (result) = 1;
+ tree list = NULL_TREE, t, args, champ;
+ int fate;
- if (! extern_p)
+ for (t = specs; t; t = TREE_CHAIN (t))
{
- DECL_INTERFACE_KNOWN (result) = 1;
- DECL_NOT_REALLY_EXTERN (result) = 1;
+ args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+ mainargs, outer_args);
+ if (args)
+ {
+ list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
+ TREE_TYPE (list) = TREE_TYPE (t);
+ }
+ }
+
+ if (! list)
+ return NULL_TREE;
+
+ t = list;
+ champ = t;
+ t = TREE_CHAIN (t);
+ for (; t; t = TREE_CHAIN (t))
+ {
+ fate = more_specialized_class (champ, t);
+ if (fate == 1)
+ ;
+ else
+ {
+ if (fate == 0)
+ {
+ t = TREE_CHAIN (t);
+ if (! t)
+ return error_mark_node;
+ }
+ champ = t;
+ }
}
+
+ for (t = list; t && t != champ; t = TREE_CHAIN (t))
+ {
+ fate = more_specialized_class (champ, t);
+ if (fate != 1)
+ return error_mark_node;
+ }
+
+ return champ;
}
/* called from the parser. */
+
void
-do_function_instantiation (declspecs, declarator, storage)
+do_decl_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage;
{
- tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0,
- NULL_TREE, NULL_TREE);
- tree name;
- tree fn;
+ tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL_TREE);
tree result = NULL_TREE;
int extern_p = 0;
+ if (! DECL_LANG_SPECIFIC (decl))
+ {
+ cp_error ("explicit instantiation of non-template `%#D'", decl);
+ return;
+ }
+
/* If we've already seen this template instance, use it. */
- if (name = DECL_ASSEMBLER_NAME (decl),
- fn = IDENTIFIER_GLOBAL_VALUE (name),
- fn && DECL_TEMPLATE_INSTANTIATION (fn))
- result = fn;
- else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn)
- {
- for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
- if (decls_match (fn, decl)
- && DECL_DEFER_OUTPUT (fn))
- {
- result = fn;
- break;
- }
- else if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
- tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
- int i, dummy = 0;
- i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
- TYPE_ARG_TYPES (TREE_TYPE (fn)),
- TYPE_ARG_TYPES (TREE_TYPE (decl)),
- &dummy, 0);
- if (i == 0)
- {
- if (result)
- cp_error ("ambiguous template instantiation for `%D' requested", decl);
- else
- result = instantiate_template (fn, targs);
- }
- free (targs);
- }
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, 0);
+ if (result && TREE_CODE (result) != VAR_DECL)
+ result = NULL_TREE;
+ }
+ else if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ cp_error ("explicit instantiation of `%#D'", decl);
+ return;
}
+ else if (DECL_TEMPLATE_INSTANTIATION (decl))
+ result = decl;
+
if (! result)
{
cp_error ("no matching template for `%D' found", decl);
return;
}
+ if (! DECL_TEMPLATE_INFO (result))
+ {
+ cp_pedwarn ("explicit instantiation of non-template `%#D'", result);
+ return;
+ }
+
if (flag_external_templates)
return;
@@ -2577,8 +7007,11 @@ do_function_instantiation (declspecs, declarator, storage)
else
cp_error ("storage class `%D' applied to template instantiation",
storage);
- mark_function_instantiated (result, extern_p);
+
+ mark_decl_instantiated (result, extern_p);
repo_template_instantiated (result, extern_p);
+ if (! extern_p)
+ instantiate_decl (result);
}
void
@@ -2599,12 +7032,23 @@ mark_class_instantiated (t, extern_p)
}
void
-do_type_instantiation (name, storage)
- tree name, storage;
+do_type_instantiation (t, storage)
+ tree t, storage;
{
- tree t = TREE_TYPE (name);
int extern_p = 0;
int nomem_p = 0;
+ int static_p = 0;
+
+ if (TREE_CODE (t) == TYPE_DECL)
+ t = TREE_TYPE (t);
+
+ if (! IS_AGGR_TYPE (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
+ {
+ cp_error ("explicit instantiation of non-template type `%T'", t);
+ return;
+ }
+
+ complete_type (t);
/* With -fexternal-templates, explicit instantiations are treated the same
as implicit ones. */
@@ -2624,6 +7068,8 @@ do_type_instantiation (name, storage)
nomem_p = 1;
else if (storage == ridpointers[(int) RID_EXTERN])
extern_p = 1;
+ else if (storage == ridpointers[(int) RID_STATIC])
+ static_p = 1;
else
{
cp_error ("storage class `%D' applied to template instantiation",
@@ -2647,30 +7093,26 @@ do_type_instantiation (name, storage)
{
tree tmp;
- /* Classes nested in template classes currently don't have an
- IDENTIFIER_TEMPLATE--their out-of-line members are handled
- by the enclosing template class. Note that there are name
- conflict bugs with this approach. */
- tmp = TYPE_IDENTIFIER (t);
- if (IDENTIFIER_TEMPLATE (tmp))
- instantiate_member_templates (tmp);
-
- /* this should really be done by instantiate_member_templates */
- tmp = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
- for (; tmp; tmp = TREE_CHAIN (tmp))
- if (DECL_TEMPLATE_INSTANTIATION (tmp))
- {
- mark_function_instantiated (tmp, extern_p);
- repo_template_instantiated (tmp, extern_p);
- }
-#if 0
+ if (! static_p)
+ for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
+ if (TREE_CODE (tmp) == FUNCTION_DECL
+ && DECL_TEMPLATE_INSTANTIATION (tmp))
+ {
+ mark_decl_instantiated (tmp, extern_p);
+ repo_template_instantiated (tmp, extern_p);
+ if (! extern_p)
+ instantiate_decl (tmp);
+ }
+
for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
- {
- if (TREE_CODE (tmp) == VAR_DECL)
- /* eventually do something */;
- }
-#endif
+ if (TREE_CODE (tmp) == VAR_DECL && DECL_TEMPLATE_INSTANTIATION (tmp))
+ {
+ mark_decl_instantiated (tmp, extern_p);
+ repo_template_instantiated (tmp, extern_p);
+ if (! extern_p)
+ instantiate_decl (tmp);
+ }
for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
if (IS_AGGR_TYPE (TREE_VALUE (tmp)))
@@ -2678,17 +7120,376 @@ do_type_instantiation (name, storage)
}
}
+/* Given a function DECL, which is a specialization of TEMP, modify
+ DECL to be a re-instantiation of TEMPL with the same template
+ arguments.
+
+ One reason for doing this is a scenario like this:
+
+ template <class T>
+ void f(const T&, int i);
+
+ void g() { f(3, 7); }
+
+ template <class T>
+ void f(const T& t, const int i) { }
+
+ Note that when the template is first instantiated, with
+ instantiate_template, the resulting DECL will have no name for the
+ first parameter, and the wrong type for the second. So, when we go
+ to instantiate the DECL, we regenerate it. */
+
+void
+regenerate_decl_from_template (decl, tmpl)
+ tree decl;
+ tree tmpl;
+{
+ tree args;
+ tree save_ti;
+ tree code_pattern;
+ tree new_decl;
+
+ args = DECL_TI_ARGS (decl);
+ code_pattern = DECL_TEMPLATE_RESULT (tmpl);
+
+ /* Trick tsubst into giving us a new decl. CODE_PATTERN must be the
+ most distant ancestor of DECL, since that's the one that will
+ actually be altered by a redefinition. */
+ save_ti = DECL_TEMPLATE_INFO (code_pattern);
+ DECL_TEMPLATE_INFO (code_pattern) = NULL_TREE;
+ new_decl = tsubst (code_pattern, args, NULL_TREE);
+ SET_DECL_IMPLICIT_INSTANTIATION (new_decl);
+ DECL_TEMPLATE_INFO (code_pattern) = save_ti;
+
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ /* Set up DECL_INITIAL, since tsubst doesn't. */
+ pushclass (DECL_CONTEXT (decl), 2);
+ DECL_INITIAL (new_decl) =
+ tsubst_expr (DECL_INITIAL (code_pattern), args,
+ DECL_TI_TEMPLATE (decl));
+ popclass (1);
+ }
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
+ new decl. */
+ DECL_INITIAL (new_decl) = error_mark_node;
+
+ if (DECL_TEMPLATE_SPECIALIZATION (new_decl)
+ && !DECL_TEMPLATE_INFO (new_decl))
+ /* Set up the information about what is being specialized. */
+ DECL_TEMPLATE_INFO (new_decl) = DECL_TEMPLATE_INFO (decl);
+ }
+
+ duplicate_decls (new_decl, decl);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ DECL_INITIAL (new_decl) = NULL_TREE;
+}
+
+/* Produce the definition of D, a _DECL generated from a template. */
+
tree
-create_nested_upt (scope, name)
- tree scope, name;
+instantiate_decl (d)
+ tree d;
{
- tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
- tree d = build_decl (TYPE_DECL, name, t);
+ tree ti = DECL_TEMPLATE_INFO (d);
+ tree tmpl = TI_TEMPLATE (ti);
+ tree args = TI_ARGS (ti);
+ tree td;
+ tree decl_pattern, code_pattern;
+ int nested = in_function_p ();
+ int d_defined;
+ int pattern_defined;
+ int line = lineno;
+ char *file = input_filename;
+
+ for (td = tmpl;
+ DECL_TEMPLATE_INSTANTIATION (td)
+ /* This next clause handles friend templates defined inside
+ class templates. The friend templates are not really
+ instantiations from the point of view of the language, but
+ they are instantiations from the point of view of the
+ compiler. */
+ || (DECL_TEMPLATE_INFO (td) && !DECL_TEMPLATE_SPECIALIZATION (td));
+ )
+ td = DECL_TI_TEMPLATE (td);
+
+ /* In the case of a member template, decl_pattern is the partially
+ instantiated declaration (in the instantiated class), and code_pattern
+ is the original template definition. */
+ decl_pattern = DECL_TEMPLATE_RESULT (tmpl);
+ code_pattern = DECL_TEMPLATE_RESULT (td);
+
+ if (TREE_CODE (d) == FUNCTION_DECL)
+ {
+ d_defined = (DECL_INITIAL (d) != NULL_TREE);
+ pattern_defined = (DECL_INITIAL (code_pattern) != NULL_TREE);
+ }
+ else
+ {
+ d_defined = ! DECL_IN_AGGR_P (d);
+ pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
+ }
+
+ if (d_defined)
+ return d;
+
+ if (TREE_CODE (d) == FUNCTION_DECL)
+ {
+ tree spec = retrieve_specialization (tmpl, args);
+
+ if (spec != NULL_TREE
+ && DECL_TEMPLATE_SPECIALIZATION (spec))
+ return spec;
+ }
+
+ /* This needs to happen before any tsubsting. */
+ if (! push_tinst_level (d))
+ return d;
+
+ push_to_top_level ();
+ lineno = DECL_SOURCE_LINE (d);
+ input_filename = DECL_SOURCE_FILE (d);
+
+ if (pattern_defined)
+ {
+ repo_template_used (d);
+
+ if (flag_external_templates && ! DECL_INTERFACE_KNOWN (d))
+ {
+ if (flag_alt_external_templates)
+ {
+ if (interface_unknown)
+ warn_if_unknown_interface (d);
+ }
+ else if (DECL_INTERFACE_KNOWN (code_pattern))
+ {
+ DECL_INTERFACE_KNOWN (d) = 1;
+ DECL_NOT_REALLY_EXTERN (d) = ! DECL_EXTERNAL (code_pattern);
+ }
+ else
+ warn_if_unknown_interface (code_pattern);
+ }
+
+ if (at_eof)
+ import_export_decl (d);
+ }
+
+ /* Reject all external templates except inline functions. */
+ if (DECL_INTERFACE_KNOWN (d)
+ && ! DECL_NOT_REALLY_EXTERN (d)
+ && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
+ goto out;
+
+ if (TREE_CODE (d) == VAR_DECL
+ && TREE_READONLY (d)
+ && DECL_INITIAL (d) == NULL_TREE
+ && DECL_INITIAL (code_pattern) != NULL_TREE)
+ /* We need to set up DECL_INITIAL regardless of pattern_defined if
+ the variable is a static const initialized in the class body. */;
+ else if (! pattern_defined
+ || (! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d) && nested)
+ && ! at_eof))
+ {
+ /* Defer all templates except inline functions used in another
+ function. */
+ lineno = line;
+ input_filename = file;
+
+ add_pending_template (d);
+ goto out;
+ }
+
+ regenerate_decl_from_template (d, td);
+
+ /* We already set the file and line above. Reset them now in case
+ they changed as a result of calling regenerate_decl_from_template. */
+ lineno = DECL_SOURCE_LINE (d);
+ input_filename = DECL_SOURCE_FILE (d);
+
+ if (TREE_CODE (d) == VAR_DECL)
+ {
+ DECL_IN_AGGR_P (d) = 0;
+ if (DECL_INTERFACE_KNOWN (d))
+ DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
+ else
+ {
+ DECL_EXTERNAL (d) = 1;
+ DECL_NOT_REALLY_EXTERN (d) = 1;
+ }
+ cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0, 0);
+ }
+ else if (TREE_CODE (d) == FUNCTION_DECL)
+ {
+ tree t = DECL_SAVED_TREE (code_pattern);
+
+ start_function (NULL_TREE, d, NULL_TREE, 1);
+ store_parm_decls ();
+
+ if (t && TREE_CODE (t) == RETURN_INIT)
+ {
+ store_return_init
+ (TREE_OPERAND (t, 0),
+ tsubst_expr (TREE_OPERAND (t, 1), args, tmpl));
+ t = TREE_CHAIN (t);
+ }
+
+ if (t && TREE_CODE (t) == CTOR_INITIALIZER)
+ {
+ current_member_init_list
+ = tsubst_expr_values (TREE_OPERAND (t, 0), args);
+ current_base_init_list
+ = tsubst_expr_values (TREE_OPERAND (t, 1), args);
+ t = TREE_CHAIN (t);
+ }
- TYPE_NAME (t) = d;
- TYPE_VALUES (t) = TYPE_VALUES (scope);
- TYPE_CONTEXT (t) = scope;
+ setup_vtbl_ptr ();
+ /* Always keep the BLOCK node associated with the outermost
+ pair of curly braces of a function. These are needed
+ for correct operation of dwarfout.c. */
+ keep_next_level ();
+
+ my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
+ tsubst_expr (t, args, tmpl);
+
+ finish_function (lineno, 0, nested);
+ }
+
+out:
+ lineno = line;
+ input_filename = file;
+
+ pop_from_top_level ();
+ pop_tinst_level ();
- pushdecl (d);
return d;
}
+
+tree
+tsubst_chain (t, argvec)
+ tree t, argvec;
+{
+ if (t)
+ {
+ tree first = tsubst (t, argvec, NULL_TREE);
+ tree last = first;
+
+ for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t))
+ {
+ tree x = tsubst (t, argvec, NULL_TREE);
+ TREE_CHAIN (last) = x;
+ last = x;
+ }
+
+ return first;
+ }
+ return NULL_TREE;
+}
+
+static tree
+tsubst_expr_values (t, argvec)
+ tree t, argvec;
+{
+ tree first = NULL_TREE;
+ tree *p = &first;
+
+ for (; t; t = TREE_CHAIN (t))
+ {
+ tree pur = tsubst_copy (TREE_PURPOSE (t), argvec, NULL_TREE);
+ tree val = tsubst_expr (TREE_VALUE (t), argvec, NULL_TREE);
+ *p = build_tree_list (pur, val);
+ p = &TREE_CHAIN (*p);
+ }
+ return first;
+}
+
+tree last_tree;
+
+void
+add_tree (t)
+ tree t;
+{
+ last_tree = TREE_CHAIN (last_tree) = t;
+}
+
+
+void
+begin_tree ()
+{
+ saved_trees = tree_cons (NULL_TREE, last_tree, saved_trees);
+ last_tree = NULL_TREE;
+}
+
+
+void
+end_tree ()
+{
+ my_friendly_assert (saved_trees != NULL_TREE, 0);
+
+ last_tree = TREE_VALUE (saved_trees);
+ saved_trees = TREE_CHAIN (saved_trees);
+}
+
+/* D is an undefined function declaration in the presence of templates with
+ the same name, listed in FNS. If one of them can produce D as an
+ instantiation, remember this so we can instantiate it at EOF if D has
+ not been defined by that time. */
+
+void
+add_maybe_template (d, fns)
+ tree d, fns;
+{
+ tree t;
+
+ if (DECL_MAYBE_TEMPLATE (d))
+ return;
+
+ t = most_specialized (fns, d, NULL_TREE);
+ if (! t)
+ return;
+ if (t == error_mark_node)
+ {
+ cp_error ("ambiguous template instantiation for `%D'", d);
+ return;
+ }
+
+ *maybe_template_tail = perm_tree_cons (t, d, NULL_TREE);
+ maybe_template_tail = &TREE_CHAIN (*maybe_template_tail);
+ DECL_MAYBE_TEMPLATE (d) = 1;
+}
+
+/* Instantiate an enumerated type. Used by instantiate_class_template and
+ tsubst_expr. */
+
+static tree
+tsubst_enum (tag, args, field_chain)
+ tree tag, args;
+ tree * field_chain;
+{
+ extern tree current_local_enum;
+ tree prev_local_enum = current_local_enum;
+
+ tree newtag = start_enum (TYPE_IDENTIFIER (tag));
+ tree e, values = NULL_TREE;
+
+ for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
+ {
+ tree elt = build_enumerator (TREE_PURPOSE (e),
+ tsubst_expr (TREE_VALUE (e), args,
+ NULL_TREE));
+ TREE_CHAIN (elt) = values;
+ values = elt;
+ }
+
+ finish_enum (newtag, values);
+
+ if (NULL != field_chain)
+ *field_chain = grok_enum_decls (NULL_TREE);
+
+ current_local_enum = prev_local_enum;
+
+ return newtag;
+}
diff --git a/contrib/gcc/cp/ptree.c b/contrib/gcc/cp/ptree.c
index ad1480a..aa3066c 100644
--- a/contrib/gcc/cp/ptree.c
+++ b/contrib/gcc/cp/ptree.c
@@ -21,8 +21,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include "system.h"
#include "tree.h"
-#include <stdio.h>
#include "cp-tree.h"
void
@@ -66,16 +66,16 @@ print_lang_type (file, node, indent)
register tree node;
int indent;
{
- if (TREE_CODE (node) == TEMPLATE_TYPE_PARM)
+ if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (node) == TEMPLATE_TEMPLATE_PARM)
{
- print_node (file, "tinfo", TYPE_VALUES (node), indent + 4);
- return;
- }
-
- if (TREE_CODE (node) == UNINSTANTIATED_P_TYPE)
- {
- print_node (file, "template", UPT_TEMPLATE (node), indent + 4);
- print_node (file, "parameters", UPT_PARMS (node), indent + 4);
+ indent_to (file, indent + 3);
+ fputs ("index ", file);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, TEMPLATE_TYPE_IDX (node));
+ fputs (" level ", file);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, TEMPLATE_TYPE_LEVEL (node));
+ fputs (" orig_level ", file);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, TEMPLATE_TYPE_ORIG_LEVEL (node));
return;
}
@@ -98,10 +98,6 @@ print_lang_type (file, node, indent)
fputs (" X()", file);
if (TYPE_HAS_CONVERSION (node))
fputs (" has-type-conversion", file);
- if (TYPE_HAS_INT_CONVERSION (node))
- fputs (" has-int-conversion", file);
- if (TYPE_HAS_REAL_CONVERSION (node))
- fputs (" has-float-conversion", file);
if (TYPE_HAS_INIT_REF (node))
{
if (TYPE_HAS_CONST_INIT_REF (node))
@@ -121,10 +117,6 @@ print_lang_type (file, node, indent)
fputs (" has=", file);
if (TYPE_HAS_ASSIGN_REF (node))
fputs (" this=(X&)", file);
- if (TYPE_OVERLOADS_METHOD_CALL_EXPR (node))
- fputs (" op->()", file);
- if (TYPE_GETS_INIT_AGGR (node))
- fputs (" gets X(X, ...)", file);
if (TYPE_OVERLOADS_CALL_EXPR (node))
fputs (" op()", file);
if (TYPE_OVERLOADS_ARRAY_REF (node))
@@ -158,7 +150,7 @@ print_lang_identifier (file, node, indent)
tree node;
int indent;
{
- print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
+ print_node (file, "bindings", IDENTIFIER_NAMESPACE_BINDINGS (node), indent + 4);
print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
@@ -166,3 +158,34 @@ print_lang_identifier (file, node, indent)
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4);
}
+
+void
+lang_print_xnode (file, node, indent)
+ FILE *file;
+ tree node;
+ int indent;
+{
+ switch (TREE_CODE (node))
+ {
+ case CPLUS_BINDING:
+ print_node (file, "scope", BINDING_SCOPE (node), indent+4);
+ print_node (file, "value", BINDING_VALUE (node), indent+4);
+ print_node (file, "chain", TREE_CHAIN (node), indent+4);
+ break;
+ case OVERLOAD:
+ print_node (file, "function", OVL_FUNCTION (node), indent+4);
+ print_node (file, "chain", TREE_CHAIN (node), indent+4);
+ break;
+ case TEMPLATE_PARM_INDEX:
+ indent_to (file, indent + 3);
+ fputs ("index ", file);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, TEMPLATE_PARM_IDX (node));
+ fputs (" level ", file);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, TEMPLATE_PARM_LEVEL (node));
+ fputs (" orig_level ", file);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, TEMPLATE_PARM_ORIG_LEVEL (node));
+ break;
+ default:
+ break;
+ }
+}
diff --git a/contrib/gcc/cp/repo.c b/contrib/gcc/cp/repo.c
index 50fc9f8..742250d 100644
--- a/contrib/gcc/cp/repo.c
+++ b/contrib/gcc/cp/repo.c
@@ -1,5 +1,5 @@
/* Code to maintain a C++ template repository.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1997 Free Software Foundation, Inc.
Contributed by Jason Merrill (jason@cygnus.com)
This file is part of GNU CC.
@@ -25,22 +25,30 @@ Boston, MA 02111-1307, USA. */
The results of the automatic process should be easily reproducible with
explicit code. */
-#include <stdio.h>
#include "config.h"
+#include "system.h"
#include "tree.h"
#include "cp-tree.h"
#include "input.h"
#include "obstack.h"
+#include "toplev.h"
-extern char * rindex ();
-extern char * getenv ();
-extern char * getpwd ();
+extern char *getpwd PROTO((void));
+
+static tree repo_get_id PROTO((tree));
+static char *extract_string PROTO((char **));
+static char *get_base_filename PROTO((char *));
+static void open_repo_file PROTO((char *));
+static char *afgets PROTO((FILE *));
+static void reopen_repo_file_for_write PROTO((void));
static tree pending_repo;
static tree original_repo;
static char *repo_name;
static FILE *repo_file;
+static char *old_args, *old_dir, *old_main;
+
extern int flag_use_repository;
extern int errorcount, sorrycount;
extern struct obstack temporary_obstack;
@@ -49,6 +57,7 @@ extern struct obstack permanent_obstack;
#define IDENTIFIER_REPO_USED(NODE) (TREE_LANG_FLAG_3 (NODE))
#define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
+#if 0
/* Record the flags used to compile this translation unit. */
void
@@ -82,8 +91,9 @@ void
repo_class_defined (t)
tree t;
{}
+#endif
-tree
+static tree
repo_get_id (t)
tree t;
{
@@ -97,7 +107,7 @@ repo_get_id (t)
}
/* Note that a template has been used. If we can see the definition, offer
- to emit it. */
+ to emit it. */
void
repo_template_used (t)
@@ -120,7 +130,7 @@ repo_template_used (t)
else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
{
if (IDENTIFIER_REPO_CHOSEN (id))
- mark_function_instantiated (t, 0);
+ mark_decl_instantiated (t, 0);
}
else
my_friendly_abort (1);
@@ -132,9 +142,10 @@ repo_template_used (t)
}
}
+#if 0
/* Note that the vtable for a class has been used, and offer to emit it. */
-void
+static void
repo_vtable_used (t)
tree t;
{
@@ -172,6 +183,7 @@ repo_tinfo_used (ti)
tree ti;
{
}
+#endif
void
repo_template_instantiated (t, extern_p)
@@ -186,12 +198,37 @@ repo_template_instantiated (t, extern_p)
}
}
+/* Parse a reasonable subset of shell quoting syntax. */
+
static char *
-save_string (s, len)
- char *s;
- int len;
+extract_string (pp)
+ char **pp;
{
- return obstack_copy0 (&temporary_obstack, s, len);
+ char *p = *pp;
+ int backquote = 0;
+ int inside = 0;
+
+ for (;;)
+ {
+ char c = *p;
+ if (c == '\0')
+ break;
+ ++p;
+ if (backquote)
+ obstack_1grow (&temporary_obstack, c);
+ else if (! inside && c == ' ')
+ break;
+ else if (! inside && c == '\\')
+ backquote = 1;
+ else if (c == '\'')
+ inside = !inside;
+ else
+ obstack_1grow (&temporary_obstack, c);
+ }
+
+ obstack_1grow (&temporary_obstack, '\0');
+ *pp = p;
+ return obstack_finish (&temporary_obstack);
}
static char *
@@ -199,30 +236,17 @@ get_base_filename (filename)
char *filename;
{
char *p = getenv ("COLLECT_GCC_OPTIONS");
- char *output = 0;
+ char *output = NULL;
int compiling = 0;
- if (p)
- while (*p)
- {
- char *q = p;
- while (*q && *q != ' ') q++;
- if (*p == '-' && p[1] == 'o')
- {
- p += 2;
- if (p == q)
- {
- p++; q++;
- if (*q)
- while (*q && *q != ' ') q++;
- }
+ while (p && *p)
+ {
+ char *q = extract_string (&p);
- output = save_string (p, q - p);
- }
- else if (*p == '-' && p[1] == 'c')
- compiling = 1;
- if (*q) q++;
- p = q;
+ if (strcmp (q, "-o") == 0)
+ output = extract_string (&p);
+ else if (strcmp (q, "-c") == 0)
+ compiling = 1;
}
if (compiling && output)
@@ -235,26 +259,20 @@ get_base_filename (filename)
return NULL;
}
- p = rindex (filename, '/');
- if (p)
- return p+1;
- else
- return filename;
+ return file_name_nondirectory (filename);
}
static void
open_repo_file (filename)
char *filename;
{
- register char *p, *q;
+ register char *p;
char *s = get_base_filename (filename);
if (s == NULL)
return;
- p = rindex (s, '/');
- if (! p)
- p = s;
+ p = file_name_nondirectory (s);
p = rindex (p, '.');
if (! p)
p = s + strlen (s);
@@ -292,13 +310,21 @@ init_repo (filename)
if (repo_file == 0)
return;
- while (buf = afgets (repo_file))
+ while ((buf = afgets (repo_file)))
{
switch (buf[0])
{
case 'A':
+ old_args = obstack_copy0 (&permanent_obstack, buf + 2,
+ strlen (buf + 2));
+ break;
case 'D':
+ old_dir = obstack_copy0 (&permanent_obstack, buf + 2,
+ strlen (buf + 2));
+ break;
case 'M':
+ old_main = obstack_copy0 (&permanent_obstack, buf + 2,
+ strlen (buf + 2));
break;
case 'C':
case 'O':
@@ -344,8 +370,8 @@ void
finish_repo ()
{
tree t;
- char *p;
int repo_changed = 0;
+ char *dir, *args;
if (! flag_use_repository)
return;
@@ -378,6 +404,16 @@ finish_repo ()
}
}
+ dir = getpwd ();
+ args = getenv ("COLLECT_GCC_OPTIONS");
+
+ if (! repo_changed && pending_repo)
+ if (strcmp (old_main, main_input_filename) != 0
+ || strcmp (old_dir, dir) != 0
+ || (args == NULL) != (old_args == NULL)
+ || (args && strcmp (old_args, args) != 0))
+ repo_changed = 1;
+
if (! repo_changed || errorcount || sorrycount)
goto out;
@@ -387,13 +423,9 @@ finish_repo ()
goto out;
fprintf (repo_file, "M %s\n", main_input_filename);
-
- p = getpwd ();
- fprintf (repo_file, "D %s\n", p);
-
- p = getenv ("COLLECT_GCC_OPTIONS");
- if (p != 0)
- fprintf (repo_file, "A %s\n", p);
+ fprintf (repo_file, "D %s\n", dir);
+ if (args)
+ fprintf (repo_file, "A %s\n", args);
for (t = pending_repo; t; t = TREE_CHAIN (t))
{
diff --git a/contrib/gcc/cp/rtti.c b/contrib/gcc/cp/rtti.c
new file mode 100644
index 0000000..b93c1cc
--- /dev/null
+++ b/contrib/gcc/cp/rtti.c
@@ -0,0 +1,1135 @@
+/* RunTime Type Identification
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Mostly written by Jason Merrill (jason@cygnus.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "cp-tree.h"
+#include "flags.h"
+#include "output.h"
+#include "assert.h"
+#include "toplev.h"
+
+#ifndef INT_TYPE_SIZE
+#define INT_TYPE_SIZE BITS_PER_WORD
+#endif
+
+extern struct obstack permanent_obstack;
+
+static tree call_void_fn PROTO((char *));
+static tree build_headof_sub PROTO((tree));
+static tree build_headof PROTO((tree));
+static tree get_tinfo_var PROTO((tree));
+static tree get_typeid_1 PROTO((tree));
+static tree ifnonnull PROTO((tree, tree));
+static tree build_dynamic_cast_1 PROTO((tree, tree));
+static void expand_si_desc PROTO((tree, tree));
+static void expand_class_desc PROTO((tree, tree));
+static void expand_attr_desc PROTO((tree, tree));
+static void expand_ptr_desc PROTO((tree, tree));
+static void expand_generic_desc PROTO((tree, tree, char *));
+static tree throw_bad_cast PROTO((void));
+static tree throw_bad_typeid PROTO((void));
+
+tree type_info_type_node;
+tree tinfo_fn_id;
+tree tinfo_fn_type;
+
+void
+init_rtti_processing ()
+{
+ if (flag_honor_std)
+ push_namespace (get_identifier ("std"));
+ type_info_type_node = xref_tag
+ (class_type_node, get_identifier ("type_info"), NULL_TREE, 1);
+ if (flag_honor_std)
+ pop_namespace ();
+ tinfo_fn_id = get_identifier ("__tf");
+ tinfo_fn_type = build_function_type
+ (build_reference_type (build_type_variant (type_info_type_node, 1, 0)),
+ void_list_node);
+}
+
+/* Given a pointer to an object with at least one virtual table
+ pointer somewhere, return a pointer to a possible sub-object that
+ has a virtual table pointer in it that is the vtable parent for
+ that sub-object. */
+
+static tree
+build_headof_sub (exp)
+ tree exp;
+{
+ tree type = TREE_TYPE (TREE_TYPE (exp));
+ tree basetype = CLASSTYPE_RTTI (type);
+ tree binfo = get_binfo (basetype, type, 0);
+
+ exp = convert_pointer_to_real (binfo, exp);
+ return exp;
+}
+
+/* Given the expression EXP of type `class *', return the head of the
+ object pointed to by EXP with type cv void*, if the class has any
+ virtual functions (TYPE_VIRTUAL_P), else just return the
+ expression. */
+
+static tree
+build_headof (exp)
+ tree exp;
+{
+ tree type = TREE_TYPE (exp);
+ tree aref;
+ tree offset;
+
+ if (TREE_CODE (type) != POINTER_TYPE)
+ {
+ error ("`headof' applied to non-pointer type");
+ return error_mark_node;
+ }
+ type = TREE_TYPE (type);
+
+ if (!TYPE_VIRTUAL_P (type))
+ return exp;
+
+ /* If we don't have rtti stuff, get to a sub-object that does. */
+ if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))
+ exp = build_headof_sub (exp);
+
+ /* We use this a couple of times below, protect it. */
+ exp = save_expr (exp);
+
+ aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
+
+ if (flag_vtable_thunks)
+ offset = aref;
+ else
+ offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
+
+ type = build_type_variant (ptr_type_node, TREE_READONLY (exp),
+ TREE_THIS_VOLATILE (exp));
+ return build (PLUS_EXPR, type, exp,
+ cp_convert (ptrdiff_type_node, offset));
+}
+
+/* Build a call to a generic entry point taking and returning void. */
+
+static tree
+call_void_fn (name)
+ char *name;
+{
+ tree d = get_identifier (name);
+ tree type;
+
+ if (IDENTIFIER_GLOBAL_VALUE (d))
+ d = IDENTIFIER_GLOBAL_VALUE (d);
+ else
+ {
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+
+ type = build_function_type (void_type_node, void_list_node);
+ d = build_lang_decl (FUNCTION_DECL, d, type);
+ DECL_EXTERNAL (d) = 1;
+ TREE_PUBLIC (d) = 1;
+ DECL_ARTIFICIAL (d) = 1;
+ pushdecl_top_level (d);
+ make_function_rtl (d);
+ assemble_external (d);
+
+ pop_obstacks ();
+ }
+
+ return build_call (d, void_type_node, NULL_TREE);
+}
+
+/* Get a bad_cast node for the program to throw...
+
+ See libstdc++/exception.cc for __throw_bad_cast */
+
+static tree
+throw_bad_cast ()
+{
+ return call_void_fn ("__throw_bad_cast");
+}
+
+static tree
+throw_bad_typeid ()
+{
+ return call_void_fn ("__throw_bad_typeid");
+}
+
+/* Return the type_info function associated with the expression EXP. If
+ EXP is a reference to a polymorphic class, return the dynamic type;
+ otherwise return the static type of the expression. */
+
+tree
+get_tinfo_fn_dynamic (exp)
+ tree exp;
+{
+ tree type;
+
+ if (exp == error_mark_node)
+ return error_mark_node;
+
+ if (type_unknown_p (exp))
+ {
+ error ("typeid of overloaded function");
+ return error_mark_node;
+ }
+
+ type = TREE_TYPE (exp);
+
+ /* peel back references, so they match. */
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+
+ /* Peel off cv qualifiers. */
+ type = TYPE_MAIN_VARIANT (type);
+
+ /* If exp is a reference to polymorphic type, get the real type_info. */
+ if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
+ {
+ /* build reference to type_info from vtable. */
+ tree t;
+
+ if (! flag_rtti)
+ {
+ warning ("taking dynamic typeid of object without -frtti");
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ init_rtti_processing ();
+ pop_obstacks ();
+ flag_rtti = 1;
+ }
+
+ /* If we don't have rtti stuff, get to a sub-object that does. */
+ if (! CLASSTYPE_VFIELDS (type))
+ {
+ exp = build_unary_op (ADDR_EXPR, exp, 0);
+ exp = build_headof_sub (exp);
+ exp = build_indirect_ref (exp, NULL_PTR);
+ }
+
+ if (flag_vtable_thunks)
+ t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
+ else
+ t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
+ TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
+ return t;
+ }
+
+ /* otherwise return the type_info for the static type of the expr. */
+ return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
+}
+
+tree
+build_typeid (exp)
+ tree exp;
+{
+ exp = get_tinfo_fn_dynamic (exp);
+ exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);
+ return convert_from_reference (exp);
+}
+
+tree
+build_x_typeid (exp)
+ tree exp;
+{
+ tree cond = NULL_TREE;
+ tree type = TREE_TYPE (tinfo_fn_type);
+ int nonnull;
+
+ if (processing_template_decl)
+ return build_min_nt (TYPEID_EXPR, exp);
+
+ if (TREE_CODE (exp) == INDIRECT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
+ && TYPE_VIRTUAL_P (TREE_TYPE (exp))
+ && ! resolves_to_fixed_type_p (exp, &nonnull)
+ && ! nonnull)
+ {
+ exp = stabilize_reference (exp);
+ cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));
+ }
+
+ exp = get_tinfo_fn_dynamic (exp);
+
+ if (exp == error_mark_node)
+ return error_mark_node;
+
+ exp = build_call (exp, type, NULL_TREE);
+
+ if (cond)
+ {
+ tree bad = throw_bad_typeid ();
+
+ bad = build_compound_expr
+ (expr_tree_cons (NULL_TREE, bad, build_expr_list
+ (NULL_TREE, cp_convert (type, integer_zero_node))));
+ exp = build (COND_EXPR, type, cond, exp, bad);
+ }
+
+ return convert_from_reference (exp);
+}
+
+static tree
+get_tinfo_var (type)
+ tree type;
+{
+ tree tname = build_overload_with_type (get_identifier ("__ti"), type);
+ tree tdecl, arrtype;
+ int size;
+
+ if (IDENTIFIER_GLOBAL_VALUE (tname))
+ return IDENTIFIER_GLOBAL_VALUE (tname);
+
+ /* Figure out how much space we need to allocate for the type_info object.
+ If our struct layout or the type_info classes are changed, this will
+ need to be modified. */
+ if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
+ size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
+ || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
+ size = 3 * POINTER_SIZE;
+ else if (IS_AGGR_TYPE (type))
+ {
+ if (CLASSTYPE_N_BASECLASSES (type) == 0)
+ size = 2 * POINTER_SIZE;
+ else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
+ && (TREE_VIA_PUBLIC
+ (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
+ size = 3 * POINTER_SIZE;
+ else
+ size = 3 * POINTER_SIZE + TYPE_PRECISION (sizetype);
+ }
+ else
+ size = 2 * POINTER_SIZE;
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+
+ /* The type for a character array of the appropriate size. */
+ arrtype = build_cplus_array_type
+ (unsigned_char_type_node,
+ build_index_type (size_int (size / BITS_PER_UNIT - 1)));
+
+ tdecl = build_decl (VAR_DECL, tname, arrtype);
+ TREE_PUBLIC (tdecl) = 1;
+ DECL_EXTERNAL (tdecl) = 1;
+ DECL_ARTIFICIAL (tdecl) = 1;
+ pushdecl_top_level (tdecl);
+ cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
+
+ pop_obstacks ();
+
+ return tdecl;
+}
+
+tree
+get_tinfo_fn (type)
+ tree type;
+{
+ tree name;
+ tree d;
+
+ if (TREE_CODE (type) == OFFSET_TYPE)
+ type = TREE_TYPE (type);
+ if (TREE_CODE (type) == METHOD_TYPE)
+ type = build_function_type (TREE_TYPE (type),
+ TREE_CHAIN (TYPE_ARG_TYPES (type)));
+
+ name = build_overload_with_type (tinfo_fn_id, type);
+
+ if (IDENTIFIER_GLOBAL_VALUE (name))
+ return IDENTIFIER_GLOBAL_VALUE (name);
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+
+ d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
+ DECL_EXTERNAL (d) = 1;
+ TREE_PUBLIC (d) = 1;
+ DECL_ARTIFICIAL (d) = 1;
+ DECL_NOT_REALLY_EXTERN (d) = 1;
+ DECL_MUTABLE_P (d) = 1;
+ TREE_TYPE (name) = copy_to_permanent (type);
+
+ pushdecl_top_level (d);
+ make_function_rtl (d);
+ assemble_external (d);
+ mark_inline_for_output (d);
+ pop_obstacks ();
+
+ return d;
+}
+
+static tree
+get_typeid_1 (type)
+ tree type;
+{
+ tree t = build_call
+ (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
+ return convert_from_reference (t);
+}
+
+/* Return the type_info object for TYPE, creating it if necessary. */
+
+tree
+get_typeid (type)
+ tree type;
+{
+ if (type == error_mark_node)
+ return error_mark_node;
+
+ if (! flag_rtti)
+ {
+ warning ("requesting typeid of object without -frtti");
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ init_rtti_processing ();
+ pop_obstacks ();
+ flag_rtti = 1;
+ }
+
+ if (processing_template_decl)
+ return build_min_nt (TYPEID_EXPR, type);
+
+ /* If the type of the type-id is a reference type, the result of the
+ typeid expression refers to a type_info object representing the
+ referenced type. */
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+
+ /* The top-level cv-qualifiers of the lvalue expression or the type-id
+ that is the operand of typeid are always ignored. */
+ type = TYPE_MAIN_VARIANT (type);
+
+ return get_typeid_1 (type);
+}
+
+/* Check whether TEST is null before returning RESULT. If TEST is used in
+ RESULT, it must have previously had a save_expr applied to it. */
+
+static tree
+ifnonnull (test, result)
+ tree test, result;
+{
+ return build (COND_EXPR, TREE_TYPE (result),
+ build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
+ cp_convert (TREE_TYPE (result), integer_zero_node),
+ result);
+}
+
+/* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
+ paper. */
+
+static tree
+build_dynamic_cast_1 (type, expr)
+ tree type, expr;
+{
+ enum tree_code tc = TREE_CODE (type);
+ tree exprtype = TREE_TYPE (expr);
+ enum tree_code ec;
+ tree dcast_fn;
+
+ assert (exprtype != NULL_TREE);
+ ec = TREE_CODE (exprtype);
+
+ switch (tc)
+ {
+ case POINTER_TYPE:
+ if (ec == REFERENCE_TYPE)
+ {
+ expr = convert_from_reference (expr);
+ exprtype = TREE_TYPE (expr);
+ ec = TREE_CODE (exprtype);
+ }
+ if (ec != POINTER_TYPE)
+ goto fail;
+ if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
+ goto fail;
+ if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
+ goto fail;
+ if (TREE_READONLY (TREE_TYPE (exprtype))
+ && ! TYPE_READONLY (TREE_TYPE (type)))
+ goto fail;
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
+ break;
+ /* else fall through */
+ case REFERENCE_TYPE:
+ if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
+ goto fail;
+ if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
+ goto fail;
+ break;
+ /* else fall through */
+ default:
+ goto fail;
+ }
+
+ /* Apply trivial conversion T -> T& for dereferenced ptrs. */
+ if (ec == RECORD_TYPE)
+ {
+ exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
+ TREE_THIS_VOLATILE (expr));
+ exprtype = build_reference_type (exprtype);
+ expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
+ LOOKUP_NORMAL, NULL_TREE);
+ ec = REFERENCE_TYPE;
+ }
+
+ if (tc == REFERENCE_TYPE)
+ {
+ if (ec != REFERENCE_TYPE)
+ goto fail;
+ if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
+ goto fail;
+ if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
+ goto fail;
+ if (TREE_READONLY (TREE_TYPE (exprtype))
+ && ! TYPE_READONLY (TREE_TYPE (type)))
+ goto fail;
+ }
+
+ /* If *type is an unambiguous accessible base class of *exprtype,
+ convert statically. */
+ {
+ int distance;
+ tree path;
+
+ distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
+ &path);
+ if (distance >= 0)
+ return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
+ }
+
+ /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
+ if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
+ {
+ tree expr1;
+ /* if TYPE is `void *', return pointer to complete object. */
+ if (tc == POINTER_TYPE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
+ {
+ /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
+ if (TREE_CODE (expr) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
+ return build1 (NOP_EXPR, type, expr);
+
+ /* Since expr is used twice below, save it. */
+ expr = save_expr (expr);
+
+ expr1 = build_headof (expr);
+ if (TREE_TYPE (expr1) != type)
+ expr1 = build1 (NOP_EXPR, type, expr1);
+ return ifnonnull (expr, expr1);
+ }
+ else
+ {
+ tree retval;
+ tree result, td1, td2, td3, elems, expr2;
+
+ /* If we got here, we can't convert statically. Therefore,
+ dynamic_cast<D&>(b) (b an object) cannot succeed. */
+ if (ec == REFERENCE_TYPE)
+ {
+ if (TREE_CODE (expr) == VAR_DECL
+ && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
+ {
+ cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
+ expr, type);
+ return throw_bad_cast ();
+ }
+ }
+ /* Ditto for dynamic_cast<D*>(&b). */
+ else if (TREE_CODE (expr) == ADDR_EXPR)
+ {
+ tree op = TREE_OPERAND (expr, 0);
+ if (TREE_CODE (op) == VAR_DECL
+ && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
+ {
+ cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
+ expr, type);
+ retval = build_int_2 (0, 0);
+ TREE_TYPE (retval) = type;
+ return retval;
+ }
+ }
+
+ /* Since expr is used twice below, save it. */
+ expr = save_expr (expr);
+
+ expr1 = expr;
+ if (tc == REFERENCE_TYPE)
+ expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
+
+ /* Build run-time conversion. */
+ expr2 = build_headof (expr1);
+
+ if (ec == POINTER_TYPE)
+ td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
+ else
+ td1 = get_tinfo_fn_dynamic (expr);
+ td1 = decay_conversion (td1);
+
+ td2 = decay_conversion
+ (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));
+ td3 = decay_conversion
+ (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));
+
+ elems = tree_cons
+ (NULL_TREE, td1, tree_cons
+ (NULL_TREE, td2, tree_cons
+ (NULL_TREE, build_int_2 (1, 0), tree_cons
+ (NULL_TREE, expr2, tree_cons
+ (NULL_TREE, td3, tree_cons
+ (NULL_TREE, expr1, NULL_TREE))))));
+
+ dcast_fn = get_identifier ("__dynamic_cast");
+ if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
+ dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
+ else
+ {
+ tree tmp;
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ tmp = tree_cons
+ (NULL_TREE, TREE_TYPE (td1), tree_cons
+ (NULL_TREE, TREE_TYPE (td1), tree_cons
+ (NULL_TREE, integer_type_node, tree_cons
+ (NULL_TREE, ptr_type_node, tree_cons
+ (NULL_TREE, TREE_TYPE (td1), tree_cons
+ (NULL_TREE, ptr_type_node, void_list_node))))));
+ tmp = build_function_type (ptr_type_node, tmp);
+ dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
+ DECL_EXTERNAL (dcast_fn) = 1;
+ TREE_PUBLIC (dcast_fn) = 1;
+ DECL_ARTIFICIAL (dcast_fn) = 1;
+ pushdecl_top_level (dcast_fn);
+ make_function_rtl (dcast_fn);
+ assemble_external (dcast_fn);
+ pop_obstacks ();
+ }
+
+ result = build_call
+ (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
+
+ if (tc == REFERENCE_TYPE)
+ {
+ expr1 = throw_bad_cast ();
+ expr1 = build_compound_expr
+ (expr_tree_cons (NULL_TREE, expr1,
+ build_expr_list (NULL_TREE, cp_convert (type, integer_zero_node))));
+ TREE_TYPE (expr1) = type;
+ result = save_expr (result);
+ return build (COND_EXPR, type, result, result, expr1);
+ }
+
+ /* Now back to the type we want from a void*. */
+ result = cp_convert (type, result);
+ return ifnonnull (expr, result);
+ }
+ }
+
+ fail:
+ cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
+ expr, exprtype, type);
+ return error_mark_node;
+}
+
+tree
+build_dynamic_cast (type, expr)
+ tree type, expr;
+{
+ if (type == error_mark_node || expr == error_mark_node)
+ return error_mark_node;
+
+ if (processing_template_decl)
+ return build_min (DYNAMIC_CAST_EXPR, copy_to_permanent (type), expr);
+
+ return convert_from_reference (build_dynamic_cast_1 (type, expr));
+}
+
+/* Build and initialize various sorts of descriptors. Every descriptor
+ node has a name associated with it (the name created by mangling).
+ For this reason, we use the identifier as our access to the __*_desc
+ nodes, instead of sticking them directly in the types. Otherwise we
+ would burden all built-in types (and pointer types) with slots that
+ we don't necessarily want to use.
+
+ For each descriptor we build, we build a variable that contains
+ the descriptor's information. When we need this info at runtime,
+ all we need is access to these variables.
+
+ Note: these constructors always return the address of the descriptor
+ info, since that is simplest for their mutual interaction. */
+
+extern tree const_string_type_node;
+
+/* Build an initializer for a __si_type_info node. */
+
+static void
+expand_si_desc (tdecl, type)
+ tree tdecl;
+ tree type;
+{
+ tree t, elems, fn;
+ char *name = build_overload_name (type, 1, 1);
+ tree name_string = combine_strings (build_string (strlen (name)+1, name));
+
+ type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
+ expand_expr_stmt (get_typeid_1 (type));
+ t = decay_conversion (get_tinfo_var (type));
+ elems = tree_cons
+ (NULL_TREE, decay_conversion (tdecl), tree_cons
+ (NULL_TREE, decay_conversion (name_string), tree_cons
+ (NULL_TREE, t, NULL_TREE)));
+
+ fn = get_identifier ("__rtti_si");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ {
+ tree tmp;
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ tmp = tree_cons
+ (NULL_TREE, ptr_type_node, tree_cons
+ (NULL_TREE, const_string_type_node, tree_cons
+ (NULL_TREE, build_pointer_type (type_info_type_node),
+ void_list_node)));
+ tmp = build_function_type (void_type_node, tmp);
+
+ fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ pushdecl_top_level (fn);
+ make_function_rtl (fn);
+ assemble_external (fn);
+ pop_obstacks ();
+ }
+
+ fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
+ expand_expr_stmt (fn);
+}
+
+/* Build an initializer for a __class_type_info node. */
+
+static void
+expand_class_desc (tdecl, type)
+ tree tdecl;
+ tree type;
+{
+ tree name_string;
+ tree fn, tmp;
+ char *name;
+
+ int i = CLASSTYPE_N_BASECLASSES (type);
+ int base_cnt = 0;
+ tree binfos = TYPE_BINFO_BASETYPES (type);
+#if 0
+ /* See code below that used these. */
+ tree vb = CLASSTYPE_VBASECLASSES (type);
+ int n_base = i;
+#endif
+ tree base, elems, access, offset, isvir;
+ tree elt, elts = NULL_TREE;
+ static tree base_info_type_node;
+
+ if (base_info_type_node == NULL_TREE)
+ {
+ tree fields [4];
+
+ /* A reasonably close approximation of __class_type_info::base_info */
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ base_info_type_node = make_lang_type (RECORD_TYPE);
+
+ /* Actually const __user_type_info * */
+ fields [0] = build_lang_field_decl
+ (FIELD_DECL, NULL_TREE,
+ build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
+ fields [1] = build_lang_field_decl
+ (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
+ DECL_BIT_FIELD (fields[1]) = 1;
+ DECL_FIELD_SIZE (fields[1]) = 29;
+
+ fields [2] = build_lang_field_decl
+ (FIELD_DECL, NULL_TREE, boolean_type_node);
+ DECL_BIT_FIELD (fields[2]) = 1;
+ DECL_FIELD_SIZE (fields[2]) = 1;
+
+ /* Actually enum access */
+ fields [3] = build_lang_field_decl
+ (FIELD_DECL, NULL_TREE, integer_type_node);
+ DECL_BIT_FIELD (fields[3]) = 1;
+ DECL_FIELD_SIZE (fields[3]) = 2;
+
+ finish_builtin_type (base_info_type_node, "__base_info", fields,
+ 3, ptr_type_node);
+ pop_obstacks ();
+ }
+
+ while (--i >= 0)
+ {
+ tree binfo = TREE_VEC_ELT (binfos, i);
+
+ expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
+ base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
+
+ if (TREE_VIA_VIRTUAL (binfo))
+ {
+ tree t = BINFO_TYPE (binfo);
+ char *name;
+ tree field;
+
+ name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
+ sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
+ field = lookup_field (type, get_identifier (name), 0, 0);
+ offset = size_binop (FLOOR_DIV_EXPR,
+ DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
+ offset = convert (sizetype, offset);
+ }
+ else
+ offset = BINFO_OFFSET (binfo);
+
+ if (TREE_VIA_PUBLIC (binfo))
+ access = access_public_node;
+ else if (TREE_VIA_PROTECTED (binfo))
+ access = access_protected_node;
+ else
+ access = access_private_node;
+ if (TREE_VIA_VIRTUAL (binfo))
+ isvir = boolean_true_node;
+ else
+ isvir = boolean_false_node;
+
+ elt = build
+ (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
+ (NULL_TREE, base, tree_cons
+ (NULL_TREE, offset, tree_cons
+ (NULL_TREE, isvir, tree_cons
+ (NULL_TREE, access, NULL_TREE)))));
+ TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
+ elts = expr_tree_cons (NULL_TREE, elt, elts);
+ base_cnt++;
+ }
+#if 0
+ i = n_base;
+ while (vb)
+ {
+ tree b;
+ access = access_public_node;
+ while (--i >= 0)
+ {
+ b = TREE_VEC_ELT (binfos, i);
+ if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
+ {
+ if (TREE_VIA_PUBLIC (b))
+ access = access_public_node;
+ else if (TREE_VIA_PROTECTED (b))
+ access = access_protected_node;
+ else
+ access = access_private_node;
+ break;
+ }
+ }
+ base = build_t_desc (BINFO_TYPE (vb), 1);
+ offset = BINFO_OFFSET (vb);
+ isvir = build_int_2 (1, 0);
+
+ base_list = expr_tree_cons (NULL_TREE, base, base_list);
+ isvir_list = expr_tree_cons (NULL_TREE, isvir, isvir_list);
+ acc_list = expr_tree_cons (NULL_TREE, access, acc_list);
+ off_list = expr_tree_cons (NULL_TREE, offset, off_list);
+
+ base_cnt++;
+ vb = TREE_CHAIN (vb);
+ }
+#endif
+
+ name = build_overload_name (type, 1, 1);
+ name_string = combine_strings (build_string (strlen (name)+1, name));
+
+ {
+ tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
+ elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
+ TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
+ = TREE_STATIC (elts) = 1;
+ complete_array_type (arrtype, elts, 1);
+ }
+
+ elems = tree_cons
+ (NULL_TREE, decay_conversion (tdecl), tree_cons
+ (NULL_TREE, decay_conversion (name_string), tree_cons
+ (NULL_TREE, decay_conversion (elts), tree_cons
+ (NULL_TREE, cp_convert (sizetype, build_int_2 (base_cnt, 0)),
+ NULL_TREE))));
+
+ fn = get_identifier ("__rtti_class");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ {
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ tmp = tree_cons
+ (NULL_TREE, ptr_type_node, tree_cons
+ (NULL_TREE, const_string_type_node, tree_cons
+ (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
+ (NULL_TREE, sizetype, void_list_node))));
+ tmp = build_function_type (void_type_node, tmp);
+
+ fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ pushdecl_top_level (fn);
+ make_function_rtl (fn);
+ assemble_external (fn);
+ pop_obstacks ();
+ }
+
+ fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
+ expand_expr_stmt (fn);
+}
+
+/* Build an initializer for a __pointer_type_info node. */
+
+static void
+expand_ptr_desc (tdecl, type)
+ tree tdecl;
+ tree type;
+{
+ tree t, elems, fn;
+ char *name = build_overload_name (type, 1, 1);
+ tree name_string = combine_strings (build_string (strlen (name)+1, name));
+
+ type = TREE_TYPE (type);
+ expand_expr_stmt (get_typeid_1 (type));
+ t = decay_conversion (get_tinfo_var (type));
+ elems = tree_cons
+ (NULL_TREE, decay_conversion (tdecl), tree_cons
+ (NULL_TREE, decay_conversion (name_string), tree_cons
+ (NULL_TREE, t, NULL_TREE)));
+
+ fn = get_identifier ("__rtti_ptr");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ {
+ tree tmp;
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ tmp = tree_cons
+ (NULL_TREE, ptr_type_node, tree_cons
+ (NULL_TREE, const_string_type_node, tree_cons
+ (NULL_TREE, build_pointer_type (type_info_type_node),
+ void_list_node)));
+ tmp = build_function_type (void_type_node, tmp);
+
+ fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ pushdecl_top_level (fn);
+ make_function_rtl (fn);
+ assemble_external (fn);
+ pop_obstacks ();
+ }
+
+ fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
+ expand_expr_stmt (fn);
+}
+
+/* Build an initializer for a __attr_type_info node. */
+
+static void
+expand_attr_desc (tdecl, type)
+ tree tdecl;
+ tree type;
+{
+ tree elems, t, fn;
+ char *name = build_overload_name (type, 1, 1);
+ tree name_string = combine_strings (build_string (strlen (name)+1, name));
+ tree attrval = build_int_2
+ (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
+
+ expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
+ t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
+ elems = tree_cons
+ (NULL_TREE, decay_conversion (tdecl), tree_cons
+ (NULL_TREE, decay_conversion (name_string), tree_cons
+ (NULL_TREE, attrval, expr_tree_cons (NULL_TREE, t, NULL_TREE))));
+
+ fn = get_identifier ("__rtti_attr");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ {
+ tree tmp;
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ tmp = tree_cons
+ (NULL_TREE, ptr_type_node, tree_cons
+ (NULL_TREE, const_string_type_node, tree_cons
+ (NULL_TREE, integer_type_node, tree_cons
+ (NULL_TREE, build_pointer_type (type_info_type_node),
+ void_list_node))));
+ tmp = build_function_type (void_type_node, tmp);
+
+ fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ pushdecl_top_level (fn);
+ make_function_rtl (fn);
+ assemble_external (fn);
+ pop_obstacks ();
+ }
+
+ fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
+ expand_expr_stmt (fn);
+}
+
+/* Build an initializer for a type_info node that just has a name. */
+
+static void
+expand_generic_desc (tdecl, type, fnname)
+ tree tdecl;
+ tree type;
+ char *fnname;
+{
+ char *name = build_overload_name (type, 1, 1);
+ tree name_string = combine_strings (build_string (strlen (name)+1, name));
+ tree elems = tree_cons
+ (NULL_TREE, decay_conversion (tdecl), tree_cons
+ (NULL_TREE, decay_conversion (name_string), NULL_TREE));
+
+ tree fn = get_identifier (fnname);
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ {
+ tree tmp;
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ tmp = tree_cons
+ (NULL_TREE, ptr_type_node, tree_cons
+ (NULL_TREE, const_string_type_node, void_list_node));
+ tmp = build_function_type (void_type_node, tmp);
+
+ fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ pushdecl_top_level (fn);
+ make_function_rtl (fn);
+ assemble_external (fn);
+ pop_obstacks ();
+ }
+
+ fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
+ expand_expr_stmt (fn);
+}
+
+/* Generate the code for a type_info initialization function.
+ Note that we take advantage of the passage
+
+ 5.2.7 Type identification [expr.typeid]
+
+ Whether or not the destructor is called for the type_info object at the
+ end of the program is unspecified.
+
+ and don't bother to arrange for these objects to be destroyed. It
+ doesn't matter, anyway, since the destructors don't do anything.
+
+ This must only be called from toplevel (i.e. from finish_file)! */
+
+void
+synthesize_tinfo_fn (fndecl)
+ tree fndecl;
+{
+ tree type = TREE_TYPE (DECL_NAME (fndecl));
+ tree tmp, addr, tdecl;
+
+ if (at_eof)
+ {
+ import_export_decl (fndecl);
+ if (DECL_REALLY_EXTERN (fndecl))
+ return;
+ }
+
+ tdecl = get_tinfo_var (type);
+ DECL_EXTERNAL (tdecl) = 0;
+ TREE_STATIC (tdecl) = 1;
+ DECL_COMMON (tdecl) = 1;
+ TREE_USED (tdecl) = 1;
+ DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
+ cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
+
+ start_function (NULL_TREE, fndecl, NULL_TREE, 1);
+ store_parm_decls ();
+ clear_last_expr ();
+ push_momentary ();
+
+ /* If the first word of the array (the vtable) is non-zero, we've already
+ initialized the object, so don't do it again. */
+ addr = decay_conversion (tdecl);
+ tmp = cp_convert (build_pointer_type (ptr_type_node), addr);
+ tmp = build_indirect_ref (tmp, 0);
+ tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
+ expand_start_cond (tmp, 0);
+
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ expand_generic_desc (tdecl, type, "__rtti_func");
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ expand_generic_desc (tdecl, type, "__rtti_array");
+ else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
+ expand_attr_desc (tdecl, type);
+ else if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
+ expand_generic_desc (tdecl, type, "__rtti_ptmd");
+ else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
+ expand_generic_desc (tdecl, type, "__rtti_ptmf");
+ else
+ expand_ptr_desc (tdecl, type);
+ }
+ else if (TYPE_PTRMEMFUNC_P (type))
+ expand_generic_desc (tdecl, type, "__rtti_ptmf");
+ else if (IS_AGGR_TYPE (type))
+ {
+ if (CLASSTYPE_N_BASECLASSES (type) == 0)
+ expand_generic_desc (tdecl, type, "__rtti_user");
+ else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
+ && (TREE_VIA_PUBLIC
+ (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
+ expand_si_desc (tdecl, type);
+ else
+ expand_class_desc (tdecl, type);
+ }
+ else if (TREE_CODE (type) == ENUMERAL_TYPE)
+ expand_generic_desc (tdecl, type, "__rtti_user");
+ else
+ my_friendly_abort (252);
+
+ expand_end_cond ();
+
+ /* OK, now return the type_info object. */
+ tmp = cp_convert (build_pointer_type (type_info_type_node), addr);
+ tmp = build_indirect_ref (tmp, 0);
+ c_expand_return (tmp);
+ finish_function (lineno, 0, 0);
+}
diff --git a/contrib/gcc/cp/search.c b/contrib/gcc/cp/search.c
index 0ac50a1..d5971e0 100644
--- a/contrib/gcc/cp/search.c
+++ b/contrib/gcc/cp/search.c
@@ -1,6 +1,6 @@
/* Breadth-first and depth-first routines for
searching multiple-inheritance lattice for GNU C++.
- Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-96, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -20,30 +20,32 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* High-level class interface. */
+/* High-level class interface. */
#include "config.h"
+#include "system.h"
#include "tree.h"
-#include <stdio.h>
#include "cp-tree.h"
#include "obstack.h"
#include "flags.h"
#include "rtl.h"
#include "output.h"
+#include "toplev.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-void init_search ();
extern struct obstack *current_obstack;
extern tree abort_fndecl;
#include "stack.h"
/* Obstack used for remembering decision points of breadth-first. */
+
static struct obstack search_obstack;
/* Methods for pushing and popping objects to and from obstacks. */
+
struct stack_level *
push_stack_level (obstack, tp, size)
struct obstack *obstack;
@@ -74,19 +76,83 @@ pop_stack_level (stack)
#define search_level stack_level
static struct search_level *search_stack;
-static tree lookup_field_1 ();
-static int lookup_fnfields_1 ();
-static void dfs_walk ();
-static int markedp ();
-static void dfs_unmark ();
-static void dfs_init_vbase_pointers ();
+static void clear_memoized_cache PROTO((void));
+static tree make_memoized_table_entry PROTO((tree, tree, int));
+static tree get_abstract_virtuals_1 PROTO((tree, int, tree));
+static tree get_vbase_1 PROTO((tree, tree, unsigned int *));
+static tree convert_pointer_to_vbase PROTO((tree, tree));
+static tree lookup_field_1 PROTO((tree, tree));
+static tree convert_pointer_to_single_level PROTO((tree, tree));
+static int lookup_fnfields_1 PROTO((tree, tree));
+static int lookup_fnfields_here PROTO((tree, tree));
+static int is_subobject_of_p PROTO((tree, tree));
+static int hides PROTO((tree, tree));
+static tree virtual_context PROTO((tree, tree, tree));
+static tree get_template_base_recursive
+ PROTO((tree, tree, tree, int));
+static void dfs_walk PROTO((tree, void (*) (tree), int (*) (tree)));
+static void dfs_check_overlap PROTO((tree));
+static int dfs_no_overlap_yet PROTO((tree));
+static void envelope_add_decl PROTO((tree, tree, tree *));
+static int get_base_distance_recursive
+ PROTO((tree, int, int, int, int *, tree *, tree, tree *,
+ int, int *, int, int));
+static void expand_upcast_fixups
+ PROTO((tree, tree, tree, tree, tree, tree, tree *));
+static void fixup_virtual_upcast_offsets
+ PROTO((tree, tree, int, int, tree, tree, tree, tree,
+ tree *));
+static int markedp PROTO((tree));
+static int unmarkedp PROTO((tree));
+#ifdef MI_MATRIX
+static int numberedp PROTO((tree));
+static int unnumberedp PROTO((tree));
+#endif
+static int marked_vtable_pathp PROTO((tree));
+static int unmarked_vtable_pathp PROTO((tree));
+static int marked_new_vtablep PROTO((tree));
+static int unmarked_new_vtablep PROTO((tree));
+static int dfs_debug_unmarkedp PROTO((tree));
+#ifdef MI_MATRIX
+static void dfs_number PROTO((tree));
+static void dfs_unnumber PROTO((tree));
+static void dfs_record_inheritance PROTO((tree));
+#endif
+static void dfs_debug_mark PROTO((tree));
+static void dfs_find_vbases PROTO((tree));
+static void dfs_clear_vbase_slots PROTO((tree));
+static void dfs_unmark PROTO((tree));
+static void dfs_init_vbase_pointers PROTO((tree));
+static void dfs_get_vbase_types PROTO((tree));
+static void dfs_pushdecls PROTO((tree));
+static void dfs_compress_decls PROTO((tree));
+static void dfs_unuse_fields PROTO((tree));
+static void add_conversions PROTO((tree));
+static tree get_virtuals_named_this PROTO((tree));
+static tree get_virtual_destructor PROTO((tree, int));
+static int tree_has_any_destructor_p PROTO((tree, int));
+static int covariant_return_p PROTO((tree, tree));
+static struct search_level *push_search_level
+ PROTO((struct stack_level *, struct obstack *));
+static struct search_level *pop_search_level
+ PROTO((struct stack_level *));
+static struct type_level *push_type_level
+ PROTO((struct stack_level *, struct obstack *));
+static struct type_level *pop_type_level
+ PROTO((struct type_level *));
+static tree my_tree_cons PROTO((tree, tree, tree));
+static tree my_build_string PROTO((char *));
+static struct memoized_entry * my_new_memoized_entry
+ PROTO((struct memoized_entry *));
+static HOST_WIDE_INT breadth_first_search
+ PROTO((tree, int (*) (tree, int), int (*) (tree, int)));
static tree vbase_types;
-static tree vbase_decl, vbase_decl_ptr;
-static tree vbase_decl_ptr_intermediate;
+static tree vbase_decl_ptr_intermediate, vbase_decl_ptr;
static tree vbase_init_result;
/* Allocate a level of searching. */
+
static struct search_level *
push_search_level (stack, obstack)
struct stack_level *stack;
@@ -99,6 +165,7 @@ push_search_level (stack, obstack)
}
/* Discard a level of search allocation. */
+
static struct search_level *
pop_search_level (obstack)
struct stack_level *obstack;
@@ -109,6 +176,7 @@ pop_search_level (obstack)
}
/* Search memoization. */
+
struct type_level
{
struct stack_level base;
@@ -133,7 +201,6 @@ static tree _vptr_name;
/* Make things that look like tree nodes, but allocate them
on type_obstack_entries. */
static int my_tree_node_counter;
-static tree my_tree_cons (), my_build_string ();
extern int flag_memoize_lookups, flag_save_memoized_contexts;
@@ -141,12 +208,14 @@ extern int flag_memoize_lookups, flag_save_memoized_contexts;
static int my_memoized_entry_counter;
static int memoized_fast_finds[2], memoized_adds[2], memoized_fast_rejects[2];
static int memoized_fields_searched[2];
+#ifdef GATHER_STATISTICS
static int n_fields_searched;
static int n_calls_lookup_field, n_calls_lookup_field_1;
static int n_calls_lookup_fnfields, n_calls_lookup_fnfields_1;
static int n_calls_get_base_type;
static int n_outer_fields_searched;
static int n_contexts_saved;
+#endif /* GATHER_STATISTICS */
/* Local variables to help save memoization contexts. */
static tree prev_type_memoized;
@@ -157,6 +226,7 @@ static struct type_level *prev_type_stack;
static tree closed_envelopes = NULL_TREE;
/* Allocate a level of type memoization context. */
+
static struct type_level *
push_type_level (stack, obstack)
struct stack_level *stack;
@@ -186,18 +256,17 @@ pop_type_level (stack)
/* Make something that looks like a TREE_LIST, but
do it on the type_obstack_entries obstack. */
+
static tree
my_tree_cons (purpose, value, chain)
tree purpose, value, chain;
{
- tree p = (tree)obstack_alloc (&type_obstack_entries, sizeof (struct tree_list));
+ tree p;
+ struct obstack *ambient_obstack = current_obstack;
+ current_obstack = &type_obstack_entries;
+ p = tree_cons (purpose, value, chain);
+ current_obstack = ambient_obstack;
++my_tree_node_counter;
- TREE_TYPE (p) = NULL_TREE;
- ((HOST_WIDE_INT *)p)[3] = 0;
- TREE_SET_CODE (p, TREE_LIST);
- TREE_PURPOSE (p) = purpose;
- TREE_VALUE (p) = value;
- TREE_CHAIN (p) = chain;
return p;
}
@@ -217,6 +286,7 @@ my_build_string (str)
/* Memoizing machinery to make searches for multiple inheritance
reasonably efficient. */
+
#define MEMOIZE_HASHSIZE 8
typedef struct memoized_entry
{
@@ -237,26 +307,43 @@ static struct memoized_entry *
my_new_memoized_entry (chain)
struct memoized_entry *chain;
{
- struct memoized_entry *p =
- (struct memoized_entry *)obstack_alloc (&type_obstack_entries,
- sizeof (struct memoized_entry));
+ struct memoized_entry *p
+ = (struct memoized_entry *)obstack_alloc (&type_obstack_entries,
+ sizeof (struct memoized_entry));
bzero ((char *) p, sizeof (struct memoized_entry));
MEMOIZED_CHAIN (p) = chain;
MEMOIZED_UID (p) = ++my_memoized_entry_counter;
return p;
}
+/* Clears the deferred pop from pop_memoized_context, if any. */
+
+static void
+clear_memoized_cache ()
+{
+ if (prev_type_stack)
+ {
+ type_stack = pop_type_level (prev_type_stack);
+ prev_type_memoized = 0;
+ prev_type_stack = 0;
+ }
+}
+
/* Make an entry in the memoized table for type TYPE
that the entry for NAME is FIELD. */
-tree
+static tree
make_memoized_table_entry (type, name, function_p)
tree type, name;
int function_p;
{
- int index = MEMOIZED_HASH_FN (name);
+ int idx = MEMOIZED_HASH_FN (name);
tree entry, *prev_entry;
+ /* Since we allocate from the type_obstack, we must pop any deferred
+ levels. */
+ clear_memoized_cache ();
+
memoized_adds[function_p] += 1;
if (CLASSTYPE_MTABLE_ENTRY (type) == 0)
{
@@ -268,9 +355,9 @@ make_memoized_table_entry (type, name, function_p)
my_friendly_abort (88);
}
if (function_p)
- prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
else
- prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
entry = my_tree_cons (name, NULL_TREE, *prev_entry);
*prev_entry = entry;
@@ -309,6 +396,7 @@ make_memoized_table_entry (type, name, function_p)
be NULL_TREE if we are not in a class's scope.
USE_OLD, if nonzero tries to use previous context. */
+
void
push_memoized_context (type, use_old)
tree type;
@@ -323,7 +411,7 @@ push_memoized_context (type, use_old)
{
#ifdef GATHER_STATISTICS
n_contexts_saved++;
-#endif
+#endif /* GATHER_STATISTICS */
type_stack = prev_type_stack;
prev_type_stack = 0;
@@ -334,9 +422,7 @@ push_memoized_context (type, use_old)
return;
}
/* Otherwise, need to pop old stack here. */
- type_stack = pop_type_level (prev_type_stack);
- prev_type_memoized = 0;
- prev_type_stack = 0;
+ clear_memoized_cache ();
}
type_stack = push_type_level ((struct stack_level *)type_stack,
@@ -349,6 +435,7 @@ push_memoized_context (type, use_old)
If we wanted to, we could not use pop_search_level, since
poping that level allows the data we have collected to
be clobbered; a stack of obstacks would be needed. */
+
void
pop_memoized_context (use_old)
int use_old;
@@ -364,6 +451,9 @@ pop_memoized_context (use_old)
while (len--)
tem[len*2+1] = (tree)CLASSTYPE_MTABLE_ENTRY (tem[len*2]);
+ /* If there was a deferred pop, we need to pop it now. */
+ clear_memoized_cache ();
+
prev_type_stack = type_stack;
prev_type_memoized = type_stack->type;
}
@@ -384,9 +474,10 @@ pop_memoized_context (use_old)
/* Get a virtual binfo that is found inside BINFO's hierarchy that is
the same type as the type given in PARENT. To be optimal, we want
the first one that is found by going through the least number of
- virtual bases. DEPTH should be NULL_PTR. */
+ virtual bases. */
+
static tree
-get_vbase (parent, binfo, depth)
+get_vbase_1 (parent, binfo, depth)
tree parent, binfo;
unsigned int *depth;
{
@@ -394,12 +485,6 @@ get_vbase (parent, binfo, depth)
int i, n_baselinks;
tree rval = NULL_TREE;
- if (depth == 0)
- {
- unsigned int d = (unsigned int)-1;
- return get_vbase (parent, binfo, &d);
- }
-
if (BINFO_TYPE (binfo) == parent && TREE_VIA_VIRTUAL (binfo))
{
*depth = 0;
@@ -420,7 +505,7 @@ get_vbase (parent, binfo, depth)
if (*depth == 0)
break;
- nrval = get_vbase (parent, base_binfo, depth);
+ nrval = get_vbase_1 (parent, base_binfo, depth);
if (nrval)
rval = nrval;
}
@@ -428,46 +513,28 @@ get_vbase (parent, binfo, depth)
return rval;
}
+tree
+get_vbase (parent, binfo)
+ tree parent;
+ tree binfo;
+{
+ unsigned int d = (unsigned int)-1;
+ return get_vbase_1 (parent, binfo, &d);
+}
+
/* 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
+
+static 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);
+ tree vb = get_vbase (type, TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr))));
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
- we mean it's only one step up the inheritance lattice. We check this
- by walking horizontally across the types that TYPE directly inherits
- from, to see if PARENT is among them. This is used by get_binfo and
- by compute_access. */
-static int
-immediately_derived (parent, type)
- tree parent, type;
-{
- if (TYPE_BINFO (type))
- {
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (parent == BINFO_TYPE (base_binfo))
- return 1;
- }
- }
- return 0;
-}
-#endif
-
/* Check whether the type given in BINFO is derived from PARENT. If
it isn't, return 0. If it is, but the derivation is MI-ambiguous
AND protect != 0, emit an error message and return error_mark_node.
@@ -484,7 +551,7 @@ get_binfo (parent, binfo, protect)
register tree parent, binfo;
int protect;
{
- tree type;
+ tree type = NULL_TREE;
int dist;
tree rval = NULL_TREE;
@@ -519,17 +586,27 @@ get_binfo (parent, binfo, protect)
}
/* This is the newer depth first get_base_distance routine. */
+
static int
-get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
+get_base_distance_recursive (binfo, depth, is_private, rval,
rval_private_ptr, new_binfo_ptr, parent, path_ptr,
- protect, via_virtual_ptr, via_virtual)
- tree binfo, basetype_path, *new_binfo_ptr, parent, *path_ptr;
- int *rval_private_ptr, depth, is_private, rval, protect, *via_virtual_ptr,
- via_virtual;
+ protect, via_virtual_ptr, via_virtual,
+ current_scope_in_chain)
+ tree binfo;
+ int depth, is_private, rval;
+ int *rval_private_ptr;
+ tree *new_binfo_ptr, parent, *path_ptr;
+ int protect, *via_virtual_ptr, via_virtual;
+ int current_scope_in_chain;
{
tree binfos;
int i, n_baselinks;
+ if (protect
+ && !current_scope_in_chain
+ && is_friend (BINFO_TYPE (binfo), current_scope ()))
+ current_scope_in_chain = 1;
+
if (BINFO_TYPE (binfo) == parent || binfo == parent)
{
if (rval == -1)
@@ -577,19 +654,21 @@ get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
tree base_binfo = TREE_VEC_ELT (binfos, i);
/* Find any specific instance of a virtual base, when searching with
- a binfo... */
+ a binfo... */
if (BINFO_MARKED (base_binfo) == 0 || TREE_CODE (parent) == TREE_VEC)
{
int via_private
= (protect
&& (is_private
|| (!TREE_VIA_PUBLIC (base_binfo)
+ && !(TREE_VIA_PROTECTED (base_binfo)
+ && current_scope_in_chain)
&& !is_friend (BINFO_TYPE (binfo), current_scope ()))));
int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
int was;
/* When searching for a non-virtual, we cannot mark
- virtually found binfos. */
+ virtually found binfos. */
if (! this_virtual)
SET_BINFO_MARKED (base_binfo);
@@ -597,11 +676,12 @@ get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
was = WATCH_VALUES (rval, *via_virtual_ptr);
rval = get_base_distance_recursive (base_binfo, depth, via_private,
- binfo, rval, rval_private_ptr,
+ rval, rval_private_ptr,
new_binfo_ptr, parent, path_ptr,
protect, via_virtual_ptr,
- this_virtual);
- /* watch for updates; only update if path is good. */
+ this_virtual,
+ current_scope_in_chain);
+ /* watch for updates; only update if path is good. */
if (path_ptr && WATCH_VALUES (rval, *via_virtual_ptr) != was)
BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
if (rval == -2 && *via_virtual_ptr == 0)
@@ -642,19 +722,22 @@ get_base_distance (parent, binfo, protect, path_ptr)
{
int rval;
int rval_private = 0;
- tree type;
+ tree type = NULL_TREE;
tree new_binfo = NULL_TREE;
int via_virtual;
int watch_access = protect;
+ /* Should we be completing types here? */
if (TREE_CODE (parent) != TREE_VEC)
- parent = TYPE_MAIN_VARIANT (parent);
+ parent = complete_type (TYPE_MAIN_VARIANT (parent));
+ else
+ complete_type (TREE_TYPE (parent));
if (TREE_CODE (binfo) == TREE_VEC)
type = BINFO_TYPE (binfo);
else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo)))
{
- type = binfo;
+ type = complete_type (binfo);
binfo = TYPE_BINFO (type);
if (path_ptr)
@@ -675,9 +758,10 @@ get_base_distance (parent, binfo, protect, path_ptr)
if (path_ptr)
watch_access = 1;
- rval = get_base_distance_recursive (binfo, 0, 0, NULL_TREE, -1,
+ rval = get_base_distance_recursive (binfo, 0, 0, -1,
&rval_private, &new_binfo, parent,
- path_ptr, watch_access, &via_virtual, 0);
+ path_ptr, watch_access, &via_virtual, 0,
+ 0);
dfs_walk (binfo, dfs_unmark, markedp);
@@ -688,7 +772,7 @@ get_base_distance (parent, binfo, protect, path_ptr)
if (rval && protect && rval_private)
return -3;
- /* find real virtual base classes. */
+ /* find real virtual base classes. */
if (rval == -1 && TREE_CODE (parent) == TREE_VEC
&& parent == binfo_member (BINFO_TYPE (parent),
CLASSTYPE_VBASECLASSES (type)))
@@ -711,20 +795,32 @@ get_base_distance (parent, binfo, protect, path_ptr)
/* Do a 1-level search for NAME as a member of TYPE. The caller must
figure out whether it can access this field. (Since it is only one
level, this is reasonable.) */
+
static tree
lookup_field_1 (type, name)
tree type, name;
{
- register tree field = TYPE_FIELDS (type);
+ register tree field;
+
+ if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
+ /* The TYPE_FIELDS of a TEMPLATE_TYPE_PARM are not fields at all;
+ instead TYPE_FIELDS is the TEMPLATE_PARM_INDEX. (Miraculously,
+ the code often worked even when we treated the index as a list
+ of fields!) */
+ return NULL_TREE;
+
+ field = TYPE_FIELDS (type);
#ifdef GATHER_STATISTICS
n_calls_lookup_field_1++;
-#endif
+#endif /* GATHER_STATISTICS */
while (field)
{
#ifdef GATHER_STATISTICS
n_fields_searched++;
-#endif
+#endif /* GATHER_STATISTICS */
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (field)) == 'd', 0);
if (DECL_NAME (field) == NULL_TREE
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
@@ -754,17 +850,17 @@ lookup_field_1 (type, name)
/* There are a number of cases we need to be aware of here:
current_class_type current_function_decl
- * global NULL NULL
- * fn-local NULL SET
- * class-local SET NULL
- * class->fn SET SET
- * fn->class SET SET
+ global NULL NULL
+ fn-local NULL SET
+ class-local SET NULL
+ class->fn SET SET
+ fn->class SET SET
Those last two make life interesting. If we're in a function which is
itself inside a class, we need decls to go into the fn's decls (our
second case below). But if we're in a class and the class itself is
inside a function, we need decls to go into the decls for the class. To
- achieve this last goal, we must see if, when both current_class_decl and
+ achieve this last goal, we must see if, when both current_class_ptr and
current_function_decl are set, the class was declared inside that
function. If so, we know to put the decls into the class's scope. */
@@ -794,23 +890,23 @@ current_scope ()
This will be static when lookup_fnfield comes into this file.
- access_public means that the field can be accessed by the current lexical
+ access_public_node means that the field can be accessed by the current lexical
scope.
- access_protected means that the field cannot be accessed by the current
+ access_protected_node means that the field cannot be accessed by the current
lexical scope because it is protected.
- access_private means that the field cannot be accessed by the current
- lexical scope because it is private. */
+ access_private_node means that the field cannot be accessed by the current
+ lexical scope because it is private. */
#if 0
-#define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), access_public
-#define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), access_protected
-#define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), access_private
+#define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), access_public_node
+#define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), access_protected_node
+#define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), access_private_node
#else
-#define PUBLIC_RETURN return access_public
-#define PROTECTED_RETURN return access_protected
-#define PRIVATE_RETURN return access_private
+#define PUBLIC_RETURN return access_public_node
+#define PROTECTED_RETURN return access_protected_node
+#define PRIVATE_RETURN return access_private_node
#endif
#if 0
@@ -818,11 +914,11 @@ current_scope ()
static tree previous_scope = NULL_TREE;
#endif
-enum access_type
+tree
compute_access (basetype_path, field)
tree basetype_path, field;
{
- enum access_type access;
+ tree access;
tree types;
tree context;
int protected_ok, via_protected;
@@ -831,16 +927,16 @@ compute_access (basetype_path, field)
/* Replaces static decl above. */
tree previous_scope;
#endif
- int static_mem =
- ((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field))
- || (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field)));
+ int static_mem
+ = ((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field))
+ || (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field)));
if (! flag_access_control)
- return access_public;
+ return access_public_node;
/* The field lives in the current class. */
if (BINFO_TYPE (basetype_path) == current_class_type)
- return access_public;
+ return access_public_node;
#if 0
/* Disabled until pushing function scope clears these out. If ever. */
@@ -848,30 +944,28 @@ compute_access (basetype_path, field)
if (current_scope () == previous_scope)
{
if (DECL_PUBLIC (field))
- return access_public;
+ return access_public_node;
if (DECL_PROTECTED (field))
- return access_protected;
+ return access_protected_node;
if (DECL_PRIVATE (field))
- return access_private;
+ return access_private_node;
}
#endif
/* We don't currently support access control on nested types. */
if (TREE_CODE (field) == TYPE_DECL)
- return access_public;
+ return access_public_node;
previous_scope = current_scope ();
-
- context = DECL_CLASS_CONTEXT (field);
- if (context == NULL_TREE)
- context = DECL_CONTEXT (field);
+
+ context = DECL_REAL_CONTEXT (field);
/* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT
slot set to the union type rather than the record type containing
- the anonymous union. In this case, DECL_FIELD_CONTEXT is correct. */
- if (context && TREE_CODE (context) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
- context = DECL_FIELD_CONTEXT (field);
+ the anonymous union. */
+ if (context && ANON_UNION_TYPE_P (context)
+ && TREE_CODE (field) == FIELD_DECL)
+ context = TYPE_CONTEXT (context);
/* Virtual function tables are never private. But we should know that
we are looking for this, and not even try to hide it. */
@@ -898,8 +992,8 @@ compute_access (basetype_path, field)
else if (TREE_PROTECTED (field))
{
if (current_class_type
- && static_mem
- && ACCESSIBLY_DERIVED_FROM_P (context, current_class_type))
+ && (static_mem || DECL_CONSTRUCTOR_P (field))
+ && ACCESSIBLY_DERIVED_FROM_P (context, current_class_type))
PUBLIC_RETURN;
else
PROTECTED_RETURN;
@@ -912,7 +1006,7 @@ compute_access (basetype_path, field)
basetype_path = reverse_path (basetype_path);
types = basetype_path;
via_protected = 0;
- access = access_default;
+ access = access_default_node;
protected_ok = static_mem && current_class_type
&& ACCESSIBLY_DERIVED_FROM_P (BINFO_TYPE (types), current_class_type);
@@ -934,7 +1028,7 @@ compute_access (basetype_path, field)
member = purpose_member (type, DECL_ACCESS (field));
if (member)
{
- access = (enum access_type) TREE_VALUE (member);
+ access = TREE_VALUE (member);
break;
}
@@ -948,7 +1042,7 @@ compute_access (basetype_path, field)
via_protected = 1;
else if (! TREE_VIA_PUBLIC (types) && ! private_ok)
{
- access = access_private;
+ access = access_private_node;
break;
}
}
@@ -959,30 +1053,30 @@ compute_access (basetype_path, field)
/* No special visibilities apply. Use normal rules. */
- if (access == access_default)
+ if (access == access_default_node)
{
if (is_friend (context, previous_scope))
- access = access_public;
+ access = access_public_node;
else if (TREE_PRIVATE (field))
- access = access_private;
+ access = access_private_node;
else if (TREE_PROTECTED (field))
- access = access_protected;
+ access = access_protected_node;
else
- access = access_public;
+ access = access_public_node;
}
- if (access == access_public && via_protected)
- access = access_protected;
+ if (access == access_public_node && via_protected)
+ access = access_protected_node;
- if (access == access_protected && protected_ok)
- access = access_public;
+ if (access == access_protected_node && protected_ok)
+ access = access_public_node;
#if 0
- if (access == access_public)
+ if (access == access_public_node)
DECL_PUBLIC (field) = 1;
- else if (access == access_protected)
+ else if (access == access_protected_node)
DECL_PROTECTED (field) = 1;
- else if (access == access_private)
+ else if (access == access_private_node)
DECL_PRIVATE (field) = 1;
else my_friendly_abort (96);
#endif
@@ -993,6 +1087,7 @@ compute_access (basetype_path, field)
found as a base class and sub-object of the object denoted by
BINFO. This routine relies upon binfos not being shared, except
for binfos for virtual bases. */
+
static int
is_subobject_of_p (parent, binfo)
tree parent, binfo;
@@ -1019,7 +1114,8 @@ is_subobject_of_p (parent, binfo)
correspond to ANSI working paper Sept 17, 1992 10p4. The two
binfos given are the binfos corresponding to the particular places
the FIELD_DECLs are found. This routine relies upon binfos not
- being shared, except for virtual bases. */
+ being shared, except for virtual bases. */
+
static int
hides (hider_binfo, hidee_binfo)
tree hider_binfo, hidee_binfo;
@@ -1029,29 +1125,31 @@ hides (hider_binfo, hidee_binfo)
part is always true is the second part is true.
When hider and hidee are the same (two ways to get to the exact
- same member) we consider either one as hiding the other. */
+ same member) we consider either one as hiding the other. */
return is_subobject_of_p (hidee_binfo, hider_binfo);
}
/* Very similar to lookup_fnfields_1 but it ensures that at least one
function was declared inside the class given by TYPE. It really should
only return functions that match the given TYPE. */
+
static int
lookup_fnfields_here (type, name)
tree type, name;
{
- int index = lookup_fnfields_1 (type, name);
+ int idx = lookup_fnfields_1 (type, name);
tree fndecls;
- if (index <= 0)
- return index;
- fndecls = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ /* ctors and dtors are always only in the right class. */
+ if (idx <= 1)
+ return idx;
+ fndecls = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
while (fndecls)
{
- if (TYPE_MAIN_VARIANT (DECL_CLASS_CONTEXT (fndecls))
+ if (TYPE_MAIN_VARIANT (DECL_CLASS_CONTEXT (OVL_CURRENT (fndecls)))
== TYPE_MAIN_VARIANT (type))
- return index;
- fndecls = TREE_CHAIN (fndecls);
+ return idx;
+ fndecls = OVL_CHAIN (fndecls);
}
return -1;
}
@@ -1064,17 +1162,18 @@ lookup_fnfields_here (type, name)
It was not clear what should happen if WANT_TYPE is set, and an
ambiguity is found. At least one use (lookup_name) to not see
the error. */
+
tree
lookup_field (xbasetype, name, protect, want_type)
register tree xbasetype, name;
int protect, want_type;
{
int head = 0, tail = 0;
- tree rval, rval_binfo = NULL_TREE, rval_binfo_h;
- tree type, basetype_chain, basetype_path;
- enum access_type this_v = access_default;
+ tree rval, rval_binfo = NULL_TREE, rval_binfo_h = NULL_TREE;
+ tree type = NULL_TREE, basetype_chain, basetype_path = NULL_TREE;
+ tree this_v = access_default_node;
tree entry, binfo, binfo_h;
- enum access_type own_access = access_default;
+ tree own_access = access_default_node;
int vbase_name_p = VBASE_NAME_P (name);
/* rval_binfo is the binfo associated with the found member, note,
@@ -1086,7 +1185,7 @@ lookup_field (xbasetype, name, protect, want_type)
/* rval_binfo_h and binfo_h are binfo values used when we perform the
hiding checks, as virtual base classes may not be shared. The strategy
- is we always go into the the binfo hierarchy owned by TYPE_BINFO of
+ is we always go into the binfo hierarchy owned by TYPE_BINFO of
virtual base classes, as we cross virtual base class lines. This way
we know that binfo of a virtual base class will always == itself when
found along any line. (mrs) */
@@ -1095,12 +1194,25 @@ lookup_field (xbasetype, name, protect, want_type)
/* Set this to nonzero if we don't know how to compute
accurate error messages for access control. */
- int index = MEMOIZED_HASH_FN (name);
+ int idx = MEMOIZED_HASH_FN (name);
+#if 0
+ /* We cannot search for constructor/destructor names like this. */
+ /* This can't go here, but where should it go? */
/* If we are looking for a constructor in a templated type, use the
unspecialized name, as that is how we store it. */
if (IDENTIFIER_TEMPLATE (name))
name = constructor_name (name);
+#endif
+
+ if (xbasetype == current_class_type && TYPE_BEING_DEFINED (xbasetype)
+ && IDENTIFIER_CLASS_VALUE (name))
+ {
+ tree field = IDENTIFIER_CLASS_VALUE (name);
+ if (TREE_CODE (field) != FUNCTION_DECL
+ && ! (want_type && TREE_CODE (field) != TYPE_DECL))
+ return field;
+ }
if (TREE_CODE (xbasetype) == TREE_VEC)
{
@@ -1110,15 +1222,18 @@ lookup_field (xbasetype, name, protect, want_type)
else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
{
type = xbasetype;
- basetype_path = TYPE_BINFO (xbasetype);
+ basetype_path = TYPE_BINFO (type);
BINFO_VIA_PUBLIC (basetype_path) = 1;
BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
}
- else my_friendly_abort (97);
+ else
+ my_friendly_abort (97);
+
+ complete_type (type);
if (CLASSTYPE_MTABLE_ENTRY (type))
{
- tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
while (tem && TREE_PURPOSE (tem) != name)
{
@@ -1144,8 +1259,8 @@ lookup_field (xbasetype, name, protect, want_type)
#ifdef GATHER_STATISTICS
n_calls_lookup_field++;
-#endif
- if (protect && flag_memoize_lookups && ! global_bindings_p ())
+#endif /* GATHER_STATISTICS */
+ if (protect && flag_memoize_lookups && ! toplevel_bindings_p ())
entry = make_memoized_table_entry (type, name, 0);
else
entry = 0;
@@ -1154,6 +1269,9 @@ lookup_field (xbasetype, name, protect, want_type)
if (rval || lookup_fnfields_here (type, name) >= 0)
{
+ if (entry)
+ TREE_VALUE (entry) = rval;
+
if (rval)
{
if (want_type)
@@ -1179,50 +1297,30 @@ lookup_field (xbasetype, name, protect, want_type)
this_v = compute_access (basetype_path, rval);
if (TREE_CODE (rval) == CONST_DECL)
{
- if (this_v == access_private)
+ if (this_v == access_private_node)
errstr = "enum `%D' is a private value of class `%T'";
- else if (this_v == access_protected)
+ else if (this_v == access_protected_node)
errstr = "enum `%D' is a protected value of class `%T'";
}
else
{
- if (this_v == access_private)
+ if (this_v == access_private_node)
errstr = "member `%D' is a private member of class `%T'";
- else if (this_v == access_protected)
+ else if (this_v == access_protected_node)
errstr = "member `%D' is a protected member of class `%T'";
}
}
- if (entry)
- {
- if (errstr)
- {
- /* This depends on behavior of lookup_field_1! */
- tree error_string = my_build_string (errstr);
- TREE_TYPE (entry) = error_string;
- }
- else
- {
- /* Let entry know there is no problem with this access. */
- TREE_TYPE (entry) = NULL_TREE;
- }
- TREE_VALUE (entry) = rval;
- }
-
- if (errstr && protect)
- {
- cp_error (errstr, name, type);
- return error_mark_node;
- }
- return rval;
+ rval_binfo = basetype_path;
+ goto out;
}
- basetype_chain = build_tree_list (NULL_TREE, basetype_path);
+ basetype_chain = build_expr_list (NULL_TREE, basetype_path);
TREE_VIA_PUBLIC (basetype_chain) = TREE_VIA_PUBLIC (basetype_path);
TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path);
TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
- /* The ambiguity check relies upon breadth first searching. */
+ /* The ambiguity check relies upon breadth first searching. */
search_stack = push_search_level (search_stack, &search_obstack);
binfo = basetype_path;
@@ -1248,11 +1346,11 @@ lookup_field (xbasetype, name, protect, want_type)
TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
if (TREE_VIA_VIRTUAL (base_binfo))
- btypes = tree_cons (NULL_TREE,
+ btypes = my_tree_cons (NULL_TREE,
TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
btypes);
else
- btypes = tree_cons (NULL_TREE,
+ btypes = my_tree_cons (NULL_TREE,
TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
btypes);
obstack_ptr_grow (&search_obstack, btypes);
@@ -1293,12 +1391,12 @@ lookup_field (xbasetype, name, protect, want_type)
else if (rval_binfo && hides (rval_binfo_h, binfo_h))
{
/* This is ok, the member found is in rval_binfo, not
- here (binfo). */
+ here (binfo). */
}
else if (rval_binfo==NULL_TREE || hides (binfo_h, rval_binfo_h))
{
/* This is ok, the member found is here (binfo), not in
- rval_binfo. */
+ rval_binfo. */
if (nval)
{
rval = nval;
@@ -1310,7 +1408,7 @@ lookup_field (xbasetype, name, protect, want_type)
}
else
{
- /* Undo finding it before, as something else hides it. */
+ /* Undo finding it before, as something else hides it. */
rval = NULL_TREE;
}
rval_binfo = binfo;
@@ -1318,9 +1416,9 @@ lookup_field (xbasetype, name, protect, want_type)
}
else
{
- /* This is ambiguous. */
+ /* This is ambiguous. */
errstr = "request for member `%D' is ambiguous";
- protect = 2;
+ protect += 2;
break;
}
}
@@ -1370,14 +1468,14 @@ lookup_field (xbasetype, name, protect, want_type)
/* If is possible for one of the derived types on the path to
have defined special access for this field. Look for such
declarations and report an error if a conflict is found. */
- enum access_type new_v;
+ tree new_v = NULL_TREE;
- if (this_v != access_default)
+ if (this_v != access_default_node)
new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval);
- if (this_v != access_default && new_v != this_v)
+ if (this_v != access_default_node && new_v != this_v)
{
errstr = "conflicting access to member `%D'";
- this_v = access_default;
+ this_v = access_default_node;
}
own_access = new_v;
CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
@@ -1397,20 +1495,21 @@ lookup_field (xbasetype, name, protect, want_type)
if (errstr == 0)
{
- if (own_access == access_private)
+ if (own_access == access_private_node)
errstr = "member `%D' declared private";
- else if (own_access == access_protected)
+ else if (own_access == access_protected_node)
errstr = "member `%D' declared protected";
- else if (this_v == access_private)
+ else if (this_v == access_private_node)
errstr = TREE_PRIVATE (rval)
? "member `%D' is private"
: "member `%D' is from private base class";
- else if (this_v == access_protected)
+ else if (this_v == access_protected_node)
errstr = TREE_PROTECTED (rval)
? "member `%D' is protected"
: "member `%D' is from protected base class";
}
+ out:
if (entry)
{
if (errstr)
@@ -1426,15 +1525,44 @@ lookup_field (xbasetype, name, protect, want_type)
}
}
+ if (protect == 2)
+ {
+ /* If we are not interested in ambiguities, don't report them,
+ just return NULL_TREE. */
+ rval = NULL_TREE;
+ protect = 0;
+ }
+
if (errstr && protect)
{
cp_error (errstr, name, type);
rval = error_mark_node;
}
+
+ /* Do implicit typename stuff. */
+ if (rval && TREE_CODE (rval) == TYPE_DECL
+ && ! DECL_ARTIFICIAL (rval)
+ && processing_template_decl
+ && ! currently_open_class (BINFO_TYPE (rval_binfo))
+ && uses_template_parms (type))
+ {
+ binfo = rval_binfo;
+ for (; ; binfo = BINFO_INHERITANCE_CHAIN (binfo))
+ if (BINFO_INHERITANCE_CHAIN (binfo) == NULL_TREE
+ || (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo))
+ == current_class_type))
+ break;
+
+ entry = make_typename_type (BINFO_TYPE (binfo), name);
+ TREE_TYPE (entry) = TREE_TYPE (rval);
+ rval = TYPE_MAIN_DECL (entry);
+ }
+
return rval;
}
/* Try to find NAME inside a nested class. */
+
tree
lookup_nested_field (name, complain)
tree name;
@@ -1443,14 +1571,14 @@ lookup_nested_field (name, complain)
register tree t;
tree id = NULL_TREE;
- if (TREE_CHAIN (current_class_type))
+ if (TYPE_MAIN_DECL (current_class_type))
{
/* Climb our way up the nested ladder, seeing if we're trying to
modify a field in an enclosing class. If so, we should only
be able to modify if it's static. */
- for (t = TREE_CHAIN (current_class_type);
+ for (t = TYPE_MAIN_DECL (current_class_type);
t && DECL_CONTEXT (t);
- t = TREE_CHAIN (DECL_CONTEXT (t)))
+ t = TYPE_MAIN_DECL (DECL_CONTEXT (t)))
{
if (TREE_CODE (DECL_CONTEXT (t)) != RECORD_TYPE)
break;
@@ -1477,10 +1605,8 @@ lookup_nested_field (name, complain)
enums in nested classes) when we do need to call
this fn at parse time. So, in those cases, we pass
complain as a 0 and just return a NULL_TREE. */
- error ("assignment to non-static member `%s' of enclosing class `%s'",
- lang_printable_name (id),
- IDENTIFIER_POINTER (TYPE_IDENTIFIER
- (DECL_CONTEXT (t))));
+ cp_error ("assignment to non-static member `%D' of enclosing class `%T'",
+ id, DECL_CONTEXT (t));
/* Mark this for do_identifier(). It would otherwise
claim that the variable was undeclared. */
TREE_TYPE (id) = error_mark_node;
@@ -1501,6 +1627,7 @@ lookup_nested_field (name, complain)
/* TYPE is a class type. Return the index of the fields within
the method vector with name NAME, or -1 is no such field exists. */
+
static int
lookup_fnfields_1 (type, name)
tree type, name;
@@ -1514,18 +1641,41 @@ lookup_fnfields_1 (type, name)
#ifdef GATHER_STATISTICS
n_calls_lookup_fnfields_1++;
-#endif
- if (*methods && name == constructor_name (type))
+#endif /* GATHER_STATISTICS */
+
+ /* Constructors are first... */
+ if (*methods && name == ctor_identifier)
return 0;
+ /* and destructors are second. */
+ if (*++methods && name == dtor_identifier)
+ return 1;
+
while (++methods != end)
{
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
-#endif
- if (DECL_NAME (*methods) == name)
+#endif /* GATHER_STATISTICS */
+ if (DECL_NAME (OVL_CURRENT (*methods)) == name)
break;
}
+
+ /* If we didn't find it, it might have been a template
+ conversion operator. (Note that we don't look for this case
+ above so that we will always find specializations first.) */
+ if (methods == end
+ && IDENTIFIER_TYPENAME_P (name))
+ {
+ methods = &TREE_VEC_ELT (method_vec, 0) + 1;
+
+ while (++methods != end)
+ {
+ if (TREE_CODE (OVL_CURRENT (*methods)) == TEMPLATE_DECL
+ && IDENTIFIER_TYPENAME_P (DECL_NAME (OVL_CURRENT (*methods))))
+ break;
+ }
+ }
+
if (methods != end)
return methods - &TREE_VEC_ELT (method_vec, 0);
}
@@ -1537,7 +1687,7 @@ lookup_fnfields_1 (type, name)
which gives the following information (in a list):
TREE_TYPE: list of basetypes needed to get to...
- TREE_VALUE: list of all functions in of given type
+ TREE_VALUE: list of all functions in a given type
which have name NAME.
No access information is computed by this function,
@@ -1551,14 +1701,15 @@ lookup_fnfields_1 (type, name)
As a special case, is COMPLAIN is -1, we don't complain, and we
don't return error_mark_node, but rather the complete list of
virtuals. This is used by get_virtuals_named_this. */
+
tree
lookup_fnfields (basetype_path, name, complain)
tree basetype_path, name;
int complain;
{
int head = 0, tail = 0;
- tree type, rval, rval_binfo = NULL_TREE, rvals = NULL_TREE, rval_binfo_h;
- tree entry, binfo, basetype_chain, binfo_h;
+ tree type, rval, rval_binfo = NULL_TREE, rvals = NULL_TREE;
+ tree rval_binfo_h = NULL_TREE, entry, binfo, basetype_chain, binfo_h;
int find_all = 0;
/* rval_binfo is the binfo associated with the found member, note,
@@ -1570,7 +1721,7 @@ lookup_fnfields (basetype_path, name, complain)
/* rval_binfo_h and binfo_h are binfo values used when we perform the
hiding checks, as virtual base classes may not be shared. The strategy
- is we always go into the the binfo hierarchy owned by TYPE_BINFO of
+ is we always go into the binfo hierarchy owned by TYPE_BINFO of
virtual base classes, as we cross virtual base class lines. This way
we know that binfo of a virtual base class will always == itself when
found along any line. (mrs) */
@@ -1582,7 +1733,7 @@ lookup_fnfields (basetype_path, name, complain)
/* Set this to nonzero if we don't know how to compute
accurate error messages for access control. */
- int index = MEMOIZED_HASH_FN (name);
+ int idx = MEMOIZED_HASH_FN (name);
if (complain == -1)
{
@@ -1590,19 +1741,23 @@ lookup_fnfields (basetype_path, name, complain)
protect = complain = 0;
}
+#if 0
+ /* We cannot search for constructor/destructor names like this. */
+ /* This can't go here, but where should it go? */
/* If we are looking for a constructor in a templated type, use the
unspecialized name, as that is how we store it. */
if (IDENTIFIER_TEMPLATE (name))
name = constructor_name (name);
+#endif
binfo = basetype_path;
binfo_h = binfo;
- type = BINFO_TYPE (basetype_path);
+ type = complete_type (BINFO_TYPE (basetype_path));
- /* The memoization code is in need of maintenance. */
+ /* The memoization code is in need of maintenance. */
if (!find_all && CLASSTYPE_MTABLE_ENTRY (type))
{
- tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
while (tem && TREE_PURPOSE (tem) != name)
{
@@ -1653,25 +1808,25 @@ lookup_fnfields (basetype_path, name, complain)
#ifdef GATHER_STATISTICS
n_calls_lookup_fnfields++;
-#endif
- if (protect && flag_memoize_lookups && ! global_bindings_p ())
+#endif /* GATHER_STATISTICS */
+ if (protect && flag_memoize_lookups && ! toplevel_bindings_p ())
entry = make_memoized_table_entry (type, name, 1);
else
entry = 0;
- index = lookup_fnfields_here (type, name);
- if (index >= 0 || lookup_field_1 (type, name))
+ idx = lookup_fnfields_here (type, name);
+ if (idx >= 0 || lookup_field_1 (type, name))
{
rval_binfo = basetype_path;
rval_binfo_h = rval_binfo;
}
- if (index >= 0)
+ if (idx >= 0)
{
- rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
rvals = my_tree_cons (basetype_path, rval, rvals);
if (BINFO_BASETYPES (binfo) && CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
+ TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
if (entry)
{
@@ -1683,6 +1838,16 @@ lookup_fnfields (basetype_path, name, complain)
}
rval = NULL_TREE;
+ if (name == ctor_identifier || name == dtor_identifier)
+ {
+ /* Don't allow lookups of constructors and destructors to go
+ deeper than the first place we look. */
+ if (entry)
+ TREE_TYPE (entry) = TREE_VALUE (entry) = NULL_TREE;
+
+ return NULL_TREE;
+ }
+
if (basetype_path == TYPE_BINFO (type))
{
basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
@@ -1692,13 +1857,13 @@ lookup_fnfields (basetype_path, name, complain)
}
else
{
- basetype_chain = build_tree_list (NULL_TREE, basetype_path);
+ basetype_chain = build_expr_list (NULL_TREE, basetype_path);
TREE_VIA_PUBLIC (basetype_chain) = TREE_VIA_PUBLIC (basetype_path);
TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path);
TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
}
- /* The ambiguity check relies upon breadth first searching. */
+ /* The ambiguity check relies upon breadth first searching. */
search_stack = push_search_level (search_stack, &search_obstack);
binfo = basetype_path;
@@ -1708,7 +1873,7 @@ lookup_fnfields (basetype_path, name, complain)
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int index;
+ int idx;
/* Process and/or queue base types. */
for (i = 0; i < n_baselinks; i++)
@@ -1724,11 +1889,11 @@ lookup_fnfields (basetype_path, name, complain)
TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
if (TREE_VIA_VIRTUAL (base_binfo))
- btypes = tree_cons (NULL_TREE,
+ btypes = my_tree_cons (NULL_TREE,
TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
btypes);
else
- btypes = tree_cons (NULL_TREE,
+ btypes = my_tree_cons (NULL_TREE,
TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
btypes);
obstack_ptr_grow (&search_obstack, btypes);
@@ -1758,32 +1923,32 @@ lookup_fnfields (basetype_path, name, complain)
and we do find NAME in TYPE, verify that such a second
sighting is in fact valid. */
- index = lookup_fnfields_here (type, name);
+ idx = lookup_fnfields_here (type, name);
- if (index >= 0 || (lookup_field_1 (type, name)!=NULL_TREE && !find_all))
+ if (idx >= 0 || (lookup_field_1 (type, name)!=NULL_TREE && !find_all))
{
if (rval_binfo && !find_all && hides (rval_binfo_h, binfo_h))
{
/* This is ok, the member found is in rval_binfo, not
- here (binfo). */
+ here (binfo). */
}
else if (rval_binfo==NULL_TREE || find_all || hides (binfo_h, rval_binfo_h))
{
/* This is ok, the member found is here (binfo), not in
- rval_binfo. */
- if (index >= 0)
+ rval_binfo. */
+ if (idx >= 0)
{
- rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
/* Note, rvals can only be previously set if find_all is
true. */
rvals = my_tree_cons (basetype_path, rval, rvals);
if (TYPE_BINFO_BASETYPES (type)
&& CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
+ TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
}
else
{
- /* Undo finding it before, as something else hides it. */
+ /* Undo finding it before, as something else hides it. */
rval = NULL_TREE;
rvals = NULL_TREE;
}
@@ -1792,7 +1957,7 @@ lookup_fnfields (basetype_path, name, complain)
}
else
{
- /* This is ambiguous. */
+ /* This is ambiguous. */
errstr = "request for method `%D' is ambiguous";
rvals = error_mark_node;
break;
@@ -1835,22 +2000,51 @@ lookup_fnfields (basetype_path, name, complain)
return rvals;
}
+
+/* Look for a field or function named NAME in an inheritance lattice
+ dominated by XBASETYPE. PROTECT is zero if we can avoid computing
+ access information, otherwise it is 1. WANT_TYPE is 1 when we should
+ only return TYPE_DECLs, if no TYPE_DECL can be found return NULL_TREE. */
+
+tree
+lookup_member (xbasetype, name, protect, want_type)
+ tree xbasetype, name;
+ int protect, want_type;
+{
+ tree ret, basetype_path;
+
+ if (TREE_CODE (xbasetype) == TREE_VEC)
+ basetype_path = xbasetype;
+ else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
+ {
+ basetype_path = TYPE_BINFO (xbasetype);
+ BINFO_VIA_PUBLIC (basetype_path) = 1;
+ BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
+ }
+ else
+ my_friendly_abort (97);
+
+ ret = lookup_field (basetype_path, name, protect, want_type);
+ if (! ret && ! want_type)
+ ret = lookup_fnfields (basetype_path, name, protect);
+ return ret;
+}
/* BREADTH-FIRST SEARCH ROUTINES. */
/* Search a multiple inheritance hierarchy by breadth-first search.
- TYPE is an aggregate type, possibly in a multiple-inheritance hierarchy.
+ BINFO is an aggregate type, possibly in a multiple-inheritance hierarchy.
TESTFN is a function, which, if true, means that our condition has been met,
and its return value should be returned.
QFN, if non-NULL, is a predicate dictating whether the type should
even be queued. */
-HOST_WIDE_INT
+static HOST_WIDE_INT
breadth_first_search (binfo, testfn, qfn)
tree binfo;
- int (*testfn)();
- int (*qfn)();
+ int (*testfn) PROTO((tree, int));
+ int (*qfn) PROTO((tree, int));
{
int head = 0, tail = 0;
int rval = 0;
@@ -1888,7 +2082,7 @@ breadth_first_search (binfo, testfn, qfn)
binfo = search_stack->first[head++];
i = (HOST_WIDE_INT) search_stack->first[head++];
- if (rval = (*testfn) (binfo, i))
+ if ((rval = (*testfn) (binfo, i)))
break;
binfo = BINFO_BASETYPE (binfo, i);
}
@@ -1908,18 +2102,7 @@ breadth_first_search (binfo, testfn, qfn)
}
/* Functions to use in breadth first searches. */
-typedef tree (*pft)();
-typedef int (*pfi)();
-
-int tree_needs_constructor_p (binfo, i)
- tree binfo;
- int i;
-{
- tree basetype;
- my_friendly_assert (i != 0, 296);
- basetype = BINFO_TYPE (BINFO_BASETYPE (binfo, i));
- return TYPE_NEEDS_CONSTRUCTING (basetype);
-}
+typedef int (*pfi) PROTO((tree, int));
static tree declarator;
@@ -1941,15 +2124,16 @@ get_virtuals_named_this (binfo)
{
tree fndecl;
- for (fndecl = TREE_VALUE (fields); fndecl; fndecl = DECL_CHAIN (fndecl))
- if (DECL_VINDEX (fndecl))
+ for (fndecl = TREE_VALUE (fields); fndecl; fndecl = OVL_NEXT (fndecl))
+ if (DECL_VINDEX (OVL_CURRENT (fndecl)))
return fields;
fields = next_baselink (fields);
}
return NULL_TREE;
}
-static tree get_virtual_destructor (binfo, i)
+static tree
+get_virtual_destructor (binfo, i)
tree binfo;
int i;
{
@@ -1957,12 +2141,13 @@ static tree get_virtual_destructor (binfo, i)
if (i >= 0)
type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
if (TYPE_HAS_DESTRUCTOR (type)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0)))
- return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
+ && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1)))
+ return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1);
return 0;
}
-int tree_has_any_destructor_p (binfo, i)
+static int
+tree_has_any_destructor_p (binfo, i)
tree binfo;
int i;
{
@@ -1972,18 +2157,83 @@ int tree_has_any_destructor_p (binfo, i)
return TYPE_NEEDS_DESTRUCTOR (type);
}
+/* Returns > 0 if a function with type DRETTYPE overriding a function
+ with type BRETTYPE is covariant, as defined in [class.virtual].
+
+ Returns 1 if trivial covariance, 2 if non-trivial (requiring runtime
+ adjustment), or -1 if pedantically invalid covariance. */
+
+static int
+covariant_return_p (brettype, drettype)
+ tree brettype, drettype;
+{
+ tree binfo;
+
+ if (TREE_CODE (brettype) == FUNCTION_DECL
+ || TREE_CODE (brettype) == THUNK_DECL)
+ {
+ brettype = TREE_TYPE (TREE_TYPE (brettype));
+ drettype = TREE_TYPE (TREE_TYPE (drettype));
+ }
+ else if (TREE_CODE (brettype) == METHOD_TYPE)
+ {
+ brettype = TREE_TYPE (brettype);
+ drettype = TREE_TYPE (drettype);
+ }
+
+ if (comptypes (brettype, drettype, 1))
+ return 0;
+
+ if (! (TREE_CODE (brettype) == TREE_CODE (drettype)
+ && (TREE_CODE (brettype) == POINTER_TYPE
+ || TREE_CODE (brettype) == REFERENCE_TYPE)
+ && TYPE_READONLY (brettype) == TYPE_READONLY (drettype)
+ && TYPE_VOLATILE (brettype) == TYPE_VOLATILE (drettype)))
+ return 0;
+
+ if (! can_convert (brettype, drettype))
+ return 0;
+
+ brettype = TREE_TYPE (brettype);
+ drettype = TREE_TYPE (drettype);
+
+ /* If not pedantic, allow any standard pointer conversion. */
+ if (! IS_AGGR_TYPE (drettype) || ! IS_AGGR_TYPE (brettype))
+ return -1;
+
+ binfo = get_binfo (brettype, drettype, 1);
+
+ /* If we get an error_mark_node from get_binfo, it already complained,
+ so let's just succeed. */
+ if (binfo == error_mark_node)
+ return 1;
+
+ if (! BINFO_OFFSET_ZEROP (binfo) || TREE_VIA_VIRTUAL (binfo))
+ return 2;
+ return 1;
+}
+
/* Given a class type TYPE, and a function decl FNDECL, look for a
virtual function in TYPE's hierarchy which FNDECL could match as a
virtual function. It doesn't matter which one we find.
DTORP is nonzero if we are looking for a destructor. Destructors
need special treatment because they do not match by name. */
+
tree
get_matching_virtual (binfo, fndecl, dtorp)
tree binfo, fndecl;
int dtorp;
{
tree tmp = NULL_TREE;
+ int i;
+
+ if (TREE_CODE (fndecl) == TEMPLATE_DECL)
+ /* In [temp.mem] we have:
+
+ A specialization of a member function template does not
+ override a virtual function from a base class. */
+ return NULL_TREE;
/* Breadth first search routines start searching basetypes
of TYPE, so we must perform first ply of search here. */
@@ -2024,8 +2274,10 @@ get_matching_virtual (binfo, fndecl, dtorp)
for (; baselink; baselink = next_baselink (baselink))
{
- for (tmp = TREE_VALUE (baselink); tmp; tmp = DECL_CHAIN (tmp))
+ tree tmps;
+ for (tmps = TREE_VALUE (baselink); tmps; tmps = OVL_NEXT (tmps))
{
+ tmp = OVL_CURRENT (tmps);
if (! DECL_VINDEX (tmp))
continue;
@@ -2045,35 +2297,15 @@ get_matching_virtual (binfo, fndecl, dtorp)
tree brettype = TREE_TYPE (TREE_TYPE (tmp));
if (comptypes (brettype, drettype, 1))
/* OK */;
- else if
- (TREE_CODE (brettype) == TREE_CODE (drettype)
- && (TREE_CODE (brettype) == POINTER_TYPE
- || TREE_CODE (brettype) == REFERENCE_TYPE)
- && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (brettype)),
- TYPE_MAIN_VARIANT (TREE_TYPE (drettype)),
- 0))
- /* covariant return type */
+ else if ((i = covariant_return_p (brettype, drettype)))
{
- tree b = TREE_TYPE (brettype), d = TREE_TYPE (drettype);
- if (TYPE_MAIN_VARIANT (b) != TYPE_MAIN_VARIANT (d))
- {
- tree binfo = get_binfo (b, d, 1);
- if (binfo != error_mark_node
- && ! BINFO_OFFSET_ZEROP (binfo))
- sorry ("adjusting pointers for covariant returns");
- }
- if (TYPE_READONLY (d) > TYPE_READONLY (b))
- {
- cp_error ("return type of `%#D' adds const", fndecl);
- cp_error_at (" overriding definition as `%#D'",
- tmp);
- }
- else if (TYPE_VOLATILE (d) > TYPE_VOLATILE (b))
+ if (i == 2)
+ sorry ("adjusting pointers for covariant returns");
+
+ if (pedantic && i == -1)
{
- cp_error ("return type of `%#D' adds volatile",
- fndecl);
- cp_error_at (" overriding definition as `%#D'",
- tmp);
+ cp_pedwarn_at ("invalid covariant return type for `%#D' (must be pointer or reference to class)", fndecl);
+ cp_pedwarn_at (" overriding `%#D'", tmp);
}
}
else if (IS_AGGR_TYPE_2 (brettype, drettype)
@@ -2081,25 +2313,24 @@ get_matching_virtual (binfo, fndecl, dtorp)
{
error ("invalid covariant return type (must use pointer or reference)");
cp_error_at (" overriding `%#D'", tmp);
- cp_error (" with `%#D'", fndecl);
+ cp_error_at (" with `%#D'", fndecl);
}
else if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE)
{
- cp_error ("conflicting return type specified for virtual function `%#D'", fndecl);
+ cp_error_at ("conflicting return type specified for virtual function `%#D'", fndecl);
cp_error_at (" overriding definition as `%#D'", tmp);
SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
}
break;
}
}
- if (tmp)
+ /* If not at the end */
+ if (tmps)
{
best = tmp;
break;
}
}
- if (best == NULL_TREE && warn_overloaded_virtual)
- cp_warning_at ("conflicting specification deriving virtual function `%D'", fndecl);
return best;
}
@@ -2108,10 +2339,12 @@ get_matching_virtual (binfo, fndecl, dtorp)
/* Return the list of virtual functions which are abstract in type
TYPE that come from non virtual base classes. See
expand_direct_vtbls_init for the style of search we do. */
+
static tree
get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
- tree binfo, abstract_virtuals;
+ tree binfo;
int do_self;
+ tree abstract_virtuals;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2119,8 +2352,8 @@ get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable =
- i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+ int is_not_base_vtable
+ = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (! TREE_VIA_VIRTUAL (base_binfo))
abstract_virtuals
= get_abstract_virtuals_1 (base_binfo, is_not_base_vtable,
@@ -2148,6 +2381,7 @@ get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
/* Return the list of virtual functions which are abstract in type TYPE.
This information is cached, and so must be built on a
non-temporary obstack. */
+
tree
get_abstract_virtuals (type)
tree type;
@@ -2155,7 +2389,7 @@ get_abstract_virtuals (type)
tree vbases;
tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
- /* First get all from non-virtual bases. */
+ /* First get all from non-virtual bases. */
abstract_virtuals
= get_abstract_virtuals_1 (TYPE_BINFO (type), 1, abstract_virtuals);
@@ -2190,7 +2424,7 @@ get_baselinks (type_as_binfo_list, type, name)
tree type_as_binfo_list;
tree type, name;
{
- int head = 0, tail = 0, index;
+ int head = 0, tail = 0, idx;
tree rval = 0, nval = 0;
tree basetypes = type_as_binfo_list;
tree binfo = TYPE_BINFO (type);
@@ -2226,17 +2460,17 @@ get_baselinks (type_as_binfo_list, type, name)
basetypes = search_stack->first[head++];
binfo = TREE_VALUE (basetypes);
type = BINFO_TYPE (binfo);
- index = lookup_fnfields_1 (type, name);
- if (index >= 0)
+ idx = lookup_fnfields_1 (type, name);
+ if (idx >= 0)
{
- nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
rval = hash_tree_cons (0, 0, 0, basetypes, nval, rval);
if (TYPE_BINFO_BASETYPES (type) == 0)
goto dont_queue;
else if (TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)) == 1)
{
if (CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rval) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
+ TREE_TYPE (rval) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
goto dont_queue;
}
}
@@ -2266,6 +2500,7 @@ next_baselink (baselink)
/* DEPTH-FIRST SEARCH ROUTINES. */
+#ifdef MI_MATRIX
/* Assign unique numbers to _CLASSTYPE members of the lattice
specified by TYPE. The root nodes are marked first; the nodes
are marked depth-fisrt, left-right. */
@@ -2290,11 +2525,13 @@ static int mi_size;
((mi_matrix+mi_size*(CLASSTYPE_CID (C1)-1))[CLASSTYPE_CID (C2)-1])
#define BINFO_DERIVES_FROM_STAR(C) \
(mi_matrix+(BINFO_CID (C)-1))
+#endif
/* This routine converts a pointer to be a pointer of an immediate
base class. The normal convert_pointer_to routine would diagnose
the conversion as ambiguous, under MI code that has the base class
- as an ambiguous base class. */
+ as an ambiguous base class. */
+
static tree
convert_pointer_to_single_level (to_type, expr)
tree to_type, expr;
@@ -2313,12 +2550,13 @@ convert_pointer_to_single_level (to_type, expr)
This routine has to remember the path it walked up, when
dfs_init_vbase_pointers is the work function, as otherwise there
- would be no record. */
+ would be no record. */
+
static void
dfs_walk (binfo, fn, qfn)
tree binfo;
- void (*fn)();
- int (*qfn)();
+ void (*fn) PROTO((tree));
+ int (*qfn) PROTO((tree));
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2329,7 +2567,10 @@ dfs_walk (binfo, fn, qfn)
if (qfn == 0 || (*qfn)(base_binfo))
{
- if (fn == dfs_init_vbase_pointers)
+ if (TREE_CODE (BINFO_TYPE (base_binfo)) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (BINFO_TYPE (base_binfo)) == TEMPLATE_TEMPLATE_PARM)
+ /* Pass */;
+ else if (fn == dfs_init_vbase_pointers)
{
/* When traversing an arbitrary MI hierarchy, we need to keep
a record of the path we took to get down to the final base
@@ -2354,7 +2595,7 @@ dfs_walk (binfo, fn, qfn)
/* No need for the conversion here, as we know it is the
right type. */
vbase_decl_ptr_intermediate
- = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo));
+ = CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo));
}
else
{
@@ -2366,47 +2607,56 @@ dfs_walk (binfo, fn, qfn)
dfs_walk (base_binfo, fn, qfn);
vbase_decl_ptr_intermediate = saved_vbase_decl_ptr_intermediate;
- } else
- dfs_walk (base_binfo, fn, qfn);
+ }
+ else
+ dfs_walk (base_binfo, fn, qfn);
}
}
fn (binfo);
}
+#ifdef MI_MATRIX
/* Predicate functions which serve for dfs_walk. */
static int numberedp (binfo) tree binfo;
{ return BINFO_CID (binfo); }
static int unnumberedp (binfo) tree binfo;
{ return BINFO_CID (binfo) == 0; }
+#endif
static int markedp (binfo) tree binfo;
{ return BINFO_MARKED (binfo); }
-static int bfs_markedp (binfo, i) tree binfo; int i;
-{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)); }
static int unmarkedp (binfo) tree binfo;
{ return BINFO_MARKED (binfo) == 0; }
+
+#if 0
+static int bfs_markedp (binfo, i) tree binfo; int i;
+{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)); }
static int bfs_unmarkedp (binfo, i) tree binfo; int i;
{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-static int marked_vtable_pathp (binfo) tree binfo;
-{ return BINFO_VTABLE_PATH_MARKED (binfo); }
static int bfs_marked_vtable_pathp (binfo, i) tree binfo; int i;
{ return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int unmarked_vtable_pathp (binfo) tree binfo;
-{ return BINFO_VTABLE_PATH_MARKED (binfo) == 0; }
static int bfs_unmarked_vtable_pathp (binfo, i) tree binfo; int i;
{ return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-static int marked_new_vtablep (binfo) tree binfo;
-{ return BINFO_NEW_VTABLE_MARKED (binfo); }
static int bfs_marked_new_vtablep (binfo, i) tree binfo; int i;
{ return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int unmarked_new_vtablep (binfo) tree binfo;
-{ return BINFO_NEW_VTABLE_MARKED (binfo) == 0; }
static int bfs_unmarked_new_vtablep (binfo, i) tree binfo; int i;
{ return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
+#endif
+static int marked_vtable_pathp (binfo) tree binfo;
+{ return BINFO_VTABLE_PATH_MARKED (binfo); }
+static int unmarked_vtable_pathp (binfo) tree binfo;
+{ return BINFO_VTABLE_PATH_MARKED (binfo) == 0; }
+static int marked_new_vtablep (binfo) tree binfo;
+{ return BINFO_NEW_VTABLE_MARKED (binfo); }
+static int unmarked_new_vtablep (binfo) tree binfo;
+{ return BINFO_NEW_VTABLE_MARKED (binfo) == 0; }
+
+#if 0
static int dfs_search_slot_nonempty_p (binfo) tree binfo;
{ return CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) != 0; }
+#endif
static int dfs_debug_unmarkedp (binfo) tree binfo;
{ return CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) == 0; }
@@ -2415,6 +2665,7 @@ static int dfs_debug_unmarkedp (binfo) tree binfo;
test anything (vis a vis marking) if they are paired with
a predicate function (above). */
+#ifdef MI_MATRIX
/* Assign each type within the lattice a number which is unique
in the lattice. The first number assigned is 1. */
@@ -2431,15 +2682,19 @@ dfs_unnumber (binfo)
{
BINFO_CID (binfo) = 0;
}
+#endif
+#if 0
static void
dfs_mark (binfo) tree binfo;
{ SET_BINFO_MARKED (binfo); }
+#endif
static void
dfs_unmark (binfo) tree binfo;
{ CLEAR_BINFO_MARKED (binfo); }
+#if 0
static void
dfs_mark_vtable_path (binfo) tree binfo;
{ SET_BINFO_VTABLE_PATH_MARKED (binfo); }
@@ -2459,6 +2714,7 @@ dfs_unmark_new_vtable (binfo) tree binfo;
static void
dfs_clear_search_slot (binfo) tree binfo;
{ CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
+#endif
static void
dfs_debug_mark (binfo)
@@ -2472,9 +2728,12 @@ dfs_debug_mark (binfo)
CLASSTYPE_DEBUG_REQUESTED (t) = 1;
- /* If interface info is known, the value of (?@@?) is correct. */
- if (methods == 0
- || CLASSTYPE_INTERFACE_KNOWN (t)
+ if (methods == 0)
+ return;
+
+ /* If interface info is known, either we've already emitted the debug
+ info or we don't need to. */
+ if (CLASSTYPE_INTERFACE_KNOWN (t)
|| (write_virtuals == 2 && TYPE_VIRTUAL_P (t)))
return;
@@ -2484,10 +2743,13 @@ dfs_debug_mark (binfo)
if (current_function_decl == NULL_TREE
|| DECL_CLASS_CONTEXT (current_function_decl) != t)
{
- if (TREE_VEC_ELT (methods, 0))
+ if (TREE_VEC_ELT (methods, 1))
+ methods = TREE_VEC_ELT (methods, 1);
+ else if (TREE_VEC_ELT (methods, 0))
methods = TREE_VEC_ELT (methods, 0);
else
- methods = TREE_VEC_ELT (methods, 1);
+ methods = TREE_VEC_ELT (methods, 2);
+ methods = OVL_CURRENT (methods);
while (methods)
{
if (DECL_VINDEX (methods)
@@ -2505,13 +2767,14 @@ dfs_debug_mark (binfo)
/* We cannot rely on some alien method to solve our problems,
so we must write out the debug info ourselves. */
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
- rest_of_type_compilation (t, global_bindings_p ());
+ rest_of_type_compilation (t, toplevel_bindings_p ());
}
/* Attach to the type of the virtual base class, the pointer to the
virtual base class, given the global pointer vbase_decl_ptr.
We use the global vbase_types. ICK! */
+
static void
dfs_find_vbases (binfo)
tree binfo;
@@ -2530,8 +2793,8 @@ dfs_find_vbases (binfo)
tree binfo = binfo_member (vbase, vbase_types);
CLASSTYPE_SEARCH_SLOT (vbase)
- = (char *) build (PLUS_EXPR, build_pointer_type (vbase),
- vbase_decl_ptr, BINFO_OFFSET (binfo));
+ = build (PLUS_EXPR, build_pointer_type (vbase),
+ vbase_decl_ptr, BINFO_OFFSET (binfo));
}
}
SET_BINFO_VTABLE_PATH_MARKED (binfo);
@@ -2548,12 +2811,12 @@ dfs_init_vbase_pointers (binfo)
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
- /* If there is a rtti, it is the first field, though perhaps from
- the base class. Otherwise, the first fields are virtual base class
- pointer fields. */
- if (CLASSTYPE_RTTI (type) && VFIELD_NAME_P (DECL_NAME (fields)))
- /* Get past vtable for the object. */
+#if 0
+ /* See finish_struct_1 for when we can enable this. */
+ /* If we have a vtable pointer first, skip it. */
+ if (VFIELD_NAME_P (DECL_NAME (fields)))
fields = TREE_CHAIN (fields);
+#endif
if (fields == NULL_TREE
|| DECL_NAME (fields) == NULL_TREE
@@ -2570,7 +2833,7 @@ dfs_init_vbase_pointers (binfo)
{
tree ref = build (COMPONENT_REF, TREE_TYPE (fields),
build_indirect_ref (this_vbase_ptr, NULL_PTR), fields);
- tree init = (tree)CLASSTYPE_SEARCH_SLOT (TREE_TYPE (TREE_TYPE (fields)));
+ tree init = CLASSTYPE_SEARCH_SLOT (TREE_TYPE (TREE_TYPE (fields)));
vbase_init_result = tree_cons (binfo_member (TREE_TYPE (TREE_TYPE (fields)),
vbase_types),
build_modify_expr (ref, NOP_EXPR, init),
@@ -2582,6 +2845,7 @@ dfs_init_vbase_pointers (binfo)
/* Sometimes this needs to clear both VTABLE_PATH and NEW_VTABLE. Other
times, just NEW_VTABLE, but optimizer should make both with equal
efficiency (though it does not currently). */
+
static void
dfs_clear_vbase_slots (binfo)
tree binfo;
@@ -2603,9 +2867,7 @@ init_vbase_pointers (type, decl_ptr)
tree binfo = TYPE_BINFO (type);
flag_this_is_variable = -2;
vbase_types = CLASSTYPE_VBASECLASSES (type);
- vbase_decl_ptr = decl_ptr;
- vbase_decl = build_indirect_ref (decl_ptr, NULL_PTR);
- vbase_decl_ptr_intermediate = vbase_decl_ptr;
+ vbase_decl_ptr = vbase_decl_ptr_intermediate = decl_ptr;
vbase_init_result = NULL_TREE;
dfs_walk (binfo, dfs_find_vbases, unmarked_vtable_pathp);
dfs_walk (binfo, dfs_init_vbase_pointers, marked_vtable_pathp);
@@ -2626,6 +2888,7 @@ init_vbase_pointers (type, decl_ptr)
We know that if there is more than one place (binfo) the fndecl that the
declared, they all refer to the same binfo. See get_class_offset_1 for
the check that ensures this. */
+
static tree
virtual_context (fndecl, t, vbase)
tree fndecl, t, vbase;
@@ -2663,7 +2926,10 @@ virtual_context (fndecl, t, vbase)
they may upcast into a direct base, or
they may upcast into a different vbase.
- We only need to do fixups in case 2 and 3.
+ We only need to do fixups in case 2 and 3. In case 2, we add in
+ the virtual base offset to effect an upcast, in case 3, we add in
+ the virtual base offset to effect an upcast, then subtract out the
+ offset for the other virtual base, to effect a downcast into it.
This routine mirrors fixup_vtable_deltas in functionality, though
this one is runtime based, and the other is compile time based.
@@ -2671,10 +2937,15 @@ virtual_context (fndecl, t, vbase)
done at runtime.
VBASE_OFFSETS is an association list of virtual bases that contains
- offset information, so the offsets are only calculated once. */
+ offset information for the virtual bases, so the offsets are only
+ calculated once. The offsets are computed by where we think the
+ vbase should be (as noted by the CLASSTYPE_SEARCH_SLOT) minus where
+ the vbase really is. */
+
static void
-expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
- tree binfo, addr, orig_addr, vbase, t, *vbase_offsets;
+expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
+ vbase_offsets)
+ tree binfo, addr, orig_addr, vbase, vbase_addr, t, *vbase_offsets;
{
tree virtuals = BINFO_VIRTUALS (binfo);
tree vc;
@@ -2684,8 +2955,8 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
delta = purpose_member (vbase, *vbase_offsets);
if (! delta)
{
- delta = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbase));
- delta = build (MINUS_EXPR, ptrdiff_type_node, delta, addr);
+ delta = CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbase));
+ delta = build (MINUS_EXPR, ptrdiff_type_node, delta, vbase_addr);
delta = save_expr (delta);
delta = tree_cons (vbase, delta, *vbase_offsets);
*vbase_offsets = delta;
@@ -2702,8 +2973,8 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
&& current_fndecl != abort_fndecl
&& (vc=virtual_context (current_fndecl, t, vbase)) != vbase)
{
- /* This may in fact need a runtime fixup. */
- tree idx = DECL_VINDEX (current_fndecl);
+ /* This may in fact need a runtime fixup. */
+ tree idx = build_int_2 (n, 0);
tree vtbl = BINFO_VTABLE (binfo);
tree nvtbl = lookup_name (DECL_NAME (vtbl), 0);
tree aref, ref, naref;
@@ -2714,51 +2985,69 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
|| nvtbl == IDENTIFIER_GLOBAL_VALUE (DECL_NAME (vtbl)))
{
/* Dup it if it isn't in local scope yet. */
- nvtbl = build_decl (VAR_DECL,
- DECL_NAME (vtbl),
- TYPE_MAIN_VARIANT (TREE_TYPE (BINFO_VTABLE (binfo))));
+ nvtbl = build_decl
+ (VAR_DECL, DECL_NAME (vtbl),
+ TYPE_MAIN_VARIANT (TREE_TYPE (BINFO_VTABLE (binfo))));
DECL_ALIGN (nvtbl) = MAX (TYPE_ALIGN (double_type_node),
DECL_ALIGN (nvtbl));
TREE_READONLY (nvtbl) = 0;
+ DECL_ARTIFICIAL (nvtbl) = 1;
nvtbl = pushdecl (nvtbl);
init = NULL_TREE;
- cp_finish_decl (nvtbl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
- DECL_VIRTUAL_P (nvtbl) = 1;
- DECL_CONTEXT (nvtbl) = t;
+ cp_finish_decl (nvtbl, init, NULL_TREE, 0,
+ LOOKUP_ONLYCONVERTING);
+
+ /* We don't set DECL_VIRTUAL_P and DECL_CONTEXT on nvtbl
+ because they wouldn't be useful; everything that wants to
+ look at the vtable will look at the decl for the normal
+ vtable. Setting DECL_CONTEXT also screws up
+ decl_function_context. */
+
init = build (MODIFY_EXPR, TREE_TYPE (nvtbl),
nvtbl, vtbl);
TREE_SIDE_EFFECTS (init) = 1;
expand_expr_stmt (init);
- /* Update the vtable pointers as necessary. */
- ref = build_vfield_ref (build_indirect_ref (addr, NULL_PTR), DECL_CONTEXT (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))));
- expand_expr_stmt (build_modify_expr (ref, NOP_EXPR,
- build_unary_op (ADDR_EXPR, nvtbl, 0)));
+ /* Update the vtable pointers as necessary. */
+ ref = build_vfield_ref
+ (build_indirect_ref (addr, NULL_PTR),
+ DECL_CONTEXT (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))));
+ expand_expr_stmt
+ (build_modify_expr (ref, NOP_EXPR,
+ build_unary_op (ADDR_EXPR, nvtbl, 0)));
}
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
naref = build_array_ref (nvtbl, idx);
- old_delta = build_component_ref (aref, delta_identifier, 0, 0);
- new_delta = build_component_ref (naref, delta_identifier, 0, 0);
+ old_delta = build_component_ref (aref, delta_identifier,
+ NULL_TREE, 0);
+ new_delta = build_component_ref (naref, delta_identifier,
+ NULL_TREE, 0);
+
+ /* This is a upcast, so we have to add the offset for the
+ virtual base. */
old_delta = build_binary_op (PLUS_EXPR, old_delta,
TREE_VALUE (delta), 0);
if (vc)
{
- /* If this is set, we need to add in delta adjustments for
- the other virtual base. */
+ /* If this is set, we need to subtract out the delta
+ adjustments for the other virtual base that we
+ downcast into. */
tree vc_delta = purpose_member (vc, *vbase_offsets);
if (! vc_delta)
{
tree vc_addr = convert_pointer_to_real (vc, orig_addr);
- vc_delta = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vc));
+ vc_delta = CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vc));
vc_delta = build (MINUS_EXPR, ptrdiff_type_node,
- vc_addr, vc_delta);
+ vc_delta, vc_addr);
vc_delta = save_expr (vc_delta);
*vbase_offsets = tree_cons (vc, vc_delta, *vbase_offsets);
}
else
vc_delta = TREE_VALUE (vc_delta);
- old_delta = build_binary_op (PLUS_EXPR, old_delta, vc_delta, 0);
+ /* This is a downcast, so we have to subtract the offset
+ for the virtual base. */
+ old_delta = build_binary_op (MINUS_EXPR, old_delta, vc_delta, 0);
}
TREE_READONLY (new_delta) = 0;
@@ -2772,10 +3061,12 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
/* Fixup upcast offsets for all direct vtables. Patterned after
expand_direct_vtbls_init. */
+
static void
fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, orig_addr, type, vbase, vbase_offsets)
- tree real_binfo, binfo, addr, orig_addr, type, vbase, *vbase_offsets;
+ tree real_binfo, binfo;
int init_self, can_elide;
+ tree addr, orig_addr, type, vbase, *vbase_offsets;
{
tree real_binfos = BINFO_BASETYPES (real_binfo);
tree binfos = BINFO_BASETYPES (binfo);
@@ -2785,8 +3076,8 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
{
tree real_base_binfo = TREE_VEC_ELT (real_binfos, i);
tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable =
- i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
+ int is_not_base_vtable
+ = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
if (! TREE_VIA_VIRTUAL (real_base_binfo))
fixup_virtual_upcast_offsets (real_base_binfo, base_binfo,
is_not_base_vtable, can_elide, addr,
@@ -2800,8 +3091,9 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
/* Should we use something besides CLASSTYPE_VFIELDS? */
if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))
{
- addr = convert_pointer_to_real (binfo, addr);
- expand_upcast_fixups (real_binfo, addr, orig_addr, vbase, type, vbase_offsets);
+ tree new_addr = convert_pointer_to_real (binfo, addr);
+ expand_upcast_fixups (real_binfo, new_addr, orig_addr, vbase, addr,
+ type, vbase_offsets);
}
}
@@ -2818,30 +3110,22 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
offsets are valid to store vtables. When zero, we must store new
vtables through virtual baseclass pointers.
- We setup and use the globals: vbase_decl, vbase_decl_ptr, vbase_types
+ We setup and use the globals: vbase_decl_ptr, vbase_types
ICK! */
void
-expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
+expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
tree binfo;
tree true_exp, decl_ptr;
- int use_computed_offsets;
{
tree type = BINFO_TYPE (binfo);
+
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
rtx fixup_insns = NULL_RTX;
- int old_flag = flag_this_is_variable;
tree vbases = CLASSTYPE_VBASECLASSES (type);
vbase_types = vbases;
vbase_decl_ptr = true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) : decl_ptr;
- vbase_decl = true_exp ? true_exp : build_indirect_ref (decl_ptr, NULL_PTR);
-
- if (use_computed_offsets)
- {
- /* This is an object of type IN_TYPE, */
- flag_this_is_variable = -2;
- }
dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep);
@@ -2849,57 +3133,25 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
for (; vbases; vbases = TREE_CHAIN (vbases))
{
tree addr;
- if (use_computed_offsets)
- addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases));
- else
- {
-#if 1
- 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);
-
- /* See is we can get lucky. */
- if (TREE_VIA_VIRTUAL (vbinfo))
- addr = convert_pointer_to_real (vbinfo, vbase_decl_ptr);
- else
- {
- /* We go through all these contortions to avoid this
- call, as it will fail when the virtual base type
- is ambiguous from here. We don't yet have a way
- to search for and find just an instance of the
- virtual base class. Searching for the binfo in
- vbases won't work, as we don't have the vbase
- pointer field, for all vbases in the main class,
- only direct vbases. */
- addr = convert_pointer_to_real (TREE_TYPE (vbases),
- vbase_decl_ptr);
- if (addr == error_mark_node)
- continue;
- }
-#endif
- }
- /* Do all vtables from this virtual base. */
+ addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vbase_decl_ptr);
+
+ /* Do all vtables from this virtual base. */
/* This assumes that virtual bases can never serve as parent
- binfos. (in the CLASSTPE_VFIELD_PARENT sense) */
+ binfos. (in the CLASSTYPE_VFIELD_PARENT sense) */
expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
1, 0, addr);
- /* If we are using computed offsets we can skip fixups. */
- if (use_computed_offsets)
- continue;
-
- /* Now we adjust the offsets for virtual functions that cross
- virtual boundaries on an implicit upcast on vf call so that
- the layout of the most complete type is used, instead of
- assuming the layout of the virtual bases from our current type. */
+ /* Now we adjust the offsets for virtual functions that
+ cross virtual boundaries on an implicit upcast on vf call
+ so that the layout of the most complete type is used,
+ instead of assuming the layout of the virtual bases from
+ our current type. */
if (flag_vtable_thunks)
{
- /* We don't have dynamic thunks yet! So for now, just fail silently. */
+ /* We don't have dynamic thunks yet!
+ So for now, just fail silently. */
}
else
{
@@ -2930,19 +3182,9 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
}
dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
-
- flag_this_is_variable = old_flag;
}
}
-void
-clear_search_slots (type)
- tree type;
-{
- dfs_walk (TYPE_BINFO (type),
- dfs_clear_search_slot, dfs_search_slot_nonempty_p);
-}
-
/* get virtual base class types.
This adds type to the vbase_types list in reverse dfs order.
Ordering is very important, so don't change it. */
@@ -2963,6 +3205,7 @@ dfs_get_vbase_types (binfo)
}
/* get a list of virtual base classes in dfs order. */
+
tree
get_vbase_types (type)
tree type;
@@ -2989,6 +3232,7 @@ get_vbase_types (type)
return vbase_types;
}
+#ifdef MI_MATRIX
static void
dfs_record_inheritance (binfo)
tree binfo;
@@ -3004,6 +3248,11 @@ dfs_record_inheritance (binfo)
tree baseclass = BINFO_TYPE (base_binfo);
mi_boolean *base_row = BINFO_DERIVES_FROM_STAR (base_binfo);
+ if (TREE_CODE (baseclass) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (baseclass) == TEMPLATE_TEMPLATE_PARM)
+ continue;
+ my_friendly_assert (CLASSTYPE_CID (baseclass) != 0, 2365);
+
/* Don't search if there's nothing there! MI_SIZE can be
zero as a result of parse errors. */
if (TYPE_BINFO_BASETYPES (baseclass) && mi_size > 0)
@@ -3045,11 +3294,14 @@ build_mi_matrix (type)
}
#endif
+ dfs_walk (binfo, dfs_number, unnumberedp);
+
mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
+ if (mi_size < (cid-1))
+ mi_size = cid-1;
mi_matrix = (char *)xmalloc ((mi_size + 1) * (mi_size + 1));
mi_type = type;
bzero (mi_matrix, (mi_size + 1) * (mi_size + 1));
- dfs_walk (binfo, dfs_number, unnumberedp);
dfs_walk (binfo, dfs_record_inheritance, unmarkedp);
dfs_walk (binfo, dfs_unmark, markedp);
}
@@ -3067,6 +3319,7 @@ free_mi_matrix ()
cid = 0;
#endif
}
+#endif
/* If we want debug info for a type TYPE, make sure all its base types
are also marked as being potentially interesting. This avoids
@@ -3078,6 +3331,22 @@ note_debug_info_needed (type)
tree type;
{
tree field;
+
+ if (current_template_parms)
+ return;
+
+ if (TYPE_BEING_DEFINED (type))
+ /* We can't go looking for the base types and fields just yet. */
+ return;
+
+ /* We can't do the TYPE_DECL_SUPPRESS_DEBUG thing with DWARF, which
+ does not support name references between translation units. Well, we
+ could, but that would mean putting global labels in the debug output
+ before each exported type and each of its functions and static data
+ members. */
+ if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
+ return;
+
dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp);
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
@@ -3100,7 +3369,13 @@ envelope_add_decl (type, decl, values)
tree name = DECL_NAME (decl);
int dont_add = 0;
- /* virtual base names are always unique. */
+ /* Yet Another Implicit Typename Kludge: Since we don't tsubst
+ the members for partial instantiations, DECL_CONTEXT (decl) is wrong.
+ But pretend it's right for this function. */
+ if (processing_template_decl)
+ type = DECL_REAL_CONTEXT (decl);
+
+ /* virtual base names are always unique. */
if (VBASE_NAME_P (name))
*values = NULL_TREE;
@@ -3121,10 +3396,7 @@ envelope_add_decl (type, decl, values)
warning ("in this context");
}
- context = (TREE_CODE (value) == FUNCTION_DECL
- && DECL_VIRTUAL_P (value))
- ? DECL_CLASS_CONTEXT (value)
- : DECL_CONTEXT (value);
+ context = DECL_REAL_CONTEXT (value);
if (context == type)
{
@@ -3134,7 +3406,17 @@ envelope_add_decl (type, decl, values)
else
dont_add = 1;
}
- else if (context && TYPE_DERIVES_FROM (context, type))
+ else if (type == current_class_type
+#ifdef MI_MATRIX
+ /* If we don't check CLASSTYPE_CID on CONTEXT right now,
+ we'll end up subtracting from the address of MI_MATRIX,
+ putting us off in la la land. */
+ || (CLASSTYPE_CID (type)
+ && TYPE_DERIVES_FROM (context, type))
+#else
+ || DERIVED_FROM_P (context, type)
+#endif
+ )
{
/* Don't add in *values to list */
*values = NULL_TREE;
@@ -3152,7 +3434,17 @@ envelope_add_decl (type, decl, values)
? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value);
- if (context && TYPE_DERIVES_FROM (context, type))
+ if (type == current_class_type
+#ifdef MI_MATRIX
+ /* If we don't check CLASSTYPE_CID on CONTEXT right now,
+ we'll end up subtracting from the address of MI_MATRIX,
+ putting us off in la la land. */
+ || (CLASSTYPE_CID (type)
+ && TYPE_DERIVES_FROM (context, type))
+#else
+ || DERIVED_FROM_P (context, type)
+#endif
+ )
{
/* remove *tmp from list */
*tmp = TREE_CHAIN (*tmp);
@@ -3253,17 +3545,17 @@ dfs_pushdecls (binfo)
}
method_vec = CLASSTYPE_METHOD_VEC (type);
- if (method_vec != 0)
+ if (method_vec)
{
/* Farm out constructors and destructors. */
- methods = &TREE_VEC_ELT (method_vec, 1);
+ methods = &TREE_VEC_ELT (method_vec, 2);
end = TREE_VEC_END (method_vec);
while (methods != end)
{
/* This will cause lookup_name to return a pointer
to the tree_list of possible methods of this name. */
- tree name = DECL_NAME (*methods);
+ tree name = DECL_NAME (OVL_CURRENT (*methods));
tree class_value = IDENTIFIER_CLASS_VALUE (name);
/* If the class value is not an envelope of the kind described in
@@ -3283,7 +3575,11 @@ dfs_pushdecls (binfo)
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));
+ /* Arbitrarily choose the first function in the list. This is OK
+ because this is only used for initial lookup; anything that
+ actually uses the function will look it up again. */
+ envelope_add_decl (type, OVL_CURRENT (*methods),
+ &TREE_PURPOSE (class_value));
pop_obstacks ();
methods++;
@@ -3293,6 +3589,7 @@ dfs_pushdecls (binfo)
}
/* Consolidate unique (by name) member functions. */
+
static void
dfs_compress_decls (binfo)
tree binfo;
@@ -3303,14 +3600,15 @@ dfs_compress_decls (binfo)
if (method_vec != 0)
{
/* Farm out constructors and destructors. */
- tree *methods = &TREE_VEC_ELT (method_vec, 1);
+ tree *methods = &TREE_VEC_ELT (method_vec, 2);
tree *end = TREE_VEC_END (method_vec);
for (; methods != end; methods++)
{
/* This is known to be an envelope of the kind described before
dfs_pushdecls. */
- tree class_value = IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods));
+ tree class_value =
+ IDENTIFIER_CLASS_VALUE (DECL_NAME (OVL_CURRENT (*methods)));
tree tmp = TREE_PURPOSE (class_value);
/* This was replaced in scope by somebody else. Just leave it
@@ -3320,7 +3618,7 @@ dfs_compress_decls (binfo)
if (TREE_CHAIN (tmp) == NULL_TREE
&& TREE_VALUE (tmp)
- && DECL_CHAIN (TREE_VALUE (tmp)) == NULL_TREE)
+ && OVL_NEXT (TREE_VALUE (tmp)) == NULL_TREE)
{
TREE_PURPOSE (class_value) = TREE_VALUE (tmp);
}
@@ -3335,26 +3633,14 @@ dfs_compress_decls (binfo)
with `error_mark_node' so that if they are encountered
without explicit qualification, we can emit an error
message. */
+
void
push_class_decls (type)
tree type;
{
- tree id;
struct obstack *ambient_obstack = current_obstack;
-
search_stack = push_search_level (search_stack, &search_obstack);
- id = TYPE_IDENTIFIER (type);
-#if 0
- if (IDENTIFIER_TEMPLATE (id) != 0)
- {
- tree tmpl = IDENTIFIER_TEMPLATE (id);
- push_template_decls (DECL_ARGUMENTS (TREE_PURPOSE (tmpl)),
- TREE_VALUE (tmpl), 1);
- overload_template_name (id, 1);
- }
-#endif
-
/* Push class fields into CLASS_VALUE scope, and mark. */
dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp);
@@ -3381,7 +3667,31 @@ push_class_decls (type)
{
tree node = TREE_VALUE (new);
- while (TREE_CODE (node) == TREE_LIST)
+ if (TREE_CODE (node) == TYPE_DECL
+ && DECL_ARTIFICIAL (node)
+ && IS_AGGR_TYPE (TREE_TYPE (node))
+ && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (node)))
+ {
+ tree t = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (node));
+ tree n = new;
+
+ for (; n; n = TREE_CHAIN (n))
+ {
+ tree d = TREE_VALUE (n);
+ if (TREE_CODE (d) == TYPE_DECL
+ && DECL_ARTIFICIAL (node)
+ && IS_AGGR_TYPE (TREE_TYPE (d))
+ && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (d))
+ && CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d)) == t)
+ /* OK */;
+ else
+ break;
+ }
+
+ if (n == NULL_TREE)
+ new = t;
+ }
+ else while (TREE_CODE (node) == TREE_LIST)
node = TREE_VALUE (node);
id = DECL_NAME (node);
}
@@ -3402,6 +3712,7 @@ push_class_decls (type)
}
/* Here's a subroutine we need because C lacks lambdas. */
+
static void
dfs_unuse_fields (binfo)
tree binfo;
@@ -3429,8 +3740,7 @@ unuse_fields (type)
}
void
-pop_class_decls (type)
- tree type;
+pop_class_decls ()
{
/* We haven't pushed a search level when dealing with cached classes,
so we'd better not try to pop it. */
@@ -3464,9 +3774,9 @@ print_search_statistics ()
fprintf (stderr, "%d fnfields searched in %d calls to lookup_fnfields\n",
n_outer_fields_searched, n_calls_lookup_fnfields);
fprintf (stderr, "%d calls to get_base_type\n", n_calls_get_base_type);
-#else
+#else /* GATHER_STATISTICS */
fprintf (stderr, "no search statistics\n");
-#endif
+#endif /* GATHER_STATISTICS */
}
void
@@ -3478,7 +3788,7 @@ init_search_processing ()
/* This gives us room to build our chains of basetypes,
whether or not we decide to memoize them. */
- type_stack = push_type_level (0, &type_obstack);
+ type_stack = push_type_level ((struct stack_level *)0, &type_obstack);
_vptr_name = get_identifier ("_vptr");
}
@@ -3494,24 +3804,34 @@ reinit_search_statistics ()
memoized_fast_rejects[1] = 0;
memoized_fields_searched[0] = 0;
memoized_fields_searched[1] = 0;
+#ifdef GATHER_STATISTICS
n_fields_searched = 0;
n_calls_lookup_field = 0, n_calls_lookup_field_1 = 0;
n_calls_lookup_fnfields = 0, n_calls_lookup_fnfields_1 = 0;
n_calls_get_base_type = 0;
n_outer_fields_searched = 0;
n_contexts_saved = 0;
+#endif /* GATHER_STATISTICS */
}
+#define scratch_tree_cons expr_tree_cons
+
static tree conversions;
static void
add_conversions (binfo)
tree binfo;
{
- tree tmp = CLASSTYPE_FIRST_CONVERSION (BINFO_TYPE (binfo));
- for (; tmp && IDENTIFIER_TYPENAME_P (DECL_NAME (tmp));
- tmp = TREE_CHAIN (tmp))
- conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)),
- conversions);
+ int i;
+ tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
+
+ for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
+ {
+ tree tmp = TREE_VEC_ELT (method_vec, i);
+ if (! IDENTIFIER_TYPENAME_P (DECL_NAME (OVL_CURRENT (tmp))))
+ break;
+ conversions = scratch_tree_cons (binfo, tmp, conversions);
+ }
+ SET_BINFO_MARKED (binfo);
}
tree
@@ -3519,6 +3839,135 @@ lookup_conversions (type)
tree type;
{
conversions = NULL_TREE;
- dfs_walk (TYPE_BINFO (type), add_conversions, 0);
+ if (TYPE_SIZE (type))
+ {
+ dfs_walk (TYPE_BINFO (type), add_conversions, unmarkedp);
+ dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp);
+ }
return conversions;
}
+
+/* Subroutine of get_template_base. */
+
+static tree
+get_template_base_recursive (binfo, rval, template, via_virtual)
+ tree binfo, template, rval;
+ int via_virtual;
+{
+ tree binfos;
+ int i, n_baselinks;
+ tree type = BINFO_TYPE (binfo);
+
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && CLASSTYPE_TI_TEMPLATE (type) == template)
+ {
+ if (rval == NULL_TREE || rval == type)
+ return type;
+ else
+ return error_mark_node;
+ }
+
+ binfos = BINFO_BASETYPES (binfo);
+ n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+
+ /* Process base types. */
+ for (i = 0; i < n_baselinks; i++)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+
+ /* Find any specific instance of a virtual base, when searching with
+ a binfo... */
+ if (BINFO_MARKED (base_binfo) == 0)
+ {
+ int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
+
+ /* When searching for a non-virtual, we cannot mark
+ virtually found binfos. */
+ if (! this_virtual)
+ SET_BINFO_MARKED (base_binfo);
+
+ rval = get_template_base_recursive
+ (base_binfo, rval, template, this_virtual);
+ if (rval == error_mark_node)
+ return rval;
+ }
+ }
+
+ return rval;
+}
+
+/* Given a class template TEMPLATE and a class type or binfo node BINFO,
+ find the unique base type in BINFO that is an instance of TEMPLATE.
+ If there are more than one, return error_mark_node. Used by unify. */
+
+tree
+get_template_base (template, binfo)
+ register tree template, binfo;
+{
+ tree type = NULL_TREE, rval;
+
+ if (TREE_CODE (binfo) == TREE_VEC)
+ type = BINFO_TYPE (binfo);
+ else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo)))
+ {
+ type = complete_type (binfo);
+ binfo = TYPE_BINFO (type);
+ }
+ else
+ my_friendly_abort (92);
+
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && CLASSTYPE_TI_TEMPLATE (type) == template)
+ return type;
+
+ rval = get_template_base_recursive (binfo, NULL_TREE, template, 0);
+ dfs_walk (binfo, dfs_unmark, markedp);
+
+ return rval;
+}
+
+/* Check whether the empty class indicated by EMPTY_BINFO is also present
+ at offset 0 in COMPARE_TYPE, and set found_overlap if so. */
+
+static tree compare_type;
+static int found_overlap;
+static void
+dfs_check_overlap (empty_binfo)
+ tree empty_binfo;
+{
+ tree binfo;
+ for (binfo = TYPE_BINFO (compare_type); ; binfo = BINFO_BASETYPE (binfo, 0))
+ {
+ if (BINFO_TYPE (binfo) == BINFO_TYPE (empty_binfo))
+ {
+ found_overlap = 1;
+ break;
+ }
+ else if (BINFO_BASETYPES (binfo) == NULL_TREE)
+ break;
+ }
+}
+
+/* Trivial function to stop base traversal when we find something. */
+
+static int
+dfs_no_overlap_yet (t)
+ tree t ATTRIBUTE_UNUSED;
+{
+ return found_overlap == 0;
+}
+
+/* Returns nonzero if EMPTY_TYPE or any of its bases can also be found at
+ offset 0 in NEXT_TYPE. Used in laying out empty base class subobjects. */
+
+int
+types_overlap_p (empty_type, next_type)
+ tree empty_type, next_type;
+{
+ if (! IS_AGGR_TYPE (next_type))
+ return 0;
+ compare_type = next_type;
+ found_overlap = 0;
+ dfs_walk (TYPE_BINFO (empty_type), dfs_check_overlap, dfs_no_overlap_yet);
+ return found_overlap;
+}
diff --git a/contrib/gcc/cp/semantics.c b/contrib/gcc/cp/semantics.c
new file mode 100644
index 0000000..5068512
--- /dev/null
+++ b/contrib/gcc/cp/semantics.c
@@ -0,0 +1,1393 @@
+/* Perform the semantic phase of parsing, i.e., the process of
+ building tree structure, checking semantic consistency, and
+ building RTL. These routines are used both during actual parsing
+ and during the instantiation of template functions.
+
+ Copyright (C) 1998 Free Software Foundation, Inc.
+ Written by Mark Mitchell (mmitchell@usa.net) based on code found
+ formerly in parse.y and pt.c.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "cp-tree.h"
+#include "except.h"
+#include "lex.h"
+#include "toplev.h"
+
+/* There routines provide a modular interface to perform many parsing
+ operations. They may therefore be used during actual parsing, or
+ during template instantiation, which may be regarded as a
+ degenerate form of parsing. Since the current g++ parser is
+ lacking in several respects, and will be reimplemented, we are
+ attempting to move most code that is not directly related to
+ parsing into this file; that will make implementing the new parser
+ much easier since it will be able to make use of these routines. */
+
+/* When parsing a template, LAST_TREE contains the last statement
+ parsed. These are chained together through the TREE_CHAIN field,
+ but often need to be re-organized since the parse is performed
+ bottom-up. This macro makes LAST_TREE the indicated SUBSTMT of
+ STMT. */
+
+#define RECHAIN_STMTS(stmt, substmt, last) \
+ do { \
+ substmt = last; \
+ TREE_CHAIN (stmt) = NULL_TREE; \
+ last_tree = stmt; \
+ } while (0)
+
+#define RECHAIN_STMTS_FROM_LAST(stmt, substmt) \
+ RECHAIN_STMTS (stmt, substmt, last_tree)
+
+#define RECHAIN_STMTS_FROM_CHAIN(stmt, substmt) \
+ RECHAIN_STMTS (stmt, substmt, TREE_CHAIN (stmt))
+
+/* Finish an expression-statement, whose EXPRESSION is as indicated. */
+
+void
+finish_expr_stmt (expr)
+ tree expr;
+{
+ if (expr != NULL_TREE)
+ {
+ if (!processing_template_decl)
+ {
+ emit_line_note (input_filename, lineno);
+ /* Do default conversion if safe and possibly important,
+ in case within ({...}). */
+ if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
+ && lvalue_p (expr))
+ || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
+ expr = default_conversion (expr);
+ }
+
+ cplus_expand_expr_stmt (expr);
+ clear_momentary ();
+ }
+
+ finish_stmt ();
+}
+
+/* Begin an if-statement. Returns a newly created IF_STMT if
+ appropriate. */
+
+tree
+begin_if_stmt ()
+{
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
+ add_tree (r);
+ }
+ else
+ r = NULL_TREE;
+
+ do_pushlevel ();
+
+ return r;
+}
+
+/* Process the COND of an if-statement, which may be given by
+ IF_STMT. */
+
+void
+finish_if_stmt_cond (cond, if_stmt)
+ tree cond;
+ tree if_stmt;
+{
+ if (processing_template_decl)
+ {
+ if (last_tree != if_stmt)
+ RECHAIN_STMTS_FROM_LAST (if_stmt, IF_COND (if_stmt));
+ else
+ IF_COND (if_stmt) = cond;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_start_cond (condition_conversion (cond), 0);
+ }
+}
+
+/* Finish the then-clause of an if-statement, which may be given by
+ IF_STMT. */
+
+tree
+finish_then_clause (if_stmt)
+ tree if_stmt;
+{
+ if (processing_template_decl)
+ {
+ RECHAIN_STMTS_FROM_CHAIN (if_stmt,
+ THEN_CLAUSE (if_stmt));
+ last_tree = if_stmt;
+ return if_stmt;
+ }
+ else
+ return NULL_TREE;
+}
+
+/* Begin the else-clause of an if-statement. */
+
+void
+begin_else_clause ()
+{
+ if (!processing_template_decl)
+ expand_start_else ();
+}
+
+/* Finish the else-clause of an if-statement, which may be given by
+ IF_STMT. */
+
+void
+finish_else_clause (if_stmt)
+ tree if_stmt;
+{
+ if (processing_template_decl)
+ RECHAIN_STMTS_FROM_CHAIN (if_stmt, ELSE_CLAUSE (if_stmt));
+}
+
+/* Finsh an if-statement. */
+
+void
+finish_if_stmt ()
+{
+ if (!processing_template_decl)
+ expand_end_cond ();
+
+ do_poplevel ();
+ finish_stmt ();
+}
+
+/* Begin a while-statement. Returns a newly created WHILE_STMT if
+ appropriate. */
+
+tree
+begin_while_stmt ()
+{
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
+ add_tree (r);
+ }
+ else
+ {
+ emit_nop ();
+ emit_line_note (input_filename, lineno);
+ expand_start_loop (1);
+ r = NULL_TREE;
+ }
+
+ do_pushlevel ();
+
+ return r;
+}
+
+/* Process the COND of an if-statement, which may be given by
+ WHILE_STMT. */
+
+void
+finish_while_stmt_cond (cond, while_stmt)
+ tree cond;
+ tree while_stmt;
+{
+ if (processing_template_decl)
+ {
+ if (last_tree != while_stmt)
+ RECHAIN_STMTS_FROM_LAST (while_stmt,
+ WHILE_COND (while_stmt));
+ else
+ TREE_OPERAND (while_stmt, 0) = cond;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_exit_loop_if_false (0, condition_conversion (cond));
+ }
+
+ /* If COND wasn't a declaration, clear out the
+ block we made for it and start a new one here so the
+ optimization in expand_end_loop will work. */
+ if (getdecls () == NULL_TREE)
+ {
+ do_poplevel ();
+ do_pushlevel ();
+ }
+}
+
+/* Finish a while-statement, which may be given by WHILE_STMT. */
+
+void
+finish_while_stmt (while_stmt)
+ tree while_stmt;
+{
+ do_poplevel ();
+
+ if (processing_template_decl)
+ RECHAIN_STMTS_FROM_CHAIN (while_stmt, WHILE_BODY (while_stmt));
+ else
+ expand_end_loop ();
+ finish_stmt ();
+}
+
+/* Begin a do-statement. Returns a newly created DO_STMT if
+ appropriate. */
+
+tree
+begin_do_stmt ()
+{
+ if (processing_template_decl)
+ {
+ tree r = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
+ add_tree (r);
+ return r;
+ }
+ else
+ {
+ emit_nop ();
+ emit_line_note (input_filename, lineno);
+ expand_start_loop_continue_elsewhere (1);
+ return NULL_TREE;
+ }
+}
+
+/* Finish the body of a do-statement, which may be given by DO_STMT. */
+
+void
+finish_do_body (do_stmt)
+ tree do_stmt;
+{
+ if (processing_template_decl)
+ RECHAIN_STMTS_FROM_CHAIN (do_stmt, DO_BODY (do_stmt));
+ else
+ expand_loop_continue_here ();
+}
+
+/* Finish a do-statement, which may be given by DO_STMT, and whose
+ COND is as indicated. */
+
+void
+finish_do_stmt (cond, do_stmt)
+ tree cond;
+ tree do_stmt;
+{
+ if (processing_template_decl)
+ DO_COND (do_stmt) = cond;
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_exit_loop_if_false (0, condition_conversion (cond));
+ expand_end_loop ();
+ }
+
+ clear_momentary ();
+ finish_stmt ();
+}
+
+/* Finish a return-statement. The EXPRESSION returned, if any, is as
+ indicated. */
+
+void
+finish_return_stmt (expr)
+ tree expr;
+{
+ emit_line_note (input_filename, lineno);
+ c_expand_return (expr);
+ finish_stmt ();
+}
+
+/* Begin a for-statement. Returns a new FOR_STMT if appropriate. */
+
+tree
+begin_for_stmt ()
+{
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE,
+ NULL_TREE, NULL_TREE);
+ add_tree (r);
+ }
+ else
+ r = NULL_TREE;
+
+ if (flag_new_for_scope > 0)
+ {
+ do_pushlevel ();
+ note_level_for_for ();
+ }
+
+ return r;
+}
+
+/* Finish the for-init-statement of a for-statement, which may be
+ given by FOR_STMT. */
+
+void
+finish_for_init_stmt (for_stmt)
+ tree for_stmt;
+{
+ if (processing_template_decl)
+ {
+ if (last_tree != for_stmt)
+ RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_INIT_STMT (for_stmt));
+ }
+ else
+ {
+ emit_nop ();
+ emit_line_note (input_filename, lineno);
+ expand_start_loop_continue_elsewhere (1);
+ }
+
+ do_pushlevel ();
+}
+
+/* Finish the COND of a for-statement, which may be given by
+ FOR_STMT. */
+
+void
+finish_for_cond (cond, for_stmt)
+ tree cond;
+ tree for_stmt;
+{
+ if (processing_template_decl)
+ {
+ if (last_tree != for_stmt)
+ RECHAIN_STMTS_FROM_LAST (for_stmt, FOR_COND (for_stmt));
+ else
+ FOR_COND (for_stmt) = cond;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ if (cond)
+ expand_exit_loop_if_false (0, condition_conversion (cond));
+ }
+
+ /* If the cond wasn't a declaration, clear out the
+ block we made for it and start a new one here so the
+ optimization in expand_end_loop will work. */
+ if (getdecls () == NULL_TREE)
+ {
+ do_poplevel ();
+ do_pushlevel ();
+ }
+}
+
+/* Finish the increment-EXPRESSION in a for-statement, which may be
+ given by FOR_STMT. */
+
+void
+finish_for_expr (expr, for_stmt)
+ tree expr;
+ tree for_stmt;
+{
+ if (processing_template_decl)
+ FOR_EXPR (for_stmt) = expr;
+
+ /* Don't let the tree nodes for EXPR be discarded
+ by clear_momentary during the parsing of the next stmt. */
+ push_momentary ();
+}
+
+/* Finish the body of a for-statement, which may be given by
+ FOR_STMT. The increment-EXPR for the loop must be
+ provided. */
+
+void
+finish_for_stmt (expr, for_stmt)
+ tree expr;
+ tree for_stmt;
+{
+ /* Pop the scope for the body of the loop. */
+ do_poplevel ();
+
+ if (processing_template_decl)
+ RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_BODY (for_stmt));
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_loop_continue_here ();
+ if (expr)
+ cplus_expand_expr_stmt (expr);
+ expand_end_loop ();
+ }
+
+ pop_momentary ();
+
+ if (flag_new_for_scope > 0)
+ do_poplevel ();
+
+ finish_stmt ();
+}
+
+/* Finish a break-statement. */
+
+void
+finish_break_stmt ()
+{
+ emit_line_note (input_filename, lineno);
+ if (processing_template_decl)
+ add_tree (build_min_nt (BREAK_STMT));
+ else if ( ! expand_exit_something ())
+ cp_error ("break statement not within loop or switch");
+}
+
+/* Finish a continue-statement. */
+
+void
+finish_continue_stmt ()
+{
+ emit_line_note (input_filename, lineno);
+ if (processing_template_decl)
+ add_tree (build_min_nt (CONTINUE_STMT));
+ else if (! expand_continue_loop (0))
+ cp_error ("continue statement not within a loop");
+}
+
+/* Begin a switch-statement. */
+
+void
+begin_switch_stmt ()
+{
+ do_pushlevel ();
+}
+
+/* Finish the cond of a switch-statement. Returns a new
+ SWITCH_STMT if appropriate. */
+
+tree
+finish_switch_cond (cond)
+ tree cond;
+{
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (SWITCH_STMT, cond, NULL_TREE);
+ add_tree (r);
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ c_expand_start_case (cond);
+ r = NULL_TREE;
+ }
+ push_switch ();
+
+ /* Don't let the tree nodes for COND be discarded by
+ clear_momentary during the parsing of the next stmt. */
+ push_momentary ();
+
+ return r;
+}
+
+/* Finish the body of a switch-statement, which may be given by
+ SWITCH_STMT. The COND to switch on is indicated. */
+
+void
+finish_switch_stmt (cond, switch_stmt)
+ tree cond;
+ tree switch_stmt;
+{
+ if (processing_template_decl)
+ RECHAIN_STMTS_FROM_CHAIN (switch_stmt, SWITCH_BODY (switch_stmt));
+ else
+ expand_end_case (cond);
+ pop_momentary ();
+ pop_switch ();
+ do_poplevel ();
+ finish_stmt ();
+}
+
+/* Finish a case-label. */
+
+void
+finish_case_label (low_value, high_value)
+ tree low_value;
+ tree high_value;
+{
+ do_case (low_value, high_value);
+}
+
+
+/* Finish a goto-statement. */
+
+void
+finish_goto_stmt (destination)
+ tree destination;
+{
+ if (processing_template_decl)
+ add_tree (build_min_nt (GOTO_STMT, destination));
+ else
+ {
+ emit_line_note (input_filename, lineno);
+
+ if (TREE_CODE (destination) == IDENTIFIER_NODE)
+ {
+ tree decl = lookup_label (destination);
+ TREE_USED (decl) = 1;
+ expand_goto (decl);
+ }
+ else
+ expand_computed_goto (destination);
+ }
+}
+
+/* Begin a try-block. Returns a newly-created TRY_BLOCK if
+ appropriate. */
+
+tree
+begin_try_block ()
+{
+ if (processing_template_decl)
+ {
+ tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
+ NULL_TREE);
+ add_tree (r);
+ return r;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_start_try_stmts ();
+ return NULL_TREE;
+ }
+}
+
+/* Finish a try-block, which may be given by TRY_BLOCK. */
+
+void
+finish_try_block (try_block)
+ tree try_block;
+{
+ if (processing_template_decl)
+ RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
+ else
+ {
+ expand_start_all_catch ();
+ }
+}
+
+/* Finish a handler-sequence for a try-block, which may be given by
+ TRY_BLOCK. */
+
+void
+finish_handler_sequence (try_block)
+ tree try_block;
+{
+ if (processing_template_decl)
+ RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
+ else
+ {
+ expand_end_all_catch ();
+ }
+}
+
+/* Begin a handler. Returns a HANDLER if appropriate. */
+
+tree
+begin_handler ()
+{
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (HANDLER, NULL_TREE, NULL_TREE);
+ add_tree (r);
+ }
+ else
+ r = NULL_TREE;
+
+ do_pushlevel ();
+
+ return r;
+}
+
+/* Finish the handler-parameters for a handler, which may be given by
+ HANDLER. */
+
+void
+finish_handler_parms (handler)
+ tree handler;
+{
+ if (processing_template_decl)
+ RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_PARMS (handler));
+}
+
+/* Finish a handler, which may be given by HANDLER. */
+
+void
+finish_handler (handler)
+ tree handler;
+{
+ if (processing_template_decl)
+ RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_BODY (handler));
+ else
+ expand_end_catch_block ();
+
+ do_poplevel ();
+}
+
+/* Begin a compound-statement. If HAS_NO_SCOPE is non-zero, the
+ compound-statement does not define a scope. Returns a new
+ COMPOUND_STMT if appropriate. */
+
+tree
+begin_compound_stmt (has_no_scope)
+ int has_no_scope;
+{
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (COMPOUND_STMT, NULL_TREE);
+ add_tree (r);
+ if (has_no_scope)
+ COMPOUND_STMT_NO_SCOPE (r) = 1;
+ }
+ else
+ r = NULL_TREE;
+
+ if (!has_no_scope)
+ do_pushlevel ();
+
+ return r;
+}
+
+
+/* Finish a compound-statement, which may be given by COMPOUND_STMT.
+ If HAS_NO_SCOPE is non-zero, the compound statement does not define
+ a scope. */
+
+tree
+finish_compound_stmt (has_no_scope, compound_stmt)
+ int has_no_scope;
+ tree compound_stmt;
+{
+ tree r;
+
+ if (!has_no_scope)
+ r = do_poplevel ();
+ else
+ r = NULL_TREE;
+
+ if (processing_template_decl)
+ RECHAIN_STMTS_FROM_CHAIN (compound_stmt,
+ COMPOUND_BODY (compound_stmt));
+
+ finish_stmt ();
+
+ return r;
+}
+
+/* Finish an asm-statement, whose components are a CV_QUALIFIER, a
+ STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, and some
+ CLOBBERS. */
+
+void
+finish_asm_stmt (cv_qualifier, string, output_operands,
+ input_operands, clobbers)
+ tree cv_qualifier;
+ tree string;
+ tree output_operands;
+ tree input_operands;
+ tree clobbers;
+{
+ if (TREE_CHAIN (string))
+ string = combine_strings (string);
+
+ if (processing_template_decl)
+ {
+ tree r = build_min_nt (ASM_STMT, cv_qualifier, string,
+ output_operands, input_operands,
+ clobbers);
+ add_tree (r);
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ if (output_operands != NULL_TREE || input_operands != NULL_TREE
+ || clobbers != NULL_TREE)
+ {
+ if (cv_qualifier != NULL_TREE
+ && cv_qualifier != ridpointers[(int) RID_VOLATILE])
+ cp_warning ("%s qualifier ignored on asm",
+ IDENTIFIER_POINTER (cv_qualifier));
+
+ c_expand_asm_operands (string, output_operands,
+ input_operands,
+ clobbers,
+ cv_qualifier
+ == ridpointers[(int) RID_VOLATILE],
+ input_filename, lineno);
+ }
+ else
+ {
+ if (cv_qualifier != NULL_TREE)
+ cp_warning ("%s qualifier ignored on asm",
+ IDENTIFIER_POINTER (cv_qualifier));
+ expand_asm (string);
+ }
+
+ finish_stmt ();
+ }
+}
+
+/* Finish a parenthesized expression EXPR. */
+
+tree
+finish_parenthesized_expr (expr)
+ tree expr;
+{
+ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expr))))
+ /* This inhibits warnings in truthvalue_conversion. */
+ C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK);
+
+ return expr;
+}
+
+/* Begin a statement-expression. The value returned must be passed to
+ finish_stmt_expr. */
+
+tree
+begin_stmt_expr ()
+{
+ keep_next_level ();
+ /* If we're processing_template_decl, then the upcoming compound
+ statement will be chained onto the tree structure, starting at
+ last_tree. We return last_tree so that we can later unhook the
+ compound statement. */
+ return processing_template_decl ? last_tree : expand_start_stmt_expr();
+}
+
+/* Finish a statement-expression. RTL_EXPR should be the value
+ returned by the previous begin_stmt_expr; EXPR is the
+ statement-expression. Returns an expression representing the
+ statement-expression. */
+
+tree
+finish_stmt_expr (rtl_expr, expr)
+ tree rtl_expr;
+ tree expr;
+{
+ tree result;
+
+ if (!processing_template_decl)
+ {
+ rtl_expr = expand_end_stmt_expr (rtl_expr);
+ /* The statements have side effects, so the group does. */
+ TREE_SIDE_EFFECTS (rtl_expr) = 1;
+ }
+
+ if (TREE_CODE (expr) == BLOCK)
+ {
+ /* Make a BIND_EXPR for the BLOCK already made. */
+ if (processing_template_decl)
+ result = build (BIND_EXPR, NULL_TREE,
+ NULL_TREE, last_tree, expr);
+ else
+ result = build (BIND_EXPR, TREE_TYPE (rtl_expr),
+ NULL_TREE, rtl_expr, expr);
+
+ /* Remove the block from the tree at this point.
+ It gets put back at the proper place
+ when the BIND_EXPR is expanded. */
+ delete_block (expr);
+ }
+ else
+ result = expr;
+
+ if (processing_template_decl)
+ {
+ /* Remove the compound statement from the tree structure; it is
+ now saved in the BIND_EXPR. */
+ last_tree = rtl_expr;
+ TREE_CHAIN (last_tree) = NULL_TREE;
+ }
+
+ return result;
+}
+
+/* Finish a call to FN with ARGS. Returns a representation of the
+ call. */
+
+tree
+finish_call_expr (fn, args, koenig)
+ tree fn;
+ tree args;
+ int koenig;
+{
+ tree result;
+
+ if (koenig)
+ {
+ if (TREE_CODE (fn) == BIT_NOT_EXPR)
+ fn = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND (fn, 0));
+ else if (TREE_CODE (fn) != TEMPLATE_ID_EXPR)
+ fn = do_identifier (fn, 2, args);
+ }
+ result = build_x_function_call (fn, args, current_class_ref);
+
+ if (TREE_CODE (result) == CALL_EXPR
+ && TREE_TYPE (result) != void_type_node)
+ result = require_complete_type (result);
+
+ return result;
+}
+
+/* Finish a call to a postfix increment or decrement or EXPR. (Which
+ is indicated by CODE, which should be POSTINCREMENT_EXPR or
+ POSTDECREMENT_EXPR.) */
+
+tree
+finish_increment_expr (expr, code)
+ tree expr;
+ enum tree_code code;
+{
+ /* If we get an OFFSET_REF, turn it into what it really means (e.g.,
+ a COMPONENT_REF). This way if we've got, say, a reference to a
+ static member that's being operated on, we don't end up trying to
+ find a member operator for the class it's in. */
+
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
+ return build_x_unary_op (code, expr);
+}
+
+/* Finish a use of `this'. Returns an expression for `this'. */
+
+tree
+finish_this_expr ()
+{
+ tree result;
+
+ if (current_class_ptr)
+ {
+#ifdef WARNING_ABOUT_CCD
+ TREE_USED (current_class_ptr) = 1;
+#endif
+ result = current_class_ptr;
+ }
+ else if (current_function_decl
+ && DECL_STATIC_FUNCTION_P (current_function_decl))
+ {
+ error ("`this' is unavailable for static member functions");
+ result = error_mark_node;
+ }
+ else
+ {
+ if (current_function_decl)
+ error ("invalid use of `this' in non-member function");
+ else
+ error ("invalid use of `this' at top level");
+ result = error_mark_node;
+ }
+
+ return result;
+}
+
+/* Finish a member function call using OBJECT and ARGS as arguments to
+ FN. Returns an expression for the call. */
+
+tree
+finish_object_call_expr (fn, object, args)
+ tree fn;
+ tree object;
+ tree args;
+{
+#if 0
+ /* This is a future direction of this code, but because
+ build_x_function_call cannot always undo what is done in
+ build_component_ref entirely yet, we cannot do this. */
+
+ tree real_fn = build_component_ref (object, fn, NULL_TREE, 1);
+ return finish_call_expr (real_fn, args);
+#else
+ if (TREE_CODE (fn) == TYPE_DECL)
+ {
+ if (processing_template_decl)
+ /* This can happen on code like:
+
+ class X;
+ template <class T> void f(T t) {
+ t.X();
+ }
+
+ We just grab the underlying IDENTIFIER. */
+ fn = DECL_NAME (fn);
+ else
+ {
+ cp_error ("calling type `%T' like a method", fn);
+ return error_mark_node;
+ }
+ }
+
+ return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
+#endif
+}
+
+/* Finish a qualified member function call using OBJECT and ARGS as
+ arguments to FN. Returns an expressino for the call. */
+
+tree
+finish_qualified_object_call_expr (fn, object, args)
+ tree fn;
+ tree object;
+ tree args;
+{
+ if (IS_SIGNATURE (TREE_OPERAND (fn, 0)))
+ {
+ warning ("signature name in scope resolution ignored");
+ return finish_object_call_expr (TREE_OPERAND (fn, 1), object, args);
+ }
+ else
+ return build_scoped_method_call (object, TREE_OPERAND (fn, 0),
+ TREE_OPERAND (fn, 1), args);
+}
+
+/* Finish a pseudo-destructor call expression of OBJECT, with SCOPE
+ being the scope, if any, of DESTRUCTOR. Returns an expression for
+ the call. */
+
+tree
+finish_pseudo_destructor_call_expr (object, scope, destructor)
+ tree object;
+ tree scope;
+ tree destructor;
+{
+ if (scope && scope != destructor)
+ cp_error ("destructor specifier `%T::~%T()' must have matching names",
+ scope, destructor);
+
+ if ((scope == NULL_TREE || IDENTIFIER_GLOBAL_VALUE (destructor))
+ && (TREE_CODE (TREE_TYPE (object)) !=
+ TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (destructor)))))
+ cp_error ("`%E' is not of type `%T'", object, destructor);
+
+ return cp_convert (void_type_node, object);
+}
+
+/* Finish a call to a globally qualified member function FN using
+ ARGS. Returns an expression for the call. */
+
+tree
+finish_globally_qualified_member_call_expr (fn, args)
+ tree fn;
+ tree args;
+{
+ if (processing_template_decl)
+ return build_min_nt (CALL_EXPR, copy_to_permanent (fn), args,
+ NULL_TREE);
+ else
+ return build_member_call (TREE_OPERAND (fn, 0),
+ TREE_OPERAND (fn, 1),
+ args);
+}
+
+/* Finish an expression taking the address of LABEL. Returns an
+ expression for the address. */
+
+tree
+finish_label_address_expr (label)
+ tree label;
+{
+ tree result;
+
+ label = lookup_label (label);
+ if (label == NULL_TREE)
+ result = null_pointer_node;
+ else
+ {
+ TREE_USED (label) = 1;
+ result = build1 (ADDR_EXPR, ptr_type_node, label);
+ TREE_CONSTANT (result) = 1;
+ }
+
+ return result;
+}
+
+/* Finish an expression of the form CODE EXPR. */
+
+tree
+finish_unary_op_expr (code, expr)
+ enum tree_code code;
+ tree expr;
+{
+ tree result = build_x_unary_op (code, expr);
+ if (code == NEGATE_EXPR && TREE_CODE (expr) == INTEGER_CST)
+ TREE_NEGATED_INT (result) = 1;
+ overflow_warning (result);
+ return result;
+}
+
+/* Finish an id-expression. */
+
+tree
+finish_id_expr (expr)
+ tree expr;
+{
+ if (TREE_CODE (expr) == IDENTIFIER_NODE)
+ expr = do_identifier (expr, 1, NULL_TREE);
+
+ return expr;
+}
+
+/* Begin a new-placement. */
+
+int
+begin_new_placement ()
+{
+ /* The arguments to a placement new might be passed to a
+ deallocation function, in the event that the allocation throws an
+ exception. Since we don't expand exception handlers until the
+ end of a function, we must make sure the arguments stay around
+ that long. */
+ return suspend_momentary ();
+}
+
+/* Finish a new-placement. The ARGS are the placement arguments. The
+ COOKIE is the value returned by the previous call to
+ begin_new_placement. */
+
+tree
+finish_new_placement (args, cookie)
+ tree args;
+ int cookie;
+{
+ resume_momentary (cookie);
+ return args;
+}
+
+/* Begin a function defniition declared with DECL_SPECS and
+ DECLARATOR. Returns non-zero if the function-declaration is
+ legal. */
+
+int
+begin_function_definition (decl_specs, declarator)
+ tree decl_specs;
+ tree declarator;
+{
+ tree specs;
+ tree attrs;
+ split_specs_attrs (decl_specs, &specs, &attrs);
+ if (!start_function (specs, declarator, attrs, 0))
+ return 0;
+
+ reinit_parse_for_function ();
+ return 1;
+}
+
+/* Begin a constructor declarator of the form `SCOPE::NAME'. Returns
+ a SCOPE_REF. */
+
+tree
+begin_constructor_declarator (scope, name)
+ tree scope;
+ tree name;
+{
+ tree result = build_parse_node (SCOPE_REF, scope, name);
+
+ if (scope != current_class_type)
+ {
+ push_nested_class (scope, 3);
+ TREE_COMPLEXITY (result) = current_class_depth;
+ }
+
+ return result;
+}
+
+/* Finish an init-declarator. Returns a DECL. */
+
+tree
+finish_declarator (declarator, declspecs, attributes,
+ prefix_attributes, initialized)
+ tree declarator;
+ tree declspecs;
+ tree attributes;
+ tree prefix_attributes;
+ int initialized;
+{
+ return start_decl (declarator, declspecs, initialized, attributes,
+ prefix_attributes);
+}
+
+/* Finish a translation unit. */
+
+void
+finish_translation_unit ()
+{
+ /* In case there were missing closebraces,
+ get us back to the global binding level. */
+ while (! toplevel_bindings_p ())
+ poplevel (0, 0, 0);
+ while (current_namespace != global_namespace)
+ pop_namespace ();
+ finish_file ();
+}
+
+/* Finish a template type parameter, specified as AGGR IDENTIFIER.
+ Returns the parameter. */
+
+tree
+finish_template_type_parm (aggr, identifier)
+ tree aggr;
+ tree identifier;
+{
+ if (aggr == signature_type_node)
+ sorry ("signature as template type parameter");
+ else if (aggr != class_type_node)
+ {
+ pedwarn ("template type parameters must use the keyword `class' or `typename'");
+ aggr = class_type_node;
+ }
+
+ return build_tree_list (aggr, identifier);
+}
+
+/* Finish a template template parameter, specified as AGGR IDENTIFIER.
+ Returns the parameter. */
+
+tree
+finish_template_template_parm (aggr, identifier)
+ tree aggr;
+ tree identifier;
+{
+ tree decl = build_decl (TYPE_DECL, identifier, NULL_TREE);
+ tree tmpl = build_lang_decl (TEMPLATE_DECL, identifier, NULL_TREE);
+ DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
+ DECL_TEMPLATE_RESULT (tmpl) = decl;
+ SET_DECL_ARTIFICIAL (decl);
+ end_template_decl ();
+
+ return finish_template_type_parm (aggr, tmpl);
+}
+
+/* Finish a parameter list, indicated by PARMS. If ELLIPSIS is
+ non-zero, the parameter list was terminated by a `...'. */
+
+tree
+finish_parmlist (parms, ellipsis)
+ tree parms;
+ int ellipsis;
+{
+ if (!ellipsis)
+ chainon (parms, void_list_node);
+ /* We mark the PARMS as a parmlist so that declarator processing can
+ disambiguate certain constructs. */
+ if (parms != NULL_TREE)
+ TREE_PARMLIST (parms) = 1;
+
+ return parms;
+}
+
+/* Begin a class definition, as indicated by T. */
+
+tree
+begin_class_definition (t)
+ tree t;
+{
+ tree new_type = t;
+
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
+ if (t == error_mark_node
+ || ! IS_AGGR_TYPE (t))
+ {
+ t = new_type = make_lang_type (RECORD_TYPE);
+ pushtag (make_anon_name (), t, 0);
+ }
+ if (TYPE_SIZE (t))
+ duplicate_tag_error (t);
+ if (TYPE_SIZE (t) || TYPE_BEING_DEFINED (t))
+ {
+ t = make_lang_type (TREE_CODE (t));
+ pushtag (TYPE_IDENTIFIER (t), t, 0);
+ new_type = t;
+ }
+ if (processing_template_decl && TYPE_CONTEXT (t)
+ && TREE_CODE (TYPE_CONTEXT (t)) != NAMESPACE_DECL
+ && ! current_class_type)
+ push_template_decl (TYPE_STUB_DECL (t));
+ pushclass (t, 0);
+ TYPE_BEING_DEFINED (t) = 1;
+ if (IS_AGGR_TYPE (t) && CLASSTYPE_USE_TEMPLATE (t))
+ {
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (t)
+ && TYPE_SIZE (t) == NULL_TREE)
+ {
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
+ if (processing_template_decl)
+ push_template_decl (TYPE_MAIN_DECL (t));
+ }
+ else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
+ cp_error ("specialization after instantiation of `%T'", t);
+ }
+ /* Reset the interface data, at the earliest possible
+ moment, as it might have been set via a class foo;
+ before. */
+ /* Don't change signatures. */
+ if (! IS_SIGNATURE (t))
+ {
+ extern tree pending_vtables;
+ int needs_writing;
+ tree name = TYPE_IDENTIFIER (t);
+
+ if (! ANON_AGGRNAME_P (name))
+ {
+ CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
+ SET_CLASSTYPE_INTERFACE_UNKNOWN_X
+ (t, interface_unknown);
+ }
+
+ /* Record how to set the access of this class's
+ virtual functions. If write_virtuals == 2 or 3, then
+ inline virtuals are ``extern inline''. */
+ switch (write_virtuals)
+ {
+ case 0:
+ case 1:
+ needs_writing = 1;
+ break;
+ case 2:
+ needs_writing = !! value_member (name, pending_vtables);
+ break;
+ case 3:
+ needs_writing = ! CLASSTYPE_INTERFACE_ONLY (t)
+ && CLASSTYPE_INTERFACE_KNOWN (t);
+ break;
+ default:
+ needs_writing = 0;
+ }
+ CLASSTYPE_VTABLE_NEEDS_WRITING (t) = needs_writing;
+ }
+#if 0
+ t = TYPE_IDENTIFIER ($<ttype>0);
+ if (t && IDENTIFIER_TEMPLATE (t))
+ overload_template_name (t, 1);
+#endif
+ reset_specialization();
+
+ /* In case this is a local class within a template
+ function, we save the current tree structure so
+ that we can get it back later. */
+ begin_tree ();
+
+ return new_type;
+}
+
+/* Finish a class definition T, with the indicated COMPONENTS, and
+ with the indicate ATTRIBUTES. If SEMI, the definition is
+ immediately followed by a semicolon. Returns the type. */
+
+tree
+finish_class_definition (t, components, attributes, semi)
+ tree t;
+ tree components;
+ tree attributes;
+ int semi;
+{
+#if 0
+ /* Need to rework class nesting in the presence of nested classes,
+ etc. */
+ shadow_tag (CLASSTYPE_AS_LIST (t)); */
+#endif
+
+ /* finish_struct nukes this anyway; if finish_exception does too,
+ then it can go. */
+ if (semi)
+ note_got_semicolon (t);
+
+ /* If we got any attributes in class_head, xref_tag will stick them in
+ TREE_TYPE of the type. Grab them now. */
+ attributes = chainon (TREE_TYPE (t), attributes);
+ TREE_TYPE (t) = NULL_TREE;
+
+ if (TREE_CODE (t) == ENUMERAL_TYPE)
+ ;
+ else
+ {
+ t = finish_struct (t, components, attributes, semi);
+ if (semi)
+ note_got_semicolon (t);
+ }
+
+ pop_obstacks ();
+
+ if (! semi)
+ check_for_missing_semicolon (t);
+ if (current_scope () == current_function_decl)
+ do_pending_defargs ();
+
+ return t;
+}
+
+/* Finish processing the default argument expressions cached during
+ the processing of a class definition. */
+
+void
+finish_default_args ()
+{
+ if (pending_inlines
+ && current_scope () == current_function_decl)
+ do_pending_inlines ();
+}
+
+/* Finish processing the inline function definitions cached during the
+ processing of a class definition. */
+
+void
+begin_inline_definitions ()
+{
+ if (current_class_type == NULL_TREE)
+ clear_inline_text_obstack ();
+
+ /* Undo the begin_tree in begin_class_definition. */
+ end_tree ();
+}
+
+/* Finish processing the declaration of a member class template
+ TYPES whose template parameters are given by PARMS. */
+
+tree
+finish_member_class_template (parms, types)
+ tree parms;
+ tree types;
+{
+ note_list_got_semicolon (types);
+ grok_x_components (types, NULL_TREE);
+ if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
+ /* The component was in fact a friend declaration. We avoid
+ finish_member_template_decl performing certain checks by
+ unsetting TYPES. */
+ types = NULL_TREE;
+ finish_member_template_decl (parms, types);
+ /* As with other component type declarations, we do
+ not store the new DECL on the list of
+ component_decls. */
+ return NULL_TREE;
+}
diff --git a/contrib/gcc/cp/sig.c b/contrib/gcc/cp/sig.c
index 135dc6d..65350db 100644
--- a/contrib/gcc/cp/sig.c
+++ b/contrib/gcc/cp/sig.c
@@ -1,5 +1,5 @@
/* Functions dealing with signatures and signature pointers/references.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
Contributed by Gerald Baumgartner (gb@cs.purdue.edu)
This file is part of GNU CC.
@@ -21,21 +21,34 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
-#include <stdio.h>
+#include "system.h"
#include "obstack.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
#include "assert.h"
+#include "toplev.h"
extern struct obstack *current_obstack;
extern struct obstack permanent_obstack;
extern struct obstack *saveable_obstack;
-extern void error ();
-extern void sorry ();
extern void compiler_error ();
-extern void make_decl_rtl PROTO((tree, char *, int));
+
+static tree save_this PROTO((tree));
+static tree build_sptr_ref PROTO((tree));
+static tree build_member_function_pointer PROTO((tree));
+static void undo_casts PROTO((tree));
+static tree build_signature_pointer_or_reference_name
+ PROTO((tree, int, int, int));
+static void build_signature_pointer_or_reference_decl
+ PROTO((tree, tree));
+static tree build_signature_pointer_or_reference_type
+ PROTO((tree, int, int, int));
+static tree get_sigtable_name PROTO((tree, tree));
+static tree build_signature_table_constructor PROTO((tree, tree));
+static int match_method_types PROTO((tree, tree));
+static tree build_sigtable PROTO((tree, tree, tree));
/* Used to help generate globally unique names for signature tables. */
@@ -153,8 +166,7 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
const s * sptr;
};
- Similarly, for `volatile' and `const volatile'.
- */
+ Similarly, for `volatile' and `const volatile'. */
t = make_lang_type (RECORD_TYPE);
{
@@ -185,7 +197,10 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
TREE_CHAIN (optr) = sptr;
TYPE_FIELDS (t) = optr;
- TYPE_ALIGN (t) = TYPE_ALIGN (optr_type);
+ /* Allow signature pointers/references to be grabbed 2 words at a time.
+ For this to work on a Sparc, we need 8-byte alignment. */
+ TYPE_ALIGN (t) = MAX (TYPE_ALIGN (double_type_node),
+ TYPE_ALIGN (optr_type));
/* A signature pointer/reference type isn't a `real' class type. */
IS_AGGR_TYPE (t) = 0;
@@ -336,7 +351,7 @@ append_signature_fields (list_of_fieldlists)
tree l, x;
tree last_x = NULL_TREE;
tree mfptr;
- tree last_mfptr;
+ tree last_mfptr = NULL_TREE;
tree mfptr_list = NULL_TREE;
/* For signatures it should actually be only a list with one element. */
@@ -396,8 +411,8 @@ match_method_types (sig_mtype, class_mtype)
/* Compare the first argument `this.' */
{
/* Get the type of what the `optr' is pointing to. */
- tree sig_this =
- TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (sig_arg_types))));
+ tree sig_this
+ = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (sig_arg_types))));
tree class_this = TREE_VALUE (class_arg_types);
if (TREE_CODE (class_this) == RECORD_TYPE) /* Is `this' a sig ptr? */
@@ -420,6 +435,7 @@ match_method_types (sig_mtype, class_mtype)
}
/* Undo casts of opaque type variables to the RHS types. */
+
static void
undo_casts (sig_ty)
tree sig_ty;
@@ -446,7 +462,7 @@ build_signature_table_constructor (sig_ty, rhs)
tree sig_field = TYPE_FIELDS (sig_ty);
tree result = NULL_TREE;
tree first_rhs_field = NULL_TREE;
- tree last_rhs_field;
+ tree last_rhs_field = NULL_TREE;
int sig_ptr_p = IS_SIGNATURE (rhstype);
int offset_p = sig_ptr_p;
@@ -516,25 +532,26 @@ build_signature_table_constructor (sig_ty, rhs)
else
{
/* Find the class method of the correct type. */
-
+ tree rhs_methods;
basetypes = TREE_PURPOSE (baselink);
if (TREE_CODE (basetypes) == TREE_LIST)
basetypes = TREE_VALUE (basetypes);
- rhs_method = TREE_VALUE (baselink);
- for (; rhs_method; rhs_method = TREE_CHAIN (rhs_method))
- if (sig_mname == DECL_NAME (rhs_method)
+ rhs_methods = TREE_VALUE (baselink);
+ for (; rhs_methods; rhs_methods = OVL_NEXT (rhs_methods))
+ if ((rhs_method = OVL_CURRENT (rhs_methods))
+ && sig_mname == DECL_NAME (rhs_method)
&& ! DECL_STATIC_FUNCTION_P (rhs_method)
&& match_method_types (sig_mtype, TREE_TYPE (rhs_method)))
break;
- if (rhs_method == NULL_TREE
+ if (rhs_methods == NULL_TREE
|| (compute_access (basetypes, rhs_method)
- != access_public))
+ != access_public_node))
{
error ("class `%s' does not contain a method conforming to `%s'",
TYPE_NAME_STRING (rhstype),
- fndecl_as_string (NULL, sig_method, 1));
+ fndecl_as_string (sig_method, 1));
undo_casts (sig_ty);
return error_mark_node;
}
@@ -559,7 +576,7 @@ build_signature_table_constructor (sig_ty, rhs)
}
else
{
- tree tag, vb_off, delta, index, pfn, vt_off;
+ tree tag, vb_off, delta, idx, pfn = NULL_TREE, vt_off = NULL_TREE;
tree tag_decl, vb_off_decl, delta_decl, index_decl;
tree pfn_decl, vt_off_decl;
@@ -569,8 +586,9 @@ build_signature_table_constructor (sig_ty, rhs)
tag = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
delta = integer_zero_node;
- index = integer_zero_node;
- pfn = build_unary_op (ADDR_EXPR, rhs_method, 0);
+ idx = integer_zero_node;
+ pfn = build_addr_func (rhs_method);
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1;
TREE_TYPE (pfn) = ptr_type_node;
TREE_ADDRESSABLE (rhs_method) = 1;
offset_p = 0; /* we can't offset the rhs sig table */
@@ -580,9 +598,13 @@ build_signature_table_constructor (sig_ty, rhs)
/* virtual member function */
tag = integer_one_node;
vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
- delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method),
- rhstype, 1));
- index = DECL_VINDEX (rhs_method);
+ if (flag_vtable_thunks)
+ delta = BINFO_OFFSET
+ (get_binfo (DECL_CONTEXT (rhs_method), rhstype, 1));
+ else
+ delta = BINFO_OFFSET
+ (get_binfo (DECL_CLASS_CONTEXT (rhs_method), rhstype, 1));
+ idx = DECL_VINDEX (rhs_method);
vt_off = get_vfield_offset (get_binfo (DECL_CONTEXT (rhs_method),
rhstype, 0));
}
@@ -593,8 +615,9 @@ build_signature_table_constructor (sig_ty, rhs)
vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method),
rhstype, 1));
- index = integer_zero_node;
- pfn = build_unary_op (ADDR_EXPR, rhs_method, 0);
+ idx = integer_zero_node;
+ pfn = build_addr_func (rhs_method);
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1;
TREE_TYPE (pfn) = ptr_type_node;
TREE_ADDRESSABLE (rhs_method) = 1;
}
@@ -609,25 +632,25 @@ build_signature_table_constructor (sig_ty, rhs)
pfn_decl = TREE_CHAIN (index_decl);
vt_off_decl = TREE_CHAIN (pfn_decl);
- tag = convert (TREE_TYPE (tag_decl), tag);
- vb_off = convert (TREE_TYPE (vb_off_decl), vb_off);
- delta = convert (TREE_TYPE (delta_decl), delta);
- index = convert (TREE_TYPE (index_decl), index);
+ tag = cp_convert (TREE_TYPE (tag_decl), tag);
+ vb_off = cp_convert (TREE_TYPE (vb_off_decl), vb_off);
+ delta = cp_convert (TREE_TYPE (delta_decl), delta);
+ idx = cp_convert (TREE_TYPE (index_decl), idx);
if (DECL_VINDEX (rhs_method))
{
- vt_off = convert (TREE_TYPE (vt_off_decl), vt_off);
+ vt_off = cp_convert (TREE_TYPE (vt_off_decl), vt_off);
tbl_entry = build_tree_list (vt_off_decl, vt_off);
}
else
{
- pfn = convert (TREE_TYPE (pfn_decl), pfn);
+ pfn = cp_convert (TREE_TYPE (pfn_decl), pfn);
tbl_entry = build_tree_list (pfn_decl, pfn);
}
tbl_entry = tree_cons (delta_decl, delta,
- tree_cons (index_decl, index, tbl_entry));
+ tree_cons (index_decl, idx, tbl_entry));
tbl_entry = tree_cons (tag_decl, tag,
tree_cons (vb_off_decl, vb_off, tbl_entry));
tbl_entry = build (CONSTRUCTOR, sigtable_entry_type,
@@ -703,7 +726,7 @@ build_sigtable (sig_type, rhs_type, init_from)
}
if (decl == NULL_TREE)
{
- tree init;
+ tree init = NULL_TREE;
/* We allow only one signature table to be generated for signatures
with opaque types. Otherwise we create a loophole in the type
@@ -732,7 +755,7 @@ build_sigtable (sig_type, rhs_type, init_from)
decl = pushdecl_top_level (build_decl (VAR_DECL, name, sig_type));
current_function_decl = context;
}
- IDENTIFIER_GLOBAL_VALUE (name) = decl;
+ SET_IDENTIFIER_GLOBAL_VALUE (name, decl);
store_init_value (decl, init_expr);
if (IS_SIGNATURE (rhs_type))
{
@@ -779,9 +802,9 @@ build_signature_pointer_constructor (lhs, rhs)
if (! ((TREE_CODE (rhstype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (rhstype)) == RECORD_TYPE)
- || (TYPE_LANG_SPECIFIC (rhstype) &&
- (IS_SIGNATURE_POINTER (rhstype)
- || IS_SIGNATURE_REFERENCE (rhstype)))))
+ || (TYPE_LANG_SPECIFIC (rhstype)
+ && (IS_SIGNATURE_POINTER (rhstype)
+ || IS_SIGNATURE_REFERENCE (rhstype)))))
{
error ("invalid assignment to signature pointer or reference");
return error_mark_node;
@@ -803,8 +826,8 @@ build_signature_pointer_constructor (lhs, rhs)
saveable_obstack = &permanent_obstack;
}
- if (TYPE_LANG_SPECIFIC (rhstype) &&
- (IS_SIGNATURE_POINTER (rhstype) || IS_SIGNATURE_REFERENCE (rhstype)))
+ if (TYPE_LANG_SPECIFIC (rhstype)
+ && (IS_SIGNATURE_POINTER (rhstype) || IS_SIGNATURE_REFERENCE (rhstype)))
{
if (SIGNATURE_TYPE (rhstype) == sig_ty)
{
@@ -859,7 +882,6 @@ build_signature_pointer_constructor (lhs, rhs)
result = tree_cons (NULL_TREE, optr_expr,
build_tree_list (NULL_TREE, sptr_expr));
result = build_nt (CONSTRUCTOR, NULL_TREE, result);
- TREE_HAS_CONSTRUCTOR (result) = 1;
result = digest_init (lhstype, result, 0);
}
else
@@ -910,22 +932,24 @@ save_this (instance)
/* Build a signature member function call. Looks up the signature table
entry corresponding to FUNCTION. Depending on the value of the CODE
field, either call the function in PFN directly, or use OFFSET to
- index INSTANCE's virtual function table. */
+ index the object's virtual function table. */
tree
-build_signature_method_call (basetype, instance, function, parms)
- tree basetype, instance, function, parms;
+build_signature_method_call (function, parms)
+ tree function, parms;
{
+ tree instance = TREE_VALUE (parms);
tree saved_instance = save_this (instance); /* Create temp for `this'. */
tree object_ptr = build_optr_ref (saved_instance);
tree new_object_ptr, new_parms;
tree signature_tbl_ptr = build_sptr_ref (saved_instance);
tree sig_field_name = DECL_NAME (DECL_MEMFUNC_POINTER_TO (function));
+ tree basetype = DECL_CONTEXT (function);
tree basetype_path = TYPE_BINFO (basetype);
tree tbl_entry = build_component_ref (build1 (INDIRECT_REF, basetype,
signature_tbl_ptr),
sig_field_name, basetype_path, 1);
- tree tag, delta, pfn, vt_off, index, vfn;
+ tree tag, delta, pfn, vt_off, idx, vfn;
tree deflt_call = NULL_TREE, direct_call, virtual_call, result;
tbl_entry = save_expr (tbl_entry);
@@ -933,7 +957,7 @@ build_signature_method_call (basetype, instance, function, parms)
delta = build_component_ref (tbl_entry, delta_identifier, NULL_TREE, 1);
pfn = build_component_ref (tbl_entry, pfn_identifier, NULL_TREE, 1);
vt_off = build_component_ref (tbl_entry, vt_off_identifier, NULL_TREE, 1);
- index = build_component_ref (tbl_entry, index_identifier, NULL_TREE, 1);
+ idx = build_component_ref (tbl_entry, index_identifier, NULL_TREE, 1);
TREE_TYPE (pfn) = build_pointer_type (TREE_TYPE (function));
if (IS_DEFAULT_IMPLEMENTATION (function))
@@ -943,11 +967,11 @@ build_signature_method_call (basetype, instance, function, parms)
}
new_object_ptr = build (PLUS_EXPR, build_pointer_type (basetype),
- convert (ptrdiff_type_node, object_ptr),
- convert (ptrdiff_type_node, delta));
+ cp_convert (ptrdiff_type_node, object_ptr),
+ cp_convert (ptrdiff_type_node, delta));
parms = tree_cons (NULL_TREE,
- convert (build_pointer_type (basetype), object_ptr),
+ cp_convert (build_pointer_type (basetype), object_ptr),
TREE_CHAIN (parms));
new_parms = tree_cons (NULL_TREE, new_object_ptr, TREE_CHAIN (parms));
@@ -955,10 +979,10 @@ build_signature_method_call (basetype, instance, function, parms)
/* Cast the signature method to have `this' of a normal pointer type. */
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 (build_pointer_type (basetype),
- TYPE_READONLY (old_this),
- TYPE_VOLATILE (old_this));
+ TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))))
+ = build_type_variant (build_pointer_type (basetype),
+ TYPE_READONLY (old_this),
+ TYPE_VOLATILE (old_this));
direct_call = build_function_call (pfn, new_parms);
@@ -967,23 +991,20 @@ build_signature_method_call (basetype, instance, function, parms)
vfld = build (PLUS_EXPR,
build_pointer_type (build_pointer_type (vtbl_type_node)),
- convert (ptrdiff_type_node, object_ptr),
- convert (ptrdiff_type_node, vt_off));
+ cp_convert (ptrdiff_type_node, object_ptr),
+ cp_convert (ptrdiff_type_node, vt_off));
vtbl = build_indirect_ref (build_indirect_ref (vfld, NULL_PTR),
NULL_PTR);
- aref = build_array_ref (vtbl, index);
+ aref = build_array_ref (vtbl, idx);
if (flag_vtable_thunks)
vfn = aref;
else
- vfn = build_component_ref (aref, pfn_identifier, 0, 0);
+ vfn = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function));
- if (flag_vtable_thunks)
- virtual_call = build_function_call (vfn, parms);
- else
- virtual_call = build_function_call (vfn, new_parms);
+ virtual_call = build_function_call (vfn, new_parms);
}
/* Undo the cast, make `this' a signature pointer again. */
@@ -998,7 +1019,7 @@ build_signature_method_call (basetype, instance, function, parms)
&& (!deflt_call || deflt_call == error_mark_node)))
{
compiler_error ("cannot build call of signature member function `%s'",
- fndecl_as_string (NULL, function, 1));
+ fndecl_as_string (function, 1));
return error_mark_node;
}
@@ -1039,7 +1060,7 @@ build_optr_ref (instance)
/* Create a COMPONENT_REF expression for referencing the SPTR field
of a signature pointer or reference. */
-tree
+static tree
build_sptr_ref (instance)
tree instance;
{
diff --git a/contrib/gcc/cp/spew.c b/contrib/gcc/cp/spew.c
index 4b30b95..f153150 100644
--- a/contrib/gcc/cp/spew.c
+++ b/contrib/gcc/cp/spew.c
@@ -24,20 +24,20 @@ Boston, MA 02111-1307, USA. */
when compiling parse.c and spew.c. */
#include "config.h"
-#include <stdio.h>
+#include "system.h"
#include "input.h"
#include "tree.h"
#include "lex.h"
-#include "parse.h"
#include "cp-tree.h"
+#include "parse.h"
#include "flags.h"
#include "obstack.h"
/* This takes a token stream that hasn't decided much about types and
tries to figure out as much as it can, with excessive lookahead and
- backtracking. */
+ backtracking. */
-/* fifo of tokens recognized and available to parser. */
+/* fifo of tokens recognized and available to parser. */
struct token {
/* The values for YYCHAR will fit in a short. */
short yychar;
@@ -45,7 +45,17 @@ struct token {
YYSTYPE yylval;
};
-static int do_aggr ();
+static int do_aggr PROTO((void));
+static int probe_obstack PROTO((struct obstack *, tree, unsigned int));
+static void scan_tokens PROTO((int));
+
+#ifdef SPEW_DEBUG
+static int num_tokens PROTO((void));
+static struct token *nth_token PROTO((int));
+static void add_token PROTO((struct token *));
+static void consume_token PROTO((void));
+static int debug_yychar PROTO((int));
+#endif
/* From lex.c: */
/* the declaration found for the last IDENTIFIER token read in.
@@ -67,50 +77,55 @@ static unsigned int yylex_ctr = 0;
static int debug_yychar ();
#endif
-/* Initialize token_obstack. Called once, from init_lex. */
+/* Initialize token_obstack. Called once, from init_parse. */
+
void
init_spew ()
{
- gcc_obstack_init(&token_obstack);
+ gcc_obstack_init (&token_obstack);
}
#ifdef SPEW_DEBUG
/* Use functions for debugging... */
-/* Return the number of tokens available on the fifo. */
+/* Return the number of tokens available on the fifo. */
+
static int
num_tokens ()
{
- return (obstack_object_size(&token_obstack)/sizeof(struct token))
+ return (obstack_object_size (&token_obstack) / sizeof (struct token))
- first_token;
}
-/* Fetch the token N down the line from the head of the fifo. */
+/* Fetch the token N down the line from the head of the fifo. */
+
static struct token*
nth_token (n)
int n;
{
/* could just have this do slurp_ implicitly, but this way is easier
- * to debug... */
- my_friendly_assert (n < num_tokens(), 298);
- return ((struct token*)obstack_base(&token_obstack))+n+first_token;
+ to debug... */
+ my_friendly_assert (n < num_tokens (), 298);
+ return ((struct token*)obstack_base (&token_obstack)) + n + first_token;
}
-/* Add a token to the token fifo. */
+/* Add a token to the token fifo. */
+
static void
add_token (t)
struct token* t;
{
- obstack_grow(&token_obstack,t,sizeof (struct token));
+ obstack_grow (&token_obstack, t, sizeof (struct token));
}
/* Consume the next token out of the fifo. */
+
static void
-consume_token()
+consume_token ()
{
- if (num_tokens() == 1)
+ if (num_tokens () == 1)
{
- obstack_free(&token_obstack, obstack_base (&token_obstack));
+ obstack_free (&token_obstack, obstack_base (&token_obstack));
first_token = 0;
}
else
@@ -121,15 +136,15 @@ consume_token()
/* ...otherwise use macros. */
#define num_tokens() \
- ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token)
+ ((obstack_object_size (&token_obstack) / sizeof (struct token)) - first_token)
#define nth_token(N) \
- (((struct token*)obstack_base(&token_obstack))+(N)+first_token)
+ (((struct token*)obstack_base (&token_obstack))+(N)+first_token)
-#define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token))
+#define add_token(T) obstack_grow (&token_obstack, (T), sizeof (struct token))
#define consume_token() \
- (num_tokens() == 1 \
+ (num_tokens () == 1 \
? (obstack_free (&token_obstack, obstack_base (&token_obstack)), \
(first_token = 0)) \
: first_token++)
@@ -158,11 +173,11 @@ scan_tokens (n)
goto pad_tokens;
}
- while (num_tokens() <= n)
+ while (num_tokens () <= n)
{
- obstack_blank(&token_obstack,sizeof (struct token));
+ obstack_blank (&token_obstack, sizeof (struct token));
tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
- tmp->yychar = real_yylex();
+ tmp->yychar = real_yylex ();
tmp->end_of_file = end_of_file;
tmp->yylval = yylval;
end_of_file = 0;
@@ -173,7 +188,7 @@ scan_tokens (n)
pad_tokens:
while (num_tokens () <= n)
{
- obstack_blank(&token_obstack,sizeof (struct token));
+ obstack_blank (&token_obstack, sizeof (struct token));
tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
tmp->yychar = EMPTY;
tmp->end_of_file = 0;
@@ -182,35 +197,7 @@ scan_tokens (n)
}
}
-/* Create room for N tokens at the front of the fifo. This is used
- to insert new tokens into the stream ahead of the current token. */
-
-static void
-shift_tokens (n)
- int n;
-{
- if (first_token >= n)
- first_token -= n;
- else
- {
- int old_token_count = num_tokens ();
- char *tmp;
-
- obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token));
- if (old_token_count)
- {
- tmp = (char *)alloca ((num_tokens () + (n-first_token))
- * sizeof (struct token));
- /* This move does not rely on the system being able to handle
- overlapping moves. */
- bcopy ((char *) nth_token (0), tmp,
- old_token_count * sizeof (struct token));
- bcopy (tmp, (char *) nth_token (n),
- old_token_count * sizeof (struct token));
- }
- first_token = 0;
- }
-}
+/* Like _obstack_allocated_p, but stop after checking NLEVELS chunks. */
static int
probe_obstack (h, obj, nlevels)
@@ -224,7 +211,7 @@ probe_obstack (h, obj, nlevels)
lp = (h)->chunk;
/* We use >= rather than > since the object cannot be exactly at
the beginning of the chunk but might be an empty object exactly
- at the end of an adjacent chunk. */
+ at the end of an adjacent chunk. */
for (; nlevels != 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);
nlevels -= 1)
{
@@ -237,40 +224,52 @@ probe_obstack (h, obj, nlevels)
/* from lex.c: */
/* Value is 1 (or 2) if we should try to make the next identifier look like
a typename (when it may be a local variable or a class variable).
- Value is 0 if we treat this name in a default fashion. */
+ Value is 0 if we treat this name in a default fashion. */
extern int looking_for_typename;
int looking_for_template;
+extern int do_snarf_defarg;
extern struct obstack *current_obstack, *saveable_obstack;
tree got_scope;
tree got_object;
int
-peekyylex()
+peekyylex ()
{
scan_tokens (0);
return nth_token (0)->yychar;
}
int
-yylex()
+yylex ()
{
struct token tmp_token;
tree trrr;
+ int old_looking_for_typename = 0;
retry:
#ifdef SPEW_DEBUG
if (spew_debug)
{
yylex_ctr ++;
- fprintf(stderr, "\t\t## %d ##",yylex_ctr);
+ fprintf (stderr, "\t\t## %d ##", yylex_ctr);
}
#endif
+ if (do_snarf_defarg)
+ {
+ my_friendly_assert (num_tokens () == 0, 2837);
+ tmp_token.yychar = DEFARG;
+ tmp_token.yylval.ttype = snarf_defarg ();
+ tmp_token.end_of_file = 0;
+ do_snarf_defarg = 0;
+ add_token (&tmp_token);
+ }
+
/* if we've got tokens, send them */
- if (num_tokens())
+ else if (num_tokens ())
{
- tmp_token= *nth_token(0);
+ tmp_token= *nth_token (0);
/* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.
If we don't find it in CURRENT_OBSTACK's current or immediately
@@ -288,13 +287,13 @@ yylex()
tmp_token.yychar = real_yylex ();
tmp_token.yylval = yylval;
tmp_token.end_of_file = end_of_file;
- add_token(&tmp_token);
+ add_token (&tmp_token);
}
/* many tokens just need to be returned. At first glance, all we
- * have to do is send them back up, but some of them are needed to
- * figure out local context. */
- switch(tmp_token.yychar)
+ have to do is send them back up, but some of them are needed to
+ figure out local context. */
+ switch (tmp_token.yychar)
{
case EMPTY:
/* This is a lexical no-op. */
@@ -308,8 +307,11 @@ yylex()
case IDENTIFIER:
scan_tokens (1);
if (nth_token (1)->yychar == SCOPE)
- /* Don't interfere with the setting from an 'aggr' prefix. */
- looking_for_typename++;
+ {
+ /* Don't interfere with the setting from an 'aggr' prefix. */
+ old_looking_for_typename = looking_for_typename;
+ looking_for_typename = 1;
+ }
else if (nth_token (1)->yychar == '<')
looking_for_template = 1;
@@ -321,81 +323,92 @@ yylex()
switch (tmp_token.yychar)
{
case TYPENAME:
- lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
- if (lastiddecl != trrr)
- {
- lastiddecl = trrr;
- if (got_scope || got_object)
- tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
- }
- break;
- case IDENTIFIER:
- lastiddecl = trrr;
- break;
- case PTYPENAME:
- lastiddecl = NULL_TREE;
- break;
+ case SELFNAME:
case NSNAME:
+ case PTYPENAME:
lastiddecl = trrr;
+
+ /* If this got special lookup, remember it. In these cases,
+ we don't have to worry about being a declarator-id. */
if (got_scope || got_object)
tmp_token.yylval.ttype = trrr;
break;
+
+ case PFUNCNAME:
+ case IDENTIFIER:
+ lastiddecl = trrr;
+ break;
+
default:
my_friendly_abort (101);
}
}
else
- lastiddecl = trrr;
+ lastiddecl = NULL_TREE;
got_scope = NULL_TREE;
- /* and fall through to... */
+ /* and fall through to... */
case IDENTIFIER_DEFN:
case TYPENAME:
case TYPENAME_DEFN:
case PTYPENAME:
case PTYPENAME_DEFN:
consume_token ();
- if (looking_for_typename > 0)
- looking_for_typename--;
+ /* If we see a SCOPE next, restore the old value.
+ Otherwise, we got what we want. */
+ looking_for_typename = old_looking_for_typename;
looking_for_template = 0;
break;
case SCSPEC:
- /* do_aggr needs to check if the previous token was RID_FRIEND,
- so just increment first_token instead of calling consume_token. */
- first_token++;
+ case NEW:
+ /* do_aggr needs to check if the previous token was RID_NEW,
+ so just increment first_token instead of calling consume_token. */
+ ++first_token;
break;
+
case TYPESPEC:
consume_token ();
break;
case AGGR:
- *nth_token(0) = tmp_token;
+ *nth_token (0) = tmp_token;
do_aggr ();
- /* fall through to output... */
+ /* fall through to output... */
case ENUM:
/* Set this again, in case we are rescanning. */
- looking_for_typename = 1;
- /* fall through... */
+ looking_for_typename = 2;
+ /* fall through... */
default:
- consume_token();
+ consume_token ();
}
+ /* class member lookup only applies to the first token after the object
+ expression, except for explicit destructor calls. */
+ if (tmp_token.yychar != '~')
+ got_object = NULL_TREE;
+
+ /* Clear looking_for_typename if we got 'enum { ... };'. */
+ if (tmp_token.yychar == '{' || tmp_token.yychar == ':'
+ || tmp_token.yychar == ';')
+ looking_for_typename = 0;
+
yylval = tmp_token.yylval;
yychar = tmp_token.yychar;
end_of_file = tmp_token.end_of_file;
#ifdef SPEW_DEBUG
if (spew_debug)
- debug_yychar(yychar);
+ debug_yychar (yychar);
#endif
+
return yychar;
}
/* token[0] == AGGR (struct/union/enum)
- * Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
- * If token[2] == '{' or ':' then it's TYPENAME_DEFN.
- * It's also a definition if it's a forward declaration (as in 'struct Foo;')
- * which we can tell lf token[2] == ';' *and* token[-1] != FRIEND.
- */
+ Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
+ If token[2] == '{' or ':' then it's TYPENAME_DEFN.
+ It's also a definition if it's a forward declaration (as in 'struct Foo;')
+ which we can tell if token[2] == ';' *and* token[-1] != FRIEND or NEW. */
+
static int
do_aggr ()
{
@@ -408,10 +421,16 @@ do_aggr ()
yc2 = nth_token (2)->yychar;
if (yc2 == ';')
{
- /* It's a forward declaration iff we were not preceded by 'friend'. */
- if (first_token > 0 && nth_token (-1)->yychar == SCSPEC
- && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
- return 0;
+ /* It's a forward declaration iff we were not preceded by
+ 'friend' or `new'. */
+ if (first_token > 0)
+ {
+ if (nth_token (-1)->yychar == SCSPEC
+ && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
+ return 0;
+ if (nth_token (-1)->yychar == NEW)
+ return 0;
+ }
}
else if (yc2 != '{' && yc2 != ':')
return 0;
@@ -434,7 +453,8 @@ do_aggr ()
}
#ifdef SPEW_DEBUG
-/* debug_yychar takes a yychar (token number) value and prints its name. */
+/* debug_yychar takes a yychar (token number) value and prints its name. */
+
static int
debug_yychar (yy)
int yy;
@@ -444,7 +464,7 @@ debug_yychar (yy)
int i;
- if(yy<256) {
+ if (yy<256) {
fprintf (stderr, "<%d: %c >\n", yy, yy);
return 0;
}
diff --git a/contrib/gcc/cp/tinfo.cc b/contrib/gcc/cp/tinfo.cc
new file mode 100644
index 0000000..d8380da
--- /dev/null
+++ b/contrib/gcc/cp/tinfo.cc
@@ -0,0 +1,134 @@
+// Methods for type_info for -*- C++ -*- Run Time Type Identification.
+// Copyright (C) 1994, 1996 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#pragma implementation "typeinfo"
+
+#include <stddef.h>
+#include "tinfo.h"
+#include "new" // for placement new
+
+// This file contains the minimal working set necessary to link with code
+// that uses virtual functions and -frtti but does not actually use RTTI
+// functionality.
+
+std::type_info::
+~type_info ()
+{ }
+
+// We can't rely on common symbols being shared between shared objects.
+bool type_info::
+operator== (const type_info& arg) const
+{
+ return (&arg == this) || (strcmp (name (), arg.name ()) == 0);
+}
+
+extern "C" void
+__rtti_class (void *addr, const char *name,
+ const __class_type_info::base_info *bl, size_t bn)
+{ new (addr) __class_type_info (name, bl, bn); }
+
+extern "C" void
+__rtti_si (void *addr, const char *n, const std::type_info *ti)
+{
+ new (addr) __si_type_info
+ (n, static_cast <const __user_type_info &> (*ti));
+}
+
+extern "C" void
+__rtti_user (void *addr, const char *name)
+{ new (addr) __user_type_info (name); }
+
+// dynamic_cast helper methods.
+// Returns a pointer to the desired sub-object or 0.
+
+void * __user_type_info::
+dcast (const type_info& to, int, void *addr, const type_info *, void *) const
+{ return (*this == to) ? addr : 0; }
+
+void * __si_type_info::
+dcast (const type_info& to, int require_public, void *addr,
+ const type_info *sub, void *subptr) const
+{
+ if (*this == to)
+ return addr;
+ return base.dcast (to, require_public, addr, sub, subptr);
+}
+
+void* __class_type_info::
+dcast (const type_info& desired, int is_public, void *objptr,
+ const type_info *sub, void *subptr) const
+{
+ if (*this == desired)
+ return objptr;
+
+ void *match_found = 0;
+ for (size_t i = 0; i < n_bases; i++)
+ {
+ if (is_public && base_list[i].access != PUBLIC)
+ continue;
+
+ void *p = (char *)objptr + base_list[i].offset;
+ if (base_list[i].is_virtual)
+ p = *(void **)p;
+ p = base_list[i].base->dcast (desired, is_public, p, sub, subptr);
+ if (p)
+ {
+ if (match_found == 0)
+ match_found = p;
+ else if (match_found != p)
+ {
+ if (sub)
+ {
+ // Perhaps we're downcasting from *sub to desired; see if
+ // subptr is a subobject of exactly one of {match_found,p}.
+
+ const __user_type_info &d =
+ static_cast <const __user_type_info &> (desired);
+
+ void *os = d.dcast (*sub, 1, match_found);
+ void *ns = d.dcast (*sub, 1, p);
+
+ if (os == ns)
+ /* ambiguous -- subptr is a virtual base */;
+ else if (os == subptr)
+ continue;
+ else if (ns == subptr)
+ {
+ match_found = p;
+ continue;
+ }
+ }
+
+ // base found at two different pointers,
+ // conversion is not unique
+ return 0;
+ }
+ }
+ }
+
+ return match_found;
+}
diff --git a/contrib/gcc/cp/tinfo.h b/contrib/gcc/cp/tinfo.h
new file mode 100644
index 0000000..3cfee04
--- /dev/null
+++ b/contrib/gcc/cp/tinfo.h
@@ -0,0 +1,55 @@
+// RTTI support internals for -*- C++ -*-
+// Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+#include "typeinfo"
+
+// Class declarations shared between the typeinfo implementation files.
+
+// type_info for a class with no base classes (or an enum).
+
+struct __user_type_info : public std::type_info {
+ __user_type_info (const char *n) : type_info (n) {}
+
+ // If our type can be converted to the desired type,
+ // return the pointer, adjusted accordingly; else return 0.
+ virtual void* dcast (const type_info &, int, void *,
+ const type_info * = 0, void * = 0) const;
+};
+
+// type_info for a class with one public, nonvirtual base class.
+
+class __si_type_info : public __user_type_info {
+ const __user_type_info &base;
+
+public:
+ __si_type_info (const char *n, const __user_type_info &b)
+ : __user_type_info (n), base (b) { }
+
+ virtual void *dcast (const type_info &, int, void *,
+ const type_info * = 0, void * = 0) const;
+};
+
+// type_info for a general class.
+
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+
+struct __class_type_info : public __user_type_info {
+ enum access { PUBLIC = 1, PROTECTED = 2, PRIVATE = 3 };
+
+ struct base_info {
+ const __user_type_info *base;
+ USItype offset: 29;
+ bool is_virtual: 1;
+ access access: 2;
+ };
+
+ const base_info *base_list;
+ size_t n_bases;
+
+ __class_type_info (const char *name, const base_info *bl, size_t bn)
+ : __user_type_info (name), base_list (bl), n_bases (bn) {}
+
+ // This is a little complex.
+ virtual void* dcast (const type_info &, int, void *,
+ const type_info * = 0, void * = 0) const;
+};
diff --git a/contrib/gcc/cp/tinfo2.cc b/contrib/gcc/cp/tinfo2.cc
new file mode 100644
index 0000000..3e63354
--- /dev/null
+++ b/contrib/gcc/cp/tinfo2.cc
@@ -0,0 +1,300 @@
+// Methods for type_info for -*- C++ -*- Run Time Type Identification.
+// Copyright (C) 1994, 1996 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#include <stddef.h>
+#include "tinfo.h"
+#include "new" // for placement new
+
+using std::type_info;
+
+bool
+type_info::before (const type_info &arg) const
+{
+ return strcmp (name (), arg.name ()) < 0;
+}
+
+// type info for pointer type.
+
+struct __pointer_type_info : public type_info {
+ const type_info& type;
+
+ __pointer_type_info (const char *n, const type_info& ti)
+ : type_info (n), type (ti) {}
+};
+
+// type info for attributes
+
+struct __attr_type_info : public type_info {
+ enum cv { NONE = 0, CONST = 1, VOLATILE = 2, CONSTVOL = 1 | 2 };
+
+ const type_info& type;
+ cv attr;
+
+ __attr_type_info (const char *n, cv a, const type_info& t)
+ : type_info (n), type (t), attr (a) {}
+};
+
+// type_info for builtin type
+
+struct __builtin_type_info : public type_info {
+ __builtin_type_info (const char *n): type_info (n) {}
+};
+
+// type info for function.
+
+struct __func_type_info : public type_info {
+ __func_type_info (const char *n) : type_info (n) {}
+};
+
+// type info for pointer to member function.
+
+struct __ptmf_type_info : public type_info {
+ __ptmf_type_info (const char *n) : type_info (n) {}
+};
+
+// type info for pointer to data member.
+
+struct __ptmd_type_info : public type_info {
+ __ptmd_type_info (const char *n): type_info (n) {}
+};
+
+// type info for array.
+
+struct __array_type_info : public type_info {
+ __array_type_info (const char *n): type_info (n) {}
+};
+
+// Entry points for the compiler.
+
+/* Low level match routine used by compiler to match types of catch
+ variables and thrown objects. */
+
+extern "C" void*
+__throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r,
+ void *objptr)
+{
+ const type_info &catch_type = *(const type_info *)catch_type_r;
+ const type_info &throw_type = *(const type_info *)throw_type_r;
+
+ if (catch_type == throw_type)
+ return objptr;
+
+#if 0
+ printf ("We want to match a %s against a %s!\n",
+ throw_type.name (), catch_type.name ());
+#endif
+
+ void *new_objptr = 0;
+
+ if (const __user_type_info *p
+ = dynamic_cast <const __user_type_info *> (&throw_type))
+ {
+ /* The 1 skips conversions to private bases. */
+ new_objptr = p->dcast (catch_type, 1, objptr);
+ }
+ else if (const __pointer_type_info *fr =
+ dynamic_cast <const __pointer_type_info *> (&throw_type))
+ {
+ const __pointer_type_info *to =
+ dynamic_cast <const __pointer_type_info *> (&catch_type);
+
+ if (! to)
+ goto fail;
+
+ const type_info *subfr = &fr->type, *subto = &to->type;
+ __attr_type_info::cv cvfrom, cvto;
+
+ if (const __attr_type_info *at
+ = dynamic_cast <const __attr_type_info *> (subfr))
+ {
+ cvfrom = at->attr;
+ subfr = &at->type;
+ }
+ else
+ cvfrom = __attr_type_info::NONE;
+
+ if (const __attr_type_info *at
+ = dynamic_cast <const __attr_type_info *> (subto))
+ {
+ cvto = at->attr;
+ subto = &at->type;
+ }
+ else
+ cvto = __attr_type_info::NONE;
+
+ if (((cvfrom & __attr_type_info::CONST)
+ > (cvto & __attr_type_info::CONST))
+ || ((cvfrom & __attr_type_info::VOLATILE)
+ > (cvto & __attr_type_info::VOLATILE)))
+ goto fail;
+
+ if (*subto == *subfr)
+ new_objptr = objptr;
+ else if (*subto == typeid (void)
+ && dynamic_cast <const __func_type_info *> (subfr) == 0)
+ new_objptr = objptr;
+ else if (const __user_type_info *p
+ = dynamic_cast <const __user_type_info *> (subfr))
+ {
+ /* The 1 skips conversions to private bases. */
+ new_objptr = p->dcast (*subto, 1, objptr);
+ }
+ else if (const __pointer_type_info *pfr
+ = dynamic_cast <const __pointer_type_info *> (subfr))
+ {
+ // Multi-level pointer conversion.
+
+ const __pointer_type_info *pto
+ = dynamic_cast <const __pointer_type_info *> (subto);
+
+ if (! pto)
+ goto fail;
+
+ bool constp = (cvto & __attr_type_info::CONST);
+ for (subto = &pto->type, subfr = &pfr->type; ;
+ subto = &pto->type, subfr = &pfr->type)
+ {
+ if (const __attr_type_info *at
+ = dynamic_cast <const __attr_type_info *> (subfr))
+ {
+ cvfrom = at->attr;
+ subfr = &at->type;
+ }
+ else
+ cvfrom = __attr_type_info::NONE;
+
+ if (const __attr_type_info *at
+ = dynamic_cast <const __attr_type_info *> (subto))
+ {
+ cvto = at->attr;
+ subto = &at->type;
+ }
+ else
+ cvto = __attr_type_info::NONE;
+
+ if (((cvfrom & __attr_type_info::CONST)
+ > (cvto & __attr_type_info::CONST))
+ || ((cvfrom & __attr_type_info::VOLATILE)
+ > (cvto & __attr_type_info::VOLATILE)))
+ goto fail;
+
+ if (! constp
+ && (((cvfrom & __attr_type_info::CONST)
+ < (cvto & __attr_type_info::CONST))
+ || ((cvfrom & __attr_type_info::VOLATILE)
+ < (cvto & __attr_type_info::VOLATILE))))
+ goto fail;
+
+ if (*subto == *subfr)
+ {
+ new_objptr = objptr;
+ break;
+ }
+
+ pto = dynamic_cast <const __pointer_type_info *> (subto);
+ pfr = dynamic_cast <const __pointer_type_info *> (subfr);
+ if (! pto || ! pfr)
+ goto fail;
+
+ if (! (cvto & __attr_type_info::CONST))
+ constp = false;
+ }
+ }
+ }
+ fail:
+
+#if 0
+ if (new_objptr)
+ printf ("It converts, delta is %d\n", new_objptr-objptr);
+#endif
+ return new_objptr;
+}
+
+/* Called from __cp_pop_exception. Is P the type_info node for a pointer
+ of some kind? */
+
+bool
+__is_pointer (void *p)
+{
+ const type_info *t = reinterpret_cast <const type_info *>(p);
+ const __pointer_type_info *pt =
+ dynamic_cast <const __pointer_type_info *> (t);
+ return pt != 0;
+}
+
+extern "C" void
+__rtti_ptr (void *addr, const char *n, const type_info *ti)
+{ new (addr) __pointer_type_info (n, *ti); }
+
+extern "C" void
+__rtti_attr (void *addr, const char *n, int attrval, const type_info *ti)
+{
+ new (addr) __attr_type_info
+ (n, static_cast <__attr_type_info::cv> (attrval), *ti);
+}
+
+extern "C" void
+__rtti_func (void *addr, const char *name)
+{ new (addr) __func_type_info (name); }
+
+extern "C" void
+__rtti_ptmf (void *addr, const char *name)
+{ new (addr) __ptmf_type_info (name); }
+
+extern "C" void
+__rtti_ptmd (void *addr, const char *name)
+{ new (addr) __ptmd_type_info (name); }
+
+extern "C" void
+__rtti_array (void *addr, const char *name)
+{ new (addr) __array_type_info (name); }
+
+extern "C" void *
+__dynamic_cast (const type_info& (*from)(void), const type_info& (*to)(void),
+ int require_public, void *address,
+ const type_info & (*sub)(void), void *subptr)
+{
+ return static_cast <const __user_type_info &> (from ()).dcast
+ (to (), require_public, address, &(sub ()), subptr);
+}
+
+// type_info nodes and functions for the builtin types. The mangling here
+// must match the mangling in gcc/cp/rtti.c.
+
+#define BUILTIN(mangled) \
+unsigned char __ti##mangled [sizeof (__builtin_type_info)] \
+ __attribute__ ((aligned (__alignof__ (void *)))); \
+extern "C" const type_info &__tf##mangled (void) { \
+ if ((*(void **) __ti##mangled) == 0) \
+ new (__ti##mangled) __builtin_type_info (#mangled); \
+ return *(type_info *)__ti##mangled; \
+}
+
+BUILTIN (v); BUILTIN (x); BUILTIN (l); BUILTIN (i); BUILTIN (s); BUILTIN (b);
+BUILTIN (c); BUILTIN (w); BUILTIN (r); BUILTIN (d); BUILTIN (f);
+BUILTIN (Ui); BUILTIN (Ul); BUILTIN (Ux); BUILTIN (Us); BUILTIN (Uc);
+BUILTIN (Sc);
diff --git a/contrib/gcc/cp/tree.c b/contrib/gcc/cp/tree.c
index 7fb688e..7c7768f 100644
--- a/contrib/gcc/cp/tree.c
+++ b/contrib/gcc/cp/tree.c
@@ -1,5 +1,5 @@
/* Language-dependent node constructors for parse phase of GNU compiler.
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -20,12 +20,34 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
-#include <stdio.h>
+#include "system.h"
#include "obstack.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
#include "rtl.h"
+#include "toplev.h"
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+extern void compiler_error ();
+
+static tree get_identifier_list PROTO((tree));
+static tree bot_manip PROTO((tree));
+static tree perm_manip PROTO((tree));
+static tree build_cplus_array_type_1 PROTO((tree, tree));
+static void list_hash_add PROTO((int, tree));
+static int list_hash PROTO((tree, tree, tree));
+static tree list_hash_lookup PROTO((int, int, int, int, tree, tree,
+ tree));
+static void propagate_binfo_offsets PROTO((tree, tree));
+static void unshare_base_binfos PROTO((tree));
+static int avoid_overlap PROTO((tree, tree));
+static int equal_functions PROTO((tree, tree));
#define CEIL(x,y) (((x) + (y) - 1) / (y))
@@ -43,17 +65,20 @@ real_lvalue_p (ref)
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
- if (ref == current_class_decl && flag_this_is_variable <= 0)
+ if (ref == current_class_ptr && flag_this_is_variable <= 0)
return 0;
switch (TREE_CODE (ref))
{
/* preincrements and predecrements are valid lvals, provided
- what they refer to are valid lvals. */
+ what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
+ case UNSAVE_EXPR:
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
return real_lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
@@ -74,9 +99,6 @@ real_lvalue_p (ref)
return 1;
break;
- case WITH_CLEANUP_EXPR:
- return real_lvalue_p (TREE_OPERAND (ref, 0));
-
/* A currently unresolved scope ref. */
case SCOPE_REF:
my_friendly_abort (103);
@@ -101,11 +123,16 @@ real_lvalue_p (ref)
case MIN_EXPR:
return (real_lvalue_p (TREE_OPERAND (ref, 0))
&& real_lvalue_p (TREE_OPERAND (ref, 1)));
+
+ default:
+ break;
}
return 0;
}
+/* This differs from real_lvalue_p in that class rvalues are considered
+ lvalues. */
int
lvalue_p (ref)
tree ref;
@@ -116,17 +143,22 @@ lvalue_p (ref)
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
- if (ref == current_class_decl && flag_this_is_variable <= 0)
+ if (ref == current_class_ptr && flag_this_is_variable <= 0)
return 0;
switch (TREE_CODE (ref))
{
/* preincrements and predecrements are valid lvals, provided
- what they refer to are valid lvals. */
+ what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
+ case UNSAVE_EXPR:
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
@@ -147,9 +179,6 @@ lvalue_p (ref)
return 1;
break;
- case WITH_CLEANUP_EXPR:
- return lvalue_p (TREE_OPERAND (ref, 0));
-
case TARGET_EXPR:
return 1;
@@ -182,6 +211,9 @@ lvalue_p (ref)
case MIN_EXPR:
return (lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1)));
+
+ default:
+ break;
}
return 0;
@@ -206,44 +238,47 @@ lvalue_or_else (ref, string)
Build an encapsulation of the initialization to perform
and return it so that it can be processed by language-independent
- and language-specific expression expanders.
+ and language-specific expression expanders. */
- If WITH_CLEANUP_P is nonzero, we build a cleanup for this expression.
- Otherwise, cleanups are not built here. For example, when building
- an initialization for a stack slot, since the called function handles
- the cleanup, we would not want to do it here. */
tree
-build_cplus_new (type, init, with_cleanup_p)
+build_cplus_new (type, init)
tree type;
tree init;
- int with_cleanup_p;
{
tree slot;
tree rval;
+ if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
+ return init;
+
slot = build (VAR_DECL, type);
+ DECL_ARTIFICIAL (slot) = 1;
layout_decl (slot, 0);
- rval = build (NEW_EXPR, type,
+ rval = build (AGGR_INIT_EXPR, type,
TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
TREE_SIDE_EFFECTS (rval) = 1;
- TREE_ADDRESSABLE (rval) = 1;
- rval = build (TARGET_EXPR, type, slot, rval, 0);
+ rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE, NULL_TREE);
+ TREE_SIDE_EFFECTS (rval) = 1;
+
+ return rval;
+}
+
+/* Encapsulate the expression INIT in a TARGET_EXPR. */
+
+tree
+get_target_expr (init)
+ tree init;
+{
+ tree slot;
+ tree rval;
+
+ slot = build (VAR_DECL, TREE_TYPE (init));
+ DECL_ARTIFICIAL (slot) = 1;
+ layout_decl (slot, 0);
+ rval = build (TARGET_EXPR, TREE_TYPE (init), slot, init,
+ NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (rval) = 1;
- TREE_ADDRESSABLE (rval) = 1;
-#if 0
- if (with_cleanup_p && TYPE_NEEDS_DESTRUCTOR (type))
- {
- TREE_OPERAND (rval, 2) = error_mark_node;
- rval = build (WITH_CLEANUP_EXPR, type, rval, 0,
- build_delete (build_pointer_type (type),
- build_unary_op (ADDR_EXPR, slot, 0),
- integer_two_node,
- LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0));
- TREE_SIDE_EFFECTS (rval) = 1;
- TREE_ADDRESSABLE (rval) = 1;
- }
-#endif
return rval;
}
@@ -258,7 +293,7 @@ break_out_cleanups (exp)
if (TREE_CODE (tmp) == CALL_EXPR
&& TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (tmp)))
- return build_cplus_new (TREE_TYPE (tmp), tmp, 1);
+ return build_cplus_new (TREE_TYPE (tmp), tmp);
while (TREE_CODE (tmp) == NOP_EXPR
|| TREE_CODE (tmp) == CONVERT_EXPR
@@ -269,7 +304,7 @@ break_out_cleanups (exp)
{
TREE_OPERAND (tmp, 0)
= build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)),
- TREE_OPERAND (tmp, 0), 1);
+ TREE_OPERAND (tmp, 0));
break;
}
else
@@ -286,7 +321,7 @@ tree
break_out_calls (exp)
tree exp;
{
- register tree t1, t2;
+ register tree t1, t2 = NULL_TREE;
register enum tree_code code;
register int changed = 0;
register int i;
@@ -299,7 +334,7 @@ break_out_calls (exp)
if (code == CALL_EXPR)
return copy_node (exp);
- /* Don't try and defeat a save_expr, as it should only be done once. */
+ /* Don't try and defeat a save_expr, as it should only be done once. */
if (code == SAVE_EXPR)
return exp;
@@ -372,6 +407,7 @@ break_out_calls (exp)
extern struct obstack *current_obstack;
extern struct obstack permanent_obstack, class_obstack;
extern struct obstack *saveable_obstack;
+extern struct obstack *expression_obstack;
/* Here is how primitive or already-canonicalized types' hash
codes are made. MUST BE CONSISTENT WITH tree.c !!! */
@@ -380,6 +416,7 @@ extern struct obstack *saveable_obstack;
/* Construct, lay out and return the type of methods belonging to class
BASETYPE and whose arguments are described by ARGTYPES and whose values
are described by RETTYPE. If each type exists already, reuse it. */
+
tree
build_cplus_method_type (basetype, rettype, argtypes)
tree basetype, rettype, argtypes;
@@ -418,34 +455,8 @@ build_cplus_method_type (basetype, rettype, argtypes)
return t;
}
-tree
-build_cplus_staticfn_type (basetype, rettype, argtypes)
- tree basetype, rettype, argtypes;
-{
- register tree t;
- int hashcode;
-
- /* Make a node of the sort we want. */
- t = make_node (FUNCTION_TYPE);
-
- TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
- TREE_TYPE (t) = rettype;
-
- TYPE_ARG_TYPES (t) = argtypes;
-
- /* If we already have such a type, use the old one and free this one.
- Note that it also frees up the above cons cell if found. */
- hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes);
- t = type_hash_canon (hashcode, t);
-
- if (TYPE_SIZE (t) == 0)
- layout_type (t);
-
- return t;
-}
-
-tree
-build_cplus_array_type (elt_type, index_type)
+static tree
+build_cplus_array_type_1 (elt_type, index_type)
tree elt_type;
tree index_type;
{
@@ -462,7 +473,15 @@ build_cplus_array_type (elt_type, index_type)
saveable_obstack = &permanent_obstack;
}
- t = build_array_type (elt_type, index_type);
+ if (processing_template_decl
+ || uses_template_parms (index_type))
+ {
+ t = make_node (ARRAY_TYPE);
+ TREE_TYPE (t) = elt_type;
+ TYPE_DOMAIN (t) = index_type;
+ }
+ else
+ t = build_array_type (elt_type, index_type);
/* Push these needs up so that initialization takes place
more easily. */
@@ -472,6 +491,24 @@ build_cplus_array_type (elt_type, index_type)
saveable_obstack = ambient_saveable_obstack;
return t;
}
+
+tree
+build_cplus_array_type (elt_type, index_type)
+ tree elt_type;
+ tree index_type;
+{
+ tree t;
+ int constp = TYPE_READONLY (elt_type);
+ int volatilep = TYPE_VOLATILE (elt_type);
+ elt_type = TYPE_MAIN_VARIANT (elt_type);
+
+ t = build_cplus_array_type_1 (elt_type, index_type);
+
+ if (constp || volatilep)
+ t = cp_build_type_variant (t, constp, volatilep);
+
+ return t;
+}
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
@@ -481,15 +518,18 @@ cp_build_type_variant (type, constp, volatilep)
tree type;
int constp, volatilep;
{
+ if (type == error_mark_node)
+ return type;
+
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree real_main_variant = TYPE_MAIN_VARIANT (type);
push_obstacks (TYPE_OBSTACK (real_main_variant),
TYPE_OBSTACK (real_main_variant));
- type = build_cplus_array_type (cp_build_type_variant (TREE_TYPE (type),
- constp, volatilep),
- TYPE_DOMAIN (type));
+ type = build_cplus_array_type_1 (cp_build_type_variant
+ (TREE_TYPE (type), constp, volatilep),
+ TYPE_DOMAIN (type));
/* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not,
make a copy. (TYPE might have come from the hash table and
@@ -503,9 +543,33 @@ cp_build_type_variant (type, constp, volatilep)
TYPE_MAIN_VARIANT (type) = real_main_variant;
pop_obstacks ();
+ return type;
}
return build_type_variant (type, constp, volatilep);
}
+
+/* Returns the canonical version of TYPE. In other words, if TYPE is
+ a typedef, returns the underlying type. The cv-qualification of
+ the type returned matches the type input; they will always be
+ compatible types. */
+
+tree
+canonical_type_variant (t)
+ tree t;
+{
+ int constp, volatilep;
+ if (TREE_CODE (t) == ARRAY_TYPE)
+ {
+ constp = TYPE_READONLY (TREE_TYPE (t));
+ volatilep = TYPE_VOLATILE (TREE_TYPE (t));
+ }
+ else
+ {
+ constp = TYPE_READONLY (t);
+ volatilep = TYPE_VOLATILE (t);
+ }
+ return cp_build_type_variant (TYPE_MAIN_VARIANT (t), constp, volatilep);
+}
/* Add OFFSET to all base types of T.
@@ -513,7 +577,8 @@ cp_build_type_variant (type, constp, volatilep)
Note that we don't have to worry about having two paths to the
same base type, since this type owns its association list. */
-void
+
+static void
propagate_binfo_offsets (binfo, offset)
tree binfo;
tree offset;
@@ -530,8 +595,7 @@ propagate_binfo_offsets (binfo, offset)
else
{
int j;
- tree base_binfos = BINFO_BASETYPES (base_binfo);
- tree delta;
+ tree delta = NULL_TREE;
for (j = i+1; j < n_baselinks; j++)
if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j)))
@@ -553,31 +617,8 @@ propagate_binfo_offsets (binfo, offset)
#else
BINFO_OFFSET (base_binfo) = offset;
#endif
- if (base_binfos)
- {
- int k;
- tree chain = NULL_TREE;
-
- /* Now unshare the structure beneath BASE_BINFO. */
- for (k = TREE_VEC_LENGTH (base_binfos)-1;
- k >= 0; k--)
- {
- tree base_base_binfo = TREE_VEC_ELT (base_binfos, k);
- if (! TREE_VIA_VIRTUAL (base_base_binfo))
- TREE_VEC_ELT (base_binfos, k)
- = make_binfo (BINFO_OFFSET (base_base_binfo),
- base_base_binfo,
- BINFO_VTABLE (base_base_binfo),
- BINFO_VIRTUALS (base_base_binfo),
- chain);
- chain = TREE_VEC_ELT (base_binfos, k);
- TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
- TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
- BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
- }
- /* Now propagate the offset to the base types. */
- propagate_binfo_offsets (base_binfo, offset);
- }
+
+ unshare_base_binfos (base_binfo);
/* Go to our next class that counts for offset propagation. */
i = j;
@@ -587,48 +628,82 @@ propagate_binfo_offsets (binfo, offset)
}
}
-/* Compute the actual offsets that our virtual base classes
- will have *for this type*. This must be performed after
- the fields are laid out, since virtual baseclasses must
- lay down at the end of the record.
+/* Makes new binfos for the indirect bases under BASE_BINFO, and updates
+ BINFO_OFFSET for them and their bases. */
+
+static void
+unshare_base_binfos (base_binfo)
+ tree base_binfo;
+{
+ if (BINFO_BASETYPES (base_binfo))
+ {
+ tree base_binfos = BINFO_BASETYPES (base_binfo);
+ tree chain = NULL_TREE;
+ int j;
+
+ /* Now unshare the structure beneath BASE_BINFO. */
+ for (j = TREE_VEC_LENGTH (base_binfos)-1;
+ j >= 0; j--)
+ {
+ tree base_base_binfo = TREE_VEC_ELT (base_binfos, j);
+ if (! TREE_VIA_VIRTUAL (base_base_binfo))
+ TREE_VEC_ELT (base_binfos, j)
+ = make_binfo (BINFO_OFFSET (base_base_binfo),
+ base_base_binfo,
+ BINFO_VTABLE (base_base_binfo),
+ BINFO_VIRTUALS (base_base_binfo),
+ chain);
+ chain = TREE_VEC_ELT (base_binfos, j);
+ TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
+ TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
+ BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
+ }
- Returns the maximum number of virtual functions any of the virtual
+ /* Completely unshare potentially shared data, and
+ update what is ours. */
+ propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
+ }
+}
+
+/* Finish the work of layout_record, now taking virtual bases into account.
+ Also compute the actual offsets that our base classes will have.
+ This must be performed after the fields are laid out, since virtual
+ baseclasses must lay down at the end of the record.
+
+ Returns the maximum number of virtual functions any of the
baseclasses provide. */
+
int
-layout_vbasetypes (rec, max)
+layout_basetypes (rec, max)
tree rec;
int max;
{
+ tree binfos = TYPE_BINFO_BASETYPES (rec);
+ int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+
/* Get all the virtual base types that this type uses.
The TREE_VALUE slot holds the virtual baseclass type. */
tree vbase_types = get_vbase_types (rec);
+ unsigned int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
+ unsigned int desired_align;
+
+ /* Record size so far is CONST_SIZE bits, where CONST_SIZE is an integer. */
+ register unsigned int const_size = 0;
+ unsigned int nonvirtual_const_size;
+
#ifdef STRUCTURE_SIZE_BOUNDARY
- unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec));
-#else
- unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
+ /* Packed structures don't need to have minimum size. */
+ if (! TYPE_PACKED (rec))
+ record_align = MAX (record_align, STRUCTURE_SIZE_BOUNDARY);
#endif
- int desired_align;
-
- /* Record size so far is CONST_SIZE + VAR_SIZE bits,
- where CONST_SIZE is an integer
- and VAR_SIZE is a tree expression.
- If VAR_SIZE is null, the size is just CONST_SIZE.
- Naturally we try to avoid using VAR_SIZE. */
- register unsigned const_size = 0;
- register tree var_size = 0;
- int nonvirtual_const_size;
- tree nonvirtual_var_size;
CLASSTYPE_VBASECLASSES (rec) = vbase_types;
- if (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST)
- const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec));
- else
- var_size = TYPE_SIZE (rec);
+ my_friendly_assert (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST, 19970302);
+ const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec));
nonvirtual_const_size = const_size;
- nonvirtual_var_size = var_size;
while (vbase_types)
{
@@ -643,8 +718,7 @@ layout_vbasetypes (rec, max)
else
{
/* Give each virtual base type the alignment it wants. */
- const_size = CEIL (const_size, TYPE_ALIGN (basetype))
- * TYPE_ALIGN (basetype);
+ const_size = CEIL (const_size, desired_align) * desired_align;
offset = size_int (CEIL (const_size, BITS_PER_UNIT));
}
@@ -652,18 +726,10 @@ layout_vbasetypes (rec, max)
max = CLASSTYPE_VSIZE (basetype);
BINFO_OFFSET (vbase_types) = offset;
- if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST)
- {
- /* Every virtual baseclass takes a least a UNIT, so that we can
- take it's address and get something different for each base. */
- const_size += MAX (BITS_PER_UNIT,
- TREE_INT_CST_LOW (TYPE_SIZE (basetype))
- - TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)));
- }
- else if (var_size == 0)
- var_size = TYPE_SIZE (basetype);
- else
- var_size = size_binop (PLUS_EXPR, var_size, TYPE_SIZE (basetype));
+ /* Every virtual baseclass takes a least a UNIT, so that we can
+ take it's address and get something different for each base. */
+ const_size += MAX (BITS_PER_UNIT,
+ TREE_INT_CST_LOW (CLASSTYPE_SIZE (basetype)));
vbase_types = TREE_CHAIN (vbase_types);
}
@@ -671,7 +737,7 @@ layout_vbasetypes (rec, max)
if (const_size)
{
/* Because a virtual base might take a single byte above,
- we have to re-adjust the total size to make sure it it
+ we have to re-adjust the total size to make sure it is
a multiple of the alignment. */
/* Give the whole object the alignment it wants. */
const_size = CEIL (const_size, record_align) * record_align;
@@ -682,117 +748,176 @@ layout_vbasetypes (rec, max)
TYPE_ALIGN (rec) = record_align;
if (const_size != nonvirtual_const_size)
{
- CLASSTYPE_VBASE_SIZE (rec)
- = size_int (const_size - nonvirtual_const_size);
TYPE_SIZE (rec) = size_int (const_size);
+ TYPE_SIZE_UNIT (rec) = size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (rec),
+ size_int (BITS_PER_UNIT));
+ }
+
+ /* Now propagate offset information throughout the lattice. */
+ for (i = 0; i < n_baseclasses; i++)
+ {
+ register tree base_binfo = TREE_VEC_ELT (binfos, i);
+ register tree basetype = BINFO_TYPE (base_binfo);
+ tree field = TYPE_FIELDS (rec);
+
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ continue;
+
+ my_friendly_assert (TREE_TYPE (field) == basetype, 23897);
+ BINFO_OFFSET (base_binfo)
+ = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)),
+ BITS_PER_UNIT));
+ unshare_base_binfos (base_binfo);
+ TYPE_FIELDS (rec) = TREE_CHAIN (field);
}
- /* Now propagate offset information throughout the lattice
- under the vbase type. */
for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types;
vbase_types = TREE_CHAIN (vbase_types))
{
- tree base_binfos = BINFO_BASETYPES (vbase_types);
-
BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec);
+ unshare_base_binfos (vbase_types);
+ }
- if (base_binfos)
- {
- tree chain = NULL_TREE;
- int j;
- /* Now unshare the structure beneath BASE_BINFO. */
+ return max;
+}
- for (j = TREE_VEC_LENGTH (base_binfos)-1;
- j >= 0; j--)
- {
- tree base_base_binfo = TREE_VEC_ELT (base_binfos, j);
- if (! TREE_VIA_VIRTUAL (base_base_binfo))
- TREE_VEC_ELT (base_binfos, j)
- = make_binfo (BINFO_OFFSET (base_base_binfo),
- base_base_binfo,
- BINFO_VTABLE (base_base_binfo),
- BINFO_VIRTUALS (base_base_binfo),
- chain);
- chain = TREE_VEC_ELT (base_binfos, j);
- TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
- TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
- BINFO_INHERITANCE_CHAIN (chain) = vbase_types;
- }
+/* If the empty base field in DECL overlaps with a base of the same type in
+ NEWDECL, which is either another base field or the first data field of
+ the class, pad the base just before NEWDECL and return 1. Otherwise,
+ return 0. */
+
+static int
+avoid_overlap (decl, newdecl)
+ tree decl, newdecl;
+{
+ tree field;
+
+ if (newdecl == NULL_TREE
+ || ! types_overlap_p (TREE_TYPE (decl), TREE_TYPE (newdecl)))
+ return 0;
+
+ for (field = decl; TREE_CHAIN (field) && TREE_CHAIN (field) != newdecl;
+ field = TREE_CHAIN (field))
+ ;
+
+ DECL_SIZE (field) = integer_one_node;
+
+ return 1;
+}
- propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types));
+/* Returns a list of fields to stand in for the base class subobjects
+ of REC. These fields are later removed by layout_basetypes. */
+
+tree
+build_base_fields (rec)
+ tree rec;
+{
+ /* Chain to hold all the new FIELD_DECLs which stand in for base class
+ subobjects. */
+ tree base_decls = NULL_TREE;
+ tree binfos = TYPE_BINFO_BASETYPES (rec);
+ int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ tree decl, nextdecl;
+ int i, saw_empty = 0;
+ unsigned int base_align = 0;
+
+ for (i = 0; i < n_baseclasses; ++i)
+ {
+ register tree base_binfo = TREE_VEC_ELT (binfos, i);
+ register tree basetype = BINFO_TYPE (base_binfo);
+
+ if (TYPE_SIZE (basetype) == 0)
+ /* This error is now reported in xref_tag, thus giving better
+ location information. */
+ continue;
+
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ continue;
+
+ decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, basetype);
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_FIELD_CONTEXT (decl) = DECL_CLASS_CONTEXT (decl) = rec;
+ DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
+ DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
+ TREE_CHAIN (decl) = base_decls;
+ base_decls = decl;
+
+ if (! flag_new_abi)
+ {
+ /* Brain damage for backwards compatibility. For no good reason,
+ the old layout_basetypes made every base at least as large as
+ the alignment for the bases up to that point, gratuitously
+ wasting space. So we do the same thing here. */
+ base_align = MAX (base_align, DECL_ALIGN (decl));
+ DECL_SIZE (decl)
+ = size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
+ base_align));
}
+ else if (DECL_SIZE (decl) == integer_zero_node)
+ saw_empty = 1;
}
- return max;
-}
+ /* Reverse the list of fields so we allocate the bases in the proper
+ order. */
+ base_decls = nreverse (base_decls);
-/* Lay out the base types of a record type, REC.
- Tentatively set the size and alignment of REC
- according to the base types alone.
+ /* In the presence of empty base classes, we run the risk of allocating
+ two objects of the same class on top of one another. Avoid that. */
+ if (flag_new_abi && saw_empty)
+ for (decl = base_decls; decl; decl = TREE_CHAIN (decl))
+ {
+ if (DECL_SIZE (decl) == integer_zero_node)
+ {
+ /* First step through the following bases until we find
+ an overlap or a non-empty base. */
+ for (nextdecl = TREE_CHAIN (decl); nextdecl;
+ nextdecl = TREE_CHAIN (nextdecl))
+ {
+ if (avoid_overlap (decl, nextdecl)
+ || DECL_SIZE (nextdecl) != integer_zero_node)
+ goto nextbase;
+ }
+
+ /* If we're still looking, also check against the first
+ field. */
+ for (nextdecl = TYPE_FIELDS (rec);
+ nextdecl && TREE_CODE (nextdecl) != FIELD_DECL;
+ nextdecl = TREE_CHAIN (nextdecl))
+ /* keep looking */;
+ avoid_overlap (decl, nextdecl);
+ }
+ nextbase:;
+ }
- Offsets for immediate nonvirtual baseclasses are also computed here.
+ return base_decls;
+}
- TYPE_BINFO (REC) should be NULL_TREE on entry, and this routine
- creates a list of base_binfos in TYPE_BINFO (REC) from BINFOS.
+/* Returns list of virtual base class pointers in a FIELD_DECL chain. */
- Returns list of virtual base classes in a FIELD_DECL chain. */
tree
-layout_basetypes (rec, binfos)
- tree rec, binfos;
+build_vbase_pointer_fields (rec)
+ tree rec;
{
/* Chain to hold all the new FIELD_DECLs which point at virtual
base classes. */
tree vbase_decls = NULL_TREE;
-
-#ifdef STRUCTURE_SIZE_BOUNDARY
- unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec));
-#else
- unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
-#endif
-
- /* Record size so far is CONST_SIZE + VAR_SIZE bits, where CONST_SIZE is
- an integer and VAR_SIZE is a tree expression. If VAR_SIZE is null,
- the size is just CONST_SIZE. Naturally we try to avoid using
- VAR_SIZE. And so far, we've been successful. */
-#if 0
- register tree var_size = 0;
-#endif
-
- register unsigned const_size = 0;
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ tree binfos = TYPE_BINFO_BASETYPES (rec);
+ int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ tree decl;
+ int i;
/* Handle basetypes almost like fields, but record their
offsets differently. */
for (i = 0; i < n_baseclasses; i++)
{
- int inc, desired_align, int_vbase_size;
register tree base_binfo = TREE_VEC_ELT (binfos, i);
register tree basetype = BINFO_TYPE (base_binfo);
- tree decl, offset;
if (TYPE_SIZE (basetype) == 0)
- {
-#if 0
- /* This error is now reported in xref_tag, thus giving better
- location information. */
- error_with_aggr_type (base_binfo,
- "base class `%s' has incomplete type");
-
- TREE_VIA_PUBLIC (base_binfo) = 1;
- TREE_VIA_PROTECTED (base_binfo) = 0;
- TREE_VIA_VIRTUAL (base_binfo) = 0;
-
- /* Should handle this better so that
-
- class A;
- class B: private A { virtual void F(); };
-
- does not dump core when compiled. */
- my_friendly_abort (121);
-#endif
- continue;
- }
+ /* This error is now reported in xref_tag, thus giving better
+ location information. */
+ continue;
/* All basetypes are recorded in the association list of the
derived type. */
@@ -816,17 +941,20 @@ layout_basetypes (rec, binfos)
tree other_base_binfo = TREE_VEC_ELT (binfos, j);
if (! TREE_VIA_VIRTUAL (other_base_binfo)
&& binfo_member (basetype,
- CLASSTYPE_VBASECLASSES (BINFO_TYPE (other_base_binfo))))
+ CLASSTYPE_VBASECLASSES (BINFO_TYPE
+ (other_base_binfo))
+ ))
goto got_it;
}
sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype));
- decl = build_lang_decl (FIELD_DECL, get_identifier (name),
- build_pointer_type (basetype));
+ decl = build_lang_field_decl (FIELD_DECL, get_identifier (name),
+ build_pointer_type (basetype));
/* If you change any of the below, take a look at all the
other VFIELD_BASEs and VTABLE_BASEs in the code, and change
- them too. */
+ them too. */
DECL_ASSEMBLER_NAME (decl) = get_identifier (VTABLE_BASE);
DECL_VIRTUAL_P (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
DECL_FIELD_CONTEXT (decl) = rec;
DECL_CLASS_CONTEXT (decl) = rec;
DECL_FCONTEXT (decl) = basetype;
@@ -837,78 +965,12 @@ layout_basetypes (rec, binfos)
BINFO_VPTR_FIELD (base_binfo) = decl;
vbase_decls = decl;
- if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE)
- {
- warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0),
- "destructor `%s' non-virtual");
- warning ("in inheritance relationship `%s: virtual %s'",
- TYPE_NAME_STRING (rec),
- TYPE_NAME_STRING (basetype));
- }
got_it:
/* The space this decl occupies has already been accounted for. */
- continue;
- }
-
- if (const_size == 0)
- offset = integer_zero_node;
- else
- {
- /* Give each base type the alignment it wants. */
- const_size = CEIL (const_size, TYPE_ALIGN (basetype))
- * TYPE_ALIGN (basetype);
- offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
-
-#if 0
- /* bpk: Disabled this check until someone is willing to
- claim it as theirs and explain exactly what circumstances
- warrant the warning. */
- if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE)
- {
- warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0),
- "destructor `%s' non-virtual");
- warning ("in inheritance relationship `%s:%s %s'",
- TYPE_NAME_STRING (rec),
- TREE_VIA_VIRTUAL (base_binfo) ? " virtual" : "",
- TYPE_NAME_STRING (basetype));
- }
-#endif
- }
- BINFO_OFFSET (base_binfo) = offset;
- if (CLASSTYPE_VSIZE (basetype))
- {
- BINFO_VTABLE (base_binfo) = TYPE_BINFO_VTABLE (basetype);
- BINFO_VIRTUALS (base_binfo) = TYPE_BINFO_VIRTUALS (basetype);
- }
- TREE_CHAIN (base_binfo) = TYPE_BINFO (rec);
- TYPE_BINFO (rec) = base_binfo;
-
- /* Add only the amount of storage not present in
- the virtual baseclasses. */
-
- int_vbase_size = TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype));
- if (TREE_INT_CST_LOW (TYPE_SIZE (basetype)) > int_vbase_size)
- {
- inc = MAX (record_align,
- (TREE_INT_CST_LOW (TYPE_SIZE (basetype))
- - int_vbase_size));
-
- /* Record must have at least as much alignment as any field. */
- desired_align = TYPE_ALIGN (basetype);
- record_align = MAX (record_align, desired_align);
-
- const_size += inc;
+ ;
}
}
- if (const_size)
- CLASSTYPE_SIZE (rec) = size_int (const_size);
- else
- CLASSTYPE_SIZE (rec) = integer_zero_node;
- CLASSTYPE_ALIGN (rec) = record_align;
-
return vbase_decls;
}
@@ -932,27 +994,27 @@ struct list_hash
and the hash code is computed differently for each of these. */
#define TYPE_HASH_SIZE 59
-struct list_hash *list_hash_table[TYPE_HASH_SIZE];
+static struct list_hash *list_hash_table[TYPE_HASH_SIZE];
/* Compute a hash code for a list (chain of TREE_LIST nodes
with goodies in the TREE_PURPOSE, TREE_VALUE, and bits of the
TREE_COMMON slots), by adding the hash codes of the individual entries. */
-int
-list_hash (list)
- tree list;
+static int
+list_hash (purpose, value, chain)
+ tree purpose, value, chain;
{
register int hashcode = 0;
- if (TREE_CHAIN (list))
- hashcode += TYPE_HASH (TREE_CHAIN (list));
+ if (chain)
+ hashcode += TYPE_HASH (chain);
- if (TREE_VALUE (list))
- hashcode += TYPE_HASH (TREE_VALUE (list));
+ if (value)
+ hashcode += TYPE_HASH (value);
else
hashcode += 1007;
- if (TREE_PURPOSE (list))
- hashcode += TYPE_HASH (TREE_PURPOSE (list));
+ if (purpose)
+ hashcode += TYPE_HASH (purpose);
else
hashcode += 1009;
return hashcode;
@@ -961,31 +1023,30 @@ list_hash (list)
/* Look in the type hash table for a type isomorphic to TYPE.
If one is found, return it. Otherwise return 0. */
-tree
-list_hash_lookup (hashcode, list)
- int hashcode;
- tree list;
+static tree
+list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
+ purpose, value, chain)
+ int hashcode, via_public, via_virtual, via_protected;
+ tree purpose, value, chain;
{
register struct list_hash *h;
+
for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
if (h->hashcode == hashcode
- && TREE_VIA_VIRTUAL (h->list) == TREE_VIA_VIRTUAL (list)
- && TREE_VIA_PUBLIC (h->list) == TREE_VIA_PUBLIC (list)
- && TREE_VIA_PROTECTED (h->list) == TREE_VIA_PROTECTED (list)
- && TREE_PURPOSE (h->list) == TREE_PURPOSE (list)
- && TREE_VALUE (h->list) == TREE_VALUE (list)
- && TREE_CHAIN (h->list) == TREE_CHAIN (list))
- {
- my_friendly_assert (TREE_TYPE (h->list) == TREE_TYPE (list), 299);
- return h->list;
- }
+ && TREE_VIA_VIRTUAL (h->list) == via_virtual
+ && TREE_VIA_PUBLIC (h->list) == via_public
+ && TREE_VIA_PROTECTED (h->list) == via_protected
+ && TREE_PURPOSE (h->list) == purpose
+ && TREE_VALUE (h->list) == value
+ && TREE_CHAIN (h->list) == chain)
+ return h->list;
return 0;
}
/* Add an entry to the list-hash-table
for a list TYPE whose hash code is HASHCODE. */
-void
+static void
list_hash_add (hashcode, list)
int hashcode;
tree list;
@@ -1011,30 +1072,8 @@ list_hash_add (hashcode, list)
This function frees the list you pass in if it is a duplicate. */
/* Set to 1 to debug without canonicalization. Never set by program. */
-static int debug_no_list_hash = 0;
-
-tree
-list_hash_canon (hashcode, list)
- int hashcode;
- tree list;
-{
- tree t1;
-
- if (debug_no_list_hash)
- return list;
-
- t1 = list_hash_lookup (hashcode, list);
- if (t1 != 0)
- {
- obstack_free (&class_obstack, list);
- return t1;
- }
- /* If this is a new list, record it for later reuse. */
- list_hash_add (hashcode, list);
-
- return list;
-}
+static int debug_no_list_hash = 0;
tree
hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
@@ -1043,37 +1082,43 @@ hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
{
struct obstack *ambient_obstack = current_obstack;
tree t;
- int hashcode;
+ int hashcode = 0;
+
+ if (! debug_no_list_hash)
+ {
+ hashcode = list_hash (purpose, value, chain);
+ t = list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
+ purpose, value, chain);
+ if (t)
+ return t;
+ }
current_obstack = &class_obstack;
+
t = tree_cons (purpose, value, chain);
TREE_VIA_PUBLIC (t) = via_public;
TREE_VIA_PROTECTED (t) = via_protected;
TREE_VIA_VIRTUAL (t) = via_virtual;
- hashcode = list_hash (t);
- t = list_hash_canon (hashcode, t);
+
+ /* If this is a new list, record it for later reuse. */
+ if (! debug_no_list_hash)
+ list_hash_add (hashcode, t);
+
current_obstack = ambient_obstack;
return t;
}
/* Constructor for hashed lists. */
+
tree
hash_tree_chain (value, chain)
tree value, chain;
{
- struct obstack *ambient_obstack = current_obstack;
- tree t;
- int hashcode;
-
- current_obstack = &class_obstack;
- t = tree_cons (NULL_TREE, value, chain);
- hashcode = list_hash (t);
- t = list_hash_canon (hashcode, t);
- current_obstack = ambient_obstack;
- return t;
+ return hash_tree_cons (0, 0, 0, NULL_TREE, value, chain);
}
/* Similar, but used for concatenating two lists. */
+
tree
hash_chainon (list1, list2)
tree list1, list2;
@@ -1111,17 +1156,9 @@ get_identifier_list (value)
list = tree_cons (NULL_TREE, value, NULL_TREE);
else
{
- register tree id;
- /* This will return the correct thing for regular types,
- nested types, and templates. Yay! */
- if (TYPE_NESTED_NAME (type))
- id = TYPE_NESTED_NAME (type);
- else
- id = TYPE_IDENTIFIER (type);
-
- if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
+ if (! CLASSTYPE_ID_AS_LIST (type))
CLASSTYPE_ID_AS_LIST (type)
- = perm_tree_cons (NULL_TREE, id, NULL_TREE);
+ = perm_tree_cons (NULL_TREE, TYPE_IDENTIFIER (type), NULL_TREE);
list = CLASSTYPE_ID_AS_LIST (type);
}
}
@@ -1137,7 +1174,8 @@ get_decl_list (value)
if (TREE_CODE (value) == IDENTIFIER_NODE)
list = get_identifier_list (value);
else if (TREE_CODE (value) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (value))
+ && TYPE_LANG_SPECIFIC (value)
+ && value == TYPE_MAIN_VARIANT (value))
list = CLASSTYPE_AS_LIST (value);
if (list != NULL_TREE)
@@ -1148,59 +1186,6 @@ get_decl_list (value)
return build_decl_list (NULL_TREE, value);
}
-
-/* Look in the type hash table for a type isomorphic to
- `build_tree_list (NULL_TREE, VALUE)'.
- If one is found, return it. Otherwise return 0. */
-
-tree
-list_hash_lookup_or_cons (value)
- tree value;
-{
- register int hashcode = TYPE_HASH (value);
- register struct list_hash *h;
- struct obstack *ambient_obstack;
- tree list = NULL_TREE;
-
- if (TREE_CODE (value) == IDENTIFIER_NODE)
- list = get_identifier_list (value);
- else if (TREE_CODE (value) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (TREE_TYPE (value)))
- list = CLASSTYPE_ID_AS_LIST (TREE_TYPE (value));
- else if (TREE_CODE (value) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (value))
- list = CLASSTYPE_AS_LIST (value);
-
- if (list != NULL_TREE)
- {
- my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 302);
- return list;
- }
-
- if (debug_no_list_hash)
- return hash_tree_chain (value, NULL_TREE);
-
- for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
- if (h->hashcode == hashcode
- && TREE_VIA_VIRTUAL (h->list) == 0
- && TREE_VIA_PUBLIC (h->list) == 0
- && TREE_VIA_PROTECTED (h->list) == 0
- && TREE_PURPOSE (h->list) == 0
- && TREE_VALUE (h->list) == value)
- {
- my_friendly_assert (TREE_TYPE (h->list) == 0, 303);
- my_friendly_assert (TREE_CHAIN (h->list) == 0, 304);
- return h->list;
- }
-
- ambient_obstack = current_obstack;
- current_obstack = &class_obstack;
- list = build_tree_list (NULL_TREE, value);
- list_hash_add (hashcode, list);
- current_obstack = ambient_obstack;
- return list;
-}
/* Build an association between TYPE and some parameters:
@@ -1210,7 +1195,7 @@ list_hash_lookup_or_cons (value)
BINFO is the base binfo to use, if we are deriving from one. This
is necessary, as we want specialized parent binfos from base
classes, so that the VTABLE_NAMEs of bases are for the most derived
- type, instead of of the simple type.
+ type, instead of the simple type.
VTABLE is the virtual function table with which to initialize
sub-objects of type TYPE.
@@ -1225,7 +1210,7 @@ make_binfo (offset, binfo, vtable, virtuals, chain)
tree vtable, virtuals;
tree chain;
{
- tree new_binfo = make_tree_vec (6);
+ tree new_binfo = make_tree_vec (7);
tree type;
if (TREE_CODE (binfo) == TREE_VEC)
@@ -1282,38 +1267,6 @@ reverse_path (path)
return prev;
}
-tree
-virtual_member (elem, list)
- tree elem;
- tree list;
-{
- tree t;
- tree rval, nval;
-
- for (t = list; t; t = TREE_CHAIN (t))
- if (elem == BINFO_TYPE (t))
- return t;
- rval = 0;
- for (t = list; t; t = TREE_CHAIN (t))
- {
- tree binfos = BINFO_BASETYPES (t);
- int i;
-
- if (binfos != NULL_TREE)
- for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
- {
- nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
- if (nval)
- {
- if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval))
- my_friendly_abort (104);
- rval = nval;
- }
- }
- }
- return rval;
-}
-
void
debug_binfo (elem)
tree elem;
@@ -1321,9 +1274,9 @@ debug_binfo (elem)
unsigned HOST_WIDE_INT n;
tree virtuals;
- fprintf (stderr, "type \"%s\"; offset = %d\n",
+ fprintf (stderr, "type \"%s\"; offset = %ld\n",
TYPE_NAME_STRING (BINFO_TYPE (elem)),
- TREE_INT_CST_LOW (BINFO_OFFSET (elem)));
+ (long) TREE_INT_CST_LOW (BINFO_OFFSET (elem)));
fprintf (stderr, "vtable type:\n");
debug_tree (BINFO_TYPE (elem));
if (BINFO_VTABLE (elem))
@@ -1338,142 +1291,168 @@ debug_binfo (elem)
while (virtuals)
{
tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
- fprintf (stderr, "%s [%d =? %d]\n",
+ fprintf (stderr, "%s [%ld =? %ld]\n",
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
- n, TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
+ (long) n, (long) TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
++n;
virtuals = TREE_CHAIN (virtuals);
}
}
-/* Return the length of a chain of nodes chained through DECL_CHAIN.
- We expect a null pointer to mark the end of the chain.
- This is the Lisp primitive `length'. */
+/* Initialize an CPLUS_BINDING node that does not live on an obstack. */
-int
-decl_list_length (t)
- tree t;
+tree
+binding_init (node)
+ struct tree_binding* node;
{
- register tree tail;
- register int len = 0;
-
- my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL
- || TREE_CODE (t) == TEMPLATE_DECL, 300);
- for (tail = t; tail; tail = DECL_CHAIN (tail))
- len++;
-
- return len;
+ static struct tree_binding* source;
+ if (!source)
+ {
+ extern struct obstack permanent_obstack;
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ source = (struct tree_binding*)make_node (CPLUS_BINDING);
+ pop_obstacks ();
+ }
+ *node = *source;
+ TREE_PERMANENT ((tree)node) = 0;
+ return (tree)node;
}
int
count_functions (t)
tree t;
{
+ int i;
if (TREE_CODE (t) == FUNCTION_DECL)
return 1;
- else if (TREE_CODE (t) == TREE_LIST)
- return decl_list_length (TREE_VALUE (t));
+ else if (TREE_CODE (t) == OVERLOAD)
+ {
+ for (i=0; t; t = OVL_CHAIN (t))
+ i++;
+ return i;
+ }
my_friendly_abort (359);
return 0;
}
-/* Like value_member, but for DECL_CHAINs. */
-tree
-decl_value_member (elem, list)
- tree elem, list;
-{
- while (list)
- {
- if (elem == list)
- return list;
- list = DECL_CHAIN (list);
- }
- return NULL_TREE;
-}
-
int
is_overloaded_fn (x)
tree x;
{
- if (TREE_CODE (x) == FUNCTION_DECL)
- return 1;
-
- if (TREE_CODE (x) == TREE_LIST
- && (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
- || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
- return 1;
-
- return 0;
+ /* XXX A baselink is also considered an overloaded function.
+ As is a placeholder from push_class_decls. */
+ if (TREE_CODE (x) == TREE_LIST)
+ {
+ my_friendly_assert (TREE_CODE (TREE_PURPOSE (x)) == TREE_VEC
+ || TREE_CODE (TREE_PURPOSE (x)) == IDENTIFIER_NODE,
+ 388);
+ x = TREE_VALUE (x);
+ }
+ return (TREE_CODE (x) == FUNCTION_DECL
+ || TREE_CODE (x) == TEMPLATE_ID_EXPR
+ || DECL_FUNCTION_TEMPLATE_P (x)
+ || TREE_CODE (x) == OVERLOAD);
}
int
really_overloaded_fn (x)
tree x;
{
- if (TREE_CODE (x) == TREE_LIST
- && (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
- || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
- return 1;
-
- return 0;
+ /* A baselink is also considered an overloaded function.
+ This might also be an ambiguous class member. */
+ if (TREE_CODE (x) == TREE_LIST)
+ x = TREE_VALUE (x);
+ return (TREE_CODE (x) == OVERLOAD
+ && (TREE_CHAIN (x) != NULL_TREE
+ || DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (x))));
}
tree
get_first_fn (from)
tree from;
{
- if (TREE_CODE (from) == FUNCTION_DECL)
- return from;
+ my_friendly_assert (is_overloaded_fn (from), 9);
+ /* A baselink is also considered an overloaded function. */
+ if (TREE_CODE (from) == TREE_LIST)
+ from = TREE_VALUE (from);
+ return OVL_CURRENT (from);
+}
- my_friendly_assert (TREE_CODE (from) == TREE_LIST, 9);
+/* Return a new OVL node, concatenating it with the old one. */
+
+tree
+ovl_cons (decl, chain)
+ tree decl;
+ tree chain;
+{
+ tree result = make_node (OVERLOAD);
+ TREE_TYPE (result) = unknown_type_node;
+ OVL_FUNCTION (result) = decl;
+ TREE_CHAIN (result) = chain;
- return TREE_VALUE (from);
+ return result;
}
+/* Same as ovl_cons, but on the scratch_obstack. */
+
tree
-fnaddr_from_vtable_entry (entry)
- tree entry;
+scratch_ovl_cons (value, chain)
+ tree value, chain;
{
- if (flag_vtable_thunks)
- {
- tree func = entry;
- if (TREE_CODE (func) == ADDR_EXPR)
- func = TREE_OPERAND (func, 0);
- if (TREE_CODE (func) == THUNK_DECL)
- return DECL_INITIAL (func);
- else
- return entry;
- }
- else
- return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));
+ register tree node;
+ register struct obstack *ambient_obstack = current_obstack;
+ extern struct obstack *expression_obstack;
+ current_obstack = expression_obstack;
+ node = ovl_cons (value, chain);
+ current_obstack = ambient_obstack;
+ return node;
}
-void
-set_fnaddr_from_vtable_entry (entry, value)
- tree entry, value;
+/* Build a new overloaded function. If this is the first one,
+ just return it; otherwise, ovl_cons the _DECLs */
+
+tree
+build_overload (decl, chain)
+ tree decl;
+ tree chain;
{
- if (flag_vtable_thunks)
- abort ();
- else
- TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry)))) = value;
+ if (!chain)
+ return decl;
+ if (TREE_CODE (chain) != OVERLOAD)
+ chain = ovl_cons (chain, NULL_TREE);
+ return ovl_cons (decl, chain);
}
-tree
-function_arg_chain (t)
- tree t;
+/* Returns true iff functions are equivalent. Equivalent functions are
+ not identical only if one is a function-local extern function.
+ This assumes that function-locals don't have TREE_PERMANENT. */
+
+static int
+equal_functions (fn1, fn2)
+ tree fn1;
+ tree fn2;
{
- return TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (t)));
+ if (!TREE_PERMANENT (fn1) || !TREE_PERMANENT (fn2))
+ return decls_match (fn1, fn2);
+ return fn1 == fn2;
}
+/* True if fn is in ovl. */
+
int
-promotes_to_aggr_type (t, code)
- tree t;
- enum tree_code code;
+ovl_member (fn, ovl)
+ tree fn;
+ tree ovl;
{
- if (TREE_CODE (t) == code)
- t = TREE_TYPE (t);
- return IS_AGGR_TYPE (t);
+ if (ovl == NULL_TREE)
+ return 0;
+ if (TREE_CODE (ovl) != OVERLOAD)
+ return equal_functions (ovl, fn);
+ for (; ovl; ovl = OVL_CHAIN (ovl))
+ if (equal_functions (OVL_FUNCTION (ovl), fn))
+ return 1;
+ return 0;
}
int
@@ -1484,30 +1463,13 @@ is_aggr_type_2 (t1, t2)
return 0;
return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
}
-
-/* Give message using types TYPE1 and TYPE2 as arguments.
- PFN is the function which will print the message;
- S is the format string for PFN to use. */
-void
-message_2_types (pfn, s, type1, type2)
- void (*pfn) ();
- char *s;
- tree type1, type2;
-{
- tree name1 = TYPE_NAME (type1);
- tree name2 = TYPE_NAME (type2);
- if (TREE_CODE (name1) == TYPE_DECL)
- name1 = DECL_NAME (name1);
- if (TREE_CODE (name2) == TYPE_DECL)
- name2 = DECL_NAME (name2);
- (*pfn) (s, IDENTIFIER_POINTER (name1), IDENTIFIER_POINTER (name2));
-}
#define PRINT_RING_SIZE 4
char *
-lang_printable_name (decl)
+lang_printable_name (decl, v)
tree decl;
+ int v;
{
static tree decl_ring[PRINT_RING_SIZE];
static char *print_ring[PRINT_RING_SIZE];
@@ -1515,9 +1477,10 @@ lang_printable_name (decl)
int i;
/* Only cache functions. */
- if (TREE_CODE (decl) != FUNCTION_DECL
+ if (v < 2
+ || TREE_CODE (decl) != FUNCTION_DECL
|| DECL_LANG_SPECIFIC (decl) == 0)
- return decl_as_string (decl, 1);
+ return lang_decl_name (decl, v);
/* See if this print name is lying around. */
for (i = 0; i < PRINT_RING_SIZE; i++)
@@ -1541,50 +1504,30 @@ lang_printable_name (decl)
if (print_ring[ring_counter])
free (print_ring[ring_counter]);
- {
- int print_ret_type_p
- = (!DECL_CONSTRUCTOR_P (decl)
- && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
-
- char *name = (char *)decl_as_string (decl, print_ret_type_p);
- print_ring[ring_counter] = (char *)malloc (strlen (name) + 1);
- strcpy (print_ring[ring_counter], name);
- decl_ring[ring_counter] = decl;
- }
+ print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v));
+ decl_ring[ring_counter] = decl;
return print_ring[ring_counter];
}
-/* Comparison function for sorting identifiers in RAISES lists.
- Note that because IDENTIFIER_NODEs are unique, we can sort
- them by address, saving an indirection. */
-static int
-id_cmp (p1, p2)
- tree *p1, *p2;
-{
- return (HOST_WIDE_INT)TREE_VALUE (*p1) - (HOST_WIDE_INT)TREE_VALUE (*p2);
-}
-
/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions
listed in RAISES. */
+
tree
build_exception_variant (type, raises)
tree type;
tree raises;
{
- int i;
tree v = TYPE_MAIN_VARIANT (type);
- tree t, t2, cname;
- tree *a = (tree *)alloca ((list_length (raises)+1) * sizeof (tree));
int constp = TYPE_READONLY (type);
int volatilep = TYPE_VOLATILE (type);
- for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v))
+ for (; v; v = TYPE_NEXT_VARIANT (v))
{
if (TYPE_READONLY (v) != constp
|| TYPE_VOLATILE (v) != volatilep)
continue;
- /* @@ This should do set equality, not exact match. */
+ /* @@ This should do set equality, not exact match. */
if (simple_cst_list_equal (TYPE_RAISES_EXCEPTIONS (v), raises))
/* List of exceptions raised matches previously found list.
@@ -1594,9 +1537,8 @@ build_exception_variant (type, raises)
}
/* Need to build a new variant. */
- v = copy_node (type);
- TYPE_NEXT_VARIANT (v) = TYPE_NEXT_VARIANT (type);
- TYPE_NEXT_VARIANT (type) = v;
+ v = build_type_copy (type);
+
if (raises && ! TREE_PERMANENT (raises))
{
push_obstacks_nochange ();
@@ -1604,10 +1546,32 @@ build_exception_variant (type, raises)
raises = copy_list (raises);
pop_obstacks ();
}
+
TYPE_RAISES_EXCEPTIONS (v) = raises;
return v;
}
+/* Given a TEMPLATE_TEMPLATE_PARM node T, create a new one together with its
+ lang_specific field and its corresponding TEMPLATE_DECL node */
+
+tree
+copy_template_template_parm (t)
+ tree t;
+{
+ tree template = TYPE_NAME (t);
+ tree t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
+ template = copy_node (template);
+ copy_lang_decl (template);
+ TREE_TYPE (template) = t2;
+ TYPE_NAME (t2) = template;
+ TYPE_STUB_DECL (t2) = template;
+
+ /* No need to copy these */
+ TYPE_FIELDS (t2) = TYPE_FIELDS (t);
+ CLASSTYPE_TEMPLATE_INFO (t2) = CLASSTYPE_TEMPLATE_INFO (t);
+ return t2;
+}
+
/* Subroutine of copy_to_permanent
Assuming T is a node build bottom-up, make it all exist on
@@ -1616,9 +1580,8 @@ build_exception_variant (type, raises)
tree
mapcar (t, func)
tree t;
- tree (*func)();
+ tree (*func) PROTO((tree));
{
- enum tree_code code;
tree tmp;
if (t == NULL_TREE)
@@ -1627,7 +1590,7 @@ mapcar (t, func)
if (tmp = func (t), tmp != NULL_TREE)
return tmp;
- switch (code = TREE_CODE (t))
+ switch (TREE_CODE (t))
{
case ERROR_MARK:
return error_mark_node;
@@ -1635,7 +1598,21 @@ mapcar (t, func)
case VAR_DECL:
case FUNCTION_DECL:
case CONST_DECL:
- break;
+ /* Rather than aborting, return error_mark_node. This allows us
+ to report a sensible error message on code like this:
+
+ void g() { int i; f<i>(7); }
+
+ In a case like:
+
+ void g() { const int i = 7; f<i>(7); }
+
+ however, we must actually return the constant initializer. */
+ tmp = decl_constant_value (t);
+ if (tmp != t)
+ return mapcar (tmp, func);
+ else
+ return error_mark_node;
case PARM_DECL:
{
@@ -1658,6 +1635,15 @@ mapcar (t, func)
return t;
}
+ case OVERLOAD:
+ {
+ tree chain = OVL_CHAIN (t);
+ t = copy_node (t);
+ OVL_FUNCTION (t) = mapcar (OVL_FUNCTION (t), func);
+ OVL_CHAIN (t) = mapcar (chain, func);
+ return t;
+ }
+
case TREE_VEC:
{
int len = TREE_VEC_LENGTH (t);
@@ -1675,7 +1661,7 @@ mapcar (t, func)
case COND_EXPR:
case TARGET_EXPR:
- case NEW_EXPR:
+ case AGGR_INIT_EXPR:
t = copy_node (t);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
@@ -1720,10 +1706,28 @@ mapcar (t, func)
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
+ case ARRAY_REF:
+ case SCOPE_REF:
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
+ t = copy_node (t);
+ TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+ TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
+ return t;
+
case CALL_EXPR:
t = copy_node (t);
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
+
+ /* tree.def says that operand two is RTL, but
+ build_call_declarator puts trees in there. */
+ if (TREE_OPERAND (t, 2)
+ && TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST)
+ TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
+ else
+ TREE_OPERAND (t, 2) = NULL_TREE;
return t;
case CONVERT_EXPR:
@@ -1734,32 +1738,66 @@ mapcar (t, func)
case TRUTH_NOT_EXPR:
case NOP_EXPR:
case COMPONENT_REF:
+ case CLEANUP_POINT_EXPR:
t = copy_node (t);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
return t;
case POINTER_TYPE:
- return build_pointer_type (mapcar (TREE_TYPE (t), func));
+ tmp = build_pointer_type (mapcar (TREE_TYPE (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case REFERENCE_TYPE:
- return build_reference_type (mapcar (TREE_TYPE (t), func));
+ tmp = build_reference_type (mapcar (TREE_TYPE (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case FUNCTION_TYPE:
- return build_function_type (mapcar (TREE_TYPE (t), func),
- mapcar (TYPE_ARG_TYPES (t), func));
+ tmp = build_function_type (mapcar (TREE_TYPE (t), func),
+ mapcar (TYPE_ARG_TYPES (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case ARRAY_TYPE:
- return build_array_type (mapcar (TREE_TYPE (t), func),
- mapcar (TYPE_DOMAIN (t), func));
+ tmp = build_cplus_array_type (mapcar (TREE_TYPE (t), func),
+ mapcar (TYPE_DOMAIN (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case INTEGER_TYPE:
- return build_index_type (mapcar (TYPE_MAX_VALUE (t), func));
-
+ tmp = build_index_type (mapcar (TYPE_MAX_VALUE (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case OFFSET_TYPE:
- return build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func),
- mapcar (TREE_TYPE (t), func));
+ tmp = build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func),
+ mapcar (TREE_TYPE (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case METHOD_TYPE:
- return build_method_type
- (mapcar (TYPE_METHOD_BASETYPE (t), func),
- build_function_type
- (mapcar (TREE_TYPE (t), func),
- mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func)));
+ tmp = build_cplus_method_type
+ (mapcar (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), func),
+ mapcar (TREE_TYPE (t), func),
+ mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+
+ case COMPLEX_CST:
+ t = copy_node (t);
+ TREE_REALPART (t) = mapcar (TREE_REALPART (t), func);
+ TREE_IMAGPART (t) = mapcar (TREE_REALPART (t), func);
+ return t;
+
+ case CONSTRUCTOR:
+ t = copy_node (t);
+ CONSTRUCTOR_ELTS (t) = mapcar (CONSTRUCTOR_ELTS (t), func);
+ return t;
+
+ case TEMPLATE_TEMPLATE_PARM:
+ return copy_template_template_parm (t);
+
+ case BIND_EXPR:
+ t = copy_node (t);
+ TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+ TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
+ TREE_OPERAND (t, 2) = NULL_TREE;
+ return t;
+
+ case NEW_EXPR:
+ t = copy_node (t);
+ TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+ TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
+ TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
+ return t;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
@@ -1768,7 +1806,7 @@ mapcar (t, func)
/* else fall through */
/* This list is incomplete, but should suffice for now.
- It is very important that `sorry' does not call
+ It is very important that `sorry' not call
`report_error_function'. That could cause an infinite loop. */
default:
sorry ("initializer contains unrecognized tree code");
@@ -1786,50 +1824,65 @@ perm_manip (t)
{
if (TREE_PERMANENT (t))
return t;
+
+ /* Support `void f () { extern int i; A<&i> a; }' */
+ if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL)
+ && TREE_PUBLIC (t))
+ {
+ t = copy_node (t);
+
+ /* copy_rtx won't make a new SYMBOL_REF, so call make_decl_rtl again. */
+ DECL_RTL (t) = 0;
+ make_decl_rtl (t, NULL_PTR, 1);
+
+ return t;
+ }
return NULL_TREE;
}
/* Assuming T is a node built bottom-up, make it all exist on
permanent obstack, if it is not permanent already. */
+
tree
copy_to_permanent (t)
tree t;
{
- register struct obstack *ambient_obstack = current_obstack;
- register struct obstack *ambient_saveable_obstack = saveable_obstack;
- int resume;
-
if (t == NULL_TREE || TREE_PERMANENT (t))
return t;
- saveable_obstack = &permanent_obstack;
- current_obstack = saveable_obstack;
- resume = suspend_momentary ();
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
t = mapcar (t, perm_manip);
- resume_momentary (resume);
- current_obstack = ambient_obstack;
- saveable_obstack = ambient_saveable_obstack;
+ pop_obstacks ();
return t;
}
+#ifdef GATHER_STATISTICS
+extern int depth_reached;
+#endif
+
void
print_lang_statistics ()
{
- extern struct obstack maybepermanent_obstack;
+ extern struct obstack decl_obstack;
print_obstack_statistics ("class_obstack", &class_obstack);
- print_obstack_statistics ("permanent_obstack", &permanent_obstack);
- print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack);
+ print_obstack_statistics ("decl_obstack", &decl_obstack);
print_search_statistics ();
print_class_statistics ();
+#ifdef GATHER_STATISTICS
+ fprintf (stderr, "maximum template instantiation depth reached: %d\n",
+ depth_reached);
+#endif
}
/* This is used by the `assert' macro. It is provided in libgcc.a,
which `cc' doesn't know how to link. Note that the C++ front-end
no longer actually uses the `assert' macro (instead, it calls
my_friendly_assert). But all of the back-end files still need this. */
+
void
__eprintf (string, expression, line, filename)
#ifdef __STDC__
@@ -1849,8 +1902,9 @@ __eprintf (string, expression, line, filename)
abort ();
}
-/* Return, as an INTEGER_CST node, the number of elements for
- TYPE (which is an ARRAY_TYPE). This counts only elements of the top array. */
+/* Return, as an INTEGER_CST node, the number of elements for TYPE
+ (which is an ARRAY_TYPE). This counts only elements of the top
+ array. */
tree
array_type_nelts_top (type)
@@ -1861,9 +1915,9 @@ array_type_nelts_top (type)
integer_one_node));
}
-/* Return, as an INTEGER_CST node, the number of elements for
- TYPE (which is an ARRAY_TYPE). This one is a recursive count of all
- ARRAY_TYPEs that are clumped together. */
+/* Return, as an INTEGER_CST node, the number of elements for TYPE
+ (which is an ARRAY_TYPE). This one is a recursive count of all
+ ARRAY_TYPEs that are clumped together. */
tree
array_type_nelts_total (type)
@@ -1888,12 +1942,26 @@ bot_manip (t)
if (TREE_CODE (t) != TREE_LIST && ! TREE_SIDE_EFFECTS (t))
return t;
else if (TREE_CODE (t) == TARGET_EXPR)
- return build_cplus_new (TREE_TYPE (t),
- break_out_target_exprs (TREE_OPERAND (t, 1)), 0);
+ {
+ if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
+ {
+ mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0));
+ return build_cplus_new
+ (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
+ }
+ t = copy_node (t);
+ TREE_OPERAND (t, 0) = build (VAR_DECL, TREE_TYPE (t));
+ layout_decl (TREE_OPERAND (t, 0), 0);
+ return t;
+ }
+ else if (TREE_CODE (t) == CALL_EXPR)
+ mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
+
return NULL_TREE;
}
/* Actually, we'll just clean out the target exprs for the moment. */
+
tree
break_out_target_exprs (t)
tree t;
@@ -1901,95 +1969,456 @@ break_out_target_exprs (t)
return mapcar (t, bot_manip);
}
+/* Obstack used for allocating nodes in template function and variable
+ definitions. */
+
+/* Similar to `build_nt', except we build
+ on the permanent_obstack, regardless. */
+
tree
-unsave_expr (expr)
- tree expr;
+build_min_nt VPROTO((enum tree_code code, ...))
{
- tree t;
+#ifndef __STDC__
+ enum tree_code code;
+#endif
+ register struct obstack *ambient_obstack = expression_obstack;
+ va_list p;
+ register tree t;
+ register int length;
+ register int i;
+
+ VA_START (p, code);
+
+#ifndef __STDC__
+ code = va_arg (p, enum tree_code);
+#endif
- t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr);
- TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr);
+ expression_obstack = &permanent_obstack;
+
+ t = make_node (code);
+ length = tree_code_length[(int) code];
+ TREE_COMPLEXITY (t) = lineno;
+
+ for (i = 0; i < length; i++)
+ {
+ tree x = va_arg (p, tree);
+ TREE_OPERAND (t, i) = copy_to_permanent (x);
+ }
+
+ va_end (p);
+ expression_obstack = ambient_obstack;
return t;
}
-/* Modify a tree in place so that all the evaluate only once things
- are cleared out. Return the EXPR given. */
+/* Similar to `build', except we build
+ on the permanent_obstack, regardless. */
+
tree
-unsave_expr_now (expr)
- tree expr;
+build_min VPROTO((enum tree_code code, tree tt, ...))
{
+#ifndef __STDC__
enum tree_code code;
+ tree tt;
+#endif
+ register struct obstack *ambient_obstack = expression_obstack;
+ va_list p;
+ register tree t;
+ register int length;
register int i;
- if (expr == NULL_TREE)
- return expr;
+ VA_START (p, tt);
+
+#ifndef __STDC__
+ code = va_arg (p, enum tree_code);
+ tt = va_arg (p, tree);
+#endif
- code = TREE_CODE (expr);
- switch (code)
+ expression_obstack = &permanent_obstack;
+
+ t = make_node (code);
+ length = tree_code_length[(int) code];
+ TREE_TYPE (t) = tt;
+ TREE_COMPLEXITY (t) = lineno;
+
+ for (i = 0; i < length; i++)
{
+ tree x = va_arg (p, tree);
+ TREE_OPERAND (t, i) = copy_to_permanent (x);
+ }
+
+ va_end (p);
+ expression_obstack = ambient_obstack;
+ return t;
+}
+
+/* Same as `tree_cons' but make a permanent object. */
+
+tree
+min_tree_cons (purpose, value, chain)
+ tree purpose, value, chain;
+{
+ register tree node;
+ register struct obstack *ambient_obstack = current_obstack;
+ current_obstack = &permanent_obstack;
+
+ node = tree_cons (copy_to_permanent (purpose),
+ copy_to_permanent (value), chain);
+ current_obstack = ambient_obstack;
+ return node;
+}
+
+tree
+get_type_decl (t)
+ tree t;
+{
+ if (TREE_CODE (t) == TYPE_DECL)
+ return t;
+ if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+ return TYPE_STUB_DECL (t);
+
+ my_friendly_abort (42);
+
+ /* Stop compiler from complaining control reaches end of non-void function. */
+ return 0;
+}
+
+int
+can_free (obstack, t)
+ struct obstack *obstack;
+ tree t;
+{
+ int size = 0;
+
+ if (TREE_CODE (t) == TREE_VEC)
+ size = (TREE_VEC_LENGTH (t)-1) * sizeof (tree) + sizeof (struct tree_vec);
+ else
+ my_friendly_abort (42);
+
+#define ROUND(x) ((x + obstack_alignment_mask (obstack)) \
+ & ~ obstack_alignment_mask (obstack))
+ if ((char *)t + ROUND (size) == obstack_next_free (obstack))
+ return 1;
+#undef ROUND
+
+ return 0;
+}
+
+/* Return first vector element whose BINFO_TYPE is ELEM.
+ Return 0 if ELEM is not in VEC. VEC may be NULL_TREE. */
+
+tree
+vec_binfo_member (elem, vec)
+ tree elem, vec;
+{
+ int i;
+
+ if (vec)
+ for (i = 0; i < TREE_VEC_LENGTH (vec); ++i)
+ if (comptypes (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i)), 1))
+ return TREE_VEC_ELT (vec, i);
+
+ return NULL_TREE;
+}
+
+/* Kludge around the fact that DECL_CONTEXT for virtual functions returns
+ the wrong thing for decl_function_context. Hopefully the uses in the
+ backend won't matter, since we don't need a static chain for local class
+ methods. FIXME! */
+
+tree
+hack_decl_function_context (decl)
+ tree decl;
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FUNCTION_MEMBER_P (decl))
+ return decl_function_context (TYPE_MAIN_DECL (DECL_CLASS_CONTEXT (decl)));
+ return decl_function_context (decl);
+}
+
+/* Return truthvalue of whether T1 is the same tree structure as T2.
+ Return 1 if they are the same.
+ Return 0 if they are understandably different.
+ Return -1 if either contains tree structure not understood by
+ this function. */
+
+int
+cp_tree_equal (t1, t2)
+ tree t1, t2;
+{
+ register enum tree_code code1, code2;
+ int cmp;
+
+ if (t1 == t2)
+ return 1;
+ if (t1 == 0 || t2 == 0)
+ return 0;
+
+ code1 = TREE_CODE (t1);
+ code2 = TREE_CODE (t2);
+
+ if (code1 == NOP_EXPR || code1 == CONVERT_EXPR || code1 == NON_LVALUE_EXPR)
+ {
+ if (code2 == NOP_EXPR || code2 == CONVERT_EXPR || code2 == NON_LVALUE_EXPR)
+ return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ else
+ return cp_tree_equal (TREE_OPERAND (t1, 0), t2);
+ }
+ else if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
+ || code2 == NON_LVALUE_EXPR)
+ return cp_tree_equal (t1, TREE_OPERAND (t2, 0));
+
+ if (code1 != code2)
+ return 0;
+
+ switch (code1)
+ {
+ case INTEGER_CST:
+ return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
+ && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
+
+ case REAL_CST:
+ return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
+
+ case STRING_CST:
+ return TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
+ && !bcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
+ TREE_STRING_LENGTH (t1));
+
+ case CONSTRUCTOR:
+ /* We need to do this when determining whether or not two
+ non-type pointer to member function template arguments
+ are the same. */
+ if (!(comptypes (TREE_TYPE (t1), TREE_TYPE (t2), 1)
+ /* The first operand is RTL. */
+ && TREE_OPERAND (t1, 0) == TREE_OPERAND (t2, 0)))
+ return 0;
+ return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+
+ case TREE_LIST:
+ cmp = cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
+ if (cmp <= 0)
+ return cmp;
+ cmp = cp_tree_equal (TREE_VALUE (t1), TREE_VALUE (t2));
+ if (cmp <= 0)
+ return cmp;
+ return cp_tree_equal (TREE_CHAIN (t1), TREE_CHAIN (t2));
+
case SAVE_EXPR:
- SAVE_EXPR_RTL (expr) = NULL_RTX;
- break;
+ return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+
+ case CALL_EXPR:
+ cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ if (cmp <= 0)
+ return cmp;
+ return simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
case TARGET_EXPR:
- sorry ("TARGET_EXPR reused inside UNSAVE_EXPR");
+ /* Special case: if either target is an unallocated VAR_DECL,
+ it means that it's going to be unified with whatever the
+ TARGET_EXPR is really supposed to initialize, so treat it
+ as being equivalent to anything. */
+ if ((TREE_CODE (TREE_OPERAND (t1, 0)) == VAR_DECL
+ && DECL_NAME (TREE_OPERAND (t1, 0)) == NULL_TREE
+ && DECL_RTL (TREE_OPERAND (t1, 0)) == 0)
+ || (TREE_CODE (TREE_OPERAND (t2, 0)) == VAR_DECL
+ && DECL_NAME (TREE_OPERAND (t2, 0)) == NULL_TREE
+ && DECL_RTL (TREE_OPERAND (t2, 0)) == 0))
+ cmp = 1;
+ else
+ cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ if (cmp <= 0)
+ return cmp;
+ return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+
+ case WITH_CLEANUP_EXPR:
+ cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ if (cmp <= 0)
+ return cmp;
+ return cp_tree_equal (TREE_OPERAND (t1, 2), TREE_OPERAND (t1, 2));
+
+ case COMPONENT_REF:
+ if (TREE_OPERAND (t1, 1) == TREE_OPERAND (t2, 1))
+ return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ return 0;
+
+ case VAR_DECL:
+ case PARM_DECL:
+ case CONST_DECL:
+ case FUNCTION_DECL:
+ return 0;
+
+ case TEMPLATE_PARM_INDEX:
+ return TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
+ && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2);
+
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
+ return 0;
+ if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t1, 0))) == 't')
+ return comptypes (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), 1);
break;
-
- case RTL_EXPR:
- warning ("RTL_EXPR reused inside UNSAVE_EXPR");
- RTL_EXPR_SEQUENCE (expr) = NULL_RTX;
+
+ default:
break;
+ }
- case CALL_EXPR:
- CALL_EXPR_RTL (expr) = NULL_RTX;
- if (TREE_OPERAND (expr, 1)
- && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
+ switch (TREE_CODE_CLASS (code1))
+ {
+ int i;
+ case '1':
+ case '2':
+ case '<':
+ case 'e':
+ case 'r':
+ case 's':
+ cmp = 1;
+ for (i=0; i<tree_code_length[(int) code1]; ++i)
{
- tree exp = TREE_OPERAND (expr, 1);
- while (exp)
- {
- unsave_expr_now (TREE_VALUE (exp));
- exp = TREE_CHAIN (exp);
- }
+ cmp = cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i));
+ if (cmp <= 0)
+ return cmp;
}
- break;
-
- case WITH_CLEANUP_EXPR:
- warning ("WITH_CLEANUP_EXPR reused inside UNSAVE_EXPR");
- RTL_EXPR_RTL (expr) = NULL_RTX;
- break;
+ return cmp;
}
- 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;
+ return -1;
+}
- 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;
+/* Similar to make_tree_vec, but build on a temporary obstack. */
- default:
- my_friendly_abort (999);
- }
+tree
+make_temp_vec (len)
+ int len;
+{
+ register tree node;
+ register struct obstack *ambient_obstack = current_obstack;
+ current_obstack = expression_obstack;
+ node = make_tree_vec (len);
+ current_obstack = ambient_obstack;
+ return node;
+}
+
+/* Build a wrapper around some pointer PTR so we can use it as a tree. */
+
+tree
+build_ptr_wrapper (ptr)
+ void *ptr;
+{
+ tree t = make_node (WRAPPER);
+ WRAPPER_PTR (t) = ptr;
+ return t;
+}
+
+/* Same, but on the expression_obstack. */
+
+tree
+build_expr_ptr_wrapper (ptr)
+ void *ptr;
+{
+ tree t;
+ push_expression_obstack ();
+ t = build_ptr_wrapper (ptr);
+ pop_obstacks ();
+ return t;
+}
+
+/* Build a wrapper around some integer I so we can use it as a tree. */
+
+tree
+build_int_wrapper (i)
+ int i;
+{
+ tree t = make_node (WRAPPER);
+ WRAPPER_INT (t) = i;
+ return t;
}
-/* 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. */
+tree
+build_srcloc (file, line)
+ char *file;
+ int line;
+{
+ tree t;
+
+ /* Make sure that we put these on the permanent obstack; up in
+ add_pending_template, we pass this return value into perm_tree_cons,
+ which also puts it on the permanent_obstack. However, this wasn't
+ explicitly doing the same. */
+ register struct obstack *ambient_obstack = current_obstack;
+ current_obstack = &permanent_obstack;
+
+ t = make_node (SRCLOC);
+ SRCLOC_FILE (t) = file;
+ SRCLOC_LINE (t) = line;
+
+ current_obstack = ambient_obstack;
+
+ return t;
+}
+
+tree
+build_srcloc_here ()
+{
+ return build_srcloc (input_filename, lineno);
+}
+
+void
+push_expression_obstack ()
+{
+ push_obstacks_nochange ();
+ current_obstack = expression_obstack;
+}
+
+/* The type of ARG when used as an lvalue. */
+
+tree
+lvalue_type (arg)
+ tree arg;
+{
+ tree type = TREE_TYPE (arg);
+ if (TREE_CODE (arg) == OVERLOAD)
+ type = unknown_type_node;
+ return cp_build_type_variant
+ (type, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg));
+}
+
+/* The type of ARG for printing error messages; denote lvalues with
+ reference types. */
+
+tree
+error_type (arg)
+ tree arg;
+{
+ tree type = TREE_TYPE (arg);
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ ;
+ else if (real_lvalue_p (arg))
+ type = build_reference_type (lvalue_type (arg));
+ else if (IS_AGGR_TYPE (type))
+ type = lvalue_type (arg);
+
+ return type;
+}
+
+/* Does FUNCTION use a variable-length argument list? */
+
+int
+varargs_function_p (function)
+ tree function;
+{
+ tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
+ for (; parm; parm = TREE_CHAIN (parm))
+ if (TREE_VALUE (parm) == void_type_node)
+ return 0;
+ return 1;
+}
+
+/* Returns 1 if decl is a member of a class. */
+
int
-cp_expand_decl_cleanup (decl, cleanup)
- tree decl, cleanup;
+member_p (decl)
+ tree decl;
{
- return expand_decl_cleanup (decl, unsave_expr (cleanup));
+ tree ctx = DECL_CONTEXT (decl);
+ return (ctx && TREE_CODE_CLASS (TREE_CODE (ctx)) == 't');
}
diff --git a/contrib/gcc/cp/typeck.c b/contrib/gcc/cp/typeck.c
index 9247bf0..4e1d4fd 100644
--- a/contrib/gcc/cp/typeck.c
+++ b/contrib/gcc/cp/typeck.c
@@ -1,5 +1,5 @@
/* Build expressions with type checking for C++ compiler.
- Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -29,31 +29,38 @@ Boston, MA 02111-1307, USA. */
and to process initializations in declarations (since they work
like a strange sort of assignment). */
-extern void error ();
-extern void warning ();
-
#include "config.h"
-#include <stdio.h>
+#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "cp-tree.h"
#include "flags.h"
#include "output.h"
-
-int mark_addressable ();
-static tree convert_for_assignment ();
-/* static */ tree convert_for_initialization ();
-extern tree shorten_compare ();
-extern void binary_op_error ();
-static tree pointer_int_sum ();
-static tree pointer_diff ();
-static tree convert_sequence ();
-/* static */ tree unary_complex_lvalue ();
+#include "expr.h"
+#include "toplev.h"
+
+extern void compiler_error ();
+
+static tree convert_for_assignment PROTO((tree, tree, char*, tree,
+ int));
+static tree pointer_int_sum PROTO((enum tree_code, tree, tree));
+static tree rationalize_conditional_expr PROTO((enum tree_code, tree));
+static int comp_target_parms PROTO((tree, tree, int));
+static int comp_ptr_ttypes_real PROTO((tree, tree, int));
+static int comp_ptr_ttypes_const PROTO((tree, tree));
+static int comp_ptr_ttypes_reinterpret PROTO((tree, tree));
+static int comp_array_types PROTO((int (*) (tree, tree, int), tree,
+ tree, int));
+static tree build_ptrmemfunc1 PROTO((tree, tree, tree, tree, tree));
+static tree common_base_type PROTO((tree, tree));
+#if 0
+static tree convert_sequence PROTO((tree, tree));
+#endif
+static tree lookup_anon_field PROTO((tree, tree));
+static tree pointer_diff PROTO((tree, tree, tree));
+static tree qualify_type PROTO((tree, tree));
static tree get_delta_difference PROTO((tree, tree, int));
-extern rtx original_result_rtx;
-extern int warn_synth;
-
/* Return the target type of TYPE, which meas return T for:
T*, T&, T[], T (...), and otherwise, just T. */
@@ -79,7 +86,15 @@ tree
require_complete_type (value)
tree value;
{
- tree type = TREE_TYPE (value);
+ tree type;
+
+ if (processing_template_decl)
+ return value;
+
+ if (TREE_CODE (value) == OVERLOAD)
+ type = unknown_type_node;
+ else
+ type = TREE_TYPE (value);
/* First, detect a valid value with a complete type. */
if (TYPE_SIZE (type) != 0
@@ -93,34 +108,92 @@ require_complete_type (value)
not been laid out. Try to avoid an error by interpreting
it as this->X::Y, if reasonable. */
if (TREE_CODE (value) == OFFSET_REF
- && C_C_D != 0
- && TREE_OPERAND (value, 0) == C_C_D)
+ && current_class_ref != 0
+ && TREE_OPERAND (value, 0) == current_class_ref)
{
tree base, member = TREE_OPERAND (value, 1);
tree basetype = TYPE_OFFSET_BASETYPE (type);
my_friendly_assert (TREE_CODE (member) == FIELD_DECL, 305);
- base = convert_pointer_to (basetype, current_class_decl);
+ base = convert_pointer_to (basetype, current_class_ptr);
value = build (COMPONENT_REF, TREE_TYPE (member),
build_indirect_ref (base, NULL_PTR), member);
return require_complete_type (value);
}
- incomplete_type_error (value, type);
- return error_mark_node;
+ if (TYPE_SIZE (complete_type (type)))
+ return value;
+ else
+ {
+ incomplete_type_error (value, type);
+ return error_mark_node;
+ }
+}
+
+/* Try to complete TYPE, if it is incomplete. For example, if TYPE is
+ a template instantiation, do the instantiation. Returns TYPE,
+ whether or not it could be completed, unless something goes
+ horribly wrong, in which case the error_mark_node is returned. */
+
+tree
+complete_type (type)
+ tree type;
+{
+ if (type == NULL_TREE)
+ /* Rather than crash, we return something sure to cause an error
+ at some point. */
+ return error_mark_node;
+
+ if (type == error_mark_node || TYPE_SIZE (type) != NULL_TREE)
+ ;
+ else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
+ {
+ tree t = complete_type (TREE_TYPE (type));
+ if (TYPE_SIZE (t) != NULL_TREE && ! processing_template_decl)
+ layout_type (type);
+ TYPE_NEEDS_CONSTRUCTING (type)
+ = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
+ TYPE_NEEDS_DESTRUCTOR (type)
+ = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
+ }
+ else if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+ instantiate_class_template (TYPE_MAIN_VARIANT (type));
+
+ return type;
+}
+
+/* Like complete_type, but issue an error if the TYPE cannot be
+ completed. Returns NULL_TREE if the type cannot be made
+ complete. */
+
+tree
+complete_type_or_else (type)
+ tree type;
+{
+ type = complete_type (type);
+ if (type != error_mark_node && !TYPE_SIZE (type))
+ {
+ incomplete_type_error (NULL_TREE, type);
+ return NULL_TREE;
+ }
+ else
+ return type;
}
/* Return truthvalue of whether type of EXP is instantiated. */
+
int
type_unknown_p (exp)
tree exp;
{
- return (TREE_CODE (exp) == TREE_LIST
+ return (TREE_CODE (exp) == OVERLOAD
+ || TREE_CODE (exp) == TREE_LIST
|| TREE_TYPE (exp) == unknown_type_node
|| (TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE
&& TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node));
}
/* Return truthvalue of whether T is function (or pfn) type. */
+
int
fntype_p (t)
tree t;
@@ -134,6 +207,7 @@ fntype_p (t)
/* Do `exp = require_instantiated_type (type, exp);' to make sure EXP
does not have an uninstantiated type.
TYPE is type to instantiate with, if uninstantiated. */
+
tree
require_instantiated_type (type, exp, errval)
tree type, exp, errval;
@@ -144,7 +218,8 @@ require_instantiated_type (type, exp, errval)
return errval;
}
- if (TREE_TYPE (exp) == unknown_type_node
+ if (TREE_CODE (exp) == OVERLOAD
+ || TREE_TYPE (exp) == unknown_type_node
|| (TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE
&& TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node))
{
@@ -239,6 +314,25 @@ commonparms (p1, p2)
return newargs;
}
+/* Given a type, perhaps copied for a typedef,
+ find the "original" version of it. */
+tree
+original_type (t)
+ tree t;
+{
+ while (TYPE_NAME (t) != NULL_TREE)
+ {
+ tree x = TYPE_NAME (t);
+ if (TREE_CODE (x) != TYPE_DECL)
+ break;
+ x = DECL_ORIGINAL_TYPE (x);
+ if (x == NULL_TREE)
+ break;
+ t = x;
+ }
+ return t;
+}
+
/* Return the common type of two types.
We assume that comptypes has already been done and returned 1;
if that isn't so, this may crash.
@@ -258,8 +352,12 @@ common_type (t1, t2)
tree attributes;
/* Save time if the two types are the same. */
-
- if (t1 == t2) return t1;
+ if (t1 == t2)
+ return t1;
+ t1 = original_type (t1);
+ t2 = original_type (t2);
+ if (t1 == t2)
+ return t1;
/* If one type is nonsense, use the other. */
if (t1 == error_mark_node)
@@ -267,7 +365,8 @@ common_type (t1, t2)
if (t2 == error_mark_node)
return t1;
- /* Merge the attributes */
+ /* Merge the attributes. */
+ attributes = merge_machine_type_attributes (t1, t2);
{ register tree a1, a2;
a1 = TYPE_ATTRIBUTES (t1);
@@ -281,25 +380,27 @@ common_type (t1, t2)
/* One that completely contains the other? Take it. */
else if (a2 && !attribute_list_contained (a1, a2))
- if (attribute_list_contained (a2, a1))
+ {
+ if (attribute_list_contained (a2, a1))
attributes = a2;
- else
- {
- /* Pick the longest list, and hang on the other list. */
- /* ??? For the moment we punt on the issue of attrs with args. */
+ else
+ {
+ /* Pick the longest list, and hang on the other list. */
+ /* ??? For the moment we punt on the issue of attrs with args. */
- if (list_length (a1) < list_length (a2))
- attributes = a2, a2 = a1;
+ if (list_length (a1) < list_length (a2))
+ attributes = a2, a2 = a1;
- for (; a2; a2 = TREE_CHAIN (a2))
- if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
- attributes) == NULL_TREE)
- {
- a1 = copy_node (a2);
- TREE_CHAIN (a1) = attributes;
- attributes = a1;
- }
- }
+ for (; a2; a2 = TREE_CHAIN (a2))
+ if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
+ attributes) == NULL_TREE)
+ {
+ a1 = copy_node (a2);
+ TREE_CHAIN (a1) = attributes;
+ attributes = a1;
+ }
+ }
+ }
}
/* Treat an enum type as the unsigned integer type of the same width. */
@@ -309,9 +410,32 @@ common_type (t1, t2)
if (TREE_CODE (t2) == ENUMERAL_TYPE)
t2 = type_for_size (TYPE_PRECISION (t2), 1);
+ if (TYPE_PTRMEMFUNC_P (t1))
+ t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
+ if (TYPE_PTRMEMFUNC_P (t2))
+ t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
+
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
+ /* If one type is complex, form the common type of the non-complex
+ components, then make that complex. Use T1 or T2 if it is the
+ required type. */
+ if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
+ {
+ tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
+ tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
+ tree subtype = common_type (subtype1, subtype2);
+
+ if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
+ return build_type_attribute_variant (t1, attributes);
+ else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
+ return build_type_attribute_variant (t2, attributes);
+ else
+ return build_type_attribute_variant (build_complex_type (subtype),
+ attributes);
+ }
+
switch (code1)
{
case INTEGER_TYPE:
@@ -382,6 +506,10 @@ common_type (t1, t2)
target = tt1;
else if (tt1 == void_type_node || tt2 == void_type_node)
target = void_type_node;
+ else if (tt1 == unknown_type_node)
+ target = tt2;
+ else if (tt2 == unknown_type_node)
+ target = tt1;
else
target = common_type (tt1, tt2);
@@ -397,15 +525,6 @@ common_type (t1, t2)
return t1;
}
-#if 0
- case POINTER_TYPE:
- t1 = build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
- return build_type_attribute_variant (t1, attributes);
-
- case REFERENCE_TYPE:
- t1 = build_reference_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
- return build_type_attribute_variant (t1, attributes);
-#endif
case ARRAY_TYPE:
{
@@ -416,7 +535,8 @@ common_type (t1, t2)
if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
return build_type_attribute_variant (t2, attributes);
/* Merge the element types, and have a size if either arg has one. */
- t1 = build_cplus_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+ t1 = build_cplus_array_type
+ (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
return build_type_attribute_variant (t1, attributes);
}
@@ -459,8 +579,8 @@ common_type (t1, t2)
case RECORD_TYPE:
case UNION_TYPE:
- my_friendly_assert (TYPE_MAIN_VARIANT (t1) == t1
- && TYPE_MAIN_VARIANT (t2) == t2, 306);
+ t1 = TYPE_MAIN_VARIANT (t1);
+ t2 = TYPE_MAIN_VARIANT (t2);
if (DERIVED_FROM_P (t1, t2) && binfo_or_else (t1, t2))
return build_type_attribute_variant (t1, attributes);
@@ -480,7 +600,8 @@ common_type (t1, t2)
tree b1 = TYPE_OFFSET_BASETYPE (t1);
tree b2 = TYPE_OFFSET_BASETYPE (t2);
- if (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2))
+ if (comptypes (b1, b2, 1)
+ || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));
else
{
@@ -494,10 +615,13 @@ common_type (t1, t2)
/* If this was a member function type, get back to the
original type of type member function (i.e., without
the class instance variable up front. */
- t1 = build_function_type (TREE_TYPE (t1), TREE_CHAIN (TYPE_ARG_TYPES (t1)));
- t2 = build_function_type (TREE_TYPE (t2), TREE_CHAIN (TYPE_ARG_TYPES (t2)));
+ t1 = build_function_type (TREE_TYPE (t1),
+ TREE_CHAIN (TYPE_ARG_TYPES (t1)));
+ 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));
+ t3 = build_cplus_method_type (basetype, TREE_TYPE (t3),
+ TYPE_ARG_TYPES (t3));
t1 = build_exception_variant (t3, raises);
}
else
@@ -511,7 +635,8 @@ common_type (t1, t2)
tree b1 = TYPE_OFFSET_BASETYPE (t1);
tree b2 = TYPE_OFFSET_BASETYPE (t2);
- if (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2))
+ if (comptypes (b1, b2, 1)
+ || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
return build_type_attribute_variant (t2, attributes);
else if (binfo_or_else (b2, b1))
return build_type_attribute_variant (t1, attributes);
@@ -524,17 +649,17 @@ common_type (t1, t2)
}
/* Return 1 if TYPE1 and TYPE2 raise the same exceptions. */
+
int
-compexcepttypes (t1, t2, strict)
+compexcepttypes (t1, t2)
tree t1, t2;
- int strict;
{
return TYPE_RAISES_EXCEPTIONS (t1) == TYPE_RAISES_EXCEPTIONS (t2);
}
static int
comp_array_types (cmp, t1, t2, strict)
- register int (*cmp)();
+ register int (*cmp) PROTO((tree, tree, int));
tree t1, t2;
int strict;
{
@@ -580,13 +705,14 @@ comp_array_types (cmp, t1, t2, strict)
0 : <= (compared according to C++)
-1: <= or >= (relaxed)
- Otherwise, pointers involving base classes and derived classes
- can be mixed as valid: i.e. a pointer to a base class may be assigned
- to a pointer to one of its derived classes, as per C++. A pointer to
+ Otherwise, pointers involving base classes and derived classes can
+ be mixed as valid: i.e. a pointer to a derived class may be converted
+ to a pointer to one of its base classes, as per C++. A pointer to
a derived class may be passed as a parameter to a function expecting a
pointer to a base classes. These allowances do not commute. In this
case, TYPE1 is assumed to be the base class, and TYPE2 is assumed to
be the derived class. */
+
int
comptypes (type1, type2, strict)
tree type1, type2;
@@ -620,6 +746,11 @@ comptypes (type1, type2, strict)
return 1;
}
+ if (TYPE_PTRMEMFUNC_P (t1))
+ t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
+ if (TYPE_PTRMEMFUNC_P (t2))
+ t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
+
/* Different classes of types can't be compatible. */
if (TREE_CODE (t1) != TREE_CODE (t2))
@@ -644,29 +775,51 @@ comptypes (type1, type2, strict)
return 0;
if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
return 0;
+ if (strict > 0 && TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
+ return 0;
/* Allow for two different type nodes which have essentially the same
definition. Note that we already checked for equality of the type
- type qualifiers (just above). */
+ qualifiers (just above). */
if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return 1;
-#ifdef COMP_TYPE_ATTRIBUTES
+ /* ??? COMP_TYPE_ATTRIBUTES is currently useless for variables as each
+ attribute is its own main variant (`val' will remain 0). */
+#ifndef COMP_TYPE_ATTRIBUTES
+#define COMP_TYPE_ATTRIBUTES(t1,t2) 1
+#endif
+
+ /* 1 if no need for warning yet, 2 if warning cause has been seen. */
if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
return 0;
-#else
- /* 1 if no need for warning yet, 2 if warning cause has been seen. */
- attrval = 1;
-#endif
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
val = 0;
switch (TREE_CODE (t1))
{
+ case TEMPLATE_TEMPLATE_PARM:
+ if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
+ || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2))
+ return 0;
+ if (! comp_template_parms (DECL_TEMPLATE_PARMS (TYPE_NAME (t1)),
+ DECL_TEMPLATE_PARMS (TYPE_NAME (t2))))
+ return 0;
+ if (! CLASSTYPE_TEMPLATE_INFO (t1) && ! CLASSTYPE_TEMPLATE_INFO (t2))
+ return 1;
+ /* Don't check inheritance. */
+ strict = 1;
+ /* fall through */
+
case RECORD_TYPE:
case UNION_TYPE:
+ if (CLASSTYPE_TEMPLATE_INFO (t1) && CLASSTYPE_TEMPLATE_INFO (t2)
+ && (CLASSTYPE_TI_TEMPLATE (t1) == CLASSTYPE_TI_TEMPLATE (t2)
+ || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM))
+ return comp_template_args (CLASSTYPE_TI_ARGS (t1),
+ CLASSTYPE_TI_ARGS (t2));
if (strict <= 0)
goto look_hard;
return 0;
@@ -678,7 +831,7 @@ comptypes (type1, type2, strict)
break;
case METHOD_TYPE:
- if (! compexcepttypes (t1, t2, strict))
+ if (! compexcepttypes (t1, t2))
return 0;
/* This case is anti-symmetrical!
@@ -706,7 +859,7 @@ comptypes (type1, type2, strict)
{
int rval;
look_hard:
- rval = t1 == t2 || UNIQUELY_DERIVED_FROM_P (t1, t2);
+ rval = t1 == t2 || DERIVED_FROM_P (t1, t2);
if (rval)
{
@@ -715,7 +868,7 @@ comptypes (type1, type2, strict)
}
if (strict < 0)
{
- val = UNIQUELY_DERIVED_FROM_P (t2, t1);
+ val = DERIVED_FROM_P (t2, t1);
break;
}
}
@@ -726,7 +879,7 @@ comptypes (type1, type2, strict)
break;
case FUNCTION_TYPE:
- if (! compexcepttypes (t1, t2, strict))
+ if (! compexcepttypes (t1, t2))
return 0;
val = ((TREE_TYPE (t1) == TREE_TYPE (t2)
@@ -740,41 +893,31 @@ comptypes (type1, type2, strict)
break;
case TEMPLATE_TYPE_PARM:
- return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2);
+ return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2)
+ && TEMPLATE_TYPE_LEVEL (t1) == TEMPLATE_TYPE_LEVEL (t2);
- case UNINSTANTIATED_P_TYPE:
- if (UPT_TEMPLATE (t1) != UPT_TEMPLATE (t2))
+ case TYPENAME_TYPE:
+ if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2))
return 0;
- {
- int i = TREE_VEC_LENGTH (UPT_PARMS (t1));
- tree *p1 = &TREE_VEC_ELT (UPT_PARMS (t1), 0);
- tree *p2 = &TREE_VEC_ELT (UPT_PARMS (t2), 0);
-
- while (i--)
- {
- if (TREE_CODE_CLASS (TREE_CODE (p1[i])) == 't')
- {
- if (! comptypes (p1[i], p2[i], 1))
- return 0;
- }
- else
- {
- if (simple_cst_equal (p1[i], p2[i]) <= 0)
- return 0;
- }
- }
- }
- return 1;
+ return comptypes (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2), 1);
+
+ default:
+ break;
}
return attrval == 2 && val == 1 ? 2 : val;
}
-/* Return 1 if TTL and TTR are pointers to types that are equivalent,
- ignoring their qualifiers.
+/* Return 1 or -1 if TTL and TTR are pointers to types that are equivalent,
+ ignoring their qualifiers, 0 if not. Return 1 means that TTR can be
+ converted to TTL. Return -1 means that TTL can be converted to TTR but
+ not vice versa.
NPTRS is the number of pointers we can strip off and keep cool.
This is used to permit (for aggr A, aggr B) A, B* to convert to A*,
- but to not permit B** to convert to A**. */
+ but to not permit B** to convert to A**.
+
+ This should go away. Callers should use can_convert or something
+ similar instead. (jason 17 Apr 1997) */
int
comp_target_types (ttl, ttr, nptrs)
@@ -789,14 +932,20 @@ comp_target_types (ttl, ttr, nptrs)
if (TREE_CODE (ttr) != TREE_CODE (ttl))
return 0;
- if (TREE_CODE (ttr) == POINTER_TYPE)
+ if (TREE_CODE (ttr) == POINTER_TYPE
+ || (TREE_CODE (ttr) == REFERENCE_TYPE))
{
+ int is_ptr = TREE_CODE (ttr) == POINTER_TYPE;
+
ttl = TREE_TYPE (ttl);
ttr = TREE_TYPE (ttr);
- if (nptrs > 0)
+ if (nptrs > 0 && is_ptr)
{
- if (TREE_CODE (ttl) == VOID_TYPE
+ if (TREE_CODE (ttl) == UNKNOWN_TYPE
+ || TREE_CODE (ttr) == UNKNOWN_TYPE)
+ return 1;
+ else if (TREE_CODE (ttl) == VOID_TYPE
&& TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttr) != METHOD_TYPE
&& TREE_CODE (ttr) != OFFSET_TYPE)
@@ -843,35 +992,71 @@ comp_target_types (ttl, ttr, nptrs)
}
}
- if (TREE_CODE (ttr) == REFERENCE_TYPE)
- return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs);
if (TREE_CODE (ttr) == ARRAY_TYPE)
return comp_array_types (comp_target_types, ttl, ttr, 0);
else if (TREE_CODE (ttr) == FUNCTION_TYPE || TREE_CODE (ttr) == METHOD_TYPE)
- if (comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))
- switch (comp_target_parms (TYPE_ARG_TYPES (ttl), TYPE_ARG_TYPES (ttr), 1))
+ {
+ tree argsl, argsr;
+ int saw_contra = 0;
+
+ if (pedantic)
{
- case 0:
- return 0;
- case 1:
- return 1;
- case 2:
- return -1;
- default:
- my_friendly_abort (112);
+ if (comptypes (TREE_TYPE (ttl), TREE_TYPE (ttr), 1) == 0)
+ return 0;
}
- else
- return 0;
+ else
+ {
+ switch (comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), -1))
+ {
+ case 0:
+ return 0;
+ case -1:
+ saw_contra = 1;
+ }
+ }
+
+ argsl = TYPE_ARG_TYPES (ttl);
+ argsr = TYPE_ARG_TYPES (ttr);
+
+ /* Compare 'this' here, not in comp_target_parms. */
+ if (TREE_CODE (ttr) == METHOD_TYPE)
+ {
+ tree tl = TYPE_METHOD_BASETYPE (ttl);
+ tree tr = TYPE_METHOD_BASETYPE (ttr);
+ if (comptypes (tr, tl, 0) == 0)
+ {
+ if (comptypes (tl, tr, 0))
+ saw_contra = 1;
+ else
+ return 0;
+ }
+
+ argsl = TREE_CHAIN (argsl);
+ argsr = TREE_CHAIN (argsr);
+ }
+
+ switch (comp_target_parms (argsl, argsr, 1))
+ {
+ case 0:
+ return 0;
+ case -1:
+ saw_contra = 1;
+ }
+
+ return saw_contra ? -1 : 1;
+ }
/* for C++ */
else if (TREE_CODE (ttr) == OFFSET_TYPE)
{
/* Contravariance: we can assign a pointer to base member to a pointer
to derived member. Note difference from simple pointer case, where
we can pass a pointer to derived to a pointer to base. */
- if (comptypes (TYPE_OFFSET_BASETYPE (ttr), TYPE_OFFSET_BASETYPE (ttl), 0))
+ if (comptypes (TYPE_OFFSET_BASETYPE (ttr),
+ TYPE_OFFSET_BASETYPE (ttl), 0))
return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs);
- else if (comptypes (TYPE_OFFSET_BASETYPE (ttl), TYPE_OFFSET_BASETYPE (ttr), 0)
+ else if (comptypes (TYPE_OFFSET_BASETYPE (ttl),
+ TYPE_OFFSET_BASETYPE (ttr), 0)
&& comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))
return -1;
}
@@ -889,14 +1074,55 @@ comp_target_types (ttl, ttr, nptrs)
return 0;
}
+/* Returns 1 if TYPE1 is more cv-qualified than TYPE2, -1 if TYPE2 is
+ more cv-qualified that TYPE1, and 0 otherwise. */
+
+int
+comp_cv_qualification (type1, type2)
+ tree type1;
+ tree type2;
+{
+ if (TYPE_READONLY (type1) == TYPE_READONLY (type2)
+ && TYPE_VOLATILE (type1) == TYPE_VOLATILE (type2))
+ return 0;
+
+ if (TYPE_READONLY (type1) >= TYPE_READONLY (type2)
+ && TYPE_VOLATILE (type1) >= TYPE_VOLATILE (type2))
+ return 1;
+
+ if (TYPE_READONLY (type2) >= TYPE_READONLY (type1)
+ && TYPE_VOLATILE (type2) >= TYPE_VOLATILE (type1))
+ return -1;
+
+ return 0;
+}
+
+/* Returns 1 if the cv-qualification signature of TYPE1 is a proper
+ subset of the cv-qualification signature of TYPE2, and the types
+ are similar. Returns -1 if the other way 'round, and 0 otherwise. */
+
+int
+comp_cv_qual_signature (type1, type2)
+ tree type1;
+ tree type2;
+{
+ if (comp_ptr_ttypes_real (type2, type1, -1))
+ return 1;
+ else if (comp_ptr_ttypes_real (type1, type2, -1))
+ return -1;
+ else
+ return 0;
+}
+
/* If two types share a common base type, return that basetype.
If there is not a unique most-derived base type, this function
returns ERROR_MARK_NODE. */
-tree
+
+static tree
common_base_type (tt1, tt2)
tree tt1, tt2;
{
- tree best = NULL_TREE, tmp;
+ tree best = NULL_TREE;
int i;
/* If one is a baseclass of another, that's good enough. */
@@ -905,15 +1131,6 @@ common_base_type (tt1, tt2)
if (UNIQUELY_DERIVED_FROM_P (tt2, tt1))
return tt2;
-#if 0
- /* If they share a virtual baseclass, that's good enough. */
- for (tmp = CLASSTYPE_VBASECLASSES (tt1); tmp; tmp = TREE_CHAIN (tmp))
- {
- if (binfo_member (BINFO_TYPE (tmp), CLASSTYPE_VBASECLASSES (tt2)))
- return BINFO_TYPE (tmp);
- }
-#endif
-
/* Otherwise, try to find a unique baseclass of TT1
that is shared by TT2, and follow that down. */
for (i = CLASSTYPE_N_BASECLASSES (tt1)-1; i >= 0; i--)
@@ -957,9 +1174,10 @@ common_base_type (tt1, tt2)
If either list is empty, we win.
Otherwise, the two lists must be equivalent, element by element.
- C++: See comment above about TYPE1, TYPE2, STRICT.
- If STRICT == 3, it means checking is strict, but do not compare
- default parameter values. */
+ C++: See comment above about TYPE1, TYPE2.
+
+ STRICT is no longer used. */
+
int
compparms (parms1, parms2, strict)
tree parms1, parms2;
@@ -970,45 +1188,16 @@ compparms (parms1, parms2, strict)
/* An unspecified parmlist matches any specified parmlist
whose argument types don't need default promotions. */
- if (strict <= 0 && t1 == 0)
- return self_promoting_args_p (t2);
- if (strict < 0 && t2 == 0)
- return self_promoting_args_p (t1);
-
while (1)
{
if (t1 == 0 && t2 == 0)
return 1;
/* If one parmlist is shorter than the other,
- they fail to match, unless STRICT is <= 0. */
+ they fail to match. */
if (t1 == 0 || t2 == 0)
- {
- if (strict > 0)
- return 0;
- if (strict < 0)
- return 1;
- if (strict == 0)
- return t1 && TREE_PURPOSE (t1);
- }
- if (! comptypes (TREE_VALUE (t2), TREE_VALUE (t1), strict))
- {
- if (strict > 0)
- return 0;
- if (strict == 0)
- return t2 == void_list_node && TREE_PURPOSE (t1);
- return TREE_PURPOSE (t1) || TREE_PURPOSE (t2);
- }
-#if 0
- /* Default parms are not part of the type of a function. */
- if (strict != 3 && TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
- {
- int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
- if (cmp < 0)
- my_friendly_abort (113);
- if (cmp == 0)
- return 0;
- }
-#endif
+ return 0;
+ if (! comptypes (TREE_VALUE (t2), TREE_VALUE (t1), 1))
+ return 0;
t1 = TREE_CHAIN (t1);
t2 = TREE_CHAIN (t2);
@@ -1016,8 +1205,15 @@ compparms (parms1, parms2, strict)
}
/* This really wants return whether or not parameter type lists
- would make their owning functions assignment compatible or not. */
-int
+ would make their owning functions assignment compatible or not.
+
+ The return value is like for comp_target_types.
+
+ This should go away, possibly with the exception of the empty parmlist
+ conversion; there are no conversions between function types in C++.
+ (jason 17 Apr 1997) */
+
+static int
comp_target_parms (parms1, parms2, strict)
tree parms1, parms2;
int strict;
@@ -1025,9 +1221,9 @@ comp_target_parms (parms1, parms2, strict)
register tree t1 = parms1, t2 = parms2;
int warn_contravariance = 0;
- /* An unspecified parmlist matches any specified parmlist
- whose argument types don't need default promotions.
- @@@ see 13.3.3 for a counterexample... */
+ /* In C, an unspecified parmlist matches any specified parmlist
+ whose argument types don't need default promotions. This is not
+ true for C++, but let's do it anyway for unfixed headers. */
if (t1 == 0 && t2 != 0)
{
@@ -1054,11 +1250,15 @@ comp_target_parms (parms1, parms2, strict)
}
p1 = TREE_VALUE (t1);
p2 = TREE_VALUE (t2);
- if (p1 == p2)
+ if (comptypes (p1, p2, 1))
continue;
+ if (pedantic)
+ return 0;
+
if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE)
- || (TREE_CODE (p1) == REFERENCE_TYPE && TREE_CODE (p2) == REFERENCE_TYPE))
+ || (TREE_CODE (p1) == REFERENCE_TYPE
+ && TREE_CODE (p2) == REFERENCE_TYPE))
{
if (strict <= 0
&& (TYPE_MAIN_VARIANT (TREE_TYPE (p1))
@@ -1076,58 +1276,24 @@ comp_target_parms (parms1, parms2, strict)
}
if (IS_AGGR_TYPE (TREE_TYPE (p1)))
{
- if (comptypes (p2, p1, 0) == 0)
- {
- if (comptypes (p1, p2, 0) != 0)
- warn_contravariance = 1;
- else
- return 0;
- }
- continue;
+ if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (p1)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (p2)), 1) == 0)
+ return 0;
}
}
/* Note backwards order due to contravariance. */
- if (comp_target_types (p2, p1, 1) == 0)
+ if (comp_target_types (p2, p1, 1) <= 0)
{
- if (comp_target_types (p1, p2, 1))
+ if (comp_target_types (p1, p2, 1) > 0)
{
warn_contravariance = 1;
continue;
}
if (strict != 0)
return 0;
-#if 0
- /* What good do these cases do? */
- if (strict == 0)
- return p2 == void_type_node && TREE_PURPOSE (t1);
- return TREE_PURPOSE (t1) || TREE_PURPOSE (t2);
-#endif
- }
- /* Target types are compatible--just make sure that if
- we use parameter lists, that they are ok as well. */
- if (TREE_CODE (p1) == FUNCTION_TYPE || TREE_CODE (p1) == METHOD_TYPE)
- switch (comp_target_parms (TYPE_ARG_TYPES (p1),
- TYPE_ARG_TYPES (p2),
- strict))
- {
- case 0:
- return 0;
- case 1:
- break;
- case 2:
- warn_contravariance = 1;
- }
-
- if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
- {
- int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
- if (cmp < 0)
- my_friendly_abort (114);
- if (cmp == 0)
- return 0;
}
}
- return 1 + warn_contravariance;
+ return warn_contravariance ? -1 : 1;
}
/* Return 1 if PARMS specifies a fixed number of parameters
@@ -1145,10 +1311,10 @@ self_promoting_args_p (parms)
if (TREE_CHAIN (t) == 0 && type != void_type_node)
return 0;
- if (TYPE_MAIN_VARIANT (type) == float_type_node)
+ if (type == 0)
return 0;
- if (type == 0)
+ if (TYPE_MAIN_VARIANT (type) == float_type_node)
return 0;
if (C_PROMOTING_INTEGER_TYPE_P (type))
@@ -1176,7 +1342,18 @@ unsigned_type (type)
return long_unsigned_type_node;
if (type1 == long_long_integer_type_node)
return long_long_unsigned_type_node;
- return type;
+ if (type1 == intTI_type_node)
+ return unsigned_intTI_type_node;
+ if (type1 == intDI_type_node)
+ return unsigned_intDI_type_node;
+ if (type1 == intSI_type_node)
+ return unsigned_intSI_type_node;
+ if (type1 == intHI_type_node)
+ return unsigned_intHI_type_node;
+ if (type1 == intQI_type_node)
+ return unsigned_intQI_type_node;
+
+ return signed_or_unsigned_type (1, type);
}
/* Return a signed type the same as TYPE in other respects. */
@@ -1196,7 +1373,18 @@ signed_type (type)
return long_integer_type_node;
if (type1 == long_long_unsigned_type_node)
return long_long_integer_type_node;
- return type;
+ if (type1 == unsigned_intTI_type_node)
+ return intTI_type_node;
+ if (type1 == unsigned_intDI_type_node)
+ return intDI_type_node;
+ if (type1 == unsigned_intSI_type_node)
+ return intSI_type_node;
+ if (type1 == unsigned_intHI_type_node)
+ return intHI_type_node;
+ if (type1 == unsigned_intQI_type_node)
+ return intQI_type_node;
+
+ return signed_or_unsigned_type (0, type);
}
/* Return a type the same as TYPE except unsigned or
@@ -1207,8 +1395,10 @@ signed_or_unsigned_type (unsignedp, type)
int unsignedp;
tree type;
{
- if (! INTEGRAL_TYPE_P (type))
+ if (! INTEGRAL_TYPE_P (type)
+ || TREE_UNSIGNED (type) == unsignedp)
return type;
+
if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
@@ -1223,6 +1413,8 @@ signed_or_unsigned_type (unsignedp, type)
return type;
}
+/* Compute the value of the `sizeof' operator. */
+
tree
c_sizeof (type)
tree type;
@@ -1230,6 +1422,9 @@ c_sizeof (type)
enum tree_code code = TREE_CODE (type);
tree t;
+ if (processing_template_decl)
+ return build_min (SIZEOF_EXPR, sizetype, type);
+
if (code == FUNCTION_TYPE)
{
if (pedantic || warn_pointer_arith)
@@ -1274,15 +1469,16 @@ c_sizeof (type)
return size_int (0);
}
- if (TYPE_SIZE (type) == 0)
+ if (TYPE_SIZE (complete_type (type)) == 0)
{
- error ("`sizeof' applied to an incomplete type");
+ cp_error ("`sizeof' applied to incomplete type `%T'", type);
return size_int (0);
}
/* Convert in case a char is more than one unit. */
t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
size_int (TYPE_PRECISION (char_type_node)));
+ t = convert (sizetype, t);
/* size_binop does not put the constant in range, so do it now. */
if (TREE_CODE (t) == INTEGER_CST && force_fit_type (t, 0))
TREE_CONSTANT_OVERFLOW (t) = TREE_OVERFLOW (t) = 1;
@@ -1290,6 +1486,36 @@ c_sizeof (type)
}
tree
+expr_sizeof (e)
+ tree e;
+{
+ if (processing_template_decl)
+ return build_min (SIZEOF_EXPR, sizetype, e);
+
+ if (TREE_CODE (e) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (e, 1)))
+ error ("sizeof applied to a bit-field");
+ /* ANSI says arrays and functions are converted inside comma.
+ But we can't really convert them in build_compound_expr
+ because that would break commas in lvalues.
+ So do the conversion here if operand was a comma. */
+ if (TREE_CODE (e) == COMPOUND_EXPR
+ && (TREE_CODE (TREE_TYPE (e)) == ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (e)) == FUNCTION_TYPE))
+ e = default_conversion (e);
+ else if (TREE_CODE (e) == TREE_LIST)
+ {
+ tree t = TREE_VALUE (e);
+ if (t != NULL_TREE
+ && ((TREE_TYPE (t)
+ && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
+ || is_overloaded_fn (t)))
+ pedwarn ("ANSI C++ forbids taking the sizeof a function type");
+ }
+ return c_sizeof (TREE_TYPE (e));
+}
+
+tree
c_sizeof_nowarn (type)
tree type;
{
@@ -1305,18 +1531,12 @@ c_sizeof_nowarn (type)
type = TREE_TYPE (type);
if (TYPE_SIZE (type) == 0)
- {
-#if 0
- /* ??? Tiemann, why have any diagnostic here?
- There is none in the corresponding function for C. */
- warning ("sizeof applied to an incomplete type");
-#endif
- return size_int (0);
- }
+ return size_int (0);
/* Convert in case a char is more than one unit. */
t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
size_int (TYPE_PRECISION (char_type_node)));
+ t = convert (sizetype, t);
force_fit_type (t, 0);
return t;
}
@@ -1331,6 +1551,9 @@ c_alignof (type)
enum tree_code code = TREE_CODE (type);
tree t;
+ if (processing_template_decl)
+ return build_min (ALIGNOF_EXPR, sizetype, type);
+
if (code == FUNCTION_TYPE || code == METHOD_TYPE)
return size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
@@ -1368,13 +1591,19 @@ decay_conversion (exp)
register tree type = TREE_TYPE (exp);
register enum tree_code code = TREE_CODE (type);
- if (code == OFFSET_TYPE /* || TREE_CODE (exp) == OFFSET_REF */ )
+ if (code == OFFSET_TYPE)
{
if (TREE_CODE (exp) == OFFSET_REF)
return decay_conversion (resolve_offset_ref (exp));
type = TREE_TYPE (type);
code = TREE_CODE (type);
+
+ if (type == unknown_type_node)
+ {
+ cp_pedwarn ("assuming & on overloaded member function");
+ return build_unary_op (ADDR_EXPR, exp, 0);
+ }
}
if (code == REFERENCE_TYPE)
@@ -1408,12 +1637,7 @@ decay_conversion (exp)
}
if (code == METHOD_TYPE)
{
- if (TREE_CODE (exp) == OFFSET_REF)
- {
- my_friendly_assert (TREE_CODE (TREE_OPERAND (exp, 1)) == FUNCTION_DECL,
- 308);
- return build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
- }
+ cp_pedwarn ("assuming & on `%E'", exp);
return build_unary_op (ADDR_EXPR, exp, 0);
}
if (code == ARRAY_TYPE)
@@ -1431,11 +1655,12 @@ decay_conversion (exp)
if (TREE_CODE (TREE_TYPE (inner)) == REFERENCE_TYPE)
{
inner = build1 (CONVERT_EXPR,
- build_pointer_type (TREE_TYPE (TREE_TYPE (inner))),
+ build_pointer_type (TREE_TYPE
+ (TREE_TYPE (inner))),
inner);
- TREE_REFERENCE_EXPR (inner) = 1;
+ TREE_CONSTANT (inner) = TREE_CONSTANT (TREE_OPERAND (inner, 0));
}
- return convert (build_pointer_type (TREE_TYPE (type)), inner);
+ return cp_convert (build_pointer_type (TREE_TYPE (type)), inner);
}
if (TREE_CODE (exp) == COMPOUND_EXPR)
@@ -1464,8 +1689,8 @@ decay_conversion (exp)
if (TYPE_READONLY (type) || TYPE_VOLATILE (type)
|| constp || volatilep)
restype = cp_build_type_variant (restype,
- TYPE_READONLY (type) || constp,
- TYPE_VOLATILE (type) || volatilep);
+ TYPE_READONLY (type) || constp,
+ TYPE_VOLATILE (type) || volatilep);
ptrtype = build_pointer_type (restype);
if (TREE_CODE (exp) == VAR_DECL)
@@ -1484,7 +1709,7 @@ decay_conversion (exp)
/* This way is better for a COMPONENT_REF since it can
simplify the offset for a component. */
adr = build_unary_op (ADDR_EXPR, exp, 1);
- return convert (ptrtype, adr);
+ return cp_convert (ptrtype, adr);
}
return exp;
@@ -1506,14 +1731,27 @@ default_conversion (exp)
{
tree t = type_promotes_to (type);
if (t != type)
- return convert (t, exp);
+ return cp_convert (t, exp);
}
- if (flag_traditional
- && TYPE_MAIN_VARIANT (type) == float_type_node)
- return convert (double_type_node, exp);
return exp;
}
+
+/* Take the address of an inline function without setting TREE_ADDRESSABLE
+ or TREE_USED. */
+
+tree
+inline_conversion (exp)
+ tree exp;
+{
+ if (TREE_CODE (exp) == FUNCTION_DECL)
+ {
+ tree type = build_type_variant
+ (TREE_TYPE (exp), TREE_READONLY (exp), TREE_THIS_VOLATILE (exp));
+ exp = build1 (ADDR_EXPR, build_pointer_type (type), exp);
+ }
+ return exp;
+}
tree
build_object_ref (datum, basetype, field)
@@ -1532,107 +1770,107 @@ build_object_ref (datum, basetype, field)
basetype, field, dtype);
return error_mark_node;
}
- else if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (basetype)))
+ else if (IS_SIGNATURE (basetype))
{
warning ("signature name in scope resolution ignored");
return build_component_ref (datum, field, NULL_TREE, 1);
}
- else if (is_aggr_typedef (basetype, 1))
+ else if (is_aggr_type (basetype, 1))
{
- tree real_basetype = IDENTIFIER_TYPE_VALUE (basetype);
- tree binfo = binfo_or_else (real_basetype, TREE_TYPE (datum));
+ tree binfo = binfo_or_else (basetype, dtype);
if (binfo)
- return build_component_ref (build_scoped_ref (datum, basetype),
- field, binfo, 1);
+ return build_x_component_ref (build_scoped_ref (datum, basetype),
+ field, binfo, 1);
}
return error_mark_node;
}
-/* Like `build_component_ref, but uses an already found field.
- Must compute access for C_C_D. Otherwise, ok. */
+/* Like `build_component_ref, but uses an already found field, and converts
+ from a reference. Must compute access for current_class_ref.
+ Otherwise, ok. */
+
tree
build_component_ref_1 (datum, field, protect)
tree datum, field;
int protect;
{
- register tree basetype = TREE_TYPE (datum);
- register enum tree_code code = TREE_CODE (basetype);
- register tree ref;
-
- if (code == REFERENCE_TYPE)
- {
- datum = convert_from_reference (datum);
- basetype = TREE_TYPE (datum);
- code = TREE_CODE (basetype);
- }
+ return convert_from_reference
+ (build_component_ref (datum, field, NULL_TREE, protect));
+}
- if (! IS_AGGR_TYPE_CODE (code))
- {
- if (code != ERROR_MARK)
- cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
- field, datum, basetype);
- return error_mark_node;
- }
+/* Given a COND_EXPR, MIN_EXPR, or MAX_EXPR in T, return it in a form that we
+ can, for example, use as an lvalue. This code used to be in
+ unary_complex_lvalue, but we needed it to deal with `a = (d == c) ? b : c'
+ expressions, where we're dealing with aggregates. But now it's again only
+ called from unary_complex_lvalue. The case (in particular) that led to
+ this was with CODE == ADDR_EXPR, since it's not an lvalue when we'd
+ get it there. */
- if (TYPE_SIZE (basetype) == 0)
+static tree
+rationalize_conditional_expr (code, t)
+ enum tree_code code;
+ tree t;
+{
+ /* For MIN_EXPR or MAX_EXPR, fold-const.c has arranged things so that
+ the first operand is always the one to be used if both operands
+ are equal, so we know what conditional expression this used to be. */
+ if (TREE_CODE (t) == MIN_EXPR || TREE_CODE (t) == MAX_EXPR)
{
- incomplete_type_error (0, basetype);
- return error_mark_node;
+ return
+ build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR
+ ? LE_EXPR : GE_EXPR),
+ TREE_OPERAND (t, 0),
+ TREE_OPERAND (t, 1)),
+ build_unary_op (code, TREE_OPERAND (t, 0), 0),
+ build_unary_op (code, TREE_OPERAND (t, 1), 0));
}
- /* Look up component name in the structure type definition. */
+ return
+ build_conditional_expr (TREE_OPERAND (t, 0),
+ build_unary_op (code, TREE_OPERAND (t, 1), 0),
+ build_unary_op (code, TREE_OPERAND (t, 2), 0));
+}
- if (field == error_mark_node)
- my_friendly_abort (115);
+/* Given the TYPE of an anonymous union field inside T, return the
+ FIELD_DECL for the field. If not found return NULL_TREE. Because
+ anonymous unions can nest, we must also search all anonymous unions
+ that are directly reachable. */
- if (TREE_STATIC (field))
- return field;
+static tree
+lookup_anon_field (t, type)
+ tree t, type;
+{
+ tree field;
- if (datum == C_C_D)
+ for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
{
- enum access_type access
- = compute_access (TYPE_BINFO (current_class_type), field);
+ if (TREE_STATIC (field))
+ continue;
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
- if (access == access_private)
+ /* If we find it directly, return the field. */
+ if (DECL_NAME (field) == NULL_TREE
+ && type == TREE_TYPE (field))
{
- cp_error ("field `%D' is private", field);
- return error_mark_node;
+ return field;
}
- else if (access == access_protected)
+
+ /* Otherwise, it could be nested, search harder. */
+ if (DECL_NAME (field) == NULL_TREE
+ && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
- cp_error ("field `%D' is protected", field);
- return error_mark_node;
+ tree subfield = lookup_anon_field (TREE_TYPE (field), type);
+ if (subfield)
+ return subfield;
}
}
-
- ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field);
-
- if (TREE_READONLY (datum) || TREE_READONLY (field))
- TREE_READONLY (ref) = 1;
- if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
- TREE_THIS_VOLATILE (ref) = 1;
- if (DECL_MUTABLE_P (field))
- TREE_READONLY (ref) = 0;
-
- return ref;
+ return NULL_TREE;
}
-/* Given a COND_EXPR in T, return it in a form that we can, for
- example, use as an lvalue. This code used to be in unary_complex_lvalue,
- but we needed it to deal with `a = (d == c) ? b : c' expressions, where
- we're dealing with aggregates. So, we now call this in unary_complex_lvalue,
- and in build_modify_expr. The case (in particular) that led to this was
- with CODE == ADDR_EXPR, since it's not an lvalue when we'd get it there. */
-static tree
-rationalize_conditional_expr (code, t)
- enum tree_code code;
- tree t;
-{
- return
- build_conditional_expr (TREE_OPERAND (t, 0),
- build_unary_op (code, TREE_OPERAND (t, 1), 0),
- build_unary_op (code, TREE_OPERAND (t, 2), 0));
-}
+/* Build a COMPONENT_REF for a given DATUM, and it's member COMPONENT.
+ COMPONENT can be an IDENTIFIER_NODE that is the name of the member
+ that we are interested in, or it can be a FIELD_DECL. */
tree
build_component_ref (datum, component, basetype_path, protect)
@@ -1640,11 +1878,15 @@ build_component_ref (datum, component, basetype_path, protect)
int protect;
{
register tree basetype = TREE_TYPE (datum);
- register enum tree_code code = TREE_CODE (basetype);
+ register enum tree_code code;
register tree field = NULL;
register tree ref;
- /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it. */
+ if (processing_template_decl)
+ return build_min_nt (COMPONENT_REF, datum, component);
+
+ /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference
+ inside it. */
switch (TREE_CODE (datum))
{
case COMPOUND_EXPR:
@@ -1661,33 +1903,42 @@ build_component_ref (datum, component, basetype_path, protect)
basetype_path, protect),
build_component_ref (TREE_OPERAND (datum, 2), component,
basetype_path, protect));
+
+ case TEMPLATE_DECL:
+ cp_error ("invalid use of %D", datum);
+ datum = error_mark_node;
+ break;
+
+ default:
+ break;
}
+ code = TREE_CODE (basetype);
+
if (code == REFERENCE_TYPE)
{
-#if 0
- /* TREE_REFERENCE_EXPRs are not converted by `convert_from_reference'.
- @@ Maybe that is not right. */
- if (TREE_REFERENCE_EXPR (datum))
- datum = build1 (INDIRECT_REF, TREE_TYPE (basetype), datum);
- else
-#endif
- datum = convert_from_reference (datum);
+ datum = convert_from_reference (datum);
+ basetype = TREE_TYPE (datum);
+ code = TREE_CODE (basetype);
+ }
+ if (TREE_CODE (datum) == OFFSET_REF)
+ {
+ datum = resolve_offset_ref (datum);
basetype = TREE_TYPE (datum);
code = TREE_CODE (basetype);
}
- /* First, see if there is a field or component with name COMPONENT. */
+ /* First, see if there is a field or component with name COMPONENT. */
if (TREE_CODE (component) == TREE_LIST)
{
+ /* I could not trigger this code. MvL */
+ my_friendly_abort (980326);
+#ifdef DEAD
my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE
&& DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309);
+#endif
return build (COMPONENT_REF, TREE_TYPE (component), datum, component);
}
-#if 0
- if (TREE_CODE (component) == TYPE_EXPR)
- return build_component_type_expr (datum, component, NULL_TREE, protect);
-#endif
if (! IS_AGGR_TYPE_CODE (code))
{
@@ -1697,11 +1948,8 @@ build_component_ref (datum, component, basetype_path, protect)
return error_mark_node;
}
- if (TYPE_SIZE (basetype) == 0)
- {
- incomplete_type_error (0, basetype);
- return error_mark_node;
- }
+ if (!complete_type_or_else (basetype))
+ return error_mark_node;
if (TREE_CODE (component) == BIT_NOT_EXPR)
{
@@ -1716,7 +1964,7 @@ build_component_ref (datum, component, basetype_path, protect)
cp_error ("type `%T' has no destructor", basetype);
return error_mark_node;
}
- return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);
+ return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1);
}
/* Look up component name in the structure type definition. */
@@ -1726,12 +1974,22 @@ build_component_ref (datum, component, basetype_path, protect)
hierarchy, the compiler will abort (because vptr lookups are
not supposed to be ambiguous. */
field = CLASSTYPE_VFIELD (basetype);
+ else if (TREE_CODE (component) == FIELD_DECL)
+ field = component;
+ else if (TREE_CODE (component) == TYPE_DECL)
+ {
+ cp_pedwarn ("invalid use of type decl `%#D' as expression", component);
+ return component;
+ }
else
{
+ tree name = component;
+ if (TREE_CODE (component) == VAR_DECL)
+ name = DECL_NAME (component);
if (basetype_path == NULL_TREE)
basetype_path = TYPE_BINFO (basetype);
- field = lookup_field (basetype_path, component,
- protect && ! VFIELD_NAME_P (component), 0);
+ field = lookup_field (basetype_path, name,
+ protect && !VFIELD_NAME_P (name), 0);
if (field == error_mark_node)
return error_mark_node;
@@ -1740,36 +1998,47 @@ build_component_ref (datum, component, basetype_path, protect)
/* Not found as a data field, look for it as a method. If found,
then if this is the only possible one, return it, else
report ambiguity error. */
- tree fndecls = lookup_fnfields (basetype_path, component, 1);
+ tree fndecls = lookup_fnfields (basetype_path, name, 1);
if (fndecls == error_mark_node)
return error_mark_node;
if (fndecls)
{
if (TREE_CHAIN (fndecls) == NULL_TREE
- && DECL_CHAIN (TREE_VALUE (fndecls)) == NULL_TREE)
+ && TREE_CODE (TREE_VALUE (fndecls)) != OVERLOAD)
{
- enum access_type access;
- tree fndecl;
+ tree access, fndecl;
/* Unique, so use this one now. */
basetype = TREE_PURPOSE (fndecls);
fndecl = TREE_VALUE (fndecls);
access = compute_access (TREE_PURPOSE (fndecls), fndecl);
- if (access == access_public)
+ if (access == access_public_node)
{
if (DECL_VINDEX (fndecl)
&& ! resolves_to_fixed_type_p (datum, 0))
{
tree addr = build_unary_op (ADDR_EXPR, datum, 0);
- addr = convert_pointer_to (DECL_CONTEXT (fndecl), addr);
+ tree fntype = TREE_TYPE (fndecl);
+
+ addr = convert_pointer_to (DECL_CONTEXT (fndecl),
+ addr);
datum = build_indirect_ref (addr, NULL_PTR);
my_friendly_assert (datum != error_mark_node, 310);
- fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl));
+ fndecl = build_vfn_ref (&addr, datum,
+ DECL_VINDEX (fndecl));
+ /* The type of fndecl is a function type,
+ not a pointer-to-function type, since
+ build_vfn_ref returns not the correct
+ vtable slot, but the indirection of the
+ correct vtable slot. */
+ TREE_TYPE (fndecl) = fntype;
}
- assemble_external (fndecl);
- return fndecl;
+ else
+ mark_used (fndecl);
+ return build (OFFSET_REF, TREE_TYPE (fndecl),
+ datum, fndecl);
}
- if (access == access_protected)
+ if (access == access_protected_node)
cp_error ("member function `%D' is protected", fndecl);
else
cp_error ("member function `%D' is private", fndecl);
@@ -1781,9 +2050,6 @@ build_component_ref (datum, component, basetype_path, protect)
not matter unless we're actually calling the function. */
tree t;
- for (t = TREE_VALUE (fndecls); t; t = DECL_CHAIN (t))
- assemble_external (t);
-
t = build_tree_list (error_mark_node, fndecls);
TREE_TYPE (t) = build_offset_type (basetype,
unknown_type_node);
@@ -1791,12 +2057,7 @@ build_component_ref (datum, component, basetype_path, protect)
}
}
-#if 0
- if (component == ansi_opname[(int) TYPE_EXPR])
- cp_error ("`%#T' has no such type conversion operator", basetype);
- else
-#endif
- cp_error ("`%#T' has no member named `%D'", basetype, component);
+ cp_error ("`%#T' has no member named `%D'", basetype, name);
return error_mark_node;
}
else if (TREE_TYPE (field) == error_mark_node)
@@ -1805,30 +2066,61 @@ build_component_ref (datum, component, basetype_path, protect)
if (TREE_CODE (field) != FIELD_DECL)
{
if (TREE_CODE (field) == TYPE_DECL)
- {
- cp_error ("invalid use of type decl `%#D' as expression", field);
- return error_mark_node;
- }
- if (DECL_RTL (field) != 0)
- assemble_external (field);
- TREE_USED (field) = 1;
+ cp_pedwarn ("invalid use of type decl `%#D' as expression", field);
+ else if (DECL_RTL (field) != 0)
+ mark_used (field);
+ else
+ TREE_USED (field) = 1;
return field;
}
}
- if (DECL_FIELD_CONTEXT (field) != basetype
- && TYPE_USES_COMPLEX_INHERITANCE (basetype))
+ /* See if we have to do any conversions so that we pick up the field from the
+ right context. */
+ if (DECL_FIELD_CONTEXT (field) != basetype)
{
- tree addr = build_unary_op (ADDR_EXPR, datum, 0);
- if (integer_zerop (addr))
+ tree context = DECL_FIELD_CONTEXT (field);
+ tree base = context;
+ while (!comptypes (base, basetype,1) && TYPE_NAME (base)
+ && ANON_UNION_TYPE_P (base))
{
- error ("invalid reference to NULL ptr, use ptr-to-member instead");
- return error_mark_node;
+ base = TYPE_CONTEXT (base);
+ }
+
+ /* Handle base classes here... */
+ if (base != basetype && TYPE_USES_COMPLEX_INHERITANCE (basetype))
+ {
+ tree addr = build_unary_op (ADDR_EXPR, datum, 0);
+ if (integer_zerop (addr))
+ {
+ error ("invalid reference to NULL ptr, use ptr-to-member instead");
+ return error_mark_node;
+ }
+ if (VBASE_NAME_P (DECL_NAME (field)))
+ {
+ /* It doesn't matter which vbase pointer we grab, just
+ find one of them. */
+ tree binfo = get_binfo (base,
+ TREE_TYPE (TREE_TYPE (addr)), 0);
+ addr = convert_pointer_to_real (binfo, addr);
+ }
+ else
+ addr = convert_pointer_to (base, addr);
+ datum = build_indirect_ref (addr, NULL_PTR);
+ my_friendly_assert (datum != error_mark_node, 311);
+ }
+ basetype = base;
+
+ /* Handle things from anon unions here... */
+ if (TYPE_NAME (context) && ANON_UNION_TYPE_P (context))
+ {
+ tree subfield = lookup_anon_field (basetype, context);
+ tree subdatum = build_component_ref (datum, subfield,
+ basetype_path, protect);
+ return build_component_ref (subdatum, field, basetype_path, protect);
}
- addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr);
- datum = build_indirect_ref (addr, NULL_PTR);
- my_friendly_assert (datum != error_mark_node, 311);
}
+
ref = fold (build (COMPONENT_REF, TREE_TYPE (field),
break_out_cleanups (datum), field));
@@ -1836,11 +2128,27 @@ build_component_ref (datum, component, basetype_path, protect)
TREE_READONLY (ref) = 1;
if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
TREE_THIS_VOLATILE (ref) = 1;
- if (DECL_MUTABLE_P (field))
+ if (DECL_LANG_SPECIFIC (field) && DECL_MUTABLE_P (field))
TREE_READONLY (ref) = 0;
return ref;
}
+
+/* Variant of build_component_ref for use in expressions, which should
+ never have REFERENCE_TYPE. */
+
+tree
+build_x_component_ref (datum, component, basetype_path, protect)
+ tree datum, component, basetype_path;
+ int protect;
+{
+ tree t = build_component_ref (datum, component, basetype_path, protect);
+
+ if (! processing_template_decl)
+ t = convert_from_reference (t);
+
+ return t;
+}
/* Given an expression PTR for a pointer, return an expression
for the value pointed to.
@@ -1854,7 +2162,13 @@ build_x_indirect_ref (ptr, errorstring)
tree ptr;
char *errorstring;
{
- tree rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, NULL_TREE);
+ tree rval;
+
+ if (processing_template_decl)
+ return build_min_nt (INDIRECT_REF, ptr);
+
+ rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
+ NULL_TREE);
if (rval)
return rval;
return build_indirect_ref (ptr, errorstring);
@@ -1865,27 +2179,22 @@ build_indirect_ref (ptr, errorstring)
tree ptr;
char *errorstring;
{
- register tree pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE ?
- ptr : default_conversion (ptr));
- register tree type = TREE_TYPE (pointer);
+ register tree pointer, type;
- if (ptr == current_class_decl)
- return C_C_D;
+ if (ptr == error_mark_node)
+ return error_mark_node;
- if (IS_AGGR_TYPE (type))
- {
- ptr = build_expr_type_conversion (WANT_POINTER, pointer, 1);
+ pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
+ ? ptr : default_conversion (ptr));
+ type = TREE_TYPE (pointer);
- if (ptr)
- {
- pointer = ptr;
- type = TREE_TYPE (pointer);
- }
- }
+ if (ptr == current_class_ptr)
+ return current_class_ref;
if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
{
if (TREE_CODE (pointer) == ADDR_EXPR
+ && !flag_volatile
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (pointer, 0)))
== TYPE_MAIN_VARIANT (TREE_TYPE (type)))
&& (TREE_READONLY (TREE_OPERAND (pointer, 0))
@@ -1899,10 +2208,14 @@ build_indirect_ref (ptr, errorstring)
register tree ref = build1 (INDIRECT_REF,
TYPE_MAIN_VARIANT (t), pointer);
+ /* We *must* set TREE_READONLY when dereferencing a pointer to const,
+ so that we get the proper error message if the result is used
+ to assign to. Also, &* is supposed to be a no-op. */
TREE_READONLY (ref) = TYPE_READONLY (t);
- TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
TREE_SIDE_EFFECTS (ref)
- = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
+ = (TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer)
+ || flag_volatile);
+ TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
return ref;
}
}
@@ -1937,21 +2250,9 @@ build_indirect_ref (ptr, errorstring)
will inherit the type of the array, which will be some pointer type. */
tree
-build_x_array_ref (array, index)
- tree array, index;
-{
- tree rval = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array, index, NULL_TREE);
- if (rval)
- return rval;
- return build_array_ref (array, index);
-}
-
-tree
build_array_ref (array, idx)
tree array, idx;
{
- tree itype;
-
if (idx == 0)
{
error ("subscript missing in array reference");
@@ -1962,8 +2263,6 @@ build_array_ref (array, idx)
|| TREE_TYPE (idx) == error_mark_node)
return error_mark_node;
- itype = TREE_TYPE (idx);
-
if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
&& TREE_CODE (array) != INDIRECT_REF)
{
@@ -1994,7 +2293,8 @@ build_array_ref (array, idx)
Likewise an array of elements of variable size. */
if (TREE_CODE (idx) != INTEGER_CST
|| (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))) != 0
- && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
+ && (TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))))
+ != INTEGER_CST)))
{
if (mark_addressable (array) == 0)
return error_mark_node;
@@ -2072,15 +2372,17 @@ build_array_ref (array, idx)
return error_mark_node;
}
- return build_indirect_ref (build_binary_op_nodefault (PLUS_EXPR, ar, ind, PLUS_EXPR),
+ return build_indirect_ref (build_binary_op_nodefault (PLUS_EXPR, ar,
+ ind, PLUS_EXPR),
"array indexing");
}
}
/* Build a function call to function FUNCTION with parameters PARAMS.
PARAMS is a list--a chain of TREE_LIST nodes--in which the
- TREE_VALUE of each node is a parameter-expression.
- FUNCTION's data type may be a function type or a pointer-to-function.
+ TREE_VALUE of each node is a parameter-expression. The PARAMS do
+ not include any object pointer that may be required. FUNCTION's
+ data type may be a function type or a pointer-to-function.
For C++: If FUNCTION's data type is a TREE_LIST, then the tree list
is the list of possible methods that FUNCTION could conceivably
@@ -2095,35 +2397,82 @@ build_array_ref (array, idx)
In the second case, TREE_PURPOSE (function) is the function's
name directly.
- DECL is the class instance variable, usually CURRENT_CLASS_DECL. */
+ DECL is the class instance variable, usually CURRENT_CLASS_REF.
+
+ When calling a TEMPLATE_DECL, we don't require a complete return
+ type. */
-/*
- * [eichin:19911015.1726EST] actually return a possibly incomplete
- * type
- */
tree
build_x_function_call (function, params, decl)
tree function, params, decl;
{
tree type;
+ tree template_id = NULL_TREE;
int is_method;
if (function == error_mark_node)
return error_mark_node;
+ if (processing_template_decl)
+ return build_min_nt (CALL_EXPR, function, params, NULL_TREE);
+
+ /* Save explicit template arguments if found */
+ if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
+ {
+ template_id = function;
+ function = TREE_OPERAND (function, 0);
+ }
+
type = TREE_TYPE (function);
+
+ if (TREE_CODE (type) == OFFSET_TYPE
+ && TREE_TYPE (type) == unknown_type_node
+ && TREE_CODE (function) == TREE_LIST
+ && TREE_CHAIN (function) == NULL_TREE)
+ {
+ /* Undo (Foo:bar)()... */
+ type = TYPE_OFFSET_BASETYPE (type);
+ function = TREE_VALUE (function);
+ my_friendly_assert (TREE_CODE (function) == TREE_LIST, 999);
+ my_friendly_assert (TREE_CHAIN (function) == NULL_TREE, 999);
+ function = TREE_VALUE (function);
+ if (TREE_CODE (function) == OVERLOAD)
+ function = OVL_FUNCTION (function);
+ my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 999);
+ function = DECL_NAME (function);
+ return build_method_call (decl, function, params,
+ TYPE_BINFO (type), LOOKUP_NORMAL);
+ }
+
is_method = ((TREE_CODE (function) == TREE_LIST
&& current_class_type != NULL_TREE
- && IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function)) == function)
+ && (IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function))
+ == function))
|| TREE_CODE (function) == IDENTIFIER_NODE
|| TREE_CODE (type) == METHOD_TYPE
|| TYPE_PTRMEMFUNC_P (type));
+ if ((TREE_CODE (function) == FUNCTION_DECL
+ && DECL_STATIC_FUNCTION_P (function))
+ || (TREE_CODE (function) == TEMPLATE_DECL
+ && DECL_STATIC_FUNCTION_P (DECL_RESULT (function))))
+ return build_member_call
+ (DECL_CONTEXT (function), DECL_NAME (function), params);
+
+ /* A friend template. Make it look like a toplevel declaration. */
+ if (! is_method && TREE_CODE (function) == TEMPLATE_DECL)
+ function = scratch_ovl_cons (function, NULL_TREE);
+
/* Handle methods, friends, and overloaded functions, respectively. */
if (is_method)
{
- if (TREE_CODE (function) == FUNCTION_DECL)
+ tree basetype = NULL_TREE;
+
+ if (TREE_CODE (function) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (function))
{
+ basetype = DECL_CLASS_CONTEXT (function);
+
if (DECL_NAME (function))
function = DECL_NAME (function);
else
@@ -2131,15 +2480,10 @@ build_x_function_call (function, params, decl)
}
else if (TREE_CODE (function) == TREE_LIST)
{
-#if 0
- if (TREE_CODE (TREE_VALUE (function)) == TREE_LIST)
- function = TREE_PURPOSE (TREE_VALUE (function));
- else
- function = TREE_PURPOSE (function);
-#else
- my_friendly_assert (TREE_CODE (TREE_VALUE (function)) == FUNCTION_DECL, 312);
+ my_friendly_assert (TREE_CODE (TREE_VALUE (function))
+ == FUNCTION_DECL, 312);
+ basetype = DECL_CLASS_CONTEXT (TREE_VALUE (function));
function = TREE_PURPOSE (function);
-#endif
}
else if (TREE_CODE (function) != IDENTIFIER_NODE)
{
@@ -2158,7 +2502,8 @@ build_x_function_call (function, params, decl)
if (TREE_CODE (TREE_TYPE (function)) != POINTER_TYPE
&& ! TYPE_PTRMEMFUNC_P (TREE_TYPE (function))
&& TREE_CODE (function) != OFFSET_REF)
- function = build (OFFSET_REF, TREE_TYPE (type), NULL_TREE, function);
+ function = build (OFFSET_REF, TREE_TYPE (type), NULL_TREE,
+ function);
goto do_x_function;
}
@@ -2166,6 +2511,10 @@ build_x_function_call (function, params, decl)
must go through here in case it is a virtual function.
@@ Perhaps this could be optimized. */
+ if (basetype && (! current_class_type
+ || ! DERIVED_FROM_P (basetype, current_class_type)))
+ return build_member_call (basetype, function, params);
+
if (decl == NULL_TREE)
{
if (current_class_type == NULL_TREE)
@@ -2180,6 +2529,9 @@ build_x_function_call (function, params, decl)
decl = build_indirect_ref (decl, NULL_PTR);
}
+ /* Put back explicit template arguments, if any. */
+ if (template_id)
+ function = template_id;
return build_method_call (decl, function, params,
NULL_TREE, LOOKUP_NORMAL);
}
@@ -2188,16 +2540,16 @@ build_x_function_call (function, params, decl)
{
/* Should we undo what was done in build_component_ref? */
if (TREE_CODE (TREE_PURPOSE (TREE_OPERAND (function, 1))) == TREE_VEC)
- /* Get the name that build_component_ref hid. */
+ /* Get the name that build_component_ref hid. */
function = DECL_NAME (TREE_VALUE (TREE_OPERAND (function, 1)));
else
function = TREE_PURPOSE (TREE_OPERAND (function, 1));
return build_method_call (decl, function, params,
NULL_TREE, LOOKUP_NORMAL);
}
- else if (TREE_CODE (function) == TREE_LIST)
+ else if (really_overloaded_fn (function))
{
- if (TREE_VALUE (function) == NULL_TREE)
+ if (OVL_FUNCTION (function) == NULL_TREE)
{
cp_error ("function `%D' declared overloaded, but no definitions appear with which to resolve it?!?",
TREE_PURPOSE (function));
@@ -2205,18 +2557,15 @@ build_x_function_call (function, params, decl)
}
else
{
- tree val = TREE_VALUE (function);
-
- if (TREE_CODE (val) == TEMPLATE_DECL)
- return build_overload_call_maybe
- (function, params, LOOKUP_COMPLAIN, (struct candidate *)0);
- else if (DECL_CHAIN (val) != NULL_TREE)
- return build_overload_call
- (function, params, LOOKUP_COMPLAIN, (struct candidate *)0);
- else
- my_friendly_abort (360);
+ /* Put back explicit template arguments, if any. */
+ if (template_id)
+ function = template_id;
+ return build_new_function_call (function, params);
}
}
+ else
+ /* Remove a potential OVERLOAD around it */
+ function = OVL_CURRENT (function);
do_x_function:
if (TREE_CODE (function) == OFFSET_REF)
@@ -2228,12 +2577,23 @@ build_x_function_call (function, params, decl)
if (TREE_OPERAND (function, 0))
decl = TREE_OPERAND (function, 0);
else
- decl = C_C_D;
+ decl = current_class_ref;
decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
- function = get_member_function_from_ptrfunc (&decl_addr,
- TREE_OPERAND (function, 1));
- params = tree_cons (NULL_TREE, decl_addr, params);
+
+ /* Sigh. OFFSET_REFs are being used for too many things.
+ They're being used both for -> and ->*, and we want to resolve
+ the -> cases here, but leave the ->*. We could use
+ resolve_offset_ref for those, too, but it would call
+ get_member_function_from_ptrfunc and decl_addr wouldn't get
+ updated properly. Nasty. */
+ if (TREE_CODE (TREE_OPERAND (function, 1)) == FIELD_DECL)
+ function = resolve_offset_ref (function);
+ else
+ function = TREE_OPERAND (function, 1);
+
+ function = get_member_function_from_ptrfunc (&decl_addr, function);
+ params = expr_tree_cons (NULL_TREE, decl_addr, params);
return build_function_call (function, params);
}
@@ -2243,14 +2603,14 @@ build_x_function_call (function, params, decl)
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
- if (TYPE_LANG_SPECIFIC (type) && TYPE_OVERLOADS_CALL_EXPR (type))
+ if (IS_AGGR_TYPE (type))
return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, function, params, NULL_TREE);
}
if (is_method)
{
tree fntype = TREE_TYPE (function);
- tree ctypeptr;
+ tree ctypeptr = NULL_TREE;
/* Explicitly named method? */
if (TREE_CODE (function) == FUNCTION_DECL)
@@ -2260,7 +2620,8 @@ build_x_function_call (function, params, decl)
passed in as an argument. */
else if (TYPE_PTRMEMFUNC_P (fntype))
{
- tree rec = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (fntype)));
+ tree rec = TYPE_METHOD_BASETYPE (TREE_TYPE
+ (TYPE_PTRMEMFUNC_FN_TYPE (fntype)));
ctypeptr = build_pointer_type (rec);
}
/* Unexpected node type? */
@@ -2282,8 +2643,8 @@ build_x_function_call (function, params, decl)
decl = convert_pointer_to (TREE_TYPE (ctypeptr), decl);
}
else
- decl = build_c_cast (ctypeptr, decl, 0);
- params = tree_cons (NULL_TREE, decl, params);
+ decl = build_c_cast (ctypeptr, decl);
+ params = expr_tree_cons (NULL_TREE, decl, params);
}
return build_function_call (function, params);
@@ -2304,7 +2665,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
- tree fntype, index, e1, delta, delta2, e2, e3, aref, vtbl;
+ tree fntype, idx, e1, delta, delta2, e2, e3, aref, vtbl;
tree instance;
tree instance_ptr = *instance_ptrptr;
@@ -2316,43 +2677,49 @@ get_member_function_from_ptrfunc (instance_ptrptr, 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));
+
+ /* Promoting idx before saving it improves performance on RISC
+ targets. Without promoting, the first compare used
+ load-with-sign-extend, while the second used normal load then
+ shift to sign-extend. An optimizer flaw, perhaps, but it's easier
+ to make this change. */
+ idx = save_expr (default_conversion
+ (build_component_ref (function,
+ index_identifier,
+ NULL_TREE, 0)));
+ e1 = build_binary_op (GT_EXPR, idx, integer_zero_node, 1);
+ delta = cp_convert (ptrdiff_type_node,
+ build_component_ref (function, delta_identifier,
+ NULL_TREE, 0));
delta2 = DELTA2_FROM_PTRMEMFUNC (function);
- /* convert down to the right base, before using the instance. */
+ /* Convert down to the right base, before using the instance. */
instance
= convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
instance_ptr);
- if (instance == error_mark_node)
+ if (instance == error_mark_node && instance_ptr != error_mark_node)
return instance;
vtbl = convert_pointer_to (ptr_type_node, instance);
vtbl
= build (PLUS_EXPR,
build_pointer_type (build_pointer_type (vtable_entry_type)),
- vtbl, convert (ptrdiff_type_node, delta2));
+ vtbl, cp_convert (ptrdiff_type_node, delta2));
vtbl = build_indirect_ref (vtbl, NULL_PTR);
aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
- index,
+ idx,
integer_one_node, 1));
if (! flag_vtable_thunks)
{
aref = save_expr (aref);
- /* Save the intermediate result in a SAVE_EXPR so we don't have to
- compute each component of the virtual function pointer twice. */
- if (/* !building_cleanup && */ TREE_CODE (aref) == INDIRECT_REF)
- TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
-
- delta = build_binary_op (PLUS_EXPR,
- build_conditional_expr (e1, build_component_ref (aref, delta_identifier, 0, 0), integer_zero_node),
- delta, 1);
+ delta = build_binary_op
+ (PLUS_EXPR,
+ build_conditional_expr (e1, build_component_ref (aref,
+ delta_identifier,
+ NULL_TREE, 0),
+ integer_zero_node),
+ delta, 1);
}
*instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
@@ -2360,11 +2727,18 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
if (flag_vtable_thunks)
e2 = aref;
else
- e2 = build_component_ref (aref, pfn_identifier, 0, 0);
+ e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
e3 = PFN_FROM_PTRMEMFUNC (function);
TREE_TYPE (e2) = TREE_TYPE (e3);
- function = build_conditional_expr (e1, e2, e3);
+ e1 = build_conditional_expr (e1, e2, e3);
+
+ if (instance_ptr == error_mark_node
+ && TREE_CODE (e1) != ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (e1, 0)) != FUNCTION_DECL)
+ cp_error ("object missing in `%E'", function);
+
+ function = e1;
/* Make sure this doesn't get evaluated first inside one of the
branches of the COND_EXPR. */
@@ -2399,68 +2773,41 @@ build_function_call_real (function, params, require_complete, flags)
GNU_xref_call (current_function_decl,
IDENTIFIER_POINTER (name ? name
- : TYPE_IDENTIFIER (DECL_CLASS_CONTEXT (function))));
- assemble_external (function);
+ : TYPE_IDENTIFIER (DECL_CLASS_CONTEXT
+ (function))));
+ mark_used (function);
fndecl = function;
/* Convert anything with function type to a pointer-to-function. */
- if (pedantic
- && name
- && IDENTIFIER_LENGTH (name) == 4
- && ! strcmp (IDENTIFIER_POINTER (name), "main")
- && DECL_CONTEXT (function) == NULL_TREE)
- {
- pedwarn ("ANSI C++ forbids calling `main' from within program");
- }
-
- if (pedantic && DECL_THIS_INLINE (function) && ! DECL_INITIAL (function)
- && ! DECL_ARTIFICIAL (function)
- && ! DECL_PENDING_INLINE_INFO (function))
- cp_pedwarn ("inline function `%#D' called before definition",
- function);
+ if (pedantic && DECL_MAIN_P (function))
+ pedwarn ("ANSI C++ forbids calling `main' from within program");
/* Differs from default_conversion by not setting TREE_ADDRESSABLE
(because calling an inline function does not mean the function
needs to be separately compiled). */
if (DECL_INLINE (function))
- {
- /* Is it a synthesized method that needs to be synthesized? */
- if (DECL_ARTIFICIAL (function) && ! flag_no_inline
- && ! DECL_INITIAL (function)
- /* Kludge: don't synthesize for default args. */
- && current_function_decl)
- synthesize_method (function);
-
- fntype = build_type_variant (TREE_TYPE (function),
- TREE_READONLY (function),
- TREE_THIS_VOLATILE (function));
- function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
- }
+ function = inline_conversion (function);
else
- {
- assemble_external (function);
- TREE_USED (function) = 1;
- function = default_conversion (function);
- }
+ function = build_addr_func (function);
}
else
{
fndecl = NULL_TREE;
- /* Convert anything with function type to a pointer-to-function. */
- if (function == error_mark_node)
- return error_mark_node;
- function = default_conversion (function);
+ function = build_addr_func (function);
}
+ if (function == error_mark_node)
+ return error_mark_node;
+
fntype = TREE_TYPE (function);
if (TYPE_PTRMEMFUNC_P (fntype))
{
- tree instance_ptr = build_unary_op (ADDR_EXPR, C_C_D, 0);
- fntype = TYPE_PTRMEMFUNC_FN_TYPE (fntype);
- function = get_member_function_from_ptrfunc (&instance_ptr, function);
+ cp_error ("must use .* or ->* to call pointer-to-member function in `%E (...)'",
+ function);
+ return error_mark_node;
}
is_method = (TREE_CODE (fntype) == POINTER_TYPE
@@ -2468,7 +2815,8 @@ build_function_call_real (function, params, require_complete, flags)
if (!((TREE_CODE (fntype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE)
- || is_method))
+ || is_method
+ || TREE_CODE (function) == TEMPLATE_ID_EXPR))
{
cp_error ("`%E' cannot be used as a function", function);
return error_mark_node;
@@ -2488,10 +2836,12 @@ build_function_call_real (function, params, require_complete, flags)
params, fndecl, 0);
if (coerced_params == error_mark_node)
- if (flags & LOOKUP_SPECULATIVELY)
- return NULL_TREE;
- else
- return error_mark_node;
+ {
+ if (flags & LOOKUP_SPECULATIVELY)
+ return NULL_TREE;
+ else
+ return error_mark_node;
+ }
/* Check for errors in format strings. */
@@ -2513,22 +2863,25 @@ build_function_call_real (function, params, require_complete, flags)
if (coerced_params == 0)
return integer_zero_node;
return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
+
+ default:
+ break;
}
/* C++ */
value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
{
- register tree result =
- build (CALL_EXPR, value_type,
- function, coerced_params, NULL_TREE);
-
- TREE_SIDE_EFFECTS (result) = 1;
+ register tree result
+ = build_call (function, value_type, coerced_params);
- if (! require_complete)
- return convert_from_reference (result);
- if (value_type == void_type_node)
- return result;
- result = require_complete_type (result);
+ if (require_complete)
+ {
+ if (value_type == void_type_node)
+ return result;
+ result = require_complete_type (result);
+ }
+ if (IS_AGGR_TYPE (value_type))
+ result = build_cplus_new (value_type, result);
return convert_from_reference (result);
}
}
@@ -2539,14 +2892,6 @@ build_function_call (function, params)
{
return build_function_call_real (function, params, 1, LOOKUP_NORMAL);
}
-
-tree
-build_function_call_maybe (function, params)
- tree function, params;
-{
- return build_function_call_real (function, params, 0, 0);
-}
-
/* Convert the actual parameter expressions in the list VALUES
to the types in the list TYPELIST.
@@ -2576,15 +2921,17 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
tree return_loc, typelist, values, fndecl;
int flags;
{
- extern tree gc_protect_fndecl;
register tree typetail, valtail;
register tree result = NULL_TREE;
- char *called_thing;
+ char *called_thing = 0;
int i = 0;
if (! flag_elide_constructors)
return_loc = 0;
+ /* Argument passing is always copy-initialization. */
+ flags |= LOOKUP_ONLYCONVERTING;
+
if (fndecl)
{
if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
@@ -2613,9 +2960,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
{
if (fndecl)
{
- char *buf = (char *)alloca (40 + strlen (called_thing));
- sprintf (buf, "too many arguments to %s `%%s'", called_thing);
- error_with_decl (fndecl, buf);
+ cp_error_at ("too many arguments to %s `%+D'", called_thing,
+ fndecl);
error ("at this point in file");
}
else
@@ -2638,44 +2984,22 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
/* Strip the `&' from an overloaded FUNCTION_DECL. */
if (TREE_CODE (val) == ADDR_EXPR)
val = TREE_OPERAND (val, 0);
- if (TREE_CODE (val) == TREE_LIST
- && TREE_CHAIN (val) == NULL_TREE
- && TREE_TYPE (TREE_VALUE (val)) != NULL_TREE
- && (TREE_TYPE (val) == unknown_type_node
- || DECL_CHAIN (TREE_VALUE (val)) == NULL_TREE))
- /* Instantiates automatically. */
- val = TREE_VALUE (val);
+ if (really_overloaded_fn (val))
+ cp_error ("insufficient type information to resolve address of overloaded function `%D'",
+ DECL_NAME (get_first_fn (val)));
else
- {
- error ("insufficient type information in parameter list");
- val = integer_zero_node;
- }
+ error ("insufficient type information in parameter list");
+ val = integer_zero_node;
}
else if (TREE_CODE (val) == OFFSET_REF
&& TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
{
- /* This is unclean. Should be handled elsewhere. */
+ /* This is unclean. Should be handled elsewhere. */
val = build_unary_op (ADDR_EXPR, val, 0);
}
else if (TREE_CODE (val) == OFFSET_REF)
val = resolve_offset_ref (val);
- {
-#if 0
- /* This code forces the assumption that if we have a ptr-to-func
- type in an arglist, that every routine that wants to check
- its validity has done so, and thus we need not do any
- more conversion. I don't remember why this is necessary. */
- else if (TREE_CODE (ttype) == FUNCTION_TYPE
- && (type == NULL
- || TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (type)) == VOID_TYPE))
- {
- type = build_pointer_type (ttype);
- }
-#endif
- }
-
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */
if (TREE_CODE (val) == NOP_EXPR
@@ -2701,29 +3025,21 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
/* Formal parm type is specified by a function prototype. */
tree parmval;
- if (TYPE_SIZE (type) == 0)
+ if (TYPE_SIZE (complete_type (type)) == 0)
{
error ("parameter type of called function is incomplete");
parmval = val;
}
else
{
-#if 0 && defined (PROMOTE_PROTOTYPES)
- /* This breaks user-defined conversions. */
- /* Rather than truncating and then reextending,
- convert directly to int, if that's the type we will want. */
- if (! flag_traditional
- && (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- type = integer_type_node;
-#endif
- parmval = convert_for_initialization (return_loc, type, val, flags,
- "argument passing", fndecl, i);
+ parmval = convert_for_initialization
+ (return_loc, type, val, flags,
+ "argument passing", fndecl, i);
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
+ && (TYPE_PRECISION (type)
+ < TYPE_PRECISION (integer_type_node)))
parmval = default_conversion (parmval);
#endif
}
@@ -2731,41 +3047,18 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
if (parmval == error_mark_node)
return error_mark_node;
- result = tree_cons (NULL_TREE, parmval, result);
+ result = expr_tree_cons (NULL_TREE, parmval, result);
}
else
{
if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
val = convert_from_reference (val);
- if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
- && (TYPE_PRECISION (TREE_TYPE (val))
- < TYPE_PRECISION (double_type_node)))
- /* Convert `float' to `double'. */
- result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
- else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val))
- && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
- {
- cp_warning ("cannot pass objects of type `%T' through `...'",
- TREE_TYPE (val));
- result = tree_cons (NULL_TREE, val, result);
- }
- else
- /* Convert `short' and `char' to full-size `int'. */
- result = tree_cons (NULL_TREE, default_conversion (val), result);
+ result = expr_tree_cons (NULL_TREE,
+ convert_arg_to_ellipsis (val),
+ result);
}
- if (flag_gc
- /* There are certain functions for which we don't need
- to protect our arguments. GC_PROTECT_FNDECL is one. */
- && fndecl != gc_protect_fndecl
- && type_needs_gc_entry (TREE_TYPE (TREE_VALUE (result)))
- && ! value_safe_from_gc (NULL_TREE, TREE_VALUE (result)))
- /* This will build a temporary variable whose cleanup is
- to clear the obstack entry. */
- TREE_VALUE (result) = protect_value_from_gc (NULL_TREE,
- TREE_VALUE (result));
-
if (typetail)
typetail = TREE_CHAIN (typetail);
}
@@ -2778,42 +3071,13 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
for (; typetail != void_list_node; ++i)
{
tree type = TREE_VALUE (typetail);
- tree val = break_out_target_exprs (TREE_PURPOSE (typetail));
- tree parmval;
-
- if (val == NULL_TREE)
- parmval = error_mark_node;
- else if (TREE_CODE (val) == CONSTRUCTOR)
- {
- parmval = digest_init (type, val, (tree *)0);
- parmval = convert_for_initialization (return_loc, type, parmval, flags,
- "default constructor", fndecl, i);
- }
- else
- {
- /* This could get clobbered by the following call. */
- if (TREE_HAS_CONSTRUCTOR (val))
- val = copy_node (val);
-
- parmval = convert_for_initialization (return_loc, type, val, flags,
- "default argument", fndecl, i);
-#ifdef PROMOTE_PROTOTYPES
- if ((TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- parmval = default_conversion (parmval);
-#endif
- }
+ tree val = TREE_PURPOSE (typetail);
+ tree parmval = convert_default_arg (type, val);
if (parmval == error_mark_node)
return error_mark_node;
- if (flag_gc
- && type_needs_gc_entry (TREE_TYPE (parmval))
- && ! value_safe_from_gc (NULL_TREE, parmval))
- parmval = protect_value_from_gc (NULL_TREE, parmval);
-
- result = tree_cons (0, parmval, result);
+ result = expr_tree_cons (0, parmval, result);
typetail = TREE_CHAIN (typetail);
/* ends with `...'. */
if (typetail == NULL_TREE)
@@ -2846,14 +3110,10 @@ build_x_binary_op (code, arg1, arg2)
enum tree_code code;
tree arg1, arg2;
{
- tree rval = build_opfncall (code, LOOKUP_SPECULATIVELY,
- arg1, arg2, NULL_TREE);
- if (rval)
- return build_opfncall (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
- if (code == MEMBER_REF)
- return build_m_component_ref (build_indirect_ref (arg1, NULL_PTR),
- arg2);
- return build_binary_op (code, arg1, arg2, 1);
+ if (processing_template_decl)
+ return build_min_nt (code, arg1, arg2);
+
+ return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
}
tree
@@ -2869,7 +3129,6 @@ build_binary_op (code, arg1, arg2, convert_p)
if (convert_p)
{
- tree args_save [2];
tree type0, type1;
args[0] = decay_conversion (args[0]);
args[1] = decay_conversion (args[1]);
@@ -2893,15 +3152,7 @@ build_binary_op (code, arg1, arg2, convert_p)
}
if (IS_AGGR_TYPE (type0) || IS_AGGR_TYPE (type1))
- {
- /* Try to convert this to something reasonable. */
- if (! build_default_binary_type_conversion(code, &args[0], &args[1]))
- {
- cp_error ("no match for `%O(%#T, %#T)'", code,
- TREE_TYPE (arg1), TREE_TYPE (arg2));
- return error_mark_node;
- }
- }
+ my_friendly_abort (754867);
}
return build_binary_op_nodefault (code, args[0], args[1], code);
}
@@ -3028,7 +3279,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
We must subtract them as integers, then divide by object size. */
if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
&& comp_target_types (type0, type1, 1))
- return pointer_diff (op0, op1);
+ return pointer_diff (op0, op1, common_type (type0, type1));
/* Handle pointer minus int. Just like pointer plus int. */
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
return pointer_int_sum (MINUS_EXPR, op0, op1);
@@ -3045,8 +3296,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+ || code0 == COMPLEX_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == COMPLEX_TYPE))
{
if (TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1))
cp_warning ("division by zero in `%E / 0'", op0);
@@ -3083,7 +3336,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
in the short type, making the entire operation go away. */
if (TREE_CODE (op0) == INTEGER_CST
&& TREE_CODE (op1) == NOP_EXPR
- && TYPE_PRECISION (type1) > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))
+ && (TYPE_PRECISION (type1)
+ > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0))))
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op1, 0))))
{
final_type = result_type;
@@ -3092,7 +3346,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
}
if (TREE_CODE (op1) == INTEGER_CST
&& TREE_CODE (op0) == NOP_EXPR
- && TYPE_PRECISION (type0) > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))
+ && (TYPE_PRECISION (type0)
+ > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0))))
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
{
final_type = result_type;
@@ -3104,9 +3359,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
if (code1 == INTEGER_TYPE && integer_zerop (op1))
- cp_warning ("division by zero in `%E % 0'", op0);
+ cp_warning ("division by zero in `%E %% 0'", op0);
else if (code1 == REAL_TYPE && real_zerop (op1))
- cp_warning ("division by zero in `%E % 0.'", op0);
+ cp_warning ("division by zero in `%E %% 0.'", op0);
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
@@ -3155,7 +3410,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
+ op1 = cp_convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */
converted = 1;
}
@@ -3177,7 +3432,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
+ op1 = cp_convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */
converted = 1;
}
@@ -3202,15 +3457,17 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
+ op1 = cp_convert (integer_type_node, op1);
}
break;
case EQ_EXPR:
case NE_EXPR:
build_type = boolean_type_node;
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+ || code0 == COMPLEX_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == COMPLEX_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
@@ -3259,14 +3516,14 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
else if (TYPE_PTRMEMFUNC_P (type0) && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
{
- op0 = build_component_ref (op0, index_identifier, 0, 0);
+ op0 = build_component_ref (op0, index_identifier, NULL_TREE, 0);
op1 = integer_zero_node;
result_type = TREE_TYPE (op0);
}
else if (TYPE_PTRMEMFUNC_P (type1) && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
{
- op0 = build_component_ref (op1, index_identifier, 0, 0);
+ op0 = build_component_ref (op1, index_identifier, NULL_TREE, 0);
op1 = integer_zero_node;
result_type = TREE_TYPE (op0);
}
@@ -3280,18 +3537,23 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
&& ((op1.index != -1 && op0.delta2 == op1.delta2)
|| op0.pfn == op1.pfn)) */
- tree index0 = build_component_ref (op0, index_identifier, 0, 0);
- tree index1 = save_expr (build_component_ref (op1, index_identifier, 0, 0));
+ tree index0 = build_component_ref (op0, index_identifier,
+ NULL_TREE, 0);
+ tree index1 = save_expr (build_component_ref (op1, index_identifier,
+ NULL_TREE, 0));
tree pfn0 = PFN_FROM_PTRMEMFUNC (op0);
tree pfn1 = PFN_FROM_PTRMEMFUNC (op1);
tree delta20 = DELTA2_FROM_PTRMEMFUNC (op0);
tree delta21 = DELTA2_FROM_PTRMEMFUNC (op1);
tree e1, e2, e3;
tree integer_neg_one_node
- = build_binary_op (MINUS_EXPR, integer_zero_node, integer_one_node, 1);
+ = build_binary_op (MINUS_EXPR, integer_zero_node,
+ integer_one_node, 1);
e1 = build_binary_op (EQ_EXPR, index0, index1, 1);
e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node, 1);
- e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2, build_binary_op (EQ_EXPR, delta20, delta21, 1), 1);
+ e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2,
+ build_binary_op (EQ_EXPR, delta20, delta21, 1),
+ 1);
e3 = build_binary_op (EQ_EXPR, pfn0, pfn1, 1);
e2 = build_binary_op (TRUTH_ORIF_EXPR, e2, e3, 1);
e2 = build_binary_op (TRUTH_ANDIF_EXPR, e1, e2, 1);
@@ -3302,7 +3564,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
else if (TYPE_PTRMEMFUNC_P (type0)
&& TYPE_PTRMEMFUNC_FN_TYPE (type0) == type1)
{
- tree index0 = build_component_ref (op0, index_identifier, 0, 0);
+ tree index0 = build_component_ref (op0, index_identifier,
+ NULL_TREE, 0);
tree index1;
tree pfn0 = PFN_FROM_PTRMEMFUNC (op0);
tree delta20 = DELTA2_FROM_PTRMEMFUNC (op0);
@@ -3313,25 +3576,32 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
if (TREE_CODE (TREE_OPERAND (op1, 0)) == FUNCTION_DECL
&& DECL_VINDEX (TREE_OPERAND (op1, 0)))
{
- /* Map everything down one to make room for the null pointer to member. */
+ /* Map everything down one to make room for
+ the null pointer to member. */
index1 = size_binop (PLUS_EXPR,
DECL_VINDEX (TREE_OPERAND (op1, 0)),
integer_one_node);
op1 = integer_zero_node;
- delta21 = CLASSTYPE_VFIELD (TYPE_METHOD_BASETYPE (TREE_TYPE (type1)));
+ delta21 = CLASSTYPE_VFIELD (TYPE_METHOD_BASETYPE
+ (TREE_TYPE (type1)));
delta21 = DECL_FIELD_BITPOS (delta21);
- delta21 = size_binop (FLOOR_DIV_EXPR, delta21, size_int (BITS_PER_UNIT));
+ delta21 = size_binop (FLOOR_DIV_EXPR, delta21,
+ size_int (BITS_PER_UNIT));
+ delta21 = convert (sizetype, delta21);
}
else
index1 = integer_neg_one_node;
{
- tree nop1 = build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type0), op1);
+ tree nop1 = build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type0),
+ op1);
TREE_CONSTANT (nop1) = TREE_CONSTANT (op1);
op1 = nop1;
}
e1 = build_binary_op (EQ_EXPR, index0, index1, 1);
e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node, 1);
- e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2, build_binary_op (EQ_EXPR, delta20, delta21, 1), 1);
+ e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2,
+ build_binary_op (EQ_EXPR, delta20, delta21, 1),
+ 1);
e3 = build_binary_op (EQ_EXPR, pfn0, op1, 1);
e2 = build_binary_op (TRUTH_ORIF_EXPR, e2, e3, 1);
e2 = build_binary_op (TRUTH_ANDIF_EXPR, e1, e2, 1);
@@ -3392,25 +3662,25 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
- if (pedantic)
- pedwarn ("ANSI C++ forbids comparison between pointer and integer");
- else if (! flag_traditional)
- warning ("comparison between pointer and integer");
+ pedwarn ("ANSI C++ forbids comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
- if (pedantic)
- pedwarn ("ANSI C++ forbids comparison between pointer and integer");
- else if (! flag_traditional)
- warning ("comparison between pointer and integer");
+ pedwarn ("ANSI C++ forbids comparison between pointer and integer");
}
break;
+
+ default:
+ break;
}
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+ &&
+ (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
{
+ int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
+
if (shorten || common || short_compare)
result_type = common_type (type0, type1);
@@ -3425,7 +3695,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
Eg, (short)-1 | (unsigned short)-1 is (int)-1
but calculated in (unsigned short) it would be (unsigned short)-1. */
- if (shorten)
+ if (shorten && none_complex)
{
int unsigned0, unsigned1;
tree arg0 = get_narrower (op0, &unsigned0);
@@ -3466,7 +3736,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
&& (unsigned0 || !uns))
result_type
= signed_or_unsigned_type (unsigned0,
- common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
+ common_type (TREE_TYPE (arg0),
+ TREE_TYPE (arg1)));
else if (TREE_CODE (arg0) == INTEGER_CST
&& (unsigned1 || !uns)
&& (TYPE_PRECISION (TREE_TYPE (arg1))
@@ -3511,7 +3782,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
it never happens because available widths are 2**N. */
&& (!TREE_UNSIGNED (final_type)
|| unsigned_arg
- || ((unsigned) 2 * TYPE_PRECISION (TREE_TYPE (arg0))
+ || (((unsigned) 2 * TYPE_PRECISION (TREE_TYPE (arg0)))
<= TYPE_PRECISION (result_type))))
{
/* Do an unsigned shift if the operand was zero-extended. */
@@ -3520,7 +3791,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
TREE_TYPE (arg0));
/* Convert value-to-be-shifted to that type. */
if (TREE_TYPE (op0) != result_type)
- op0 = convert (result_type, op0);
+ op0 = cp_convert (result_type, op0);
converted = 1;
}
}
@@ -3539,13 +3810,13 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree val
= shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
if (val != 0)
- return convert (boolean_type_node, val);
+ return cp_convert (boolean_type_node, val);
op0 = xop0, op1 = xop1;
converted = 1;
resultcode = xresultcode;
}
- if (short_compare && extra_warnings)
+ if (short_compare && warn_sign_compare)
{
int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
@@ -3554,6 +3825,17 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree primop0 = get_narrower (op0, &unsignedp0);
tree primop1 = get_narrower (op1, &unsignedp1);
+ /* Check for comparison of different enum types. */
+ if (flag_int_enum_equivalence == 0
+ && TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
+ && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
+ {
+ cp_warning ("comparison between `%#T' and `%#T'",
+ TREE_TYPE (orig_op0), TREE_TYPE (orig_op1));
+ }
+
/* Give warnings for comparisons between signed and unsigned
quantities that may fail. */
/* Do the checking based on the original operand trees, so that
@@ -3580,9 +3862,11 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
not use the most significant bit of result_type. */
else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR)
&& ((op0_signed && TREE_CODE (orig_op1) == INTEGER_CST
- && int_fits_type_p (orig_op1, signed_type (result_type))
+ && int_fits_type_p (orig_op1,
+ signed_type (result_type)))
|| (op1_signed && TREE_CODE (orig_op0) == INTEGER_CST
- && int_fits_type_p (orig_op0, signed_type (result_type))))))
+ && int_fits_type_p (orig_op0,
+ signed_type (result_type)))))
/* OK */;
else
warning ("comparison between signed and unsigned");
@@ -3595,8 +3879,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
have all bits set that are set in the ~ operand when it is
extended. */
- if (TREE_CODE (primop0) == BIT_NOT_EXPR
- ^ TREE_CODE (primop1) == BIT_NOT_EXPR)
+ if ((TREE_CODE (primop0) == BIT_NOT_EXPR)
+ ^ (TREE_CODE (primop1) == BIT_NOT_EXPR))
{
if (TREE_CODE (primop0) == BIT_NOT_EXPR)
primop0 = get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
@@ -3659,9 +3943,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
if (! converted)
{
if (TREE_TYPE (op0) != result_type)
- op0 = convert (result_type, op0);
+ op0 = cp_convert (result_type, op0);
if (TREE_TYPE (op1) != result_type)
- op1 = convert (result_type, op1);
+ op1 = cp_convert (result_type, op1);
}
if (build_type == NULL_TREE)
@@ -3675,7 +3959,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
if (folded == result)
TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
if (final_type != 0)
- return convert (final_type, folded);
+ return cp_convert (final_type, folded);
return folded;
}
}
@@ -3697,6 +3981,9 @@ pointer_int_sum (resultcode, ptrop, intop)
register tree result_type = TREE_TYPE (ptrop);
+ if (!complete_type_or_else (result_type))
+ return error_mark_node;
+
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
{
if (pedantic || warn_pointer_arith)
@@ -3717,12 +4004,12 @@ pointer_int_sum (resultcode, ptrop, intop)
}
else if (TREE_CODE (TREE_TYPE (result_type)) == OFFSET_TYPE)
{
- if (pedantic)
+ if (pedantic || warn_pointer_arith)
pedwarn ("ANSI C++ forbids using pointer to a member in arithmetic");
size_exp = integer_one_node;
}
else
- size_exp = size_in_bytes (TREE_TYPE (result_type));
+ size_exp = size_in_bytes (complete_type (TREE_TYPE (result_type)));
/* Needed to make OOPS V2R3 work. */
intop = folded;
@@ -3748,19 +4035,21 @@ pointer_int_sum (resultcode, ptrop, intop)
intop = TREE_OPERAND (intop, 0);
}
- /* Convert the integer argument to a type the same size as a pointer
+ /* Convert the integer argument to a type the same size as sizetype
so the multiply won't overflow spuriously. */
- if (TYPE_PRECISION (TREE_TYPE (intop)) != POINTER_SIZE)
- intop = convert (type_for_size (POINTER_SIZE, 0), intop);
+ if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype))
+ intop = cp_convert (type_for_size (TYPE_PRECISION (sizetype), 0), intop);
/* Replace the integer argument with a suitable product by the object size.
Do this multiplication as signed, then convert to the appropriate
pointer type (actually unsigned integral). */
- intop = convert (result_type,
- build_binary_op (MULT_EXPR, intop,
- convert (TREE_TYPE (intop), size_exp), 1));
+ intop = cp_convert (result_type,
+ build_binary_op (MULT_EXPR, intop,
+ cp_convert (TREE_TYPE (intop),
+ size_exp),
+ 1));
/* Create the sum or difference. */
@@ -3776,14 +4065,18 @@ pointer_int_sum (resultcode, ptrop, intop)
The resulting tree has type int. */
static tree
-pointer_diff (op0, op1)
+pointer_diff (op0, op1, ptrtype)
register tree op0, op1;
+ register tree ptrtype;
{
register tree result, folded;
tree restype = ptrdiff_type_node;
- tree target_type = TREE_TYPE (TREE_TYPE (op0));
+ tree target_type = TREE_TYPE (ptrtype);
- if (pedantic)
+ if (!complete_type_or_else (target_type))
+ return error_mark_node;
+
+ if (pedantic || warn_pointer_arith)
{
if (TREE_CODE (target_type) == VOID_TYPE)
pedwarn ("ANSI C++ forbids using pointer of type `void *' in subtraction");
@@ -3798,8 +4091,8 @@ pointer_diff (op0, op1)
/* First do the subtraction as integers;
then drop through to build the divide operator. */
- op0 = build_binary_op (MINUS_EXPR,
- convert (restype, op0), convert (restype, op1), 1);
+ op0 = build_binary_op (MINUS_EXPR, cp_convert (restype, op0),
+ cp_convert (restype, op1), 1);
/* This generates an error if op1 is a pointer to an incomplete type. */
if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0)
@@ -3814,7 +4107,7 @@ pointer_diff (op0, op1)
/* Do the division. */
- result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
+ result = build (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1));
folded = fold (result);
if (folded == result)
@@ -3845,9 +4138,6 @@ build_component_addr (arg, argtype, msg)
return error_mark_node;
}
- if (flag_gc)
- cp_warning ("address of `%T::%D' taken", basetype, field);
-
if (TREE_CODE (field) == FIELD_DECL
&& TYPE_USES_COMPLEX_INHERITANCE (basetype))
{
@@ -3867,8 +4157,9 @@ build_component_addr (arg, argtype, msg)
tree offset = size_binop (EASY_DIV_EXPR, DECL_FIELD_BITPOS (field),
size_int (BITS_PER_UNIT));
int flag = TREE_CONSTANT (rval);
+ offset = convert (sizetype, offset);
rval = fold (build (PLUS_EXPR, argtype,
- rval, convert (argtype, offset)));
+ rval, cp_convert (argtype, offset)));
TREE_CONSTANT (rval) = flag;
}
return rval;
@@ -3883,21 +4174,33 @@ build_x_unary_op (code, xarg)
enum tree_code code;
tree xarg;
{
+ if (processing_template_decl)
+ return build_min_nt (code, xarg, NULL_TREE);
+
/* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
- error message. */
+ error message. */
if (code == ADDR_EXPR
+ && TREE_CODE (xarg) != TEMPLATE_ID_EXPR
&& ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (xarg)))
&& TYPE_SIZE (TREE_TYPE (xarg)) == NULL_TREE)
|| (TREE_CODE (xarg) == OFFSET_REF)))
/* don't look for a function */;
else
{
- tree rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg,
- NULL_TREE, NULL_TREE);
- if (rval)
- return build_opfncall (code, LOOKUP_NORMAL, xarg,
- NULL_TREE, NULL_TREE);
+ tree rval;
+
+ rval = build_new_op (code, LOOKUP_NORMAL, xarg,
+ NULL_TREE, NULL_TREE);
+ if (rval || code != ADDR_EXPR)
+ return rval;
}
+
+ if (code == ADDR_EXPR)
+ {
+ if (TREE_CODE (xarg) == TARGET_EXPR)
+ warning ("taking address of temporary");
+ }
+
return build_unary_op (code, xarg, 0);
}
@@ -3907,7 +4210,10 @@ tree
condition_conversion (expr)
tree expr;
{
- tree t = convert (boolean_type_node, expr);
+ tree t;
+ if (processing_template_decl)
+ return expr;
+ t = cp_convert (boolean_type_node, expr);
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
return t;
}
@@ -3920,6 +4226,7 @@ condition_conversion (expr)
NOCONVERT nonzero suppresses the default promotions
(such as from short to int). */
+
tree
build_unary_op (code, xarg, noconvert)
enum tree_code code;
@@ -3949,6 +4256,7 @@ build_unary_op (code, xarg, noconvert)
if (!noconvert)
arg = default_conversion (arg);
arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
+ TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
}
break;
@@ -3960,7 +4268,14 @@ build_unary_op (code, xarg, noconvert)
break;
case BIT_NOT_EXPR:
- if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM, arg, 1)))
+ if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ {
+ code = CONJ_EXPR;
+ if (!noconvert)
+ arg = default_conversion (arg);
+ }
+ else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM,
+ arg, 1)))
errstring = "wrong type argument to bit-complement";
else if (!noconvert)
arg = default_conversion (arg);
@@ -3973,8 +4288,16 @@ build_unary_op (code, xarg, noconvert)
arg = default_conversion (arg);
break;
+ case CONJ_EXPR:
+ /* Conjugating a real value is a no-op, but allow it anyway. */
+ if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1)))
+ errstring = "wrong type argument to conjugation";
+ else if (!noconvert)
+ arg = default_conversion (arg);
+ break;
+
case TRUTH_NOT_EXPR:
- arg = convert (boolean_type_node, arg);
+ arg = cp_convert (boolean_type_node, arg);
val = invert_truthvalue (arg);
if (arg != error_mark_node)
return val;
@@ -3984,6 +4307,22 @@ build_unary_op (code, xarg, noconvert)
case NOP_EXPR:
break;
+ case REALPART_EXPR:
+ if (TREE_CODE (arg) == COMPLEX_CST)
+ return TREE_REALPART (arg);
+ else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+ else
+ return arg;
+
+ case IMAGPART_EXPR:
+ if (TREE_CODE (arg) == COMPLEX_CST)
+ return TREE_IMAGPART (arg);
+ else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+ else
+ return cp_convert (TREE_TYPE (arg), integer_zero_node);
+
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
case PREDECREMENT_EXPR:
@@ -3995,6 +4334,19 @@ build_unary_op (code, xarg, noconvert)
if (val != 0)
return val;
+ /* Increment or decrement the real part of the value,
+ and don't change the imaginary part. */
+ if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ {
+ tree real, imag;
+
+ arg = stabilize_reference (arg);
+ real = build_unary_op (REALPART_EXPR, arg, 1);
+ imag = build_unary_op (IMAGPART_EXPR, arg, 1);
+ return build (COMPLEX_EXPR, TREE_TYPE (arg),
+ build_unary_op (code, real, 1), imag);
+ }
+
/* Report invalid types. */
if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_POINTER,
@@ -4038,13 +4390,14 @@ build_unary_op (code, xarg, noconvert)
if (TREE_CODE (argtype) == POINTER_TYPE)
{
enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype));
- if (TYPE_SIZE (TREE_TYPE (argtype)) == 0)
+ if (TYPE_SIZE (complete_type (TREE_TYPE (argtype))) == 0)
cp_error ("cannot %s a pointer to incomplete type `%T'",
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? "increment" : "decrement"), TREE_TYPE (argtype));
- else if (tmp == FUNCTION_TYPE || tmp == METHOD_TYPE
- || tmp == VOID_TYPE || tmp == OFFSET_TYPE)
+ else if ((pedantic || warn_pointer_arith)
+ && (tmp == FUNCTION_TYPE || tmp == METHOD_TYPE
+ || tmp == VOID_TYPE || tmp == OFFSET_TYPE))
cp_pedwarn ("ANSI C++ forbids %sing a pointer of type `%T'",
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
@@ -4054,7 +4407,7 @@ build_unary_op (code, xarg, noconvert)
else
inc = integer_one_node;
- inc = convert (argtype, inc);
+ inc = cp_convert (argtype, inc);
/* Handle incrementing a cast-expression. */
@@ -4068,7 +4421,7 @@ build_unary_op (code, xarg, noconvert)
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
{
- tree incremented, modify, value;
+ tree incremented, modify, value, compound;
if (! lvalue_p (arg) && pedantic)
pedwarn ("cast to non-reference type used as lvalue");
arg = stabilize_reference (arg);
@@ -4081,9 +4434,17 @@ build_unary_op (code, xarg, noconvert)
? PLUS_EXPR : MINUS_EXPR),
argtype, value, inc);
TREE_SIDE_EFFECTS (incremented) = 1;
+
modify = build_modify_expr (arg, NOP_EXPR, incremented);
- return build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+ compound = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+
+ /* Eliminate warning about unused result of + or -. */
+ TREE_NO_UNUSED_WARNING (compound) = 1;
+ return compound;
}
+
+ default:
+ break;
}
/* Complain about anything else that is not a true lvalue. */
@@ -4124,7 +4485,7 @@ build_unary_op (code, xarg, noconvert)
val = build (code, TREE_TYPE (arg), arg, inc);
TREE_SIDE_EFFECTS (val) = 1;
- return convert (result_type, val);
+ return cp_convert (result_type, val);
}
case ADDR_EXPR:
@@ -4134,38 +4495,30 @@ build_unary_op (code, xarg, noconvert)
argtype = TREE_TYPE (arg);
if (TREE_CODE (argtype) == REFERENCE_TYPE)
{
- arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
- TREE_REFERENCE_EXPR (arg) = 1;
+ arg = build1
+ (CONVERT_EXPR,
+ build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
+ TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
return arg;
}
- else if (pedantic
- && TREE_CODE (arg) == FUNCTION_DECL
- && DECL_NAME (arg)
- && DECL_CONTEXT (arg) == NULL_TREE
- && IDENTIFIER_LENGTH (DECL_NAME (arg)) == 4
- && IDENTIFIER_POINTER (DECL_NAME (arg))[0] == 'm'
- && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (arg)), "main"))
+ else if (pedantic && DECL_MAIN_P (arg))
/* ARM $3.4 */
pedwarn ("taking address of function `main'");
/* Let &* cancel out to simplify resulting code. */
if (TREE_CODE (arg) == INDIRECT_REF)
{
- /* We don't need to have `current_class_decl' wrapped in a
+ /* We don't need to have `current_class_ptr' wrapped in a
NON_LVALUE_EXPR node. */
- if (arg == C_C_D)
- return current_class_decl;
+ if (arg == current_class_ref)
+ return current_class_ptr;
- /* Keep `default_conversion' from converting if
- ARG is of REFERENCE_TYPE. */
arg = TREE_OPERAND (arg, 0);
if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
{
- if (TREE_CODE (arg) == VAR_DECL && DECL_INITIAL (arg)
- && !TREE_SIDE_EFFECTS (DECL_INITIAL (arg)))
- arg = DECL_INITIAL (arg);
- arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
- TREE_REFERENCE_EXPR (arg) = 1;
+ arg = build1
+ (CONVERT_EXPR,
+ build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
}
else if (lvalue_p (arg))
@@ -4196,20 +4549,46 @@ build_unary_op (code, xarg, noconvert)
return build1 (ADDR_EXPR, unknown_type_node, arg);
}
- if (TREE_CODE (arg) == TREE_LIST)
+ if (TREE_CODE (arg) == OVERLOAD
+ || (TREE_CODE (arg) == OFFSET_REF
+ && TREE_CODE (TREE_OPERAND (arg, 1)) == TEMPLATE_ID_EXPR))
+ return build1 (ADDR_EXPR, unknown_type_node, arg);
+ else if (TREE_CODE (arg) == TREE_LIST)
{
- if (TREE_CODE (TREE_VALUE (arg)) == FUNCTION_DECL
- && DECL_CHAIN (TREE_VALUE (arg)) == NULL_TREE)
+ if (TREE_CODE (TREE_VALUE (arg)) == FUNCTION_DECL)
/* Unique overloaded non-member function. */
return build_unary_op (ADDR_EXPR, TREE_VALUE (arg), 0);
if (TREE_CHAIN (arg) == NULL_TREE
&& TREE_CODE (TREE_VALUE (arg)) == TREE_LIST
- && DECL_CHAIN (TREE_VALUE (TREE_VALUE (arg))) == NULL_TREE)
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (arg))) != OVERLOAD)
/* Unique overloaded member function. */
return build_unary_op (ADDR_EXPR, TREE_VALUE (TREE_VALUE (arg)),
0);
return build1 (ADDR_EXPR, unknown_type_node, arg);
}
+ else if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
+ {
+ tree targs;
+ tree fn;
+
+ /* We don't require a match here; it's possible that the
+ context (like a cast to a particular type) will resolve
+ the particular choice of template. */
+ fn = determine_specialization (arg,
+ NULL_TREE,
+ &targs,
+ 0,
+ 0);
+
+ if (fn)
+ {
+ fn = instantiate_template (fn, targs);
+ mark_addressable (fn);
+ return build_unary_op (ADDR_EXPR, fn, 0);
+ }
+
+ return build1 (ADDR_EXPR, unknown_type_node, arg);
+ }
/* Handle complex lvalues (when permitted)
by reduction to simpler cases. */
@@ -4228,11 +4607,16 @@ build_unary_op (code, xarg, noconvert)
case FIX_CEIL_EXPR:
if (! lvalue_p (arg) && pedantic)
pedwarn ("taking the address of a cast to non-reference type");
+ break;
+
+ default:
+ break;
}
/* Allow the address of a constructor if all the elements
are constant. */
- if (TREE_CODE (arg) == CONSTRUCTOR && TREE_CONSTANT (arg))
+ if (TREE_CODE (arg) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (arg)
+ && TREE_CONSTANT (arg))
;
/* Anything not already handled and not a true memory reference
is an error. */
@@ -4262,8 +4646,9 @@ build_unary_op (code, xarg, noconvert)
tree addr;
if (TREE_CODE (arg) == COMPONENT_REF)
- addr = build_component_addr (arg, argtype,
- "attempt to take address of bit-field structure member `%s'");
+ addr = build_component_addr
+ (arg, argtype,
+ "attempt to take address of bit-field structure member `%s'");
else
addr = build1 (code, argtype, arg);
@@ -4271,8 +4656,19 @@ build_unary_op (code, xarg, noconvert)
function counts as a constant */
if (staticp (arg))
TREE_CONSTANT (addr) = 1;
+
+ if (TREE_CODE (argtype) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
+ {
+ build_ptrmemfunc_type (argtype);
+ addr = build_ptrmemfunc (argtype, addr, 0);
+ }
+
return addr;
}
+
+ default:
+ break;
}
if (!errstring)
@@ -4286,6 +4682,7 @@ build_unary_op (code, xarg, noconvert)
return error_mark_node;
}
+#if 0
/* If CONVERSIONS is a conversion expression or a nested sequence of such,
convert ARG with the same conversions in the same order
and return the result. */
@@ -4304,14 +4701,15 @@ convert_sequence (conversions, arg)
case FIX_FLOOR_EXPR:
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
- return convert (TREE_TYPE (conversions),
- convert_sequence (TREE_OPERAND (conversions, 0),
- arg));
+ return cp_convert (TREE_TYPE (conversions),
+ convert_sequence (TREE_OPERAND (conversions, 0),
+ arg));
default:
return arg;
}
}
+#endif
/* Apply unary lvalue-demanding operator CODE to the expression ARG
for certain kinds of expressions which are not really lvalues
@@ -4333,7 +4731,8 @@ unary_complex_lvalue (code, arg)
}
/* Handle (a ? b : c) used as an "lvalue". */
- if (TREE_CODE (arg) == COND_EXPR)
+ if (TREE_CODE (arg) == COND_EXPR
+ || TREE_CODE (arg) == MIN_EXPR || TREE_CODE (arg) == MAX_EXPR)
return rationalize_conditional_expr (code, arg);
if (TREE_CODE (arg) == MODIFY_EXPR
@@ -4351,15 +4750,9 @@ unary_complex_lvalue (code, arg)
|| TREE_CODE (arg) == INIT_EXPR)
{
tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
- return build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
- }
-
- if (TREE_CODE (arg) == WITH_CLEANUP_EXPR)
- {
- tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
- real_result = build (WITH_CLEANUP_EXPR, TREE_TYPE (real_result),
- real_result, 0, TREE_OPERAND (arg, 2));
- return real_result;
+ arg = build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
+ TREE_NO_UNUSED_WARNING (arg) = 1;
+ return arg;
}
if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
@@ -4370,7 +4763,6 @@ unary_complex_lvalue (code, arg)
is really the representation of a pointer to it.
Here give the representation its true type. */
tree t;
- tree offset;
my_friendly_assert (TREE_CODE (arg) != SCOPE_REF, 313);
@@ -4379,15 +4771,24 @@ unary_complex_lvalue (code, arg)
t = TREE_OPERAND (arg, 1);
- if (TREE_CODE (t) == FUNCTION_DECL) /* Check all this code for right semantics. */
- return build_unary_op (ADDR_EXPR, t, 0);
+ /* Check all this code for right semantics. */
+ if (TREE_CODE (t) == FUNCTION_DECL)
+ {
+ if (DECL_DESTRUCTOR_P (t))
+ cp_error ("taking address of destructor");
+ return build_unary_op (ADDR_EXPR, t, 0);
+ }
if (TREE_CODE (t) == VAR_DECL)
return build_unary_op (ADDR_EXPR, t, 0);
else
{
+ tree type;
+ tree offset;
+
if (TREE_OPERAND (arg, 0)
&& (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR
- || TREE_OPERAND (TREE_OPERAND (arg, 0), 0) != error_mark_node))
+ || (TREE_OPERAND (TREE_OPERAND (arg, 0), 0)
+ != error_mark_node)))
if (TREE_CODE (t) != FIELD_DECL)
{
/* Don't know if this should return address to just
@@ -4396,38 +4797,25 @@ unary_complex_lvalue (code, arg)
return error_mark_node;
}
- offset = get_delta_difference (DECL_FIELD_CONTEXT (t),
- TREE_TYPE (TREE_OPERAND (arg, 0)),
- 0);
- offset = size_binop (PLUS_EXPR, offset,
- size_binop (EASY_DIV_EXPR,
- DECL_FIELD_BITPOS (t),
- size_int (BITS_PER_UNIT)));
- return convert (build_pointer_type (TREE_TYPE (arg)), offset);
- }
- }
+ /* Add in the offset to the field. */
+ offset = convert (sizetype,
+ size_binop (EASY_DIV_EXPR,
+ DECL_FIELD_BITPOS (t),
+ size_int (BITS_PER_UNIT)));
- if (TREE_CODE (arg) == OFFSET_REF)
- {
- tree left = TREE_OPERAND (arg, 0), left_addr;
- tree right_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 1), 0);
+ /* We offset all pointer to data members by 1 so that we can
+ distinguish between a null pointer to data member and the first
+ data member of a structure. */
+ offset = size_binop (PLUS_EXPR, offset, size_int (1));
- if (left == 0)
- if (current_class_decl)
- left_addr = current_class_decl;
- else
- {
- error ("no `this' for pointer to member");
- return error_mark_node;
- }
- else
- left_addr = build_unary_op (ADDR_EXPR, left, 0);
+ type = build_offset_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
+ type = build_pointer_type (type);
- return build (PLUS_EXPR, build_pointer_type (TREE_TYPE (arg)),
- build1 (NOP_EXPR, integer_type_node, left_addr),
- build1 (NOP_EXPR, integer_type_node, right_addr));
+ return cp_convert (type, offset);
+ }
}
+
/* We permit compiler to make function calls returning
objects of aggregate type look like lvalues. */
{
@@ -4441,24 +4829,13 @@ unary_complex_lvalue (code, arg)
if (TREE_CODE (arg) == SAVE_EXPR)
targ = arg;
else
- targ = build_cplus_new (TREE_TYPE (arg), arg, 1);
+ targ = build_cplus_new (TREE_TYPE (arg), arg);
return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), targ);
}
if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == INDIRECT_REF)
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
- we do, here's how to handle it. */
- if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == WITH_CLEANUP_EXPR)
- {
-#if 0
- /* Not really a bug, but something to turn on when testing. */
- compiler_error ("WITH_CLEANUP_EXPR wrapped in SAVE_EXPR");
-#endif
- return unary_complex_lvalue (ADDR_EXPR, targ);
- }
}
/* Don't let anything else be handled specially. */
@@ -4469,7 +4846,7 @@ unary_complex_lvalue (code, arg)
address of it; it should not be allocated in a register.
Value is 1 if successful.
- C++: we do not allow `current_class_decl' to be addressable. */
+ C++: we do not allow `current_class_ptr' to be addressable. */
int
mark_addressable (exp)
@@ -4486,22 +4863,24 @@ mark_addressable (exp)
case ADDR_EXPR:
case COMPONENT_REF:
case ARRAY_REF:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
x = TREE_OPERAND (x, 0);
break;
case PARM_DECL:
- if (x == current_class_decl)
+ if (x == current_class_ptr)
{
- error ("address of `this' not available");
+ if (! flag_this_is_variable)
+ error ("address of `this' not available");
TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
put_var_into_stack (x);
return 1;
}
case VAR_DECL:
- if (TREE_STATIC (x)
- && TREE_READONLY (x)
+ if (TREE_STATIC (x) && TREE_READONLY (x)
&& DECL_RTL (x) != 0
- && ! decl_in_memory_p (x))
+ && ! DECL_IN_MEMORY_P (x))
{
/* We thought this would make a good constant variable,
but we were wrong. */
@@ -4510,7 +4889,8 @@ mark_addressable (exp)
TREE_ASM_WRITTEN (x) = 0;
DECL_RTL (x) = 0;
- rest_of_decl_compilation (x, 0, IDENTIFIER_LOCAL_VALUE (x) == 0, 0);
+ rest_of_decl_compilation (x, 0, IDENTIFIER_LOCAL_VALUE (x) == 0,
+ 0);
TREE_ADDRESSABLE (x) = 1;
pop_obstacks ();
@@ -4526,31 +4906,36 @@ mark_addressable (exp)
case CONST_DECL:
case RESULT_DECL:
- /* For C++, we don't warn about taking the address of a register
- variable for CONST_DECLs; ARM p97 explicitly says it's okay. */
+ if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
+ && !DECL_ARTIFICIAL (x) && extra_warnings)
+ cp_warning ("address requested for `%D', which is declared `register'",
+ x);
put_var_into_stack (x);
TREE_ADDRESSABLE (x) = 1;
return 1;
case FUNCTION_DECL:
- /* We have to test both conditions here. The first may
- be non-zero in the case of processing a default function.
- The second may be non-zero in the case of a template function. */
- x = DECL_MAIN_VARIANT (x);
- if ((DECL_THIS_INLINE (x) || DECL_PENDING_INLINE_INFO (x))
- && (DECL_CONTEXT (x) == NULL_TREE
- || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (x))) != 't'
- || ! CLASSTYPE_INTERFACE_ONLY (DECL_CONTEXT (x))))
+ if (DECL_LANG_SPECIFIC (x) != 0)
{
- mark_inline_for_output (x);
- if (x == current_function_decl)
- DECL_EXTERNAL (x) = 0;
+ x = DECL_MAIN_VARIANT (x);
+ /* We have to test both conditions here. The first may be
+ non-zero in the case of processing a default function. The
+ second may be non-zero in the case of a template function. */
+ if (DECL_TEMPLATE_INFO (x) && !DECL_TEMPLATE_SPECIALIZATION (x))
+ mark_used (x);
}
TREE_ADDRESSABLE (x) = 1;
TREE_USED (x) = 1;
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
- if (asm_out_file)
- assemble_external (x);
+ return 1;
+
+ case CONSTRUCTOR:
+ TREE_ADDRESSABLE (x) = 1;
+ return 1;
+
+ case TARGET_EXPR:
+ TREE_ADDRESSABLE (x) = 1;
+ mark_addressable (TREE_OPERAND (x, 0));
return 1;
default:
@@ -4564,15 +4949,10 @@ tree
build_x_conditional_expr (ifexp, op1, op2)
tree ifexp, op1, op2;
{
- tree rval = NULL_TREE;
+ if (processing_template_decl)
+ return build_min_nt (COND_EXPR, ifexp, op1, op2);
- /* See comments in `build_x_binary_op'. */
- if (op1 != 0)
- rval = build_opfncall (COND_EXPR, LOOKUP_SPECULATIVELY, ifexp, op1, op2);
- if (rval)
- return build_opfncall (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
-
- return build_conditional_expr (ifexp, op1, op2);
+ return build_new_op (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
}
tree
@@ -4584,7 +4964,6 @@ build_conditional_expr (ifexp, op1, op2)
register enum tree_code code1;
register enum tree_code code2;
register tree result_type = NULL_TREE;
- tree orig_op1 = op1, orig_op2 = op2;
/* If second operand is omitted, it is the same as the first one;
make sure it is calculated only once. */
@@ -4595,7 +4974,7 @@ build_conditional_expr (ifexp, op1, op2)
ifexp = op1 = save_expr (ifexp);
}
- ifexp = convert (boolean_type_node, ifexp);
+ ifexp = cp_convert (boolean_type_node, ifexp);
if (TREE_CODE (ifexp) == ERROR_MARK)
return error_mark_node;
@@ -4626,17 +5005,12 @@ build_conditional_expr (ifexp, op1, op2)
code2 = TREE_CODE (type2);
}
-#if 1 /* Produces wrong result if within sizeof. Sorry. */
/* Don't promote the operands separately if they promote
the same way. Return the unpromoted type and let the combined
value get promoted if necessary. */
if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)
&& code2 != ARRAY_TYPE
-#if 0
- /* For C++, let the enumeral type come through. */
- && code2 != ENUMERAL_TYPE
-#endif
&& code2 != FUNCTION_TYPE
&& code2 != METHOD_TYPE)
{
@@ -4665,9 +5039,17 @@ build_conditional_expr (ifexp, op1, op2)
result = fold (build (COND_EXPR, type1, ifexp, op1, op2));
if (TREE_TYPE (result) != type1)
result = build1 (NOP_EXPR, type1, result);
+ /* Expand both sides into the same slot,
+ hopefully the target of the ?: expression. */
+ if (TREE_CODE (op1) == TARGET_EXPR && TREE_CODE (op2) == TARGET_EXPR)
+ {
+ tree slot = build (VAR_DECL, TREE_TYPE (result));
+ layout_decl (slot, 0);
+ result = build (TARGET_EXPR, TREE_TYPE (result),
+ slot, result, NULL_TREE, NULL_TREE);
+ }
return result;
}
-#endif
/* They don't match; promote them both and then try to reconcile them.
But don't permit mismatching enum types. */
@@ -4675,7 +5057,8 @@ build_conditional_expr (ifexp, op1, op2)
{
if (code2 == ENUMERAL_TYPE)
{
- cp_error ("enumeral mismatch in conditional expression: `%T' vs `%T'", type1, type2);
+ cp_error ("enumeral mismatch in conditional expression: `%T' vs `%T'",
+ type1, type2);
return error_mark_node;
}
else if (extra_warnings && ! IS_AGGR_TYPE_CODE (code2)
@@ -4739,16 +5122,14 @@ build_conditional_expr (ifexp, op1, op2)
pedwarn ("ANSI C++ forbids conditional expr with only one void side");
result_type = void_type_node;
}
+ else if (code1 == POINTER_TYPE && null_ptr_cst_p (op2))
+ result_type = qualify_type (type1, type2);
+ else if (code2 == POINTER_TYPE && null_ptr_cst_p (op1))
+ result_type = qualify_type (type2, type1);
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
{
if (comp_target_types (type1, type2, 1))
result_type = common_type (type1, type2);
- else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node
- && TREE_CODE (orig_op1) != NOP_EXPR)
- result_type = qualify_type (type2, type1);
- else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node
- && TREE_CODE (orig_op2) != NOP_EXPR)
- result_type = qualify_type (type1, type2);
else if (TYPE_MAIN_VARIANT (TREE_TYPE (type1)) == void_type_node)
{
if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
@@ -4766,7 +5147,8 @@ build_conditional_expr (ifexp, op1, op2)
result_type = type2;
else if (IS_AGGR_TYPE (TREE_TYPE (type1))
&& IS_AGGR_TYPE (TREE_TYPE (type2))
- && (result_type = common_base_type (TREE_TYPE (type1), TREE_TYPE (type2))))
+ && (result_type = common_base_type (TREE_TYPE (type1),
+ TREE_TYPE (type2))))
{
if (result_type == error_mark_node)
{
@@ -4793,30 +5175,12 @@ build_conditional_expr (ifexp, op1, op2)
}
else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
{
- if (!integer_zerop (op2))
- pedwarn ("pointer/integer type mismatch in conditional expression");
- else
- {
- op2 = null_pointer_node;
-#if 0 /* Sez who? */
- if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
-#endif
- }
+ pedwarn ("pointer/integer type mismatch in conditional expression");
result_type = type1;
}
else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
- if (!integer_zerop (op1))
- pedwarn ("pointer/integer type mismatch in conditional expression");
- else
- {
- op1 = null_pointer_node;
-#if 0 /* Sez who? */
- if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
-#endif
- }
+ pedwarn ("pointer/integer type mismatch in conditional expression");
result_type = type2;
}
@@ -4826,33 +5190,56 @@ build_conditional_expr (ifexp, op1, op2)
an aggregate value, try converting to a scalar type. */
if (code1 == RECORD_TYPE && code2 == RECORD_TYPE)
{
- cp_error ("aggregate mismatch in conditional expression: `%T' vs `%T'", type1, type2);
+ cp_error ("aggregate mismatch in conditional expression: `%T' vs `%T'",
+ type1, type2);
return error_mark_node;
}
+ /* Warning: this code assumes that conversion between cv-variants of
+ a type is done using NOP_EXPRs. */
if (code1 == RECORD_TYPE && TYPE_HAS_CONVERSION (type1))
{
- tree tmp = build_type_conversion (CONVERT_EXPR, type2, op1, 0);
+ /* There are other types besides pointers and records. */
+ tree tmp;
+ if (code2 == POINTER_TYPE)
+ tmp = build_pointer_type
+ (build_type_variant (TREE_TYPE (type2), 1, 1));
+ else
+ tmp = type2;
+ tmp = build_type_conversion (CONVERT_EXPR, tmp, op1, 0);
if (tmp == NULL_TREE)
{
- cp_error ("aggregate type `%T' could not convert on lhs of `:'", type1);
+ cp_error ("incompatible types `%T' and `%T' in `?:'",
+ type1, type2);
return error_mark_node;
}
if (tmp == error_mark_node)
error ("ambiguous pointer conversion");
- result_type = type2;
+ else
+ STRIP_NOPS (tmp);
+ result_type = common_type (type2, TREE_TYPE (tmp));
op1 = tmp;
}
else if (code2 == RECORD_TYPE && TYPE_HAS_CONVERSION (type2))
{
- tree tmp = build_type_conversion (CONVERT_EXPR, type1, op2, 0);
+ tree tmp;
+ if (code1 == POINTER_TYPE)
+ tmp = build_pointer_type
+ (build_type_variant (TREE_TYPE (type1), 1, 1));
+ else
+ tmp = type1;
+
+ tmp = build_type_conversion (CONVERT_EXPR, tmp, op2, 0);
if (tmp == NULL_TREE)
{
- cp_error ("aggregate type `%T' could not convert on rhs of `:'", type2);
+ cp_error ("incompatible types `%T' and `%T' in `?:'",
+ type1, type2);
return error_mark_node;
}
if (tmp == error_mark_node)
error ("ambiguous pointer conversion");
- result_type = type1;
+ else
+ STRIP_NOPS (tmp);
+ result_type = common_type (type1, TREE_TYPE (tmp));
op2 = tmp;
}
else if (flag_cond_mismatch)
@@ -4869,48 +5256,13 @@ build_conditional_expr (ifexp, op1, op2)
result_type = build_ptrmemfunc_type (result_type);
if (result_type != TREE_TYPE (op1))
- op1 = convert_and_check (result_type, op1);
+ op1 = convert_for_initialization
+ (NULL_TREE, result_type, op1, LOOKUP_NORMAL, "converting", NULL_TREE, 0);
if (result_type != TREE_TYPE (op2))
- op2 = convert_and_check (result_type, op2);
-
-#if 0
- /* XXX delete me, I've been here for years. */
- if (IS_AGGR_TYPE_CODE (code1))
- {
- result_type = TREE_TYPE (op1);
- if (TREE_CONSTANT (ifexp))
- return (integer_zerop (ifexp) ? op2 : op1);
+ op2 = convert_for_initialization
+ (NULL_TREE, result_type, op2, LOOKUP_NORMAL, "converting", NULL_TREE, 0);
- if (TYPE_MODE (result_type) == BLKmode)
- {
- register tree tempvar
- = build_decl (VAR_DECL, NULL_TREE, result_type);
- register tree xop1 = build_modify_expr (tempvar, NOP_EXPR, op1);
- register tree xop2 = build_modify_expr (tempvar, NOP_EXPR, op2);
- register tree result = fold (build (COND_EXPR, result_type,
- ifexp, xop1, xop2));
-
- layout_decl (tempvar, 0);
- /* No way to handle variable-sized objects here.
- I fear that the entire handling of BLKmode conditional exprs
- needs to be redone. */
- my_friendly_assert (TREE_CONSTANT (DECL_SIZE (tempvar)), 315);
- DECL_RTL (tempvar)
- = assign_stack_local (DECL_MODE (tempvar),
- (TREE_INT_CST_LOW (DECL_SIZE (tempvar))
- + BITS_PER_UNIT - 1)
- / BITS_PER_UNIT,
- 0);
-
- TREE_SIDE_EFFECTS (result)
- = TREE_SIDE_EFFECTS (ifexp) | TREE_SIDE_EFFECTS (op1)
- | TREE_SIDE_EFFECTS (op2);
- return build (COMPOUND_EXPR, result_type, result, tempvar);
- }
- }
-#endif /* 0 */
-
- if (TREE_CONSTANT (ifexp))
+ if (TREE_CODE (ifexp) == INTEGER_CST)
return integer_zerop (ifexp) ? op2 : op1;
return convert_from_reference
@@ -4919,6 +5271,7 @@ build_conditional_expr (ifexp, op1, op2)
/* Handle overloading of the ',' operator when needed. Otherwise,
this function just builds an expression list. */
+
tree
build_x_compound_expr (list)
tree list;
@@ -4926,13 +5279,17 @@ build_x_compound_expr (list)
tree rest = TREE_CHAIN (list);
tree result;
+ if (processing_template_decl)
+ return build_min_nt (COMPOUND_EXPR, list, NULL_TREE);
+
if (rest == NULL_TREE)
return build_compound_expr (list);
result = build_opfncall (COMPOUND_EXPR, LOOKUP_NORMAL,
TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
if (result)
- return build_x_compound_expr (tree_cons (NULL_TREE, result, TREE_CHAIN (rest)));
+ return build_x_compound_expr (expr_tree_cons (NULL_TREE, result,
+ TREE_CHAIN (rest)));
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
{
@@ -4949,8 +5306,10 @@ build_x_compound_expr (list)
warn_if_unused_value (TREE_VALUE(list));
#endif
- return build_compound_expr (tree_cons (NULL_TREE, TREE_VALUE (list),
- build_tree_list (NULL_TREE, build_x_compound_expr (rest))));
+ return build_compound_expr
+ (expr_tree_cons (NULL_TREE, TREE_VALUE (list),
+ build_expr_list (NULL_TREE,
+ build_x_compound_expr (rest))));
}
/* Given a list of expressions, return a compound expression
@@ -4990,127 +5349,264 @@ build_compound_expr (list)
break_out_cleanups (TREE_VALUE (list)), rest);
}
-#ifdef __GNUC__
-__inline
-#endif
-int
-null_ptr_cst_p (t)
- tree t;
-{
- return (TREE_CODE (t) == INTEGER_CST && integer_zerop (t));
-}
-
-tree build_static_cast (type, expr)
+tree
+build_static_cast (type, expr)
tree type, expr;
{
- return build_c_cast (type, expr, 0);
+ tree intype, binfo;
+ int ok;
+
+ if (type == error_mark_node || expr == error_mark_node)
+ return error_mark_node;
+
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
+
+ if (processing_template_decl)
+ {
+ tree t = build_min (STATIC_CAST_EXPR, copy_to_permanent (type),
+ expr);
+ return t;
+ }
+
+ /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
+ Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */
+ if (TREE_CODE (type) != REFERENCE_TYPE
+ && TREE_CODE (expr) == NOP_EXPR
+ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 0);
+
+ if (TREE_CODE (type) == VOID_TYPE)
+ return build1 (CONVERT_EXPR, type, expr);
+
+ if (type_unknown_p (expr))
+ {
+ expr = instantiate_type (type, expr, 1);
+ if (expr == error_mark_node)
+ return error_mark_node;
+ }
+
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ return (convert_from_reference
+ (convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT,
+ LOOKUP_COMPLAIN, NULL_TREE)));
+
+ if (IS_AGGR_TYPE (type))
+ return build_cplus_new
+ (type, (build_method_call
+ (NULL_TREE, ctor_identifier, build_expr_list (NULL_TREE, expr),
+ TYPE_BINFO (type), LOOKUP_NORMAL)));
+
+ expr = decay_conversion (expr);
+ intype = TREE_TYPE (expr);
+
+ /* FIXME handle casting to array type. */
+
+ ok = 0;
+ if (can_convert_arg (type, intype, expr))
+ ok = 1;
+ else if (TYPE_PTROB_P (type) && TYPE_PTROB_P (intype))
+ {
+ tree binfo;
+ if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype))
+ && (TYPE_READONLY (TREE_TYPE (type))
+ >= TYPE_READONLY (TREE_TYPE (intype)))
+ && (TYPE_VOLATILE (TREE_TYPE (type))
+ >= TYPE_VOLATILE (TREE_TYPE (intype)))
+ && (binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 0))
+ && ! TREE_VIA_VIRTUAL (binfo))
+ ok = 1;
+ }
+ else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ {
+ if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))),
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (intype))), 1)
+ && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (type)))
+ >= TYPE_READONLY (TREE_TYPE (TREE_TYPE (intype))))
+ && (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (type)))
+ >= TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (intype))))
+ && (binfo = get_binfo (TYPE_OFFSET_BASETYPE (TREE_TYPE (type)),
+ TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)), 0))
+ && ! TREE_VIA_VIRTUAL (binfo))
+ ok = 1;
+ }
+ else if (TREE_CODE (intype) != BOOLEAN_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE
+ && TREE_CODE (type) != FUNCTION_TYPE
+ && can_convert (intype, type))
+ ok = 1;
+
+ if (ok)
+ return build_c_cast (type, expr);
+
+ cp_error ("static_cast from `%T' to `%T'", intype, type);
+ return error_mark_node;
}
-tree build_reinterpret_cast (type, expr)
+tree
+build_reinterpret_cast (type, expr)
tree type, expr;
{
- tree intype = TREE_TYPE (expr);
+ tree intype;
- if (TYPE_PTRMEMFUNC_P (type))
- type = TYPE_PTRMEMFUNC_FN_TYPE (type);
- if (TYPE_PTRMEMFUNC_P (intype))
- intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
+ if (type == error_mark_node || expr == error_mark_node)
+ return error_mark_node;
+
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
- if (! POINTER_TYPE_P (type) && ! TREE_CODE (type) == INTEGER_TYPE)
+ if (processing_template_decl)
{
- cp_error ("reinterpret_cast cannot convert to type `%T'", type);
- return error_mark_node;
+ tree t = build_min (REINTERPRET_CAST_EXPR,
+ copy_to_permanent (type), expr);
+ return t;
}
- if (! POINTER_TYPE_P (intype) && ! TREE_CODE (intype) == INTEGER_TYPE)
+
+ if (TREE_CODE (type) != REFERENCE_TYPE)
{
- cp_error ("reinterpret_cast cannot convert from type `%T'", type);
- return error_mark_node;
+ expr = decay_conversion (expr);
+
+ /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
+ Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */
+ if (TREE_CODE (expr) == NOP_EXPR
+ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 0);
}
- if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (intype) != POINTER_TYPE)
+
+ if (type_unknown_p (expr))
{
- cp_error ("reinterpret_cast cannot convert non-pointer type `%T' to `%T'",
- intype, type);
- return error_mark_node;
+ expr = instantiate_type (type, expr, 1);
+ if (expr == error_mark_node)
+ return error_mark_node;
}
- if (TREE_CODE (intype) == INTEGER_TYPE && TREE_CODE (type) != POINTER_TYPE)
+
+ intype = TREE_TYPE (expr);
+
+ if (TREE_CODE (type) == REFERENCE_TYPE)
{
- cp_error ("reinterpret_cast cannot convert `%T' to non-pointer type `%T'",
- intype, type);
- return error_mark_node;
+ if (! real_lvalue_p (expr))
+ {
+ cp_error ("reinterpret_cast from `%T' rvalue to `%T'", intype, type);
+ return error_mark_node;
+ }
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+ if (expr != error_mark_node)
+ expr = build_reinterpret_cast
+ (build_pointer_type (TREE_TYPE (type)), expr);
+ if (expr != error_mark_node)
+ expr = build_indirect_ref (expr, 0);
+ return expr;
}
+ else if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
+ return build_static_cast (type, expr);
- if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) == POINTER_TYPE)
- expr = convert (ptr_type_node, expr);
+ if (TYPE_PTR_P (type) && (TREE_CODE (intype) == INTEGER_TYPE
+ || TREE_CODE (intype) == ENUMERAL_TYPE))
+ /* OK */;
+ else if (TREE_CODE (type) == INTEGER_TYPE && TYPE_PTR_P (intype))
+ {
+ if (TYPE_PRECISION (type) < TYPE_PRECISION (intype))
+ cp_pedwarn ("reinterpret_cast from `%T' to `%T' loses precision",
+ intype, type);
+ }
+ else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
+ || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
+ {
+ if (TREE_READONLY_DECL_P (expr))
+ expr = decl_constant_value (expr);
+ return fold (build1 (NOP_EXPR, type, expr));
+ }
+ else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
+ {
+ if (! comp_ptr_ttypes_reinterpret (TREE_TYPE (type), TREE_TYPE (intype)))
+ cp_pedwarn ("reinterpret_cast from `%T' to `%T' casts away const (or volatile)",
+ intype, type);
- return build_c_cast (type, expr, 0);
+ if (TREE_READONLY_DECL_P (expr))
+ expr = decl_constant_value (expr);
+ return fold (build1 (NOP_EXPR, type, expr));
+ }
+ else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
+ || (TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype)))
+ {
+ pedwarn ("ANSI C++ forbids casting between pointers to functions and objects");
+ if (TREE_READONLY_DECL_P (expr))
+ expr = decl_constant_value (expr);
+ return fold (build1 (NOP_EXPR, type, expr));
+ }
+ else
+ {
+ cp_error ("reinterpret_cast from `%T' to `%T'", intype, type);
+ return error_mark_node;
+ }
+
+ return cp_convert (type, expr);
}
-tree build_const_cast (type, expr)
+tree
+build_const_cast (type, expr)
tree type, expr;
{
- tree intype = TREE_TYPE (expr);
- tree t1, t2;
+ tree intype;
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))
- intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
- if (! POINTER_TYPE_P (type))
- {
- cp_error ("const_cast cannot convert to non-pointer type `%T'", type);
- return error_mark_node;
- }
- if (TREE_CODE (type) == REFERENCE_TYPE && ! real_lvalue_p (expr))
+ if (processing_template_decl)
{
- cp_error ("const_cast cannot convert rvalue to type `%T'", type);
- return error_mark_node;
+ tree t = build_min (CONST_CAST_EXPR, copy_to_permanent (type),
+ expr);
+ return t;
}
- if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) != POINTER_TYPE)
+
+ if (TREE_CODE (type) != REFERENCE_TYPE)
{
- cp_error ("const_cast cannot convert non-pointer type `%T' to type `%T'",
- intype, type);
- return error_mark_node;
+ expr = decay_conversion (expr);
+
+ /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
+ Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */
+ if (TREE_CODE (expr) == NOP_EXPR
+ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 0);
}
- if (TREE_CODE (type) == REFERENCE_TYPE)
+ if (type_unknown_p (expr))
{
- t1 = TREE_TYPE (type);
- t2 = intype;
+ expr = instantiate_type (type, expr, 1);
+ if (expr == error_mark_node)
+ return error_mark_node;
}
- else
- {
- t1 = TREE_TYPE (type);
- t2 = TREE_TYPE (intype);
- for (; TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE;
- t1 = TREE_TYPE (t1), t2 = TREE_TYPE (t2))
- ;
- }
+ intype = TREE_TYPE (expr);
- if (TREE_CODE (t1) == OFFSET_TYPE && TREE_CODE (t2) == OFFSET_TYPE)
+ if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
+ return build_static_cast (type, expr);
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
{
- if (TYPE_OFFSET_BASETYPE (t1) != TYPE_OFFSET_BASETYPE (t2))
+ if (! real_lvalue_p (expr))
{
- cp_error ("const_cast cannot convert between pointers to members of different types `%T' and `%T'",
- TYPE_OFFSET_BASETYPE (t2), TYPE_OFFSET_BASETYPE (t1));
+ cp_error ("const_cast from `%T' rvalue to `%T'", intype, type);
return error_mark_node;
}
- t1 = TREE_TYPE (t1);
- t2 = TREE_TYPE (t2);
- }
- if (TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2))
- {
- cp_error ("const_cast cannot convert unrelated type `%T' to `%T'",
- t2, t1);
- return error_mark_node;
+ if (comp_ptr_ttypes_const (TREE_TYPE (type), intype))
+ {
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+ expr = build1 (NOP_EXPR, type, expr);
+ return convert_from_reference (expr);
+ }
}
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (intype) == POINTER_TYPE
+ && comp_ptr_ttypes_const (TREE_TYPE (type), TREE_TYPE (intype)))
+ return cp_convert (type, expr);
- return build_c_cast (type, expr, 0);
+ cp_error ("const_cast from `%T' to `%T'", intype, type);
+ return error_mark_node;
}
/* Build an expression representing a cast to type TYPE of expression EXPR.
@@ -5119,10 +5615,8 @@ tree build_const_cast (type, expr)
when doing the cast. */
tree
-build_c_cast (type, expr, allow_nonconverting)
- register tree type;
- tree expr;
- int allow_nonconverting;
+build_c_cast (type, expr)
+ tree type, expr;
{
register tree value = expr;
@@ -5172,11 +5666,12 @@ build_c_cast (type, expr, allow_nonconverting)
return error_mark_node;
}
- /* If there's only one function in the overloaded space,
- just take it. */
- if (TREE_CODE (value) == TREE_LIST
- && TREE_CHAIN (value) == NULL_TREE)
- value = TREE_VALUE (value);
+ if (processing_template_decl)
+ {
+ tree t = build_min (CAST_EXPR, type,
+ min_tree_cons (NULL_TREE, value, NULL_TREE));
+ return t;
+ }
if (TREE_CODE (type) == VOID_TYPE)
value = build1 (CONVERT_EXPR, type, value);
@@ -5191,16 +5686,39 @@ build_c_cast (type, expr, allow_nonconverting)
else
{
tree otype;
- int flag;
/* Convert functions and arrays to pointers and
convert references to their expanded types,
- but don't convert any other types. */
- if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
- || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
- value = default_conversion (value);
+ but don't convert any other types. If, however, we are
+ casting to a class type, there's no reason to do this: the
+ cast will only succeed if there is a converting constructor,
+ and the default conversions will be done at that point. In
+ fact, doing the default conversion here is actually harmful
+ in cases like this:
+
+ typedef int A[2];
+ struct S { S(const A&); };
+
+ since we don't want the array-to-pointer conversion done. */
+ if (!IS_AGGR_TYPE (type))
+ {
+ if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
+ || (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
+ /* Don't do the default conversion if we want a
+ pointer to a function. */
+ && ! (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE))
+ || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
+ value = default_conversion (value);
+ }
+ else if (TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
+ /* However, even for class types, we still need to strip away
+ the reference type, since the call to convert_force below
+ does not expect the input expression to be of reference
+ type. */
+ value = convert_from_reference (value);
+
otype = TREE_TYPE (value);
/* Optionally warn about potentially worrisome casts. */
@@ -5229,6 +5747,8 @@ build_c_cast (type, expr, allow_nonconverting)
warning ("cast increases required alignment of target type");
#if 0
+ /* We should see about re-enabling these, they seem useful to
+ me. */
if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE
&& TYPE_PRECISION (type) != TYPE_PRECISION (otype))
@@ -5243,11 +5763,9 @@ build_c_cast (type, expr, allow_nonconverting)
warning ("cast to pointer from integer of different size");
#endif
- flag = allow_nonconverting ? CONV_NONCONVERTING : 0;
-
if (TREE_CODE (type) == REFERENCE_TYPE)
value = (convert_from_reference
- (convert_to_reference (type, value, CONV_OLD_CONVERT|flag,
+ (convert_to_reference (type, value, CONV_C_CAST,
LOOKUP_COMPLAIN, NULL_TREE)));
else
{
@@ -5257,7 +5775,7 @@ build_c_cast (type, expr, allow_nonconverting)
value = decl_constant_value (value);
ovalue = value;
- value = convert_force (type, value, flag);
+ value = convert_force (type, value, CONV_C_CAST);
/* Ignore any integer overflow caused by the cast. */
if (TREE_CODE (value) == INTEGER_CST)
@@ -5269,324 +5787,22 @@ build_c_cast (type, expr, allow_nonconverting)
}
/* Always produce some operator for an explicit cast,
- so we can tell (for -pedantic) that the cast is no lvalue.
- Also, pedantically, don't let (void *) (FOO *) 0 be a null
- pointer constant. */
- if (TREE_CODE (type) != REFERENCE_TYPE
- && (value == expr
- || (pedantic
- && TREE_CODE (value) == INTEGER_CST
- && TREE_CODE (expr) == INTEGER_CST
- && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)))
+ so we can tell (for -pedantic) that the cast is no lvalue. */
+ if (TREE_CODE (type) != REFERENCE_TYPE && value == expr
+ && real_lvalue_p (value))
value = non_lvalue (value);
return value;
}
-#if 0
-/* Build an assignment expression of lvalue LHS from value RHS.
-
- In C++, if the left hand side of the assignment is a REFERENCE_TYPE,
- that reference becomes deferenced down to it base type. */
-
-/* Return a reference to the BASE_INDEX part of EXPR. TYPE is
- the type to which BASE_INDEX applies. */
-static tree
-get_base_ref (type, base_index, expr)
- tree type;
- int base_index;
- tree expr;
-{
- tree binfos = TYPE_BINFO_BASETYPES (type);
- tree base_binfo = TREE_VEC_ELT (binfos, base_index);
- tree ref;
-
- if (TREE_CODE (expr) == ARRAY_REF
- || ! BINFO_OFFSET_ZEROP (base_binfo)
- || TREE_VIA_VIRTUAL (base_binfo)
- || TYPE_MODE (type) != TYPE_MODE (BINFO_TYPE (base_binfo)))
- {
- tree addr = build_unary_op (ADDR_EXPR, expr, 0);
- ref = build_indirect_ref (convert_pointer_to (base_binfo, addr),
- NULL_PTR);
- }
- else
- {
- ref = copy_node (expr);
- TREE_TYPE (ref) = BINFO_TYPE (base_binfo);
- }
- return ref;
-}
-
/* Build an assignment expression of lvalue LHS from value RHS.
MODIFYCODE is the code for a binary operator that we use
to combine the old value of LHS with RHS to get the new value.
Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
- C++: If MODIFYCODE is INIT_EXPR, then leave references unbashed.
-
- `build_modify_expr_1' implements recursive part of memberwise
- assignment operation. */
-static tree
-build_modify_expr_1 (lhs, modifycode, rhs, basetype_path)
- tree lhs, rhs;
- enum tree_code modifycode;
- tree basetype_path;
-{
- register tree result;
- tree newrhs = rhs;
- tree lhstype = TREE_TYPE (lhs);
- tree olhstype = lhstype;
-
- /* Avoid duplicate error messages from operands that had errors. */
- if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
- return error_mark_node;
-
- /* If a binary op has been requested, combine the old LHS value with the RHS
- producing the value we should actually store into the LHS. */
-
- if (modifycode == INIT_EXPR)
- ;
- else if (modifycode == NOP_EXPR)
- {
- /* must deal with overloading of `operator=' here. */
- if (TREE_CODE (lhstype) == REFERENCE_TYPE)
- lhstype = TREE_TYPE (lhstype);
- else
- lhstype = olhstype;
- }
- else
- {
- lhs = stabilize_reference (lhs);
- newrhs = build_binary_op (modifycode, lhs, rhs, 1);
- modifycode = NOP_EXPR;
- }
-
- /* If storing into a structure or union member,
- it has probably been given type `int'.
- Compute the type that would go with
- the actual amount of storage the member occupies. */
-
- if (TREE_CODE (lhs) == COMPONENT_REF
- && (TREE_CODE (lhstype) == INTEGER_TYPE
- || TREE_CODE (lhstype) == REAL_TYPE
- || TREE_CODE (lhstype) == ENUMERAL_TYPE))
- lhstype = TREE_TYPE (get_unwidened (lhs, 0));
-
- /* C++: The semantics of C++ differ from those of C when an
- assignment of an aggregate is desired. Assignment in C++ is
- now defined as memberwise assignment of non-static members
- and base class objects. This rule applies recursively
- until a member of a built-in type is found.
-
- Also, we cannot do a bit-wise copy of aggregates which
- contain virtual function table pointers. Those
- pointer values must be preserved through the copy.
- However, this is handled in expand_expr, and not here.
- This is because much better code can be generated at
- that stage than this one. */
- if (TREE_CODE (lhstype) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (lhstype)
- && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
- {
- register tree elt;
- int i;
-
- /* Perform operation on object. */
- if (modifycode == INIT_EXPR && TYPE_HAS_INIT_REF (lhstype))
- {
- result = build_method_call (lhs, constructor_name_full (lhstype),
- build_tree_list (NULL_TREE, rhs),
- basetype_path, LOOKUP_NORMAL);
- return build_indirect_ref (result, NULL_PTR);
- }
- else if (modifycode == NOP_EXPR)
- {
- /* `operator=' is not an inheritable operator; see 13.4.3. */
- if (TYPE_LANG_SPECIFIC (lhstype) && TYPE_HAS_ASSIGNMENT (lhstype))
- {
- result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
- if (result == NULL_TREE)
- return error_mark_node;
- return result;
- }
- }
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (lhstype)
- || (modifycode == NOP_EXPR && TYPE_GETS_ASSIGNMENT (lhstype))
- || (modifycode == INIT_EXPR && TYPE_GETS_INIT_REF (lhstype)))
- {
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (lhstype));
- result = NULL_TREE;
-
- if (binfos != NULL_TREE)
- /* Perform operation on each member, depth-first, left-right. */
- for (i = 0; i <= TREE_VEC_LENGTH (binfos)-1; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree base_lhs, base_rhs;
- tree new_result;
-
- /* Assignments from virtual baseclasses handled elsewhere. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- base_lhs = get_base_ref (lhstype, i, lhs);
- base_rhs = get_base_ref (lhstype, i, newrhs);
-
- BINFO_INHERITANCE_CHAIN (base_binfo) = basetype_path;
- new_result
- = build_modify_expr_1 (base_lhs, modifycode, base_rhs,
- base_binfo);
-
- /* We either get back a compound stmt, or a simple one. */
- if (new_result && TREE_CODE (new_result) == TREE_LIST)
- new_result = build_compound_expr (new_result);
- result = tree_cons (NULL_TREE, new_result, result);
- }
-
- for (elt = TYPE_FIELDS (lhstype); elt; elt = TREE_CHAIN (elt))
- {
- tree vbases = NULL_TREE;
- tree elt_lhs, elt_rhs;
-
- if (TREE_CODE (elt) != FIELD_DECL)
- continue;
- if (DECL_NAME (elt)
- && (VFIELD_NAME_P (DECL_NAME (elt))
- || VBASE_NAME_P (DECL_NAME (elt))))
- continue;
-
- if (TREE_READONLY (elt)
- || TREE_CODE (TREE_TYPE (elt)) == REFERENCE_TYPE)
- {
- cp_error ("cannot generate default `%T::operator ='",
- lhstype);
- if (TREE_CODE (TREE_TYPE (elt)) == REFERENCE_TYPE)
- cp_error_at ("because member `%#D' is a reference", elt);
- else
- cp_error_at ("because member `%#D' is const", elt);
-
- return error_mark_node;
- }
-
- if (IS_AGGR_TYPE (TREE_TYPE (elt))
- && TYPE_LANG_SPECIFIC (TREE_TYPE (elt)))
- vbases = CLASSTYPE_VBASECLASSES (TREE_TYPE (elt));
-
- elt_lhs = build (COMPONENT_REF, TREE_TYPE (elt), lhs, elt);
- elt_rhs = build (COMPONENT_REF, TREE_TYPE (elt), newrhs, elt);
- /* It is not always safe to go through `build_modify_expr_1'
- when performing element-wise copying. This is because
- an element may be of ARRAY_TYPE, which will not
- be properly copied as a naked element. */
- if (TREE_CODE (TREE_TYPE (elt)) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (TREE_TYPE (elt)))
- basetype_path = TYPE_BINFO (TREE_TYPE (elt));
-
- while (vbases)
- {
- tree elt_lhs_addr = build_unary_op (ADDR_EXPR, elt_lhs, 0);
- tree elt_rhs_addr = build_unary_op (ADDR_EXPR, elt_rhs, 0);
-
- elt_lhs_addr = convert_pointer_to (vbases, elt_lhs_addr);
- elt_rhs_addr = convert_pointer_to (vbases, elt_rhs_addr);
- result
- = tree_cons (NULL_TREE,
- build_modify_expr_1
- (build_indirect_ref (elt_lhs_addr, NULL_PTR),
- modifycode,
- build_indirect_ref (elt_rhs_addr, NULL_PTR),
- basetype_path),
- result);
- if (TREE_VALUE (result) == error_mark_node)
- return error_mark_node;
- vbases = TREE_CHAIN (vbases);
- }
- elt_lhs = build_modify_expr_1 (elt_lhs, modifycode, elt_rhs,
- basetype_path);
- result = tree_cons (NULL_TREE, elt_lhs, result);
- }
-
- if (result)
- return build_compound_expr (result);
- /* No fields to move. */
- return integer_zero_node;
- }
- else
- {
- result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
- void_type_node, lhs, rhs);
- TREE_SIDE_EFFECTS (result) = 1;
- return result;
- }
- }
-
- result = build_modify_expr (lhs, modifycode, newrhs);
- /* ARRAY_TYPEs cannot be converted to anything meaningful,
- and leaving it there screws up `build_compound_expr' when
- it tries to defaultly convert everything. */
- if (TREE_CODE (TREE_TYPE (result)) == ARRAY_TYPE)
- TREE_TYPE (result) = void_type_node;
- return result;
-}
-#endif
-
-/* Taken from expr.c:
- Subroutine of expand_expr:
- record the non-copied parts (LIST) of an expr (LHS), and return a list
- which specifies the initial values of these parts. */
-
-static tree
-init_noncopied_parts (lhs, list)
- tree lhs;
- tree list;
-{
- tree tail;
- tree parts = 0;
-
- for (tail = list; tail; tail = TREE_CHAIN (tail))
- if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
- parts = chainon (parts, init_noncopied_parts (lhs, TREE_VALUE (tail)));
- else
- {
- tree part = TREE_VALUE (tail);
- tree part_type = TREE_TYPE (part);
- tree to_be_initialized = build (COMPONENT_REF, part_type, lhs, part);
- parts = tree_cons (TREE_PURPOSE (tail), to_be_initialized, parts);
- }
- return parts;
-}
+ C++: If MODIFYCODE is INIT_EXPR, then leave references unbashed. */
tree
-expand_target_expr (t)
- tree t;
-{
- tree xval = make_node (RTL_EXPR);
- rtx rtxval;
-
- do_pending_stack_adjust ();
- start_sequence_for_rtl_expr (xval);
- emit_note (0, -1);
- rtxval = expand_expr (t, NULL, VOIDmode, 0);
- do_pending_stack_adjust ();
- TREE_SIDE_EFFECTS (xval) = 1;
- RTL_EXPR_SEQUENCE (xval) = get_insns ();
- end_sequence ();
- RTL_EXPR_RTL (xval) = rtxval;
- TREE_TYPE (xval) = TREE_TYPE (t);
- return xval;
-}
-
-/* Build an assignment expression of lvalue LHS from value RHS.
- MODIFYCODE is the code for a binary operator that we use
- to combine the old value of LHS with RHS to get the new value.
- Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
-
- C++: If MODIFYCODE is INIT_EXPR, then leave references unbashed.
-*/
-tree
build_modify_expr (lhs, modifycode, rhs)
tree lhs;
enum tree_code modifycode;
@@ -5599,24 +5815,18 @@ build_modify_expr (lhs, modifycode, rhs)
tree olhs = lhs;
/* Avoid duplicate error messages from operands that had errors. */
- if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
+ if (lhs == error_mark_node || rhs == error_mark_node)
return error_mark_node;
/* Types that aren't fully specified cannot be used in assignments. */
lhs = require_complete_type (lhs);
- /* Decide early if we are going to protect RHS from GC
- before assigning it to LHS. */
- if (type_needs_gc_entry (TREE_TYPE (rhs))
- && ! value_safe_from_gc (lhs, rhs))
- rhs = protect_value_from_gc (lhs, rhs);
-
newrhs = rhs;
/* Handle assignment to signature pointers/refs. */
- if (TYPE_LANG_SPECIFIC (lhstype) &&
- (IS_SIGNATURE_POINTER (lhstype) || IS_SIGNATURE_REFERENCE (lhstype)))
+ if (TYPE_LANG_SPECIFIC (lhstype)
+ && (IS_SIGNATURE_POINTER (lhstype) || IS_SIGNATURE_REFERENCE (lhstype)))
{
return build_signature_pointer_constructor (lhs, rhs);
}
@@ -5630,7 +5840,8 @@ build_modify_expr (lhs, modifycode, rhs)
case PREINCREMENT_EXPR:
if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0)))
lhs = build (TREE_CODE (lhs), TREE_TYPE (lhs),
- stabilize_reference (TREE_OPERAND (lhs, 0)));
+ stabilize_reference (TREE_OPERAND (lhs, 0)),
+ TREE_OPERAND (lhs, 1));
return build (COMPOUND_EXPR, lhstype,
lhs,
build_modify_expr (TREE_OPERAND (lhs, 0),
@@ -5640,14 +5851,14 @@ build_modify_expr (lhs, modifycode, rhs)
case COMPOUND_EXPR:
newrhs = build_modify_expr (TREE_OPERAND (lhs, 1),
modifycode, rhs);
- if (TREE_CODE (newrhs) == ERROR_MARK)
+ if (newrhs == error_mark_node)
return error_mark_node;
return build (COMPOUND_EXPR, lhstype,
TREE_OPERAND (lhs, 0), newrhs);
case MODIFY_EXPR:
newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs);
- if (TREE_CODE (newrhs) == ERROR_MARK)
+ if (newrhs == error_mark_node)
return error_mark_node;
return build (COMPOUND_EXPR, lhstype, lhs, newrhs);
@@ -5660,19 +5871,22 @@ build_modify_expr (lhs, modifycode, rhs)
so the code to compute it is only emitted once. */
tree cond
= build_conditional_expr (TREE_OPERAND (lhs, 0),
- build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 1)),
+ build_modify_expr (cp_convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 1)),
modifycode, rhs),
- build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 2)),
+ build_modify_expr (cp_convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 2)),
modifycode, rhs));
- if (TREE_CODE (cond) == ERROR_MARK)
+ if (cond == error_mark_node)
return cond;
/* Make sure the code to compute the rhs comes out
before the split. */
return build (COMPOUND_EXPR, TREE_TYPE (lhs),
/* Case to void to suppress warning
from warn_if_unused_value. */
- convert (void_type_node, rhs), cond);
+ cp_convert (void_type_node, rhs), cond);
}
+
+ default:
+ break;
}
if (TREE_CODE (lhs) == OFFSET_REF)
@@ -5709,19 +5923,11 @@ build_modify_expr (lhs, modifycode, rhs)
{
if (! IS_AGGR_TYPE (lhstype))
/* Do the default thing */;
- else if (! TYPE_HAS_CONSTRUCTOR (lhstype))
- {
- cp_error ("`%T' has no constructors", lhstype);
- return error_mark_node;
- }
- else if (TYPE_HAS_TRIVIAL_INIT_REF (lhstype)
- && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
- /* Do the default thing */;
else
{
- result = build_method_call (lhs, constructor_name_full (lhstype),
- build_tree_list (NULL_TREE, rhs),
- NULL_TREE, LOOKUP_NORMAL);
+ result = build_method_call (lhs, ctor_identifier,
+ build_expr_list (NULL_TREE, rhs),
+ TYPE_BINFO (lhstype), LOOKUP_NORMAL);
if (result == NULL_TREE)
return error_mark_node;
return result;
@@ -5729,25 +5935,9 @@ build_modify_expr (lhs, modifycode, rhs)
}
else if (modifycode == NOP_EXPR)
{
-#if 1
/* `operator=' is not an inheritable operator. */
if (! IS_AGGR_TYPE (lhstype))
/* Do the default thing */;
- else if (! TYPE_HAS_ASSIGNMENT (lhstype))
- {
- cp_error ("`%T' does not define operator=", lhstype);
- return error_mark_node;
- }
- else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (lhstype)
- && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
- {
- if (warn_synth)
- /* If we care about this, do overload resolution. */
- build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
-
- /* Do the default thing */;
- }
else
{
result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
@@ -5756,72 +5946,22 @@ build_modify_expr (lhs, modifycode, rhs)
return error_mark_node;
return result;
}
-#else
- /* Treat `operator=' as an inheritable operator. */
- if (TYPE_LANG_SPECIFIC (lhstype) && TYPE_GETS_ASSIGNMENT (lhstype))
- {
- tree orig_lhstype = lhstype;
- while (! TYPE_HAS_ASSIGNMENT (lhstype))
- {
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (lhstype);
- tree basetype = NULL_TREE;
- for (i = 0; i < n_baseclasses; i++)
- if (TYPE_GETS_ASSIGNMENT (TYPE_BINFO_BASETYPE (lhstype, i)))
- {
- if (basetype != NULL_TREE)
- {
- message_2_types (error, "base classes `%s' and `%s' both have operator ='",
- basetype,
- TYPE_BINFO_BASETYPE (lhstype, i));
- return error_mark_node;
- }
- basetype = TYPE_BINFO_BASETYPE (lhstype, i);
- }
- lhstype = basetype;
- }
- if (orig_lhstype != lhstype)
- {
- lhs = build_indirect_ref (convert_pointer_to (lhstype,
- build_unary_op (ADDR_EXPR, lhs, 0)), NULL_PTR);
- if (lhs == error_mark_node)
- {
- cp_error ("conversion to private basetype `%T'", lhstype);
- return error_mark_node;
- }
- }
- result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
- if (result == NULL_TREE)
- return error_mark_node;
- return result;
- }
-#endif
lhstype = olhstype;
}
else if (PROMOTES_TO_AGGR_TYPE (lhstype, REFERENCE_TYPE))
{
- /* This case must convert to some sort of lvalue that
- can participate in an op= operation. */
- tree lhs_tmp = lhs;
- tree rhs_tmp = rhs;
- if (build_default_binary_type_conversion (modifycode, &lhs_tmp, &rhs_tmp))
- {
- lhs = stabilize_reference (lhs_tmp);
- /* Forget is was ever anything else. */
- olhstype = lhstype = TREE_TYPE (lhs);
- newrhs = build_binary_op (modifycode, lhs, rhs_tmp, 1);
- }
- else
- {
- cp_error ("no match for `%O(%#T, %#T)'", modifycode,
- TREE_TYPE (lhs), TREE_TYPE (rhs));
- return error_mark_node;
- }
+ my_friendly_abort (978652);
}
else
{
lhs = stabilize_reference (lhs);
newrhs = build_binary_op (modifycode, lhs, rhs, 1);
+ if (newrhs == error_mark_node)
+ {
+ cp_error (" in evaluation of `%Q(%#T, %#T)'", modifycode,
+ TREE_TYPE (lhs), TREE_TYPE (rhs));
+ return error_mark_node;
+ }
}
/* Handle a cast used as an "lvalue".
@@ -5848,16 +5988,22 @@ build_modify_expr (lhs, modifycode, rhs)
{
tree inner_lhs = TREE_OPERAND (lhs, 0);
tree result;
- if (! lvalue_p (lhs) && pedantic)
- pedwarn ("cast to non-reference type used as lvalue");
+
+ /* WP 5.4.1: The result is an lvalue if T is a reference type,
+ otherwise the result is an rvalue. */
+ if (! lvalue_p (lhs))
+ pedwarn ("ANSI C++ forbids cast to non-reference type used as lvalue");
result = build_modify_expr (inner_lhs, NOP_EXPR,
- convert (TREE_TYPE (inner_lhs),
- convert (lhstype, newrhs)));
- if (TREE_CODE (result) == ERROR_MARK)
+ cp_convert (TREE_TYPE (inner_lhs),
+ cp_convert (lhstype, newrhs)));
+ if (result == error_mark_node)
return result;
- return convert (TREE_TYPE (lhs), result);
+ return cp_convert (TREE_TYPE (lhs), result);
}
+
+ default:
+ break;
}
/* Now we have handled acceptable kinds of LHS that are not truly lvalues.
@@ -5907,7 +6053,7 @@ build_modify_expr (lhs, modifycode, rhs)
}
/* check to see if there is an assignment to `this' */
- if (lhs == current_class_decl)
+ if (lhs == current_class_ptr)
{
if (flag_this_is_variable > 0
&& DECL_NAME (current_function_decl) != NULL_TREE
@@ -5959,104 +6105,6 @@ build_modify_expr (lhs, modifycode, rhs)
if (TREE_SIDE_EFFECTS (newrhs))
newrhs = stabilize_reference (newrhs);
-#if 0
- /* This is now done by generating X(X&) and operator=(X&). */
- /* C++: The semantics of C++ differ from those of C when an
- assignment of an aggregate is desired. Assignment in C++ is
- now defined as memberwise assignment of non-static members
- and base class objects. This rule applies recursively
- until a member of a built-in type is found.
-
- Also, we cannot do a bit-wise copy of aggregates which
- contain virtual function table pointers. Those
- pointer values must be preserved through the copy.
- However, this is handled in expand_expr, and not here.
- This is because much better code can be generated at
- that stage than this one. */
- if (TREE_CODE (lhstype) == RECORD_TYPE
- && ! TYPE_PTRMEMFUNC_P (lhstype)
- && (TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs))
- || (TREE_CODE (TREE_TYPE (newrhs)) == RECORD_TYPE
- && UNIQUELY_DERIVED_FROM_P (lhstype, TREE_TYPE (newrhs)))))
- {
- tree vbases = CLASSTYPE_VBASECLASSES (lhstype);
- tree lhs_addr = build_unary_op (ADDR_EXPR, lhs, 0);
- tree rhs_addr;
-
- /* Memberwise assignment would cause NEWRHS to be
- evaluated for every member that gets assigned.
- By wrapping side-effecting exprs in a SAVE_EXPR,
- NEWRHS will only be evaluated once. */
- if (IS_AGGR_TYPE (TREE_TYPE (newrhs))
- && TREE_SIDE_EFFECTS (newrhs)
- /* This are things we don't have to save. */
- && TREE_CODE (newrhs) != COND_EXPR
- && TREE_CODE (newrhs) != TARGET_EXPR
- && TREE_CODE (newrhs) != WITH_CLEANUP_EXPR)
- /* Call `break_out_cleanups' on NEWRHS in case there are cleanups.
- If NEWRHS is a CALL_EXPR that needs a cleanup, failure to do so
- will result in expand_expr expanding the call without knowing
- that it should run the cleanup. */
- newrhs = save_expr (break_out_cleanups (newrhs));
-
- if (TREE_CODE (newrhs) == COND_EXPR)
- rhs_addr = rationalize_conditional_expr (ADDR_EXPR, newrhs);
- else
- rhs_addr = build_unary_op (ADDR_EXPR, newrhs, 0);
-
- result = tree_cons (NULL_TREE,
- convert (build_reference_type (lhstype), lhs),
- NULL_TREE);
-
- if (! comptypes (TREE_TYPE (lhs_addr), TREE_TYPE (rhs_addr), 1))
- rhs_addr = convert_pointer_to (TREE_TYPE (TREE_TYPE (lhs_addr)), rhs_addr);
- {
- tree noncopied_parts = NULL_TREE;
-
- if (TYPE_NONCOPIED_PARTS (lhstype) != 0)
- noncopied_parts = init_noncopied_parts (lhs,
- TYPE_NONCOPIED_PARTS (lhstype));
- while (noncopied_parts != 0)
- {
- result = tree_cons (NULL_TREE,
- build_modify_expr (convert (ptr_type_node, TREE_VALUE (noncopied_parts)),
- NOP_EXPR,
- TREE_PURPOSE (noncopied_parts)),
- result);
- noncopied_parts = TREE_CHAIN (noncopied_parts);
- }
- }
- /* Once we have our hands on an address, we must change NEWRHS
- to work from there. Otherwise we can get multiple evaluations
- of NEWRHS. */
- if (TREE_CODE (newrhs) != SAVE_EXPR)
- newrhs = build_indirect_ref (rhs_addr, NULL_PTR);
-
- while (vbases)
- {
- tree elt_lhs = convert_pointer_to (vbases, lhs_addr);
- tree elt_rhs = convert_pointer_to (vbases, rhs_addr);
- result
- = tree_cons (NULL_TREE,
- build_modify_expr_1 (build_indirect_ref (elt_lhs, NULL_PTR),
- modifycode,
- build_indirect_ref (elt_rhs, NULL_PTR),
- TYPE_BINFO (lhstype)),
- result);
- if (TREE_VALUE (result) == error_mark_node)
- return error_mark_node;
- vbases = TREE_CHAIN (vbases);
- }
- result = tree_cons (NULL_TREE,
- build_modify_expr_1 (lhs,
- modifycode,
- newrhs,
- TYPE_BINFO (lhstype)),
- result);
- return build_compound_expr (result);
- }
-#endif
-
/* Convert new value to destination type. */
if (TREE_CODE (lhstype) == ARRAY_TYPE)
@@ -6115,16 +6163,7 @@ build_modify_expr (lhs, modifycode, rhs)
}
else
{
-#if 0
- if (IS_AGGR_TYPE (lhstype))
- {
- if (result = build_opfncall (MODIFY_EXPR,
- LOOKUP_NORMAL, lhs, newrhs,
- make_node (NOP_EXPR)))
- return result;
- }
-#endif
- /* Avoid warnings on enum bit fields. */
+ /* Avoid warnings on enum bit fields. */
if (TREE_CODE (olhstype) == ENUMERAL_TYPE
&& TREE_CODE (lhstype) == INTEGER_TYPE)
{
@@ -6137,17 +6176,18 @@ build_modify_expr (lhs, modifycode, rhs)
NULL_TREE, 0);
if (TREE_CODE (newrhs) == CALL_EXPR
&& TYPE_NEEDS_CONSTRUCTING (lhstype))
- newrhs = build_cplus_new (lhstype, newrhs, 0);
+ newrhs = build_cplus_new (lhstype, newrhs);
/* Can't initialize directly from a TARGET_EXPR, since that would
cause the lhs to be constructed twice, and possibly result in
accidental self-initialization. So we force the TARGET_EXPR to be
- expanded. expand_expr should really do this by itself. */
+ expanded without a target. */
if (TREE_CODE (newrhs) == TARGET_EXPR)
- newrhs = expand_target_expr (newrhs);
+ newrhs = build (COMPOUND_EXPR, TREE_TYPE (newrhs), newrhs,
+ TREE_OPERAND (newrhs, 0));
}
- if (TREE_CODE (newrhs) == ERROR_MARK)
+ if (newrhs == error_mark_node)
return error_mark_node;
if (TREE_CODE (newrhs) == COND_EXPR)
@@ -6158,7 +6198,7 @@ build_modify_expr (lhs, modifycode, rhs)
if (TREE_SIDE_EFFECTS (lhs))
cond = build_compound_expr (tree_cons
(NULL_TREE, lhs,
- build_tree_list (NULL_TREE, cond)));
+ build_expr_list (NULL_TREE, cond)));
/* Cannot have two identical lhs on this one tree (result) as preexpand
calls will rip them out and fill in RTL for them, but when the
@@ -6178,45 +6218,17 @@ build_modify_expr (lhs, modifycode, rhs)
result
= build (COND_EXPR, result_type, cond,
build_modify_expr (lhs, modifycode,
- convert (result_type,
- TREE_OPERAND (newrhs, 1))),
+ cp_convert (result_type,
+ TREE_OPERAND (newrhs, 1))),
build_modify_expr (lhs1, modifycode,
- convert (result_type,
- TREE_OPERAND (newrhs, 2))));
+ cp_convert (result_type,
+ TREE_OPERAND (newrhs, 2))));
}
}
- else if (modifycode != INIT_EXPR && TREE_CODE (newrhs) == WITH_CLEANUP_EXPR)
- {
- tree cleanup = TREE_OPERAND (newrhs, 2);
- tree slot;
-
- /* Finish up by running cleanups and having the "value" of the lhs. */
- tree exprlist = tree_cons (NULL_TREE, cleanup,
- build_tree_list (NULL_TREE, lhs));
- newrhs = TREE_OPERAND (newrhs, 0);
- if (TREE_CODE (newrhs) == TARGET_EXPR)
- slot = TREE_OPERAND (newrhs, 0);
- else if (TREE_CODE (newrhs) == ADDR_EXPR)
- {
- /* Bad but valid. */
- slot = newrhs;
- warning ("address taken of temporary object");
- }
- else
- my_friendly_abort (118);
-
- /* Copy the value computed in SLOT into LHS. */
- exprlist = tree_cons (NULL_TREE,
- build_modify_expr (lhs, modifycode, slot),
- exprlist);
- /* Evaluate the expression that needs CLEANUP. This will
- compute the value into SLOT. */
- exprlist = tree_cons (NULL_TREE, newrhs, exprlist);
- result = convert (lhstype, build_compound_expr (exprlist));
- }
else
result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
lhstype, lhs, newrhs);
+
TREE_SIDE_EFFECTS (result) = 1;
/* If we got the LHS in a different type for storing in,
@@ -6227,7 +6239,7 @@ build_modify_expr (lhs, modifycode, rhs)
if (olhstype == TREE_TYPE (result))
return result;
/* Avoid warnings converting integral types back into enums
- for enum bit fields. */
+ for enum bit fields. */
if (TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE
&& TREE_CODE (olhstype) == ENUMERAL_TYPE)
{
@@ -6239,13 +6251,32 @@ build_modify_expr (lhs, modifycode, rhs)
NULL_TREE, 0);
}
+tree
+build_x_modify_expr (lhs, modifycode, rhs)
+ tree lhs;
+ enum tree_code modifycode;
+ tree rhs;
+{
+ if (processing_template_decl)
+ return build_min_nt (MODOP_EXPR, lhs,
+ build_min_nt (modifycode, NULL_TREE, NULL_TREE), rhs);
+
+ if (modifycode != NOP_EXPR)
+ {
+ tree rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
+ make_node (modifycode));
+ if (rval)
+ return rval;
+ }
+ return build_modify_expr (lhs, modifycode, rhs);
+}
/* Return 0 if EXP is not a valid lvalue in this language
even though `lvalue_or_else' would accept it. */
int
language_lvalue_valid (exp)
- tree exp;
+ tree exp ATTRIBUTE_UNUSED;
{
return 1;
}
@@ -6253,6 +6284,7 @@ language_lvalue_valid (exp)
/* Get difference in deltas for different pointer to member function
types. Return integer_zero_node, if FROM cannot be converted to a
TO type. If FORCE is true, then allow reverse conversions as well. */
+
static tree
get_delta_difference (from, to, force)
tree from, to;
@@ -6280,35 +6312,117 @@ get_delta_difference (from, to, force)
if (!force)
{
error_not_base_type (from, to);
- error (" in pointer to member function conversion");
+ error (" in pointer to member conversion");
return delta;
}
binfo = get_binfo (to, from, 1);
- if (binfo == error_mark_node)
- {
- error (" in pointer to member function conversion");
- return delta;
- }
- if (binfo == 0)
- {
- error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to);
- return delta;
- }
+ if (binfo == 0 || binfo == error_mark_node)
+ return delta;
if (TREE_VIA_VIRTUAL (binfo))
{
- warning ("pointer to member conversion to virtual base class will only work if you are very careful");
+ binfo = binfo_member (BINFO_TYPE (binfo),
+ CLASSTYPE_VBASECLASSES (from));
+ cp_warning ("pointer to member cast to virtual base `%T'",
+ BINFO_TYPE (binfo));
+ warning (" will only work if you are very careful");
}
+ delta = BINFO_OFFSET (binfo);
+ delta = cp_convert (ptrdiff_type_node, delta);
+
return build_binary_op (MINUS_EXPR,
integer_zero_node,
- BINFO_OFFSET (binfo), 1);
+ delta, 1);
}
+
if (TREE_VIA_VIRTUAL (binfo))
{
- warning ("pointer to member conversion from virtual base class will only work if you are very careful");
+ if (force)
+ {
+ cp_warning ("pointer to member cast from virtual base `%T'",
+ BINFO_TYPE (binfo));
+ warning (" will only work if you are very careful");
+ }
+ else
+ cp_error ("pointer to member conversion from virtual base `%T'",
+ BINFO_TYPE (binfo));
}
+
return BINFO_OFFSET (binfo);
}
+static tree
+build_ptrmemfunc1 (type, delta, idx, pfn, delta2)
+ tree type, delta, idx, pfn, delta2;
+{
+ tree u;
+
+#if 0
+ /* This is the old way we did it. We want to avoid calling
+ digest_init, so that it can give an error if we use { } when
+ initializing a pointer to member function. */
+
+ if (pfn)
+ {
+ u = build_nt (CONSTRUCTOR, NULL_TREE,
+ expr_tree_cons (pfn_identifier, pfn, NULL_TREE));
+ }
+ else
+ {
+ u = build_nt (CONSTRUCTOR, NULL_TREE,
+ expr_tree_cons (delta2_identifier, delta2, NULL_TREE));
+ }
+
+ u = build_nt (CONSTRUCTOR, NULL_TREE,
+ expr_tree_cons (NULL_TREE, delta,
+ expr_tree_cons (NULL_TREE, idx,
+ expr_tree_cons (NULL_TREE, u, NULL_TREE))));
+
+ return digest_init (type, u, (tree*)0);
+#else
+ tree delta_field, idx_field, pfn_or_delta2_field, pfn_field, delta2_field;
+ tree subtype;
+ int allconstant, allsimple;
+
+ delta_field = TYPE_FIELDS (type);
+ idx_field = TREE_CHAIN (delta_field);
+ pfn_or_delta2_field = TREE_CHAIN (idx_field);
+ subtype = TREE_TYPE (pfn_or_delta2_field);
+ pfn_field = TYPE_FIELDS (subtype);
+ delta2_field = TREE_CHAIN (pfn_field);
+
+ if (pfn)
+ {
+ allconstant = TREE_CONSTANT (pfn);
+ allsimple = !! initializer_constant_valid_p (pfn, TREE_TYPE (pfn));
+ u = expr_tree_cons (pfn_field, pfn, NULL_TREE);
+ }
+ else
+ {
+ delta2 = convert_and_check (delta_type_node, delta2);
+ allconstant = TREE_CONSTANT (delta2);
+ allsimple = !! initializer_constant_valid_p (delta2, TREE_TYPE (delta2));
+ u = expr_tree_cons (delta2_field, delta2, NULL_TREE);
+ }
+
+ delta = convert_and_check (delta_type_node, delta);
+ idx = convert_and_check (delta_type_node, idx);
+
+ allconstant = allconstant && TREE_CONSTANT (delta) && TREE_CONSTANT (idx);
+ allsimple = allsimple
+ && initializer_constant_valid_p (delta, TREE_TYPE (delta))
+ && initializer_constant_valid_p (idx, TREE_TYPE (idx));
+
+ u = build (CONSTRUCTOR, subtype, NULL_TREE, u);
+ u = expr_tree_cons (delta_field, delta,
+ expr_tree_cons (idx_field, idx,
+ expr_tree_cons (pfn_or_delta2_field, u, NULL_TREE)));
+ u = build (CONSTRUCTOR, type, NULL_TREE, u);
+ TREE_CONSTANT (u) = allconstant;
+ TREE_STATIC (u) = allconstant && allsimple;
+ return u;
+#endif
+}
+
/* Build a constructor for a pointer to member function. It can be
used to initialize global variables, local variable, or used
as a value in expressions. TYPE is the POINTER to METHOD_TYPE we
@@ -6325,119 +6439,71 @@ build_ptrmemfunc (type, pfn, force)
tree type, pfn;
int force;
{
- tree index = integer_zero_node;
+ tree idx = integer_zero_node;
tree delta = integer_zero_node;
tree delta2 = integer_zero_node;
tree vfield_offset;
- tree npfn;
- tree u;
+ tree npfn = NULL_TREE;
- /* Handle multiple conversions of pointer to member functions. */
+ /* Handle multiple conversions of pointer to member functions. */
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
{
- tree ndelta, ndelta2, nindex;
+ tree ndelta, ndelta2;
+ tree e1, e2, e3, n;
+ tree pfn_type;
+
/* Is is already the right type? */
-#if 0
- /* Sorry, can't do this, the backend is too stupid. */
- if (TYPE_METHOD_BASETYPE (TREE_TYPE (type))
- == TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))))
- {
- if (type != TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))
- {
- npfn = build1 (NOP_EXPR, TYPE_GET_PTRMEMFUNC_TYPE (type), pfn);
- TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
- }
- return pfn;
- }
-#else
if (type == TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))
return pfn;
-#endif
- if (TREE_CODE (pfn) != CONSTRUCTOR)
- {
- tree e1, e2, e3;
- ndelta = convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, 0, 0));
- ndelta2 = convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn));
- index = build_component_ref (pfn, index_identifier, 0, 0);
- 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);
- delta2 = build_binary_op (PLUS_EXPR, ndelta2, delta2, 1);
- e1 = fold (build (GT_EXPR, boolean_type_node, index, integer_zero_node));
+ pfn_type = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn));
+ if (!force
+ && comp_target_types (type, pfn_type, 0) != 1)
+ cp_error ("conversion to `%T' from `%T'", type, pfn_type);
+
+ ndelta = cp_convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, NULL_TREE, 0));
+ ndelta2 = cp_convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn));
+ idx = build_component_ref (pfn, index_identifier, NULL_TREE, 0);
+
+ n = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (pfn_type)),
+ TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
+ force);
+
+ delta = build_binary_op (PLUS_EXPR, ndelta, n, 1);
+ delta2 = build_binary_op (PLUS_EXPR, ndelta2, n, 1);
+ e1 = fold (build (GT_EXPR, boolean_type_node, idx, integer_zero_node));
- u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
- u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, index,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- e2 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+ e2 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx,
+ NULL_TREE, delta2);
- pfn = PFN_FROM_PTRMEMFUNC (pfn);
- npfn = build1 (NOP_EXPR, type, pfn);
- TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
+ pfn = PFN_FROM_PTRMEMFUNC (pfn);
+ npfn = build1 (NOP_EXPR, type, pfn);
+ TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
- u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE));
- u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, index,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- e3 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
- return build_conditional_expr (e1, e2, e3);
- }
-
- ndelta = TREE_VALUE (CONSTRUCTOR_ELTS (pfn));
- nindex = TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn)));
- npfn = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn))));
- 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");
- return error_mark_node;
- }
+ e3 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn,
+ NULL_TREE);
+ return build_conditional_expr (e1, e2, e3);
}
- /* Handle null pointer to member function conversions. */
+ /* Handle null pointer to member function conversions. */
if (integer_zerop (pfn))
{
- pfn = build_c_cast (type, integer_zero_node, 0);
- u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, pfn, NULL_TREE));
- u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, integer_zero_node,
- tree_cons (NULL_TREE, integer_zero_node,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+ pfn = build_c_cast (type, integer_zero_node);
+ return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type),
+ integer_zero_node, integer_zero_node,
+ pfn, NULL_TREE);
}
if (TREE_CODE (pfn) == TREE_LIST
|| (TREE_CODE (pfn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (pfn, 0)) == TREE_LIST))
- {
- pfn = instantiate_type (type, pfn, 1);
- if (pfn == error_mark_node)
- return error_mark_node;
- if (TREE_CODE (pfn) != ADDR_EXPR)
- pfn = build_unary_op (ADDR_EXPR, pfn, 0);
- }
+ return instantiate_type (type, pfn, 1);
+
+ if (!force
+ && comp_target_types (type, TREE_TYPE (pfn), 0) != 1)
+ cp_error ("conversion to `%T' from `%T'", type, TREE_TYPE (pfn));
- /* Allow pointer to member conversions here. */
+ /* Allow pointer to member conversions here. */
delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
force);
@@ -6449,7 +6515,7 @@ build_ptrmemfunc (type, pfn, force)
if (TREE_CODE (TREE_OPERAND (pfn, 0)) == FUNCTION_DECL
&& DECL_VINDEX (TREE_OPERAND (pfn, 0)))
{
- /* Find the offset to the vfield pointer in the object. */
+ /* Find the offset to the vfield pointer in the object. */
vfield_offset = get_binfo (DECL_CONTEXT (TREE_OPERAND (pfn, 0)),
DECL_CLASS_CONTEXT (TREE_OPERAND (pfn, 0)),
0);
@@ -6457,25 +6523,26 @@ build_ptrmemfunc (type, pfn, force)
delta2 = size_binop (PLUS_EXPR, vfield_offset, delta2);
/* Map everything down one to make room for the null pointer to member. */
- index = size_binop (PLUS_EXPR,
- DECL_VINDEX (TREE_OPERAND (pfn, 0)),
- integer_one_node);
- u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
+ idx = size_binop (PLUS_EXPR,
+ DECL_VINDEX (TREE_OPERAND (pfn, 0)),
+ integer_one_node);
}
else
{
- index = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
-
- npfn = build1 (NOP_EXPR, type, pfn);
- TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
+ idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
- u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE));
+ if (type == TREE_TYPE (pfn))
+ {
+ npfn = pfn;
+ }
+ else
+ {
+ npfn = build1 (NOP_EXPR, type, pfn);
+ TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
+ }
}
- u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, index,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+ return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn, delta2);
}
/* Convert value RHS to type TYPE as preparation for an assignment
@@ -6521,7 +6588,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
if (rhs == error_mark_node)
return error_mark_node;
- if (TREE_VALUE (rhs) == error_mark_node)
+ if (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node)
return error_mark_node;
if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
@@ -6549,7 +6616,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
else if (TREE_READONLY_DECL_P (rhs))
rhs = decl_constant_value (rhs);
- if (type == rhstype)
+ if (comptypes (type, rhstype, 1))
{
overflow_warning (rhs);
return rhs;
@@ -6561,8 +6628,10 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
return error_mark_node;
}
/* Arithmetic types all interconvert. */
- if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == BOOLEAN_TYPE)
- && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == BOOLEAN_TYPE))
+ if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == BOOLEAN_TYPE
+ || codel == COMPLEX_TYPE)
+ && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == BOOLEAN_TYPE
+ || coder == COMPLEX_TYPE))
{
/* But we should warn if assigning REAL_TYPE to INTEGER_TYPE. */
if (coder == REAL_TYPE && codel == INTEGER_TYPE)
@@ -6600,7 +6669,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
|| (coder == ENUMERAL_TYPE
&& (INTEGRAL_CODE_P (codel) || codel == REAL_TYPE)))
{
- return cp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL);
+ return ocp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL);
}
/* Conversions among pointers */
else if (codel == POINTER_TYPE
@@ -6676,13 +6745,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
return error_mark_node;
}
- if (ctt < 0)
+ if (ctt < 0 && TYPE_MAIN_VARIANT (ttl) != TYPE_MAIN_VARIANT (ttr))
cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
rhstype, type);
if (TYPE_MAIN_VARIANT (ttl) != void_type_node
&& TYPE_MAIN_VARIANT (ttr) == void_type_node
- && rhs != null_pointer_node)
+ && ! null_ptr_cst_p (rhs))
{
if (coder == RECORD_TYPE)
cp_pedwarn ("implicit conversion of signature pointer to type `%T'",
@@ -6733,31 +6802,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
}
}
}
- else if (TREE_CODE (ttr) == OFFSET_TYPE
- && TREE_CODE (ttl) != OFFSET_TYPE)
- {
- /* Normally, pointers to different type codes (other
- than void) are not compatible, but we perform
- some type instantiation if that resolves the
- ambiguity of (X Y::*) and (X *). */
-
- if (current_class_decl)
- {
- if (TREE_CODE (rhs) == INTEGER_CST)
- {
- rhs = build (PLUS_EXPR, build_pointer_type (TREE_TYPE (ttr)),
- current_class_decl, rhs);
- return convert_for_assignment (type, rhs,
- errtype, fndecl, parmnum);
- }
- }
- if (TREE_CODE (ttl) == METHOD_TYPE)
- error ("%s between pointer-to-method and pointer-to-member types",
- errtype);
- else
- error ("%s between pointer and pointer-to-member types", errtype);
- return error_mark_node;
- }
else
{
int add_quals = 0, const_parity = 0, volatile_parity = 0;
@@ -6769,8 +6813,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
for (; ; ttl = TREE_TYPE (ttl), ttr = TREE_TYPE (ttr))
{
nptrs -= 1;
- const_parity |= TYPE_READONLY (ttl) < TYPE_READONLY (ttr);
- volatile_parity |= TYPE_VOLATILE (ttl) < TYPE_VOLATILE (ttr);
+ const_parity |= (TYPE_READONLY (ttl) < TYPE_READONLY (ttr));
+ volatile_parity |= (TYPE_VOLATILE (ttl) < TYPE_VOLATILE (ttr));
if (! left_const
&& (TYPE_READONLY (ttl) > TYPE_READONLY (ttr)
@@ -6849,24 +6893,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
cp_warning ("\t`%T' != `%T'", type, rhstype);
}
}
- else if (TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
- {
- /* When does this happen? */
- my_friendly_abort (119);
- /* Conversion of a pointer-to-member type to void *. */
- rhs = build_unary_op (ADDR_EXPR, rhs, 0);
- TREE_TYPE (rhs) = type;
- return rhs;
- }
- else if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
- {
- /* When does this happen? */
- my_friendly_abort (120);
- /* Conversion of a pointer-to-member type to void *. */
- rhs = build_unary_op (ADDR_EXPR, rhs, 0);
- TREE_TYPE (rhs) = type;
- return rhs;
- }
else
{
if (fndecl)
@@ -6877,7 +6903,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
return error_mark_node;
}
}
- return convert (type, rhs);
+ return cp_convert (type, rhs);
}
else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
{
@@ -6891,9 +6917,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
else
cp_pedwarn ("%s to `%T' from `%T' lacks a cast",
errtype, type, rhstype);
- return convert (type, rhs);
}
- return null_pointer_node;
+ return cp_convert (type, rhs);
}
else if (codel == INTEGER_TYPE
&& (coder == POINTER_TYPE
@@ -6908,7 +6933,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
else
cp_pedwarn ("%s to `%T' from `%T' lacks a cast",
errtype, type, rhstype);
- return convert (type, rhs);
+ return cp_convert (type, rhs);
}
else if (codel == BOOLEAN_TYPE
&& (coder == POINTER_TYPE
@@ -6916,7 +6941,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
&& (IS_SIGNATURE_POINTER (rhstype)
|| TYPE_PTRMEMFUNC_FLAG (rhstype)
|| IS_SIGNATURE_REFERENCE (rhstype)))))
- return convert (type, rhs);
+ return cp_convert (type, rhs);
/* C++ */
else if (((coder == POINTER_TYPE
@@ -6926,9 +6951,11 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
&& TYPE_PTRMEMFUNC_P (type))
{
tree ttl = TYPE_PTRMEMFUNC_FN_TYPE (type);
- tree ttr = (TREE_CODE (rhstype) == POINTER_TYPE ? rhstype
- : TYPE_PTRMEMFUNC_FN_TYPE (type));
- int ctt = comp_target_types (ttl, ttr, 1);
+ tree ttr = (TYPE_PTRMEMFUNC_P (rhstype)
+ ? TYPE_PTRMEMFUNC_FN_TYPE (rhstype)
+ : rhstype);
+ int ctt = (TREE_CODE (rhstype) == INTEGER_TYPE ? 1
+ : comp_target_types (ttl, ttr, 1));
if (ctt < 0)
cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
@@ -6936,7 +6963,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
else if (ctt == 0)
cp_error ("%s to `%T' from `%T'", errtype, ttl, ttr);
- /* compatible pointer to member functions. */
+ /* compatible pointer to member functions. */
return build_ptrmemfunc (ttl, rhs, 0);
}
else if (codel == ERROR_MARK || coder == ERROR_MARK)
@@ -6954,7 +6981,14 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
return nrhs;
}
else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs)))
- return convert (type, rhs);
+ return cp_convert (type, rhs);
+ /* Handle anachronistic conversions from (::*)() to cv void* or (*)(). */
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+ || TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
+ && TREE_TYPE (rhs)
+ && TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs)))
+ return cp_convert (type, rhs);
cp_error ("%s to `%T' from `%T'", errtype, type, rhstype);
return error_mark_node;
@@ -6975,6 +7009,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
exist, an ambiguity exists.
If flags doesn't include LOOKUP_COMPLAIN, don't complain about anything. */
+
tree
convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
tree exp, type, rhs;
@@ -7029,12 +7064,6 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (coder == ERROR_MARK)
return error_mark_node;
-#if 0
- /* This is *not* the quick way out! It is the way to disaster. */
- if (type == rhstype)
- goto converted;
-#endif
-
/* We accept references to incomplete types, so we can
return here before checking if RHS is of complete type. */
@@ -7042,7 +7071,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
{
/* This should eventually happen in convert_arguments. */
extern int warningcount, errorcount;
- int savew, savee;
+ int savew = 0, savee = 0;
if (fndecl)
savew = warningcount, savee = errorcount;
@@ -7069,84 +7098,14 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (TREE_CODE (rhstype) == REFERENCE_TYPE)
rhstype = TREE_TYPE (rhstype);
+ type = complete_type (type);
+
if (TYPE_LANG_SPECIFIC (type)
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type)))
return build_signature_pointer_constructor (type, rhs);
- if (IS_AGGR_TYPE (type)
- && (TYPE_NEEDS_CONSTRUCTING (type) || TREE_HAS_CONSTRUCTOR (rhs)))
- {
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
- {
- /* This is sufficient to perform initialization. No need,
- apparently, to go through X(X&) to do first-cut
- initialization. Return through a TARGET_EXPR so that we get
- cleanups if it is used. */
- if (TREE_CODE (rhs) == CALL_EXPR)
- {
- rhs = build_cplus_new (type, rhs, 0);
- return rhs;
- }
- /* Handle the case of default parameter initialization and
- initialization of static variables. */
- else if (TREE_CODE (rhs) == TARGET_EXPR)
- return rhs;
- else if (TREE_CODE (rhs) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (rhs))
- {
- my_friendly_assert (TREE_CODE (TREE_OPERAND (rhs, 0)) == CALL_EXPR, 318);
- if (exp)
- {
- my_friendly_assert (TREE_VALUE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 1)) == NULL_TREE, 316);
- TREE_VALUE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 1))
- = build_unary_op (ADDR_EXPR, exp, 0);
- }
- else
- rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0), 0);
- return rhs;
- }
- else if (TYPE_HAS_TRIVIAL_INIT_REF (type))
- return rhs;
- }
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)
- || (IS_AGGR_TYPE (rhstype) && UNIQUELY_DERIVED_FROM_P (type, rhstype)))
- {
- if (TYPE_HAS_INIT_REF (type))
- {
- tree init = build_method_call (exp, constructor_name_full (type),
- build_tree_list (NULL_TREE, rhs),
- TYPE_BINFO (type), LOOKUP_NORMAL);
-
- if (init == error_mark_node)
- return error_mark_node;
-
- if (exp == 0)
- {
- exp = build_cplus_new (type, init, 0);
- return exp;
- }
-
- return build (COMPOUND_EXPR, type, init, exp);
- }
-
- /* ??? The following warnings are turned off because
- this is another place where the default X(X&) constructor
- is implemented. */
- if (TYPE_HAS_ASSIGNMENT (type))
- cp_warning ("bitwise copy: `%T' defines operator=", type);
-
- if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
- rhs = convert_from_reference (rhs);
- if (type != rhstype)
- {
- tree nrhs = build1 (NOP_EXPR, type, rhs);
- TREE_CONSTANT (nrhs) = TREE_CONSTANT (rhs);
- rhs = nrhs;
- }
- return rhs;
- }
-
- return cp_convert (type, rhs, CONV_OLD_CONVERT, flags);
- }
+ if (IS_AGGR_TYPE (type))
+ return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
if (type == TREE_TYPE (rhs))
{
@@ -7195,7 +7154,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
if (o[i] != TREE_VALUE (tail))
{
expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)),
- const0_rtx, VOIDmode, 0);
+ const0_rtx, VOIDmode, EXPAND_NORMAL);
free_temp_slots ();
}
/* Detect modification of read-only values.
@@ -7234,8 +7193,6 @@ c_expand_return (retval)
extern tree dtor_label, ctor_label;
tree result = DECL_RESULT (current_function_decl);
tree valtype = TREE_TYPE (result);
- register int use_temp = 0;
- int returns_value = 1;
if (TREE_THIS_VOLATILE (current_function_decl))
warning ("function declared `noreturn' has a `return' statement");
@@ -7246,19 +7203,28 @@ c_expand_return (retval)
return;
}
- if (retval == NULL_TREE)
+ if (processing_template_decl)
{
- /* A non-named return value does not count. */
+ add_tree (build_min_nt (RETURN_STMT, retval));
+ return;
+ }
+
+ if (dtor_label)
+ {
+ if (retval)
+ error ("returning a value from a destructor");
/* Can't just return from a destructor. */
- if (dtor_label)
- {
- expand_goto (dtor_label);
- return;
- }
+ expand_goto (dtor_label);
+ return;
+ }
+
+ if (retval == NULL_TREE)
+ {
+ /* A non-named return value does not count. */
if (DECL_CONSTRUCTOR_P (current_function_decl))
- retval = current_class_decl;
+ retval = current_class_ptr;
else if (DECL_NAME (result) != NULL_TREE
&& TREE_CODE (valtype) != VOID_TYPE)
retval = result;
@@ -7282,83 +7248,28 @@ c_expand_return (retval)
return;
}
}
- else if (DECL_CONSTRUCTOR_P (current_function_decl)
- && retval != current_class_decl)
+ else if (DECL_CONSTRUCTOR_P (current_function_decl))
{
- error ("return from a constructor: use `this = ...' instead");
- retval = current_class_decl;
+ if (flag_this_is_variable)
+ error ("return from a constructor: use `this = ...' instead");
+ else
+ error ("returning a value from a constructor");
+ retval = current_class_ptr;
}
+ /* Effective C++ rule 15. See also start_function. */
+ if (warn_ecpp
+ && DECL_NAME (current_function_decl) == ansi_opname[(int) MODIFY_EXPR]
+ && retval != current_class_ref)
+ cp_warning ("`operator=' should return a reference to `*this'");
+
if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE)
{
current_function_returns_null = 1;
- /* We do this here so we'll avoid a warning about how the function
- "may or may not return a value" in finish_function. */
- returns_value = 0;
-
- if (retval)
+ if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
pedwarn ("`return' with a value, in function returning void");
expand_return (retval);
- }
- /* Add some useful error checking for C++. */
- else if (TREE_CODE (valtype) == REFERENCE_TYPE)
- {
- tree whats_returned;
- tree tmp_result = result;
-
- /* Don't initialize directly into a non-BLKmode retval, since that
- could lose when being inlined by another caller. (GCC can't
- read the function return register in an inline function when
- the return value is being ignored). */
- if (result && TYPE_MODE (TREE_TYPE (tmp_result)) != BLKmode)
- tmp_result = 0;
-
- /* convert to reference now, so we can give error if we
- return an reference to a non-lvalue. */
- retval = convert_for_initialization (tmp_result, valtype, retval,
- LOOKUP_NORMAL, "return",
- NULL_TREE, 0);
-
- /* Sort through common things to see what it is
- we are returning. */
- whats_returned = retval;
- if (TREE_CODE (whats_returned) == COMPOUND_EXPR)
- {
- whats_returned = TREE_OPERAND (whats_returned, 1);
- if (TREE_CODE (whats_returned) == ADDR_EXPR)
- whats_returned = TREE_OPERAND (whats_returned, 0);
- }
- if (TREE_CODE (whats_returned) == ADDR_EXPR)
- {
- whats_returned = TREE_OPERAND (whats_returned, 0);
- while (TREE_CODE (whats_returned) == NEW_EXPR
- || TREE_CODE (whats_returned) == TARGET_EXPR
- || TREE_CODE (whats_returned) == WITH_CLEANUP_EXPR)
- {
- /* Get the target. */
- whats_returned = TREE_OPERAND (whats_returned, 0);
- warning ("returning reference to temporary");
- }
- }
-
- if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned))
- {
- if (TEMP_NAME_P (DECL_NAME (whats_returned)))
- warning ("reference to non-lvalue returned");
- else if (! TREE_STATIC (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned)))
- cp_warning_at ("reference to local variable `%D' returned", whats_returned);
- }
- }
- else if (TREE_CODE (retval) == ADDR_EXPR)
- {
- tree whats_returned = TREE_OPERAND (retval, 0);
-
- if (TREE_CODE (whats_returned) == VAR_DECL
- && DECL_NAME (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
- && !TREE_STATIC (whats_returned))
- cp_warning_at ("address of local variable `%D' returned", whats_returned);
+ return;
}
/* Now deal with possible C++ hair:
@@ -7369,153 +7280,120 @@ c_expand_return (retval)
(3) If an X(X&) constructor is defined, the return
value must be returned via that. */
- /* If we're returning in a register, we can't initialize the
- return value from a TARGET_EXPR. */
- if (TREE_CODE (retval) == TARGET_EXPR
- && TYPE_MAIN_VARIANT (TREE_TYPE (retval)) == TYPE_MAIN_VARIANT (valtype)
- && ! current_function_returns_struct)
- retval = expand_target_expr (retval);
-
if (retval == result
- /* Watch out for constructors, which "return" aggregates
- via initialization, but which otherwise "return" a pointer. */
|| DECL_CONSTRUCTOR_P (current_function_decl))
+ /* It's already done for us. */;
+ else if (TREE_TYPE (retval) == void_type_node)
{
- /* This is just an error--it's already been reported. */
- if (TYPE_SIZE (valtype) == NULL_TREE)
- return;
-
- if (TYPE_MODE (valtype) != BLKmode
- && any_pending_cleanups (1))
- {
- retval = get_temp_regvar (valtype, retval);
- use_temp = obey_regdecls;
- }
- }
- else if (IS_AGGR_TYPE (valtype) && current_function_returns_struct)
- {
- expand_aggr_init (result, retval, 0, LOOKUP_ONLYCONVERTING);
- expand_cleanups_to (NULL_TREE);
- DECL_INITIAL (result) = NULL_TREE;
+ pedwarn ("return of void value in function returning non-void");
+ expand_expr_stmt (retval);
retval = 0;
}
else
{
- if (TYPE_MODE (valtype) == VOIDmode)
+ tree functype = TREE_TYPE (TREE_TYPE (current_function_decl));
+
+ /* First convert the value to the function's return type, then
+ to the type of return value's location to handle the
+ case that functype is thiner than the valtype. */
+
+ retval = convert_for_initialization
+ (NULL_TREE, functype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
+ "return", NULL_TREE, 0);
+
+ retval = convert (valtype, retval);
+
+ if (retval == error_mark_node)
{
- if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode
- && warn_return_type)
- warning ("return of void value in function returning non-void");
- expand_expr_stmt (retval);
- retval = 0;
- result = 0;
+ /* Avoid warning about control reaching end of function. */
+ expand_null_return ();
+ return;
}
- else if (TYPE_MODE (valtype) != BLKmode
- && any_pending_cleanups (1))
+
+ /* We can't initialize a register from a AGGR_INIT_EXPR. */
+ else if (! current_function_returns_struct
+ && TREE_CODE (retval) == TARGET_EXPR
+ && TREE_CODE (TREE_OPERAND (retval, 1)) == AGGR_INIT_EXPR)
+ retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval,
+ TREE_OPERAND (retval, 0));
+
+ /* Add some useful error checking for C++. */
+ else if (TREE_CODE (valtype) == REFERENCE_TYPE)
{
- retval = get_temp_regvar (valtype, retval);
- expand_cleanups_to (NULL_TREE);
- use_temp = obey_regdecls;
- result = 0;
+ tree whats_returned;
+
+ /* Sort through common things to see what it is
+ we are returning. */
+ whats_returned = retval;
+ if (TREE_CODE (whats_returned) == COMPOUND_EXPR)
+ {
+ whats_returned = TREE_OPERAND (whats_returned, 1);
+ if (TREE_CODE (whats_returned) == ADDR_EXPR)
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ }
+ while (TREE_CODE (whats_returned) == CONVERT_EXPR
+ || TREE_CODE (whats_returned) == NOP_EXPR)
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ if (TREE_CODE (whats_returned) == ADDR_EXPR)
+ {
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ while (TREE_CODE (whats_returned) == AGGR_INIT_EXPR
+ || TREE_CODE (whats_returned) == TARGET_EXPR)
+ {
+ /* Get the target. */
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ warning ("returning reference to temporary");
+ }
+ }
+
+ if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned))
+ {
+ if (TEMP_NAME_P (DECL_NAME (whats_returned)))
+ warning ("reference to non-lvalue returned");
+ else if (TREE_CODE (TREE_TYPE (whats_returned)) != REFERENCE_TYPE
+ && ! TREE_STATIC (whats_returned)
+ && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
+ && !TREE_PUBLIC (whats_returned))
+ cp_warning_at ("reference to local variable `%D' returned", whats_returned);
+ }
}
- else
+ else if (TREE_CODE (retval) == ADDR_EXPR)
{
- retval = convert_for_initialization (result, valtype, retval,
- LOOKUP_NORMAL,
- "return", NULL_TREE, 0);
- DECL_INITIAL (result) = NULL_TREE;
+ tree whats_returned = TREE_OPERAND (retval, 0);
+
+ if (TREE_CODE (whats_returned) == VAR_DECL
+ && DECL_NAME (whats_returned)
+ && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
+ && !TREE_STATIC (whats_returned)
+ && !TREE_PUBLIC (whats_returned))
+ cp_warning_at ("address of local variable `%D' returned", whats_returned);
}
- if (retval == error_mark_node)
- return;
}
- emit_queue ();
-
if (retval != NULL_TREE
&& TREE_CODE_CLASS (TREE_CODE (retval)) == 'd'
&& cond_stack == 0 && loop_stack == 0 && case_stack == 0)
current_function_return_value = retval;
- if (result)
+ if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
{
- /* Everything's great--RETVAL is in RESULT. */
- if (original_result_rtx)
- {
- 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)
- {
- /* Clear this out so the later call to decl_function_context
- won't end up bombing on us. */
- if (DECL_CONTEXT (result) == error_mark_node)
- DECL_CONTEXT (result) = NULL_TREE;
- /* Here is where we finally get RETVAL into RESULT.
- `expand_return' does the magic of protecting
- RESULT from cleanups. */
- retval = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result),
- retval));
- /* This part _must_ come second, because expand_return looks for
- the INIT_EXPR as the toplevel node only. :-( */
- retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
- TREE_SIDE_EFFECTS (retval) = 1;
- expand_return (retval);
- }
- else
- expand_return (result);
+ /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do. */
+ expand_goto (ctor_label);
}
- else
+
+ if (retval && retval != result)
{
- /* We may still need to put RETVAL into RESULT. */
- result = DECL_RESULT (current_function_decl);
- if (original_result_rtx)
- {
- /* Here we have a named return value that went
- into memory. We can compute RETVAL into that. */
- if (retval)
- expand_assignment (result, retval, 0, 0);
- else
- store_expr (result, original_result_rtx, 0);
- result = make_tree (TREE_TYPE (result), original_result_rtx);
- }
- else if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
- {
- /* Here RETVAL is CURRENT_CLASS_DECL, so there's nothing to do. */
- expand_goto (ctor_label);
- }
- else if (retval)
- {
- /* Here is where we finally get RETVAL into RESULT.
- `expand_return' does the magic of protecting
- RESULT from cleanups. */
- result = build (INIT_EXPR, TREE_TYPE (result), result, retval);
- TREE_SIDE_EFFECTS (result) = 1;
- expand_return (result);
- }
- else if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode)
- expand_return (result);
+ result = build (INIT_EXPR, TREE_TYPE (result), result, retval);
+ TREE_SIDE_EFFECTS (result) = 1;
}
- current_function_returns_value = returns_value;
-#if 0
- /* These wind up after the BARRIER, which causes problems for
- expand_end_binding. What purpose were they supposed to serve? */
- if (original_result_rtx)
- use_variable (original_result_rtx);
- if (use_temp)
- use_variable (DECL_RTL (DECL_RESULT (current_function_decl)));
-#endif
+ expand_start_target_temps ();
+
+ expand_return (result);
- /* One way to clear out cleanups that EXPR might
- generate. Note that this code will really be
- dead code, but that is ok--cleanups that were
- needed were handled by the magic of `return'. */
- expand_cleanups_to (NULL_TREE);
+ expand_end_target_temps ();
+
+ current_function_returns_value = 1;
}
/* Start a C switch statement, testing expression EXP.
@@ -7551,18 +7429,18 @@ c_expand_start_case (exp)
}
else
{
- tree index;
+ tree idx;
exp = default_conversion (exp);
type = TREE_TYPE (exp);
- index = get_unwidened (exp, 0);
+ idx = get_unwidened (exp, 0);
/* We can't strip a conversion from a signed type to an unsigned,
because if we did, int_fits_type_p would do the wrong thing
when checking case values for being in range,
and it's too hard to do the right thing. */
if (TREE_UNSIGNED (TREE_TYPE (exp))
- == TREE_UNSIGNED (TREE_TYPE (index)))
- exp = index;
+ == TREE_UNSIGNED (TREE_TYPE (idx)))
+ exp = idx;
}
expand_start_case
@@ -7572,18 +7450,31 @@ c_expand_start_case (exp)
return exp;
}
-/* CONSTP remembers whether or not all the intervening pointers in the `to'
- type have been const. */
-int
+/* Returns non-zero if the pointer-type FROM can be converted to the
+ pointer-type TO via a qualification conversion. If CONSTP is -1,
+ then we return non-zero if the pointers are similar, and the
+ cv-qualification signature of FROM is a proper subset of that of TO.
+
+ If CONSTP is positive, then all outer pointers have been
+ const-qualified. */
+
+static int
comp_ptr_ttypes_real (to, from, constp)
tree to, from;
int constp;
{
+ int to_more_cv_qualified = 0;
+
for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
{
if (TREE_CODE (to) != TREE_CODE (from))
return 0;
+ if (TREE_CODE (from) == OFFSET_TYPE
+ && comptypes (TYPE_OFFSET_BASETYPE (from),
+ TYPE_OFFSET_BASETYPE (to), 1))
+ continue;
+
/* 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)
@@ -7592,24 +7483,115 @@ comp_ptr_ttypes_real (to, from, constp)
|| 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 (TYPE_READONLY (to) > TYPE_READONLY (from)
+ || TYPE_VOLATILE (to) > TYPE_VOLATILE (from))
+ {
+ if (constp == 0)
+ return 0;
+ else
+ ++to_more_cv_qualified;
+ }
+
+ if (constp > 0)
+ constp &= TYPE_READONLY (to);
}
if (TREE_CODE (to) != POINTER_TYPE)
- return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1);
+ return
+ comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1)
+ && (constp >= 0 || to_more_cv_qualified);
}
}
/* When comparing, say, char ** to char const **, this function takes the
'char *' and 'char const *'. Do not pass non-pointer types to this
function. */
+
int
comp_ptr_ttypes (to, from)
tree to, from;
{
return comp_ptr_ttypes_real (to, from, 1);
}
+
+/* Returns 1 if to and from are (possibly multi-level) pointers to the same
+ type or inheritance-related types, regardless of cv-quals. */
+
+int
+ptr_reasonably_similar (to, from)
+ tree to, from;
+{
+ for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
+ {
+ if (TREE_CODE (to) != TREE_CODE (from))
+ return 0;
+
+ if (TREE_CODE (from) == OFFSET_TYPE
+ && comptypes (TYPE_OFFSET_BASETYPE (to),
+ TYPE_OFFSET_BASETYPE (from), -1))
+ continue;
+
+ if (TREE_CODE (to) != POINTER_TYPE)
+ return comptypes
+ (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), -1);
+ }
+}
+
+/* Like comp_ptr_ttypes, for const_cast. */
+
+static int
+comp_ptr_ttypes_const (to, from)
+ tree to, from;
+{
+ for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
+ {
+ if (TREE_CODE (to) != TREE_CODE (from))
+ return 0;
+
+ if (TREE_CODE (from) == OFFSET_TYPE
+ && comptypes (TYPE_OFFSET_BASETYPE (from),
+ TYPE_OFFSET_BASETYPE (to), 1))
+ continue;
+
+ if (TREE_CODE (to) != POINTER_TYPE)
+ return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1);
+ }
+}
+
+/* Like comp_ptr_ttypes, for reinterpret_cast. */
+
+static int
+comp_ptr_ttypes_reinterpret (to, from)
+ tree to, from;
+{
+ int constp = 1;
+
+ for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
+ {
+ if (TREE_CODE (from) == OFFSET_TYPE)
+ from = TREE_TYPE (from);
+ if (TREE_CODE (to) == OFFSET_TYPE)
+ to = TREE_TYPE (to);
+
+ if (TREE_CODE (to) != TREE_CODE (from))
+ return 1;
+
+ /* 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 (TREE_CODE (to) != POINTER_TYPE)
+ return 1;
+ }
+}
diff --git a/contrib/gcc/cp/typeck2.c b/contrib/gcc/cp/typeck2.c
index 653d6a5..39b0626 100644
--- a/contrib/gcc/cp/typeck2.c
+++ b/contrib/gcc/cp/typeck2.c
@@ -31,19 +31,20 @@ Boston, MA 02111-1307, USA. */
like a strange sort of assignment). */
#include "config.h"
-#include <stdio.h>
+#include "system.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
+#include "toplev.h"
-static tree process_init_constructor ();
-extern void pedwarn (), error ();
+static tree process_init_constructor PROTO((tree, tree, tree *));
extern int errorcount;
extern int sorrycount;
/* Print an error message stemming from an attempt to use
BASETYPE as a base class for TYPE. */
+
tree
error_not_base_type (basetype, type)
tree basetype, type;
@@ -71,33 +72,11 @@ binfo_or_else (parent_or_type, type)
return NULL_TREE;
}
-/* Print an error message stemming from an invalid use of an
- aggregate type.
-
- TYPE is the type or binfo which draws the error.
- MSG is the message to print.
- ARG is an optional argument which may provide more information. */
-void
-error_with_aggr_type (type, msg, arg)
- tree type;
- char *msg;
- HOST_WIDE_INT arg;
-{
- tree name;
-
- if (TREE_CODE (type) == TREE_VEC)
- type = BINFO_TYPE (type);
-
- name = TYPE_NAME (type);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- error (msg, IDENTIFIER_POINTER (name), arg);
-}
-
/* According to ARM $7.1.6, "A `const' object may be initialized, but its
value may not be changed thereafter. Thus, we emit hard errors for these,
rather than just pedwarns. If `SOFT' is 1, then we just pedwarn. (For
example, conversions to references.) */
+
void
readonly_error (arg, string, soft)
tree arg;
@@ -108,52 +87,73 @@ readonly_error (arg, string, soft)
void (*fn)();
if (soft)
- fn = pedwarn;
+ fn = cp_pedwarn;
else
- fn = error;
+ fn = cp_error;
if (TREE_CODE (arg) == COMPONENT_REF)
{
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
- fmt = "%s of member `%s' in read-only structure";
+ fmt = "%s of member `%D' in read-only structure";
else
- fmt = "%s of read-only member `%s'";
- (*fn) (fmt, string, lang_printable_name (TREE_OPERAND (arg, 1)));
+ fmt = "%s of read-only member `%D'";
+ (*fn) (fmt, string, TREE_OPERAND (arg, 1));
}
else if (TREE_CODE (arg) == VAR_DECL)
{
if (DECL_LANG_SPECIFIC (arg)
&& DECL_IN_AGGR_P (arg)
&& !TREE_STATIC (arg))
- fmt = "%s of constant field `%s'";
+ fmt = "%s of constant field `%D'";
else
- fmt = "%s of read-only variable `%s'";
- (*fn) (fmt, string, lang_printable_name (arg));
+ fmt = "%s of read-only variable `%D'";
+ (*fn) (fmt, string, arg);
}
else if (TREE_CODE (arg) == PARM_DECL)
- (*fn) ("%s of read-only parameter `%s'", string,
- lang_printable_name (arg));
+ (*fn) ("%s of read-only parameter `%D'", string, arg);
else if (TREE_CODE (arg) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE
&& (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL
|| TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL))
- (*fn) ("%s of read-only reference `%s'",
- string, lang_printable_name (TREE_OPERAND (arg, 0)));
+ (*fn) ("%s of read-only reference `%D'", string, TREE_OPERAND (arg, 0));
else if (TREE_CODE (arg) == RESULT_DECL)
- (*fn) ("%s of read-only named return value `%s'",
- string, lang_printable_name (arg));
+ (*fn) ("%s of read-only named return value `%D'", string, arg);
else
(*fn) ("%s of read-only location", string);
}
/* Print an error message for invalid use of a type which declares
virtual functions which are not inheritable. */
+
void
abstract_virtuals_error (decl, type)
tree decl;
tree type;
{
tree u = CLASSTYPE_ABSTRACT_VIRTUALS (type);
+ int has_abstract_virtuals, needs_final_overriders;
+ tree tu;
+
+ /* Count how many abstract methods need to be defined. */
+ for (has_abstract_virtuals = 0, tu = u; tu; tu = TREE_CHAIN (tu))
+ {
+ if (DECL_ABSTRACT_VIRTUAL_P (TREE_VALUE (tu))
+ && ! DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
+ {
+ has_abstract_virtuals = 1;
+ break;
+ }
+ }
+
+ /* Count how many virtual methods need a final overrider. */
+ for (needs_final_overriders = 0, tu = u; tu; tu = TREE_CHAIN (tu))
+ {
+ if (DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
+ {
+ needs_final_overriders = 1;
+ break;
+ }
+ }
if (decl)
{
@@ -175,24 +175,58 @@ abstract_virtuals_error (decl, type)
else if (TREE_CODE (decl) == FUNCTION_DECL)
cp_error ("invalid return type for function `%#D'", decl);
}
- else cp_error ("cannot allocate an object of type `%T'", type);
+ else
+ cp_error ("cannot allocate an object of type `%T'", type);
+
/* Only go through this once. */
if (TREE_PURPOSE (u) == NULL_TREE)
{
- error (" since the following virtual functions are abstract:");
TREE_PURPOSE (u) = error_mark_node;
- while (u)
+
+ if (has_abstract_virtuals)
+ error (" since the following virtual functions are abstract:");
+ tu = u;
+ while (tu)
+ {
+ if (DECL_ABSTRACT_VIRTUAL_P (TREE_VALUE (tu))
+ && ! DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
+ cp_error ("\t%#D", TREE_VALUE (tu));
+ tu = TREE_CHAIN (tu);
+ }
+
+ if (needs_final_overriders)
+ {
+ if (has_abstract_virtuals)
+ error (" and the following virtual functions need a final overrider:");
+ else
+ error (" since the following virtual functions need a final overrider:");
+ }
+ tu = u;
+ while (tu)
+ {
+ if (DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
+ cp_error ("\t%#D", TREE_VALUE (tu));
+ tu = TREE_CHAIN (tu);
+ }
+ }
+ else
+ {
+ if (has_abstract_virtuals)
{
- cp_error ("\t%#D", TREE_VALUE (u));
- u = TREE_CHAIN (u);
+ if (needs_final_overriders)
+ cp_error (" since type `%T' has abstract virtual functions and must override virtual functions", type);
+ else
+ cp_error (" since type `%T' has abstract virtual functions", type);
}
+ else
+ cp_error (" since type `%T' must override virtual functions", type);
}
- else cp_error (" since type `%T' has abstract virtual functions", type);
}
/* Print an error message for invalid use of a signature type.
Signatures are treated similar to abstract classes here, they
cannot be instantiated. */
+
void
signature_error (decl, type)
tree decl;
@@ -231,7 +265,7 @@ incomplete_type_error (value, type)
tree value;
tree type;
{
- char *errmsg;
+ char *errmsg = 0;
/* Avoid duplicate error message. */
if (TREE_CODE (type) == ERROR_MARK)
@@ -239,8 +273,7 @@ incomplete_type_error (value, type)
if (value != 0 && (TREE_CODE (value) == VAR_DECL
|| TREE_CODE (value) == PARM_DECL))
- error ("`%s' has an incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (value)));
+ cp_error ("`%D' has incomplete type", value);
else
{
retry:
@@ -249,15 +282,9 @@ incomplete_type_error (value, type)
switch (TREE_CODE (type))
{
case RECORD_TYPE:
- errmsg = "invalid use of undefined type `struct %s'";
- break;
-
case UNION_TYPE:
- errmsg = "invalid use of undefined type `union %s'";
- break;
-
case ENUMERAL_TYPE:
- errmsg = "invalid use of undefined type `enum %s'";
+ errmsg = "invalid use of undefined type `%#T'";
break;
case VOID_TYPE:
@@ -277,15 +304,20 @@ incomplete_type_error (value, type)
error ("invalid use of member type (did you forget the `&' ?)");
return;
+ case TEMPLATE_TYPE_PARM:
+ error ("invalid use of template type parameter");
+ return;
+
default:
my_friendly_abort (108);
}
- error_with_aggr_type (type, errmsg);
+ cp_error (errmsg, type);
}
}
/* Like error(), but don't call report_error_function(). */
+
static void
ack (s, v, v2)
char *s;
@@ -330,7 +362,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
-/* First used: 0 (reserved), Last used: 366. Free: */
+/* First used: 0 (reserved), Last used: 369. Free: */
static int abortcount = 0;
@@ -351,7 +383,8 @@ my_friendly_abort (i)
ack ("Internal compiler error.");
else
ack ("Internal compiler error %d.", i);
- ack ("Please submit a full bug report to `bug-g++@prep.ai.mit.edu'.");
+ ack ("Please submit a full bug report to `egcs-bugs@egcs.cygnus.com'.");
+ ack ("See <URL:http://egcs.cygnus.com/faq.html#bugreport> for details.");
}
else
error ("confused by earlier errors, bailing out");
@@ -365,7 +398,8 @@ my_friendly_abort (i)
else
error ("Internal compiler error %d.", i);
- fatal ("Please submit a full bug report to `bug-g++@prep.ai.mit.edu'.");
+ error ("Please submit a full bug report to `egcs-bugs@egcs.cygnus.com'.");
+ fatal ("See <URL:http://egcs.cygnus.com/faq.html#bugreport> for details.");
}
void
@@ -417,8 +451,8 @@ initializer_constant_valid_p (value, endtype)
case CONVERT_EXPR:
case NOP_EXPR:
/* Allow conversions between pointer types. */
- if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE)
+ if (POINTER_TYPE_P (TREE_TYPE (value))
+ && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
/* Allow conversions between real types. */
@@ -453,13 +487,18 @@ initializer_constant_valid_p (value, endtype)
return initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
- /* Likewise conversions from int to pointers. */
+ /* Likewise conversions from int to pointers, but also allow
+ conversions from 0. */
if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
- && (TYPE_PRECISION (TREE_TYPE (value))
- <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
- return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
+ {
+ if (integer_zerop (TREE_OPERAND (value, 0)))
+ return null_pointer_node;
+ else if (TYPE_PRECISION (TREE_TYPE (value))
+ <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))
+ return initializer_constant_valid_p (TREE_OPERAND (value, 0),
+ endtype);
+ }
/* Allow conversions to union types if the value inside is okay. */
if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
@@ -468,8 +507,8 @@ initializer_constant_valid_p (value, endtype)
return 0;
case PLUS_EXPR:
- if (TREE_CODE (endtype) == INTEGER_TYPE
- && TYPE_PRECISION (endtype) < POINTER_SIZE)
+ if ((TREE_CODE (endtype) == INTEGER_TYPE)
+ && (TYPE_PRECISION (endtype) < POINTER_SIZE))
return 0;
{
tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
@@ -485,8 +524,8 @@ initializer_constant_valid_p (value, endtype)
}
case MINUS_EXPR:
- if (TREE_CODE (endtype) == INTEGER_TYPE
- && TYPE_PRECISION (endtype) < POINTER_SIZE)
+ if ((TREE_CODE (endtype) == INTEGER_TYPE)
+ && (TYPE_PRECISION (endtype) < POINTER_SIZE))
return 0;
{
tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
@@ -502,6 +541,9 @@ initializer_constant_valid_p (value, endtype)
return null_pointer_node;
return 0;
}
+
+ default:
+ break;
}
return 0;
@@ -569,8 +611,6 @@ store_init_value (decl, init)
if (TREE_CODE (init) == CONSTRUCTOR)
{
tree field;
- tree funcs;
- int func;
/* Check that we're really an aggregate as ARM 8.4.1 defines it. */
if (CLASSTYPE_N_BASECLASSES (type))
@@ -588,16 +628,11 @@ store_init_value (decl, init)
cp_error_at ("initializer list construction invalid for `%D'", decl);
cp_error_at ("due to non-public access of member `%D'", field);
}
- funcs = TYPE_METHODS (type);
- if (funcs)
- for (func = 0; func < TREE_VEC_LENGTH (funcs); func++)
+ for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field))
+ if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
{
- field = TREE_VEC_ELT (funcs, func);
- if (field && (TREE_PRIVATE (field) || TREE_PROTECTED (field)))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- cp_error_at ("due to non-public access of member `%D'", field);
- }
+ cp_error_at ("initializer list construction invalid for `%D'", decl);
+ cp_error_at ("due to non-public access of member `%D'", field);
}
}
#endif
@@ -652,6 +687,11 @@ store_init_value (decl, init)
if (TREE_CODE (value) == ERROR_MARK)
;
+ /* Other code expects that initializers for objects of types that need
+ constructing never make it into DECL_INITIAL, and passes 'init' to
+ expand_aggr_init without checking DECL_INITIAL. So just return. */
+ else if (TYPE_NEEDS_CONSTRUCTING (type))
+ return value;
else if (TREE_STATIC (decl)
&& (! TREE_CONSTANT (value)
|| ! initializer_constant_valid_p (value, TREE_TYPE (value))
@@ -660,7 +700,7 @@ store_init_value (decl, init)
run time inited when doing pic. (mrs) */
/* Since ctors and dtors are the only things that can
reference vtables, and they are always written down
- the the vtable definition, we can leave the
+ the vtable definition, we can leave the
vtables in initialized data space.
However, other initialized data cannot be initialized
this way. Instead a global file-level initializer
@@ -705,7 +745,7 @@ digest_init (type, init, tail)
{
enum tree_code code = TREE_CODE (type);
tree element = NULL_TREE;
- tree old_tail_contents;
+ tree old_tail_contents = NULL_TREE;
/* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR
tree node which has no TREE_TYPE. */
int raw_constructor;
@@ -727,24 +767,9 @@ digest_init (type, init, tail)
if (TREE_CODE (init) == NON_LVALUE_EXPR)
init = TREE_OPERAND (init, 0);
- if (init && TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (type))
- init = default_conversion (init);
-
- if (init && TYPE_PTRMEMFUNC_P (type)
- && ((TREE_CODE (init) == ADDR_EXPR
- && ((TREE_CODE (TREE_TYPE (init)) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_TYPE (init))) == METHOD_TYPE)
- || TREE_CODE (TREE_OPERAND (init, 0)) == TREE_LIST))
- || TREE_CODE (init) == TREE_LIST
- || integer_zerop (init)
- || (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))))
- {
- return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), init, 0);
- }
-
raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
- if (init && raw_constructor
+ if (raw_constructor
&& CONSTRUCTOR_ELTS (init) != 0
&& TREE_CHAIN (CONSTRUCTOR_ELTS (init)) == 0)
{
@@ -756,44 +781,20 @@ digest_init (type, init, tail)
return element;
}
- /* Any type can be initialized from an expression of the same type,
- optionally with braces. */
-
- if (init && TREE_TYPE (init)
- && (TYPE_MAIN_VARIANT (TREE_TYPE (init)) == type
- || (code == ARRAY_TYPE && comptypes (TREE_TYPE (init), type, 1))))
- {
- if (pedantic && code == ARRAY_TYPE
- && TREE_CODE (init) != STRING_CST)
- pedwarn ("ANSI C++ forbids initializing array from array expression");
- if (TREE_CODE (init) == CONST_DECL)
- init = DECL_INITIAL (init);
- else if (TREE_READONLY_DECL_P (init))
- init = decl_constant_value (init);
- return init;
- }
-
- if (element && (TREE_TYPE (element) == type
- || (code == ARRAY_TYPE && TREE_TYPE (element)
- && comptypes (TREE_TYPE (element), type, 1))))
- {
- if (pedantic && code == ARRAY_TYPE)
- pedwarn ("ANSI C++ forbids initializing array from array expression");
- if (pedantic && (code == RECORD_TYPE || code == UNION_TYPE))
- pedwarn ("ANSI C++ forbids single nonscalar initializer with braces");
- if (TREE_CODE (element) == CONST_DECL)
- element = DECL_INITIAL (element);
- else if (TREE_READONLY_DECL_P (element))
- element = decl_constant_value (element);
- return element;
- }
-
/* Initialization of an array of chars from a string constant
optionally enclosed in braces. */
if (code == ARRAY_TYPE)
{
- tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+ tree typ1;
+
+ if (TREE_CODE (init) == TREE_LIST)
+ {
+ error ("initializing array with parameter list");
+ return error_mark_node;
+ }
+
+ typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
if ((typ1 == char_type_node
|| typ1 == signed_char_type_node
|| typ1 == unsigned_char_type_node
@@ -819,11 +820,6 @@ digest_init (type, init, tail)
return error_mark_node;
}
- if (pedantic
- && typ1 != char_type_node
- && typ1 != signed_char_type_node
- && typ1 != unsigned_char_type_node)
- pedwarn ("ANSI C++ forbids string initializer except for `char' elements");
TREE_TYPE (string) = type;
if (TYPE_DOMAIN (type) != 0
&& TREE_CONSTANT (TYPE_SIZE (type)))
@@ -847,7 +843,8 @@ digest_init (type, init, tail)
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
|| code == ENUMERAL_TYPE || code == REFERENCE_TYPE
- || code == BOOLEAN_TYPE
+ || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
+ || TYPE_PTRMEMFUNC_P (type)
|| (code == RECORD_TYPE && ! raw_constructor
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))))
{
@@ -860,7 +857,7 @@ digest_init (type, init, tail)
}
init = element;
}
- while (TREE_CODE (init) == CONSTRUCTOR)
+ while (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
{
cp_pedwarn ("braces around scalar initializer for `%T'", type);
init = CONSTRUCTOR_ELTS (init);
@@ -892,27 +889,25 @@ digest_init (type, init, tail)
}
else if (raw_constructor)
return process_init_constructor (type, init, (tree *)0);
- 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
- INIT to TYPE. We will let `expand_vec_init' do it. */
- return init;
- }
+ else if (can_convert_arg (type, TREE_TYPE (init), init)
+ || TYPE_NON_AGGREGATE_CLASS (type))
+ /* These are never initialized from multiple constructor elements. */;
else if (tail != 0)
{
*tail = old_tail_contents;
return process_init_constructor (type, 0, tail);
}
- else if (flag_traditional)
- /* Traditionally one can say `char x[100] = 0;'. */
- return process_init_constructor (type,
- build_nt (CONSTRUCTOR, 0,
- tree_cons (0, init, 0)),
- 0);
+
if (code != ARRAY_TYPE)
- return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
- "initialization", NULL_TREE, 0);
+ {
+ int flags = LOOKUP_NORMAL;
+ /* Initialization from { } is copy-initialization. */
+ if (tail)
+ flags |= LOOKUP_ONLYCONVERTING;
+
+ return convert_for_initialization (NULL_TREE, type, init, flags,
+ "initialization", NULL_TREE, 0);
+ }
}
error ("invalid initializer");
@@ -980,10 +975,15 @@ process_init_constructor (type, init, elts)
{
register tree next1;
+ if (TREE_PURPOSE (tail)
+ && (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST
+ || TREE_INT_CST_LOW (TREE_PURPOSE (tail)) != i))
+ sorry ("non-trivial labeled initializers");
+
if (TREE_VALUE (tail) != 0)
{
tree tail1 = tail;
- next1 = digest_init (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
+ next1 = digest_init (TREE_TYPE (type),
TREE_VALUE (tail), &tail1);
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))
&& TYPE_MAIN_VARIANT (TREE_TYPE (type)) != TYPE_MAIN_VARIANT (TREE_TYPE (next1)))
@@ -1014,7 +1014,7 @@ process_init_constructor (type, init, elts)
allconstant = 0;
else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
allsimple = 0;
- members = tree_cons (NULL_TREE, next1, members);
+ members = expr_tree_cons (NULL_TREE, next1, members);
}
}
if (TREE_CODE (type) == RECORD_TYPE)
@@ -1049,13 +1049,18 @@ process_init_constructor (type, init, elts)
if (! DECL_NAME (field))
{
- members = tree_cons (field, integer_zero_node, members);
+ members = expr_tree_cons (field, integer_zero_node, members);
continue;
}
if (TREE_CODE (field) != FIELD_DECL)
continue;
+ if (TREE_PURPOSE (tail)
+ && TREE_PURPOSE (tail) != field
+ && TREE_PURPOSE (tail) != DECL_NAME (field))
+ sorry ("non-trivial labeled initializers");
+
if (TREE_VALUE (tail) != 0)
{
tree tail1 = tail;
@@ -1078,7 +1083,7 @@ process_init_constructor (type, init, elts)
allconstant = 0;
else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
allsimple = 0;
- members = tree_cons (field, next1, members);
+ members = expr_tree_cons (field, next1, members);
}
for (; field; field = TREE_CHAIN (field))
{
@@ -1095,7 +1100,7 @@ process_init_constructor (type, init, elts)
allconstant = 0;
else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
allsimple = 0;
- members = tree_cons (field, next1, members);
+ members = expr_tree_cons (field, next1, members);
}
else if (TREE_READONLY (field))
error ("uninitialized const member `%s'",
@@ -1107,6 +1112,11 @@ process_init_constructor (type, init, elts)
else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
error ("member `%s' is uninitialized reference",
IDENTIFIER_POINTER (DECL_NAME (field)));
+ /* Warn when some struct elements are implicitly initialized
+ to zero. */
+ else if (extra_warnings)
+ warning ("missing initializer for member `%s'",
+ IDENTIFIER_POINTER (DECL_NAME (field)));
}
}
@@ -1117,7 +1127,8 @@ process_init_constructor (type, init, elts)
/* Find the first named field. ANSI decided in September 1990
that only named fields count here. */
- while (field && DECL_NAME (field) == 0)
+ while (field && (DECL_NAME (field) == 0
+ || TREE_CODE (field) != FIELD_DECL))
field = TREE_CHAIN (field);
/* If this element specifies a field, initialize via that field. */
@@ -1176,7 +1187,7 @@ process_init_constructor (type, init, elts)
allconstant = 0;
else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0)
allsimple = 0;
- members = tree_cons (field, next1, members);
+ members = expr_tree_cons (field, next1, members);
}
/* If arguments were specified as a list, just remove the ones we used. */
@@ -1200,7 +1211,7 @@ process_init_constructor (type, init, elts)
/* Given a structure or union value DATUM, construct and return
the structure or union component which results from narrowing
- that value by the types specified in TYPES. For example, given the
+ that value by the type specified in BASETYPE. For example, given the
hierarchy
class L { int ii; };
@@ -1214,23 +1225,14 @@ process_init_constructor (type, init, elts)
then the expression
- x::C::A::L::ii refers to the ii member of the L part of
- of A part of the C object named by X. In this case,
- DATUM would be x, and TYPES would be a SCOPE_REF consisting of
-
- SCOPE_REF
- SCOPE_REF
- C A
- L
-
- The last entry in the SCOPE_REF is always an IDENTIFIER_NODE.
-
-*/
+ x.A::ii refers to the ii member of the L part of
+ the A part of the C object named by X. In this case,
+ DATUM would be x, and BASETYPE would be A. */
tree
-build_scoped_ref (datum, types)
+build_scoped_ref (datum, basetype)
tree datum;
- tree types;
+ tree basetype;
{
tree ref;
tree type = TREE_TYPE (datum);
@@ -1243,62 +1245,17 @@ build_scoped_ref (datum, types)
type = TYPE_MAIN_VARIANT (type);
- if (TREE_CODE (types) == SCOPE_REF)
- {
- /* We have some work to do. */
- struct type_chain
- { tree type; struct type_chain *next; }
- *chain = NULL, *head = NULL, scratch;
- ref = build_unary_op (ADDR_EXPR, datum, 0);
- while (TREE_CODE (types) == SCOPE_REF)
- {
- tree t = TREE_OPERAND (types, 1);
- if (is_aggr_typedef (t, 1))
- {
- head = (struct type_chain *)alloca (sizeof (struct type_chain));
- head->type = IDENTIFIER_TYPE_VALUE (t);
- head->next = chain;
- chain = head;
- types = TREE_OPERAND (types, 0);
- }
- else return error_mark_node;
- }
- if (! is_aggr_typedef (types, 1))
- return error_mark_node;
-
- head = &scratch;
- head->type = IDENTIFIER_TYPE_VALUE (types);
- head->next = chain;
- chain = head;
- while (chain)
- {
- tree binfo = chain->type;
- type = TREE_TYPE (TREE_TYPE (ref));
- if (binfo != TYPE_BINFO (type))
- {
- binfo = get_binfo (binfo, type, 1);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (binfo == 0)
- return error_not_base_type (chain->type, type);
- ref = convert_pointer_to (binfo, ref);
- }
- chain = chain->next;
- }
- return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
- }
-
/* This is an easy conversion. */
- if (is_aggr_typedef (types, 1))
+ if (is_aggr_type (basetype, 1))
{
- tree binfo = TYPE_BINFO (IDENTIFIER_TYPE_VALUE (types));
+ tree binfo = TYPE_BINFO (basetype);
if (binfo != TYPE_BINFO (type))
{
binfo = get_binfo (binfo, type, 1);
if (binfo == error_mark_node)
return error_mark_node;
if (binfo == 0)
- return error_not_base_type (IDENTIFIER_TYPE_VALUE (types), type);
+ return error_not_base_type (basetype, type);
}
switch (TREE_CODE (datum))
@@ -1328,6 +1285,7 @@ build_scoped_ref (datum, types)
performed until an object which does not have the `->' operator
overloaded is found. An error is reported when circular pointer
delegation is detected. */
+
tree
build_x_arrow (datum)
tree datum;
@@ -1335,11 +1293,14 @@ build_x_arrow (datum)
tree types_memoized = NULL_TREE;
register tree rval = datum;
tree type = TREE_TYPE (rval);
- tree last_rval;
+ tree last_rval = NULL_TREE;
if (type == error_mark_node)
return error_mark_node;
+ if (processing_template_decl)
+ return build_min_nt (ARROW_EXPR, rval);
+
if (TREE_CODE (rval) == OFFSET_REF)
{
rval = resolve_offset_ref (datum);
@@ -1352,9 +1313,10 @@ build_x_arrow (datum)
type = TREE_TYPE (rval);
}
- if (IS_AGGR_TYPE (type) && TYPE_OVERLOADS_ARROW (type))
+ if (IS_AGGR_TYPE (type))
{
- while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval, NULL_TREE, NULL_TREE)))
+ while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval,
+ NULL_TREE, NULL_TREE)))
{
if (rval == error_mark_node)
return error_mark_node;
@@ -1371,6 +1333,13 @@ build_x_arrow (datum)
}
last_rval = rval;
}
+
+ if (last_rval == NULL_TREE)
+ {
+ cp_error ("base operand of `->' has non-pointer type `%T'", type);
+ return error_mark_node;
+ }
+
if (TREE_CODE (TREE_TYPE (last_rval)) == REFERENCE_TYPE)
last_rval = convert_from_reference (last_rval);
}
@@ -1403,6 +1372,7 @@ build_x_arrow (datum)
As a special case, if there is only one method by that name,
it is returned. Otherwise we return an expression which other
routines will have to know how to deal with later. */
+
tree
build_m_component_ref (datum, component)
tree datum, component;
@@ -1412,6 +1382,9 @@ build_m_component_ref (datum, component)
tree rettype;
tree binfo;
+ if (processing_template_decl)
+ return build_min_nt (DOTSTAR_EXPR, datum, component);
+
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component)))
{
type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (component)));
@@ -1421,7 +1394,7 @@ build_m_component_ref (datum, component)
{
component = build_indirect_ref (component, NULL_PTR);
type = TREE_TYPE (component);
- rettype = TREE_TYPE (TREE_TYPE (component));
+ rettype = TREE_TYPE (type);
}
if (datum == error_mark_node || component == error_mark_node)
@@ -1454,14 +1427,14 @@ build_m_component_ref (datum, component)
else if (binfo == error_mark_node)
return error_mark_node;
- return build (OFFSET_REF, rettype, datum, component);
+ component = build (OFFSET_REF, rettype, datum, component);
+ if (TREE_CODE (type) == OFFSET_TYPE)
+ component = resolve_offset_ref (component);
+ return component;
}
-/* Return a tree node for the expression TYPENAME '(' PARMS ')'.
+/* Return a tree node for the expression TYPENAME '(' PARMS ')'. */
- Because we cannot tell whether this construct is really a call to a
- constructor or a request for a type conversion, we try both, and
- report any ambiguities we find. */
tree
build_functional_cast (exp, parms)
tree exp;
@@ -1469,16 +1442,13 @@ build_functional_cast (exp, parms)
{
/* This is either a call to a constructor,
or a C cast in C++'s `functional' notation. */
- tree type, name = NULL_TREE;
- tree expr_as_ctor = NULL_TREE;
+ tree type;
if (exp == error_mark_node || parms == error_mark_node)
return error_mark_node;
if (TREE_CODE (exp) == IDENTIFIER_NODE)
{
- name = exp;
-
if (IDENTIFIER_HAS_TYPE_VALUE (exp))
/* Either an enum or an aggregate type. */
type = IDENTIFIER_TYPE_VALUE (exp);
@@ -1487,35 +1457,26 @@ build_functional_cast (exp, parms)
type = lookup_name (exp, 1);
if (!type || TREE_CODE (type) != TYPE_DECL)
{
- cp_error ("`%T' fails to be a typedef or built-in type", name);
+ cp_error ("`%T' fails to be a typedef or built-in type", exp);
return error_mark_node;
}
type = TREE_TYPE (type);
}
}
+ else if (TREE_CODE (exp) == TYPE_DECL)
+ type = TREE_TYPE (exp);
else
type = exp;
+ if (processing_template_decl)
+ return build_min (CAST_EXPR, type, parms);
+
if (IS_SIGNATURE (type))
{
error ("signature type not allowed in cast or constructor expression");
return error_mark_node;
}
- /* Prepare to evaluate as a call to a constructor. If this expression
- is actually used, for example,
-
- return X (arg1, arg2, ...);
-
- then the slot being initialized will be filled in. */
-
- if (name == NULL_TREE)
- {
- name = TYPE_NAME (type);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NESTED_TYPENAME (name);
- }
-
if (! IS_AGGR_TYPE (type))
{
/* this must build a C cast */
@@ -1528,29 +1489,46 @@ build_functional_cast (exp, parms)
parms = build_compound_expr (parms);
}
- return build_c_cast (type, parms, 1);
+ return build_c_cast (type, parms);
}
- if (TYPE_SIZE (type) == NULL_TREE)
+ /* Prepare to evaluate as a call to a constructor. If this expression
+ is actually used, for example,
+
+ return X (arg1, arg2, ...);
+
+ then the slot being initialized will be filled in. */
+
+ if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
{
cp_error ("type `%T' is not yet defined", type);
return error_mark_node;
}
if (parms && TREE_CHAIN (parms) == NULL_TREE)
- return build_c_cast (type, parms, 1);
+ return build_c_cast (type, TREE_VALUE (parms));
- expr_as_ctor = build_method_call (NULL_TREE, name, parms,
- NULL_TREE, LOOKUP_NORMAL);
+ /* We need to zero-initialize POD types. Let's do that for everything
+ that doesn't need a constructor. */
+ if (parms == NULL_TREE && !TYPE_NEEDS_CONSTRUCTING (type)
+ && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+ {
+ exp = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ return get_target_expr (exp);
+ }
- if (expr_as_ctor == error_mark_node)
+ exp = build_method_call (NULL_TREE, ctor_identifier, parms,
+ TYPE_BINFO (type), LOOKUP_NORMAL);
+
+ if (exp == error_mark_node)
return error_mark_node;
- return build_cplus_new (type, expr_as_ctor, 1);
+ return build_cplus_new (type, exp);
}
/* Return the character string for the name that encodes the
enumeral value VALUE in the domain TYPE. */
+
char *
enum_name_string (value, type)
tree value;
@@ -1568,8 +1546,8 @@ enum_name_string (value, type)
char *buf = (char *)oballoc (16 + TYPE_NAME_LENGTH (type));
/* Value must have been cast. */
- sprintf (buf, "(enum %s)%d",
- TYPE_NAME_STRING (type), intval);
+ sprintf (buf, "(enum %s)%ld",
+ TYPE_NAME_STRING (type), (long) intval);
return buf;
}
return IDENTIFIER_POINTER (TREE_PURPOSE (values));
@@ -1582,6 +1560,7 @@ enum_name_string (value, type)
TYPE is the type of the switch index expression.
NEW is the new value that we were trying to add.
OLD is the old value that stopped us from adding it. */
+
void
report_case_error (code, type, new_value, old_value)
int code;
@@ -1679,3 +1658,12 @@ report_case_error (code, type, new_value, old_value)
}
}
#endif
+
+void
+check_for_new_type (string, inptree)
+ char *string;
+ flagged_type_tree inptree;
+{
+ if (pedantic && inptree.new_type_flag)
+ pedwarn ("ANSI C++ forbids defining types within %s",string);
+}
diff --git a/contrib/gcc/cp/xref.c b/contrib/gcc/cp/xref.c
index ec4b174..14915d6 100644
--- a/contrib/gcc/cp/xref.c
+++ b/contrib/gcc/cp/xref.c
@@ -1,5 +1,5 @@
/* Code for handling XREF output from GNU C++.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-97, 1998 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -21,17 +21,13 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include "system.h"
#include "tree.h"
-#include <stdio.h>
#include "cp-tree.h"
#include "input.h"
+#include "toplev.h"
-#include <ctype.h>
-
-extern char *getpwd ();
-
-extern char *index ();
-extern char *rindex ();
+extern char *getpwd PROTO((void));
/* The character(s) used to join a directory specification (obtained with
getwd or equivalent) with a non-absolute file name. */
@@ -61,9 +57,6 @@ int flag_gnu_xref;
#ifndef FALSE
#define FALSE 0
#endif
-#ifndef NULL
-#define NULL 0
-#endif
#define PALLOC(typ) ((typ *) calloc(1,sizeof(typ)))
@@ -128,30 +121,14 @@ static tree last_fndecl = NULL;
/* Forward definitions */
/* */
/************************************************************************/
-
-extern void GNU_xref_begin();
-extern void GNU_xref_end();
-extern void GNU_xref_file();
-extern void GNU_xref_start_scope();
-extern void GNU_xref_end_scope();
-extern void GNU_xref_ref();
-extern void GNU_xref_decl();
-extern void GNU_xref_call();
-extern void GNU_xref_function();
-extern void GNU_xref_assign();
-extern void GNU_xref_hier();
-extern void GNU_xref_member();
-
-static void gen_assign();
-static XREF_FILE find_file();
-static char * filename();
-static char * fctname();
-static char * declname();
-static void simplify_type();
-static char * fixname();
-static void open_xref_file();
-
-extern char * type_as_string();
+static void gen_assign PROTO((XREF_FILE, tree));
+static XREF_FILE find_file PROTO((char *));
+static char * filename PROTO((XREF_FILE));
+static char * fctname PROTO((tree));
+static char * declname PROTO((tree));
+static void simplify_type PROTO((char *));
+static char * fixname PROTO((char *, char *));
+static void open_xref_file PROTO((char *));
/* Start cross referencing. FILE is the name of the file we xref. */
@@ -183,7 +160,7 @@ GNU_xref_end (ect)
if (xf == NULL) return;
while (cur_scope != NULL)
- GNU_xref_end_scope(cur_scope->gid,0,0,0,0);
+ GNU_xref_end_scope(cur_scope->gid,0,0,0);
doing_xref = 0;
@@ -275,10 +252,10 @@ GNU_xref_start_scope (id)
TRNS is ??? */
void
-GNU_xref_end_scope (id,inid,prm,keep,trns)
+GNU_xref_end_scope (id,inid,prm,keep)
HOST_WIDE_INT id;
HOST_WIDE_INT inid;
- int prm,keep,trns;
+ int prm,keep;
{
XREF_FILE xf;
XREF_SCOPE xs,lxs,oxs;
@@ -309,8 +286,10 @@ GNU_xref_end_scope (id,inid,prm,keep,trns)
else if (keep == 2 || inid != 0) stype = "INTERN";
else stype = "EXTERN";
- fprintf (xref_file,"SCP %s %d %d %d %d %s\n",
- filename (xf), xs->start, lineno,xs->lid, inid, stype);
+ fprintf (xref_file, "SCP %s %d %d %d ",
+ filename (xf), xs->start, lineno,xs->lid);
+ fprintf (xref_file, HOST_WIDE_INT_PRINT_DEC, inid);
+ fprintf (xref_file, " %s\n", stype);
if (lxs == NULL) cur_scope = xs->outer;
else lxs->outer = xs->outer;
@@ -343,7 +322,7 @@ GNU_xref_decl (fndecl,decl)
tree decl;
{
XREF_FILE xf,xf1;
- char *cls;
+ char *cls = 0;
char *name;
char buf[10240];
int uselin;
@@ -400,7 +379,7 @@ GNU_xref_decl (fndecl,decl)
}
else if (TREE_CODE (decl) == TEMPLATE_DECL)
{
- if (DECL_TEMPLATE_IS_CLASS (decl))
+ if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
cls = "CLASSTEMP";
else if (TREE_CODE (DECL_RESULT (decl)) == FUNCTION_DECL)
cls = "FUNCTEMP";
@@ -562,6 +541,19 @@ gen_assign(xf, name)
fprintf(xref_file, "ASG %s %d %s\n", filename(xf), lineno, s);
}
+static char*
+classname (cls)
+ tree cls;
+{
+ if (cls && TREE_CODE_CLASS (TREE_CODE (cls)) == 't')
+ cls = TYPE_NAME (cls);
+ if (cls && TREE_CODE_CLASS (TREE_CODE (cls)) == 'd')
+ cls = DECL_NAME (cls);
+ if (cls && TREE_CODE (cls) == IDENTIFIER_NODE)
+ return IDENTIFIER_POINTER (cls);
+ return "?";
+}
+
/* Output cross-reference info about a class hierarchy.
CLS is the class type of interest. BASE is a baseclass
for CLS. PUB and VIRT give the access info about
@@ -569,10 +561,11 @@ gen_assign(xf, name)
of CLS.
??? Needs to handle nested classes. */
+
void
GNU_xref_hier(cls, base, pub, virt, frnd)
- char *cls;
- char *base;
+ tree cls;
+ tree base;
int pub;
int virt;
int frnd;
@@ -584,7 +577,8 @@ GNU_xref_hier(cls, base, pub, virt, frnd)
if (xf == NULL) return;
fprintf(xref_file, "HIE %s %d %s %s %d %d %d\n",
- filename(xf), lineno, cls, base, pub, virt, frnd);
+ filename(xf), lineno, classname (cls), classname (base),
+ pub, virt, frnd);
}
/* Output cross-reference info about class members. CLS
@@ -599,7 +593,9 @@ GNU_xref_member(cls, fld)
char *prot;
int confg, pure;
char *d;
+#ifdef XREF_SHORT_MEMBER_NAMES
int i;
+#endif
char buf[1024], bufa[1024];
if (!doing_xref) return;
@@ -621,8 +617,10 @@ GNU_xref_member(cls, fld)
pure = 1;
d = IDENTIFIER_POINTER(cls);
- sprintf(buf, "%d%s", strlen(d), d);
+ sprintf(buf, "%d%s", (int) strlen(d), d);
+#ifdef XREF_SHORT_MEMBER_NAMES
i = strlen(buf);
+#endif
strcpy(bufa, declname(fld));
#ifdef XREF_SHORT_MEMBER_NAMES
@@ -643,7 +641,7 @@ GNU_xref_member(cls, fld)
filename(xf), fld->decl.linenum, d, bufa, prot,
(TREE_CODE (fld) == FUNCTION_DECL ? 0 : 1),
(DECL_INLINE (fld) ? 1 : 0),
- (DECL_FRIEND_P(fld) ? 1 : 0),
+ (DECL_LANG_SPECIFIC(fld) && DECL_FRIEND_P(fld) ? 1 : 0),
(DECL_VINDEX(fld) ? 1 : 0),
(TREE_STATIC(fld) ? 1 : 0),
pure, confg);
@@ -733,7 +731,7 @@ simplify_type(typ)
int lvl, i;
i = strlen(typ);
- while (i > 0 && isspace(typ[i-1])) typ[--i] = 0;
+ while (i > 0 && ISSPACE(typ[i-1])) typ[--i] = 0;
if (i > 7 && STREQL(&typ[i-5], "const"))
{
OpenPOWER on IntegriCloud