summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp')
-rw-r--r--contrib/gcc/cp/ChangeLog6220
-rw-r--r--contrib/gcc/cp/Make-lang.in91
-rw-r--r--contrib/gcc/cp/Makefile.in89
-rw-r--r--contrib/gcc/cp/NEWS36
-rw-r--r--contrib/gcc/cp/call.c787
-rw-r--r--contrib/gcc/cp/class.c2956
-rw-r--r--contrib/gcc/cp/config-lang.in2
-rw-r--r--contrib/gcc/cp/cp-tree.def42
-rw-r--r--contrib/gcc/cp/cp-tree.h1241
-rw-r--r--contrib/gcc/cp/cvt.c233
-rw-r--r--contrib/gcc/cp/decl.c4733
-rw-r--r--contrib/gcc/cp/decl.h5
-rw-r--r--contrib/gcc/cp/decl2.c2516
-rw-r--r--contrib/gcc/cp/errfn.c166
-rw-r--r--contrib/gcc/cp/error.c529
-rw-r--r--contrib/gcc/cp/except.c204
-rw-r--r--contrib/gcc/cp/exception.cc35
-rw-r--r--contrib/gcc/cp/expr.c83
-rw-r--r--contrib/gcc/cp/friend.c294
-rw-r--r--contrib/gcc/cp/g++spec.c19
-rw-r--r--contrib/gcc/cp/gxx.gperf9
-rw-r--r--contrib/gcc/cp/gxxint.texi150
-rw-r--r--contrib/gcc/cp/inc/exception6
-rw-r--r--contrib/gcc/cp/inc/new6
-rw-r--r--contrib/gcc/cp/inc/new.h2
-rw-r--r--contrib/gcc/cp/inc/typeinfo8
-rw-r--r--contrib/gcc/cp/init.c1000
-rw-r--r--contrib/gcc/cp/input.c8
-rw-r--r--contrib/gcc/cp/lang-options.h43
-rw-r--r--contrib/gcc/cp/lang-specs.h31
-rw-r--r--contrib/gcc/cp/lex.c1182
-rw-r--r--contrib/gcc/cp/lex.h4
-rw-r--r--contrib/gcc/cp/method.c604
-rw-r--r--contrib/gcc/cp/new.cc2
-rw-r--r--contrib/gcc/cp/new1.cc2
-rw-r--r--contrib/gcc/cp/new2.cc2
-rw-r--r--contrib/gcc/cp/parse.y842
-rw-r--r--contrib/gcc/cp/pt.c7681
-rw-r--r--contrib/gcc/cp/ptree.c16
-rw-r--r--contrib/gcc/cp/repo.c22
-rw-r--r--contrib/gcc/cp/rtti.c167
-rw-r--r--contrib/gcc/cp/search.c3737
-rw-r--r--contrib/gcc/cp/semantics.c461
-rw-r--r--contrib/gcc/cp/sig.c161
-rw-r--r--contrib/gcc/cp/spew.c24
-rw-r--r--contrib/gcc/cp/tinfo.cc6
-rw-r--r--contrib/gcc/cp/tinfo.h4
-rw-r--r--contrib/gcc/cp/tinfo2.cc2
-rw-r--r--contrib/gcc/cp/tree.c1067
-rw-r--r--contrib/gcc/cp/typeck.c2266
-rw-r--r--contrib/gcc/cp/typeck2.c417
-rw-r--r--contrib/gcc/cp/xref.c69
52 files changed, 25222 insertions, 15060 deletions
diff --git a/contrib/gcc/cp/ChangeLog b/contrib/gcc/cp/ChangeLog
index 5102e32..82d1a8b 100644
--- a/contrib/gcc/cp/ChangeLog
+++ b/contrib/gcc/cp/ChangeLog
@@ -1,6 +1,1724 @@
-Sun Mar 14 02:38:07 PST 1999 Jeff Law (law@cygnus.com)
+Mon Aug 16 01:29:24 PDT 1999 Jeff Law (law@cygnus.com)
- * egcs-1.1.2 Released.
+ * gcc-2.95.1 Released.
+
+1999-08-12 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (lang_decode_option): Deprecate signatures.
+
+1999-08-11 Martin v. Loewis <martin@mira.isdn.cs.tu-berlin.de>
+
+ * lex.c (do_identifier): If we find a hidden type after a global
+ was selected already, continue using the global.
+
+1999-08-10 Martin v. Loewis <martin@mira.isdn.cs.tu-berlin.de>
+
+ * decl2.c (set_decl_namespace): Do not complain about non-matching
+ decls if processing a template.
+
+1999-08-09 Jason Merrill <jason@yorick.cygnus.com>
+
+ * parse.y (function_try_block): Call end_protect_partials
+ before expand_start_all_catch.
+
+1999-08-06 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (maybe_get_template_decl_from_type_decl): Make sure that
+ we're looking at a class.
+
+ * decl.c (lookup_name_real): Set the complain flag if we're
+ looking for a namespace member.
+
+ * decl.c (pushdecl): Only give an error for shadowing a parm
+ from *this* function.
+
+ * decl2.c (build_expr_from_tree, case METHOD_CALL_EXPR): Only
+ build_expr_from_tree on the args of a TEMPLATE_ID_EXPR.
+
+ * class.c (mark_overriders): Fix order of args to overrides.
+ (warn_hidden): Likewise. Fix for having virtual and non-virtual
+ functions with the same name.
+
+ * cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro.
+ * typeck.c (expand_ptrmemfunc_cst): Calculate delta correctly for
+ virtual functions and MI. Simplify.
+
+ * typeck.c (c_expand_return): Downgrade pedwarn about returning NULL
+ from op new to warning.
+
+ * decl2.c (reparse_absdcl_as_casts): Don't warn about old-style
+ casts in system headers or extern "C" blocks.
+
+ * pt.c (do_decl_instantiation): Downgrade duplicate instantiation
+ errors to pedwarn.
+
+ * error.c (dump_type_real): Handle TREE_LIST again.
+
+ * typeck.c (comp_target_parms): Don't complain about
+ converting from () to (...) if !flag_strict_prototype.
+
+ * class.c (instantiate_type): Downgrade errors for object-dependent
+ memfn refs to pedwarn.
+
+1999-08-06 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * pt.c (tsubst): Use build_index_type to build in-template array
+ index type. Fixes g++.oliva/dwarf1.C.
+ * decl.c (grokdeclarator): Likewise, just for consistency, as it
+ doesn't seem to trigger the bug without it.
+
+Thu Aug 5 02:40:42 1999 Jeffrey A Law (law@cygnus.com)
+
+ * typeck2.c: Update URLs and mail addresses.
+
+1999-08-03 Mumit Khan <khan@xraylith.wisc.edu>
+
+ * decl.c (start_decl): Set attributes before duplicate_decls call.
+
+Wed Jul 28 21:39:31 PDT 1999 Jeff Law (law@cygnus.com)
+
+ * gcc-2.95 Released.
+
+Sun Jul 25 15:24:21 1999 Jeffrey A Law (law@cygnus.com)
+
+ * g++FAQ.texi: Deleted per Joe Buck's request.
+ * Makefile.in: Corresponding changes.
+
+Sat Jul 17 23:50:47 1999 Jeffrey A Law (law@cygnus.com)
+
+ * Makefile.in (INTERFACE): Bump to 2.
+
+1999-07-17 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * typeck2.c (my_friendly_abort): Updated URL with bug reporting
+ instructions to gcc.gnu.org. Removed e-mail address.
+
+1999-07-15 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (check_default_tmpl_args): Handle friends defined in the
+ class just like member functions defined in the class.
+
+Thu Jul 15 01:26:49 1999 H.J. Lu <hjl@gnu.org>
+
+ * decl.c (duplicate_decls): Relax restriction for exception
+ checks on duplicate symbols.
+
+1999-07-07 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokdeclarator): Update the names of all variants when
+ de-anonymizing.
+
+Wed Jul 7 01:26:47 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * decl2.c (mark_vtable_entries): Fix check for rtti offset.
+
+1999-06-26 Richard Henderson <rth@cygnus.com>
+
+ * decl.c (cp_finish_decl): Fix typo in cp_warning_at call.
+
+1999-06-21 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (expand_aggr_vbase_init): Rename to
+ construct_virtual_bases. Conditionalize construction here,
+ rather than ...
+ (emit_base_init): Here.
+
+1999-06-19 Mark Mitchell <mark@codesourcery.com>
+
+ * semantics.c (finish_asm_statement): Apply decay conversions to
+ input operands.
+
+ * decl.c (expand_static_init): When building an anonymous function
+ for use with atexit, compute its body before and after entering
+ the function.
+
+1999-06-18 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (expand_aggr_vbase_init): Add flag parameter.
+ (build_partial_cleanup_for): Remove, inlining into ..
+ (expand_cleanup_for_base): ... here. Take flag parameter.
+ (emit_base_init): Pass the in_chrg parameter to
+ emit_aggr_vbase_init.
+ (emit_aggr_vbase_init): Pass it to expand_cleanup_for_base.
+
+1999-06-16 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (import_export_decl): Use same_type_p, rather than
+ relying on pointer-equality for types.
+
+ * method.c (do_build_copy_constructor): Simplify.
+
+ * call.c (build_method_call): Remove bogus code for two-argument
+ delete.
+ * init.c (build_new_1): Expand on comment, and remove dead code.
+
+ * init.c (expand_cleanup_for_base): New function, split out
+ from ...
+ (emit_base_init): Here.
+ (expand_aggr_vbase_init): Use it.
+
+1999-06-15 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (class_cache_firstobj): Declare.
+ (maybe_push_cache_obstack): Rename to push_cache_obstack.
+ * class.c (permanent_obstack): Remove declaration.
+ (class_cache_firstobj): Make it global.
+ (add_method): Don't use permanent_obstack directly.
+ (pushclass): Only free the class_cache_obstack if we know how far
+ back to free it.
+ (maybe_push_cache_obstack): Rename to push_cache_obstack.
+ * decl.c: Remove dead comment.
+ (saved_scope): Add class_cache_firstobj.
+ (push_to_top_level): Save it.
+ (pop_from_top_level): Restore it.
+ (push_class_level_binding): Use push_cache_obstack, not
+ maybe_push_cache_obstack.
+ * search.c (push_class_decls): Likewise.
+
+1999-06-14 Nathan Sidwell <nathan@acm.org>
+
+ * call.c (build_new_op): Remove REF_BIND from all operands.
+
+1999-06-07 Mark Mitchell <mark@codesourcery.com>
+
+ * search.c (convert_pointer_to_single_level): Reimplement without
+ using get_binfo.
+
+1999-06-06 Mark Mitchell <mark@codesourcery.com>
+
+ * method.c (is_back_referenceable_type): Back-reference bools when
+ not squangling.
+
+1999-06-04 Jason Merrill <jason@yorick.cygnus.com>
+
+ * semantics.c (finish_if_stmt_cond): Copy cond to permanent_obstack.
+ (finish_while_stmt_cond, finish_do_stmt, finish_for_cond): Likewise.
+
+1999-05-30 Mark Mitchell <mark@codesourcery.com>
+
+ * lex.c (make_lang_type): Create TYPE_BINFO for
+ TEMPLATE_TYPE_PARMs just like for non-template types.
+
+1999-05-28 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (complete_array_type): Allocate off same obstack. Fix
+ DO_DEFAULT comment to match reality.
+
+1999-05-22 Mark Mitchell <mark@codesourcery.com>
+
+ * tree.c (mapcar): Handle NON_LVALUE_EXPR.
+
+1999-05-21 Mark Mitchell <mark@codesourcery.com>
+
+ * typeck.c (build_ptrmemfunc): Handle PTRMEM_CSTs carefully to
+ reveal optimization opportunities.
+
+1999-05-20 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (grokdeclarator): Don't treat [] as indicating a
+ zero-sized array in a typedef.
+
+ * call.c (build_object_call): Don't look at DECL_NAME for a type.
+ (pt.c): Or CP_TYPE_QUALS for an ERROR_MARK.
+ (typeck.c): Or TYPE_MAIN_VARIANT for a type.
+
+1999-05-20 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (lvalue_p_1): A NOP_EXPR can be an lvalue.
+ (build_cplus_new): Make sure that what we return is of the right type.
+
+1999-05-20 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (make_ptrmem_cst): New function.
+ * expr.c (cplus_expand_constant): Split out from ...
+ (cplus_expand_expr): Here. Use cplus_expand_constant.
+ (init_cplus_expand): Set lang_expand_constant.
+ * pt.c (convert_nontype_argument): Use make_ptrmem_cst.
+ * tree.c (make_ptrmem_cst): Define.
+ * typeck.c (unary_complex_lvalue): Use make_ptrmem_cst.
+ * typeck2.c (initializer_constant_valid_p): Use make_ptrmem_cst.
+
+1999-05-19 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (start_static_storage_duration_function): Fix comment.
+ (finish_file): Create static storage duration functions lazily.
+
+Wed May 19 02:50:53 1999 Arvind Sankar <arvinds@mit.edu>
+
+ * gxxint.texi: Fix typo.
+
+1999-05-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (joust): Compare the types of the conv ops, not the
+ target types of the conversions.
+
+Tue May 18 00:21:34 1999 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * lang-specs.h: Define __GNUC__ and __GNUC_MINOR__ only if -no-gcc
+ was not given.
+
+1999-05-17 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.def (TEMPLATE_ID_EXPR): Update documentation.
+ * decl.c (grokfndecl): Don't allow inline declarations of friend
+ template specializations, or friend template specializations with
+ default arguments.
+ * pt.c (tsubst): Handle substitution into array types that does
+ not yield a fixed upper bound, even when not processing a
+ template.
+ (tsubst_copy): Deal with the fact that the second operand to a
+ TEMPLATE_ID_EXPR may be NULL_TREE, a TREE_LIST, or a TREE_VEC.
+ * search.c (marked_pushdecls_p): Don't descend into
+ TEMPLATE_TYPE_PARMs and the like.
+ (unmarked_pushdecls_p): Likewise.
+
+ * call.c (build_over_call): Don't throw away
+ initializations/copies of empty classes; use MODIFY_EXPR and
+ INIT_EXPR as for non-empty classes.
+ * class.c (finish_struct_1): Put the padding byte for an empty
+ class on the TYPE_NONCOPIED_PARTS list for the class.
+
+1999-05-16 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (build_expr_from_tree): Handle COMPONENT_REFs that
+ indicate a reference to a field that is a qualified name.
+
+1999-05-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (finish_objects): Don't use .?tors.* if we don't have
+ ASM_OUTPUT_CONSTRUCTOR.
+
+ * friend.c (do_friend): Add attrlist arg. Remove support for
+ getting a non-decl as 'decl'.
+ * decl.c (grokfndecl): Remove attrlist arg. Don't set attrs or
+ rtl.
+ (grokdeclarator): Adjust.
+ * cp-tree.h: Adjust.
+
+1999-05-16 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (permanent_p): New function.
+ * init.c (build_new_1): Use mapcar, not copy_node, to copy a
+ possibly complex tree node.
+ * tree.c (mapcar): Adjust comments, and follow coding standards in
+ conditional.
+ (permanent_p): New function.
+
+1999-05-13 Per Bothner <bothner@cygnus.com>
+
+ * class.c (push_lang_context): Turn off DECL_IGNORED_P for
+ primitive Java types, if we actually see `extern "Java"'.
+
+1999-05-10 18:21 -0400 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * lang-specs.h: Pass -$ to the preprocessor.
+
+1999-05-10 Jason Merrill <jason@yorick.cygnus.com>
+
+ * init.c (build_offset_ref): Wrap baselinks in OFFSET_REF, too.
+ Don't bother wrapping an OFFSET_TYPE around unknown_type_node.
+ (resolve_offset_ref): Don't handle a raw baselink.
+ * cvt.c (build_expr_type_conversion): Likewise.
+ * typeck.c (decay_conversion, build_c_cast, convert_for_assignment,
+ convert_for_initialization): Likewise.
+ * class.c (instantiate_type): Handle seeing a baselink under an
+ OFFSET_REF.
+ * error.c (dump_expr): Likewise.
+ * pt.c (for_each_template_parm): Likewise.
+ (resolve_overloaded_unification): Likewise.
+ * tree.c (is_overloaded_fn, really_overloaded_fn): Likewise.
+ * typeck.c (expr_sizeof): Also complain about other permutations
+ of overloaded functions.
+
+1999-05-07 Jason Merrill <jason@yorick.cygnus.com>
+
+ * init.c (resolve_offset_ref): Don't return a raw method.
+ Use BASELINK_P.
+ * typeck.c (decay_conversion): Don't handle a raw method.
+ Resolve all OFFSET_REFs.
+ (get_member_function_from_ptrfunc): 0 is a valid vtable index.
+ (build_binary_op_nodefault): Handle resolving overloaded fns. Use
+ same_type_p for pmf bits. Don't use build_binary_op to compare
+ raw pointers to methods.
+ (convert_for_assignment): Check for OFFSET_REF, not OFFSET_TYPE,
+ to decide when to call resolve_offset_ref.
+ (build_c_cast, convert_for_initialization): Likewise.
+ * cvt.c (build_expr_type_conversion): Likewise.
+
+1999-05-06 Nathan Sidwell <nathan@acm.org>
+
+ * call.c (build_new_method_call): Use TYPE_MAIN_VARIANT of class.
+
+1999-05-05 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (start_objects): Don't let static constructors and
+ destructors get inlined.
+
+ * parse.y (nested_name_specifier): Make sure ordinary types are
+ complete, just like template types.
+ * parse.c: Regenerated.
+
+ * pt.c (check_explicit_specialization): Improve error messages.
+
+1999-05-04 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * typeck.c (string_conv_p): Use same_type_p to check whether we
+ try to convert between char and wchar_t.
+
+1999-05-03 Mark Mitchell <mark@codesourcery.com>
+
+ * search.c (lookup_field_r): Set the TREE_TYPE of an ambiguous
+ lookup to error_mark_node here.
+ (lookup_member): Revise documentation. Add comments. Don't set
+ the TREE_TYPE to error_mark_node here, and don't build up an extra
+ TREE_LIST for ambiguous lookups.
+ (setup_class_bindings): Adjust accordingly.
+ (push_class_decls): Revise out-of-date comments.
+
+ * typeck.c (build_const_cast): Tighten checks for legality.
+
+1999-05-02 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * init.c (build_member_call): Lookup names coming from
+ namespace-scoped LOOKUP_EXPR.
+
+1999-05-03 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * gxxint.texi: Add documentation for 'I'.
+
+1999-05-02 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * tinfo.cc (operator==): Qualify type_info with std::.
+
+1999-05-02 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (lang_decl_flags): Remove comdat. Updated dummy.
+ (DECL_COMDAT): Remove definition.
+
+1999-05-01 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (wrapup_globals_for_namespace): Fix thinko in previous
+ change.
+
+1999-04-30 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (build_vtable): Use build_lang_decl when building
+ vtables, not just build_decl.
+ (prepare_fresh_vtable): Likewise.
+ * decl.c (wrapup_globals_for_namespace): Mark vtables as
+ DECL_EXTERNAL when calling wrapup_global_declarations.
+ * decl2.c (priority_info_s): Add initializations_p and
+ destructions_p members.
+ (finish_vtable_vardecl): Use TREE_SYMBOL_REFERENCED, not TREE_USED,
+ when deciding what vtables to write out.
+ (ssdf_decls): New variable.
+ (ssdf_decls_used): Likewise.
+ (start_static_storage_duration_function): Deal with being called
+ multiple times. Avoid inlining this function.
+ (generate_inits_for_priority): Deal with reuse of priority map.
+ (get_priority_info): Clear initializations_p and destructions_p.
+ (do_static_initialization): Tweak comment.
+ (do_static_destruction): Likewise. Fix condition on sentries for
+ destruction.
+ (generate_ctor_or_dtor_function): Call all of the static storage
+ duration functions.
+ (generate_ctor_or_dtor_function_for_priority): Check
+ initializations_p and destructions_p to see what priorities need
+ initialization functions.
+ (finish_file): Rework to generate multiple static storage duration
+ functions, rather than just one.
+
+ * typeck.c (build_const_cast): Tweak last change to handle
+ templates correctly.
+
+ * typeck.c (build_const_cast): Disallow use of const_cast to
+ anything but a pointer or reference type.
+
+1999-04-30 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (cp_finish_decl): Don't permit arrays of abstract or
+ signature type.
+
+1999-04-29 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (do_static_destruction): Remove obsolete FIXME comment.
+ (finish_file): Indent comments properly.
+
+1999-04-29 Richard Henderson <rth@cygnus.com>
+
+ * decl2.c (do_static_initialization): Call do_pending_stack_adjust.
+ (do_static_destruction): Likewise.
+
+1999-04-29 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (TYPE_NOTHROW_P): New macro.
+ * decl2.c (delete_sanity): Warn on deleting void *.
+ * init.c (build_new_1): Use TYPE_NOTHROW_P.
+ * typeck.c (c_expand_return): cp_pedwarn on returning NULL from
+ throwing operator new.
+
+1999-04-28 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (build_component_addr): Remove prototype.
+ * typeck.c (build_component_addr): Make static. Remove MSG
+ argument.
+ (build_component_addr): Remove MSG parameter, clean up
+ comment.
+ (build_x_function_call): Use cp_error.
+ (build_unary_op): Adjust call of build_component_addr.
+
+1999-04-28 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (tsubst_friend_class): Check for NULL.
+
+Wed Apr 28 11:42:22 1999 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
+
+ * search.c (binfo_for_vtable): Initialize bfvi.var.
+
+1999-04-27 Nathan Sidwell <nathan@acm.org>
+
+ * rtti.c (build_x_typeid): Check rtti is enabled.
+
+1999-04-26 Mark Mitchell <mark@codesourcery.com>
+
+ * search.c (is_subobject_of_p): Make sure we're looking at the
+ right baseclasses.
+
+1999-04-26 Marc Espie <espie@cvs.openbsd.org>
+
+ * Make-lang.in (cplib2.ready): Don't depend on phony targets.
+
+1999-04-23 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (finish_file): Tweak handling of extern inlines so that
+ they are not unnecessarily put out.
+
+ * search.c (is_subobject_of_p): Handle TEMPLATE_TYPE_PARMs and
+ such as base classes.
+
+1999-04-22 Brendan Kehoe <brendan@cygnus.com>
+
+ * tree.c (build_exception_variant): Fix typo: use the chain of U,
+ not trying V, while cycling through U.
+
+1999-04-22 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (lang_decl_flags): Remove returns_first_arg and
+ preserves_first_arg. Enlarge dummy accordingly.
+ (DECL_TINFO_FN_P): New macro.
+ (SET_DECL_TINFO_FN_P): Likeiwse.
+ (DECL_RETURNS_FIRST_ARG): Remove.
+ (DECL_PRESERVES_THIS): Likewise.
+ (DECL_INIT_PRIORITY): New macro.
+ (finish_struct_1): Change prototype.
+ (cat_namespace_levels): Remove prototype.
+ (vtable_decl_p): New prototype.
+ (vtype_decl_p): Likewise.
+ (sigtable_decl_p): Likewise.
+ (walk_globals_pred): New typedef.
+ (walk_globals_fn): Likewise.
+ (walk_globals): New prototype.
+ (walk_namespaces_fn): New typedef.
+ (walk_namespaces): New prototype.
+ (wrapup_globals_for_namespace): Likewise.
+ (walk_vtables): Remove prototype.
+ (walk_sigtables): Likewise.
+ (instantiate_pending_templates): New prototype.
+ * class.c (finish_struct_1): Don't return a value.
+ * decl.h (pending_statics): Remove declaration.
+ * decl.c (walk_namespaces_r): New function.
+ (walk_globals_r): Likewise.
+ (vtable_decl_p): Likewise.
+ (vtype_decl_p): Likewise.
+ (sigtable_decl_p): Likewise.
+ (walk_namespaces): Likewise.
+ (walk_globals_data): New type.
+ (walk_globals): New function.
+ (wrapup_globals_for_namespace): Likewise.
+ (expand_static_init): Remove assertion. Remove redundancy in
+ conditional. Don't put static data members in static_aggregates
+ Tidy.
+ (finish_function): Remove redundancy in conditional. Don't set
+ DECL_RETURNS_FIRST_ARG.
+ (cat_namespace_levels): Remove.
+ * decl2.c: Include splay-tree.h and varray.h.
+ (priority_info_s): New structure.
+ (finish_vtable_vardecl): Change prototype. Adjust for new calling
+ conventions.
+ (prune_vtable_vardecl): Likewise.
+ (finish_sigtable_vardecl): Likewise.
+ (setup_initp): Remove.
+ (do_dtors): Remove.
+ (do_ctors): Remove.
+ (start_static_storage_duration_function): New function.
+ (generate_inits_for_priority): Likewise.
+ (finish_static_storage_duration_function): Likewise.
+ (get_priority_info): Likewise.
+ (do_static_initialization): Likewise.
+ (do_static_destruction): Likewise.
+ (do_static_initialization_and_destruction): Likewise.
+ (generate_ctor_or_dtor_function): Likewise.
+ (generate_ctor_and_dtor_functions_for_priority): Likewise.
+ (pending_statics): Make it a varray.
+ (pending_statics_used): New variable.
+ (saved_inlines): Make it a varray.
+ (saved_inlines_used): New variable.
+ (finish_static_data_member): Change method of updating
+ pending_statics.
+ (mark_inline_for_output): Remove #if 0'd code. Change method of
+ updating saved_inlines.
+ (walk_vtables): Remove.
+ (walk_sigtables): Likewise.
+ (import_export_decl): Use DECL_TINFO_FN_P.
+ (pending_templates): Remove declaration.
+ (maybe_templates): Likewise.
+ (static_aggregates_initp): Likewise.
+ (setup_initp): Likewise.
+ (finish_objects): Simplify.
+ (INITIALIZE_P_IDENTIFIER): New macro.
+ (PRIORITY_IDENTIFIER): New macro.
+ (SSDF_IDENTIFIER): New macro.
+ (initialize_p_decl): New variable.
+ (priority_decl): Likewise.
+ (ssdf_decl): Likewise.
+ (priority_info_map): Likewise.
+ (finish_file): Recode output of static intializers and other
+ file-scope finalization tasks.
+ * error.c (OB_END_TEMPLATE_ID): New macro.
+ (dump_type_real): Use it.
+ (dump_decl): Likewise.
+ (dump_function_name): Likewise.
+ * lex.c (set_typedecl_interface_info): Adjust for new walk_globals
+ interface.
+ (check_newline): Use walk_globals, not walk_vtables.
+ * pt.c (pending_tempalte_expansions): Remove.
+ (set_vardecl_interface_info): Likewise.
+ (pending_templates): Make static.
+ (maybe_templates): Likewise.
+ (instantiate_class_template): Adjust call to finish_struct_1.
+ (instantiate_pending_templates): New function.
+ * rtti.c (get_tinfo_fn): Use SET_DECL_TINFO_FN_P.
+ * tree.c (static_aggregates_initp): Remove.
+ (cp_valid_lang_attribute): Don't use it; use DECL_INIT_PRIORITY
+ instead.
+ * Makefile.in (decl2.o): Depend on varray.h and splay-tree.h.
+
+ * gxx.gperf (RETURN): Rename to RETURN_KEYWORD to avoid clashes
+ with the RTL code RETURN.
+ * hash.h: Regenerated.
+ * lex.c (reinit_parse_for_block): Use RETURN_KEYWORD.
+ * parse.y: Replace RETURN with RETURN_KEYWORD throughout.
+ * parse.c: Regenerated.
+ * pt.c: Include varray.h. Include rtl.h since varray.h requires
+ it.
+ (inline_parm_levels): New variable.
+ (inline_parm_levels_used): Likewise.
+ (maybe_begin_member_template_processing): Update them.
+ (maybe_end_member_template_processing): Use them, rather than
+ guessing how many levels to pop.
+
+ * decl.c (make_typename_type): Tighten error-checking.
+
+1999-04-20 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (build_binary_op): Remove unneeded parameter.
+ * class.c (build_vrable_entry_ref): Adjust call to
+ build_binary_op.
+ * decl.c (expand_static_init): Likewise.
+ (grokdeclarator): Likewise.
+ (finish_function): Likewise.
+ * decl2.c (delete_sanity): Likewise.
+ (do_dtors): Likewise.
+ (do_ctors): Likewise.
+ * error.c (dump_type_suffix): Likewise.
+ * expr.c (cplus_expand_expr): Likewise.
+ * init.c (resolve_offset_ref): Likewise.
+ (build_new): Likewise.
+ (build_new_1): Likewise.
+ (build_vec_delete_1): Likewise.
+ (expand_vec_init_catch_clause): Likewise.
+ (build_delete): Likewise.
+ * pt.c (tsubst): Likewise.
+ * rtti.c (synthesize_tinfo_fn): Likewise.
+ * search.c (expand_upcast_fixups): Likewise.
+ (expand_direct_vtbls_init): Likewise.
+ * typeck.c (get_member_function_from_ptrfunc): Likewise.
+ (build_binary_op_nodefault): Likewise.
+ (point_int_sum): Likewise.
+ (pointer_diff): Likewise.
+ (build_unary_op): Likewise.
+ (build_modify_expr): Likewise.
+ (get_delta_difference): Likewise.
+ (build_ptrmemfunc): Likewise.
+ (expand_ptrmemfunc_cst): Likewise.
+
+1999-04-20 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokfndecl): Always call cplus_decl_attributes.
+ * decl2.c (grokfield): Pass attrlist to grokdeclarator.
+
+1999-04-19 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (finish_static_data_member_decl): New function.
+ * decl2.c (finish_static_data_member_decl): Split out from ...
+ (grokfield): Here.
+ * pt.c (instantiate_class_template): Use it here instead of
+ trying to fake it.
+ (tsubst_decl): Don't set DECL_ASSEMBLER_NAME;
+ finish_static_data_member_decl will do that. Explicit set
+ DECL_EXTERNAL to match non-template processing.
+
+1999-04-18 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (finish_class_definition): Add parameter.
+ * parse.y (structsp): Use it. Don't call pop_scope here.
+ * parse.c: Regenerated.
+ * semantics.c (finish_class_definition): Pop it here.
+
+1999-04-17 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (xref_tag): Revise handling of nested template
+ declarations.
+ * pt.c (check_explicit_specialization): Tweak handling of friend
+ templates in template classes.
+ (tsubst_friend_class): Handle friend declarations for nested
+ member template classes.
+
+1999-04-16 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (finish_struct): Remove unused variable.
+ (pushclass): Likewise.
+ (invalidate_class_lookup_cache): Likewise.
+ * cp-tree.def (TYPENAME_TYPE): Improve documentation.
+ * decl.c (build_typename_type): Make sure TYPENAME_TYPE_FULLNAME
+ doesn't get obliterated.
+ (make_typename_type): Handle template classes correctly.
+
+ * cp-tree.h (TREE_NONLOCAL_FLAG): Remove.
+ (storetags): Declare.
+ * class.c (finish_struct): Don't use TREE_NONLOCAL_FLAG.
+ (pushclass): Likewise. Use storetags to install tag declarations,
+ not pushtag.
+ (invalidate_class_lookup_cache): Don't use TREE_NONLOCAL_FLAG.
+ * decl.c (storetags): Make it global.
+ (push_class_binding): Set INHERITED_VALUE_BINDING_P for an
+ implicit typename declaration.
+ (pushtag): Tidy. Don't use TREE_NONLOCAL_FLAG.
+ * method.c (hack_identifier): Likewise.
+ * search.c (lookup_member): Likewise.
+
+ * decl.c (warn_about_implicit_typename_lookup): New function.
+ (lookup_name_real): Use it. Rework handling of implicit typename
+ extension.
+
+1999-04-15 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (lookup_nested_field): Remove.
+ * class.c (push_nested_class): Handle UNION_TYPEs.
+ (pop_nested_class): Likewise.
+ * decl.c (lookup_name_real): Don't call lookup_nested_field.
+ (start_decl): Use push_nested_class, not just pushclass.
+ (cp_finish_decl): Use pop_nested_class, not just popclass.
+ * search.c (lookup_nested_field): Remove.
+
+ * cp-tree.h (lang_type): Add documentation.
+ * decl2.c (handle_class_head): Create template declarations here,
+ as appropriate.
+ * parse.y (class_head): Return whether or not we entered a new
+ scope, as well as the type named.
+ (named_class_head): Likewise.
+ (named_complex_class_head_sans_basetype): Likewise.
+ (structsp): Adjust accordingly. Pop scope when required.
+ * parse.c: Regenerated.
+ * pt.c (check_default_tmpl_args): Robustify.
+ (redeclare_class_template): Likewise.
+ (instantiate_class_template): An instantiation of an
+ anonymous union is itself an anonymous union.
+ * semantics.c (begin_class_definition): Don't create template
+ declarations here.
+
+1999-04-15 Jason Merrill <jason@yorick.cygnus.com>
+
+ * parse.y (after_type_declarator_intern): New nonterminal.
+ (after_type_declarator): Use it.
+ (direct_after_type_declarator): Likewise. Move above
+ nonnested_type to fix reduce/reduce conflict resolution.
+ (declmods): Reducing from just 'attributes' has EMPTY precedence.
+ * Makefile.in (CONFLICTS): Update.
+
+ * decl.c (define_label): Downgrade error for jumping over a
+ non-POD decl to pedwarn.
+
+1999-04-14 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (popclass): Change declaration.
+ (pop_nested_class): Likewise.
+ (poplevel_class): Remove declaration.
+ * call.c (convert_default_argument): Pass no arguments to
+ popclass.
+ * class.c (finish_struct_1): Likewise.
+ (finish_struct): Likewise.
+ (popclass): Remove argument. Simplify code accordingly.
+ (pop_nested_class): Likewise.
+ * decl.c (poplevel_class): Declare it here, and make it static.
+ (poplevel): Handle class scopes.
+ (poplevel_class): Don't take an rgument. Simplify.
+ (pop_everything): Pass no arguments to pop_nested_class.
+ (cp_finish_decl): Pass no arguments to popclass.
+ (grokdeclarator): Pass no arguments to pop_nested_class.
+ (finish_function): Likewise.
+ * decl2.c (grokfield): Likewise.
+ (pop_scope): Pass no arguments to popclass.
+ * lex.c (do_pending_defargs): Pass no arguments to pop_nested_class.
+ * pt.c (instantiate_class_template): Move call to pushclass, and
+ document. Pass no arguments to popclass.
+ (regenerate_decl_from_template): Likewise.
+
+1999-04-14 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (build_unary_op): Handle taking the address of a unique
+ bound non-static member function.
+
+1999-04-13 Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+ * lang-options.h (-Wdeprecated): New flag.
+ * decl2.c (warn_deprecated): New flag.
+ (lang_decode_option): Deprecated this-is-variable,
+ external-templates, alt-external-templates.
+ Support -Wdeprecated.
+ * errfn.c (cp_deprecated): New function.
+
+1999-04-13 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (setup_initp): Compare DECL_ASSEMBLER_NAME instead
+ of the decls themselves.
+
+ * pt.c (tsubst_function_type): Copy attributes over.
+
+ * tree.c (cp_valid_lang_attribute): New fn. Handle init_priority
+ and com_interface.
+ * cp-tree.h: Add prototype.
+ * decl.c (init_decl_processing): Set valid_lang_attribute.
+
+1999-04-13 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (finish_struct_1): Look at the const-ness of the field's
+ type, not the TREE_READONLY-ness of the declaration.
+ * method.c (synthesize_method): Likewise.
+ * pt.c (tsubst_decl): Call c_apply_type_quals_to_decl when
+ creating new declarations.
+
+1999-04-13 Mike Stump <mrs@wrs.com>
+
+ * decl2.c (import_export_decl): Because vtables always reference
+ virtual functions, even if they are inlined, don't allow
+ -fno-implement-inlines to not emit them, instead, emit them with
+ the vtable.
+ * decl.c (start_function): Likewise.
+
+1999-04-12 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (struct lang_type): Add com_interface.
+ (CLASSTYPE_COM_INTERFACE): New macro.
+ * class.c (set_rtti_entry): COM interface classes have no RTTI
+ entries in their vtables; adjust.
+ (add_virtual_function, finish_base_struct, skip_rtti_stuff,
+ modify_one_vtable, fixup_vtable_deltas1, override_one_vtable,
+ finish_struct_1): Likewise.
+ * decl2.c (mark_vtable_entries): Likewise.
+ * rtti.c (build_headof, get_tinfo_fn_dynamic): Likewise.
+ * search.c (get_abstract_virtuals_1, get_abstract_virtuals,
+ expand_upcast_fixups): Likewise.
+ * tree.c (debug_binfo): Likewise.
+
+ * cp-tree.h (COMPARE_NO_ATTRIBUTES): New macro.
+ * typeck.c (comptypes): If we get it, ignore attributes.
+ * class.c (instantiate_type): Use BASELINK_P. Change complain
+ parameter to flags; 2 means ignore attributes.
+ * call.c (build_op_delete_call): Pass it.
+
+ * decl.c (xref_tag): Only complain once about using a typedef-name
+ with 'struct'. Downgrade to pedwarn.
+
+ * decl.c (grokdeclarator): Allow [] syntax for zero-length array.
+
+ * parse.y (absdcl_intern): New nonterminal.
+ (absdcl, direct_abstract_declarator): Use it.
+
+ * pt.c (lookup_template_class): Look through implict typename.
+
+1999-04-11 Mark Mitchell <mark@codesourcery.com>
+
+ * friend.c (add_friend): Deal gracefully with error_mark_node.
+ * method.c (build_overload_value): Handle pointers-to-members as
+ template parameters.
+
+ * decl.c (push_binding): Fix typo in comment.
+
+1999-04-10 Mark Mitchell <mark@codesourcery.com>
+
+ * error.c (dump_type_real): If a typename is a template-id, put
+ out the template arguments.
+ (dump_expr): Handle TEMPLATE_ID_EXPR.
+ * pt.c (lookup_template_class): Now that full arguments are
+ available everywhere, remove code that tried to guess them.
+
+1999-04-09 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (make_typename_type): Complain if we don't find a type
+ when trying to make a typename type for a non-template type.
+
+1999-04-09 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (start_decl): Pass attributes to grokdeclarator.
+ (grokdeclarator): Handle attributes on constructor-syntax
+ initializers.
+
+1999-04-08 Mark Mitchell <mark@codesourcery.com>
+
+ * error.c (dump_expr): Don't crash on INDIRECT_REFs whose operands
+ don't have types.
+
+ * search.c (template_self_reference_p): Tweak.
+
+1999-04-07 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (build_offset_ref): Don't build yet another weird data
+ structure to describe overloaded functions.
+
+1999-04-06 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (BASELINK_P): New macro.
+ (SET_BASELINK_P): Likewise.
+ * init.c (build_member_call): Remove needless assignment in if
+ statement.
+ * search.c (lookup_field_r): Fix handling when we are looking
+ specifically for a type; these are not hidden by functions and
+ variables.
+ (lookup_member): Use SET_BASELINK_P.
+ * tree.c (is_overloaded_fn): Use BASELINK_P.
+ (really_overloaed_fn): Likewise.
+ (get_first_fn): Likewise.
+
+1999-04-05 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (lookup_name_current_level): Tweak, and improve
+ documentation.
+
+ * class.c (maybe_fixup_vptrs): Remove declaration.
+ (build_class_init_list): Likewise.
+ * decl.c (pushdecl_class_level): Call check_template_shadow here
+ ...
+ (push_class_level_binding): ... not here.
+ * search.c (dfs_push_type_decls): Only avoid
+ template-self-reference TYPE_DECLs if they are from base classes.
+
+1999-04-04 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (check_template_shadow): Don't treat OVERLOADs as _DECL
+ nodes. Tidy.
+
+1999-04-03 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c (maybe_fixup_vptrs, build_class_init_list): Lose.
+ (finish_struct_1): Don't call build_class_init_list.
+
+1999-04-02 Mark Mitchell <mark@codesourcery.com>
+
+ * tinfo.h (__class_type_info): Fix illegal declaration.
+
+ * cp-tree.def (TEMPLATE_ID_EXPR): Update comment.
+ * cp-tree.h (INHERITED_VALUE_BINDING_P): New macro.
+ (IDENTIFIER_CLASS_VALUE): Improve documentation.
+ (is_properly_derived_from): Declare.
+ (invalidate_class_lookup_cache): Likewise.
+ (maybe_maybe_note_name_used_in_class): Likewise.
+ (note_name_declared_in_class): Likewise.
+ (push_using_decl): Remove duplicate declaration.
+ (id_in_current_class): Remove declaration.
+ (push_class_binding): Change prototype.
+ (clear_identitifer_class_values): Declare.
+ * call.c (is_properly_derived_from): Make it global.
+ (build_new_function_call): Be careful about updating candidates.
+ (build_new_method_call): Handle COMPONENT_REFs. Don't crash when
+ asked to make illegal calls.
+ * class.c: Include splay-tree.h.
+ (class_stack_node): Add names_used slot.
+ (check_member_decl_is_same_in_complete_scope): Remove.
+ (add_method): Fix comment. Push the declaration into class
+ scope.
+ (finish_struct_1): When popping the class, pop the bindings too.
+ Remove check for data member/function member conflict.
+ (finish_struct): Remove calls to
+ check_member_decl_is_same_in_complete_scope. Change calls to
+ popclass.
+ (pushclass): Clear names_used in the class stack entry.
+ Use invalidate_class_lookup_cache to remove cached entries, rather
+ than magic values with popclass. Clear IDENTIFIER_CLASS_VALUE
+ before entering a new class. Remove dead code. Don't mess with
+ current_function_decl when pushing declarations.
+ (invalidate_class_lookup_cache): New function, split out from ...
+ (popclass): Here. Clean up names_used on our way out.
+ (instantiate_type): Adjust.
+ (build_self_reference): Don't push the declaration here.
+ (maybe_note_name_used_in_class): New function.
+ (note_name_declared_in_class): Likewise.
+ * decl.c (add_binding): Change prototype.
+ (find_class_binding_level): New function.
+ (innermost_nonclass_level): Likewise.
+ (current_binding_level): Update documentation.
+ (inner_binding_level): Remove. Replace with current_binding_level
+ throughout.
+ (push_binding_level): Remove special handling of
+ class_binding_level.
+ (pop_binding_level): Likewise. Use find_class_binding_level.
+ (suspend_binding_level): Likewise.
+ (global_bindings_p): Use innermost_nonclass_level.
+ (toplevel_bindings_p): Likewise.
+ (namespace_bindings_p): Likewise.
+ (pseudo_global_level_p): Likewise.
+ (push_binding): Clear INHERITED_VALUE_BINDING_P.
+ (add_binding): Check for illegal multiple declarations. Return a
+ value indicating whether or not the new binding was legal.
+ (push_local_binding): Skip over class binding levels. Check
+ return value from add_binding.
+ (push_class_binding): Set INHERITED_VALUE_BINDING_P. Call
+ note_name_declared_in_class.
+ (pushlevel_class): Remove "fake out the rest of the compiler"
+ code.
+ (poplevel_class): Reset IDENTIFIER_CLASS_VALUEs.
+ (clear_identifier_class_values): New function.
+ (pop_from_top_level): Use it.
+ (pop_everything): Tweak.
+ (maybe_process_template_type_declaration): Don't push the
+ declaration for the template here.
+ (pushtag): Don't push tag declarations into class scope here.
+ (pushdecl): Apply DeMorgan's law for readability.
+ (pushdecl_class_level): Remove special-case code for
+ TYPE_BEING_DEFINED. Handle OVERLOADs and anonymous unions.
+ (push_class_level_bindng): Deal with inherited bindings.
+ (lookup_name_real): Remove special-case code for
+ TYPE_BEING_DEFINED, and some implicit typename magic.
+ (grokdeclarator): Handle COMPONENT_REF for a template function.
+ (build_enumerator): Don't call pushdecl_class_level here.
+ (id_in_current_class): Remove.
+ * decl2.c (grokfield): Don't call pushdecl_class_level or
+ check_template_shadow.
+ * errfn.c (cp_file_of): Don't declare.
+ (cp_line_of): Likewise.
+ * error.c (dump_decl): Handle an OVERLOAD.
+ (cp_file_of): Likewise.
+ (cp_line_of): Likewise.
+ * init.c (build_member_call): Handle a COMPONENT_REF.
+ * lex.c (do_identifier): Call maybe_note_name_used_in_class, not
+ pushdecl_class_level.
+ * method.c (hack_identifier): Build COMPONENT_REFs for references
+ to member templates as well as member functions. Remove dead
+ code.
+ * parse.y (left_curly): Remove.
+ (nonnested_type): Call maybe_note_name_used_in_class, not
+ pushdecl_class_level.
+ * parse.c: Regenerated.
+ (nested_name_specifier_1): Likewise.
+ * pt.c (check_explicit_specialization): Adjust, for robustness.
+ (check_template_shadow): Handle OVERLOADs.
+ (build_template_decl): Set DECL_CONSTRUCTOR_P on the
+ TEMPLATE_DECL, if appropriate.
+ * search.c (envelope_add_decl): Remove.
+ (dfs_pushdecls): Likewise.
+ (dfs_compress_decls): Likewise.
+ (dfs_push_decls): New function.
+ (dfs_push_type_decls): Likewise.
+ (setup_class_bindings): Likewise.
+ (template_self_reference_p): Likewise.
+ (lookup_field_r): Use it.
+ (looup_member): Remove old comment. Deal with ambiguity.
+ (push_class_decls): Use dfs_push_decls and dfs_push_type_decls,
+ and remove envelope processing.
+ * semantics.c (begin_class_definition): Let pushclass push
+ declarations for base classes.
+ (finish_member_declaration): Push declarations into class scope.
+ * typeck.c (build_component_ref): Just put an OVERLOAD into the
+ COMPONENT_REF, not a TREE_LIST of an OVERLOAD.
+ (build_x_function_call): Deal with OVERLOAD. Handle template-ids.
+ * Makefile.in (class.o): Depend on splay-tree.h.
+
+Wed Mar 31 11:30:43 1999 Nathan Sidwell <nathan@acm.org>
+
+ * cvt.c (convert_pointer_to_real): Use same_type_p.
+ * typeck.c (comp_target_types): Use same_type_p.
+
+1999-03-31 Jason Merrill <jason@yorick.cygnus.com>
+
+ * semantics.c (begin_inline_definitions,
+ finish_inline_definitions): Rename from finish_default_args and
+ begin_inline_definitions, respectively, to something that isn't a
+ total lie. :)
+ * parse.y (structsp): Adjust.
+
+ * tree.c (hash_tree_cons): Remove obsolete via_* parms.
+ (list_hash_lookup): Likewise.
+ (hash_tree_chain): Adjust.
+ * pt.c (tsubst): Adjust.
+ (tsubst_arg_types): Use plain hash_tree_cons.
+ * cp-tree.h (hash_tree_cons_simple): Lose.
+ * parse.y (declmods, nonempty_cv_qualifiers): Use hash_tree_cons.
+
+Wed Mar 31 10:48:29 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (hash.h): Generate using gperf language 'C', not
+ 'KR-C', so gperf uses the `const' keyword on strings.
+
+ * gxx.gperf (resword): Const-ify a char*.
+
+1999-03-30 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (IDENTIFIER_AS_DESC, IDENTIFIER_AS_LIST,
+ CLASSTYPE_BASELINK_VEC, CLASSTYPE_N_SUPERCLASSES,
+ CLASSTYPE_N_BASECLASSES, CLASSTYPE_MAX_DEPTH,
+ CLASSTYPE_BASE_INIT_LIST, CLASSTYPE_AS_LIST, CLASSTYPE_ID_AS_LIST,
+ CLASSTYPE_BINFO_AS_LIST): Remove cruft.
+ * class.c, lex.c, parse.y, ptree.c, search.c, semantics.c,
+ tree.c: Adjust.
+
+1999-03-29 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (lang_decode_option): Remove -Wsign-promo from -Wall.
+
+1999-03-28 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (fn_type_unification): Ignore 'this' parm from conversion ops.
+
+1999-03-27 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (add_friend): Declare.
+ (add_friends): Likewise.
+ * friend.c (add_friend): Make it global. Don't add to
+ DECL_BEFRIENDING_CLASSES if the befriending class is a template.
+ (add_friends): Make it global.
+ (make_friend_class): Don't add to DECL_BEFRIENDING_CLASSES if the
+ befriending class is a template.
+ * parse.y (component_decl_1): Fix typo in comment.
+ * parse.c: Regenerated.
+ * pt.c (instantiate_class_template): Use add_friend and
+ add_friends rather that duplicating some of their functionality
+ here.
+
+1999-03-27 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (build_field_call): Unify 'this' and non-'this' cases.
+
+ * typeck.c (build_indirect_ref): Check for 'this' sooner.
+
+Fri Mar 26 10:20:34 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * call.c (op_error): Const-ify a char*.
+ (add_candidate, source_type, add_warning): Add static prototype.
+ (print_z_candidates): Const-ify a char*.
+
+ * class.c (resolve_address_of_overloaded_function,
+ fixed_type_or_null, build_vtable_entry_ref): Add static prototype.
+ (get_vtable_name, finish_struct_1): Const-ify a char*.
+
+ * cvt.c (convert_to_reference): Likewise.
+
+ * decl.c (redeclaration_error_message, record_builtin_type,
+ record_unknown_type, member_function_or_else, bad_specifiers):
+ Likewise.
+ (find_binding, select_decl, unqualified_namespace_lookup,
+ lookup_flags, qualify_lookup, record_builtin_java_type, tag_name):
+ Add static prototype.
+ (warn_extern_redeclared_static, duplicate_decls, pushdecl,
+ implicitly_declare, record_builtin_java_type, define_function,
+ grok_op_properties, tag_name): Const-ify a char*.
+
+ * cp-tree.h (FORMAT_VBASE_NAME): Allow parameter `BUF' to be const.
+ (define_function, finish_builtin_type): Const-ify a char*.
+ (cp_error, cp_error_at, cp_warning, cp_warning_at, cp_pedwarn,
+ cp_pedwarn_at, cp_compiler_error, cp_sprintf): Add prototype args.
+ (file_name_nondirectory): Const-ify a char*.
+ (init_filename_times): Don't prototype.
+ (compiler_error): Prototype.
+ (yyerror, init_repo): Const-ify a char*.
+ (build_srcloc): Don't prototype.
+ (build_x_indirect_ref, build_indirect_ref, build_component_addr):
+ Const-ify a char*.
+ (warn_for_assignment): Don't prototype.
+ (convert_for_initialization, readonly_error, check_for_new_type,
+ GNU_xref_begin, GNU_xref_file, GNU_xref_ref, GNU_xref_call):
+ Const-ify a char*.
+
+ * decl2.c (acceptable_java_type, output_vtable_inherit,
+ setup_initp, start_objects, finish_objects, do_dtors, do_ctors,
+ merge_functions, decl_namespace, validate_nonmember_using_decl,
+ do_nonmember_using_decl): Add static prototype.
+ (lang_f_options): Const-ify a char*.
+ (finish_builtin_type): Likewise.
+ (add_function, arg_assoc_namespace, arg_assoc_class): Add static
+ prototype.
+
+ * errfn.c: Include cp-tree.h.
+ (cp_thing): Add static prototype.
+ (compiler_error): Don't protoptype.
+ (cp_compiler_error): Cast `compiler_error' to `errorfn' before
+ passing it to `cp_thing'.
+
+ * error.c (interesting_scope_p): Add static prototype.
+
+ * except.c (build_eh_type_type, build_eh_type_type_ref): Const-ify
+ a char*.
+
+ * init.c (compiler_error): Don't prototype.
+ (member_init_ok_or_else): Const-ify a char*.
+ (build_java_class_ref): Add static prototype.
+
+ * lex.c (compiler_error): Don't prototype.
+ (get_time_identifier, interface_strcmp, extend_token_buffer,
+ handle_cp_pragma): Const-ify a char*.
+ (is_global, init_filename_times): Add static prototype.
+ (file_name_nondirectory, cplus_tree_code_name): Const-ify a char*.
+ (compiler_error): Change from fixed args to variable args.
+ (yyerror): Const-ify a char*.
+
+ * parse.y (cond_stmt_keyword): Const-ify a char*.
+ (parse_decl): Add static prototype.
+
+ * pt.c (template_args_equal, print_template_context): Likewise.
+ (print_candidates, check_default_tmpl_args): Const-ify a char*.
+ (instantiate_class_template): Likewise.
+
+ * repo.c (get_base_filename, open_repo_file, init_repo): Likewise.
+
+ * rtti.c (call_void_fn, expand_generic_desc, expand_si_desc,
+ expand_class_desc, expand_ptr_desc, expand_attr_desc): Likewise.
+
+ * search.c (lookup_field_info, lookup_member): Likewise.
+ (lookup_member): Cast the first argument of `bzero' to a PTR.
+
+ * sig.c (compiler_error): Don't prototype.
+ (build_signature_pointer_or_reference_nam): Const-ify a char*.
+ (get_sigtable_name, build_member_function_pointer): Likewise.
+
+ * tree.c (compiler_error): Don't prototype.
+ (no_linkage_helper, build_srcloc): Add static prototype.
+ (build_vbase_pointer_fields): Const-ify a char*.
+ (__eprintf): Don't unnecessarily handle `const' when !__STDC__.
+
+ * typeck.c (compiler_error): Don't prototype.
+ (convert_for_assignment): Const-ify a char*.
+ (comp_cv_target_types): Add static prototype.
+ (build_x_indirect_ref, build_indirect_ref, convert_arguments,
+ build_component_addr, build_unary_op, convert_for_initialization):
+ Const-ify a char*.
+
+ * typeck2.c (ack): Add static prototype and change from fixed args
+ to variable args.
+ (readonly_error, check_for_new_type): Const-ify a char*.
+
+ * xref.c (_XREF_FILE, find_file, filename, fctname, declname,
+ fixname, open_xref_file, classname, GNU_xref_begin): Likewise.
+ (GNU_xref_file): Likewise. Also use `xmalloc' instead of `malloc'.
+ (GNU_xref_end_scope, GNU_xref_ref, GNU_xref_decl, GNU_xref_call,
+ gen_assign, GNU_xref_member): Const-ify a char*.
+
+1999-03-25 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * gxxint.texi: Remove old discussion on copying virtual bases.
+
+1999-03-25 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * Make-lang.in: Remove all references to g++.o/g++.c.
+ Link g++ from gcc.o.
+
+1999-03-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (comdat_linkage): Treat vtables like functions.
+
+1999-03-25 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (tsubst_decl): tsubst into DECL_BEFRIENDING_CLASSES.
+
+1999-03-25 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (init_decl_processing): Add `signed' type as a synonym
+ for `int'.
+
+1999-03-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (common_type): Handle cv-qual unification for pointers
+ to members.
+
+ * decl.c (unqualified_namespace_lookup): Return error_mark_node
+ on error.
+ (lookup_name_real): Set LOOKUP_COMPLAIN when *not* parsing.
+ * lex.c (do_identifier): If we got error_mark_node, call
+ lookup_name again.
+
+1999-03-24 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * class.c (finish_struct_1): Always reset TYPE_FIELDS for empty
+ classes.
+
+1999-03-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (lookup_name_real): Do nested field lookup regardless of
+ TYPE_BEING_DEFINED.
+
+1999-03-24 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (lang_type): Remove has_assignment and
+ has_real_assignment. Add befriending_classes.
+ (TYPE_HAS_ASSIGNMENT): Remove.
+ (TYPE_HAS_REAL_ASSIGNMENT): Likewise.
+ (CLASSTYPE_BEFRIENDING_CLASSES): New macro.
+ (lang_decl): Document.
+ (DECL_BEFRIENDING_CLASSES): New macro.
+ (FRIEND_NAME): Move declaration to more obvious location.
+ (FRIEND_DECLS): Likewise.
+ * class.c (finish_struct_1): Don't use TYPE_HAS_REAL_ASSIGNMENT.
+ * decl.c (duplicate_decls): Copy DECL_BEFRIENDING_CLASSES.
+ (fixup_anonymous_union): Don't use TYPE_HAS_ASSIGNMENT.
+ (grok_op_properties): Likewise.
+ * friend.c (is_friend): Use FRIEND_NAME and FRIEND_DECLS.
+ (add_friend): Likewise. Don't do weird things with assignment
+ operators. Update DECL_BEFRIENDING_CLASSES.
+ (add_friends): Don't do weird things with assignment operators.
+ (make_friend_class): Likewise. Update
+ CLASSTYPE_BEFRIENDING_CLASSES.
+ * pt.c (instantiate_class_template): Don't set
+ TYPE_HAS_ASSIGNMENT.
+ (tsubst_copy): Substitute the TREE_TYPE for more unary
+ expressions.
+ * ptree.c (print_lang_type): Don't look at TYPE_HAS_ASSIGNMENT.
+ * search.c (protected_accessible_p): New function.
+ (friend_accessible_p): Likewise.
+ (accessible_p): Use them.
+
+1999-03-23 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (convert_nontype_argument): Don't create things that aren't
+ PTRMEM_CSTs when applying a qualification conversion to a
+ PTRMEM_CST.
+
+1999-03-23 Mark Mitchell <mark@codesourcery.com>
+
+ * Makefile.in (OBJS): Don't mention hash.o.
+ (OBJDEPS): Likewise.
+
+1999-03-23 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (finish_file): Set at_eof to 2 after expanding ctors.
+ * decl.c (expand_static_init): Make sure we don't add any after
+ then.
+
+ * decl.c (cp_finish_decl): Move intelligence about handling
+ DECL_COMDAT for variables from here...
+ * decl2.c (comdat_linkage): ...to here.
+ (maybe_make_one_only): Tweak.
+ (import_export_decl): Call comdat_linkage for variables, too.
+ (finish_file): Handle template statics properly.
+
+1999-03-22 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (TYPE_PTRMEMFUNC_P): Use TYPE_PTRMEMFUNC_FLAG.
+ Document internals of pointer-to-member-functions.
+ (DELTA2_FROM_PTRMEMFUNC): Make it call delta2_from_ptrmemfunc.
+ (PFN_FROM_PTRMEMFUNC): Likewise.
+ (build_type_conversion): Remove unused parameter.
+ (build_ptrmemfunc1): Declare.
+ (expand_ptrmemfunc_cst): New function.
+ (delta2_from_ptrmemfunc): Likewise.
+ (pfn_from_ptrmemfunc): Likewise.
+ * cvt.c (cp_convert_to_pointer): Remove unused parameter to
+ build_type_conversion. Use TYPE_PTRMEM_P for readability.
+ (convert_to_reference): Remove unused parameter to
+ build_type_conversion.
+ (ocp_convert): Likewise.
+ (build_user_type_conversion): Likewise.
+ * error.c (dump_expr): Handle NULL pointer-to-member functions.
+ * expr.c (cplus_expand_expr): Handle PTRMEM_CSTs for functions.
+ * method.c (build_overload_value): Don't go splitting CONSTRUCTORs
+ open when handling pointer-to-member functions.
+ * pt.c (convert_nontype_argument): Clean up error messages. Be
+ more stringent with pointers-to-members.
+ * typeck.c (build_ptrmemfunc1): Don't declare. Make it global.
+ (build_unary_op): Tidy ever-so-slightly.
+ (build_conditional_expr): Remove extra parameter to
+ build_type_conversion.
+ (build_ptrmemfunc): Build PTRMEM_CSTs if we know what function
+ we're using.
+ (expand_ptrmemfunc_cst): Define.
+ (delta2_from_ptrmemfunc): Likewise.
+ (pfn_from_ptrmemfunc): Likewise.
+
+1999-03-19 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (build_member_call): Handle template-id expressions
+ correctly.
+ * typeck.c (build_x_function_call): Likewise.
+
+1999-03-19 Chip Salzenberg <chip@perlsupport.com>
+
+ * friend.c (make_friend_class): Avoid core dump when
+ not-yet-defined friend type lacks TYPE_LANG_SPECIFIC().
+
+1999-03-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (start_function): Suppress normal linkage heuristics
+ for #pragma interface under MULTIPLE_SYMBOL_SPACES.
+
+1999-03-19 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * Make-lang.in: ($(INTL_TARGETS)): Depend on cp/parse.c.
+ ($(srcdir)/cp/parse.c): Moved from ../Makefile.in.
+
+1999-03-17 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * parse.y (named_complex_class_head_sans_basetype):
+ Do not push a scope for error_mark_node.
+ (maybe_base_class_list): Likewise.
+
+ * decl.c (start_decl): Check for error_mark_node as a type.
+ Detected by g++.brendan/array-refs.C.
+ (start_decl_1): Likewise. Detected by g++.bugs/900322_01.C.
+ (maybe_build_cleanup_1): Likewise. Detected by
+ g++.jason/incomplete1.C.
+
+ * tree.c (build_dummy_object): Use void_zero_node instead of the
+ error_mark_node.
+ (is_dummy_object): Check for such a node.
+ Detected by g++.bob/inherit1.C
+
+1999-03-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * method.c (old_backref_index): Split out...
+ (flush_repeats): From here. Rename back from try_old_backref.
+ (build_mangled_name): Put back some old-style repeat handling.
+
+Mon Mar 15 21:57:16 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * lex.c: Don't include setjmp.h.
+ (parse_float): New static function.
+ (pf_args): New struct.
+ (real_yylex): Use them in call to `do_float_handler'.
+
+1999-03-15 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (xref_basetypes): Set CLASSTYPE_VBASECLASSES here.
+ * tree.c (layout_basetypes): Not here.
+ * search.c (dfs_search): Remove; no longer used.
+
+1999-03-12 Mark Mitchell <mark@markmitchell.com>
+
+ * decl2.c (validate_nonmember_using_decl): Issue sensible
+ error-messages on bogus qualifiers.
+
+1999-03-14 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (add_function_candidate): Fix uninitialized variable.
+
+ * Makefile.in (search.o): Add dependency on varray.h.
+
+1999-03-13 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (duplicate_decls): Use same_type_p.
+ * method.c (try_old_backref): Renamed from flush_repeats. Use
+ same_type_p. Don't try to handle repeats. Return success.
+ (is_back_referenceable_type): Return 0 if TYPE_FOR_JAVA. Support
+ calls from old-style code, too.
+ (check_ktype): Use same_type_p.
+ (check_btype): Use same_type_p. Don't pull out TYPE_MAIN_VARIANT.
+ (build_qualified_name): Simplify logic.
+ (process_overload_item): Strip typedefs and quals at the top.
+ (build_mangled_name_for_type_with_Gcode): Remove call to
+ type_canonical_variant.
+ (build_mangled_name): Likewise. Remove support for old-style
+ repeats, which have been disabled since 2.7.2. Don't mess with
+ TREE_USED.
+ (build_decl_overload_real): Don't mess with TREE_USED.
+
+1999-03-13 Nathan Sidwell <nathan@acm.org>
+
+ * error.c (cp_printers): Add 'F' escape character.
+ (dump_type_real): Remove TREE_LIST (fnargs) printing.
+ Functionality moved to dump_parameters.
+ (dump_type_suffix): Use dump_parameters and dump_exception_spec.
+ (dump_function_decl): Extend meaning of V parameter. Use
+ dump_parameters and dump_exception_spec.
+ (dump_parameters): New static function.
+ (dump_exception_spec): New static function.
+ (fndecl_as_string): Change argument semantics. Use
+ dump_function_decl directly.
+
+ * sig.c (build_signature_table_constructor): Use cp_error.
+
+1999-03-13 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * semantics.c (finish_switch_cond): Handle error cases gracefully.
+ Detected by g++.law/enum5.C.
+
+ * typeck.c (build_modify_expr): Check for errors after resolving
+ offsets. Detected by g++.brendan/static1.C.
+
+ * decl.c (complete_array_type): Ignore initial_value if it is an
+ error. Detected by g++.benjamin/17930.C.
+
+ * typeck2.c (process_init_constructor): Return error if one argument
+ is in error. Detected by g++.benjamin/13478.C.
+
+1999-03-12 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (select_decl): Allow class templates when we need types.
+ * decl2.c (ambiguous_decl): Likewise.
+
+1999-03-12 Mark Mitchell <mark@markmitchell.com>
+
+ * lex.c (do_identifier): Correct call to enforce_access.
+ * search.c (accessible_p): Tweak comment.
+
+1999-03-10 Mark Mitchell <mark@markmitchell.com>
+
+ * semantics.c (begin_class_definition): Call build_self_reference.
+ (finish_member_declaration): Set DECL_CONTEXT for TYPE_DECLs.
+
+ * search.c (assert_canonical_unmarked): Fix typo in prototype.
+
+ * search.c (dfs_canonical_queue): New function.
+ (dfs_assert_unmarked_p): Likewise.
+ (assert_canonical_unmarked): Likewise.
+ (access_in_type): Use it.
+ (accessible_p): Likewise. Walk the whole tree when umarking.
+
+ * sig.c (build_signature_table_constructor): Use accessible_p
+ instead of compute_access.
+
+1999-03-09 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (add_builtin_candidates): Handle overloaded conversion ops.
+
+1999-03-09 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (flag_access_control): Declare.
+ (TREE_VIA_PPUBLIC): Document.
+ (DECL_NONSTATIC_MEMBER_P): New macro.
+ (enforce_access): Return an indication of whether or not access
+ was permitted.
+ (build_self_reference): Change prototype.
+ (compute_access): Replace with ...
+ (accessible_p): New function.
+ (dfs_walk): Change prototype.
+ (dfs_unmark): Likewise.
+ (markedp): Likewise.
+ * call.c (enforce_access): Use accessible_p.
+ * class.c (build_self_reference): Insert the declaration into the
+ list of members for this type, and make it public.
+ * decl.c (xref_basetypes): Avoid ill-timed recursion.
+ * init.c (build_offset_ref): Use lookup_member, not three separate
+ name-lookups. Call enforce_access rather than checking for
+ illegal accesses here.
+ (resolve_offset_ref): Likewise.
+ * lex.c (do_identifier): Likewise.
+ * method.c (hack_identifier): Likewise.
+ * parse.y (self_reference): Remove.
+ (opt_component_decl_list): Don't use it.
+ * parse.c: Regenerated.
+ * pt.c (print_candidates): Generalize to handle lists of
+ overloaded functions.
+ (instantiate_class_template): Don't rely on TREE_VIA_PRIVATE; it's
+ not set.
+ (get_template_base): Use new calling convention for dfs_walk.
+ * search.c: Include varray.h. Add prototypes.
+ (dfs_walk): Accept a data pointer to pass to the work functions.
+ All callers changed. All work functions changed.
+ (breadth_first_search): Rename to bfs_walk, and make consistent
+ with dfs_walk.
+ (dfs_walk_real): New function.
+ (canonical_binfo): New function.
+ (context_for_name_lookup): Likewise.
+ (shared_marked_p): Likewise.
+ (shared_unmarked_p): Likewise.
+ (lokup_field_queue_p): Likewise.
+ (lookup_field_r): Generalize to handle both functions and fields.
+ (lookup_field): Just call lookup_member.
+ (lookup_fnfields): Likewise.
+ (lookup_member): Move body of lookup_field here and generalize.
+ (dfs_accessible_queue_p): Likewise.
+ (dfs_accessible_p): Likewise.
+ (dfs_access_in_type): Likewise.
+ (access_in_type): Likewise.
+ (compute_access): Remove, and replace with ...
+ (accessible_p): New function.
+ (vbase_types): Remove.
+ (vbase_decl_ptr_intermediate): Likewise.
+ (vbase_decl_ptr): Likewise.
+ (vbase_init_result): Likewise.
+ (closed_envelopes): Likewise.
+ (bvtable): Likewise.
+
+1999-03-09 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (add_function_candidate): Check for proper number of args
+ before checking the validity of those args.
+
+1999-03-06 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (struct lang_type): Add anon_union field.
+ (ANON_UNION_TYPE_P): Use it instead of examining type.
+ (SET_ANON_UNION_TYPE_P): New macro.
+ * decl.c (check_tag_decl): Use it.
+
+ * search.c (compute_access): Handle non-type contexts earlier, and
+ handle NULL_TREE.
+
+ * tree.c (build_exception_variant): Use copy_to_permanent.
+
+ * decl2.c (setup_initp): Give statics with no priority the default
+ priority here.
+ (do_dtors, do_ctors, finish_file): Remove special handling of
+ non-prioritized statics.
+
+1999-03-05 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (ANON_UNION_TYPE_P): Robustify.
+ * decl.c (make_typename_type): Don't issue an error if an
+ immediate lookup fails; it migt be resolved later.
+ * friend.c (is_friend): Add comment.
+ * search.c (breadth_first_search): Add POSTFN and DATA
+ parameters. Tidy. All callers changed.
+ (lookup_field_queue_p): New function.
+ (lookup_field_r): Likewise.
+ (lookup_field_post): Likewise.
+ (lookup_field): Use them, via breadth_first_search, instead of
+ duplicating logic.
+ (compute_access): Robustify.
+ (lookup_fnfield_info): New structure.
+
+1999-03-05 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst, case ARRAY_REF): Use tsubst_expr again.
+
+1999-03-03 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c, decl2.c, method.c, pt.c: Add 'static' to make SunOS 4
+ cc happy.
+
+ * decl2.c (import_export_class): Also return if
+ CLASSTYPE_INTERFACE_ONLY is set.
+
+1999-03-03 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (push_overloaded_decl): Only overwrite the old binding if
+ there was one.
+ * decl2.c (do_local_using_decl): Fix loop termination.
+
+1999-03-02 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (determine_specialization): Don't declare.
+ * pt.c (determine_specialization): Make it static. Eliminate
+ complain parameter. Note that decl is always non-NULL now, and
+ simplify accordingly.
+
+ * decl.c (maybe_push_to_top_level): Always call
+ push_cp_function_context.
+ (pop_from_top_level): Always call pop_cp_function_context.
+
+1999-02-26 Nathan Sidwell <nathan@acm.org>
+
+ * typeck.c (complete_type_or_else): Add VALUE arg, for helpful
+ diagnostics.
+ * cp-tree.h (complete_type_or_else): Added VALUE parameter.
+ * init.c (build_new_1): Extra arg to complete_type_or_else.
+ (build_delete): Likewise.
+ * typeck.c (require_complete_type): Likewise.
+ (pointer_int_sum): Likewise.
+ (pointer_diff): Likewise.
+ (build_component_ref): Likewise.
+
+ * typeck2.c (incomplete_type_error): Always use cp_error.
+ Show declaration of undefined type, if appropriate.
+ Deal with UNKNOWN_TYPE nodes.
+
+ * typeck.c (require_complete_type): Use TYPE_SIZE as
+ size_zero_node to mean incomplete type.
+ (require_complete_type_in_void): New function.
+ (build_compound_expr): Call complete_type_in_void for LHS.
+ (build_c_cast): Call complete_type_in_void for void cast.
+ * cvt.c (ocp_convert): Call complete_type_in_void for void cast.
+ * decl.c (cplus_expand_expr_stmt): Void expression checks moved to
+ require_complete_type_in_void. Call it.
+ * cp-tree.h (require_complete_type_in_void): Prototype new function.
+
+ * typeck.c (convert_arguments): Use alternative format for
+ function decls. Don't require_complete_type here. Simplify
+ diagnostic printing.
+ (convert_for_initialization): Don't require_complete_type on RHS yet.
+ * call.c (convert_arg_to_ellipsis): Call require_complete_type.
+
+ * call.c (build_over_call): Cope with qualified void return type.
+ * semantics.c (finish_call_expr): Likewise.
+ * typeck.c (build_function_call_real): Likewise.
+ (c_expand_return): Likewise.
+ * decl2.c (reparse_absdcl_as_expr): Cope with qualified void type.
+
+ * call.c (print_z_candidates): Use alternate print format, to be
+ consistent with (pt.c) print_candidates.
+ * method.c (hack_identifier): List candidate members.
+ * search.c (lookup_field): Build ambiguous list, and show it, if
+ ambiguous.
+
+1999-02-26 Mark Mitchell <mark@markmitchell.com>
+
+ * typeck.c (decay_conversion): Don't confuse constant array
+ variables with their initializers.
+
+ * decl.c (duplicate_decls): Copy DECL_TEMPLATE_INSTANTIATED when
+ merging decls.
+ * pt.c (regenerate_decl_from_template): Tweak for clarity.
+ (instantiate_decl): Mark a decl instantiated before regenerating
+ it to avoid recursion.
+ * tree.c (mapcar): Don't call decl_constant_value unless we know
+ something is TREE_READONLY_DECL_P.
+
+ * class.c (check_for_override): Don't stop checking when we find
+ the first overridden function. Delete #if 0'd code.
+ * search.c (get_matching_virtual): Likewise.
+
+1999-02-25 Richard Henderson <rth@cygnus.com>
+
+ * lang-specs.h: Define __FAST_MATH__ when appropriate.
+
+1999-02-24 Mike Stump <mrs@wrs.com>
+
+ * typeck.c (convert_for_assignment): Allow boolean integral constant
+ expressions to convert to null pointer.
+
+1999-02-24 Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (lookup_namespace_name): Resolve namespace aliases.
+
+ * class.c (push_nested_class): Allow namespaces.
+
+ * decl2.c (set_decl_namespace): Add friendp parameter.
+ * decl.c (grokfndecl): Pass it.
+ (grokvardecl): Likewise.
+ * cp-tree.h: Change declaration.
+
+1999-02-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst): Allow an array of explicit size zero.
+
+1999-02-23 Jason Merrill <jason@yorick.cygnus.com>
+
+ * errfn.c: Change varargs code to look like toplev.c.
+
+ * method.c (process_modifiers): Don't prepend 'U' for char or
+ wchar_t.
+
+1999-02-20 Craig Burley <craig@jcb-sc.com>
+
+ * Make-lang.in (cplib2.ready): Don't consider updating
+ cplib2 stuff if the current directory isn't writable, as
+ it won't work (such as during a `make install').
Sun Feb 21 20:38:00 1999 H.J. Lu (hjl@gnu.org)
@@ -8,42 +1726,1410 @@ Sun Feb 21 20:38:00 1999 H.J. Lu (hjl@gnu.org)
destructors local to the file if ASM_OUTPUT_CONSTRUCTOR and
ASM_OUTPUT_DESTRUCTOR are defined.
-Sat Feb 20 15:08:42 1999 Jeffrey A Law (law@cygnus.com)
+1999-02-19 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (CLASSTYPE_METHOD_VEC): Adjust comment.
+ (fn_type_unification): Adjust prototype.
+ (lookup_fnfields_1): Declare.
+ * call.c (add_template_candidate_real): Adjust call to
+ fn_type_unification.
+ * class.c (add_method): Don't allow duplicate declarations of
+ constructors or destructors.
+ (resolve_address_of_overloaded_function): Remove unused variable.
+ Adjust call to fn_type_unification.
+ * decl.c (grokfndecl): Be more robust in the face of illegal
+ specializations.
+ * decl2.c (check_classfn): Remove hokey handling of member
+ templates.
+ * pt.c (determine_specialization): Improve comments. Adjust to
+ handle template argument deduction as per the standard.
+ (check_explicit_specialization): Fix comment spacing. Handle
+ type-conversion operators correctly. Improve error-recovery.
+ (fn_type_unification): Remove EXTRA_FN_ARG parameter.
+ (get_bindings_real): Simplify handling of static members.
+ * search.c (lookup_fnfields_1): Make it have external linkage.
+ * typeck.c (compparms): Fix comment.
+ (build_unary_op): Don't try to figure out which template
+ specialization is being referred to when when the address-of
+ operator is used with a template function.
+
+Thu Feb 18 23:40:01 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-tree.h (lvalue_or_else): Qualify a char* with the `const'
+ keyword to match an analogous change at the top level.
+
+ * tree.c (lvalue_or_else): Likewise.
+
+1999-02-17 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (xref_basetypes): Comment.
+ * pt.c (instantiate_class_template): Use xref_basetypes.
+
+1999-02-16 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (tsubst): Change prototype.
+ (tsubst_expr): Likewise.
+ (tsubst_copy): Likewise.
+ (type_unification): Remove prototype.
+ * call.c (convert_default_arg): Adjust call to tsubst_expr.
+ * class.c (resolve_address_of_overloaded_function): Just use
+ fn_type_unification.
+ * decl.c (grokdeclarator): Adjust call to tsubst.
+ * method.c (build_template_parm_names): Likewise.
+ * pt.c (GTB_VIA_VIRTUAL): New macro.
+ (GTB_IGNORE_TYPE): Likewise.
+ (resolve_overloaded_unification): Add `complain' parameter.
+ (try_one_overload): Likewise.
+ (tsubst_template_arg_vector): Likewise.
+ (tsubst_template_parms): Likewise.
+ (tsubst_aggr_type): Likewise.
+ (tsubst_arg_types): Likewise.
+ (tsubst_call_declarator_parms): Likewise.
+ (unify): Remove explicit_mask.
+ (type_unification_real): Likewise.
+ (get_template_base_recursive): Likewise.
+ (coerce_template_template_parms): Provide prototype.
+ (tsubst_function_type): Likewise.
+ (try_class_unification): New function.
+ All callers changed to use new complain parameter.
+ (get_template_base): Use try_class_unification.
+ (unify): Adjust handling of classes derived from template types.
+ (fn_type_unification): Substitute explicit arguments before
+ unification.
+
+1999-02-16 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+
+ * decl.c (pushdecl): Remove dead code.
+
+1999-02-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (finish_objects): Fix code I missed in previous change.
+
+1999-02-13 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokfndecl): Return NULL_TREE instead of error_mark_node.
+ (grokdeclarator): Don't expect error_mark_node from grokfndecl.
+
+ * pt.c (maybe_process_partial_specialization): Complain about
+ 'template <>' on non-specialization.
+
+1999-02-10 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokdeclarator): Catch wierd declarators.
+ * decl2.c (finish_file): Don't abort because of namespace parsing
+ failure.
+ (check_decl_namespace): Remove.
+
+1999-02-09 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (get_template_base): Don't declare.
+ (dfs_walk): Declare.
+ (dfs_unmark): Likewise.
+ (markedp): Likewise.
+ * pt.c (unify): Remove duplicate declaration. Pass tparms and
+ targs to get_template_base.
+ (get_template_base_recursive): Move here from search.c. Check to
+ see that the base found can be instantiated to form the desired
+ type.
+ (get_template_base): Likewise.
+ (get_class_bindings): Simplify.
+ * search.c (get_template_base_recursive): Move to pt.c.
+ (get_template_base): Likewise.
+ (markedp): Make it global.
+ (dfs_walk): Likewise.
+ (dfs_unmark): Likewise.
+
+1999-02-07 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (maybe_process_partial_specialization): Complain about
+ specialization in wrong namespace.
+ * tree.c (decl_namespace_context): New fn.
+
+1999-02-06 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+
+ * decl2.c (arg_assoc_type): Handle TEMPLATE_TEMPLATE_PARM.
+ * pt.c (coerce_template_template_parms): Handle nested
+ template template parameters.
+
+Sat Feb 6 18:08:40 1999 Jeffrey A Law (law@cygnus.com)
+
+ * typeck2.c: Update email addresses.
+
+1999-02-04 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+
+ * pt.c (unify): Call coerce_template_parms with the COMPLAIN flag
+ turned off.
+
+1999-02-04 Jason Merrill <jason@yorick.cygnus.com>
+
+ * lex.c (retrofit_lang_decl): Split out...
+ (build_lang_decl): From here.
+ * decl.c (pushdecl): Call it for functions generated by the middle
+ end that don't have DECL_LANG_SPECIFIC.
+ * cp-tree.h: Declare it.
+
+ * decl2.c: Remove flag_init_priority. Always enable initp stuff.
+ (start_objects, finish_objects): Only use special
+ init_priority code if the user specified a priority.
+ (do_ctors, do_dtors): Use DEFAULT_INIT_PRIORITY for the non-initp
+ objects.
+
+Wed Feb 3 22:50:17 1999 Marc Espie <Marc.Espie@liafa.jussieu.fr>
+
+ * Make-lang.in (GXX_OBJS): Remove choose-temp.o, pexecute.o and
+ mkstemp.o. Get them from libiberty now.
+ (DEMANGLER_PROG): Simlarly, remove getopt.o getopt1.o.
+
+Tue Feb 2 22:38:48 1999 Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
+
+ * decl2.c (lang_decode_option): Use read_integral_parameter.
+
+1999-02-01 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (tsubst, case TYPENAME_TYPE): Check TYPE_BEING_DEFINED
+ before calling complete_type_or_else.
+
+Mon Feb 1 09:49:52 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * input.c (inline): Don't define, its handled by system.h.
+
+Sun Jan 31 20:34:29 1999 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * decl2.c: Don't define flag_no_ident here. Don't process
+ -f(no-)ident here.
+ * cp-tree.h: Don't declare flag_no_ident here.
+ * lang-specs.h: Map -Qn to -fno-ident.
+
+1999-01-28 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (struct tree_binding): Replace scope field with a union.
+ (BINDING_SCOPE): Adjust.
+ * decl.c (BINDING_LEVEL): Adjust.
+
+1999-01-26 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (instantiate_class_template): Set up the DECL_INITIAL of
+ member constants.
+
+ * init.c (expand_member_init): Pull out TYPE_MAIN_VARIANT in
+ a ctor initializer.
+
+ * tree.c (equal_functions): Fix name in prototype.
+
+ * decl.c (push_local_binding): Add FLAGS argument.
+ (pushdecl, push_overloaded_decl): Pass it.
+ * decl2.c (do_local_using_decl): Likewise.
+ * cp-tree.h: Adjust prototype.
+ * decl.c (poplevel): Fix logic.
+
+ * decl.c (push_local_binding): Also wrap used decls in a TREE_LIST.
+ (poplevel): Handle that. Fix logic for removing TREE_LISTs.
+ (cat_namespace_levels): Don't loop forever.
+
+1999-01-25 Richard Henderson <rth@cygnus.com>
+
+ * typeck.c (build_reinterpret_cast): Fix typo in duplicated test.
+
+1999-01-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c (resolve_address_of_overloaded_function): Mark the
+ chosen function used.
+
+ * call.c (build_call): Make sure that a function coming in has
+ been marked used already.
+ * decl.c (expand_static_init): Call mark_used instead of
+ assemble_external.
+ * except.c (call_eh_info, do_pop_exception, expand_end_eh_spec,
+ alloc_eh_object, expand_throw): Likewise.
+ * init.c (build_builtin_delete_call): Likewise.
+ * rtti.c (call_void_fn, get_tinfo_fn, build_dynamic_cast_1,
+ expand_si_desc, expand_class_desc, expand_ptr_desc, expand_attr_desc,
+ expand_generic_desc): Likewise.
+
+1999-01-25 Martin von Löwis <loewis@informatik.hu-berlin.de>
- 1999-01-25 Martin von Löwis <loewis@informatik.hu-berlin.de>
* tree.c (equal_functions): New function.
(ovl_member): Call it.
-Sat Feb 6 17:00:48 1999 Jeffrey A Law (law@cygnus.com)
+1999-01-24 Jason Merrill <jason@yorick.cygnus.com>
- * typeck2.c: Update email addresses.
+ * cvt.c (cp_convert_to_pointer): Fix conversion of 0 to pmf.
+
+1999-01-25 Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (decls_match): Return 1 if old and new are identical.
+ (push_overloaded_decl): Set OVL_USED when PUSH_USING.
+
+1999-01-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (start_function): Make member functions one_only on windows.
+ * decl2.c (import_export_decl): Likewise.
+
+ * decl.c (grokdeclarator): Don't complain about implicit int in
+ a system header. Change same-name field check to not complain in
+ a system header instead of within extern "C".
+
+1999-01-21 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (PUSH_GLOBAL): New macro.
+ (PUSH_LOCAL): Likewise.
+ (PUSH_USING): Likewise.
+ (namespace_bindings_p): Declare.
+ (push_overloaded_decl): Likewise.
+ * decl.c (push_overloaded_decl): Don't make it static. Check for
+ illegal declarations after using declarations here.
+ (namespace_bindings_p): Likewise.
+ (duplicate_decls): Don't consider declarations from different
+ namespaces to be the same.
+ (pushdecl): Use symbolic PUSH_ constants in calls to
+ push_overloaded_decl.
+ (push_overloaded_decl_1): Likewise.
+ * decl2.c (validate_nonmember_using_decl): Tweak `std' handling.
+ (do_nonmember_using_decl): Check for illegal using declarations
+ after ordinary declarations here.
+ (do_local_using_decl): Call pushdecl to insert declarations.
+
+1999-01-21 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokdeclarator): Fix lang_c -> lang_name_c typo.
+
+1999-01-21 Mark Mitchell <mark@markmitchell.com>
+
+ * tree.c (build_cplus_array_type_1): Don't call build_array_type
+ for types involving template parameters.
+
+ * cp-tree.h (PARM_DECL_EXPR): Delete.
+ (convert_default_arg): Change prototype.
+ (check_default_argument): Declare.
+ (search_tree): Likewise.
+ * call.c (convert_default_arg): Take the function to which the
+ default argument belongs as a parameter, and do any necessary
+ instantiation here, instead of ...
+ (build_over_call): Here.
+ * decl.c (local_variable_p): New function.
+ (check_default_argument): Likewise, split out and tidied from ...
+ (grokparms): Here.
+ * error.c (dump_expr): Don't set PARM_DECL_EXPR.
+ * pt.c (tsubst_call_declarator_parms): New function.
+ (for_each_template_parm): Handle ARRAY_REFs. Do the obvious thing
+ with CALL_EXPRs, rather than trying to be clever.
+ (tsubst): Use tsubst_call_declarator_parms.
+ * tree.c (search_tree): Don't make it static.
+ * typeck.c (convert_arguments): Use new interface to
+ convert_default_arg.
+
+1999-01-20 Mark Mitchell <mark@markmitchell.com>
+
+ * error.c (dump_function_decl): Don't print the argument types for
+ a function when the verbosity level is negative.
+
+ * call.c (build_over_call): Check format attributes at call-time.
+
+ * pt.c (tsubst_copy): Fix comment.
+ (unify): Don't allow unification with variable-sized arrays.
+
+ * semantics.c (finish_stmt_expr): When processing a template make
+ the BIND_EXPR long-lived.
+
+1999-01-19 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (finish_vtable_vardecl): Make vtables comdat here.
+ (import_export_vtable): Not here.
+
+1999-01-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (build_component_ref): Wrap an OVERLOAD around a unique
+ non-static member function.
+
+1999-01-18 Nathan Sidwell <nathan@acm.org>
+
+ * class.c (instantiate_type): Only diagnose illegal address of member
+ function if complaining.
+
+ * decl.c (lookup_name_real): Remove duplicate code.
+
+1999-01-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (copy_template_template_parm): Use permanent_obstack.
+
+1999-01-18 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+
+ * pt.c (unify): Remove restrictions on deduction of argument
+ of template template parameters.
+
+1999-01-18 Nathan Sidwell <nathan@acm.org>
+
+ * rtti.c (build_dynamic_cast_1): Resolve OFFSET_REF exprs.
+
+ * class.c (resolve_address_of_overloaded_function): Show list of
+ all candidates, when none of them match.
+
+1999-01-18 Chip Salzenberg <chip@perlsupport.com>
+
+ * typeck.c (comp_ptr_ttypes_reinterpret): Per ANSI, tighten up
+ definition of 'casting away const' in reinterpret_cast<>.
+
+1999-01-18 Graham <grahams@rcp.co.uk>
+
+ * cvt.c: Add include for decl.h, remove extern for
+ static_aggregates which is now provided by decl.h.
+
+ * Makefile.in (cvt.o): Add dependency for decl.h and missing
+ dependencies for convert.h and flags.h.
+
+1999-01-18 Nathan Sidwell <nathan@acm.org>
+
+ * decl2.c (do_dtors): Set current location to that of the
+ decl, for sensible diagnostics and debugging.
+ (check_classfn): Issue `incomplete type' error, if
+ class is not defined.
+
+1999-01-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h: Add prototype for bound_pmf_p.
+
+1999-01-16 Jason Merrill <jason@yorick.cygnus.com>
+ Manfred Hollstein <manfred@s-direktnet.de>
+
+ * decl.c (grokdeclarator): Don't make 'main(){}' an error with only
+ -Wreturn-type.
+
+1999-01-16 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct lang_type): Added has_mutable flag.
+ (CLASSTYPE_HAS_MUTABLE): New macro to access it.
+ (TYPE_HAS_MUTABLE_P): New macro to read it.
+ (cp_has_mutable_p): Prototype for new function.
+ * class.c (finish_struct_1): Set has_mutable from members.
+ * decl.c (cp_finish_decl): Clear decl's TREE_READONLY flag, if
+ it contains a mutable.
+ * typeck.c (cp_has_mutable_p): New function.
+
+1999-01-15 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (process_template_parm): Ignore top-level qualifiers on
+ non-type parameters.
+
+ * decl.c (start_function): Use current_function_parms in the call
+ to require_complete_type_for_parms, not the probably empty
+ DECL_ARGUMENTS.
+
+1999-01-14 Jason Merrill <jason@yorick.cygnus.com>
+
+ * semantics.c (finish_asm_stmt): Don't warn about redundant volatile.
+
+ * decl2.c (import_export_class): MULTIPLE_SYMBOL_SPACES only means
+ that we don't suppress the other copies.
+ * lex.c (handle_cp_pragma): Likewise.
+
+1999-01-13 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Undo 1998-12-14 change.
+ * tree.c (build_cplus_array_type_1): Likewise.
+ * pt.c (instantiate_class_template): Remove misleading comment.
+ (tsubst_aggr_type): Substitute if there are template parameters,
+ regardless of whether or not they use template arguments.
+ (unify): Likewise, but for unification.
+
+1999-01-12 Richard Henderson <rth@cygnus.com>
+
+ * cp-tree.h (flag_permissive): Declare extern.
+
+1999-01-06 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (IDENTIFIER_TYPENAME_P): Use OPERATOR_TYPENAME_FORMAT
+ here.
+ (lang_type): Add is_partial_instantiation. Decrease width of
+ dummy.
+ (PARTIAL_INSTANTIATION_P): New macro.
+ (OPERATOR_TYPENAME_P): Remove.
+ * decl.c (unary_op_p): Use IDENTIFIER_TYPENAME_P, not
+ OPERATOR_TYPENAME_P.
+ (grok_op_properties): Likewise.
+ * friend.c (do_friend): Handle friends that are member functions
+ correctly.
+ * lex.c (init_parse): Use OPERATOR_TYPENAME_FORMAT.
+ * pt.c (instantiate_class_template): Rework for clarity. Avoid
+ leaving TYPE_BEING_DEFINED set in obscure cases. Don't do
+ any more partial instantiation than is absolutely necessary for
+ implicit typename. Set PARTIAL_INSTANTIATION_P.
+ (tsubst_decl): Use IDENTIFIER_TYPENAME_P.
+ * semantics.c (begin_class_definition): Handle partial
+ specializations of a type that was previously partially
+ instantiated.
+
+Wed Jan 6 03:18:53 1999 Mark Elbrecht <snowball3@usa.net.
+
+ * g++spec.c (LIBSTDCXX): Provide default definition.
+ (lang_specific_driver): Use LIBSTDCXX instead of "-lstdc++".
+
+Tue Jan 5 22:11:25 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Make-lang.in (g++.o): Depend on prefix.h.
+
+1999-01-04 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (bound_pmf_p): New fn.
+ * typeck.c (build_c_cast): Use it.
+
+ * decl.c (grok_op_properties): Use same_type_p.
+
+Tue Dec 22 15:09:25 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (cvt.o): Depend on toplev.h.
+
+ * cp-tree.h (check_template_shadow, pod_type_p): Add prototypes.
+
+ * cvt.c: Include toplev.h.
+
+ * except.c (get_eh_caught, get_eh_handlers): Hide prototypes and
+ definitions.
+
+ * init.c (expand_vec_init): Initialize variable `itype'.
+
+ * lex.c (yyerror): Cast the argument passed to a ctype function to
+ an unsigned char.
+
+ * method.c (build_mangled_C9x_name): Wrap prototype and definition
+ in "HOST_BITS_PER_WIDE_INT >= 64".
+
+ * typeck.c (build_binary_op): Mark parameter `convert_p' with
+ ATTRIBUTE_UNUSED.
+
+1998-12-22 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (TYPE_RAISES_EXCEPTIONS): Improve documentation.
+ * tree.c (build_exception_variant): Don't crash on empty throw
+ specs.
+
+1998-12-18 DJ Delorie <dj@cygnus.com>
+
+ * cvt.c (convert_to_reference): Check for both error_mark_node
+ and NULL_NODE after call to convert_for_initialization.
+
+1998-12-17 Jason Merrill <jason@yorick.cygnus.com>
+
+ * error.c (interesting_scope_p): New fn.
+ (dump_simple_decl): Use it.
+ (dump_expr, case CONSTRUCTOR): Force a & for a PMF.
+ (dump_expr, case OFFSET_REF): Print ->* if appropriate.
+
+1998-12-16 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (resolve_address_of_overloaded_function): Do conversion
+ to correct type here, rather than ...
+ (instantiate_type): Here.
+
+ * cp-tree.h (DECL_TEMPLATE_PARM_P): New macro.
+ (DECL_TEMPLATE_TEMPLATE_PARM_P): Use it.
+ (decl_template_parm_p): Remove.
+ * decl.c (pushdecl): Don't set DECL_CONTEXT for a template
+ parameter.
+ * lex.c (do_identifier): Use DECL_TEMPLATE_PARM_P.
+ * pt.c (push_inline_template_parms_recursive): Set it.
+ (decl_template_parm_p): Remove.
+ (check_template_shadow): Use DECL_TEMPLATE_PARM_P.
+ (process_template_parm): Set it.
+
+Wed Dec 16 16:33:58 1998 Dave Brolley <brolley@cygnus.com>
+
+ * lang-specs.h (default_compilers): Pass -MD, -MMD and -MG to cc1plus
+ if configured with cpplib.
+
+1998-12-15 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (poplevel): Make sure ns_binding is initialized.
+
+ * decl.c (finish_function): Undo inadvertent change in previous
+ patch.
+
+1998-12-14 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (pushclass): Tweak handling of class-level bindings.
+ (resolve_address_of_overloaded_function): Update pointer-to-member
+ handling.
+ (instantiate_type): Likewise.
+ * cvt.c (cp_convert_to_pointer): Likewise.
+ * decl.c (pop_binding): Take the DECL to pop, not just the name.
+ Deal with `struct stat' hack.
+ (binding_level): Add to documentation.
+ (push_binding): Clear BINDING_TYPE.
+ (add_binding): New function.
+ (push_local_binding): Use it.
+ (push_class_binding): Likewise.
+ (poplevel): Adjust calls to pop_binding.
+ (poplevel_class): Likewise.
+ (pushdecl): Adjust handling of TYPE_DECLs; add bindings for hidden
+ declarations to current binding level.
+ (push_class_level_binding): Likewise.
+ (push_overloaded_decl): Adjust handling of OVERLOADs in local
+ bindings.
+ (lookup_namespace_name): Don't crash when confronted with a
+ TEMPLATE_DECL.
+ (lookup_name_real): Do `struct stat' hack in local binding
+ contexts.
+ (build_ptrmemfunc_type): Adjust documentation.
+ (grokdeclarator): Don't avoid building real array types when
+ processing templates unless really necessary.
+ (finish_method): Adjust calls to pop_binding.
+ * decl2.c (reparse_absdcl_as_expr): Recursively call ourselves,
+ not reparse_decl_as_expr.
+ (build_expr_from_tree): Deal with a template-id as the function to
+ call in a METHOD_CALL_EXPR.
+ * pt.c (convert_nontype_argument): Tweak pointer-to-member handling.
+ (maybe_adjust_types_For_deduction): Don't do peculiar things with
+ METHOD_TYPEs here.
+ (resolve_overloaded_unification): Handle COMPONENT_REFs. Build
+ pointer-to-member types where necessary.
+ * tree.c (build_cplus_array_type_1): Don't avoid building real
+ array types when processing templates unless really necessary.
+ (build_exception_variant): Compare the exception lists correctly.
+
+1998-12-13 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.def (CPLUS_BINDING): Update documentation.
+ * cp-tree.h (LOCAL_BINDING_P): New macro.
+ (lang_identifier): Rename local_value to bindings.
+ (tree_binding): Make `scope' of type `void*', not `tree'.
+ (BINDING_SCOPE): Update documentation.
+ (IDENTIFIER_LOCAL_VALUE): Remove.
+ (IDENTIFIER_CLASS_VALUE): Document.
+ (IDENTIFIER_BINDING): New macro.
+ (IDENTIFIER_VALUE): Likewise.
+ (TIME_IDENTIFIER_TIME): Likewise.
+ (TIME_IDENTIFIER_FILEINFO): Likewise.
+ (IMPLICIT_TYPENAME_P): Likewise.
+ (set_identifier_local_value): Remove.
+ (push_local_binding): New function.
+ (push_class_binding): Likewise.
+ * class.c (pushclass): Update comments; use push_class_binding.
+ * decl.c (set_identifier_local_value_with_scope): Remove.
+ (set_identifier_local_value): Likewise.
+ (push_binding): New function.
+ (pop_binding): Likewise.
+ (binding_level): Update documentation. Remove shadowed.
+ (BINDING_LEVEL): New macro.
+ (free_binding_nodes): New variable.
+ (poplevel): Adjust for new name-lookup scheme. Don't mess up
+ BLOCK_VARs when doing for-scope extension. Remove effectively
+ dead code.
+ (pushlevel_class): Tweak formatting.
+ (poplevel_class): Adjust for new name-lookup scheme.
+ (print_binding_level): Likewise.
+ (store_bindings): Likewise.
+ (pushdecl): Likewise.
+ (pushdecl_class_level): Likewise.
+ (push_class_level_binding): Likewise.
+ (push_overloaded_decl): Update comments. Adjust for new
+ name-lookup scheme.
+ (lookup_name_real): Likewise.
+ (lookup_name_current_level): Likewise.
+ (cp_finish_decl): Likewise.
+ (require_complete_types_for_parms): Likewise. Remove misleading
+ #if 0'd code.
+ (grok_parms): Likewise. Don't call
+ require_complete_types_for_parms here.
+ (grok_ctor_properties): Don't treat templates as copy
+ constructors.
+ (grop_op_properties): Or as assignment operators.
+ (start_function): Document. Adjust for new name-lookup scheme.
+ (finish_function): Likewise.
+ * decl2.c (do_local_using_decl): Use push_local_binding.
+ * lex.c (begin_definition_of_inclass_inline): New function, split
+ out from ...
+ (do_pending_inlines): Here, and ...
+ (process_next_inline): Here.
+ (get_time_identifier): Use TIME_IDENTIFIER_* macros.
+ (init_filename_times): Likewise.
+ (extract_interface_info): Likewise.
+ (ste_typedecl_interface_info): Likewise.
+ (check_newline): Likewise.
+ (dump_time_statistics): Likewise.
+ (handle_cp_pragma): Likewise.
+ (do_identifier): Adjust for new name-lookup scheme.
+ * parse.y (function_try_block): Return ctor_initializer_opt value.
+ (fndef): Use it.
+ (fn.defpen): Pass appropriate values to start_function.
+ (pending_inline): Use functor_try_block value, and pass
+ appropriate values to finish_function.
+ * pt.c (is_member_template): Update documentation; remove handling
+ of FUNCTION_DECLs. As per name, this function should deal only in
+ TEMPLATE_DECLs.
+ (decl_template_parm_p): Change name of olddecl parameter to decl.
+ (check_template_shadow): Adjust for new name-lookup scheme.
+ (lookup_template_class): Likewise.
+ (tsubst_decl): Tweak so as not to confuse member templates with
+ copy constructors and assignment operators.
+ (unify): Handle UNION_TYPEs.
+ * ptree.c (print_lang_identifier): Adjust for new name-lookup scheme.
+ (lang_print_xnode): Adjust for new name-lookup scheme.
+ * typeck.c (mark_addressable): Likewise.
+ (c_expand_return): Likewise.
+
+1998-12-08 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokdeclarator): Allow field with same name as class
+ in extern "C".
+
+ * decl.c (lookup_name_real): Don't limit field lookup to types.
+ * class.c (check_member_decl_is_same_in_complete_scope): No error
+ if icv and x are the same.
+ * lex.c (do_identifier): Tweak error message.
+
+1998-12-10 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (start_enum): Use push_obstacks, not
+ end_temporary_allocation.
+ (finish_enum): Call pop_obstacks.
+
+1998-12-10 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (instantiate_type): Return error_mark_node rather than
+ junk.
+
+1998-12-09 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (most_specialized_instantiation): New function.
+ (print_candidates): Likewise.
+ * class.c (validate_lhs): Remove.
+ (resolve_address_of_overloaded_function): New function, split out
+ and then substantially reworked, from ...
+ (instantiate_type): Use it. Simplify.
+ * cvt.c (convert_to_reference): Complain when caller has indicated
+ that's the right thing to do. Don't crash if instantiate_type
+ fails.
+ * pt.c: Substitute `parameters' for `paramters' throughout.
+ (print_candidates): Don't make it static.
+ (most_specialized_instantiation): Split out from ...
+ (most_specialized): Here.
+
+Wed Dec 9 15:33:01 1998 Dave Brolley <brolley@cygnus.com>
+
+ * lex.c (lang_init_options): Initialize cpplib.
+ * decl2.c (parse_options,cpp_initialized): Removed.
+ (lang_decode_option): Move initialization of cpplib to
+ lang_init_options.
+
+1998-12-09 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Update the name of the TEMPLATE_DECL, as
+ well as the TYPE_DECL, when a typedef name is assigned to a
+ previously anonymous type.
+
+1998-12-08 Andrew MacLeod <amacleod@cygnus.com>
+
+ * cp/except.c (call_eh_info): Use __start_cp_handler instead of
+ __cp_eh_info for getting the eh info pointer. Add table_index to
+ field list.
+ (push_eh_cleanup): Don't increment 'handlers' data field.
+ (process_start_catch_block): Don't set the 'caught' field.
+
+ * cp/exception.cc (CP_EH_INFO): New macro for getting the
+ exception info pointer within library routines.
+ (__cp_eh_info): Use CP_EH_INFO.
+ (__start_cp_handler): Get exception info pointer, set caught field,
+ and increment the handlers field. Avoids this being done by handlers.
+ (__uncatch_exception, __check_eh_spec): Use CP_EH_INFO macro.
+ (uncaught_exception): Use CP_EH_INFO macro.
+
+Tue Dec 8 10:48:21 1998 Jeffrey A Law (law@cygnus.com)
+
+ * Make-lang.in (cxxmain.o): Depend on $(DEMANGLE_H), not demangle.h
+
+Mon Dec 7 17:56:06 1998 Mike Stump <mrs@wrs.com>
+
+ * lex.c (check_newline): Add support for \ as `natural'
+ characters in file names in #line to be consistent with #include
+ handling. We support escape processing in the # 1 "..." version of
+ the command. See also support in cp/lex.c.
+
+1998-12-07 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * cp/decl2.c: s/data/opts/ when initializing cpp_reader
+ structure.
+
+1998-12-07 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (build_typename_type): Set DECL_ARTIFICIAL.
+
+ * error.c (dump_simple_decl): Also print namespace context.
+ (dump_function_decl): Likewise.
+
+ * decl2.c (ambiguous_decl): Don't print old value if it's
+ error_mark_node.
+
+ * decl.c (lookup_name_real): Fix handling of local types shadowed
+ by a non-type decl. Remove obsolete code.
+ * cp-tree.h (DECL_FUNCTION_SCOPE_P): New macro.
+
+ * lang-options.h: Add -fpermissive.
+ * decl2.c: Likewise.
+ * cp-tree.h: Add flag_permissive.
+ * decl.c (init_decl_processing): If neither -fpermissive or -pedantic
+ were specified, set flag_pedantic_errors.
+ * call.c (build_over_call): Turn dropped qualifier messages
+ back into pedwarns.
+ * cvt.c (convert_to_reference): Likewise.
+ * typeck.c (convert_for_assignment): Likewise.
+
+1998-12-05 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (coerce_new_type): Use same_type_p.
+ (coerce_delete_type): Likewise.
+
+ * call.c (check_dtor_name): Return 1, not error_mark_node.
+
+1998-12-04 Jason Merrill <jason@yorick.cygnus.com>
+
+ * lex.c (handle_cp_pragma): Disable #pragma interface/implementation
+ if MULTIPLE_SYMBOL_SPACES.
+
+ * pt.c (check_template_shadow): New fn.
+ * decl2.c (grokfield): Use it.
+ * decl.c (pushdecl): Likewise.
+ (pushdecl_class_level): Likewise.
+ (start_method): Likewise.
+ (xref_tag): Don't try to use 't' if we're defining.
+
+ * call.c (check_dtor_name): Just return an error_mark_node.
+ * pt.c (lookup_template_class): Complain about using non-template here.
+ * parse.y (apparent_template_type): Not here.
+
+ * pt.c (check_explicit_specialization): Complain about specialization
+ with C linkage.
+
+ * lang-options.h: Add -f{no-,}implicit-inline-templates.
+
+ * pt.c (convert_nontype_argument): Don't assume that any integer
+ argument is intended to be a constant-expression.
+
+1998-12-03 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (handle_using_decl): Fix comment. Don't lookup
+ constructors in base classes.
+ (validate_lhs): Fix typo in comment.
+ * search.c (lookup_field_1): Don't return a USING_DECL.
+
+ * cp-tree.h (DECL_ACCESS): Improve documentation.
+
+ * decl.c (expand_static_init): Don't set the initialization-done
+ flag until the initialization is done.
+
+1998-12-02 Mark Mitchell <mark@markmitchell.com>
+
+ * decl2.c (validate_nonmember_using_decl): Complain about using
+ declarations for class members.
+
+1998-11-29 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck2.c (process_init_constructor): Use same_type_p.
+
+ * decl.c (check_tag_decl): Don't warn about null decl inside a
+ class.
+
+ * pt.c (unify, case OFFSET_TYPE): Pass down 'strict' rather than
+ UNIFY_ALLOW_NONE.
+ (convert_nontype_argument): Use TYPE_PTRMEMFUNC_FN_TYPE.
+ (resolve_overloaded_unification): Strip baselinks.
+
+Fri Nov 27 13:07:23 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * g++spec.c: Don't prototype xmalloc.
+
+1998-11-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * except.c (expand_throw): Use TYPE_PTR_P to check for pointers.
+
+ * decl.c (check_tag_decl): Do complain about null friend decl at
+ file scope.
+
+1998-11-25 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
+
+ * lex.c (make_lang_type): Clear the whole struct lang_type, not
+ only the first multiple of sizeof (int).
+
+1998-11-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (start_decl): An explicit specialization of a static data
+ member is only a definition if it has an initializer.
+
+ * except.c (expand_throw): Use cp_finish_decl for the throw temp.
+ * cvt.c (build_up_reference): Pass DIRECT_BIND down into
+ cp_finish_decl.
+ * init.c (expand_default_init): Check for DIRECT_BIND instead of
+ DECL_ARTIFICIAL.
+
+ * call.c (build_over_call): Use build_decl.
+
+ * except.c (expand_throw): Just use convert, not
+ build_reinterpret_cast.
+
+ * lex.c (handle_generic_pragma): Use token_buffer.
+
+ * decl.c (check_tag_decl): Don't complain about null friend decl.
+
+1998-11-24 Dave Pitts <dpitts@cozx.com>
+
+ * Make-lang.in (DEMANGLER_PROG): Move the output arguments to the
+ first position.
+ * lex.c (check_newline): Use ISALPHA.
+ (readescape): Use ISGRAPH.
+ (yyerror): Use ISGRAPH.
+
+1998-11-24 Nathan Sidwell <nathan@acm.org>
+
+ * search.c (get_abstract_virtuals): Do not use initial
+ CLASSTYPE_ABSTRACT_VIRTUALS.
+ * typeck2.c (abstract_virtuals_error): Show location of abstract
+ declaration.
+ * call.c (build_new_method_call): Use
+ CLASSTYPE_ABSTRACT_VIRTUAL, rather than recalculate.
+ * class.c (finish_struct_bits): Don't bother working out whether
+ get_abstract_virtuals will do anything, just do it.
+
+1998-11-24 Graham <grahams@rcp.co.uk>
+
+ * typeck.c (build_component_ref): Remove unused statement.
+
+1998-11-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c (add_method): Catch invalid overloads.
+
+ * class.c (add_method): Build up OVERLOADs properly for conversion ops.
+ * search.c (lookup_conversions): Handle getting real OVERLOADs.
+ (add_conversions): Likewise. Revert last change.
+ * call.c (add_conv_candidate): Pass totype to add_candidate instead
+ of fn. Don't add a new candidate if the last one was for the same
+ type.
+ (print_z_candidates): Handle getting a type as a function.
+ (joust): If we got two conversion candidates to the same type,
+ just pick one.
+ (build_object_call): Lose 'templates'.
+ (build_user_type_conversion_1): Handle getting real OVERLOADs.
+
+1998-11-23 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck2.c (process_init_constructor): If there are elements
+ that don't have initializers and they need to have constructors
+ run, supply them with initializers.
+
+ * class.c (finish_struct_1): A class with a 0-width bitfield is
+ still empty.
+
+1998-11-23 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (instantiate_class_template): Don't try to figure out what
+ specialization to use for a partial instantiation. Correct
+ typos in a couple of comments. Avoid calling uses_template_parms
+ multiple times.
+
+1998-11-23 Benjamin Kosnik <bkoz@cygnus.com>
+
+ * method.c (process_overload_item): Add call to
+ build_mangled_C9x_name for intTI_type_nodes.
+ (build_mangled_C9x_name): Add prototype, define.
+ * decl.c (init_decl_processing): Add names for
+ TImode_type_node.
+
+1998-11-23 Jason Merrill <jason@yorick.cygnus.com>
+
+ * parse.y (named_class_head): Update CLASSTYPE_DECLARED_CLASS.
+
+ * class.c (finish_struct_1): Set things up for 0-width bitfields
+ like we do for others.
+
+ * decl.c (check_tag_decl): New fn.
+ (shadow_tag): Split out from here.
+ * decl2.c (grok_x_components): Call it.
+
+1998-11-22 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c: Lose warn_about_return_type.
+ (grokdeclarator): Always complain about implicit int, except for
+ `main () { ... }'.
+
+ * decl.c (tag_name): New fn.
+ (xref_tag): Complain about using typedef-name after class-key.
+
+ * init.c (expand_vec_init): Also keep going if from_array.
+
+ * tree.c (is_overloaded_fn): Also handle the output of
+ build_offset_ref.
+
+ * decl.c (grokdeclarator): Use constructor_name when comparing
+ field name against enclosing class.
+ * class.c (finish_struct_anon): Likewise.
+
+1998-11-22 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (poplevel): Remove code to handle KEEP == 2.
+ (finish_function): Don't confuse BLOCK-order when
+ processing a destructor.
+
+1998-11-21 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (require_complete_types_for_parms): Call layout_decl
+ after we've completed the type.
+
+1998-11-21 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl2.c (validate_nonmember_using_decl): Allow using templates
+ from the global namespace.
+
+1998-11-21 Jason Merrill <jason@yorick.cygnus.com>
+
+ Handle specifying template args to member function templates.
+ * tree.c (build_overload): Always create an OVERLOAD for a template.
+ * search.c (add_conversions): Handle finding an OVERLOAD.
+ * decl2.c (check_classfn): Likewise.
+ * lex.c (identifier_type): See through a baselink.
+ * parse.y (do_id): Don't call do_identifier if we got a baselink.
+ * class.c (instantiate_type, case TREE_LIST): Recurse.
+
+ * decl.c (grokdeclarator): Allow a boolean constant for array
+ bounds, odd as that sounds.
+
+ * pt.c (unify): Be more strict about non-type parms, except for
+ array bounds.
+ (UNIFY_ALLOW_INTEGER): New macro.
+
+1998-11-19 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * Make-lang.in (mandir): Replace all uses of $(mandir) by $(man1dir).
+
+1998-11-19 Jason Merrill <jason@yorick.cygnus.com>
+
+ * semantics.c (begin_class_definition): Call
+ maybe_process_partial_specialization before push_template_decl.
+ Don't call push_template_decl for a specialization.
+ * search.c (lookup_field): Do return a member template class.
+ * decl2.c (handle_class_head): Handle member template classes.
+
+ * decl.c (grokdeclarator): A parm type need not be complete.
+
+ * pt.c (convert_nontype_argument): Fix thinko.
+
+1998-11-18 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (PTRMEM_CST_CLASS): Fix typo.
+ (global_delete_fndecl): New variable.
+ * decl.c (global_delete_fndecl): Define it.
+ (init_decl_processing): Set it.
+ * init.c (build_builtin_delete_call): Use it.
+ * tree.c (mapcar): Recursively call mapcar for the type of EXPR
+ nodes.
+
+1998-11-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (cplus_expand_expr_stmt): Always complain about unresolved
+ type.
+
+ * tree.c (lvalue_p_1): An INDIRECT_REF to a function is an lvalue.
+ * call.c (build_object_call): Also support references to functions.
+ * typeck.c (convert_for_initialization): Don't decay a function
+ if the target is a reference to function.
+
+ * search.c (add_conversions): Get all the overloads from a class.
+
+ * decl.c (grok_ctor_properties): Complain about any constructor
+ that will take a single arg of the class type by value.
+
+ * typeck2.c (build_functional_cast): Can't create objects of
+ abstract classes this way.
+ * cvt.c (ocp_convert): Likewise.
+
+ * decl.c (grokfndecl): Member functions of local classes are not
+ public.
+
+1998-11-18 Mark Mitchell <mark@markmitchell.com>
+
+ * Make-lang.in (cc1plus): Add dependency on hash.o.
+
+1998-11-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * search.c (get_abstract_virtuals): Complain about virtuals with
+ no final overrider.
+ * typeck2.c (abstract_virtuals_error): Remove handling for virtuals
+ with no final overrider.
+ * class.c (override_one_vtable): Don't set DECL_ABSTRACT_VIRTUAL_P
+ on virtuals with no final overrider.
+
+ * lex.c (reinit_parse_for_block): Add a space after the initial ':'.
+
+ * class.c (finish_struct_1): Don't remove zero-width bit-fields until
+ after layout_type.
+
+ * friend.c (do_friend): Don't set_mangled_name_for_decl.
+
+ * class.c (finish_struct_anon): Complain about non-fields.
+ * decl2.c (build_anon_union_vars): Likewise.
+
+ * decl.c (grokdeclarator): Normal data members can't have the same
+ name as the class, either.
+ * class.c (finish_struct_anon): Neither can members of an
+ anonymous union.
+
+1998-11-17 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (TYPE_ALIAS_SET): Document language-dependent uses.
+ (TYPE_BINFO): Likewise.
+ (IS_AGGR_TYPE): Tweak.
+ (SET_IS_AGGR_TYPE): New macro.
+ (CLASS_TYPE_P): Tweak.
+ (lang_type): Group mark bitfields together. Remove linenum.
+ (CLASSTYPE_SOURCE_LINE): Remove macro.
+ (CLASSTYPE_MARKED_N): New macro.
+ (SET_CLASSTYPE_MARKED_N): Likewise.
+ (CLEAR_CLASSTYPE_MARKED_N): Likewise.
+ (CLASS_TYPE_MARKED_*): Use them.
+ (SET_CLASSTYPE_MARKED_*): Likewise.
+ (CLEAR_CLASSTYPE_MARKED_*): Likewise.
+ (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO): Likewise.
+ (TYPE_TEMPLATE_INFO): Handle TEMPLATE_TEMPLATE_PARMs as well.
+ (TYPENAME_TYPE_FULLNAME): Use TYPE_BINFO rather than CLASSTYPE_SIZE.
+ * class.c (class_cache_obstack): New variable.
+ (class_cache_firstobj): Likewise.
+ (finish_struct): Don't set CLASSTYPE_SOURCE_LINE.
+ (pushclass): Free the cache, when appropriate.
+ (popclass): Tidy.
+ (maybe_push_cache_obstack): Use class_cache_obstack.
+ * decl.c (include hash.h).
+ (typename_hash): New function.
+ (typename_compare): Likewise.
+ (build_typename_type): Check the hash table to avoid creating
+ duplicates.
+ (build_ptrmemfunc_type): Use SET_IS_AGGR_TYPE.
+ (grokdeclarator): Use CLASS_TYPE_P.
+ (xref_basetypes): Likewise.
+ (start_function): Likewise. Don't put current_class_ref on the
+ permanent obstack.
+ * error.c (dump_type_real): Use TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO
+ and TYPE_TI_ARGS.
+ * lex.c (note_got_semicolon): Use CLASS_TYPE_P.
+ (make_lang_type): Don't create TYPE_LANG_SPECIFIC and associated
+ fields for types other than class types. Do clear TYPE_ALIAS_SET
+ for types other than class types, though.
+ * method.c (build_overload_identifier): Use CLASS_TYPE_P and
+ TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO.
+ * pt.c (process_template_parm): Don't set
+ CLASSTYPE_GOT_SEMICOLON.
+ (lookup_template_class): Use TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO.
+ Coerce arguments on the momentary obstack.
+ (for_each_template_parm): Use TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO.
+ (instantiate_class_template): Calculate template arguments on the
+ momentary obstack. Tidy.
+ (tsubst_template_arg_vector): Use make_temp_vec.
+ (tsubst_aggr_type): Put template arguments on the momentary
+ obstack.
+ (tsubst_decl): Likewise.
+ (tsubst): Copy the array bounds index to the permanent obstack
+ before building index types. Use new macros.
+ (unify): Use new macros.
+ (do_type_instantiation): Likewise.
+ * search.c (lookup_fnfields_1): Use new macros.
+ (dfs_pushdecls): Build envelopes on the cache obstack.
+ (dfs_compress_decls): Use new macros.
+ (push_class_decls): Build on the cache obstack.
+ * semantics.c (finish_typeof): Don't set CLASSTYPE_GOT_SEMICOLON.
+ * sign.c (build_signature_pointer_or_reference_type): Use
+ SET_IS_AGGR_TYPE.
+ * tree.c (make_binfo): Check CLASS_TYPE_P.
+ (copy_template_template_parm): Adjust.
+ (make_temp_vec): Use push_expression_obstack.
+ * typeck.c (complete_type): Use new macros.
+ (comptypes): Likewise.
+
+1998-11-17 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst): Add diagnostics for invalid array, reference
+ and pointer to member types.
1998-11-16 Jason Merrill <jason@yorick.cygnus.com>
* typeck2.c (my_friendly_abort): Don't fatal twice in a row.
+ * typeck.c (c_expand_start_case): Use build_expr_type_conversion.
+ Simplify.
+
+ * parse.y (structsp): Fix cut-and-paste error.
+
+ * init.c (build_new): Complain about non-integral size.
+
+ * parse.y (unary_expr): Complain about defining types in sizeof.
+
+ * typeck.c (expr_sizeof): Complain about sizeof an overloaded fn.
+
+ * rtti.c (build_x_typeid): Complain about typeid without
+ including <typeinfo>.
+ (get_typeid): Likewise. Complain about typeid of incomplete type.
+ (get_tinfo_fn_dynamic): Likewise.
+ (get_typeid_1): Not static anymore.
+ * except.c (build_eh_type_type): Use get_typeid_1.
+
+ * rtti.c (build_dynamic_cast_1): Give errors for dynamic_cast to
+ ambiguous or private bases. Fix warning for reference cast.
+
+1998-11-16 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (DECL_TEMPLATE_INSTANTIATED): New macro.
+ * decl.c (duplicate_decls): Remove special-case code to deal with
+ template friends, and just do the obvious thing.
+ * pt.c (register_specialization): Tweak for clarity, and also to
+ clear DECL_INITIAL for an instantiation before it is merged with a
+ specialization.
+ (check_explicit_specialization): Fix indentation.
+ (tsubst_friend_function): Handle both definitions in friend
+ declaration and outside friend declarations.
+ (tsubst_decl): Don't clear DECL_INITIAL for an instantiation.
+ (regenerate_decl_from_template): Tweak accordingly.
+ (instantiate_decl): Likewise.
+
+1998-11-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (cplus_expand_expr_stmt): Promote warning about naked
+ member function reference to error.
+ * cvt.c (ocp_convert): Complain about converting an overloaded
+ function to void.
+
+ * init.c (build_offset_ref): Just return a lone static member
+ function.
+
+ * decl.c (cp_finish_decl): Only complain about real CONSTRUCTORs,
+ not internal ones.
+
+ * typeck.c (build_binary_op_nodefault): Improve error handling.
+
+ * decl.c (grokfndecl): Complain about making 'main' a template.
+
+ * typeck.c (string_conv_p): Don't convert from wchar_t[] to char*.
+
+ * call.c (build_method_call): Handle a BIT_NOT_EXPR around a
+ TYPE_DECL in a template.
+
1998-11-15 Jason Merrill <jason@yorick.cygnus.com>
* typeck2.c (my_friendly_abort): Add URL in the other case, too.
-1998-11-13 Jason Merrill <jason@yorick.cygnus.com>
+ * decl.c (struct cp_function): Add named_label_uses.
+ (push_cp_function_context): Save it.
+ (pop_cp_function_context): Restore it.
+ (define_label): Also complain about jumping into the scope of
+ non-POD objects that don't have constructors.
+ * tree.c (pod_type_p): New fn.
+ * pt.c (instantiate_class_template): Clear TYPE_BEING_DEFINED sooner.
* rtti.c (synthesize_tinfo_fn): Call import_export_decl here.
(get_tinfo_fn): Not here.
+ * repo.c (repo_get_id): Abort if we get called for an incomplete
+ type.
+
+1998-11-13 Mark Mitchell <mark@markmitchell.com>
+
+ * except.c (expand_throw): Make sure first argument to
+ __cp_push_exception is of type `void*' to avoid spurious error
+ messages.
+
+1998-11-11 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (try_one_overload): Take orig_targs again. Only check for
+ mismatches against them; we don't care what a previous call found.
+ (resolve_overloaded_unification): Adjust.
+
+ * search.c (lookup_field): Don't return anything for a non-type
+ field from a dependent type.
+ * decl.c (grokdeclarator): Resolve SCOPE_REFs of the current class
+ in an array declarator.
+ (start_decl): Push into the class before looking for the field.
1998-11-08 Mark Mitchell <mark@markmitchell.com>
- * 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.
+ * method.c (build_overload_value): Handle REFERENCE_TYPE.
+
+1998-11-08 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (grokdeclarator): Allow namespace-scoped members if they
+ are friends.
+
+1998-11-08 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst_decl): Don't mess with the global value of an
+ un-mangled DECL_ASSEMBLER_NAME.
+
+1998-11-03 Christopher Faylor <cgf@cygnus.com>
+
+ * decl.c (init_decl_processing): Remove CYGWIN conditional
+ since CYGWIN is now able to deal with trapping signals.
+
+Sat Nov 7 15:48:02 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-tree.h: Don't include gansidecl.h.
+ * exception.cc: Include gansidecl.h (since we don't include config.h)
+ * g++spec.c: Don't include gansidecl.h.
+
+1998-11-06 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (lang_decl_flags): Add defined_in_class. Decrease
+ size of dummy.
+ (DECL_DEFINED_IN_CLASS_P): New macro.
+ (TEMPLATE_PARMS_FOR_INLINE): Document.
+ (check_static_variable_definition): New function.
+ * decl.c (cp_finish_decl): Set DECL_DEFINED_IN_CLASS_P, if
+ appropriate.
+ (check_static_variable_definition): Split out from ...
+ (grokdeclarator): Here.
+ * pt.c (check_default_tmpl_args): New function, split out from ...
+ (push_template_decl_real): Here.
+ (instantiate_template): Fix comment.
+
+1998-11-04 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (CP_TYPE_CONST_P): Make {0,1}-valued.
+ (CP_TYPE_VOLATILE_P): Likewise.
+ (CP_TYPE_RESTRICT_P): Likewise.
+
+1998-11-03 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (tsubst): Use build_index_type, not build_index_2_type.
1998-11-02 Jason Merrill <jason@yorick.cygnus.com>
+ * class.c (instantiate_type): Be more helpful.
+
* decl2.c (import_export_decl): Call import_export_class.
+ * cp-tree.h (EMPTY_CONSTRUCTOR_P): Check !TREE_HAS_CONSTRUCTOR.
+ * decl2.c (build_expr_from_tree): Propagate TREE_HAS_CONSTRUCTOR.
+ * pt.c (tsubst_copy): Likewise.
+
+1998-11-02 Mark Mitchell <mark@markmitchell.com>
+
+ * init.c (expand_vec_init): Fix off-by-one error.
+
+1998-11-02 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * parse.y (apparent_template_type): New type.
+ (named_complex_class_head_sans_basetype): Use it.
+ * Makefile.in (CONFLICTS): One new conflict.
+ * parse.c: Regenerated.
+
+1998-11-01 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (COMPARE_STRICT): New macro.
+ (COMPARE_BASE): Likewise.
+ (COMPARE_RELAXED): Likewise.
+ (COMPARE_REDECLARATION): Likewise.
+ (same_type_p): Likewise.
+ (same_or_base_type_p): Likewise.
+ * call.c (standard_conversion): Use them, in place of comptypes
+ with numeric arguments.
+ (reference_binding): Likewise.
+ (convert_like): Likewise.
+ (build_over_call): Likewise.
+ (is_subseq): Likewise.
+ (is_properly_derived_from): Likewise.
+ (compare_ics): Likewise.
+ (joust): Likewise.
+ * class.c (delete_duplicate_fields_1): Likewise.
+ (resolves_to_fixed_type_p): Likewise.
+ (instantiate_type): Likewise. Remove #if 0'd code.
+ * decl.c (decls_match): Likewise. Use COMPARE_REDECLARATION here.
+ (pushdecl): Likewise.
+ (lookup_name_real): Likewise.
+ (grokdeclarator): Likewise. Check for illegal array declarations.
+ (grokparms): Likewise.
+ (grok_op_properties): Likewise.
+ * decl2.c (check_classfn): Likewise.
+ * friend.c (is_friend): Likewise.
+ (make_friend_class): Likewise.
+ * init.c (expand_aggr_init): Likewise.
+ (expand_vec_init): Likewise.
+ * pt.c (is_member_template_class): Remove declaration.
+ (is_specialization_of): Use COMPARE_* and new macros.
+ (comp_template_parms): Likewise.
+ (convert_nontype_argument): Likewise.
+ (coerce_template_template_parms): Likewise.
+ (template_args_equal): Likewise.
+ (lookup_template_class): Likewise.
+ (type_unification_real): Likewise.
+ (unify): Likewise.
+ (get_bindings_real): Likewise.
+ * search.c (covariant_return_p): Likewise.
+ (get_matching_virtual): Likewise.
+ * sig.c (match_method_types): Likewise.
+ * tree.c (vec_binfo_member): Likewise.
+ (cp_tree_equal): Likewise.
+ * typeck.c (common_type): Likewise.
+ (comp_array_types): Likewise. Get issues involving unknown array
+ bounds right.
+ (comptypes): Update comments. Use new flags.
+ (comp_target_types): Use new macros.
+ (compparms): Likewise.
+ (comp_target_parms): Likewise.
+ (string_conv_p): Likewise.
+ (build_component_ref): Likewise.
+ (build_indirect_ref): Likewise.
+ (build_conditional_expr): Likewise.
+ (build_static_cast): Likewise.
+ (build_reinterpret_cast): Likewise.
+ (build_const_cast): Likewise.
+ (build_modify_expr): Likewise.
+ (convert_for_assignment): Likewise.
+ (comp_ptr_ttypes_real): Likewise.
+ (ptr_reasonably_similar): Likewise.
+ (comp_ptr_ttypes_const): Likewise.
+
+1998-10-31 Jason Merrill <jason@yorick.cygnus.com>
+
+ * rtti.c (build_dynamic_cast_1): Fix cut-and-paste error.
+
+1998-10-30 Mark Mitchell <mark@markmitchell.com>
+
+ * decl2.c (delete_sanity): Pass integer_zero_node, not
+ integer_two_node, to build_vec_delete.
+ * init.c (build_array_eh_cleanup): Remove.
+ (expand_vec_init_try_block): New function.
+ (expand_vec_init_catch_clause): Likewise.
+ (build_vec_delete_1): Don't deal with case that auto_delete_vec
+ might be integer_two_node anymore.
+ (expand_vec_init): Rework for initialization-correctness and
+ exception-correctness.
+ * typeck2.c (process_init_constructor): Make mutual exclusivity
+ of cases more obvious.
+
+1998-10-29 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (lookup_name_real): OK, only warn if not lexing.
+ Simplify suggested fix.
+
+ * cp-tree.h (IDENTIFIER_MARKED): New macro.
+ * search.c (lookup_conversions): Use breadth_first_search.
+ (add_conversions): Avoid adding two conversions to the same type.
+ (breadth_first_search): Work with base binfos, rather
+ than binfos and base indices.
+ (get_virtual_destructor): Adjust.
+ (tree_has_any_destructor_p): Adjust.
+ (get_matching_virtual): Adjust.
+
+ * pt.c (push_template_decl_real): Generalize check for incorrect
+ number of template parms.
+ (is_member_template_class): #if 0.
+
+1998-10-29 Richard Henderson <rth@cygnus.com>
+
+ * Makefile.in (cc1plus): Put CXX_OBJS, and thence @extra_cxx_objs@,
+ last.
+
+1998-10-28 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * lex.c: Call check_newline from lang_init always. After
+ calling cpp_start_read, set yy_cur and yy_lim to read from the
+ cpplib token buffer.
+
1998-10-28 Jason Merrill <jason@yorick.cygnus.com>
+ * class.c (instantiate_type): Don't consider templates for a normal
+ match.
+
* class.c (finish_struct_1): Don't complain about non-copy
assignment ops in union members.
@@ -54,99 +3140,1872 @@ Sat Feb 6 17:00:48 1999 Jeffrey A Law (law@cygnus.com)
(finish_prevtable_vardecl): Lose.
(finish_file): Don't call it.
* pt.c (instantiate_class_template): Likewise.
+ * cp-tree.h: Remove it.
+
+ * init.c (build_delete): Reset TYPE_HAS_DESTRUCTOR here.
+ * decl.c (finish_function): Not here.
+ (start_function): Do set DECL_INITIAL.
+
+ * pt.c (push_template_decl_real): Complain about default template
+ args for enclosing classes.
+
+ * call.c (add_function_candidate): Treat conversion functions
+ as coming from the argument's class.
+ * cp-tree.h (DECL_CONV_FN_P): New fn.
+ (DECL_DESTRUCTOR_P): Also check DECL_LANGUAGE.
+ * class.c (add_method): Use DECL_CONV_FN_P.
+ * decl2.c (check_classfn): Likewise.
+ * error.c (dump_function_name): Likewise.
+ (dump_function_decl): Likewise.
+ * pt.c (fn_type_unification): Likewise.
+ * search.c (add_conversions): Likewise.
+
+1998-10-27 Jason Merrill <jason@yorick.cygnus.com>
+
+ * lex.c (do_identifier): Also generate LOOKUP_EXPR for RESULT_DECL.
+ * method.c (hack_identifier): Also check for using RESULT_DECL
+ from outer context.
+
+1998-10-27 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Use type_quals, rather than constp,
+ consistently.
+
+1998-10-27 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (standard_conversion): instantiate_type here.
+ (reference_binding): And here.
+ (implicit_conversion): Not here.
+ (build_op_delete_call): No need to cons up an OVERLOAD.
+ * cvt.c (cp_convert_to_pointer): instantiate_type here.
+ (convert_to_reference): And here.
+ * decl.c (grok_reference_init): Not here.
+ (grokparms): Or here.
+ * typeck2.c (digest_init): Or here.
+ * typeck.c (decay_conversion): Take the address of overloaded
+ functions, too.
+ (require_instantiated_type): Lose.
+ (convert_arguments): Don't handle unknown types here.
+ (build_c_cast): Likewise.
+ (build_binary_op): Gut.
+ (build_conditional_expr): Don't require_instantiated_type.
+ (build_modify_expr): Likewise.
+ (build_static_cast): Don't instantiate_type.
+ (build_reinterpret_cast): Likewise.
+ (build_const_cast): Likewise.
+ (convert_for_initialization): Likewise.
+ (build_ptrmemfunc): Use type_unknown_p.
+ (convert_for_assignment): Also do default_conversion on overloaded
+ functions. Hand them off to ocp_convert.
+
+1998-10-26 Mark Mitchell <mark@markmitchell.com>
+
+ * error.c (dump_decl): Deal with TEMPLATE_DECLs that are
+ VAR_DECLs. Handle vtables whose DECL_CONTEXT is not a type.
+
+ * class.c (finish_struct_1): Use build_cplus_array_type to build
+ array types.
+ * decl.c (init_decl_processing): Likewise.
+ * except.c (expand_end_eh_spec): Likewise.
+ * search.c (expand_upcast_fixups): Simplify very slightly.
+
+1998-10-26 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokdeclarator): Complain about a variable using
+ constructor syntax coming back null from start_decl.
+
+ * friend.c (make_friend_class): Complain about trying to make
+ a non-class type a friend.
+
+ * decl.c (grokfndecl): Set DECL_INITIAL for a defn here.
+ (start_function): Not here.
+
+1998-10-26 Brendan Kehoe <brendan@cygnus.com>
+
+ * decl.c (grokdeclarator): Disallow `explicit' in a friend declaration.
+
+1998-10-26 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck2.c (process_init_constructor): Only skip anonymous fields
+ if they are bitfields.
+
+ * cp-tree.def (TYPEOF_TYPE): New code.
+ * error.c (dump_type_real): Handle it.
+ * pt.c (tsubst): Likewise.
+ * tree.c (search_tree): Likewise.
+ * semantics.c (finish_typeof): New fn.
+ * parse.y (typespec): Use it.
+ * cp-tree.h: Declare it.
+
+1998-10-26 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * cp-tree.h (FORMAT_VBASE_NAME): Make definition unconditional.
+
+1998-10-26 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (convert_arguments): Don't handle pmf references
+ specially.
+
+ * init.c (build_member_call): Don't try to convert to the base type
+ if it's ambiguous or pedantic.
+
+ * typeck2.c (check_for_new_type): Only depend on pedantic for
+ C-style casts.
+
+1998-10-25 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Set DECL_NONCONVERTING_P for all
+ non-converting constructors.
+
+1998-10-24 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * gxxint.texi: Correct documentation for n, N, Q, and B.
1998-10-23 Martin von Löwis <loewis@informatik.hu-berlin.de>
* parse.y (condition): Convert VAR_DECL from reference to indirect
reference.
-1998-10-18 Jason Merrill <jason@yorick.cygnus.com>
+1998-10-23 Andrew MacLeod <amacleod@cygnus.com>
+
+ * exception.cc (__cp_pop_exception): Free the original exception
+ value, not the potentially coerced one.
+
+1998-10-23 Mark Mitchell <mark@markmitchell.com>
+
+ * Makefile.in (hash.h): Run gperf when necessary.
+
+ * cp-tree.h (CP_TYPE_READONLY): Remove.
+ (CP_TYPE_VOLATILE): Likewise.
+ (CP_TYPE_QUALS): New macro.
+ (CP_TYPE_CONST_P): Likewise.
+ (CP_TYPE_VOLATILE_P): Likewise.
+ (CP_TYPE_RESTRICT_P): Likewise.
+ (CP_TYPE_CONST_NON_VOLATILE_P): Likewise.
+ (cp_build_type_variant): Rename to ...
+ (cp_build_qualified_type): New function.
+ (c_apply_type_quals_to_decl): Declare.
+ (SIGNATURE_POINTER_NAME_FORMAT): Modify to allow `restrict'.
+ (SIGNATURE_REFERENCE_NAME_FORMAT): Likewise.
+ (cp_type_qual_from_rid): New function.
+ (compparms): Remove unused parameter. All callers changed.
+ (cp_type_quals): New function.
+ (at_least_as_qualified_p): Likewise.
+ (more_qualified_p): Likewise.
+
+ * call.c (standard_conversion): Replace calls to
+ cp_build_type_variant with cp_build_qualified_type. Use
+ CP_TYPE_QUALS to get qualifiers and at_least_as_qualified_p to
+ compare them. Use CP_TYPE_* macros to check qualifiers.
+ (reference_binding): Likewise.
+ (implicit_conversion): Likewise.
+ (add_builtin_candidates): Likewise.
+ (build_over_call): Likewise.
+ * class.c (overrides): Compare all qualifiers, not just `const',
+ on method declarations.
+ * cvt.c (convert_to_reference): More CP_TYPE_QUALS conversion, etc.
+ (convert_pointer_to_real): Likewise.
+ (type_promotes_to): Likewise.
+ * decl.c (check_for_uninitialized_const_var): New function.
+ (init_decl_processing): More CP_TYPE_QUALS conversion, etc.
+ (cp_finish_decl): Use check_for_uninitialized_const_var.
+ (grokdeclarator): More CP_TYPE_QUALS conversion, etc. Update to
+ handle `restrict'.
+ (grok_ctor_properties): Likewise.
+ (grok_op_properties): Likewise.
+ (start_function): Likewise.
+ (rever_static_member_fn): Likewise.
+ * decl2.c (grok_method_quals): Likewise.
+ (grokfield): Likewise.
+ * error.c (dump_readonly_or_volatile): Rename to ...
+ (dump_qualifiers): New function. Handle `restrict'.
+ (dump_type_real): Use it.
+ (dump_aggr_type): Likewise.
+ (dump_type_prefix): Likewise.
+ (dump_type_suffix): Likewise.
+ (dump_function_decl): Likewise.
+ (cv_as_string): Likewise.
+ * gxx.gperf: Add __restrict and __restrict__.
+ * gxxint.texi: Document `u' as used for `__restrict', and a few
+ other previously undocumented codes.
+ * hash.h: Regenerated.
+ * init.c (expand_aggr_init): More CP_TYPE_QUALS conversion, etc.
+ (build_member_call): Likewise.
+ (build_new_1): Likewise.
+ * lex.c (init_parse): Add entry for RID_RESTRICT.
+ (cons_up_default_function): More CP_TYPE_QUALS conversion, etc.
+ (cp_type_qual_from_rid): Define.
+ * lex.h (enum rid): Add RID_RESTRICT.
+ * method.c (process_modifiers): Deal with `restrict'.
+ * parse.y (primary): More CP_TYPE_QUALS conversion, etc.
+ * parse.c: Regenerated.
+ * pt.c (convert_nontype_argument): More CP_TYPE_QUALS conversion, etc.
+ (tsubst_aggr_type): Likewise.
+ (tsubst): Likewise.
+ (check_cv_quals_for_unify): Likewise.
+ (unify): Likewise.
+ * rtti.c (init_rtti_processing): Likewise.
+ (build_headof): Likewise.
+ (get_tinfo_var): Likewise.
+ (buidl_dynamic_cast_1): Likewise. Fix `volatile' handling.
+ (expand_class_desc): Likewise.
+ (expand_attr_desc): Likewise.
+ (synthesize_tinfo_fn): Likewise.
+ * search.c (covariant_return_p): Likewise. Fix `volatile' handling.
+ (get_matching_virtual): Likewise.
+ (expand_upcast_fixups): Likewise.
+ * sig.c (build_signature_pointer_or_reference_name): Take
+ type_quals, not constp and volatilep.
+ (build_signature_pointer_or_reference_type): Likewise.
+ (match_method_types): More CP_TYPE_QUALS conversion, etc.
+ (build_signature_pointer_constructor): Likewise.
+ (build_signature_method_call): Likewise.
+ * tree.c (build_cplus_array_type): Likewise.
+ (cp_build_type_variant): Rename to ...
+ (cp_build_qualified_type): New function. Deal with `__restrict'.
+ (canonical_type_variant): More CP_TYPE_QUALS conversion, etc.
+ (build_exception_variant): Likewise.
+ (mapcar): Likewise.
+ * typeck.c (qualif_type): Likewise.
+ (common_type): Likewise.
+ (comptypes): Likewise.
+ (comp_cv_target_types): Likewise.
+ (at_least_as_qualified_p): Define.
+ (more_qualified_p): Likewise.
+ (comp_cv_qualification): More CP_TYPE_QUALS conversion, etc.
+ (compparms): Likewise.
+ (inline_conversion): Likewise.
+ (string_conv_p): Likewise.
+ (build_component_ref): Likewise.
+ (build_indirect_ref): Likewise.
+ (build_array_ref): Likewise.
+ (build_unary_op): Likewise.
+ (build_conditional_expr): Likewise.
+ (build_static_cast): Likewise.
+ (build_c_cast): Likewise.
+ (build_modify_expr): Likewise.
+ (convert_For_assignment): Likewise.
+ (comp_ptr_ttypes_real): Likewise.
+ (cp_type_quals): New function.
+
+1998-10-23 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (CP_TYPE_READONLY): New macro to handle arrays.
+ (CP_TYPE_VOLATILE): Likewise.
+ * decl.c (grokdeclarator): Use them.
+ * tree.c (canonical_type_variant): Likewise.
+
+1998-10-22 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * parse.y (named_class_head): Push into class while parsing the
+ base class list.
+ * decl2.c (push_scope, pop_scope): New functions.
+ * cp-tree.h: Declare them.
+ * init.c (build_new_1): Delay cleanup until end of full expression.
+
+1998-10-21 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (hack_identifier): Just return a member function.
+ * typeck.c (build_component_ref): Use of a type here is an error.
+
+1998-10-19 Jason Merrill <jason@yorick.cygnus.com>
+
+ Revamp references to member functions.
+ * method.c (hack_identifier): Call build_component_ref for a
+ reference to a member function.
+ * typeck.c (build_component_ref): Only return a single function
+ if it's static. Otherwise, return a COMPONENT_REF.
+ (build_x_function_call): Handle a COMPONENT_REF.
+ (build_unary_op): Handle all unknown-type things.
+ * decl2.c (arg_assoc): Handle COMPONENT_REF.
+ * class.c (instantiate_type): Complain if the function we get is a
+ nonstatic member function. Remove code for finding "compatible"
+ functions.
+ * pt.c (tsubst_copy): Handle NOP_EXPR.
+ * tree.c (build_dummy_object): New fn.
+ (maybe_dummy_object): New fn.
+ (is_dummy_object): New fn.
+ * cp-tree.h: Declare them.
+ * cvt.c (cp_convert_to_pointer): Use maybe_dummy_object.
+ * error.c (dump_expr, case OFFSET_REF): Use is_dummy_object.
+ * init.c (build_member_call): Use maybe_dummy_object and
+ is_dummy_object.
+ (build_offset_ref): Use maybe_dummy_object.
+ (resolve_offset_ref): Use is_dummy_object.
+ * typeck.c (build_x_function_call): Call build_dummy_object.
+ (unary_complex_lvalue): Call is_dummy_object.
+
+ * typeck.c (build_component_addr): Make sure field is a field.
+
+ * call.c (build_new_op): Delete obsolete code.
+
+ * pt.c (tsubst, TEMPLATE*PARM*): Abort if we don't have any args.
1998-10-18 Martin von Löwis <loewis@informatik.hu-berlin.de>
* decl2.c (validate_nonmember_using_decl): Fix using-directives of
std if std is ignored.
-1998-10-14 Jason Merrill <jason@yorick.cygnus.com>
+1998-10-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokvardecl): Fix thinko.
+
+ * decl.c (grokdeclarator): Embedded attrs bind to the right,
+ not the left.
+
+ * parse.y (fn.def2): Fix 'attrs' format.
+
+1998-10-18 Alastair J. Houghton <ajh8@doc.ic.ac.uk>
+
+ * Makefile.in (CONFLICTS): Update.
+ * parse.y (expr_or_declarator_intern): New rule.
+ (expr_or_declarator, direct_notype_declarator, primary,
+ functional_cast): Use it.
+ (notype_declarator_intern): New rule.
+ (notype_declarator, complex_notype_declarator): Use it.
+
+1998-10-17 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokfndecl): Set DECL_CONTEXT to namespace if appropriate.
+ (grokvardecl): Likewise.
+
+Sat Oct 17 23:27:20 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * class.c (make_method_vec): Cast 1st argument of `bzero' to (PTR).
+ (add_method): Likewise for arguments 1 & 2 of `bcopy'.
+
+ * decl.c (signal_catch): Mark with ATTRIBUTE_NORETURN.
+
+ * pt.c (process_partial_specialization): Cast 1st argument of
+ `bzero' to (PTR).
+
+ * tree.c (build_base_fields): Cast `base_align' to (int) when
+ comparing against one.
+
+1998-10-16 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (lookup_name_real): Handle template parameters for member
+ templates where said parameters have the same name as the
+ surrounding class.
+
+ * decl.c (expand_static_init): Build cleanups before entering the
+ anonymous function used to do them to avoid access-checking
+ confusion.
+
+ * decl.c (grokfndecl): Add back call to cplus_decl_attributes
+ accidentally removed by previous change, and make DECL_RTL here.
+ * class.c (add_method): Don't make DECL_RTL here.
+
+ * pt.c (for_each_template_parm): Don't examine uninstantiated
+ default arguments.
+
+1998-10-16 Dave Brolley <brolley@cygnus.com>
+
+ * lex.c (real_yylex): Fix unaligned access of wchar_t.
+
+1998-10-16 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (add_method): Fix documentation to reflect previous
+ changes. Check for duplicate method declarations here.
+ * decl.c (decls_match): Handle FUNCTION_DECL vs TEMPLATE_DECL
+ correctly; such things never match.
+ (grokfndecl): Don't look for duplicate methods here.
+ * decl2.c (check_classfn): Don't assume names are mangled.
+ Don't add bogus member function declarations to a class before the
+ class type is complete.
+ (grokfield): Reformat error message.
+ * method.c (set_mangled_name_for_decl): Don't mangle names while
+ processing_template_decl.
+
+1998-10-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (build_indirect_ref): Complain about a pointer to data
+ member, too.
+ * typeck2.c (build_m_component_ref): Don't indirect a pointer to
+ data member.
+ * init.c (resolve_offset_ref): Don't undo the above.
+
+ * cp-tree.h (DECL_C_BIT_FIELD, SET_DECL_C_BIT_FIELD): New macros.
+ (struct lang_decl_flags): Add `bitfield'.
+ * class.c (finish_struct_1): Use DECL_C_BIT_FIELD instead of
+ DECL_BIT_FIELD.
+ * decl2.c (grokbitfield, grok_alignof): Likewise.
+ * init.c (build_offset_ref): Likewise.
+ * typeck.c (build_component_addr, expr_sizeof): Likewise.
+ * cvt.c (build_up_reference): Don't crash if taking the address
+ returns error_mark_node.
+
+ * decl.c (grokfndecl): Also check ctype when checking for ::main().
+
+1998-10-15 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokfndecl): ::main and __builtin_* get C linkage.
+ Do mangling here.
+ (grokdeclarator): Instead of here.
+ * friend.c (do_friend): Lose special handling of ::main and
+ __builtin_*.
+ * cp-tree.h (DECL_MAIN_P): Check for C linkage.
* spew.c (yylex): Clear looking_for_typename if we got
'enum { ... };'.
+1998-10-15 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (maybe_warn_about_overly_private_class): Improve error
+ messages for class with only private constructors.
+
+ * cp-tree.def (TYPENAME_TYPE): Add to documentation.
+ * cp-tree.h (TYPENAME_TYPE_FULLNAME): Document.
+ (build_typename_type): New function.
+ * decl.c (build_typename_type): Broken out from ...
+ (make_typename_type): Use it.
+ * search.c (lookup_field): Likewise.
+
+1998-10-14 Benjamin Kosnik <bkoz@rhino.cygnus.com>
+
+ * pt.c (convert_nontype_argument): Check against type_referred_to.
+ * decl.c (grokvardecl): Check for declarator name before building
+ DECL_ASSEMBLER_NAME.
+
+1998-10-14 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (lookup_template_class): Add comment.
+ (instantiate_class_template): Don't mark the _TYPE node for
+ member class templates as an instantiation.
+
+1998-10-14 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokfndecl): Fix my thinko.
+
1998-10-13 Jason Merrill <jason@yorick.cygnus.com>
* tinfo2.cc (fast_compare): Remove.
(before): Just use strcmp.
* tinfo.cc (operator==): Just use strcmp.
+1998-10-13 Klaus-Georg Adams <Klaus-Georg.Adams@chemie.uni-karlsruhe.de>
+
+ * decl.c (grokfndecl): Don't check for linkage in `extern "C"'
+ declarations.
+
+1998-10-13 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (specializations_of_same_template_p): Remove.
+ * search.c (get_template_base): Don't use it.
+ (get_template_base_recursive): Likewise.
+ * pt.c (specializations_of_same_template_p): Remove.
+ (unify): Don't use it.
+ (lookup_template_class): Find the correct parent when setting
+ CLASSTYPE_TI_TEMPLATE.
+
1998-10-12 Jason Merrill <jason@yorick.cygnus.com>
* tinfo.cc (operator==): Always compare names.
+1998-10-12 Herman ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * decl.c (start_function): Fix cut-and-paste error.
+
1998-10-12 Jason Merrill <jason@yorick.cygnus.com>
* inc/typeinfo: Add #pragma interface.
(operator!=): Just call operator==.
* tinfo.cc: Add #pragma implementation.
(operator==): Move from inc/typeinfo and tinfo2.cc.
+ Check __COMMON_UNRELIABLE instead of _WIN32.
* typeck2.c (my_friendly_abort): Add URL.
+1998-10-12 Alastair J. Houghton <ajh8@doc.ic.ac.uk>
+
+ * decl.c (start_method): Added extra parameter for attributes.
+ * cp-tree.h (start_method): Update prototype.
+ * parse.y (fn.def2): Update start_method parameter list.
+
+1998-10-11 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (specializations_of_same_template_p): Declare.
+ * pt.c (specializations_of_same_template_p): New function.
+ (unify): Use it.
+ * search.c (get_template_base): Use it.
+ (get_template_base_recursive): Likewise.
+
+1998-10-10 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * decl2.c (start_objects): Add new variable `joiner' and
+ initialize it properly.
+
+1998-10-09 Mark Mitchell <mark@markmitchell.com>
+
+ * search.c (expand_upcast_fixups): Tweak to match 1998-10-07
+ change to vtable types.
+
+ * cvt.c (ocp_convert): Avoid infinite recursion caused by
+ 1998-10-03 change.
+
+1998-10-08 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (resolve_overloaded_unification): New fn.
+ (try_one_overload): Likewise.
+ (unify): Don't fail on unknown type.
+ (type_unification_real): Likewise. Use resolve_overloaded_unification
+ to handle an overloaded argument.
+ (template_args_equal): Split out...
+ (comp_template_args): From here.
+ (determine_specialization): Also allow a template with more
+ parms than were explicitly specified.
+ * cp-tree.h: Add template_args_equal.
+ * call.c (resolve_args): Remove TEMPLATE_ID_EXPR code.
+
+Thu Oct 8 15:58:30 1998 Anthony Green <green@cygnus.com>
+
+ * semantics.c (finish_asm_stmt): Revert my 1998-09-28
+ change.
+
+Thu Oct 8 06:00:19 1998 Jeffrey A Law (law@cygnus.com)
+
+ * typeck.c (unsigned_type): Only return TItype nodes when
+ HOST_BITS_PER_WIDE_INT is >= 64 bits.
+ (signed_type): Likewise.
+ * decl.c (intTI_type_node, unsigned_intTI_type_node): Only declare
+ when HOST_BITS_PER_WIDE_INT is >= 64 bits.
+ (init_decl_processing): Only create TItype nodes when
+ HOST_BITS_PER_WIDE_INT is >= 64 bits.
+ * cp-tree.h (intTI_type_node, unsigned_intTI_type_node): Only declare
+ when HOST_BITS_PER_WIDE_INT is >= 64 bits.
+
+Wed Oct 7 12:32:44 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (hash.h): Add -L KR-C -F ', 0, 0' flags to gperf.
+ (gxx.gperf): Update comments describing invocation flags.
+ (hash.h): Regenerate using gperf 2.7.1 (19981006 egcs).
+
+1998-10-07 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (finish_struct_1): Add commentary on previous change.
+
+ * cp-tree.h (vtbl_ptr_type_node): New variable.
+ * class.c (build_vtbl_ref): Don't indirect through the vptr; it's
+ already of the right type.
+ (finish_struct_1): Make the vptr be of type vtbl_ptr_type_node.
+ Simplify code to grow vtable.
+ * decl.c (vtbl_ptr_type_node): Define.
+ (init_decl_processing): Initialize it.
+
+1998-10-06 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.def (PTRMEM_CST): New tree node.
+ * cp-tree.h (ptrmem_cst): New type.
+ (lang_type): Remove local_typedecls.
+ (dummy): Increase to 12 bits from 11.
+ (CLASSTYPE_LOCAL_TYPEDECLS): Remove.
+ (PTRMEM_CST_CLASS): New macro.
+ (PTRMEM_CST_MEMBER): Likewise.
+ (current_access_specifier): New variable.
+ (current_class_type): Remove duplicate declaration.
+ (finish_struct): Change prototype.
+ (unreverse_member_declarations): New function.
+ (pushdecl_class_level): Change prototype.
+ (grok_enum_decls): Remove.
+ (fixup_anonymous_union): New function.
+ (grok_x_components): Change prototype.
+ (tsubst_chain): Remove.
+ (finish_member_template_decl): Likewise.
+ (check_explicit_specialization): Fix indentation.
+ (finish_class_definition): Change prototype.
+ (finish_member_class_template): Likewise.
+ (finish_member_declaration): New function.
+ (check_multiple_declarators): Likewise.
+ * class.c (class_stack_node_t): New type.
+ (current_class_base): Remove.
+ (current_class_stack): Change type.
+ (current_access_specifier): New variable.
+ (grow_method): Remove.
+ (check_member_decl_is_same_in_complete_scope): Break out from
+ finish_struct.
+ (make_method_vec): New function.
+ (free_method_vec): Likewise.
+ (add_implicitly_declared_members): Break out from finish_struct_1.
+ (free_method_vecs): New variable.
+ (add_method): Rework for direct use from parser.
+ (handle_using_decl): Watch for NULL_TREE while iterating through
+ CLASSTYPE_METHOD_VEC.
+ (finish_struct_methods): Don't build CLASSTYPE_METHOD_VEC here;
+ just do some error-checking.
+ (warn_hidden): Change iteration through CLASSTYPE_METHOD_VEC.
+ (finish_struct_1): Simplify. Use add_implicitly_declared_members.
+ (finish_struct): Change prototype. Simplify; fields and methods
+ are already set up at this point.
+ (init_class_processing): Set up current_class_stack.
+ (pushclass): Save current_access_specifier.
+ (popclass): Restore it.
+ (currently_open_class): Simplify.
+ (build_self_reference): Remove use of CLASSTYPE_LOCAL_TYPEDECLS.
+ * decl.c (saved_scope): Add access_specifier.
+ (maybe_push_to_top_level): Save it.
+ (pop_from_top_level): Restore it.
+ (maybe_process_template_type_declaration): Use
+ finish_member_declaration.
+ (pushtag): Likewise.
+ (pushdecl_class_level): Don't return a value.
+ (fixup_anonymous_union): Break out from grok_x_components.
+ (shadow_tag): Use it.
+ (xref_tag): Complain about using an elaborated type specifier to
+ reference a template type parameter or typedef name.
+ (xref_basetypes): Don't set CLASSTYPE_LOCAL_TYPEDECLS.
+ (current_local_enum): Remove.
+ (build_enumerator): Call finish_member_declaration.
+ (grok_enum_decls): Remove.
+ * decl2.c (grok_x_components): Simplify.
+ (check_classfn): Change iteration through CLASSTYPE_METHOD_VEC.
+ (grokfield): Don't set CLASSTYPE_LOCAL_TYPEDECLS.
+ (merge_functions): Add to comment.
+ (arg_assoc_type): Prototype.
+ (arg_assoc): Pass as many arguments as there are parameters.
+ * error.c (dump_expr): Handle PTRMEM_CST. Improve handling of
+ OFFSET_REF.
+ * expr.c (cpls_expand_expr): Remove dead code. Handle
+ PTRMEM_CST.
+ * friend.c (do_friend): Lookup friends when in nested classes.
+ Change comments.
+ * init.c (build_offset_ref): Do lookup even for classes that are
+ only partially defined.
+ (decl_constant_value): Remove dead code.
+ * method.c (build_overload_value): Remove hack where by TYPE was
+ not a TYPE. Handle PTRMEM_CST.
+ (build_template_parm_names): Don't pass a PARM_DECL where a TYPE
+ should go.
+ * parse.y (components, notype_components, component_decl,
+ component_decl_1, component_declarator, component_declarator0):
+ Now all are itype rather than ttype. Rework to add members to
+ classes on the fly.
+ (typesqpecqual_reserved): Use check_multiple_declarators.
+ (structsp): Update class to finish_class_definition.
+ (do_xref_defn): Unsplit into named_class_head.
+ (access_specifier): Set current_access_specifier.
+ * pt.c (set_current_access_from_decl): New function.
+ (finish_member_template_decl): Don't take the parameters.
+ (comp_template_args): Make more robust.
+ (lookup_template_class): Don't use current_local_enum.
+ (for_each_template_parm): Handle PTRMEM_CST.
+ (instantiate_class_template): Use set_current_access_from_decl,
+ finish_member_declaration and unreverse_member_declarations. Set
+ lineno/input_filename before generating implicit member functions.
+ (type_unification_real): Don't assume back-unification happens
+ only for the last argument.
+ (regenerate_decl_from_template): Call pushclass a bit earlier.
+ (tsubst_chain): Remove.
+ (tsubst_enum): Use set_current_access_from_decl.
+ (set_mangled_name_for_template_decl): Fix indentation.
+ * search.c (lookup_fnfields_1): Change iteration through
+ CLASSTYPE_METHOD_VEC.
+ (dfs_pushdecls): Likewise.
+ (dfs_compress_decls): Likewise.
+ (add_conversions): Likewise.
+ * semantics.c (finish_class_definition): Don't take components.
+ Change call to finish_struct.
+ (finish_member_declaration): New function.
+ (finish_member_class_template): Don't take template parameters.
+ Change call to grok_x_components. Call finish_member_template_decl.
+ (check_multiple_declarators): New function.
+ * sig.c (append_signature_fields): Work from the TYPE_METHODS, not
+ a passed in fieldlist.
+ * tree.c (search_tree): Handle PTRMEM_CST.
+ (mapcar): Likewise.
+ * typeck.c (unary_complex_lvalue): Build PTRMEM_CSTs, not
+ INTEGER_CSTs, for pointer-to-data members.
+
+ * call.c (resolve_args): Resolve template specializations, if
+ possible.
+
+Tue Oct 6 07:57:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (spew.o): Depend on toplev.h.
+
+ * call.c (compare_ics): Initialize variables `deref_from_type2',
+ `deref_to_type1' and `deref_to_type2'.
+
+ * except.c (get_eh_type): Hide prototype and definition.
+ (process_start_catch_block_old): Remove unused static prototype.
+
+ * pt.c (tsubst_decl): Initialize variable `argvec'.
+
+ * spew.c: Include toplev.h.
+
+1998-10-05 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (instantiate_decl): Do save and restore file position.
+
1998-10-05 Martin von Löwis <loewis@informatik.hu-berlin.de>
* method.c (build_decl_overload_real): Clear
numeric_output_need_bar after __.
+1998-10-05 Nathan Sidwell <nathan@acm.org>
+
+ * call.c (build_new_method_call): Issue 'incomplete type' error,
+ if class is not defined.
+
+1998-10-05 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * call.c (build_object_call): Move declaration of variable
+ `fn' into the scope where it is used. Don't access variable
+ `fn' when it is uninitialized, instead use `fns'.
+
+1998-10-04 Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
+
+ * errfn.c (cp_thing): Print buf as a string not as a printf format
+ to avoid problems with the operator%. Consequently, `%%' sequences
+ in format are copied as `%' in buf.
+
1998-10-04 Jason Merrill <jason@yorick.cygnus.com>
+ * pt.c (pop_tinst_level): Call extract_interface_info.
+ (instantiate_decl): Don't save and restore file position.
+
* decl.c (cp_finish_decl): Make statics in extern inlines and
templates common, if possible and the target doesn't support weak
symbols.
+ * decl.c (grokdeclarator): Remove redundant calls to
+ build_type_variant and some duplicated code.
+ * sig.c (build_signature_reference_type): Only take the type parm.
+ (build_signature_pointer_type): Likewise.
+ * tree.c (build_cplus_method_type): Adjust.
+ * cp-tree.h: Update.
+
+1998-10-04 Mark Mitchell <mark@markmitchell.com>
+
+ * call.c (build_over_call): Make pedwarns about dropped qualifiers
+ into full-fledged errors.
+ * cvt.c (convert_to_reference): Likewise.
+ * typeck.c (convert_for_assignment): Likewise.
+
+ * search.c (expand_upcast_vtables): In addition to unsetting
+ TREE_READONLY, remove top-level const type qualifier.
+
+1998-10-03 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (current_class_ptr, current_class_ref): Clarify
+ documentation.
+ * cvt.c (ocp_convert): Don't expect fold to remove all trivial
+ NOP type conversions.
+ * decl.c (decls_match): Use comptypes directly; ignore
+ qualifiers on the DECL.
+ (duplicate_decls): Remove qualifier checks on DECL.
+ (grokdeclarator): Make the type built up include top-level
+ qualifiers.
+ * decl2.c (do_dtors): Fix spelling error.
+ * error.c (dump_simple_decl): Don't look at qualifiers on the decl
+ when printing type information.
+ * init.c (build_new_1): Add documentation. Deal with the fact
+ that type of allocated memory now contains qualifiers.
+ * lex.c (is_global): Improve error-recovery.
+ * sig.c (build_member_function_pointer): Don't cast away const
+ on fields of sigtable_entry_type.
+ * tree.c (lvalue_type): Don't look at top-level qualifiers on
+ expressions.
+ * typeck.c (decay_conversion): Likewise.
+ (build_component_ref): Make sure the type of the COMPONENT_REF
+ contains top-level qualifiers, as appropriate. Improve
+ error-handling.
+ (build_indirect_ref): Simplify. Don't strip top-level qualifiers.
+ (build_array_ref): Likewise.
+ (build_unary_op): Improve error-recovery.
+ (unary_complex_lvalue): Make taking the address a bound member
+ function an error, not a sorry.
+ (build_conditional_expr): Look at the type qualifiers, not the
+ qualifiers on the expression itself.
+
1998-10-03 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (merge_functions): Remove duplicates.
+ * decl2.c: Add -f{no-,}implicit-inline-templates.
+ (import_export_decl): Check it.
+
+ * decl.c (lookup_name_real): Template parms also take precedence
+ over implicit typename. Only warn if yylex.
+
* typeck.c (build_conditional_expr): Only fold if ifexp is an
INTEGER_CST.
-Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
+ * decl2.c (finish_vtable_vardecl): Check DECL_INTERFACE_KNOWN
+ instead of linkage.
+
+1998-10-01 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (FORMAT_VBASE_NAME): New macro.
+ * class.c (build_vbase_pointer): Use it.
+ * rtti.c (expand_class_desc): Likewise.
+ * tree.c (build_vbase_pointer_fields): Likewise.
+
+Thu Oct 1 10:43:45 1998 Nick Clifton <nickc@cygnus.com>
+
+ * decl.c (start_decl): Add invocation of
+ SET_DEFAULT_DECL_ATTRIBUTES, if defined.
+ (start_function): Add invocation of
+ SET_DEFAULT_DECL_ATTRIBUTES, if defined.
+
+ * lex.c: Replace occurrences of HANDLE_SYSV_PRAGMA with
+ HANDLE_GENERIC_PRAGMAS.
+
+1998-09-28 Anthony Green <green@cygnus.com>
+
+ * semantics.c (finish_asm_stmt): Always permit volatile asms.
+
+1998-09-28 Mark Mitchell <mark@markmitchell.com>
+
+ * 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.
+
+1998-09-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * search.c (get_base_distance): Remove assert.
+
+ * decl2.c (build_anon_union_vars): Don't process a field with no
+ name.
+ (finish_anon_union): Also complain about local anon unions with no
+ members.
+
+1998-09-25 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (lookup_namespace_name): If the name is a namespace,
+ return it immediately.
+
+Fri Sep 25 11:45:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-tree.h (define_case_label): Remove unused parameter.
+ (check_java_method): Likewise.
+ (grokclassfn): Likewise.
+ (expand_aggr_init): Likewise.
+ (build_x_delete): Likewise.
+ (maybe_end_member_template_processing): Likewise.
+ (unshare_base_binfos): Add prototype.
+ (string_conv_p): Likewise.
+ (my_friendly_abort): Mark with ATTRIBUTE_NORETURN.
+
+ * cvt.c (build_up_reference): Remove unused parameter
+ `checkconst', all callers changed.
+ (build_type_conversion): Mark parameter `code' with
+ ATTRIBUTE_UNUSED.
+ (build_expr_type_conversion): Initialize variable `conv'.
+
+ * decl.c (push_namespace): Initialize variable `d'.
+ (define_case_label): Remove unused parameter `decl', all callers
+ changed.
+
+ * decl2.c (lang_decode_option): If !USE_CPPLIB, mark parameter
+ `argc' with ATTRIBUTE_UNUSED.
+ (grokclassfn): Remove unused parameter `cname', all callers
+ changed.
+ (check_java_method): Likewise for parameter `ctype'.
+ (copy_assignment_arg_p): Mark parameter `virtualp' with
+ ATTRIBUTE_UNUSED.
+ (finish_prevtable_vardecl): Likewise for parameter `prev'.
+
+ * expr.c (extract_init): Likewise for parameters `decl' and `init'.
+
+ * init.c (expand_aggr_init_1): Remove unused parameter
+ `alias_this', all callers changed.
+ (expand_aggr_init): Likewise.
+ (expand_default_init): Likewise.
+ (build_new_1): Initialize variable `susp'.
+ (build_x_delete): Remove unused parameter `type', all callers
+ changed.
+
+ * lex.c (set_typedecl_interface_info): Mark parameter `prev' with
+ ATTRIBUTE_UNUSED.
+ (readescape): Use (unsigned) value in shift.
+ (real_yylex): Likewise. Likewise. Also cast `sizeof' to int when
+ comparing to a signed quantity.
+
+ * pt.c (maybe_end_member_template_processing): Remove unused
+ parameter `decl', all callers changed.
+ (check_explicit_specialization): Add braces around empty body in
+ an else-statement.
+ (current_template_args): Initialize variable `args'.
+ (lookup_template_class): Likewise for variable `prev_local_enum'.
+ (tsubst_decl): Likewise for variable `r'.
+ (set_mangled_name_for_template_decl): Initialize variable
+ `context'.
+
+ * spew.c (scan_tokens): Change type of parameter `n' to unsigned.
+ Likewise for variable `i'.
+ (yylex): Initialize variable `trrr'.
+
+ * typeck.c (compparms): Mark variable `strict' with
+ ATTRIBUTE_UNUSED.
+
+ * xref.c (simplify_type): Cast argument of ctype function to
+ `unsigned char'.
+
+1998-09-24 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (language_lvalue_valid): Remove.
+ * decl.c (grokdeclarator): Don't disallow references to functions.
+ * tree.c (lvalue_p_1): New function, combining duplicated
+ code from ...
+ (lvalue_p): Use it.
+ (real_lvalue_p): Likewise.
+ * typeck.c (language_lvalue_valid): Remove.
+ (build_modify_expr): Treat FUNCTION_TYPEs as readonly, even though
+ they don't have TREE_READONLY set.
+ * typeck2.c (readonly_error): Add case for FUNCTION_DECLs.
+
+1998-09-24 Benjamin Kosnik <bkoz@loony.cygnus.com>
+
+ * spew.c (yylex): Give diagnostic.
+ * hash.h (is_reserved_word): Add export.
+ * gxx.gperf: Likewise.
+ * lex.h (rid): Add RID_EXPORT.
+ * lex.c (init_parse): Likewise.
+
+Tue Sep 22 21:01:19 1998 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * friend.c (do_friend): Make warning a full sentence.
+
+1998-09-22 Mark Mitchell <mark@markmitchell.com>
+
+ * parse.y (component_decl_list): Improve error-recovery.
+
+1998-09-22 Benjamin Kosnik <bkoz@loony.cygnus.com>
+
+ * decl.c (make_typename_type): Move error to point where name
+ variable can be used by dump_type.
+
+1998-09-22 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokfndecl): Improve error-recovery.
+ * decl2.c (grokfield): Likewise.
+ * pt.c (finish_member_template_decl): Likewise.
+
+1998-09-20 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * method.c (hack_identifier): Finding multiple members is always
+ an error.
+
+1998-09-21 Per Bothner <bothner@cygnus.com>
+
+ * Make-lang.in (c++-filt): Link libiberty.a after cxxmain.o.
+
+Mon Sep 21 01:53:05 1998 Felix Lee <flee@cygnus.com>
+
+ * lex.c (init_lex): Use getenv ("LANG"), not GET_ENVIRONMENT ().
+
+1998-09-20 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (maybe_warn_about_overly_private_class): Reformat.
+
+1998-09-17 Andrew MacLeod <amacleod@cygnus.com>
+
+ * exception.cc (__cplus_type_matcher): Realign some code.
+
+1998-09-16 Mark Mitchell <mark@markmitchell.com>
+
+ * Make-lang.in (tinfo.o): Use CXXFLAGS when compiling.
+ (tinfo2.o): Likewise.
+ (exception.o): Likewise.
+ (new.o): Likewise.
+ (opnew.o): Likewise.
+ (opnewnt.o): Likewise.
+ (opvnew.o): Likewise.
+ (opvnewnt.o): Likewise.
+ (opdel.o): Likewise.
+ (opdelnt.o): Likewise.
+ (opvdel.o): Likewise.
+ (opvdelnt.o): Likewise.
+
+1998-09-16 Richard Henderson <rth@cygnus.com>
+
+ * decl.c (init_decl_processing): Kill __builtin_fp and __builtin_sp.
+
+1998-09-15 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * call.c (build_field_call): Handle static data members too.
+
+ * typeck.c (comptypes): When comparing pointer types, check
+ whether referred types match even in strictest modes.
+
+1998-09-15 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h: Revert previous change.
+ (finish_struct_methods): Remove declaration.
+ * class.c: Revert previous change.
+ (maybe_warn_about_overly_private_class): New function.
+ (finish_struct_methods): Declare here, and make static. Remove
+ unnecessary parameters. Tidy slightly. Use
+ maybe_warn_about_overly_private_class.
+ (finish_struct_1): Adjust. Remove check for private constructors,
+ now done elsewhere.
+ (finish_struct): Adjust.
+
+1998-09-15 Andrew MacLeod <amacleod@cygnus.com>
+
+ * except.c (expand_start_catch_block): No need to check for new
+ exception model.
+ (process_start_catch_block_old): Deleted.
+ (process_start_catch_block): Add call to start_decl_1().
+ (expand_end_catch_block): Add call to end_catch_handler().
+ * exception.cc (__cplus_type_matcher): Only check the exception
+ language if there is an exception table.
+
+1998-09-15 Andrew MacLeod <amacleod@cygnus.com>
+
+ * search.c (expand_indirect_vtbls_init): Mark temporary stack slots
+ as used to prevent conflicts with virtual function tables.
+
+1998-09-14 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (lang_type): Add has_non_private_static_mem_fn.
+ (CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN): New macro, to access it.
+ * class.c (maybe_class_too_private_p): New function.
+ (finish_struct_methods): Use it.
+ (finish_struct_1): Likewise.
+ (finish_struct): Set CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN if
+ appropriate.
+
+ * pt.c (check_specialization_scope): Fix spelling error.
+ (check_explicit_specialization): Remove code to handle explicit
+ specializations in class scope; they are now correctly diagnosed
+ as errors.
+
+1998-09-10 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (pushdecl): Don't copy types if the
+ DECL_ABSTRACT_ORIGIN of the new decl matches the TYPE_NAME of the
+ type.
+
+1998-09-09 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+
+ * class.c (get_enclosing_class): New function.
+ (is_base_of_enclosing_class): Likewise.
+ * cp-tree.h (get_enclosing_class): Declare.
+ (is_base_of_enclosing_class): Likewise.
+ * pt.c (coerce_template_parms): Use them.
+
+1998-09-09 Jason Merrill <jason@yorick.cygnus.com>
+
+ * g++spec.c (lang_specific_driver): Check whether MATH_LIBRARY is
+ null to decide whether to use it.
+
+ * error.c (dump_type_real): Handle NAMESPACE_DECL.
+ * parse.y (base_class.1): Avoid crash on error.
+
+1998-09-08 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (make_typename_type): If context is a namespace, the code
+ is in error.
+
+1998-09-08 Mumit Khan <khan@xraylith.wisc.edu>
* parse.y (nomods_initdcl0): Set up the parser stack correctly.
+1998-09-08 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (anonymous_namespace_name): Declare.
+ * decl.c: Define it.
+ (push_namespace): Use anonymous_namespace_name, rather than local
+ static anon_name.
+ * error.c (dump_decl): If a namespace is named
+ anonymous_namespace_name, call it {anonymous}.
+
+ * decl.c (grokparms): Distinguish between references and pointers
+ in error message.
+
+1998-09-08 Richard Henderson <rth@cygnus.com>
+ Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (process_partial_specialization): Consistently allocate
+ and zero tpd.parms based on ntparms. Use tpd2.parms, not
+ tpd.parms, where appropriate.
+
+Sun Sep 6 00:00:51 1998 Jeffrey A Law (law@cygnus.com)
+
+ * Makefile.in (INCLUDES): Update after recent toplevel gcc
+ reorganizations.
+
+1998-09-05 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove.
+ * class.c (finish_struct): Remove hackery to deal with explicit
+ specializations in class scope.
+ * decl.c (grokfndecl): Improve error-recovery.
+ * decl2.c (grokfield): Likewise.
+ * pt.c (check_specialization_scope): New function.
+ (begin_specialization): Call it.
+ (process_partial_specialization): New function, split out from
+ push_template_decl. Check partial specializations more
+ stringently.
+ (push_template_decl): Call it.
+ (check_explicit_specialization): Don't attempt to handle explicit
+ specializations in class scope.
+ (template_parm_data): Document. Add current_arg and
+ arg_uses_template_parms.
+ (mark_template_parm): Set it.
+ (tsubst_arg_types): Remove unused variable.
+ * semantics.c (begin_class_definition): Tweak.
+
+1998-09-04 Mark Mitchell <mark@markmitchell.com>
+
+ * inc/typeinfo (type_info::type_info(const char*)): Make
+ `explicit'.
+
+ * cp-tree.h (hash_tree_cons_simple): New macro.
+ * pt.c (tsubst_arg_types): New function. Use hash_tree_cons.
+ (coerce_template_parms): Use make_temp_vec, instead of
+ make_tree_vec. Document this behavior.
+ (lookup_template_class): Likewise.
+ (tsubst, cases METHOD_TYPE, FUNCTION_TYPE): Use tsubst_arg_types.
+ Remove dead code (and add assertion to check its deadness). Fix
+ bug w.r.t. exception specifications.
+
+1998-09-03 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (import_export_vtable): Always make artificials comdat.
+ (import_export_decl): Likewise.
+ * pt.c (mark_decl_instantiated): Likewise.
+
+1998-09-03 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (finish_globally_qualified_member_call_expr):
+ Rename to ...
+ (finish_qualified_call_expr).
+ * semantics.c: Likewise.
+ * parse.y (primary): Use it.
+ * method.c (hack_identifier): Remove redundant code.
+
+ * init.c (resolve_offset_ref): Call convert_from_reference to
+ handle members of reference type. Improve error recovery.
+
+1998-09-03 Benjamin Kosnik <bkoz@cygnus.com>
+
+ * cp-tree.h: Declare warn_nontemplate_friend.
+ * decl2.c (lang_decode_option): Set.
+ * lang-options.h: Add -Wnon-template-friend.
+ * friend.c (do_friend): Use to toggle non-template function warning.
+
+1998-09-03 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (finish_enum): Don't resolve CONST_DECLs to their
+ corresponding INTEGER_CSTs when processing_template_decl.
+ * pt.c (tsubst_enum): Tweak accordingly.
+
+1998-09-03 Benjamin Kosnik <bkoz@rhino.cygnus.com>
+
+ * decl.c (pushdecl_class_level): Add warning here.
+ (pushdecl): Tweak.
+
+1998-09-02 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cvt.c (convert_pointer_to_real): Tidy.
+ * search.c (get_base_distance_recursive): Simplify.
+ (get_base_distance): Likewise.
+
+ * pt.c (unify): Only special-case INTEGER_TYPE if it uses template
+ parms.
+
+Wed Sep 02 09:25:29 1998 Nick Clifton <nickc@cygnus.com>
+
+ * lex.c (check_newline): Call HANDLE_PRAGMA before
+ HANDLE_SYSV_PRAGMA if both are defined. Generate warning messages
+ if unknown pragmas are encountered.
+ (handle_sysv_pragma): Interpret return code from
+ handle_pragma_token (). Return success/failure indication rather
+ than next unprocessed character.
+ (pragma_getc): New function: retrieves characters from the
+ input stream. Defined when HANDLE_PRAGMA is defined.
+ (pragma_ungetc): New function: replaces characters back into the
+ input stream. Defined when HANDLE_PRAGMA is defined.
+
+1998-09-01 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (output_vtable_inherit): Use %cDIGIT in the operands.
+ * class.c (build_vtable_entry_ref): Likewise.
+
+1998-09-01 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION): New macro.
+ * decl2.c (import_export_decl): Likewise.
+ * pt.c (instantiate_decl): Use it.
+
+1998-09-01 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (lookup_name_real): Also do implicit typename thing for
+ artificial TYPE_DECLs.
+ * search.c (lookup_field): Likewise.
+ (lookup_fnfields, lookup_field): Adjust for implicit typename kludge.
+ * semantics.c (begin_constructor_declarator): Use enter_scope_of.
+ (enter_scope_of): Extract type from implicit typename.
+ (begin_class_definition): Likewise.
+ * lex.c (identifier_type): Handle implicit typename when checking
+ for SELFNAME.
+
+ * cp-tree.h: Declare flag_strict_prototype.
+ * lex.c (do_scoped_id, do_identifier): Don't implicitly_declare if
+ -fstrict-prototype.
+ * decl.c (init_decl_processing): If -f{no,-}strict-prototype wasn't
+ specified, set it to the value of pedantic.
+
+1998-09-01 Mark Mitchell <mark@markmitchell.com>
+
+ * decl2.c (arg_assoc): Handle template-id expressions as arguments.
+
+1998-08-31 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (finish_enum): Handle member enums of classes declared in
+ template functions.
+
+ * decl2.c (grok_x_components): Strip attributes before calling
+ groktypename.
+
+1998-08-31 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h, decl2.c: Remove support for -fall-virtual,
+ -fenum-int-equivalence and -fno-nonnull-objects.
+ * class.c (check_for_override): Remove support for -fall-virtual.
+ (finish_struct_1): Likewise.
+ * call.c (build_new_op): Remove support for -fenum-int-equivalence.
+ * typeck.c (build_binary_op_nodefault): Likewise.
+ * cvt.c (ocp_convert): Likewise.
+ * call.c (build_vfield_ref): Remove support for -fno-nonnull-objects.
+ * class.c (build_vbase_path): Likewise.
+
+Sun Aug 30 22:16:31 1998 H.J. Lu (hjl@gnu.org)
+
+ * Makefile.in (INTERFACE): New, set to 1.
+
+1998-08-30 Mark Mitchell <mark@markmitchell.com>
+
+ * error.c (dump_decl): Use CP_DECL_CONTEXT, not DECL_CONTEXT, when
+ comparing with global_namespace.
+ (dump_aggr_type): Likewise.
+
+ * decl.c (grokfndecl): Issue error on declaration of friend
+ templates with explicit template arguments.
+
+ * pt.c (convert_template_argument): New function, split out
+ from...
+ (coerce_template_parms): Here.
+ (tsubst): Attempt better error-recovery.
+
+1998-08-28 Benjamin Kosnik <bkoz@loony.cygnus.com>
+
+ * pt.c (decl_template_parm_p): Add checks for
+ TEMPLATE_TEMPLATE_PARM.
+
+1998-08-28 Mark Mitchell <mark@markmitchell.com>
+
+ * lex.c (do_identifier): Fix thinko in previous change.
+
+1998-08-28 Jason Merrill <jason@yorick.cygnus.com>
+
+ * search.c (dfs_search, binfo_for_vtable, dfs_bfv_helper): New fns.
+ * decl2.c (output_vtable_inherit): Call binfo_for_vtable.
+
+1998-08-28 Richard Henderson <rth@cygnus.com>
+
+ Add support for discarding unused virtual functions.
+ * lang-options.h: Add -fvtable-gc.
+ * cp-tree.h: Add flag_vtable_gc.
+ * decl2.c (output_vtable_inherit): New fn.
+ (finish_vtable_vardecl): Call it.
+ * class.c (build_vtable_entry_ref): New fn.
+ (build_vtbl_ref): Call it.
+
+1998-08-28 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (build_enumerator): Take the enumeration type as a
+ parameter.
+ * decl.c (finish_enum): Don't set the TREE_TYPE for the
+ enumeration constant values if we're processing_template_decls.
+ Don't set the type for the CONST_DECLs either; that's done in
+ build_enumerator.
+ (build_enumerator): Take the enumeration type as a
+ parameter.
+ * lex.c (do_identifier): Don't resolve enumeration constants while
+ processing template declarations, even if they happen to be
+ TEMPLATE_PARM_INDEXs.
+
+ * parse.y (current_enum_type): New variable.
+ (primary): Don't allow statement-expression in local classes just
+ as we don't in global classes.
+ (structsp): Use current_enum_type.
+ (enum_list): Likewise.
+ * pt.c (tsubst_enum): Don't check for NOP_EXPRs introduced by
+ finish_enum; they no longer occur.
+
+ * cp-tree.h (finish_base_specifier): New function.
+ * parse.y (base_class): Use it.
+ * semantics.c (finish_base_specifier): Define it.
+
+ * parse.y (structsp): Warn on use of typename outside of template
+ declarations.
+
+1998-08-27 Jason Merrill <jason@yorick.cygnus.com>
+
+ * lex.c (handle_cp_pragma): Remove #pragma vtable.
+ * lang-options.h: Remove +e options.
+ * decl2.c (lang_decode_option): Likewise.
+ (import_export_vtable): Don't check write_virtuals.
+ (finish_vtable_vardecl, finish_file): Likewise.
+ * search.c (dfs_debug_mark): Likewise.
+ * semantics.c (begin_class_definition): Likewise.
+ * class.c (build_vtable, finish_vtbls, finish_struct_1): Likewise.
+
+ * call.c (build_over_call): Check flag_elide_constructors.
+ * decl2.c: flag_elide_constructors defaults to 1.
+ * typeck.c (convert_arguments): Remove return_loc parm.
+ (build_function_call_real): Adjust.
+
+ * search.c: Tear out all mi_matrix and memoize code.
+ (lookup_field, lookup_fnfields): Use scratch_tree_cons.
+ * lang-options.h: Remove documentation for -fhandle-exceptions,
+ -fmemoize-lookups and -fsave-memoized.
+ * cp-tree.h: Lose mi_matrix and memoize support.
+ * decl2.c: Ignore -fmemoize-lookups and -fsave-memoized.
+ * class.c: Lose struct class_level.
+ (pushclass, popclass): Lose memoize support.
+ * init.c (build_offset_ref): Likewise.
+
+ Never change BINFO_INHERITANCE_CHAIN.
+ * init.c (emit_base_init): Change modification of
+ BINFO_INHERITANCE_CHAIN to an assert.
+ * search.c (get_base_distance_recursive): Likewise.
+ (get_base_distance): Likewise.
+ (lookup_member): Likewise.
+ (convert_pointer_to_single_level): Likewise.
+ (lookup_field): Likewise. Lose setting TREE_VIA_* on TREE_LISTs.
+ (lookup_fnfields): Likewise.
+ * tree.c (propagate_binfo_offsets): Don't call unshare_base_binfos.
+ (unshare_base_binfos): Don't call propagate_binfo_offsets.
+ (layout_basetypes): Call propagate_binfo_offsets instead of
+ unshare_base_binfos.
+ * decl.c (xref_basetypes): Call unshare_base_binfos.
+ * pt.c (instantiate_class_template): Likewise.
+ * tree.c (reverse_path): Remove 'copy' parm; always make a
+ temporary copy.
+ * class.c (build_vbase_path): Just call it.
+ * search.c (compute_access): Likewise. Don't re-reverse.
+
+1998-08-27 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (build_vbase_path): Use reverse_path.
+ (finish_base_struct): Move warnings for inaccessible bases to
+ layout_basetypes.
+ (modify_one_vtable): Remove check of TREE_USED (binfo).
+ (fixup_vtable_deltas1): Likewise.
+ * cp-tree.h (BINFO_INHERITANCE_CHAIN): Document here.
+ (xref_tag): Remove binfos parameter.
+ (make_binfo): Remove chain parameter.
+ (reverse_path): Add copy parameter.
+ * decl.c (init_decl_processing): Change calls to xref_tag.
+ (xref_tag): Remove binfos parameter.
+ (xref_basetypes): Change calls to make_binfo.
+ * decl2.c (grok_x_components): Change calls to xref_tag.
+ (handle_class_head): Likewise.
+ * friend.c (do_friend): Likewise.
+ * lex.c (make_lang_type): Change calls to make_binfo.
+ * parse.y (structsp): Change calls to xref_tag.
+ (named_complex_class_head_sans_basetype): Likewise.
+ (named_class_head): Likewise.
+ * rtti.c (init_rtti_processing): Likewise.
+ * search.c (compute_access): Change calls to reverse_path.
+ (dfs_get_vbase_types): Change calls to make_binfo.
+ (get_vbase_types): Remove dead code.
+ * tree.c (unshare_base_binfos): Change calls to make_binfo.
+ (layout_basetypes): Warn here about inaccessible bases.
+ (make_binfo): Remove chain parameter.
+ (reverse_path): Add copy parameter.
+
+1998-08-27 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c: #if 0 complete_type_p.
+ * init.c (build_java_class_ref, build_new_1): Remove unused locals.
+ * method.c (process_overload_item): Likewise.
+ * typeck.c (comp_target_types): Likewise.
+
+ Stop sharing binfos for indirect virtual bases.
+ * tree.c (propagate_binfo_offsets): Unshare vbases, too.
+ (layout_basetypes): Likewise.
+ (unshare_base_binfos): Copy vbases, too.
+ * cp-tree.h (BINFO_VIA_PUBLIC, BINFO_BASEINIT_MARKED,
+ BINFO_VBASE_INIT_MARKED): Remove obsolete macros.
+ (BINFO_PUSHDECLS_MARKED, SET_BINFO_PUSHDECLS_MARKED,
+ CLEAR_BINFO_PUSHDECLS_MARKED): New macros.
+ * search.c (lookup_field, lookup_fnfields, lookup_member): Remove
+ reference to BINFO_VIA_PUBLIC.
+ (marked_pushdecls_p, unmarked_pushdecls_p): New fns.
+ (push_class_decls): Use them.
+ (dfs_pushdecls): Use SET_BINFO_PUSHDECLS_MARKED.
+ (dfs_compress_decls): Use CLEAR_BINFO_PUSHDECLS_MARKED.
+
+1998-08-27 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (build_enumerator): Set DECL_CONTEXT for the
+ CONST_DECLs.
+
+1998-08-26 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (finish_enum): Change prototype.
+ * decl.c (finish_enum): Use TYPE_VALUES, rather than taking a
+ VALUES parameter. Don't try to compute mins/maxs if
+ processing_template_decl.
+ * parse.y (structsp): Use new calling sequence for finish_enum.
+ * pt.c (tsubst_enum): Likewise. Take the new type as input.
+ (lookup_template_class): Remove unused variables. Tweak.
+ Register enums on instantiation list before substituting
+ enumeration constants.
+ (tsubst_decl): Remove unused variables.
+ (regenerate_decl_from_template): Likewise.
+
+ * decl.c (duplicate_decls): Don't obliterate the
+ DECL_TEMPLATE_INFO for a template if we're not replacing it with
+ anything.
+
+ * lex.c (do_identifier): Fix typo in comment.
+
+Wed Aug 26 10:54:51 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * errfn.c: Remove stdarg.h/varargs.h.
+ * tree.c: Likewise.
+
+1998-08-25 Brendan Kehoe <brendan@cygnus.com>
+
+ * pt.c (tsubst_copy): Only do typename overloading on an
+ IDENTIFIER_NODE that happens to look like a typename if it actually
+ has a type for us to use.
+
+1998-08-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (comp_cv_target_types): Split out...
+ (comp_target_types): From here. Don't allow cv-qual changes under
+ a pointer if nptrs == 0. Fix OFFSET_TYPE handling.
+ (build_ptrmemfunc): Pass 1 to nptrs.
+ * cvt.c (perform_qualification_conversions): Use comp_ptr_ttypes.
+
+1998-08-25 Mark Mitchell <mark@markmitchell.com>
+
+ * search.c (dependent_base_p): Don't compare a binfo to
+ current_class_type; use the TREE_TYPE of the binfo instead.
+
+ * cp-tree.h (CLASS_TYPE_P): Revise definition.
+
1998-08-25 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (duplicate_decls): Don't complain about different
exceptions from an internal decl even if pedantic.
+ * typeck.c (convert_for_assignment): Converting from pm of vbase
+ to derived is an error, not a sorry.
+
+ * call.c (build_over_call): Use convert_pointer_to_real for 'this'.
+ * class.c (fixed_type_or_null): Rename from
+ resolves_to_fixed_type_p. Return the dynamic type of the
+ expression, if fixed, or null.
+ (resolves_to_fixed_type_p): Use it. Return 0 if the dynamic type
+ does not match the static type.
+ (build_vbase_path): Rename 'alias_this' to 'nonnull'. Use
+ resolves_to_fixed_type_p again.
+
+1998-08-24 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (tsubst_decl): Move special case code for dealing with
+ tricky friend templates here from ...
+ (regenerate_decl_from_template): Here.
+
+1998-08-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (start_decl): Remove redundant linkage check.
+
1998-08-24 Gavin Romig-Koch <gavin@cygnus.com>
* typeck.c (c_expand_return): Handle the case that valtype
is wider than the functions return type.
+1998-08-24 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (CLASS_TYPE_P): New macro.
+ * decl.c (grokdeclarator): Use it instead of IS_AGGR_TYPE.
+ * pt.c (process_template_parm): Undo previous change.
+
+1998-08-24 Benjamin Kosnik <bkoz@cygnus.com>
+
+ * cp-tree.h: Declare.
+ * pt.c (decl_template_parm_p): New function.
+ * decl.c (pushdecl): Check decls for redeclaring template parms.
+ (xref_tag): Make redeclaration an error, print decl.
+ * decl2.c (grokfield): Check field_decls for redeclaration as well.
+
+1998-08-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * parse.y (primary): Fix up the type of string constants.
+
+1998-08-24 Mark Mitchell <mark@markmitchell.com>
+
+ * typeck.c (convert_for_initialization): Move check for odd uses
+ of NULL to avoid duplicate warnings.
+
+1998-08-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (lvalue_type): Fix for arrays.
+ * typeck.c (string_conv_p): New fn.
+ (convert_for_assignment): Use it.
+ (build_unary_op): Use lvalue_type.
+ * call.c (standard_conversion, convert_like): Use string_conv_p.
+ (add_function_candidate): Use lvalue_type.
+ * cvt.c (convert_to_reference): Likewise.
+ * decl2.c (lang_decode_option): Ignore -traditional.
+ * decl.c (init_decl_processing): flag_writable_strings inhibits
+ flag_const_strings.
+
+1998-08-24 Andrew MacLeod <amacleod@cygnus.com>
+
+ * lang-options.h (lang_options): Add fconst-strings to the list
+ of valid options.
+ * decl2.c (lang_f_options, lang_decode_option): Likewise.
+
+1998-08-24 Nathan Sidwell <nathan@acm.org>
+
+ * lex.c (real_yylex): Don't warn about long long constants if
+ we're allowing long long.
+
1998-08-24 Martin von Löwis <loewis@informatik.hu-berlin.de>
+ * decl.c (pushdecl): Use IDENTIFIER_NAMESPACE_VALUE instead of
+ accessing bindings directly.
+
* search.c (my_tree_cons): Reimplement.
+ * lang-specs.h: Remove __HONOR_STD.
+ * inc/exception, inc/new, inc/new.h, inc/typeinfo: Likewise.
+
+1998-08-23 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Complain about in-class initialization
+ of aggregates and/or references.
+ * pt.c (process_template_parm): Clear IS_AGGR_TYPE for
+ TEMPLATE_TYPE_PARMs.
+
+ * decl2.c (grok_array_decl): Add comment.
+ (mark_used): Don't instantiate an explicit instantiation.
+ * friend.c (make_friend_class): Remove bogus comment. Fix check
+ for partial specializations.
+ * pt.c (check_explicit_specialization): Don't
+ SET_DECL_EXPLICIT_INSTANTIATION here.
+ (mark_decl_instantiated): Or here.
+ (do_decl_instantiation): Do it here, instead. Add checks for
+ duplicate explicit instantiations, etc. Tidy.
+ (do_type_instantiation): Likewise.
+ (instantiate_decl): Improve comments. Complain about explicit
+ instantiations where no definition is available.
+
+ * cp-tree.h (ansi_null_node): Remove.
+ * call.c (build_over_call): Warn about converting NULL to an
+ arithmetic type.
+ * cvt.c (build_expr_type_conversion): Likewise. Use
+ null_ptr_cst_p instead of expanding it inline.
+ * decl.c (ansi_null_node): Remove.
+ (init_decl_processing): Make null_node always have integral type.
+ * except.c (build_throw): Warn about converting NULL to an
+ arithmetic type.
+ * lex.c (init_parse): Remove handling of ansi_null_node.
+ * pt.c (type_unification_real): Don't convert NULL to void* type.
+ * typeck.c (build_binary_op_nodefault): Fix NULL warnings.
+ (convert_for_assignment): Warn about converting NULL to an
+ arithmetic type.
+ (convert_for_initialization): Likewise.
+
+1998-08-20 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (search_tree, no_linkage_helper, no_linkage_check): New fn.
+ * pt.c (coerce_template_parms): Use no_linkage_check.
+ * decl.c (grokvardecl): Likewise.
+ (grokfndecl): Likewise. Members of anonymous types have no linkage.
+
+ * method.c (process_overload_item): Remove useless code.
+
+1998-08-20 Per Bothner <bothner@cygnus.com>
+
+ Handle new'ing of Java classes.
+ * init.c (build_class_classref): New function.
+ (build_new_1): If type is TYPE_FOR_JAVA: Call _Jv_AllocObject;
+ constructor does not return this; don't need to exception-protect.
+
+ * pt.c (lookup_template_class): Copy TYPE_FOR_JAVA flag.
+ * decl2.c (acceptable_java_type): Handle template-derived types.
+
+1998-08-20 Per Bothner <bothner@cygnus.com>
+
+ * decl2.c (import_export_vtable): Suppress vtables for Java classes.
+
+1998-08-20 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (duplicate_decls): Always merge the old and new patterns
+ for templates, regardless of whether or not the new one has
+ DECL_INITIAL. Don't throw away specializations. Merge
+ DECL_SAVED_TREE.
+ * pt.c (tsubst_decl): Use the right pattern when calculating the
+ complete args for a new template instance.
+ (do_decl_instantiation): Fix typo in comment.
+ (regenerate_decl_from_template): Deal with tricky friend template
+ case.
+ (instantiate_decl): Likewise.
+
+Thu Aug 20 09:09:45 1998 Jeffrey A Law (law@cygnus.com)
+
+ * init.c (build_builtin_delete_call): Add missing assemble_external
+ call.
+
+1998-08-20 Jason Merrill <jason@yorick.cygnus.com>
+
+ * parse.y (notype_unqualified_id): Also accept ~A<int>.
+
+1998-08-19 Mark Mitchell <mark@markmitchell.com>
+
+ * typeck.c (build_binary_op_nodefault): Warn on use of NULL in
+ arithmetic.
+ * except.c (build_throw): Warn when NULL is thrown, even with
+ -ansi. Use ansi_null_node, rather than integer_zero_node, in the
+ thrown expression.
+
+ * cp-tree.h (ansi_null_node): New variable.
+ * decl.c (ansi_null_node): New variable.
+ (init_decl_processing): Initialize its type.
+ * lex.c (init_parse): Initialize its value. Use ansi_null_node
+ for null_node in non-ANSI mode.
+ * typeck.c (build_binary_op_nodefault): Use ansi_null_node in
+ place of null_node to avoid spurious errors.
+
+1998-08-17 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (enter_scope_of): New function.
+ * parse.y (complex_direct_notype_declarator): Use it.
+ * semantics.c (enter_scope_of): New function.
+
1998-08-17 Jason Merrill <jason@yorick.cygnus.com>
+ * decl.c (grokparms): No, here.
+
+ * decl.c (grokdeclarator): Catch parm with pointer to array of
+ unknown bound here...
+ * method.c (process_overload_item): ...not here.
+
+ * gxxint.texi: Remove obsolete documentation of overloading code.
+
* decl.c (finish_enum): Also set TYPE_SIZE_UNIT.
* class.c (finish_struct_bits): Likewise.
-1998-08-17 Mark Mitchell <mark@markmitchell.com>
+ * tree.c (lvalue_type): Fix for arrays.
+ * typeck.c (build_unary_op): Use lvalue_type.
+ * call.c (add_function_candidate): Likewise.
+ * cvt.c (convert_to_reference): Likewise.
+
+ * decl2.c (lang_decode_option): Ignore -traditional.
+
+ * init.c (build_offset_ref): Don't mess with error_mark_node.
+ * lex.c (do_scoped_id): Use cp_error.
+
+ * rtti.c (get_tinfo_fn): Don't mess with the context for now.
+
+1998-08-17 Benjamin Kosnik <bkoz@loony.cygnus.com>
+
+ * decl.c (grokdeclarator): Allow anonymous types to be cv-qualified.
+
+Mon Aug 17 10:40:18 1998 Jeffrey A Law (law@cygnus.com)
+
+ * cp-tree.h (set_identifier_local_value): Provide prototype.
+
+ * decl2.c (do_namespace_alias): Remove unused variables `binding'
+ and `old'.
+
+Fri Aug 14 16:42:27 1998 Nick Clifton <nickc@cygnus.com>
+
+ * Makefile.in: Rename BBISON to BISON so that it can be properly
+ inherited from the parent makefile.
+
+1998-08-13 Jason Merrill <jason@yorick.cygnus.com>
+
+ * lang-options.h: Add -finit-priority.
+ * decl2.c: Likewise. Check flag_init_priority instead of
+ USE_INIT_PRIORITY.
+
+ * decl2.c (setup_initp): New fn.
+ (start_objects, finish_objects, do_ctors): Handle init_priority.
+ (do_dtors, finish_file): Likewise.
+
+1998-08-13 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst_copy): Hush warning.
+
+ * rtti.c (get_tinfo_fn): Also set DECL_IGNORED_P.
+
+1998-08-12 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (print_template_context): Don't abort when instantiating a
+ synthesized method.
+
+ * decl.c (grokdeclarator): Issue errors on namespace qualified
+ declarators in parameter lists or in class scope.
+
+1998-08-09 Mark Mitchell <mark@markmitchell.com>
* pt.c (check_explicit_specialization): Don't abort on bogus
explicit instantiations.
-1998-08-14 Jason Merrill <jason@yorick.cygnus.com>
+1998-08-07 Mark Mitchell <mark@markmitchell.com>
+
+ * typeck.c (require_complete_type): Use complete_type_or_else.
+ (complete_type_or_else): Always return NULL_TREE on failure, as
+ documented.
+
+ * pt.c (tsubst_aggr_type): Prototype.
+ (tsubst_decl): New function, split out from tsubst. Set
+ input_filename and lineno as appropriate.
+ (pop_tinst_level): Restore the file and line number saved in
+ push_tinst_level.
+ (instantiate_class_template): Set input_filename and lineno as
+ appropriate.
+ (tsubst): Move _DECL processing to tsubst_decl. Make sure the
+ context for a TYPENAME_TYPE is complete.
+
+ * decl2.c (grokbitfield): Issue errors on bitfields declared with
+ function type.
+ (do_dtors): As in do_ctors, pretend to be a member of the same
+ class as a static data member while generating a call to its
+ destructor.
- * rtti.c (get_tinfo_fn): Don't mess with the context for now.
+ * cvt.c (cp_convert_to_pointer): Handle NULL pointer
+ conversions, even in complex virtual base class hierarchies.
-1998-08-13 Mumit Khan <khan@xraylith.wisc.edu>
+1998-08-06 Mark Mitchell <mark@markmitchell.com>
- * decl2.c (import_export_class): Don't use dllexport
- attribute as a heuristic.
+ * cp-tree.h (ENUM_TEMPLATE_INFO): New macro.
+ (TYPE_TEMPLATE_INFO): Likewise.
+ (SET_TYPE_TEMPLATE_INFO): Likewise.
+ (ENUM_TI_TEMPLATE): Likewise.
+ (ENUM_TI_ARGS): Likewise.
+ (lookup_nested_type_by_name): Remove.
+ * decl.c (maybe_process_template_type_declaration): Handle enums.
+ (start_enum): Don't check for primary-template enum declarations
+ here.
+ (finish_enum): Clean up, document. Make sure template enum
+ constants get the correct type.
+ (build_enumerator): Copy initializers for template enumerations,
+ too.
+ (grok_enum_decls): Document.
+ * lex.c (do_identifier): Document use of LOOKUP_EXPR a bit
+ better. Build LOOKUP_EXPRs for local variables, even if they are
+ TREE_PERMANENT.
+ * pt.c (tsubst_enum): Remove field_chain parameter.
+ (template_class_depth): Include the depth of surrounding function
+ contexts.
+ (push_template_decl): Check for primary-template enum declarations
+ here. Deal with enumeration templates.
+ (lookup_template_class): Likewise.
+ (for_each_template_parm): Likewise.
+ (instantiate_class_template): Don't call tsubst_enum directly,
+ call tsubst instead, to instantiate enums. Deal with all
+ field_chain issues here, not in tsubst_enum.
+ (lookup_nested_type_by_name): Remove.
+ (tsubst_aggr_type): Revise handling of enumeration types.
+ (tsubst): Likewise.
+ (tsubst_copy): Likewise.
+ (tsubst_expr): Call tsubst, not tsubst_enum for TAG_DEFNs.
+
+1998-08-04 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it
+ uses template parameters.
+ * method.c (build_template_parm_names): Use the full set of
+ template arguments for tsubst'ing.
+ (build_overload_identifier): Pass the full set of template
+ arguments to build_template_parm_names, not just the
+ innermost_args.
+ * pt.c (TMPL_ARGS_DEPTH): Define using
+ TMPL_ARGS_HAVE_MULTIPLE_LEVELS, for clarity.
+ (NUM_TMPL_ARGS): New macro.
+ (add_outermost_template_args): Deal with the case where the outer
+ args will be completely discarded.
+ (coerce_template_parms): Use the full set of template arguments
+ for tsubst'ing. Simplify. Add some asserts. Improve
+ error messages.
+ (lookup_template_class): Pass the full set of template arguments
+ to coerce_template_parms.
+ (tsubst): Add assertion.
+ (do_type_instantiation): Don't instantiate member template
+ classes.
+
+ * init.c (build_offset_ref): Deal with a TEMPLATE_ID_EXPR whose
+ name is a LOOKUP_EXPR, rather than an IDENTIFIER_NODE.
+
+1998-08-03 Jason Merrill <jason@yorick.cygnus.com>
+
+ * method.c (set_mangled_name_for_decl): Change return type to void.
+
+ * decl.c (lookup_name_real): A namespace-level decl takes priority
+ over implicit typename. Avoid doing the same lookup twice.
+
+ * search.c (dependent_base_p): New fn.
+ (dfs_pushdecls, dfs_compress_decls): Use it.
+
+ * typeck.c (get_member_function_from_ptrfunc): Don't try to handle
+ virtual functions if the type doesn't have any.
+
+1998-08-03 Mark Mitchell <mark@markmitchell.com>
+
+ * decl2.c (grokfield): Don't mangle the name of a TYPE_DECL if it
+ uses template parameters.
+
+1998-08-02 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.def (LOOKUP_EXPR): Document. Remove second argument.
+ * cp-tree.h (DECL_TI_TEMPLATE): Improve documentation.
+ * lex.c (do_identifier): Don't use a second argument, or a type,
+ when building LOOKUP_EXPRs.
+ (do_identifier): Likewise.
+ (do_scoped_id): Likewise.
+ * method.c (hack_identifier): Improve error message.
+ * pt.c (lookup_template_function): Don't needlessly call
+ copy_to_permanent or build_min.
+ (tsubst_copy): Remove #if 0'd code. tsubst into LOOKUP_EXPRs if
+ necessary.
+ (do_decl_instantiation): Improve error message.
+ * tree.c (mapcar, case LOOKUP_EXPR): Don't be sorry; make a copy.
+ (build_min): Copy the type to the permanent obstack, too.
+
+1998-08-01 Jason Merrill <jason@yorick.cygnus.com>
+
+ * init.c (init_init_processing): Remove BI* handling.
+ (build_builtin_call): Remove.
+ (build_builtin_delete_call): New fn.
+ (build_delete): Use it.
+
+1998-07-31 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (PROCESSING_REAL_TEMPLATE_DECL_P): New macro.
+ (maybe_check_template_type): New function.
+ * decl.c (maybe_process_template_type_declaration): New function,
+ split out from pushtag Call maybe_check_template_type.
+ (pushtag): Use it. Use PROCESSING_REAL_TEMPLATE_DECL_P.
+ (xref_tag): Use PROCESSING_REAL_TEMPLATE_DECL_P.
+ * friend.c (do_friend): Use PROCESSING_REAL_TEMPLATE_DECL_P.
+ * pt.c (template_class_depth_real): Generalization of ...
+ (template_class_depth): Use it.
+ (register_specialization): Use duplicate_decls for duplicate
+ declarations of specializations.
+ (maybe_check_template_type): New function.
+ (push_template_decl_real): Fix comment.
+ (convert_nontype_argument): Likewise.
+ (lookup_template_class): Likewise. Avoid an infinite loop on
+ erroneous code.
+ (tsubst_friend_function): Fix comment.
+ (tsubst, case FUNCTION_DECL): Deal with a DECL_TI_TEMPLATE that is
+ an IDENTIFIER_NODE.
+ * semantics.c (begin_function_definition): Use
+ reset_specialization to note that template headers don't apply
+ directly to declarations after the opening curly for a function.
1998-07-29 Jason Merrill <jason@yorick.cygnus.com>
@@ -155,13 +5014,141 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
* decl.c (lookup_name_real): Fix typo.
+1998-07-28 Mark Mitchell <mark@markmitchell.com>
+
+ * friend.c (is_friend): Be lenient with member functions to deal
+ with nested friends.
+
1998-07-28 Jason Merrill <jason@yorick.cygnus.com>
* class.c (finish_struct_1): Convert integer_zero_node to
- ssizetype before passing it to set_rtti_entry.
+ ssizetype before passing it to set_rtti_entry.
* typeck2.c (initializer_constant_valid_p): Allow conversion of 0
of any size to a pointer.
+1998-07-27 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (TI_USES_TEMPLATE_PARMS): Remove.
+ (build_template_decl_overload): Remove.
+ (set_mangled_name_for_decl): New function.
+ (innermost_args): Remove is_spec parameter.
+ (most_specialized, most_specialized_class): Remove declarations.
+ (lookup_template_class): Add entering_scope parameter.
+ (maybe_process_partial_specialization): New function.
+ (finish_template_decl): Likewise.
+ (finish_template_type): Likewise.
+ * class.c (finish_struct): Clean up processing of member template
+ specializations.
+ * decl.c (pushtag): Fix formatting.
+ (lookup_tag): Improve handling of pseudo-global levels.
+ (make_typename_type): Adjust call to lookup_template_class.
+ (shadow_tag): Use maybe_process_partial_specialization.
+ (xref_tag): Improve handling of member friends.
+ (start_function): Call push_nested_class before
+ push_template_decl. Don't call push_template_decl for
+ specializations.
+ * decl2.c (grok_x_components): Don't call xref_tag for
+ template instantiations. Handle UNION_TYPEs like RECORD_TYPEs.
+ (grokclassfn): Use set_mangled_name_for_decl.
+ (arg_assoc_class): Adjust call to innermost_args.
+ (mark_used): Don't call instantiate_decl for a TEMPLATE_DECL.
+ * error.c (dump_function_name): Improve printing of template
+ function names.
+ * friend.c (is_friend): Don't compare types of decls to determine
+ friendship, unless flag_guiding_decls.
+ (make_friend_class): Partial specializations cannot be friends.
+ (do_friend): Use set_mangled_name_for_decl. Call
+ push_template_decl_real instead of push_template_decl.
+ * method.c (build_decl_overload_real): Remove prototype. Give it
+ external linkage.
+ (build_overload_identififer): Adjust call to innermost_args.
+ (build_template_decl_overload): Remove.
+ (set_mangled_name_for_decl): New function.
+ * parse.y (.finish_template_type): New non-terminal.
+ (template_def): Use finish_template_decl. Use template_extdef
+ instead of extdef.
+ (template_extdef, template_datadef): New non-terminals, containing
+ only those rules for things which can be templates.
+ (datadef): Tidy.
+ (template_type, self_template_type): Use .finish_template_type.
+ (named_class_head): Use maybe_process_partial_specialization.
+ * pt.c (mangle_class_name_for_template): Remove context parameter.
+ (get_class_bindings): Remove outer_args parameter.
+ (complete_template_args): Remove.
+ (add_outermost_template_args): New function.
+ (register_specialization): Return the specialization.
+ (unregister_specialization): New function.
+ (tsubst_template_parms): Likewise.
+ (most_specialized, most_specialized_class): Prototype here as
+ static.
+ (original_template): Rename to most_general_template.
+ (tsubst_template_parms): New function.
+ (set_mangled_name_for_template_decl): Likewise.
+ (TMPL_ARGS_DEPTH): New macro.
+ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): Adjust.
+ (TMPL_ARGS_LEVEL): New macro.
+ (SET_TMPL_ARGS_LEVEL): Likewise.
+ (TMPL_ARG): Likewise.
+ (SET_TMPL_ARG): Likewise.
+ (TMPL_ARGS_DEPTH): Likewise.
+ (finish_member_template_decl): Use finish_template_decl.
+ (maybe_process_partial_specialization): New function, split out
+ from tsubst.
+ (inline_needs_template_parms): Use TMPL_PARMS_DEPTH.
+ (maybe_begin_member_template_processing): Use new macros.
+ (is_member_template): Likewise.
+ (is_member_template_class): Likewise.
+ (add_to_template_args): Likewise. Deal with multiple levels of
+ args.
+ (maybe_process_partial_specialization): New function.
+ (retrieve_specialization): Add consistency check.
+ (determine_specialization): Return full argument list.
+ (check_explicit_specialization): Tweak friend handling. Use full
+ argument lists. Simplify.
+ (current_template_args): Use new macros.
+ (push_template_decl_real): Change ill-named mainargs to specargs.
+ Check that a partial specialization actually specializes at least
+ one parameter. Improve friend handling. Modify for full
+ template arguments.
+ (classtype_mangled_name): Don't mangle the names of
+ specializations.
+ (lookup_template_class): Add entering_scope parameter. Use it to
+ avoid finding a template type when an instantiation is required.
+ Simplify. Use full template arguments.
+ (tsubst_friend_function): Use unregister_specialization. Use new
+ macros. Use full template arguments.
+ (tsubst_friend_class): Substitute, using tsubst_template_parms,
+ into the template parameters before passing them to
+ redeclare_class_template.
+ (instantiate_class_template): Simplify. Use full template
+ arguments. Adjust calls to get_class_bindings. Use
+ SET_IDENTIFIER_TYPE_VALUE where needed. Improve friend handling.
+ (innermost_args): Use new macros.
+ (tsubst_aggr_type): New function, split out from tsubst.
+ (tsubst): Use tsubst_aggr_type, tsubst_template_parms, new calling
+ conventions for lookup_template_class. Refine handling of partial
+ instantiations. Remove calls to complete_template_args.
+ Simplify. Add consistency checks. Use set_mangled_name_for_decl
+ and set_mangled_name_for_template_decl.
+ (tsubst_copy): Use tsubst_aggr_type.
+ (instantiate_template): Use full template arguments.
+ (more_specialized): Improve formatting.
+ (more_specialized_class): Adjust calls to get_class_bindings.
+ (get_bindings_real): Don't call complete_template_args.
+ (most_specialized): Don't overwrite input; create a new list.
+ (most_specialized_class): Use most_general_template.
+ (regenerate_decl_from_template): Use unregister_specialization.
+ Use full template arguments.
+ (instantiate_decl): Use full template arguments.
+ (set_mangled_name_for_template_decl): New function.
+ * semantics.c (begin_class_definition): Use
+ maybe_process_partial_specialization.
+ (finish_member_class_template): New function.
+ (finish_template_decl): Likewise.
+ (finish_template_type): Likewise.
+ (typeck.c): Don't crash after issuing a compiler_error.
+ * Makefile.in (CONFLICTS): Adjust; we removed a s/r conflict.
+
1998-07-27 Jason Merrill <jason@yorick.cygnus.com>
* typeck2.c (build_functional_cast): Handle default-initialization.
@@ -174,6 +5161,11 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
* tree.c (ovl_member): Fix for single function in OVL.
+1998-07-27 Dave Brolley <brolley@cygnus.com>
+
+ * c-lex.c (yylex): Fix boundary conditions in character literal and
+ string literal loops.
+
1998-07-24 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (lookup_name_real): OK, do return the from_obj value
@@ -217,7 +5209,7 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
(finish_prevtable_vardecl): From here.
* class.c (finish_struct_1): Call import_export_class if at_eof.
- * decl.c (start_function): #if 0 mysterious code I wrote and have
+ * 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.
@@ -237,6 +5229,14 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
* method.c (process_overload_item): Use build_overload_value for
arrays.
+1998-07-20 Dave Brolley <brolley@cygnus.com>
+
+ * lex.c (mbchar.h): #include it.
+ (GET_ENVIRONMENT): New macro.
+ (init_parse): Set character set based on LANG environment variable.
+ (real_yylex): Handle multibyte characters in character literals.
+ (real_yylex): Handle multibyte characters in string literals.
+
1998-07-19 Jason Merrill <jason@yorick.cygnus.com>
* lex.c (do_identifier): Look for class value even if we don't
@@ -252,7 +5252,7 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
* 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.
@@ -369,7 +5369,7 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
(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.
+ aliases. Store alias with pushdecl. Remove odr errors.
* parse.y (namespace_alias): New non-terminal.
(extdef): Use it.
@@ -405,6 +5405,12 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
* decl2.c (namespace_ancestor): Use CP_DECL_CONTEXT.
(arg_assoc): Don't skip the first argument of a function.
+Tue Jul 14 20:09:22 1998 Jeffrey A Law (law@cygnus.com)
+
+ * search.c (my_tree_cons): Clean up.
+
+1998-07-14 Jason Merrill <jason@yorick.cygnus.com>
+
* call.c (joust): Don't warn about "confusing" conversions to the
same type.
@@ -420,14 +5426,14 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
of namespace-qualified ids to -1, enter the namespace.
* method.c (build_template_decl_overload): Expect _DECL as first
- parameter. Put context temporarily into current_namespace.
+ parameter. Put context temporarily into current_namespace.
* pt.c (check_explicit_specialization): Change caller.
(tsubst): Likewise.
* init.c (build_offset_ref): Call mark_used and
convert_from_reference for namespace members.
-Mon Jul 13 23:25:28 1998 Martin von Lvwis <loewis@informatik.hu-berlin.de>
+Mon Jul 13 23:25:28 1998 Martin von Löwis <loewis@informatik.hu-berlin.de>
* search.c (my_tree_cons): The bitfield is at index 2.
@@ -435,7 +5441,7 @@ Mon Jul 13 17:21:01 1998 Nick Clifton <nickc@cygnus.com>
* 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.
@@ -472,14 +5478,14 @@ Mon Jul 13 17:21:01 1998 Nick Clifton <nickc@cygnus.com>
* decl.c (xref_baseypes): Change caller.
* friend.c (make_friend_class): Likewise.
-1998-07-12 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+1998-07-12 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
- * typeck.c (comptypes, case TEMPLATE_TEMPLATE_PARM): Add parameter
+ * typeck.c (comptypes, case TEMPLATE_TEMPLATE_PARM): Add parameter
comparison.
- * pt.c (for_each_template_parm, case TEMPLATE_DECL): If it is a
+ * 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
+ (for_each_template_parm, case TEMPLATE_TEMPLATE_PARM): Traverse
its template arguments if exists.
* pt.c (coerce_template_template_parms): New function equivalent
@@ -493,17 +5499,17 @@ Mon Jul 13 17:21:01 1998 Nick Clifton <nickc@cygnus.com>
current_class_type. Don't display error message when COMPLAIN is
false.
-1998-07-12 Klaus Kaempf (kkaempf@progis.de)
+1998-07-12 Klaus Kaempf (kkaempf@progis.de)
- * repo.c (get_base_filename): Use file_name_nondirectory.
- (open_repo_file): Ditto.
+ * repo.c (get_base_filename): Use file_name_nondirectory.
+ (open_repo_file): Likewise.
* 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
+ * 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.
@@ -511,7 +5517,7 @@ Mon Jul 13 17:21:01 1998 Nick Clifton <nickc@cygnus.com>
* 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.
+ (DEFARG_LENGTH, DEFARG_POINTER): Use it.
Sun Jul 12 01:20:57 1998 Jeffrey A Law (law@cygnus.com)
@@ -577,7 +5583,7 @@ Sun Jul 12 01:20:57 1998 Jeffrey A Law (law@cygnus.com)
* 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
+ * 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.
@@ -590,8 +5596,8 @@ Sun Jul 12 01:20:57 1998 Jeffrey A Law (law@cygnus.com)
1998-06-30 Benjamin Kosnik <bkoz@bliss.nabi.net>
- * decl2.c (lang_decode_option): Remove warn_template_debugging.
- * lang-options.h: Ditto.
+ * decl2.c (lang_decode_option): Remove warn_template_debugging.
+ * lang-options.h: Likewise.
Mon Jun 29 20:17:40 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
@@ -613,7 +5619,7 @@ Sat Jun 27 23:34:18 1998 Fred Fish <fnf@ninemoons.com>
Sat Jun 27 12:22:56 1998 Jeffrey A Law (law@cygnus.com)
- * Make-lang.in (g++): Depend on mkstemp.o. Link in mkstemp.o
+ * Make-lang.in (g++): Depend on mkstemp.o. Link in mkstemp.o
Sat Jun 27 07:36:09 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
@@ -636,7 +5642,7 @@ Sat Jun 27 07:36:09 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* 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.
+ 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.
@@ -704,7 +5710,7 @@ Sat Jun 27 07:36:09 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* 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.
+ (__cp_push_exception): Set the original exception value.
1998-06-23 Jason Merrill <jason@yorick.cygnus.com>
@@ -739,8 +5745,8 @@ Mon Jun 22 08:50:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
Fri Jun 19 23:22:42 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * typeck2.c (pop_init_level): Warn about implicit zero initialization
- of struct members.
+ * typeck2.c (pop_init_level): Warn about implicit zero initialization
+ of struct members.
Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
@@ -785,7 +5791,7 @@ Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
1998-06-16 Andrew MacLeod <amacleod@cygnus.com>
- * decl.c (grokvardecl): Don't build external assembler names for
+ * 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.
@@ -821,7 +5827,7 @@ Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(pointer_diff): Likewise.
* pt.c (for_each_template_parm): Traverse the TYPE_CONTEXT for
- types.
+ types.
* search.c (get_matching_virtual): Note that member templates
cannot override virtual functions.
@@ -856,7 +5862,7 @@ Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
1998-06-11 Benjamin Kosnik <bkoz@elmo.cygnus.com>
* friend.c (do_friend): Add support for nested classes using
- member functions of the enclosing class as friends.
+ member functions of the enclosing class as friends.
1998-06-10 Mark Mitchell <mark@markmitchell.com>
@@ -870,9 +5876,9 @@ Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(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
+
+ * call.c (convert_like): Don't fail silently if
+ build_user_type_conversion fails. Always return error_mark_node
for failure.
1998-06-10 Jason Merrill <jason@yorick.cygnus.com>
@@ -931,8 +5937,8 @@ Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
1998-06-10 Branko Cibej <branko.cibej@hermes.si>
- * typeck.c (c_expand_return): Don't warn about void expressions on
- return statements in functions returning void.
+ * typeck.c (c_expand_return): Don't warn about void expressions on
+ return statements in functions returning void.
1998-06-09 Mark Mitchell <mark@markmitchell.com>
@@ -959,26 +5965,26 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* Makefile.in (decl2.o): Depend on dwarf2out.h and dwarfout.h.
* cp-tree.h: Add prototype for `maybe_print_template_context' and
- `maybe_make_one_only'.
+ `maybe_make_one_only'.
* decl.c (auto_function): Remove unused variable `decl'.
* decl2.c: Include dwarf2out.h and dwarfout.h.
* lex.c: Remove redundant declarations of `set_float_handler' and
- `asm_out_file'.
+ `asm_out_file'.
1998-06-08 Andrew MacLeod <amacleod@cygnus.com>
- * except.c (init_exception_processing): Remove NEW_EH_MODEL compile
+ * 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
+ (__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
+ (__uncatch_exception, __check_eh_spec, std::uncaught_exception): Call
__cp_eh_info instead of __cp_exception_info.
1998-06-08 Jason Merrill <jason@yorick.cygnus.com>
@@ -1002,7 +6008,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* lex.c (lang_init_options): New function.
(lang_init): Remove flag_exceptions == 2 hack.
-
+
1998-06-05 Jason Merrill <jason@yorick.cygnus.com>
* search.c (envelope_add_decl): Tweak for implicit typename.
@@ -1044,7 +6050,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(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
+ (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
@@ -1127,9 +6133,9 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* 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
+ * decl.c (grok_ctor_properties): Make sure ctors for types with
vbases have the in_chrg parm.
- * pt.c (instantiate_class_template): Update
+ * 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.
@@ -1141,7 +6147,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
1998-05-28 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_decl): Always pedwarn about vacuously redeclaring
+ * 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.
@@ -1170,7 +6176,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(maybe_push_to_top_level): Clear shadowed_labels.
* pt.c (instantiate_decl): Reset lineno and filename after calling
- regenerate_decl_from_template.
+ regenerate_decl_from_template.
* decl.c (grokdeclarator): Don't try to use TYPE_OBSTACK on an
error_mark_node.
@@ -1199,7 +6205,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
1998-05-26 Benjamin Kosnik <bkoz@loony.cygnus.com>
* decl.c (start_decl): Check for DECL_LANG_SPECIFIC before
- DECL_USE_TEMPLATE.
+ DECL_USE_TEMPLATE.
1998-05-26 Per Bothner <bothner@cygnus.com>
@@ -1244,7 +6250,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* cp-tree.h (processing_template_parmlist): Declare.
* decl.c (pushtag): Don't call push_template_decl when we
- shouldn't.
+ shouldn't.
* pt.c (processing_template_parmlist): New variable.
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro.
(complete_template_args): Use it.
@@ -1289,7 +6295,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* 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>
* decl.c (push_namespace): Namespaces have type void.
@@ -1308,14 +6314,14 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* 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
+ (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.
1998-05-22 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (lang_print_error_function): New fn.
+ * 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.
@@ -1342,7 +6348,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* 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
+ (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
@@ -1376,7 +6382,7 @@ Thu May 21 11:54:44 1998 Dave Brolley <brolley@cygnus.com>
* cp-tree.h: (get_directive_line): Different prototype for cpplib.
(GET_DIRECTIVE_LINE): Macro wrapper for get_directive_line.
- * Makefile.in (CXX_OBJS): add @extra_cxx_objs@ for cpplib.
+ * Makefile.in (CXX_OBJS): Add @extra_cxx_objs@ for cpplib.
1998-05-21 Jason Merrill <jason@yorick.cygnus.com>
@@ -1409,11 +6415,11 @@ Thu May 21 11:54:44 1998 Dave Brolley <brolley@cygnus.com>
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.
+ IDENTIFIER_NAMESPACE_VALUEs.
* parse.y (component_decl): Move code to ...
- * semantics.c (finish_member_class_template): New function.
+ * semantics.c (finish_member_class_template): New function.
Don't put member class templates on the list of components for a
- class.
+ 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.
@@ -1492,7 +6498,7 @@ Tue May 19 10:05:02 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
definition.
* errfn.c (cp_error): Cast function pointer `error' to (errorfn *)
- in call to `cp_thing'.
+ in call to `cp_thing'.
(cp_warning): Likewise for function pointer `warning'.
* except.c (do_function_call): Remove prototype and definition.
@@ -1503,10 +6509,10 @@ Tue May 19 10:05:02 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* parse.y: Include toplev.h.
* pt.c (type_unification): Remove unused variable `arg'.
- (instantiate_decl): likewise for `save_ti'.
+ (instantiate_decl): Likewise for `save_ti'.
* tree.c (propagate_binfo_offsets): Likewise for `base_binfos'.
-
+
Tue May 19 02:43:25 1998 Jason Merrill <jason@yorick.cygnus.com>
* init.c (build_member_call): Handle template_ids.
@@ -1520,9 +6526,9 @@ Mon May 18 23:22:52 1998 Jason Merrill <jason@yorick.cygnus.com>
Mon May 18 12:28:44 1998 Mark Mitchell <mmitchell@usa.net>
* parse.y (.finish_new_placement): New non-terminal.
- (unary_expr, new_type_id): Use it.
+ (unary_expr, new_type_id): Use it.
* parse.c: Regenerated.
-
+
Mon May 18 12:20:27 1998 Brendan Kehoe <brendan@cygnus.com>
* pt.c (redeclare_class_template): Say where the original definition
@@ -1538,7 +6544,7 @@ Mon May 18 03:00:57 1998 Jason Merrill <jason@yorick.cygnus.com>
Mon May 18 01:43:01 1998 Martin v. Loewis <loewis@informatik.hu-berlin.de>
- * decl.c (lookup_name_real): Don't look at IDENTIFIER_LOCAL_VALUE
+ * decl.c (lookup_name_real): Don't look at IDENTIFIER_LOCAL_VALUE
for a type unless it is one.
* class.c (finish_struct_1): Use OVL_CURRENT in error message.
@@ -1548,7 +6554,7 @@ Mon May 18 01:24:08 1998 Jeffrey A Law (law@cygnus.com)
* Makefile.in (program_transform_name, objdir): Define.
* Makefile.in (BISON): Use bison from the build tree if it exists.
- (FLEX): Similarly.
+ (FLEX): Likewise.
Sun May 17 14:52:08 1998 Martin v. Loewis <loewis@informatik.hu-berlin.de>
@@ -1567,7 +6573,7 @@ Sun May 17 13:53:48 1998 Mark Mitchell <mmitchell@usa.net>
* 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>
* decl.c (duplicate_decls): Use CANONICAL_TYPE_VARIANT to compare
@@ -1586,7 +6592,7 @@ Fri May 15 20:28:00 1998 Jason Merrill <jason@yorick.cygnus.com>
Fri May 15 15:34:02 1998 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * decl.c (duplicate_decls): Clean up, add DECL_DATA_AREA bits.
+ * decl.c (duplicate_decls): Clean up, add DECL_DATA_AREA bits.
Fri May 15 00:46:05 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -1594,20 +6600,20 @@ Fri May 15 00:46:05 1998 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (start_decl): Use 'tem'.
-Thu May 14 16:30:47 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+Thu May 14 16:30:47 1998 Andrew MacLeod <amacleod@cygnus.com>
* exception.cc: Include eh-common.h.
- (struct cp_eh_info): add eh_info struct with NEW_EH_MODEL.
+ (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
+ (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
+ (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
+ * parse.y (function_try_block): Call start_catch_block() and
end_catch_block().
Thu May 14 12:27:34 1998 Brendan Kehoe <brendan@cygnus.com>
@@ -1620,11 +6626,11 @@ Thu May 14 12:27:34 1998 Brendan Kehoe <brendan@cygnus.com>
Wed May 13 12:54:30 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* 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.
@@ -1659,7 +6665,7 @@ Tue May 12 21:37:49 1998 Jason Merrill <jason@yorick.cygnus.com>
DECL_NAMESPACE_SCOPE_P.
(lang_decl_name): Likewise.
* pt.c (tsubst_friend_function, tsubst): Likewise.
- * decl.c (pushdecl, redeclaration_error_message, start_decl,
+ * 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.
@@ -1681,7 +6687,7 @@ Mon May 11 11:38:07 1998 Mark Mitchell <mmitchell@usa.net>
* pt.c (tsubst): Remove duplicate check for IDENTIFIER_NODE.
* call.c (add_template_candidate): Adjust for changes to
- fn_type_unification.
+ fn_type_unification.
(add_template_candidate_real): Likewise.
(add_template_conv_candidate): Likewise.
(build_user_type_conversion_1): Likewise.
@@ -1726,11 +6732,11 @@ Mon May 11 11:38:07 1998 Mark Mitchell <mmitchell@usa.net>
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.
@@ -1792,7 +6798,7 @@ Sat May 9 14:44:37 1998 Jason Merrill <jason@yorick.cygnus.com>
Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
- * cp-tree.def (OVERLOAD): New node.
+ * cp-tree.def (OVERLOAD): New node.
* cp-tree.h (BINDING_TYPE, SET_IDENTIFIER_GLOBAL_VALUE,
SET_IDENTIFIER_NAMESPACE_VALUE): Define.
(NAMESPACE_BINDING): Remove.
@@ -1821,10 +6827,10 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
* 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.
+ (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.
+ (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.
@@ -1842,7 +6848,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
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
+ 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.
@@ -1869,7 +6875,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
(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
+ 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.
@@ -1877,7 +6883,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
(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.
+ 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.
@@ -1903,7 +6909,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
(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.
+ (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.
@@ -1939,7 +6945,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
* 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.
+ (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.
@@ -1966,7 +6972,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
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.
+ Mangle other namespaces 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.
@@ -2008,7 +7014,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
* 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,
+ lookup_name_current_level, start_decl, xref_tag,
finish_enum): Likewise.
* init.c (build_offset_ref): Likewise.
* search.c (lookup_field): Likewise.
@@ -2025,17 +7031,17 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
* 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,
+ * 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
+ * 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>
+Thu May 7 17:09:25 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.
@@ -2048,7 +7054,7 @@ 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,
+ 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)
@@ -2065,9 +7071,9 @@ Wed May 6 14:28:18 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
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,
+ * 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>
@@ -2080,9 +7086,9 @@ 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>
+Tue May 5 18:24:13 1998 Andrew MacLeod <amacleod@cygnus.com>
- * method.c (build_mangled_name): Add a call to build_type_variant
+ * 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>
@@ -2093,7 +7099,7 @@ Tue May 5 01:25:03 1998 Jason Merrill <jason@yorick.cygnus.com>
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
+ * 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.
@@ -2101,7 +7107,7 @@ 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>
+Thu Apr 30 13:05:33 1998 Andrew MacLeod <amacleod@cygnus.com>
* gxxint.texi: Add info for squangling codes K and B.
@@ -2130,7 +7136,7 @@ Sun Apr 26 12:10:18 1998 Mark Mitchell <mmitchell@usa.net>
(PRIMARY_TEMPLATE_P): Use it.
(push_template_decl_real): New function.
(redeclare_class_template): Take new template parameters as
- input.
+ input.
(is_specialization_of): New function.
(comp_template_args): Declare.
* decl.c (pushtag): Handle friend template classes.
@@ -2150,7 +7156,7 @@ Sun Apr 26 12:10:18 1998 Mark Mitchell <mmitchell@usa.net>
with friend templates.
* typeck.c (comptypes): Use comp_template_args, rather than
expanding it inline.
- * parse.y (component_decl): Handle a nested template type
+ * parse.y (component_decl): Handle a nested template type
like other component type declarations.
* pt.c (check_explicit_specialization): Handle overloaded
@@ -2168,14 +7174,14 @@ Thu Apr 23 21:19:06 1998 Jason Merrill <jason@yorick.cygnus.com>
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.
+ printing a warning. Re-enable 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,
+ * tree.c (build_expr_wrapper, build_expr_ptr_wrapper,
build_int_wrapper): New fns.
Thu Apr 23 18:27:53 1998 Mark P. Mitchell <mmitchell@usa.net>
@@ -2194,15 +7200,15 @@ Wed Apr 22 13:24:48 1998 Mark Mitchell <mmitchell@usa.net>
the DECL_RESULTs of a member TEMPLATE_DECL, not just the
TEMPLATE_DECL.
- * 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.
+ * 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.
Tue Apr 21 22:00:04 1998 Mark Mitchell <mmitchell@usa.net>
@@ -2345,29 +7351,29 @@ Sun Apr 12 22:31:19 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
Fri Apr 10 12:16:49 1998 Benjamin Kosnik <bkoz@loony.cygnus.com>
* decl.c (duplicate_decls): Don't warn for redundant decls if
- friend: let add_friend take care of it.
+ friend: let add_friend take care of it.
Thu Apr 9 02:40:48 1998 Jason Merrill <jason@yorick.cygnus.com>
* 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
+ * init.c (resolve_offset_ref): Warn about implicit & on pmfs
here, too.
- * typeck.c (build_unary_op): Only allow taking the address of a
+ * 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 Apr 9 22:16:57 1998 Per Bothner <bothner@cygnus.com>
- * 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.
+ * 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.
@@ -2378,14 +7384,14 @@ Thu Apr 9 22:16:57 1998 Benjamin Kosnik <bkoz@loony.cygnus.com>
* 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.
+ (build_method_call): Likewise.
+ * decl.c (lookup_name_real): Likewise.
+ (grokdeclarator): Likewise.
+ (start_decl): Likewise.
+ (grokparms): Likewise.
+ (start_function): Likewise.
+ (finish_function): Likewise.
+ (start_method): Likewise.
Thu Apr 9 00:18:44 1998 Dave Brolley (brolley@cygnus.com)
@@ -2419,7 +7425,7 @@ Sat Apr 4 12:52:35 1998 Jeffrey A Law (law@cygnus.com)
Fri Apr 3 02:22:59 1998 Jason Merrill <jason@yorick.cygnus.com>
Implement empty base optimization.
- * class.c (finish_struct_1): Add vbase fields earlier. Set
+ * 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.
@@ -2456,7 +7462,7 @@ Wed Apr 1 18:22:25 1998 Jeffrey A Law (law@cygnus.com)
* 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.
-
+
Wed Apr 1 15:38:36 1998 Jason Merrill <jason@yorick.cygnus.com>
* friend.c (is_friend): Fix access control for local classes.
@@ -2483,7 +7489,7 @@ Tue Mar 31 13:43:57 1998 Jeffrey A Law (law@cygnus.com)
Mon Mar 30 12:15:00 1998 Mark Mitchell <mmitchell@usa.net>
- * pt.c (fn_type_unification): Allow incomplete unification without
+ * pt.c (fn_type_unification): Allow incomplete unification without
an immediate error message.
Mon Mar 30 08:55:42 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -2561,7 +7567,7 @@ Fri Mar 27 20:23:18 1998 Mark Mitchell <mmitchell@usa.net>
* 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>
* inc/exception: Reorder closing braces.
@@ -2574,7 +7580,7 @@ Fri Mar 27 13:22:18 1998 Mark Mitchell <mmitchell@usa.net>
Thu Mar 26 11:16:30 1998 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_over_call): Check IS_AGGR_TYPE, not
+ * call.c (build_over_call): Check IS_AGGR_TYPE, not
TYPE_LANG_SPECIFIC.
* typeck.c (convert_arguments): Likewise.
@@ -2633,8 +7639,8 @@ Tue Mar 24 12:21:55 1998 Benjamin Kosnik <bkoz@lisa.cygnus.com>
Tue Mar 24 12:21:48 1998 Jim Wilson <wilson@cygnus.com>
- * decl.c (init_decl_processing): Initialize TYPE_MAX_VALUE for
- boolean_type_node to 1.
+ * decl.c (init_decl_processing): Initialize TYPE_MAX_VALUE for
+ boolean_type_node to 1.
Tue Mar 24 10:23:47 1998 Mark Mitchell <mmitchell@usa.net>
@@ -2673,7 +7679,7 @@ Tue Mar 24 10:23:47 1998 Mark Mitchell <mmitchell@usa.net>
(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.
+ (unify): Likewise. Deal with unification of complex expressions.
Mon Mar 23 12:24:37 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -2686,7 +7692,7 @@ Mon Mar 23 12:24:37 1998 Jason Merrill <jason@yorick.cygnus.com>
* search.c (lookup_field): Do implicit typename stuff.
Sun Mar 22 00:50:42 1998 Nick Clifton <nickc@cygnus.com>
- Geoff Noer <noer@cygnus.com>
+ Geoff Noer <noer@cygnus.com>
* Makefile.in: Various fixes for building cygwin32 native toolchains.
* Make-lang.in: Likewise.
@@ -2706,7 +7712,7 @@ Fri Mar 20 10:42:07 1998 Jason Merrill <jason@yorick.cygnus.com>
Fri Mar 20 08:12:43 1998 H.J. Lu (hjl@gnu.org)
- * semantics.c (finish_asm_stmt): Fix combine strings. Call
+ * semantics.c (finish_asm_stmt): Fix combine strings. Call
c_expand_asm_operands () if output_operands, input_operands or
clobbers is not NULL_TREE.
@@ -2714,7 +7720,7 @@ Fri Mar 20 00:10:19 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
* pt.c (complete_template_args): New function.
(get_bindings): Deal with specializations of function templates
- with return type containing parameters from outer class
+ with return type containing parameters from outer class
templates.
(tsubst, TEMPLATE_TEMPLATE_PARM): When reducing parameter level,
substitute arguments and compose a new type.
@@ -2730,7 +7736,7 @@ Thu Mar 19 11:51:58 1998 Jason Merrill <jason@yorick.cygnus.com>
* call.c (standard_conversion): Handle A* -> const A* properly.
- * pt.c (get_bindings_real): Rename from get_bindings. Add
+ * pt.c (get_bindings_real): Rename from get_bindings. Add
check_rettype parm.
(get_bindings): Pass 1.
(get_bindings_overload): Pass 0.
@@ -2751,7 +7757,7 @@ Thu Mar 19 02:27:48 1998 Jason Merrill <jason@yorick.cygnus.com>
Wed Mar 18 12:41:43 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (make_implicit_typename): Only change the type of a
+ * decl.c (make_implicit_typename): Only change the type of a
TYPENAME_TYPE.
Wed Mar 18 10:09:51 1998 Mark Mitchell <mmitchell@usa.net>
@@ -2765,7 +7771,7 @@ Wed Mar 18 10:09:51 1998 Mark Mitchell <mmitchell@usa.net>
* 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>
* pt.c (push_template_decl): Only check primary templates.
@@ -2773,7 +7779,7 @@ Wed Mar 18 00:24:10 1998 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (check_explicit_specialization): Complain about default args
in explicit specialization.
- * parse.y (nomods_initdcl0): Also call cp_finish_decl for a
+ * parse.y (nomods_initdcl0): Also call cp_finish_decl for a
constructor_declarator.
Tue Mar 17 14:44:54 1998 Mark Mitchell <mmitchell@usa.net>
@@ -2800,7 +7806,7 @@ Mon Mar 16 12:10:39 1998 Jason Merrill <jason@yorick.cygnus.com>
* class.c (pushclass): Only use the mi_matrix stuff #ifdef MI_MATRIX.
* search.c: Likewise.
- * lex.c (do_pending_defargs): Only call
+ * lex.c (do_pending_defargs): Only call
maybe_{begin,end}_member_template_processing for FUNCTION_DECLs.
* parse.y (initdcl0_innards): Move maybeasm back into initdcl0 et al.
@@ -2813,9 +7819,9 @@ Mon Mar 16 10:54:21 1998 Mark Mitchell <mmitchell@usa.net>
* 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
+ (tsubst_expr): Return the resulting 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 (TEMPLATE_PARMS_FOR_INLINE): New macro.
@@ -2832,13 +7838,13 @@ Sun Mar 15 01:14:22 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
* lex.c (do_identifier): Handle TEMPLATE_DECL that was
added in the class scope to catch redefinition error.
- * pt.c (reduce_template_parm_level): Also copy
+ * pt.c (reduce_template_parm_level): Also copy
the DECL_TEMPLATE_PARMS field.
Sun Mar 15 10:54:08 1998 Mark Mitchell <mmitchell@usa.net>
* pt.c (tsubst): Clear TYPE_REFERENCE_TO when creating a
- reduced-level template type parameter.
+ reduced-level template type parameter.
Sun Mar 15 12:26:02 1998 Manfred Hollstein <manfred@s-direktnet.de>
@@ -2849,10 +7855,10 @@ Sun Mar 15 12:26:02 1998 Manfred Hollstein <manfred@s-direktnet.de>
* 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>
- * lang-specs.h: Properly put brackets around array elements in
+ * lang-specs.h: Properly put brackets around array elements in
initializer.
* typeck.c (build_binary_op_nodefault): Correctly place parens around
@@ -2870,7 +7876,7 @@ Thu Mar 12 09:26:04 1998 Manfred Hollstein <manfred@s-direktnet.de>
* except.c (do_unwind): #if 0 definition of unused variables fcall
and next_pc.
- * expr.c (extract_scalar_init): #if 0 prototype and function
+ * expr.c (extract_scalar_init): #if 0 prototype and function
definition.
* init.c (expand_aggr_init_1): Remove unused variable init_type.
@@ -2914,13 +7920,13 @@ Fri Mar 6 23:27:35 1998 Jeffrey A Law (law@cygnus.com)
Fri Mar 6 10:06:59 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * 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.
+ * 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.
Wed Mar 4 22:26:53 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
@@ -2931,7 +7937,7 @@ Wed Mar 4 12:11:53 1998 Michael Tiemann <tiemann@axon.cygnus.com>
* 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.
+ (get_typeid): Likewise.
Wed Mar 4 11:47:55 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -2950,7 +7956,7 @@ Tue Mar 3 01:38:17 1998 Jason Merrill <jason@yorick.cygnus.com>
some formatting quirks.
* 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
+ 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.
@@ -2966,7 +7972,7 @@ Mon Mar 2 12:11:06 1998 Jason Merrill <jason@yorick.cygnus.com>
(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
+ * pt.c (instantiate_class_template): Don't actually instantiate
anything if our type uses template parms.
Mon Mar 2 11:04:59 1998 Jim Wilson <wilson@cygnus.com>
@@ -2987,9 +7993,9 @@ Sat Feb 28 12:06:44 1998 Jason Merrill <jason@yorick.cygnus.com>
* 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
+ * call.c (build_scoped_method_call): Handle member template
destructor call.
- * pt.c (tsubst_copy, METHOD_CALL_EXPR): Don't assume a member
+ * pt.c (tsubst_copy, METHOD_CALL_EXPR): Don't assume a member
destructor is represented by the type.
* cp-tree.h (TYPENAME_TYPE_FULLNAME): New macro.
@@ -3036,7 +8042,7 @@ Fri Feb 27 02:25:16 1998 Jason Merrill <jason@yorick.cygnus.com>
* 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
+ * init.c (build_offset_ref): If name isn't an identifier, just
return it.
* spew.c (yylex): Handle PTYPENAME like TYPENAME.
@@ -3067,43 +8073,43 @@ Wed Feb 25 00:35:33 1998 Jason Merrill <jason@yorick.cygnus.com>
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
+ * 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.
+ (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.
+ * 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,
+ global_namespace. For namespace scoping, lookup in given
+ namespace. For unscoped lookup, iterate over namespace,
considering using directives.
- (init_decl_processing): initialize global_namespace.
+ (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.
+ * 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
+ * lex.c (build_lang_decl): Set namespace for new declaration to
current_namespace.
- (do_scoped_id): find global names in global or current
+ (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
@@ -3133,7 +8139,7 @@ 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,
+ * pt.c (push_tinst_level): If the instantiation uses template parms,
fail silently.
* decl.c (xref_basetypes): Do call complete_type for basetypes
that involve template parameters.
@@ -3162,7 +8168,7 @@ Mon Feb 23 02:52:29 1998 Mark Mitchell <mmitchell@usa.net>
* 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.
@@ -3197,7 +8203,7 @@ Mon Feb 23 02:52:29 1998 Mark Mitchell <mmitchell@usa.net>
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.
+ 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.
@@ -3210,7 +8216,7 @@ Mon Feb 23 02:52:29 1998 Mark Mitchell <mmitchell@usa.net>
conditionally calling end_member_template_processing.
(do_pending_defargs): Likewise.
(do_identifier): Use TEMPLATE_PARM_INDEX instead of
- TEMPLATE_CONST_PARM.
+ TEMPLATE_CONST_PARM.
* method.c (build_mangled_template_parm_index): New function.
(build_overload_value): Use it.
(build_overload_name): Likewise.
@@ -3240,14 +8246,14 @@ Mon Feb 23 02:52:29 1998 Mark Mitchell <mmitchell@usa.net>
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.
+ (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
+ * spew.c (yylex): Do a little manual constant propagation to
clarify the code.
-
+
Sun Feb 22 19:53:29 1998 Jeffrey A Law (law@cygnus.com)
* error.c: Include sys/types.h.
@@ -3260,20 +8266,20 @@ Thu Feb 19 10:36:48 1998 Jason Merrill <jason@yorick.cygnus.com>
* typeck2.c (process_init_constructor): Sorry about non-trivial
labeled initializers.
- * parse.y (initlist): Reenable labeled initializers.
+ * parse.y (initlist): Re-enable labeled initializers.
Thu Feb 19 10:15:55 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
- * pt.c (coerce_template_parms) Add a new parameter, is_tmpl_parm,
- all callers changed. Rely on the new parameter instead of arg
+ * 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_to_pointer): Preserve TREE_CONSTANT.
* typeck2.c (initializer_constant_valid_p): Allow conversions
- between pointers and refrerences.
+ between pointers and references.
1998-02-19 Brendan Kehoe <brendan@cygnus.com>
@@ -3304,14 +8310,14 @@ Tue Feb 17 14:07:52 1998 Mark Mitchell <mmitchell@usa.net>
(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>
* parse.y (simple_stmt): Use getdecls() to check for decl.
Sat Feb 14 11:50:51 1998 Manfred Hollstein <manfred@s-direktnet.de>
- * Make-lang.in (DEMANGLER_INSTALL_NAME, DEMANGLER_CROSS_NAME): New
+ * Make-lang.in (DEMANGLER_INSTALL_NAME, DEMANGLER_CROSS_NAME): New
macros.
(c++.install-common): Install c++filt properly as native or as cross
variant.
@@ -3327,14 +8333,14 @@ Fri Feb 13 14:06:22 1998 Mike Stump <mrs@wrs.com>
Fri Feb 13 13:24:32 1998 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (simple_stmt): If the condition isn't a declaration,
+ * parse.y (simple_stmt): If the condition isn't a declaration,
start the controlled block after the test.
Fri Feb 13 02:26:10 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* 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
+ * decl.c (init_decl_processing): Re-enable abs, labs and fabs as
builtins.
Fri Feb 13 01:36:42 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -3363,7 +8369,7 @@ Wed Feb 11 23:28:05 1998 Mark Mitchell <mmitchell@usa.net>
Wed Feb 11 16:42:04 1998 Mark Mitchell <mmitchell@usa.net>
* tree.c (is_overloaded_fn): Use really_overloaded_fn.
- (really_overloaded_fn): Move check here from is_overloaded_fn.
+ (really_overloaded_fn): Move check here from is_overloaded_fn.
(get_first_fn): Use really_overloaded_fn and is_overloaded_fn.
Wed Feb 11 15:54:18 1998 Mark Mitchell <mmitchell@usa.net>
@@ -3402,7 +8408,7 @@ Mon Feb 9 22:23:31 1998 Mark Mitchell <mmitchell@usa.net>
(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>
* pt.c (convert_nontype_argument): Fix typo.
@@ -3415,19 +8421,19 @@ Tue Feb 10 20:36:52 1998 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): Use DECL_USE_TEMPLATE instead
when deciding to override DECL_ASSEMBLER_NAME.
-Tue Feb 10 15:30:55 EST 1998 Andrew MacLeod <amacleod@torpedo.to.cygnus.com>
+Tue Feb 10 15:30:55 1998 Andrew MacLeod <amacleod@torpedo.to.cygnus.com>
* 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
+ (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_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_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.
@@ -3440,7 +8446,7 @@ Tue Feb 10 15:30:55 EST 1998 Andrew MacLeod <amacleod@torpedo.to.cygnus.com>
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
+ (build_typename_overload, build_overload_with_type): Initiate
squangling
Sun Feb 8 23:47:38 1998 scott snyder <sss@d0linux01.fnal.gov>
@@ -3476,7 +8482,7 @@ Tue Feb 3 23:50:52 1998 Mark Mitchell <mmitchell@usa.net>
* 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.
+ decl.
* decl2.c (finish_file): Make sure that static inlines with
definitions are not marked DECL_EXTERNAL before returning.
@@ -3485,7 +8491,7 @@ Tue Feb 3 22:43:42 1998 Jason Merrill <jason@yorick.cygnus.com>
* decl.c: Lose arg_looking_for_template.
(lookup_name_real): Likewise.
- * parse.y: Lose processing_template_arg, template_arg1
+ * parse.y: Lose processing_template_arg, template_arg1.
(primary): Likewise.
* spew.c (yylex): Set lastiddecl for PTYPENAMEs, too.
@@ -3493,36 +8499,36 @@ Tue Feb 3 22:04:01 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
* 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
+ * parse.y (template_parm): Handle invalid default template
template arguments here.
- * parse.y (template_parm): Use template_arg instead of PTYPENAME
+ * parse.y (template_parm): Use template_arg instead of PTYPENAME
for default template template argument.
- * pt.c (coerce_template_parms): Merge default 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
+ * typeck.c (comptypes): Merge template argument comparison codes in
TEMPLATE_TEMPLATE_PARM and RECORD_TYPE.
-Tue Jan 6 01:42:44 1998 Mumit Khan <khan@xraylith.wisc.edu>
+Tue Jan 6 01:42:44 1998 Mumit Khan <khan@xraylith.wisc.edu>
* lex.c (file_name_nondirectory): Also check for '/'.
Mon Feb 2 11:24:22 1998 Mark Mitchell <mmitchell@usa.net>
* parse.y (primary): Deal with statement-expressions in
- templates.
+ templates.
* pt.c (tsubst_copy): Handle BIND_EXPR.
* tree.c (mapcar): Likewise.
* call.c (add_template_candidate_real): Pass extra parameter to
- fn_type_unification.
+ 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.
+ * 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.
@@ -3571,7 +8577,7 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(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'.
+ (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
@@ -3581,7 +8587,7 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* error.c: Include <stdlib.h>.
(dump_expr): Change the type of `i' to size_t. Remove unused
- label `error'.
+ label `error'.
* except.c (init_exception_processing): Remove unused variable `d'.
(expand_throw): Likewise for `label'.
@@ -3607,7 +8613,7 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
`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.
+ (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.
@@ -3628,8 +8634,8 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* 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.
+
+ * search.c (get_binfo): Initialize `type' to NULL_TREE.
(get_base_distance): Likewise.
(lookup_field): Initialize `rval_binfo_h', `type', `basetype_path'
and `new_v' to NULL_TREE.
@@ -3649,7 +8655,7 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(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.
@@ -3665,7 +8671,7 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* xref.c (GNU_xref_decl): Initialize `cls' to 0.
-Sun Feb 1 12:45:34 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+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.
@@ -3688,13 +8694,13 @@ Thu Jan 29 10:39:30 1998 Mark Mitchell <mmitchell@usa.net>
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.
+ 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.
@@ -3703,7 +8709,7 @@ Wed Jan 28 11:04:07 1998 Mark Mitchell <mmitchell@usa.net>
* 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.
@@ -3715,7 +8721,7 @@ Wed Jan 28 11:04:07 1998 Mark Mitchell <mmitchell@usa.net>
* 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
@@ -3727,7 +8733,7 @@ Wed Jan 28 11:04:07 1998 Mark Mitchell <mmitchell@usa.net>
* 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.
@@ -3755,18 +8761,18 @@ Tue Jan 27 16:42:21 1998 Mark Mitchell <mmitchell@usa.net>
(maybe_push_to_top_level): Save them.
(pop_from_top_level): Restore them.
(grokfndecl): Use new return value from
- check_explicit_specialization.
+ check_explicit_specialization.
(start_decl): Don't check flag_guiding_decls before pushing
- decls.
+ decls.
(cp_finish_decl): Remove previous (bogus) change.
(grok_declarator): Use decl_function_context rather than
- is_local_class.
+ is_local_class.
* decl2.c (finish_file): Pass extra argument to get_bindings.
- (build_expr_from_tree): Let build_x_component_ref check
+ (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.
+ 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.
@@ -3775,9 +8781,9 @@ Tue Jan 27 16:42:21 1998 Mark Mitchell <mmitchell@usa.net>
(determine_specialization): Change interface. Properly look for
most specialized versions of template candidates.
(check_explicit_specialization): Fully process explicit
- instantiations.
+ instantiations.
(push_template_decl): Avoid looking at CLASSTYPE fields in
- FUNCTION_DECLS.
+ FUNCTION_DECLS.
(determine_overloaded_function): Remove.
(convert_nontype_argument): Change name from
convert_nontype_parameter. Use determine_overloaded_function
@@ -3788,7 +8794,7 @@ Tue Jan 27 16:42:21 1998 Mark Mitchell <mmitchell@usa.net>
(lookup_template_class): Likewise.
(tsubst): Likewise.
(more_specialized): Take explict template arguments as a
- parameter.
+ parameter.
(most_specialized): Likewise.
(get_bindings): Likewise. Check that return types match before
proclaiming a function a match.
@@ -3801,7 +8807,7 @@ Tue Jan 27 16:42:21 1998 Mark Mitchell <mmitchell@usa.net>
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
+ * 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
@@ -3819,7 +8825,7 @@ 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>
+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.
@@ -3827,10 +8833,10 @@ Fri Jan 23 18:34:37 1998 Mumit Khan <khan@xraylith.wisc.edu>
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
+ 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
+ (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
@@ -3851,15 +8857,15 @@ Wed Jan 21 10:29:57 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
(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_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):
+ * 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):
+ (build_overload_nested_name, build_overload_name):
Handle TEMPLATE_TEMPLATE_PARM.
* parse.y (maybe_identifier): New nonterminal.
(template_type_parm): Use it.
@@ -3873,11 +8879,11 @@ Wed Jan 21 10:29:57 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
(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
+ (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):
+ * search.c (dfs_walk, dfs_record_inheritance):
Handle TEMPLATE_TEMPLATE_PARM.
* tree.c (copy_template_template_parm): New function.
(mapcar): Handle TEMPLATE_TEMPLATE_PARM.
@@ -3893,16 +8899,16 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
* 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.
+ * decl.c (cp_finish_decl): Check for NULL where necessary.
Consider FUNCTION_DECLS to declare objects with top-level binding,
when calling make_decl_rtl.
(grokdeclarator): Give members of local classes internal linkage.
@@ -3922,19 +8928,19 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
* pt.c (saved_trees): New variable.
(mangle_class_name_for_template): Change prototype. Use
additional function context to name local classes in templates
- correctly.
+ 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.
+ 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.
+ 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.
@@ -3946,11 +8952,11 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
(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.
+
+ * 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.
@@ -3960,7 +8966,7 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
(begin_explicit_instantiation): Likewise.
(end_explicit_instantiation): Likewise.
(determine_specialization): Renamed from
- determine_explicit_specialization.
+ determine_explicit_specialization.
(comp_template_parms): New function.
(processing_explicit_instantiation): New variable.
* cvt.c (perform_qualification_conversions): New function.
@@ -3970,7 +8976,7 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
instantiation/specialization mismatches.
(start_decl): Don't call pushdecl for template specializations,
since they don't affect overloading.
- (start_function): Likewise
+ (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
@@ -3981,7 +8987,7 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
* parse.y (finish_member_template_decl): New function.
(component_decl_1): Use it.
(fn.def2): Likewise.
- (template_arg_list_opt): New nonterminal.
+ (template_arg_list_opt): New nonterminal.
(template_type): Use it.
(self_template_type): Likewise.
(template_id): Likewise.
@@ -4005,12 +9011,12 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
(comp_template_parms): New function.
(coerce_template_parms): Call convert_nontype_parameter.
(tsubst): Refine handling of member templates. Use
- register_specialization.
+ register_specialization.
(instantiate_template): Use retrieve_specialization.
(do_decl_instantiation): Likewise.
(instantiate_decl): Likewise.
(type_unification): Improve handling of explict template
- arguments.
+ 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
@@ -4022,7 +9028,7 @@ Mon Jan 19 13:18:51 1998 Jason Merrill <jason@yorick.cygnus.com>
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.
+ * error.c (dump_decl): For enum tags, output the tag, not its value.
1998-01-13 Brendan Kehoe <brendan@cygnus.com>
@@ -4052,11 +9058,11 @@ Wed Jan 7 23:47:13 1998 Jason Merrill <jason@yorick.cygnus.com>
(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
+ * typeck.c (build_modify_expr): Remove code that ignores trivial
methods.
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.
@@ -4087,7 +9093,7 @@ Thu Dec 18 14:51:50 1997 Mark Mitchell <mmitchell@usa.net>
Thu Dec 18 14:43:19 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (unary_complex_lvalue): Ignore op0 when taking the
+ * typeck.c (unary_complex_lvalue): Ignore op0 when taking the
address of an OFFSET_REF.
* cp-tree.def: Add AGGR_INIT_EXPR.
@@ -4100,10 +9106,10 @@ Thu Dec 18 14:43:19 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Dec 17 17:08:52 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
* pt.c (instantiate_class_template): Don't do injection when
- processing_template_decl is true, as pollutes current_binding_level
- for base classes.
+ processing_template_decl is true, as pollutes current_binding_level
+ for base classes.
-Wed Dec 17 21:17:39 1997 Peter Schmid <schmid@ltoi.iap.physik.tu-darmstadt.de>
+Wed Dec 17 21:17:39 1997 Peter Schmid <schmid@ltoi.iap.physik.tu-darmstadt.de>
* pt.c (maybe_fold_nontype_arg): Add prototype.
@@ -4123,21 +9129,21 @@ Sun Dec 14 22:34:20 1997 Jason Merrill <jason@yorick.cygnus.com>
* cvt.c (cp_convert_to_pointer): Fix base conversion of pm's.
- * pt.c (type_unification_real): Change __null to type void* with
+ * pt.c (type_unification_real): Change __null to type void* with
a warning.
Sun Dec 14 20:38:35 1997 Mark Mitchell <mmitchell@usa.net>
* call.c (implicit_conversion): Don't call
build_user_type_conversion_1 with a NULL expr, since it will
- crash.
+ crash.
* pt.c (unify): Don't try to unify array bounds if either array is
unbounded.
Fri Dec 12 16:09:14 1997 Jason Merrill <jason@yorick.cygnus.com>
- * errfn.c (cp_pedwarn, cp_pedwarn_at, cp_error_at, cp_warning_at):
+ * errfn.c (cp_pedwarn, cp_pedwarn_at, cp_error_at, cp_warning_at):
Replace extern decls with casts.
* decl.c (expand_start_early_try_stmts): Don't mess with a sequence.
@@ -4150,7 +9156,7 @@ Thu Dec 11 22:18:37 1997 Jason Merrill <jason@yorick.cygnus.com>
* 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.
+ comdat_linkage for win32 tweak.
(import_export_decl): Likewise.
* pt.c (mark_decl_instantiated): Likewise.
@@ -4164,16 +9170,16 @@ Thu Dec 11 21:12:09 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl.c: Likewise.
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.
+ (__cp_push_exception): Likewise.
+ (__cp_pop_exception): Likewise.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
- * except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
+ * except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
@@ -4186,8 +9192,8 @@ Mon Dec 8 23:17:13 1997 Jason Merrill <jason@yorick.cygnus.com>
* init.c (expand_vec_init): Don't fold a list of parameters.
* decl.c (copy_args_p): Handle copy elision for types with virtual
- bases.
- * call.c (build_over_call): Likewise.
+ bases.
+ * call.c (build_over_call): Likewise.
Sun Dec 7 22:38:12 1997 Mark Mitchell <mmitchell@usa.net>
@@ -4242,8 +9248,8 @@ Fri Dec 5 01:17:34 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Dec 3 20:02:39 1997 Jason Merrill <jason@yorick.cygnus.com>
* init.c (build_new): Use a TARGET_EXPR instead of SAVE_EXPR for
- alloc_expr.
- * call.c (build_op_delete_call): Adjust.
+ alloc_expr.
+ * call.c (build_op_delete_call): Adjust.
* except.c (expand_end_catch_block): Lose rethrow region.
(expand_start_catch_block): Likewise.
@@ -4252,7 +9258,7 @@ Wed Dec 3 20:02:39 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Dec 3 13:24:04 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
* pt.c (tsubst): Remove tree_cons call (places redundant info into
- DECL_TEMPLATE_INSTANTIATION).
+ DECL_TEMPLATE_INSTANTIATION).
Wed Dec 3 11:44:52 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -4294,7 +9300,7 @@ Tue Dec 2 01:37:19 1997 Jason Merrill <jason@yorick.cygnus.com>
Fri Nov 28 01:58:14 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (check_explicit_specialization): Complain about using a
+ * pt.c (check_explicit_specialization): Complain about using a
template-id for a non-specialization.
Fri Nov 28 12:35:19 1997 Scott Christley <scottc@net-community.com>
@@ -4304,7 +9310,7 @@ Fri Nov 28 12:35:19 1997 Scott Christley <scottc@net-community.com>
Fri Nov 28 01:56:35 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * error.c (dump_decl): Handle TEMPLATE_ID_EXPR.
+ * error.c (dump_decl): Handle TEMPLATE_ID_EXPR.
Thu Nov 27 00:59:46 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -4312,9 +9318,9 @@ Thu Nov 27 00:59:46 1997 Jason Merrill <jason@yorick.cygnus.com>
handing off to convert_to_reference.
* except.c: Lose Unexpected, SetTerminate, SetUnexpected,
- TerminateFunctionCall.
+ TerminateFunctionCall.
(init_exception_processing): Likewise. Terminate et al are now
- the fns, not ADDR_EXPRs.
+ the fns, not ADDR_EXPRs.
(various): Lose redundant assemble_external calls.
(do_unwind): s/BuiltinReturnAddress/builtin_return_address_fndecl/.
@@ -4325,7 +9331,7 @@ Thu Nov 27 00:59:46 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (import_export_decl): Just set DECL_COMDAT on VAR_DECLs.
* class.c: Remove static pending_hard_virtuals.
- (add_virtual_function): Take pointers to pending_virtuals
+ (add_virtual_function): Take pointers to pending_virtuals
and pending_hard_virtuals.
(finish_struct_1): Pass them. Declare pending_hard_virtuals.
@@ -4334,7 +9340,7 @@ Wed Nov 26 20:28:49 1997 Jason Merrill <jason@yorick.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
+ (finish_vtable_vardecl): Also write out vtables from explicitly
instantiated template classes.
* pt.c (mark_class_instantiated): Revert last change.
@@ -4369,7 +9375,7 @@ Tue Nov 25 11:28:21 1997 Jason Merrill <jason@yorick.cygnus.com>
* init.c (build_new): Copy size to the saveable obstack.
* init.c (build_new): Stick a CLEANUP_POINT_EXPR inside the
- TRY_CATCH_EXPR for now.
+ TRY_CATCH_EXPR for now.
Mon Nov 24 12:15:55 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -4390,14 +9396,14 @@ Fri Nov 21 12:22:07 1997 Jason Merrill <jason@yorick.cygnus.com>
(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.
+ 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.
* except.c (expand_start_catch_block): We only need the rethrow
- region for non-sjlj exceptions.
+ region for non-sjlj exceptions.
(expand_end_catch_block): Likewise. Use outer_context_label_stack.
Thu Nov 20 14:40:17 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -4412,7 +9418,7 @@ Thu Nov 20 14:40:17 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (init_decl_processing): Update exception specs on new and
delete.
- * method.c (build_decl_overload_real): Don't mess with global
+ * method.c (build_decl_overload_real): Don't mess with global
placement delete.
* init.c (build_new): Check for null throw spec, not nothrow_t.
@@ -4427,13 +9433,13 @@ Thu Nov 20 14:40:17 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Nov 19 18:24:14 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_decl): Don't just complain about a mismatched
+ * decl.c (start_decl): Don't just complain about a mismatched
scope, fix it.
* decl.c (make_implicit_typename): Handle case where t is not
- actually from context.
+ actually from context.
* tree.c (get_type_decl): Lose identifier case.
- * spew.c (yylex): Lose useless call to identifer_typedecl_value.
+ * spew.c (yylex): Lose useless call to identifier_typedecl_value.
* parse.y (nonnested_type): Just use lookup_name.
(complex_type_name): Just use IDENTIFIER_GLOBAL_VALUE.
@@ -4448,7 +9454,7 @@ Wed Nov 19 10:39:27 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (make_implicit_typename): New fn.
(lookup_name_real): Use it. Use current_class_type as the context.
-Mon Nov 17 23:42:03 1997 Bruno Haible <haible@ilog.fr>
+Mon Nov 17 23:42:03 1997 Bruno Haible <haible@ilog.fr>
* pt.c (do_poplevel): Don't prohibit jumps into this contour.
@@ -4483,7 +9489,7 @@ Thu Nov 13 01:52:36 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Nov 12 11:04:33 1997 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (do_type_instantiation): Fix typo.
- (mark_class_instantiated): If we support one_only but not weak
+ (mark_class_instantiated): If we support one_only but not weak
symbols, don't mark this as known.
* init.c (build_new): Handle vec delete in EH cleanup.
@@ -4491,7 +9497,7 @@ Wed Nov 12 11:04:33 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Nov 12 08:11:55 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
* call.c (build_method_call): Call complete_type before checking
- for destructor.
+ for destructor.
Sun Nov 9 01:29:55 1997 Jim Wilson (wilson@cygnus.com)
@@ -4524,32 +9530,32 @@ Tue Nov 11 02:53:44 1997 Jason Merrill <jason@lasher.cygnus.com>
Mon Nov 10 20:25:31 1997 Jason Merrill <jason@yorick.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.
+ 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.
+ 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.
-Mon Nov 10 20:08:38 1997 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+Mon Nov 10 20:08:38 1997 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
- * pt.c (tsubst_copy): Handle explicit template arguments in
+ * 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
+ * decl2.c (build_expr_from_tree): Lookup function name if it
hasn't been done.
- * pt.c (tsubst): Instantiate template functions properly when
- template parameter does not appear in function arguments and return
+ * 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.
Mon Nov 10 20:08:38 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): Tweak conditions for pedwarn in
- previous change.
+ previous change.
Mon Nov 10 20:08:29 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
@@ -4570,10 +9576,10 @@ Mon Nov 10 03:04:20 1997 Jason Merrill <jason@yorick.cygnus.com>
(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,
+ * 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
+ * init.c (expand_default_init): Handle a TRY_CATCH_EXPR around
the constructor call.
Sun Nov 9 18:00:26 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
@@ -4642,7 +9648,7 @@ Fri Oct 31 01:47:57 1997 Jason Merrill <jason@yorick.cygnus.com>
(__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.
+ 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.
@@ -4670,21 +9676,21 @@ Thu Oct 23 02:01:30 1997 Jason Merrill <jason@yorick.cygnus.com>
Mon Oct 20 12:06:34 1997 Jason Merrill <jason@yorick.cygnus.com>
- * except.c (expand_exception_blocks): Call do_pending_stack_adust.
+ * except.c (expand_exception_blocks): Call do_pending_stack_adjust.
(expand_end_catch_block): Likewise.
(expand_end_eh_spec): Likewise.
Mon Oct 20 11:44:20 1997 Mark Mitchell <mmitchell@usa.net>
* decl.c (duplicate_decls): Handle template specializations
- correctly.
+ 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>
* decl.c (init_decl_processing): Give null_node unknown* type.
@@ -4701,7 +9707,7 @@ Sun Oct 19 09:13:01 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* Make-lang.in (g++): Include prefix.o.
-Thu Oct 16 15:31:09 1997 Judy Goldberg <judygold@sanwafp.com>
+Thu Oct 16 15:31:09 1997 Judy Goldberg <judygold@sanwafp.com>
* pt.c (determine_explicit_specialization): Initialize "dummy"
to keep Purify quiet.
@@ -4727,19 +9733,19 @@ Tue Oct 14 12:01:00 1997 Mark Mitchell <mmitchell@usa.net>
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>
* 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,
+ * 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.
Mon Oct 13 17:41:26 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
* decl.c (store_return_init): Allow classes with explicit ctors to
- be used with the named return values extension.
+ be used with the named return values extension.
Fri Oct 10 12:21:11 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -4753,7 +9759,7 @@ Thu Oct 9 12:08:21 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (build_new_method_call): Use simple constructor_name for
error messages.
-Wed Oct 8 22:44:42 1997 Jeffrey A Law (law@cygnus.com)
+Wed Oct 8 22:44:42 1997 Jeffrey A Law <law@cygnus.com>
* method.c (build_underscore_int): Don't use ANSI specific
features.
@@ -4774,9 +9780,9 @@ Tue Oct 7 22:52:10 1997 Jason Merrill <jason@yorick.cygnus.com>
Tue Oct 7 22:45:31 1997 Alexandre Oliva <oliva@dcc.unicamp.br>
- * typeck.c (build_reinterpret_cast): converting a void pointer
+ * typeck.c (build_reinterpret_cast): Converting a void pointer
to function pointer with a reinterpret_cast produces a warning
- if -pedantic is issued
+ if -pedantic is issued.
Tue Oct 7 22:43:43 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
@@ -4803,7 +9809,7 @@ Tue Oct 7 00:48:36 1997 Jason Merrill <jason@yorick.cygnus.com>
non-templates.
* call.c (build_new_function_call): Fix handling of null explicit
- template args.
+ template args.
(build_new_method_call): Likewise.
Mon Oct 6 23:44:34 1997 Mark Mitchell <mmitchell@usa.net>
@@ -4855,7 +9861,7 @@ Tue Sep 30 00:18:26 1997 Jason Merrill <jason@yorick.cygnus.com>
-traditional and -ansi now do not mess with
dollars_in_ident.
-Mon Sep 29 19:57:51 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+Mon Sep 29 19:57:51 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
* Makefile.in (parse.o, decl.o): Also depend on
$(srcdir)/../except.h $(srcdir)/../output.h.
@@ -4866,37 +9872,37 @@ Mon Sep 29 19:57:51 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
* call.c, cp-tree.h, decl.c, tree.c: Finish prototyping.
- * expr.c (cplus_expand_expr): Make it static.
+ * expr.c (cplus_expand_expr): Make it static.
* decl2.c, init.c, typeck.c: Include "expr.h".
(expand_expr): Use proper values when calling the function.
Mon Sep 29 11:05:54 1997 Alexandre Oliva <oliva@dcc.unicamp.br>
- * 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.
+ * lang-options.h: New -Wold-style-cast flag.
+ * cp-tree.h (warn_old_style_cast): New variable.
+ * decl2.c (warn_old_style_cast): Likewise.
+ (lang_decode_option): Support -Wold-style-cast.
+ (reparse_absdcl_as_casts): Produce old-style-cast warning.
Mon Sep 29 09:20:53 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
* decl.c (cp_finish_decl): Allow expand_aggr_init to set
- TREE_USED, reset value based on already_used.
+ TREE_USED, reset value based on already_used.
* 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.
+ 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.
+ decls.
* decl2.c (lang_decode_option): Handle -fguiding-decls.
* parse.y (notype_template_declarator): New nonterminal.
(direct_notype_declarator): Use it.
@@ -4906,112 +9912,112 @@ Sat Sep 27 16:22:48 1997 Jason Merrill <jason@yorick.cygnus.com>
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.
+ * 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.
+ * 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.def (TEMPLATE_ID_EXPR): New tree code.
- * cp-tree.h (name_mangling_version): New variable.
+ * 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,
+ (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.
+ * 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>
@@ -5041,7 +10047,7 @@ Thu Sep 25 11:11:13 1997 Jason Merrill <jason@yorick.cygnus.com>
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.
+ (joust): Re-enable ?: kludge.
1997-09-22 Brendan Kehoe <brendan@lisa.cygnus.com>
@@ -5077,12 +10083,12 @@ Wed Sep 17 10:31:25 1997 Jason Merrill <jason@yorick.cygnus.com>
Tue Sep 16 14:06:56 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (build_new_op): Give better error for syntactically
- correct, but semantically invalid, use of undeclared template.
+ correct, but semantically invalid, use of undeclared template.
* call.c (compare_qual): Handle pmfs.
* decl.c (store_parm_decls): last_parm_cleanup_insn is the insn
- after the exception spec.
+ after the exception spec.
Mon Sep 15 11:52:13 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5118,9 +10124,9 @@ Thu Sep 11 10:08:45 1997 Mark Mitchell <mmitchell@usa.net>
* pt.c (coerce_template_parms): Avoid looking at the
TYPE_LANG_DECL portion of a typename type, since there won't be
- one.
+ one.
(tsubst): Do constant folding as necessary to make sure that
- arguments passed to lookup_template_class really are constants.
+ arguments passed to lookup_template_class really are constants.
Wed Sep 10 11:21:55 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5137,9 +10143,9 @@ Tue Sep 9 19:49:38 1997 Jason Merrill <jason@yorick.cygnus.com>
Tue Sep 9 17:57:25 1997 Mark Mitchell <mmitchell@usa.net>
* error.c (dump_decl): Avoid crashing when presented with a
- uninitialized constant, as can occur with a template parameter.
+ 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.
+ current_template_parms before we start diving through them.
1997-09-09 Brendan Kehoe <brendan@lisa.cygnus.com>
@@ -5148,7 +10154,7 @@ Tue Sep 9 17:57:25 1997 Mark Mitchell <mmitchell@usa.net>
Tue Sep 9 09:36:39 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * except.c (expand_throw): Call build_delete for all
+ * except.c (expand_throw): Call build_delete for all
exception types, not just objects with destructors.
Mon Sep 8 02:33:20 1997 Jody Goldberg <jodyg@idt.net>
@@ -5156,7 +10162,7 @@ Mon Sep 8 02:33:20 1997 Jody Goldberg <jodyg@idt.net>
* 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.
+ (instantiate_class_template): Use new tsubst_enum signature.
(tsubst_expr): Likewise.
Mon Sep 8 01:21:43 1997 Mark Mitchell <mmitchell@usa.net>
@@ -5168,7 +10174,7 @@ Mon Sep 8 01:21:43 1997 Mark Mitchell <mmitchell@usa.net>
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.
+ appropriate.
* lex.c (do_pending_inlines): Pass the function, not its template
arguments, to begin_member_template_processing.
@@ -5176,17 +10182,17 @@ Mon Sep 8 01:21:43 1997 Mark Mitchell <mmitchell@usa.net>
(do_pending_defargs): Likewise.
* error.c (dump_expr): Obtain the correct declaration for a
- TEMPLATE_CONST_PARM.
+ TEMPLATE_CONST_PARM.
* 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>
* 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.
@@ -5206,24 +10212,24 @@ Fri Sep 5 01:37:17 1997 Mark Mitchell <mmitchell@usa.net>
* 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.
+ 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.
@@ -5232,13 +10238,13 @@ Fri Sep 5 01:37:17 1997 Mark Mitchell <mmitchell@usa.net>
member templates correctly.
* pt.c (is_member_template): Deal with class specializations
- correctly.
+ correctly.
(tsubst): Handle "partial instantiation" of member templates
- correctly.
+ correctly.
Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
- * pt.c (type_unification): Change calling squence to allow for
+ * pt.c (type_unification): Change calling sequence to allow for
multiple levels of template parameters.
(tsubst_expr): Likewise.
(tsubst): Likewise.
@@ -5252,7 +10258,7 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
* 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.
@@ -5260,12 +10266,12 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
(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.
+ that two member templates with the same name are ambiguous.
(finish_struct): Treat member template functions just like member
- functions.
-
+ functions.
+
* cp-tree.h (check_member_template): Add declaration.
(begin_member_template_processing): Likewise.
(end_member_template_processing): Likewise.
@@ -5278,31 +10284,31 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
(get_bindings): Likewise.
* decl.c (decls_match): Handle multiple levels of template
- parameters.
+ parameters.
(pushdecl): Handle template type params just like other type
- declarations.
+ 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.
+ parameters.
+ (dump_function_decl): Update to handle function templates.
* lex.c (do_pending_inlines): Set up template parameter context
for member templates.
(process_next_inline): Likewise.
- * method. (build_overload_identifier): Adjust for multiple levels
+ * method.c (build_overload_identifier): Adjust for multiple levels
of template parameters.
-
+
* parse.y (fn.def2): Add member templates.
(component_decl_1): Likewise.
@@ -5313,7 +10319,7 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
(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.
+ templates.
(lookup_template_class): Likewise.
(uses_template_parms): Likewise.
(tsubst): Modify processing to TEMPLATE_TYPE_PARM and
@@ -5323,7 +10329,7 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
(do_decl_instantiation): Handle member templates.
* search.c (lookup_fnfields_1): Handle member template conversion
- operators.
+ operators.
* tree.c (cp_tree_equal): Check the levels, as well as the
indices, of TEMPLATE_CONST_PARMs.
@@ -5331,12 +10337,12 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
* 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.
-
+ functions.
+
Wed Sep 3 11:09:25 1997 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (c_expand_return): Always convert_for_initialization
- before checking for returning a pointer to local.
+ before checking for returning a pointer to local.
* pt.c (type_unification): If strict and the function parm doesn't
use template parms, just compare types.
@@ -5349,7 +10355,7 @@ Wed Sep 3 10:35:49 1997 Klaus Espenlaub <kespenla@student.informatik.uni-ulm.
Wed Sep 3 00:02:53 1997 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (convert_arguments): Don't arbitrarily choose the first
- of a set of overloaded functions.
+ of a set of overloaded functions.
Tue Sep 2 12:09:13 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5360,12 +10366,12 @@ Tue Sep 2 12:09:13 1997 Jason Merrill <jason@yorick.cygnus.com>
(build_overload_identifier): Pass it.
* decl.c (duplicate_decls): Don't bash a previous template
- definition with a redeclaration.
+ definition with a redeclaration.
* pt.c (unify): float doesn't match double.
* pt.c (do_type_instantiation): Handle getting a _TYPE or a
- TYPE_DECL. Handle getting non-template types.
+ TYPE_DECL. Handle getting non-template types.
* parse.y (explicit_instantiation): Use typespec instead of
aggr template_type.
@@ -5373,7 +10379,7 @@ Tue Sep 2 10:27:08 1997 Richard Henderson <rth@cygnus.com>
* typeck.c (build_ptrmemfunc1): Clean up ptr->int cast warnings.
-Mon Sep 1 13:19:04 1997 Eugene Mamchits <eugin@ips.ras.ru>
+Mon Sep 1 13:19:04 1997 Eugene Mamchits <eugin@ips.ras.ru>
* call.c (add_builtin_candidate): Add missing TREE_TYPE.
(compare_ics): Likewise.
@@ -5381,8 +10387,8 @@ Mon Sep 1 13:19:04 1997 Eugene Mamchits <eugin@ips.ras.ru>
Mon Sep 1 13:19:04 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (joust): Warn about choosing one conversion op over
- another because of 'this' argument when the other return type is
- better.
+ another because of 'this' argument when the other return type is
+ better.
(source_type): New fn.
* call.c (build_new_op): Strip leading REF_BIND from first operand
@@ -5395,7 +10401,7 @@ Thu Aug 28 09:45:23 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (null_ptr_cst_p): Remove support for (void*)0.
-Wed Aug 27 02:03:34 1997 Jeffrey A Law (law@cygnus.com)
+Wed Aug 27 02:03:34 1997 Jeffrey A Law <law@cygnus.com>
* typeck.c (expand_target_expr): Make definition match declaration.
@@ -5415,7 +10421,7 @@ Sat Aug 23 18:02:59 1997 Mark Mitchell <mmitchell@usa.net>
* error.c (type_as_string): Put const/volatile on template type
parameters where appropriate.
-Sat Aug 23 17:47:22 1997 Jeffrey A Law (law@cygnus.com)
+Sat Aug 23 17:47:22 1997 Jeffrey A Law <law@cygnus.com>
* call.c (strictly_better): Make arguments unsigned ints.
@@ -5423,7 +10429,7 @@ Thu Aug 21 18:48:44 1997 Jason Merrill <jason@yorick.cygnus.com>
* lex.c (real_yylex): Refer to __complex instead of complex.
-Thu Aug 21 22:25:46 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Thu Aug 21 22:25:46 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
* lex.c (real_yylex): Don't use getc directly.
@@ -5435,10 +10441,10 @@ Wed Aug 20 03:13:36 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
* 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.
+ 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.
Wed Aug 20 01:34:40 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5461,7 +10467,7 @@ Tue Aug 19 02:26:07 1997 Jason Merrill <jason@yorick.cygnus.com>
* repo.c (finish_repo): Don't crash on no args.
* parse.y (named_complex_class_head_sans_basetype): Handle
- explicit global scope.
+ explicit global scope.
* decl2.c (handle_class_head): New fn.
* pt.c (unify): Add CONST_DECL case.
@@ -5494,13 +10500,13 @@ Wed Aug 13 10:46:19 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
Tue Aug 12 20:13:57 1997 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y: Don't clear the inlines from their obstack until they've
+ * parse.y: Don't clear the inlines from their obstack until they've
all been processed.
* decl.c (duplicate_decls): Don't complain about exception
- specification mismatch if flag_exceptions is off.
+ specification mismatch if flag_exceptions is off.
-Mon Aug 11 15:01:56 1997 Marc Lehmann <pcg@goof.com>
+Mon Aug 11 15:01:56 1997 Marc Lehmann <pcg@goof.com>
* Make-lang.in (c++.distclean): Remove g++.c on make distclean.
@@ -5508,10 +10514,10 @@ Sun Aug 10 12:06:09 1997 Paul Eggert <eggert@twinsun.com>
* 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.
+ Include <stdio.h> before include files that formerly used STDIO_PROTO.
* decl.c, g++spec.c, lex.c, method.c, repo.c:
- Include "config.h" first, as per autoconf manual.
+ Include "config.h" first, as per autoconf manual.
Fri Aug 8 11:47:48 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5523,13 +10529,13 @@ Fri Aug 8 11:47:48 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (lang_decode_option): Handle -fhandle-exceptions.
* lang-options.h: Add -fhandle-exceptions.
- * class.c (build_vtable): vtables are artificial.
+ * class.c (build_vtable): Vtables are artificial.
(prepare_fresh_vtable): Likewise.
Wed Aug 6 11:02:36 1997 Jason Merrill <jason@yorick.cygnus.com>
* cvt.c (ocp_convert): After converting to the target type, set
- LOOKUP_NO_CONVERSION.
+ LOOKUP_NO_CONVERSION.
* call.c (joust): Warn about potentially confusing promotion rules
with -Wsign-promo.
@@ -5607,18 +10613,18 @@ Fri Jul 18 17:56:08 1997 Jason Merrill <jason@yorick.cygnus.com>
Thu Jul 17 18:06:30 1997 Jason Merrill <jason@yorick.cygnus.com>
* method.c (build_overload_nested_name): Use static_labelno
- instead of var_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
+ * decl.c (cp_finish_decl): Statics in extern inline functions
have comdat linkage.
(start_function): Initialize static_labelno.
Thu Jul 17 11:20:17 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * class.c (finish_struct_methods): add check of warn_ctor_dtor_privacy
- before "all member functions in class [] are private"
+ * class.c (finish_struct_methods): Add check of warn_ctor_dtor_privacy
+ before "all member functions in class [] are private".
Wed Jul 16 23:47:08 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5632,7 +10638,7 @@ Wed Jul 16 12:34:29 1997 Benjamin Kosnik <bkoz@lisa.cygnus.com>
Mon Jul 14 03:23:46 1997 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (get_member_function_from_ptrfunc): Promote index
- before saving it.
+ before saving it.
Sun Jul 13 00:11:52 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5686,7 +10692,7 @@ Wed Jul 9 13:44:12 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Jul 9 13:04:38 1997 Geoffrey Noer <noer@cygnus.com>
- * decl.c (init_decl_processing): fix Jun 30 patch -- move
+ * decl.c (init_decl_processing): Fix Jun 30 patch -- move
ifndef for Cygwin32 to include SIGSEGV.
Thu Jul 3 01:44:05 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5697,17 +10703,17 @@ Thu Jul 3 01:44:05 1997 Jason Merrill <jason@yorick.cygnus.com>
* rtti.c (build_dynamic_cast): Call complete_type on the types.
* decl.c (grokfndecl): If the function we chose doesn't actually
- match, die.
+ match, die.
* decl2.c (grokclassfn): Don't specify 'const int' for the
- artificial destructor parm.
+ artificial destructor parm.
- * pt.c (type_unification): If we are called recursively, nothing
+ * pt.c (type_unification): If we are called recursively, nothing
decays.
Mon Jun 30 17:53:21 1997 Geoffrey Noer <noer@cygnus.com>
- * decl.c (init_decl_processing): Stop trying to catch signals
+ * 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
@@ -5719,11 +10725,11 @@ Mon Jun 30 14:50:01 1997 Jason Merrill <jason@yorick.cygnus.com>
Fri Jun 27 15:18:49 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck2.c (store_init_value): Always return the value if our
+ * typeck2.c (store_init_value): Always return the value if our
type needs constructing.
* method.c (hack_identifier): Convert class statics from
- reference, too.
+ reference, too.
Thu Jun 26 11:44:46 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5741,7 +10747,7 @@ Thu Jun 19 12:28:43 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
Tue Jun 17 18:35:57 1997 Mike Stump <mrs@cygnus.com>
* except.c (expand_builtin_throw): Add support
- -fno-sjlj-exceptions -fPIC exception handling on the SPARC.
+ -fno-sjlj-exceptions -fPIC exception handling on the SPARC.
Mon Jun 16 01:24:37 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5749,7 +10755,7 @@ Mon Jun 16 01:24:37 1997 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h (TI_SPEC_INFO): New macro.
(CLASSTYPE_TI_SPEC_INFO): New macro.
- * pt.c (push_template_decl): Correctly determine # of template parms
+ * pt.c (push_template_decl): Correctly determine # of template parms
for partial specs.
* call.c (compare_ics): Really fix 'this' conversions.
@@ -5758,20 +10764,20 @@ Mon Jun 16 01:24:37 1997 Jason Merrill <jason@yorick.cygnus.com>
non-template fn.
* pt.c (push_template_decl): Complain about mismatch in # of
- template parms between a class template and a member template.
+ template parms between a class template and a member template.
Sun Jun 15 02:38:20 1997 Jason Merrill <jason@yorick.cygnus.com>
* method.c (synthesize_method): You can't call
- function_cannot_inline_p after finish_function.
+ 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.
+ off DECL_INLINE before handing a synthesized method to the
+ backend.
Thu Jun 12 17:35:28 1997 Jason Merrill <jason@yorick.cygnus.com>
* method.c (synthesize_method): Remove July 30 change to never set
- DECL_INLINE if at_eof.
+ DECL_INLINE if at_eof.
Thu Jun 12 15:25:08 1997 Mike Stump <mrs@cygnus.com>
@@ -5811,22 +10817,22 @@ Tue Jun 10 00:22:09 1997 Jason Merrill <jason@yorick.cygnus.com>
Mon Jun 9 14:25:30 1997 Mike Stump <mrs@cygnus.com>
* Makefile.in, Make-lang.in: Protect C-ls with a comment
- character, idea from Paul Eggert <eggert@twinsun.com>.
+ character, idea from Paul Eggert <eggert@twinsun.com>.
Mon Jun 9 01:52:03 1997 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (c_expand_return): Be more persistent in looking for
- returned temps.
+ returned temps.
* cvt.c (build_up_reference): Use NOP_EXPR for switching from
- pointer to reference.
+ pointer to reference.
* class.c (build_vbase_path): Don't do anything if PATH has no steps.
Sun Jun 8 03:07:05 1997 Jason Merrill <jason@yorick.cygnus.com>
* init.c (build_member_call, build_offset_ref):
- Use do_scoped_id instead of do_identifier.
+ Use do_scoped_id instead of do_identifier.
* cvt.c (convert): Remove bogosity.
@@ -5840,13 +10846,13 @@ Fri Jun 6 17:36:39 1997 Jason Merrill <jason@yorick.cygnus.com>
* cvt.c (build_up_reference): Call get_binfo to get access control.
* decl2.c (import_export_decl): If we don't support weaks, leave
- statics undefined.
+ statics undefined.
Fri Jun 6 15:55:49 1997 Mike Stump <mrs@cygnus.com>
* except.c (expand_builtin_throw): Add support for machines that
- cannot access globals after throw's epilogue when
- -fno-sjlj-exceptions is used.
+ cannot access globals after throw's epilogue when
+ -fno-sjlj-exceptions is used.
Thu Jun 5 16:28:43 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5863,14 +10869,14 @@ Thu Jun 5 16:28:43 1997 Jason Merrill <jason@yorick.cygnus.com>
Tue Jun 3 18:08:23 1997 Jason Merrill <jason@yorick.cygnus.com>
* search.c (push_class_decls): A name which ambiguously refers to
- several instantiations of the same template just refers to the
- template.
+ several instantiations of the same template just refers to the
+ template.
Tue Jun 3 12:30:40 1997 Benjamin Kosnik <bkoz@cirdan.cygnus.com>
- * decl.c (build_enumerator): fix problem with unsigned long
+ * 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
+ when computing next enumerated value (for enum values around
MAX_VAL).
Mon Jun 2 17:40:56 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -6003,7 +11009,7 @@ Wed May 14 19:08:28 1997 Mike Stump <mrs@cygnus.com>
(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>
* pt.c (tsubst_copy): Handle BIT_NOT_EXPR.
@@ -6056,13 +11062,13 @@ Wed Apr 23 18:06:50 1997 Jason Merrill <jason@yorick.cygnus.com>
* 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,
+ * 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.
+ (emit_thunk, generic code): Also set up DECL_LANG_SPECIFIC.
Wed Apr 23 14:43:06 1997 Mike Stump <mrs@cygnus.com>
- * init.c (init_decl_processing): Add supoprt for setjmp/longjmp based
+ * init.c (init_decl_processing): Add support for setjmp/longjmp based
exception handling.
* except.c (init_exception_processing): Likewise.
(expand_end_catch_block): Likewise.
@@ -6080,7 +11086,7 @@ Wed Apr 23 14:43:06 1997 Mike Stump <mrs@cygnus.com>
(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.
* decl.c (maybe_build_cleanup_1): We no longer have to unsave, as
@@ -6088,7 +11094,7 @@ Wed Apr 23 14:43:06 1997 Mike Stump <mrs@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>
* tree.c (varargs_function_p): New fn.
@@ -6154,7 +11160,7 @@ Wed Apr 2 12:51:36 1997 Mike Stump <mrs@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>
* parse.y (left_curly): Avoid trying to use any fields of
@@ -6382,7 +11388,7 @@ Tue Feb 11 13:50:48 1997 Mike Stump <mrs@cygnus.com>
avoid lossing on systems that require one (ones that define malloc
in xm.h).
-Mon Feb 10 22:51:13 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
+Mon Feb 10 22:51:13 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
* decl2.c (max_tinst_depth): New variable.
(lang_decode_option): Parse "-ftemplate-depth-NN" command line
@@ -6551,7 +11557,7 @@ Thu Jan 23 16:39:06 1997 Jason Merrill <jason@yorick.cygnus.com>
Tue Jan 21 18:32:04 1997 Mike Stump <mrs@cygnus.com>
- * cvt.c (cp_convert): Pedwarn enum to pointer conversions.
+ * cvt.c (cp_convert): pedwarn enum to pointer conversions.
Mon Jan 20 17:59:51 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -6675,7 +11681,7 @@ Fri Dec 27 10:31:40 1996 Paul Eggert <eggert@twinsun.com>
* 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).
-Tue Dec 24 10:24:03 1996 Jeffrey A Law (law@cygnus.com)
+Tue Dec 24 10:24:03 1996 Jeffrey A Law <law@cygnus.com>
* decl.c (grokvardecl): Avoid ANSI style initialization.
@@ -6720,7 +11726,7 @@ Sat Dec 7 17:20:22 1996 Jason Merrill <jason@yorick.cygnus.com>
* 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>
* decl.c (grokdeclarator): When giving an anonymous struct a name,
@@ -6866,7 +11872,7 @@ Wed Nov 13 12:32:07 1996 Jason Merrill <jason@yorick.cygnus.com>
Wed Nov 13 11:51:20 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
* g++.c (main): Also set PEXECUTE_SEARCH, to make the invocation
- of GCC be path-relative.
+ of GCC be path-relative.
Wed Nov 13 11:27:16 1996 Michael Meissner <meissner@tiktok.cygnus.com>
@@ -6881,7 +11887,7 @@ Wed Nov 13 07:53:38 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
Wed Nov 13 02:00:26 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (expand_default_init): Avoid calling constructors to
+ * init.c (expand_default_init): Avoid calling constructors to
initialize reference temps.
* cvt.c (convert_to_reference): Fix.
@@ -6974,7 +11980,7 @@ Fri Nov 8 17:38:44 1996 Jason Merrill <jason@yorick.cygnus.com>
* 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
+ * 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.
@@ -7038,7 +12044,7 @@ Thu Oct 31 17:08:49 1996 Jason Merrill <jason@yorick.cygnus.com>
similar code in build_up_ref.
* cvt.c (build_up_reference): Drastically simplify.
-Mon Oct 28 12:45:05 1996 Jeffrey A Law (law@cygnus.com)
+Mon Oct 28 12:45:05 1996 Jeffrey A Law <law@cygnus.com>
* typeck.c (signed_or_unsigned_type): If the given type already
as the correct signedness, then just return it.
@@ -7163,7 +12169,7 @@ Fri Sep 27 16:40:30 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (build_expr_from_tree): Use it.
* cp-tree.h: Declare it.
- * decl.c (start_decl): variable-sized arrays cannot be initialized.
+ * decl.c (start_decl): Variable-sized arrays cannot be initialized.
* error.c (dump_type_suffix): Handle variable arrays.
Fri Sep 27 13:14:05 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
@@ -7187,7 +12193,7 @@ Thu Sep 26 10:59:00 1996 Jason Merrill <jason@yorick.cygnus.com>
calling them.
(get_tinfo_fn_dynamic): Extracted from build_typeid.
* tinfo2.cc (__dynamic_cast): Adjust.
-
+
* rtti.c (build_typeid): Use resolves_to_fixed_type_p.
(build_x_typeid): Likewise.
@@ -7266,7 +12272,7 @@ Sun Sep 22 05:31:22 1996 Jason Merrill <jason@yorick.cygnus.com>
* typeck2.c (store_init_value): Oops.
- * new.{h,cc}, exception.{h,cc}, typeinfo.h, tinfo{2.cc,.cc,.h}:
+ * 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.
@@ -7391,7 +12397,7 @@ Wed Sep 4 17:16:09 1996 Bob Manson <manson@charmed.cygnus.com>
* init.c (perform_member_init): Use add_partial_entry () instead
of directly manipulating lists.
- (emit_base_init): Ditto.
+ (emit_base_init): Likewise.
Wed Sep 4 12:14:36 1996 Mike Stump <mrs@cygnus.com>
@@ -7482,7 +12488,7 @@ Fri Aug 30 10:01:55 1996 Mike Stump <mrs@cygnus.com>
to start_function.
* parse.y (datadef): Remove non-winning optimization.
(decl): Likewise.
- (fndef): Remove ambiguous error productions uncovered by grammer
+ (fndef): Remove ambiguous error productions uncovered by grammar
fixing.
(constructor_declarator): Add exception_specification_opt here.
(component_constructor_declarator): Likewise.
@@ -7512,7 +12518,7 @@ Wed Aug 28 01:40:30 1996 Jason Merrill <jason@yorick.cygnus.com>
* call.c (joust): Extend the previous change to all comparisons.
- * decl2.c, method.c, lex.c: Use MAKE_DECL_ONE_ONLY and
+ * 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.
@@ -7547,7 +12553,7 @@ Tue Aug 27 13:12:21 1996 Jason Merrill <jason@yorick.cygnus.com>
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
+ 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>
@@ -7561,7 +12567,7 @@ Tue Aug 27 10:56:21 1996 Mike Stump <mrs@cygnus.com>
* 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>
* decl2.c (groktypefield): Remove unused code.
@@ -7573,11 +12579,11 @@ Mon Aug 26 17:00:33 1996 Mike Stump <mrs@cygnus.com>
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 (start_function): Only check interface_* for templates
@@ -7594,7 +12600,7 @@ Wed Aug 21 00:13:15 1996 Jason Merrill <jason@yorick.cygnus.com>
* call.c (build_new_method_call): Add missing args to cp_error.
- * tree.c (error_type): Dont print reference-to-array.
+ * tree.c (error_type): Don't print reference-to-array.
* typeck.c (convert_for_assignment): Don't say contravariance for
removing const.
@@ -7810,7 +12816,7 @@ Sun Aug 4 15:29:11 1996 Jason Merrill <jason@yorick.cygnus.com>
(build_conditional_expr): If both operands are TARGET_EXPRs, wrap
the COND_EXPR in a TARGET_EXPR so they use the same slot.
- * cvt.c (build_up_reference): Propagate INDIRECT_BIND to
+ * cvt.c (build_up_reference): Propagate INDIRECT_BIND to
recursive calls.
* typeck.c (complete_type): Propagate
TYPE_NEEDS_{CONSTRUCTING,DESTRUCTOR}.
@@ -7907,7 +12913,7 @@ Thu Aug 1 15:18:00 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
Thu Aug 1 11:53:51 1996 Bob Manson <manson@charmed.cygnus.com>
- * pt.c (instantiate_class_template): Call complete_type. Also, if
+ * 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.
@@ -8063,12 +13069,12 @@ Tue Jul 23 12:46:30 1996 Jason Merrill <jason@yorick.cygnus.com>
* 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
+ ({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.
+ Fall back on preincrement handling. Use op_error.
Handle warn_synth.
- (convert_like): Pass INDIRECT_BIND. Don't try to do anything with
+ (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.
@@ -8087,7 +13093,7 @@ Mon Jul 22 12:18:54 1996 Jason Merrill <jason@yorick.cygnus.com>
* g++.c (main): Don't link with -lg++.
NEW_OVER changes:
- * cvt.c (convert_to_reference): Don't use convert_from_refeence on
+ * cvt.c (convert_to_reference): Don't use convert_from_reference on
result of build_type_conversion.
(cp_convert): Only call build_method_call for ctors if
build_type_conversion failed.
@@ -8095,7 +13101,7 @@ Mon Jul 22 12:18:54 1996 Jason Merrill <jason@yorick.cygnus.com>
(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
+ (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.
@@ -8417,7 +13423,7 @@ Fri Jun 7 10:37:33 1996 Mike Stump <mrs@cygnus.com>
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>
* pt.c (tsubst_expr, case DECL_STMT): Don't pass
@@ -8494,8 +13500,8 @@ Thu May 23 12:13:08 1996 Bob Manson <manson@charmed.cygnus.com>
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
+ 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.
Wed May 22 11:45:19 1996 Bob Manson <manson@charmed.cygnus.com>
@@ -8514,7 +13520,7 @@ Wed May 22 11:45:19 1996 Bob Manson <manson@charmed.cygnus.com>
(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.
@@ -8794,11 +13800,11 @@ Wed Apr 24 15:41:15 1996 Bob Manson <manson@charmed.cygnus.com>
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
+ 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
+ * cp-tree.h: Add new type flagged_type_tree. Add a prototype
for check_for_new_type().
Wed Apr 24 00:36:21 1996 Jason Merrill <jason@yorick.cygnus.com>
@@ -8923,7 +13929,7 @@ Sun Apr 14 11:34:39 1996 Jason Merrill <jason@yorick.cygnus.com>
Fri Apr 12 09:08:27 1996 Bob Manson <manson@charmed.cygnus.com>
* call.c (build_method_call): Remember the original basetype we
- were called with. Give an error message instead of trying
+ were called with. Give an error message instead of trying
(incorrectly) to call a non-static member function through a
non-inherited class.
@@ -9052,7 +14058,7 @@ Sat Apr 6 13:56:27 1996 Jason Merrill <jason@yorick.cygnus.com>
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
+ 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.
@@ -9152,11 +14158,11 @@ Sat Mar 30 12:14:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
Fri Mar 29 15:51:36 1996 Bob Manson <manson@charmed.cygnus.com>
- * class.c (base_info, finish_base_struct): Replace
+ * class.c (base_info, finish_base_struct): Replace
needs_virtual_dtor with base_has_virtual.
(finish_struct_1): Remove the old code that tried to make default
- destructors virtual. Use base_has_virtual when checking if we need
+ destructors virtual. Use base_has_virtual when checking if we need
to add a vtable entry for the rtti code.
Fri Mar 29 14:02:36 1996 Jason Merrill <jason@yorick.cygnus.com>
@@ -9269,7 +14275,7 @@ Fri Mar 22 17:57:55 1996 Mike Stump <mrs@cygnus.com>
Fri Mar 22 13:48:29 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): Call bad_specifiers for typedefs. Also
- give an error if initialized. Pedwarn about nested type with the
+ give an error if initialized. pedwarn about nested type with the
same name as its enclosing class.
* pt.c (tsubst, case TYPE_DECL): Set DECL_CONTEXT.
@@ -9500,7 +14506,7 @@ Wed Mar 13 14:03:34 1996 Jason Merrill <jason@yorick.cygnus.com>
Tue Mar 12 14:36:02 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (build_new): Pedwarn about init and array new.
+ * init.c (build_new): pedwarn about init and array new.
(expand_vec_init): Handle lists, use convert_for_initialization.
* typeck.c (convert_for_initialization): Pass LOOKUP_NO_CONVERSION
@@ -9622,7 +14628,7 @@ Mon Mar 4 20:03:33 1996 Jason Merrill <jason@yorick.cygnus.com>
* 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>
* cvt.c (cp_convert): Warn about implicit conversion of the
@@ -9892,7 +14898,7 @@ Thu Feb 22 15:30:12 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
(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.
+ (repo_get_id, repo_vtable_used): Declare as static.
* cp-tree.h (mark_{decl,class}_instantiated, finish_repo): Add
prototypes.
@@ -9921,7 +14927,7 @@ Thu Feb 22 13:24:15 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
(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.
+ (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.
@@ -10045,7 +15051,7 @@ Thu Feb 22 00:54:22 1996 Jason Merrill <jason@yorick.cygnus.com>
Wed Feb 21 16:57:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * init.c (expand_recursive_init{,_1}): Delete decls.
+ * 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.
@@ -10081,7 +15087,7 @@ Wed Feb 21 16:57:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
* class.c (n_*): Wrap with #ifdef GATHER_STATISTICS.
- * class.c (get_vtable_entry): Diable unused function.
+ * class.c (get_vtable_entry): Disable 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.
@@ -10112,7 +15118,7 @@ Wed Feb 21 16:57:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
(grokparms): Delete unused var SAW_VOID.
(start_function): Delete unused var OLDDECL.
(cplus_expand_expr_stmt): Delete unused var
- REMOVE_IMPLICIT_IMMEDIATELY.
+ REMOVE_IMPLICIT_IMMEDIATELY.
* cp-tree.h (pushdecl_nonclass_level): Fix prototype.
@@ -10127,7 +15133,7 @@ Wed Feb 21 00:06:17 1996 Jason Merrill <jason@yorick.cygnus.com>
(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.
@@ -10744,7 +15750,7 @@ Tue Dec 19 22:36:56 1995 Jason Merrill <jason@yorick.cygnus.com>
Mon Dec 18 15:51:33 1995 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h, decl2.c (flag_weak): New flag to control the use of
- weak symbols.
+ 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.
@@ -10771,7 +15777,7 @@ Thu Dec 14 14:16:26 1995 Mike Stump <mrs@cygnus.com>
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>
+Wed Dec 13 17:05:54 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
@@ -10782,7 +15788,7 @@ Wed Dec 13 17:05:54 PST 1995 Paul Eggert <eggert@twinsun.com>
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.
+ 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.
@@ -10823,7 +15829,7 @@ Mon Dec 11 18:56:14 1995 Mike Stump <mrs@cygnus.com>
* 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
@@ -10862,7 +15868,7 @@ Wed Dec 6 11:48:21 1995 Mike Stump <mrs@cygnus.com>
* 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
+ * 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.
@@ -10956,11 +15962,11 @@ Fri Nov 10 09:18:09 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
Mon Nov 6 18:36:13 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
* call.c (build_method_call): Make sure instance has a
- TYPE_LANG_SPECIFIC node before we dive into it.
+ TYPE_LANG_SPECIFIC node before we dive into it.
Sat Nov 4 20:01:52 1995 Jason Molenda <crash@phydeaux.cygnus.com>
- * method.c (make_thunk): use TREE_SET_CODE to set thunk's tree code.
+ * method.c (make_thunk): Use TREE_SET_CODE to set thunk's tree code.
Thu Nov 2 17:56:57 1995 Mike Stump <mrs@cygnus.com>
@@ -10995,7 +16001,7 @@ Tue Oct 31 11:56:55 1995 Jason Merrill <jason@yorick.cygnus.com>
(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.
diff --git a/contrib/gcc/cp/Make-lang.in b/contrib/gcc/cp/Make-lang.in
index be02cf1..d5d4e4d 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, 1997 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
#This file is part of GNU CC.
@@ -75,43 +75,38 @@ 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
+$(INTL_TARGETS): $(srcdir)/cp/parse.c
+$(srcdir)/cp/parse.c: $(srcdir)/cp/parse.y
+ @cp_srcdir=`sed -n 's/^srcdir[ ]*=[ ]*//p' cp/Makefile` && \
+ echo "cd cp && $(MAKE) $$cp_srcdir/parse.c" && \
+ cd cp && \
+ $(MAKE) $(SUBDIR_FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) \
+ $$cp_srcdir/parse.c
# Create the compiler driver for g++.
-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)
+GXX_OBJS = gcc.o g++spec.o intl.o prefix.o version.o
+g++$(exeext): $(GXX_OBJS) $(EXTRA_GCC_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(GXX_OBJS) $(EXTRA_GCC_OBJS) $(LIBS)
# Create a version of the g++ driver which calls the cross-compiler.
g++-cross$(exeext): g++$(exeext)
-rm -f g++-cross$(exeext)
cp g++$(exeext) g++-cross$(exeext)
-cxxmain.o: cplus-dem.c demangle.h
+cxxmain.o: $(srcdir)/../libiberty/cplus-dem.c $(DEMANGLE_H)
rm -f cxxmain.c
- $(LN_S) $(srcdir)/cplus-dem.c cxxmain.c
+ $(LN_S) $(srcdir)/../libiberty/cplus-dem.c cxxmain.c
$(CC) -c -DMAIN $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DVERSION=\"$(version)\" cxxmain.c
-$(DEMANGLER_PROG): cxxmain.o underscore.o getopt.o getopt1.o $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) $(LIBS) -o $@ \
- cxxmain.o underscore.o getopt.o getopt1.o
+# Apparently OpenVM needs the -o to be at the beginning of the link line.
+$(DEMANGLER_PROG): cxxmain.o underscore.o $(LIBDEPS)
+ $(CC) -o $@ $(ALL_CFLAGS) $(LDFLAGS) \
+ cxxmain.o underscore.o $(LIBS)
CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
$(srcdir)/cp/except.c $(srcdir)/cp/input.c $(srcdir)/cp/pt.c \
@@ -125,7 +120,7 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
$(srcdir)/cp/repo.c $(srcdir)/cp/semantics.c
cc1plus$(exeext): $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \
- $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def
+ $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def hash.o
cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus$(exeext)
#
# Build hooks:
@@ -140,40 +135,40 @@ c++.dvi:
# C++ language-support library pieces for libgcc.
tinfo.o: cc1plus$(exeext) $(srcdir)/cp/tinfo.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/tinfo.cc
tinfo2.o: cc1plus$(exeext) $(srcdir)/cp/tinfo2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/tinfo2.cc
exception.o: cc1plus$(exeext) $(srcdir)/cp/exception.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c -fexceptions $(srcdir)/cp/exception.cc
new.o: cc1plus$(exeext) $(srcdir)/cp/new.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new.cc
opnew.o: cc1plus$(exeext) $(srcdir)/cp/new1.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(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) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(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) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(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) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(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) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(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) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(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) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(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) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(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...
@@ -187,8 +182,11 @@ cplib2.txt: $(CXX_LIB2SRCS) $(CXX_EXTRA_HEADERS) cplib2.ready
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 \
+# Don't try to do write if `.' is not writable;
+# in that case, we're installing from someone else's directory.
+# But go ahead and fail if that directory hasn't been properly built.
+cplib2.ready: $(GCC_PASSES) $(LIBGCC2_DEPS) stmp-int-hdrs
+ @if [ -r cplib2.txt -a -w . ]; then \
case " $(LANGUAGES) " in \
*" "[cC]"++ "*) \
echo $(CXX_LIB2FUNCS) > cplib2.new;; \
@@ -246,13 +244,13 @@ c++.install-info:
c++.install-man: $(srcdir)/cp/g++.1
-if [ -f cc1plus$(exeext) ] ; then \
if [ -f g++-cross$(exeext) ] ; then \
- rm -f $(mandir)/$(GXX_CROSS_NAME)$(manext); \
- $(INSTALL_DATA) $(srcdir)/cp/g++.1 $(mandir)/$(GXX_CROSS_NAME)$(manext); \
- chmod a-x $(mandir)/$(GXX_CROSS_NAME)$(manext); \
+ rm -f $(man1dir)/$(GXX_CROSS_NAME)$(manext); \
+ $(INSTALL_DATA) $(srcdir)/cp/g++.1 $(man1dir)/$(GXX_CROSS_NAME)$(manext); \
+ chmod a-x $(man1dir)/$(GXX_CROSS_NAME)$(manext); \
else \
- rm -f $(mandir)/$(GXX_INSTALL_NAME)$(manext); \
- $(INSTALL_DATA) $(srcdir)/cp/g++.1 $(mandir)/$(GXX_INSTALL_NAME)$(manext); \
- chmod a-x $(mandir)/$(GXX_INSTALL_NAME)$(manext); \
+ rm -f $(man1dir)/$(GXX_INSTALL_NAME)$(manext); \
+ $(INSTALL_DATA) $(srcdir)/cp/g++.1 $(man1dir)/$(GXX_INSTALL_NAME)$(manext); \
+ chmod a-x $(man1dir)/$(GXX_INSTALL_NAME)$(manext); \
fi; \
else true; fi
@@ -263,8 +261,8 @@ c++.uninstall:
-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)
+ -rm -rf $(man1dir)/$(GXX_INSTALL_NAME)$(manext)
+ -rm -rf $(man1dir)/$(GXX_CROSS_NAME)$(manext)
#
# Clean hooks:
# A lot of the ancillary files are deleted by the main makefile.
@@ -277,7 +275,6 @@ c++.clean:
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
diff --git a/contrib/gcc/cp/Makefile.in b/contrib/gcc/cp/Makefile.in
index 8d7098d..1a5b32c 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-5, 1998 Free Software Foundation, Inc.
+# Copyright (C) 1987, 88, 90-5, 1998, 1999 Free Software Foundation, Inc.
#This file is part of GNU CC.
@@ -34,6 +34,10 @@
# Suppress smart makes who think they know how to automake Yacc files
.y.c:
+# It defines the c++ interface name. It should be changed when the
+# c++ interface is changed.
+INTERFACE = 2
+
# Variables that exist for you to override.
# See below for how to change them for certain systems.
@@ -55,7 +59,7 @@ X_CPPFLAGS =
T_CPPFLAGS =
CC = @CC@
-BBISON = `if [ -f ../../bison/bison ] ; then echo ../../bison/bison -L $(srcdir)/../../bison/ ; else echo bison ; fi`
+BISON = `if [ -f ../../bison/bison ] ; then echo ../../bison/bison -L $(srcdir)/../../bison/ ; else echo bison ; fi`
BISONFLAGS =
LEX = `if [ -f ../../flex/flex ] ; then echo ../../flex/flex ; else echo flex ; fi`
LEXFLAGS =
@@ -101,6 +105,12 @@ VPATH = @srcdir@
# Additional system libraries to link with.
CLIB=
+
+# Top build directory, relative to here.
+top_builddir = ..
+
+# Internationalization library.
+INTLLIBS = @INTLLIBS@
# Change this to a null string if obstacks are installed in the
# system library.
@@ -150,13 +160,14 @@ SUBDIR_MALLOC = `if [ x$(MALLOC) != x ]; then echo ../$(MALLOC); else true; fi`
# How to link with both our special library facilities
# and the system's installed libraries.
-LIBS = $(SUBDIR_OBSTACK) $(SUBDIR_USE_ALLOCA) $(SUBDIR_MALLOC) $(CLIB)
+LIBS = $(SUBDIR_OBSTACK) $(SUBDIR_USE_ALLOCA) $(SUBDIR_MALLOC) \
+ $(INTLLIBS) $(CLIB)
# Specify the directories to be searched for header files.
# Both . and srcdir are used, in that order,
# so that tm.h and config.h will be found in the compilation
# subdirectory rather than in the source directory.
-INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
+INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config -I$(srcdir)/../../include
# Always use -I$(srcdir)/config when compiling.
.c.o:
@@ -184,9 +195,8 @@ OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o
compiler: ../cc1plus$(exeext)
-../cc1plus$(exeext): $(P) $(CXX_OBJS) $(OBJDEPS) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
- $(CXX_OBJS) $(OBJS) $(LIBS)
+../cc1plus$(exeext): $(P) $(OBJDEPS) $(CXX_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(CXX_OBJS) $(LIBS)
Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure
cd ..; $(SHELL) config.status
@@ -215,7 +225,7 @@ parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h \
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(PARSE_C) | sed 's,^\./,,'`
-CONFLICTS = expect 26 shift/reduce conflicts and 42 reduce/reduce conflicts.
+CONFLICTS = expect 30 shift/reduce conflicts and 42 reduce/reduce conflicts.
$(PARSE_H) : $(PARSE_C)
$(PARSE_C) : $(srcdir)/parse.y
@echo $(CONFLICTS)
@@ -231,33 +241,35 @@ $(PARSE_C) : $(srcdir)/parse.y
# cp $(PARSE_C) y.tab.c
# touch stamp-parse
-# hash.h really depends on $(srcdir)/gxx.gperf.
-# But this would screw things for people that don't have gperf,
-# if gxx.gpref got touched, say.
-# Thus you have to remove hash.h to force it to be re-made.
-$(srcdir)/hash.h:
- gperf -p -j1 -g -o -t -N is_reserved_word '-k1,4,7,$$' \
- $(srcdir)/gxx.gperf >$(srcdir)/hash.h
+# We used to try to protect people from having to rerun gperf. But,
+# the C front-end already requires this if c-parse.gperf is changed,
+# so we should be consistent.
+$(srcdir)/hash.h: $(srcdir)/gxx.gperf
+ gperf -L C -F ', 0, 0' -p -j1 -g -o -t -N is_reserved_word \
+ '-k1,4,7,$$' $(srcdir)/gxx.gperf >$(srcdir)/hash.h
-spew.o : spew.c $(CONFIG_H) $(CXX_TREE_H) \
- $(PARSE_H) $(srcdir)/../flags.h lex.h $(srcdir)/../system.h
+spew.o : spew.c $(CONFIG_H) $(CXX_TREE_H) $(PARSE_H) $(srcdir)/../flags.h \
+ lex.h $(srcdir)/../system.h $(srcdir)/../toplev.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 $(srcdir)/../system.h $(srcdir)/../toplev.h \
- $(srcdir)/../output.h
+ $(srcdir)/../output.h $(srcdir)/../mbchar.h
decl.o : decl.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
lex.h decl.h $(srcdir)/../stack.h $(srcdir)/../output.h \
- $(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h
+ $(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h \
+ $(srcdir)/../hash.h
decl2.o : decl2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.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
+ $(srcdir)/../toplev.h $(srcdir)/../dwarf2out.h $(srcdir)/../dwarfout.h \
+ $(srcdir)/../../include/splay-tree.h $(srcdir)/../varray.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
+ $(srcdir)/../system.h $(srcdir)/../toplev.h \
+ $(srcdir)/../../include/splay-tree.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) \
@@ -266,9 +278,11 @@ 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
+cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h decl.h \
+ $(srcdir)/../flags.h $(srcdir)/../toplev.h $(srcdir)/../convert.h
search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h \
- $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h
+ $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h \
+ $(srcdir)/../varray.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
@@ -308,32 +322,3 @@ 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
index 9cb7d5b..1a242ab 100644
--- a/contrib/gcc/cp/NEWS
+++ b/contrib/gcc/cp/NEWS
@@ -1,3 +1,39 @@
+*** Changes in GCC 2.95:
+
+* Messages about non-conformant code that we can still handle ("pedwarns")
+ are now errors by default, rather than warnings. This can be reverted
+ with -fpermissive, and is overridden by -pedantic or -pedantic-errors.
+
+* String constants are now of type `const char[n]', rather than `char[n]'.
+ This can be reverted with -fno-const-strings.
+
+* References to functions are now supported.
+
+* Lookup of class members during class definition now works in all cases.
+
+* In overload resolution, type conversion operators are now properly
+ treated as always coming from the most derived class.
+
+* C9x-style restricted pointers are supported, using the `__restrict'
+ keyword.
+
+* You can now use -fno-implicit-inline-templates to suppress writing out
+ implicit instantiations of inline templates. Normally we do write them
+ out, even with -fno-implicit-templates, so that optimization doesn't
+ affect which instantiations are needed.
+
+* -fstrict-prototype now also suppresses implicit declarations.
+
+* Many obsolete options have been removed: -fall-virtual, -fmemoize-lookups,
+ -fsave-memoized, +e?, -fenum-int-equivalence, -fno-nonnull-objects.
+
+* Unused virtual functions can be discarded on some targets by specifying
+ -ffunction-sections -fvtable-gc to the compiler and --gc-sections to the
+ linker. Unfortunately, this only works on Linux if you're linking
+ statically.
+
+* Lots of bugs stomped.
+
*** Changes in EGCS 1.1:
* Namespaces are fully supported. The library has not yet been converted
diff --git a/contrib/gcc/cp/call.c b/contrib/gcc/cp/call.c
index e65898e..094a345 100644
--- a/contrib/gcc/cp/call.c
+++ b/contrib/gcc/cp/call.c
@@ -1,5 +1,5 @@
/* Functions related to invoking methods and overloaded functions.
- Copyright (C) 1987, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com).
@@ -49,7 +49,7 @@ 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 *));
+ tree, const char *));
static tree build_object_call PROTO((tree, tree));
static tree resolve_args PROTO((tree));
static struct z_candidate * build_user_type_conversion_1
@@ -87,22 +87,22 @@ 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*));
+static struct z_candidate * add_candidate PROTO((struct z_candidate *,
+ tree, tree, int));
+static tree source_type PROTO((tree));
+static void add_warning PROTO((struct z_candidate *, struct z_candidate *));
tree
build_vfield_ref (datum, type)
tree datum, type;
{
tree rval;
- int old_assume_nonnull_objects = flag_assume_nonnull_objects;
if (datum == error_mark_node)
return error_mark_node;
- /* Vtable references are always made from non-null objects. */
- flag_assume_nonnull_objects = 1;
if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
datum = convert_from_reference (datum);
@@ -111,7 +111,6 @@ build_vfield_ref (datum, type)
datum, CLASSTYPE_VFIELD (type));
else
rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), NULL_TREE, 0);
- flag_assume_nonnull_objects = old_assume_nonnull_objects;
return rval;
}
@@ -128,91 +127,40 @@ build_field_call (basetype_path, instance_ptr, name, parms)
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. */
- field = IDENTIFIER_CLASS_VALUE (name);
-
- if (field == NULL_TREE)
- {
- cp_error ("`this' has no member named `%D'", name);
- return error_mark_node;
- }
-
- if (TREE_CODE (field) == FIELD_DECL)
- {
- /* If it's a field, try overloading operator (),
- or calling if the field is a pointer-to-function. */
- 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)))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms, NULL_TREE);
-
- if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
- {
- 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, expr_tree_cons (NULL_TREE, current_class_ptr, parms));
- }
- }
- return NULL_TREE;
- }
+ /* Speed up the common case. */
+ if (instance_ptr == current_class_ptr
+ && IDENTIFIER_CLASS_VALUE (name) == NULL_TREE)
+ return NULL_TREE;
- /* Check to see if this is not really a reference to an instance variable
- with `operator()()' overloaded. */
field = lookup_field (basetype_path, name, 1, 0);
- /* This can happen if the reference was ambiguous or for access
- violations. */
- if (field == error_mark_node)
- return error_mark_node;
+ if (field == error_mark_node || field == NULL_TREE)
+ return field;
- if (field && TREE_CODE (field) == FIELD_DECL)
+ if (TREE_CODE (field) == FIELD_DECL || TREE_CODE (field) == VAR_DECL)
{
- tree basetype;
- tree ftype = TREE_TYPE (field);
+ /* If it's a field, try overloading operator (),
+ or calling if the field is a pointer-to-function. */
+ instance = build_indirect_ref (instance_ptr, NULL_PTR);
+ instance = build_component_ref_1 (instance, field, 0);
- if (TREE_CODE (ftype) == REFERENCE_TYPE)
- ftype = TREE_TYPE (ftype);
+ if (instance == error_mark_node)
+ return error_mark_node;
- if (TYPE_LANG_SPECIFIC (ftype))
+ if (IS_AGGR_TYPE (TREE_TYPE (instance)))
+ return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
+ instance, parms, NULL_TREE);
+ else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
{
- /* Make the next search for this field very short. */
- basetype = DECL_FIELD_CONTEXT (field);
- instance_ptr = convert_pointer_to (basetype, instance_ptr);
-
- instance = build_indirect_ref (instance_ptr, NULL_PTR);
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
- build_component_ref_1 (instance, field, 0),
- parms, NULL_TREE);
+ 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, expr_tree_cons (NULL_TREE, instance_ptr, parms));
}
- if (TREE_CODE (ftype) == POINTER_TYPE)
- {
- if (TREE_CODE (TREE_TYPE (ftype)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (ftype)) == METHOD_TYPE)
- {
- /* This is a member which is a pointer to function. */
- tree ref
- = build_component_ref_1 (build_indirect_ref (instance_ptr,
- NULL_PTR),
- field, LOOKUP_COMPLAIN);
- if (ref == error_mark_node)
- return error_mark_node;
- return build_function_call (ref, parms);
- }
- }
- else if (TREE_CODE (ftype) == METHOD_TYPE)
- {
- error ("invalid call via pointer-to-member function");
- return error_mark_node;
- }
- else
- return NULL_TREE;
}
+
return NULL_TREE;
}
@@ -350,6 +298,10 @@ check_dtor_name (basetype, name)
{
name = TREE_OPERAND (name, 0);
+ /* Just accept something we've already complained about. */
+ if (name == error_mark_node)
+ return 1;
+
if (TREE_CODE (name) == TYPE_DECL)
name = TREE_TYPE (name);
else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
@@ -551,6 +503,9 @@ build_call (function, result_type, parms)
if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1;
+ if (decl)
+ my_friendly_assert (TREE_USED (decl), 990125);
+
/* 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. */
@@ -628,10 +583,15 @@ build_method_call (instance, name, parms, basetype_path, flags)
{
/* 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)
+ if (TREE_CODE (name) == BIT_NOT_EXPR)
{
- tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
+ tree type = NULL_TREE;
+
+ if (TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
+ type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
+ else if (TREE_CODE (TREE_OPERAND (name, 0)) == TYPE_DECL)
+ type = TREE_TYPE (TREE_OPERAND (name, 0));
+
if (type && TREE_CODE (type) == TEMPLATE_TYPE_PARM)
name = build_min_nt (BIT_NOT_EXPR, type);
}
@@ -639,29 +599,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
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. */
- if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2)
- {
- tree save_last = TREE_CHAIN (parms);
-
- /* get rid of unneeded argument */
- TREE_CHAIN (parms) = NULL_TREE;
- 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)
{
if (parms)
@@ -806,6 +743,15 @@ standard_conversion (to, from, expr)
to = strip_top_quals (to);
from = strip_top_quals (from);
+ if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to))
+ && expr && type_unknown_p (expr))
+ {
+ expr = instantiate_type (to, expr, 0);
+ if (expr == error_mark_node)
+ return NULL_TREE;
+ from = TREE_TYPE (expr);
+ }
+
fcode = TREE_CODE (from);
tcode = TREE_CODE (to);
@@ -839,16 +785,15 @@ standard_conversion (to, from, expr)
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))
+ if (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (from)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (to))))
;
else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE
&& ufcode != FUNCTION_TYPE)
{
from = build_pointer_type
- (cp_build_type_variant (void_type_node,
- TYPE_READONLY (TREE_TYPE (from)),
- TYPE_VOLATILE (TREE_TYPE (from))));
+ (cp_build_qualified_type (void_type_node,
+ CP_TYPE_QUALS (TREE_TYPE (from))));
conv = build_conv (PTR_CONV, from, conv);
}
else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
@@ -857,9 +802,9 @@ standard_conversion (to, from, expr)
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)))
+ && (same_type_p
+ (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))),
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to))))))
{
from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
from = build_pointer_type (from);
@@ -871,18 +816,21 @@ standard_conversion (to, from, expr)
{
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 =
+ cp_build_qualified_type (TREE_TYPE (to),
+ CP_TYPE_QUALS (TREE_TYPE (from)));
from = build_pointer_type (from);
conv = build_conv (PTR_CONV, from, conv);
}
}
- if (comptypes (from, to, 1))
+ if (same_type_p (from, to))
/* OK */;
else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from)))
conv = build_conv (QUAL_CONV, to, conv);
+ else if (expr && string_conv_p (to, expr, 0))
+ /* converting from string constant to char *. */
+ conv = build_conv (QUAL_CONV, to, conv);
else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from)))
{
conv = build_conv (PTR_CONV, to, conv);
@@ -901,15 +849,13 @@ standard_conversion (to, from, expr)
tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn)));
if (! DERIVED_FROM_P (fbase, tbase)
- || ! comptypes (TREE_TYPE (fromfn), TREE_TYPE (tofn), 1)
+ || ! same_type_p (TREE_TYPE (fromfn), TREE_TYPE (tofn))
|| ! 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))
+ TREE_CHAIN (TYPE_ARG_TYPES (tofn)))
+ || CP_TYPE_QUALS (fbase) != CP_TYPE_QUALS (tbase))
return 0;
- from = cp_build_type_variant (tbase, TYPE_READONLY (fbase),
- TYPE_VOLATILE (fbase));
+ from = cp_build_qualified_type (tbase, CP_TYPE_QUALS (fbase));
from = build_cplus_method_type (from, TREE_TYPE (fromfn),
TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
from = build_ptrmemfunc_type (build_pointer_type (from));
@@ -971,24 +917,30 @@ reference_binding (rto, rfrom, expr, flags)
tree from = rfrom;
int related;
+ if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
+ {
+ expr = instantiate_type (to, expr, 0);
+ if (expr == error_mark_node)
+ return NULL_TREE;
+ from = TREE_TYPE (expr);
+ }
+
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)
+ related = (same_type_p (TYPE_MAIN_VARIANT (to),
+ TYPE_MAIN_VARIANT (from))
|| (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))
+ if (lvalue && related && at_least_as_qualified_p (to, from))
{
conv = build1 (IDENTITY_CONV, from, expr);
- if (comptypes (TYPE_MAIN_VARIANT (to),
- TYPE_MAIN_VARIANT (from), 1))
+ if (same_type_p (TYPE_MAIN_VARIANT (to),
+ TYPE_MAIN_VARIANT (from)))
conv = build_conv (REF_BIND, rto, conv);
else
{
@@ -1012,14 +964,12 @@ reference_binding (rto, rfrom, expr, flags)
TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0);
}
if (conv
- && ((! (TYPE_READONLY (to) && ! TYPE_VOLATILE (to)
+ && ((! (CP_TYPE_CONST_NON_VOLATILE_P (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)))))
+ || (related && !at_least_as_qualified_p (to, from))))
ICS_BAD_FLAG (conv) = 1;
}
@@ -1039,14 +989,6 @@ implicit_conversion (to, from, expr, 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
@@ -1056,7 +998,7 @@ implicit_conversion (to, from, expr, flags)
;
else if (expr != NULL_TREE
&& (IS_AGGR_TYPE (non_reference (from))
- || IS_AGGR_TYPE (non_reference (to)))
+ || IS_AGGR_TYPE (non_reference (to)))
&& (flags & LOOKUP_NO_CONVERSION) == 0)
{
cand = build_user_type_conversion_1
@@ -1071,8 +1013,7 @@ implicit_conversion (to, from, expr, flags)
(TYPE_MAIN_VARIANT (TREE_TYPE (to)), expr, LOOKUP_ONLYCONVERTING);
if (cand)
{
- if (! TYPE_READONLY (TREE_TYPE (to))
- || TYPE_VOLATILE (TREE_TYPE (to)))
+ if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (to)))
ICS_BAD_FLAG (cand->second_conv) = 1;
if (!conv || (ICS_BAD_FLAG (conv)
> ICS_BAD_FLAG (cand->second_conv)))
@@ -1121,42 +1062,92 @@ add_function_candidate (candidates, fn, arglist, flags)
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
int i, len;
tree convs;
- tree parmnode = parmlist;
- tree argnode = arglist;
+ tree parmnode, argnode;
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);
+ parmlist = TREE_CHAIN (parmlist);
+ arglist = TREE_CHAIN (arglist);
if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
{
- parmnode = TREE_CHAIN (parmnode);
- argnode = TREE_CHAIN (argnode);
+ parmlist = TREE_CHAIN (parmlist);
+ arglist = TREE_CHAIN (arglist);
}
}
- len = list_length (argnode);
+ len = list_length (arglist);
convs = make_scratch_vec (len);
+ /* 13.3.2 - Viable functions [over.match.viable]
+ First, to be a viable function, a candidate function shall have enough
+ parameters to agree in number with the arguments in the list.
+
+ We need to check this first; otherwise, checking the ICSes might cause
+ us to produce an ill-formed template instantiation. */
+
+ parmnode = parmlist;
+ for (i = 0; i < len; ++i)
+ {
+ if (parmnode == NULL_TREE || parmnode == void_list_node)
+ break;
+ parmnode = TREE_CHAIN (parmnode);
+ }
+
+ if (i < len && parmnode)
+ viable = 0;
+
+ /* Make sure there are default args for the rest of the parms. */
+ else for (; parmnode && parmnode != void_list_node;
+ parmnode = TREE_CHAIN (parmnode))
+ if (! TREE_PURPOSE (parmnode))
+ {
+ viable = 0;
+ break;
+ }
+
+ if (! viable)
+ goto out;
+
+ /* Second, for F to be a viable function, there shall exist for each
+ argument an implicit conversion sequence that converts that argument
+ to the corresponding parameter of F. */
+
+ parmnode = parmlist;
+ argnode = arglist;
+
for (i = 0; i < len; ++i)
{
tree arg = TREE_VALUE (argnode);
- tree argtype = TREE_TYPE (arg);
+ tree argtype = lvalue_type (arg);
tree t;
- /* 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 (parmnode == void_list_node)
break;
- else if (parmnode)
- t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags);
+
+ if (parmnode)
+ {
+ tree parmtype = TREE_VALUE (parmnode);
+
+ /* [over.match.funcs] For conversion functions, the function is
+ considered to be a member of the class of the implicit object
+ argument for the purpose of defining the type of the implicit
+ object parameter.
+
+ Since build_over_call ignores the ICS for the `this' parameter,
+ we can just change the parm type. */
+ if (DECL_CONV_FN_P (fn) && i == 0)
+ {
+ parmtype
+ = build_qualified_type (TREE_TYPE (argtype),
+ TYPE_QUALS (TREE_TYPE (parmtype)));
+ parmtype = build_pointer_type (parmtype);
+ }
+
+ t = implicit_conversion (parmtype, argtype, arg, flags);
+ }
else
{
t = build1 (IDENTITY_CONV, argtype, arg);
@@ -1169,7 +1160,10 @@ add_function_candidate (candidates, fn, arglist, flags)
TREE_VEC_ELT (convs, i) = t;
if (! t)
- break;
+ {
+ viable = 0;
+ break;
+ }
if (ICS_BAD_FLAG (t))
viable = -1;
@@ -1179,25 +1173,20 @@ add_function_candidate (candidates, fn, arglist, flags)
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;
- }
-
+ out:
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. */
+ CANDIDATES. FLAGS is passed on to implicit_conversion.
+
+ Actually, we don't really care about FN; we care about the type it
+ converts to. There may be multiple conversion functions that will
+ convert to that type, and we rely on build_user_type_conversion_1 to
+ choose the best one; so when we create our candidate, we record the type
+ instead of the function. */
static struct z_candidate *
add_conv_candidate (candidates, fn, obj, arglist)
@@ -1213,6 +1202,10 @@ add_conv_candidate (candidates, fn, obj, arglist)
int viable = 1;
int flags = LOOKUP_NORMAL;
+ /* Don't bother looking up the same type twice. */
+ if (candidates && candidates->fn == totype)
+ return candidates;
+
for (i = 0; i < len; ++i)
{
tree arg = i == 0 ? obj : TREE_VALUE (argnode);
@@ -1257,7 +1250,7 @@ add_conv_candidate (candidates, fn, obj, arglist)
break;
}
- return add_candidate (candidates, fn, convs, viable);
+ return add_candidate (candidates, totype, convs, viable);
}
static struct z_candidate *
@@ -1803,7 +1796,7 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
;
else if (IS_AGGR_TYPE (argtypes[i]))
{
- tree convs = lookup_conversions (argtypes[i]);
+ tree convs;
if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
return candidates;
@@ -1825,11 +1818,11 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
for (; convs; convs = TREE_CHAIN (convs))
{
- type = TREE_TYPE (TREE_TYPE (TREE_VALUE (convs)));
+ type = TREE_TYPE (TREE_TYPE (OVL_CURRENT (TREE_VALUE (convs))));
if (i == 0 && ref1
&& (TREE_CODE (type) != REFERENCE_TYPE
- || TYPE_READONLY (TREE_TYPE (type))))
+ || CP_TYPE_CONST_P (TREE_TYPE (type))))
continue;
if (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE)
@@ -1911,7 +1904,7 @@ add_template_candidate_real (candidates, tmpl, explicit_targs,
tree fn;
i = fn_type_unification (tmpl, explicit_targs, targs, arglist,
- return_type, strict, NULL_TREE);
+ return_type, strict);
if (i != 0)
return candidates;
@@ -2020,7 +2013,7 @@ static void
print_z_candidates (candidates)
struct z_candidate *candidates;
{
- char *str = "candidates are:";
+ const char *str = "candidates are:";
for (; candidates; candidates = candidates->next)
{
if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
@@ -2038,8 +2031,10 @@ print_z_candidates (candidates)
cp_error ("%s %D(%T) <builtin>", str, candidates->fn,
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
}
+ else if (TYPE_P (candidates->fn))
+ cp_error ("%s %T <conversion>", str, candidates->fn);
else
- cp_error_at ("%s %+D%s", str, candidates->fn,
+ cp_error_at ("%s %+#D%s", str, candidates->fn,
candidates->viable == -1 ? " <near match>" : "");
str = " ";
}
@@ -2123,7 +2118,7 @@ build_user_type_conversion_1 (totype, expr, flags)
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
- if (TREE_CODE (fns) != TEMPLATE_DECL)
+ if (TREE_CODE (OVL_CURRENT (fns)) != TEMPLATE_DECL)
ics = implicit_conversion
(totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags);
else
@@ -2293,6 +2288,8 @@ build_new_function_call (fn, args)
for (t1 = fn; t1; t1 = OVL_CHAIN (t1))
{
tree t = OVL_FUNCTION (t1);
+ struct z_candidate *old_candidates = candidates;
+
if (TREE_CODE (t) == TEMPLATE_DECL)
{
templates = scratch_tree_cons (NULL_TREE, t, templates);
@@ -2303,6 +2300,9 @@ build_new_function_call (fn, args)
else if (! template_only)
candidates = add_function_candidate
(candidates, t, args, LOOKUP_NORMAL);
+
+ if (candidates != old_candidates)
+ candidates->basetype_path = DECL_REAL_CONTEXT (t);
}
if (! any_viable (candidates))
@@ -2349,7 +2349,6 @@ build_object_call (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))
{
@@ -2379,7 +2378,6 @@ build_object_call (obj, args)
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,
mem_args, NULL_TREE,
@@ -2400,16 +2398,15 @@ build_object_call (obj, args)
{
tree fns = TREE_VALUE (convs);
tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
- tree fn;
- if (TREE_CODE (totype) == POINTER_TYPE
+ if ((TREE_CODE (totype) == POINTER_TYPE
+ || TREE_CODE (totype) == REFERENCE_TYPE)
&& TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
- for (; fns; fns = OVL_NEXT (fn))
+ for (; fns; fns = OVL_NEXT (fns))
{
- fn = OVL_CURRENT (fn);
+ tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
- templates = scratch_tree_cons (NULL_TREE, fn, templates);
candidates = add_template_conv_candidate (candidates,
fn,
obj,
@@ -2441,7 +2438,11 @@ build_object_call (obj, args)
return error_mark_node;
}
- if (DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR])
+ /* Since cand->fn will be a type, not a function, for a conversion
+ function, we must be careful not to unconditionally look at
+ DECL_NAME here. */
+ if (TREE_CODE (cand->fn) == FUNCTION_DECL
+ && DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR])
return build_over_call (cand, mem_args, LOOKUP_NORMAL);
obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj);
@@ -2454,9 +2455,9 @@ static void
op_error (code, code2, arg1, arg2, arg3, problem)
enum tree_code code, code2;
tree arg1, arg2, arg3;
- char *problem;
+ const char *problem;
{
- char * opname
+ const char * opname
= (code == MODIFY_EXPR ? assignop_tab [code2] : opname_tab [code]);
switch (code)
@@ -2520,73 +2521,10 @@ build_new_op (code, flags, arg1, arg2, arg3)
{
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
- /* 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;
- }
+ /* Use build_op_new_call and build_op_delete_call instead. */
+ my_friendly_abort (981018);
case CALL_EXPR:
return build_object_call (arg1, arg2);
@@ -2798,8 +2736,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
case LE_EXPR:
case EQ_EXPR:
case NE_EXPR:
- if (flag_int_enum_equivalence == 0
- && TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE
+ if (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))))
@@ -2820,9 +2757,19 @@ build_new_op (code, flags, arg1, arg2, arg3)
conv = TREE_OPERAND (conv, 0);
arg1 = convert_like (conv, arg1);
if (arg2)
- arg2 = convert_like (TREE_VEC_ELT (cand->convs, 1), arg2);
+ {
+ conv = TREE_VEC_ELT (cand->convs, 1);
+ if (TREE_CODE (conv) == REF_BIND)
+ conv = TREE_OPERAND (conv, 0);
+ arg2 = convert_like (conv, arg2);
+ }
if (arg3)
- arg3 = convert_like (TREE_VEC_ELT (cand->convs, 2), arg3);
+ {
+ conv = TREE_VEC_ELT (cand->convs, 2);
+ if (TREE_CODE (conv) == REF_BIND)
+ conv = TREE_OPERAND (conv, 0);
+ arg3 = convert_like (conv, arg3);
+ }
builtin:
switch (code)
@@ -2906,10 +2853,8 @@ build_op_new_call (code, type, args, flags)
if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)
&& (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR))))
{
- 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);
+ return build_method_call (build_dummy_object (type),
+ fnname, args, NULL_TREE, flags);
}
else
return build_new_function_call
@@ -2988,12 +2933,7 @@ build_op_delete_call (code, addr, size, flags, placement)
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);
+ fn = instantiate_type (fntype, fns, 2);
if (fn != error_mark_node)
{
@@ -3013,11 +2953,11 @@ build_op_delete_call (code, addr, size, flags, placement)
tree_cons (NULL_TREE, sizetype, void_list_node));
fntype = build_function_type (void_type_node, argtypes);
- fn = instantiate_type (fntype, fns, 0);
+ fn = instantiate_type (fntype, fns, 2);
if (fn != error_mark_node)
{
- if (TREE_CODE (fns) == TREE_LIST)
+ if (BASELINK_P (fns))
/* Member functions. */
enforce_access (TREE_PURPOSE (fns), fn);
return build_function_call
@@ -3036,28 +2976,30 @@ build_op_delete_call (code, addr, size, flags, placement)
}
/* If the current scope isn't allowed to access DECL along
- BASETYPE_PATH, give an error. */
+ BASETYPE_PATH, give an error. The most derived class in
+ BASETYPE_PATH is the one used to qualify DECL. */
-void
+int
enforce_access (basetype_path, decl)
- tree basetype_path, decl;
+ tree basetype_path;
+ tree decl;
{
- tree access = compute_access (basetype_path, decl);
+ int accessible;
- 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)
+ accessible = accessible_p (basetype_path, decl);
+ if (!accessible)
{
- cp_error_at ("`%+#D' %s", decl,
- TREE_PROTECTED (decl) ? "is protected"
- : "has protected accessibility");
- error ("within this context");
+ if (TREE_PRIVATE (decl))
+ cp_error_at ("`%+#D' is private", decl);
+ else if (TREE_PROTECTED (decl))
+ cp_error_at ("`%+#D' is protected", decl);
+ else
+ cp_error_at ("`%+#D' is inaccessible", decl);
+ cp_error ("within this context");
+ return 0;
}
+
+ return 1;
}
/* Perform the conversions in CONVS on the expression EXPR. */
@@ -3156,7 +3098,7 @@ convert_like (convs, expr)
destination type takes a pointer argument. */
if (TYPE_SIZE (TREE_TYPE (expr)) == 0)
{
- if (comptypes (TREE_TYPE (expr), TREE_TYPE (convs), 1))
+ if (same_type_p (TREE_TYPE (expr), TREE_TYPE (convs)))
incomplete_type_error (expr, TREE_TYPE (expr));
else
cp_error ("could not convert `%E' (with incomplete type `%T') to `%T'",
@@ -3178,6 +3120,11 @@ convert_like (convs, expr)
case LVALUE_CONV:
return decay_conversion (expr);
+ case QUAL_CONV:
+ /* Warn about deprecated conversion if appropriate. */
+ string_conv_p (TREE_TYPE (convs), expr, 1);
+ break;
+
default:
break;
}
@@ -3205,17 +3152,47 @@ convert_arg_to_ellipsis (arg)
/* Convert `short' and `char' to full-size `int'. */
arg = default_conversion (arg);
+ arg = require_complete_type (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. */
+ the indicated TYPE, which is a parameter to FN. Do any required
+ conversions. Return the converted value. */
tree
-convert_default_arg (type, arg)
- tree type, arg;
+convert_default_arg (type, arg, fn)
+ tree type;
+ tree arg;
+ tree fn;
{
+ if (fn && DECL_TEMPLATE_INFO (fn))
+ {
+ /* This default argument came from a template. Instantiate the
+ default argument here, not in tsubst. In the case of
+ something like:
+
+ template <class T>
+ struct S {
+ static T t();
+ void f(T = t());
+ };
+
+ we must be careful to do name lookup in the scope of S<T>,
+ rather than in the current class. */
+ if (DECL_CLASS_SCOPE_P (fn))
+ pushclass (DECL_REAL_CONTEXT (fn), 2);
+
+ arg = tsubst_expr (arg, DECL_TI_ARGS (fn), /*complain=*/1, NULL_TREE);
+
+ if (DECL_CLASS_SCOPE_P (fn))
+ popclass ();
+
+ /* Make sure the default argument is reasonable. */
+ arg = check_default_argument (type, arg);
+ }
+
arg = break_out_target_exprs (arg);
if (TREE_CODE (arg) == CONSTRUCTOR)
@@ -3289,21 +3266,23 @@ build_over_call (cand, args, flags)
{
tree parmtype = TREE_VALUE (parm);
tree argtype = TREE_TYPE (TREE_VALUE (arg));
+ tree t;
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);
+ cp_pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
+ TREE_TYPE (argtype), fn);
+
+ /* [class.mfct.nonstatic]: If a nonstatic member function of a class
+ X is called for an object that is not of type X, or of a type
+ derived from X, the behavior is undefined.
+
+ So we can assume that anything passed as 'this' is non-null, and
+ optimize accordingly. */
+ if (TREE_CODE (parmtype) == POINTER_TYPE)
+ t = convert_pointer_to_real (TREE_TYPE (parmtype), TREE_VALUE (arg));
+ else
+ /* This happens with signatures. */
+ t = convert_force (parmtype, TREE_VALUE (arg), CONV_C_CAST);
+ converted_args = expr_tree_cons (NULL_TREE, t, converted_args);
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
++i;
@@ -3337,7 +3316,14 @@ build_over_call (cand, args, flags)
"argument passing", fn, i - is_method);
}
else
- val = convert_like (conv, TREE_VALUE (arg));
+ {
+ /* Issue warnings about peculiar, but legal, uses of NULL. */
+ if (ARITHMETIC_TYPE_P (TREE_VALUE (parm))
+ && TREE_VALUE (arg) == null_node)
+ cp_warning ("converting NULL to non-pointer type");
+
+ val = convert_like (conv, TREE_VALUE (arg));
+ }
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
@@ -3350,34 +3336,12 @@ build_over_call (cand, args, flags)
/* Default arguments */
for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm))
- {
- tree arg = TREE_PURPOSE (parm);
-
- if (DECL_TEMPLATE_INFO (fn))
- {
- /* This came from a template. Instantiate the default arg here,
- not in tsubst. In the case of something like:
-
- template <class T>
- struct S {
- static T t();
- void f(T = t());
- };
-
- we must be careful to do name lookup in the scope of
- S<T>, rather than in the current class. */
- if (DECL_CLASS_SCOPE_P (fn))
- pushclass (DECL_REAL_CONTEXT (fn), 2);
-
- arg = tsubst_expr (arg, DECL_TI_ARGS (fn), 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);
- }
+ converted_args
+ = expr_tree_cons (NULL_TREE,
+ convert_default_arg (TREE_VALUE (parm),
+ TREE_PURPOSE (parm),
+ fn),
+ converted_args);
/* Ellipsis */
for (; arg; arg = TREE_CHAIN (arg))
@@ -3388,10 +3352,17 @@ build_over_call (cand, args, flags)
converted_args = nreverse (converted_args);
+ if (warn_format && (DECL_NAME (fn) || DECL_ASSEMBLER_NAME (fn)))
+ check_function_format (DECL_NAME (fn), DECL_ASSEMBLER_NAME (fn),
+ converted_args);
+
/* Avoid actually calling copy constructors and copy assignment operators,
if possible. */
- if (DECL_CONSTRUCTOR_P (fn)
- && TREE_VEC_LENGTH (convs) == 1
+
+ if (! flag_elide_constructors)
+ /* Do things the hard way. */;
+ else if (DECL_CONSTRUCTOR_P (fn)
+ && TREE_VEC_LENGTH (convs) == 1
&& copy_args_p (fn))
{
tree targ;
@@ -3409,8 +3380,8 @@ build_over_call (cand, args, flags)
if (TREE_CODE (targ) == ADDR_EXPR)
{
targ = TREE_OPERAND (targ, 0);
- if (! comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg))),
- TYPE_MAIN_VARIANT (TREE_TYPE (targ)), 1))
+ if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg))),
+ TYPE_MAIN_VARIANT (TREE_TYPE (targ))))
targ = NULL_TREE;
}
else
@@ -3437,8 +3408,7 @@ build_over_call (cand, args, flags)
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_decl (VAR_DECL, NULL_TREE, DECL_CONTEXT (fn));
val = build (TARGET_EXPR, DECL_CONTEXT (fn), val, arg, 0, 0);
TREE_SIDE_EFFECTS (val) = 1;
return val;
@@ -3447,20 +3417,34 @@ build_over_call (cand, args, flags)
else if (! real_lvalue_p (arg)
|| TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
{
+ tree address;
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);
+ /* If we're initializing an empty class, then we actually
+ have to use a MODIFY_EXPR rather than an INIT_EXPR. The
+ reason is that the dummy padding member in the target may
+ not actually be allocated if TO is a base class
+ subobject. Since we've set TYPE_NONCOPIED_PARTS on the
+ padding, a MODIFY_EXPR will preserve its value, which is
+ the right thing to do if it's not really padding at all.
+
+ It's not safe to just throw away the ARG if we're looking
+ at an empty class because the ARG might contain a
+ TARGET_EXPR which wants to be bound to TO. If it is not,
+ expand_expr will assign a dummy slot for the TARGET_EXPR,
+ and we will call a destructor for it, which is wrong,
+ because we will also destroy TO, but will never have
+ constructed it. */
+ val = build (is_empty_class (DECL_CLASS_CONTEXT (fn))
+ ? MODIFY_EXPR : INIT_EXPR,
+ DECL_CONTEXT (fn), to, arg);
TREE_SIDE_EFFECTS (val) = 1;
- return build_unary_op (ADDR_EXPR, val, 0);
+ address = build_unary_op (ADDR_EXPR, val, 0);
+ /* Avoid a warning about this expression, if the address is
+ never used. */
+ TREE_USED (address) = 1;
+ return address;
}
}
else if (DECL_NAME (fn) == ansi_opname[MODIFY_EXPR]
@@ -3472,12 +3456,6 @@ build_over_call (cand, args, flags)
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;
@@ -3524,7 +3502,7 @@ build_over_call (cand, args, flags)
}
fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args);
- if (TREE_TYPE (fn) == void_type_node)
+ if (TREE_CODE (TREE_TYPE (fn)) == VOID_TYPE)
return fn;
fn = require_complete_type (fn);
if (IS_AGGR_TYPE (TREE_TYPE (fn)))
@@ -3549,8 +3527,16 @@ build_new_method_call (instance, name, args, basetype_path, flags)
{
explicit_targs = TREE_OPERAND (name, 1);
name = TREE_OPERAND (name, 0);
- if (TREE_CODE (name) == TEMPLATE_DECL)
+ if (TREE_CODE_CLASS (TREE_CODE (name)) == 'd')
name = DECL_NAME (name);
+ else
+ {
+ if (TREE_CODE (name) == COMPONENT_REF)
+ name = TREE_OPERAND (name, 1);
+ if (TREE_CODE (name) == OVERLOAD)
+ name = DECL_NAME (OVL_CURRENT (name));
+ }
+
template_only = 1;
}
@@ -3572,7 +3558,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
instance = resolve_offset_ref (instance);
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
instance = convert_from_reference (instance);
- basetype = TREE_TYPE (instance);
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
/* XXX this should be handled before we get here. */
if (! IS_AGGR_TYPE (basetype)
@@ -3672,8 +3658,12 @@ build_new_method_call (instance, name, args, basetype_path, flags)
/* XXX will LOOKUP_SPECULATIVELY be needed when this is done? */
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
- cp_error ("no matching function for call to `%T::%D (%A)%V'", basetype,
- pretty_name, user_args, TREE_TYPE (TREE_TYPE (instance_ptr)));
+ if (TYPE_SIZE (basetype) == 0)
+ incomplete_type_error (instance_ptr, basetype);
+ else
+ 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;
}
@@ -3692,12 +3682,14 @@ build_new_method_call (instance, name, args, basetype_path, flags)
&& instance == current_class_ref
&& DECL_CONSTRUCTOR_P (current_function_decl)
&& ! (flags & LOOKUP_NONVIRTUAL)
- && value_member (cand->fn, get_abstract_virtuals (basetype)))
+ && value_member (cand->fn, CLASSTYPE_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);
+ && is_dummy_object (instance_ptr))
+ {
+ cp_error ("cannot call member function `%D' without object", cand->fn);
+ return error_mark_node;
+ }
if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
&& ((instance == current_class_ref && (dtor_label || ctor_label))
@@ -3750,9 +3742,9 @@ is_subseq (ics1, ics2)
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))
+ && same_type_p (TREE_TYPE (ics2), TREE_TYPE (ics1))
+ && same_type_p (TREE_TYPE (TREE_OPERAND (ics2, 0)),
+ TREE_TYPE (TREE_OPERAND (ics1, 0))))
return 1;
}
}
@@ -3760,7 +3752,7 @@ is_subseq (ics1, ics2)
/* Returns non-zero iff DERIVED is derived from BASE. The inputs may
be any _TYPE nodes. */
-static int
+int
is_properly_derived_from (derived, base)
tree derived;
tree base;
@@ -3771,8 +3763,8 @@ is_properly_derived_from (derived, base)
/* 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)
+ return (!same_type_p (TYPE_MAIN_VARIANT (derived),
+ TYPE_MAIN_VARIANT (base))
&& DERIVED_FROM_P (base, derived));
}
@@ -3879,9 +3871,9 @@ compare_ics (ics1, ics2)
tree to_type1;
tree to_type2;
tree deref_from_type1 = NULL_TREE;
- tree deref_from_type2;
- tree deref_to_type1;
- tree deref_to_type2;
+ tree deref_from_type2 = NULL_TREE;
+ tree deref_to_type1 = NULL_TREE;
+ tree deref_to_type2 = NULL_TREE;
/* REF_BINDING is non-zero if the result of the conversion sequence
is a reference type. In that case TARGET_TYPE is the
@@ -3985,7 +3977,7 @@ compare_ics (ics1, ics2)
from_type2 = TREE_TYPE (from_type2);
}
- if (comptypes (from_type1, from_type2, 1))
+ if (same_type_p (from_type1, from_type2))
{
if (is_subseq (ics1, ics2))
return 1;
@@ -4085,7 +4077,7 @@ compare_ics (ics1, ics2)
else if (TREE_CODE (deref_to_type1) == VOID_TYPE
|| TREE_CODE (deref_to_type2) == VOID_TYPE)
{
- if (comptypes (deref_from_type1, deref_from_type2, 1))
+ if (same_type_p (deref_from_type1, deref_from_type2))
{
if (TREE_CODE (deref_to_type2) == VOID_TYPE)
{
@@ -4112,7 +4104,7 @@ compare_ics (ics1, ics2)
--conversion of B* to A* is better than conversion of C* to
A* */
- if (comptypes (deref_from_type1, deref_from_type2, 1))
+ if (same_type_p (deref_from_type1, deref_from_type2))
{
if (is_properly_derived_from (deref_to_type1,
deref_to_type2))
@@ -4121,7 +4113,7 @@ compare_ics (ics1, ics2)
deref_to_type1))
return -1;
}
- else if (comptypes (deref_to_type1, deref_to_type2, 1))
+ else if (same_type_p (deref_to_type1, deref_to_type2))
{
if (is_properly_derived_from (deref_from_type2,
deref_from_type1))
@@ -4133,7 +4125,7 @@ compare_ics (ics1, ics2)
}
}
else if (IS_AGGR_TYPE_CODE (TREE_CODE (from_type1))
- && comptypes (from_type1, from_type2, 1))
+ && same_type_p (from_type1, from_type2))
{
/* [over.ics.rank]
@@ -4152,7 +4144,7 @@ compare_ics (ics1, ics2)
}
}
else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1))
- && comptypes (to_type1, to_type2, 1))
+ && same_type_p (to_type1, to_type2))
{
/* [over.ics.rank]
@@ -4179,7 +4171,7 @@ compare_ics (ics1, ics2)
qualification signature of type T2 */
if (TREE_CODE (ics1) == QUAL_CONV
&& TREE_CODE (ics2) == QUAL_CONV
- && comptypes (from_type1, from_type2, 1))
+ && same_type_p (from_type1, from_type2))
return comp_cv_qual_signature (to_type1, to_type2);
/* [over.ics.rank]
@@ -4191,8 +4183,8 @@ compare_ics (ics1, ics2)
which the reference initialized by S1 refers */
if (ref_binding1 && ref_binding2
- && comptypes (TYPE_MAIN_VARIANT (to_type1),
- TYPE_MAIN_VARIANT (to_type2), 1))
+ && same_type_p (TYPE_MAIN_VARIANT (to_type1),
+ TYPE_MAIN_VARIANT (to_type2)))
return comp_cv_qualification (target_type2, target_type1);
/* Neither conversion sequence is better than the other. */
@@ -4250,6 +4242,11 @@ joust (cand1, cand2, warn)
if (cand1->viable < cand2->viable)
return -1;
+ /* If we have two pseudo-candidates for conversions to the same type,
+ arbitrarily pick one. */
+ if (TYPE_P (cand1->fn) && cand1->fn == cand2->fn)
+ 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
@@ -4335,8 +4332,8 @@ joust (cand1, cand2, warn)
!= 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))))
+ && ! same_type_p (TREE_TYPE (TREE_TYPE (cand1->fn)),
+ TREE_TYPE (TREE_TYPE (cand2->fn))))))
{
int comp = compare_ics (cand1->second_conv, cand2->second_conv);
if (comp != winner)
@@ -4392,8 +4389,8 @@ joust (cand1, cand2, warn)
&& 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))
+ if (!same_type_p (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)),
+ TREE_TYPE (TREE_VEC_ELT (cand2->convs, i))))
break;
if (i == TREE_VEC_LENGTH (cand1->convs))
return 1;
@@ -4408,7 +4405,7 @@ joust (cand1, cand2, warn)
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 (same_type_p (t1, t2))
{
if (TREE_CODE (c1) == REF_BIND && TREE_CODE (c2) != REF_BIND)
return 1;
diff --git a/contrib/gcc/cp/class.c b/contrib/gcc/cp/class.c
index 8a61bf8..400c67d 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, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -30,66 +30,71 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "output.h"
#include "toplev.h"
+#include "splay-tree.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-extern struct obstack permanent_obstack;
-
/* This is how we tell when two virtual member functions are really the
same. */
#define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL))
extern void set_class_shadows PROTO ((tree));
-/* Way of stacking class types. */
-static tree *current_class_base, *current_class_stack;
-static int current_class_stacksize;
+/* The number of nested classes being processed. If we are not in the
+ scope of any class, this is zero. */
+
int current_class_depth;
-struct class_level
-{
- /* The previous class level. */
- struct class_level *level_chain;
-
- /* The class instance variable, as a PARM_DECL. */
- tree decl;
- /* The class instance variable, as an object. */
- tree object;
- /* The virtual function table pointer
- for the class instance variable. */
- tree vtable_decl;
-
- /* Name of the current class. */
+/* In order to deal with nested classes, we keep a stack of classes.
+ The topmost entry is the innermost class, and is the entry at index
+ CURRENT_CLASS_DEPTH */
+
+typedef struct class_stack_node {
+ /* The name of the class. */
tree name;
- /* Type of the current class. */
+
+ /* The _TYPE node for the class. */
tree type;
- /* Flags for this class level. */
- int this_is_variable;
- int memoized_lookups;
- int save_memoized;
- int unused;
-};
+ /* The access specifier pending for new declarations in the scope of
+ this class. */
+ tree access;
-/* The current_class_ptr is the pointer to the current class.
- current_class_ref is the actual current class. */
+ /* If were defining TYPE, the names used in this class. */
+ splay_tree names_used;
+}* class_stack_node_t;
+
+/* The stack itself. This is an dynamically resized array. The
+ number of elements allocated is CURRENT_CLASS_STACK_SIZE. */
+static int current_class_stack_size;
+static class_stack_node_t current_class_stack;
+
+/* When we're processing a member function, current_class_ptr is the
+ PARM_DECL for the `this' pointer. The current_class_ref is an
+ expression for `*this'. */
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 */
tree current_class_type; /* _TYPE: the type of the current class */
+tree current_access_specifier;
tree previous_class_type; /* _TYPE: the previous type that was a class */
-tree previous_class_values; /* TREE_LIST: copy of the class_shadowed list
+tree previous_class_values; /* TREE_LIST: copy of the class_shadowed list
when leaving an outermost class scope. */
+/* The obstack on which the cached class declarations are kept. */
+static struct obstack class_cache_obstack;
+/* The first object allocated on that obstack. We can use
+ obstack_free with tis value to free the entire obstack. */
+char *class_cache_firstobj;
+
struct base_info;
static tree get_vfield_name PROTO((tree));
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));
@@ -99,7 +104,6 @@ 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));
@@ -115,7 +119,6 @@ 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));
@@ -124,8 +127,16 @@ 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 *));
+static void finish_struct_methods PROTO((tree));
+static void maybe_warn_about_overly_private_class PROTO ((tree));
+static tree make_method_vec PROTO((int));
+static void free_method_vec PROTO((tree));
+static tree add_implicitly_declared_members PROTO((tree, int, int, int));
+static tree fixed_type_or_null PROTO((tree, int *));
+static tree resolve_address_of_overloaded_function PROTO((tree, tree, int,
+ int, tree));
+static void build_vtable_entry_ref PROTO((tree, tree, tree));
/* Way of stacking language names. */
tree *current_lang_base, *current_lang_stack;
@@ -170,12 +181,12 @@ build_vbase_pointer (exp, type)
tree exp, type;
{
char *name;
+ FORMAT_VBASE_NAME (name, 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), NULL_TREE, 0);
}
+#if 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. */
@@ -221,6 +232,7 @@ complete_type_p (expr)
}
return 0;
}
+#endif
/* Build multi-level access to EXPR using hierarchy path PATH.
CODE is PLUS_EXPR if we are going with the grain,
@@ -229,17 +241,17 @@ 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'. */
+ NONNULL is non-zero if we know (for any reason) that EXPR is
+ not, in fact, zero. */
tree
-build_vbase_path (code, type, expr, path, alias_this)
+build_vbase_path (code, type, expr, path, nonnull)
enum tree_code code;
tree type, expr, path;
- int alias_this;
+ int nonnull;
{
register int changed = 0;
tree last = NULL_TREE, last_virtual = NULL_TREE;
- int nonnull = 0;
int fixed_type_p;
tree null_expr = 0, nonnull_expr;
tree basetype;
@@ -248,40 +260,23 @@ build_vbase_path (code, type, expr, path, alias_this)
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 -fthis-is-variable, we might have set nonnull incorrectly. We
+ don't care enough to get this right, so just clear it. */
+ if (flag_this_is_variable > 0)
+ nonnull = 0;
-#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) */
+ /* We could do better if we had 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, we only optimize
+ if the complete type is the same type as expr has. */
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. */
- fixed_type_p = complete_type_p (expr);
-#endif
if (!fixed_type_p && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
nonnull_expr = expr;
if (BINFO_INHERITANCE_CHAIN (path))
- {
- tree reverse_path = NULL_TREE;
-
- push_expression_obstack ();
- while (path)
- {
- tree r = copy_node (path);
- BINFO_INHERITANCE_CHAIN (r) = reverse_path;
- reverse_path = r;
- path = BINFO_INHERITANCE_CHAIN (path);
- }
- path = reverse_path;
- pop_obstacks ();
- }
+ path = reverse_path (path);
basetype = BINFO_TYPE (path);
@@ -308,8 +303,7 @@ build_vbase_path (code, type, expr, path, alias_this)
ind = build_indirect_ref (nonnull_expr, NULL_PTR);
nonnull_expr = build_vbase_pointer (ind, last_virtual);
if (nonnull == 0
- && (TREE_CODE (type) == POINTER_TYPE
- || !flag_assume_nonnull_objects)
+ && TREE_CODE (type) == POINTER_TYPE
&& null_expr == NULL_TREE)
{
null_expr = build1 (NOP_EXPR, build_pointer_type (last_virtual), integer_zero_node);
@@ -382,12 +376,7 @@ build_vbase_path (code, type, expr, path, alias_this)
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.
- Preserve such zeroness here. Otherwise, only in the
- case of constructors need we worry, and in those cases,
- it will be zero, or initialized to some valid value to
- which we may add. */
+ /* If expr might be 0, we need to preserve that zeroness. */
if (nonnull == 0)
{
if (null_expr)
@@ -475,6 +464,36 @@ build_vtable_entry (delta, pfn)
}
}
+/* We want to give the assembler the vtable identifier as well as
+ the offset to the function pointer. So we generate
+
+ __asm__ __volatile__ (".vtable_entry %c0, %c1"
+ : : "s"(&class_vtable),
+ "i"((long)&vtbl[idx].pfn - (long)&vtbl[0])); */
+
+static void
+build_vtable_entry_ref (basetype, vtbl, idx)
+ tree basetype, vtbl, idx;
+{
+ static char asm_stmt[] = ".vtable_entry %c0, %c1";
+ tree s, i, i2;
+
+ s = build_unary_op (ADDR_EXPR, TYPE_BINFO_VTABLE (basetype), 0);
+ s = build_tree_list (build_string (1, "s"), s);
+
+ i = build_array_ref (vtbl, idx);
+ if (!flag_vtable_thunks)
+ i = build_component_ref (i, pfn_identifier, vtable_entry_type, 0);
+ i = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i, 0));
+ i2 = build_array_ref (vtbl, build_int_2(0,0));
+ i2 = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i2, 0));
+ i = build_binary_op (MINUS_EXPR, i, i2);
+ i = build_tree_list (build_string (1, "i"), i);
+
+ expand_asm_operands (build_string (sizeof(asm_stmt)-1, asm_stmt),
+ NULL_TREE, chainon (s, i), NULL_TREE, 1, NULL, 0);
+}
+
/* Given an object INSTANCE, return an expression which yields the
virtual function vtable element corresponding to INDEX. There are
many special cases for INSTANCE which we take care of here, mainly
@@ -491,8 +510,7 @@ build_vtbl_ref (instance, idx)
basetype = TREE_TYPE (basetype);
if (instance == current_class_ref)
- vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
- NULL_PTR);
+ vtbl = build_vfield_ref (instance, basetype);
else
{
if (optimize)
@@ -532,10 +550,14 @@ build_vtbl_ref (instance, idx)
|| TREE_CODE (instance) == VAR_DECL))
vtbl = TYPE_BINFO_VTABLE (basetype);
else
- vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
- NULL_PTR);
+ vtbl = build_vfield_ref (instance, basetype);
}
+
assemble_external (vtbl);
+
+ if (flag_vtable_gc)
+ build_vtable_entry_ref (basetype, vtbl, idx);
+
aref = build_array_ref (vtbl, idx);
return aref;
@@ -585,7 +607,7 @@ get_vtable_name (type)
tree type_id = build_typename_overload (type);
char *buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT)
+ IDENTIFIER_LENGTH (type_id) + 2);
- char *ptr = IDENTIFIER_POINTER (type_id);
+ const char *ptr = IDENTIFIER_POINTER (type_id);
int i;
for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ;
#if 0
@@ -647,6 +669,9 @@ set_rtti_entry (virtuals, offset, type)
{
tree vfn;
+ if (CLASSTYPE_COM_INTERFACE (type))
+ return;
+
if (flag_rtti)
vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type));
else
@@ -685,7 +710,7 @@ build_vtable (binfo, type)
tree offset;
virtuals = copy_list (BINFO_VIRTUALS (binfo));
- decl = build_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo)));
+ decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo)));
/* Now do rtti stuff. */
offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);
@@ -695,7 +720,7 @@ build_vtable (binfo, type)
else
{
virtuals = NULL_TREE;
- decl = build_decl (VAR_DECL, name, void_type_node);
+ decl = build_lang_decl (VAR_DECL, name, void_type_node);
}
#ifdef GATHER_STATISTICS
@@ -724,9 +749,7 @@ build_vtable (binfo, type)
DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
DECL_ALIGN (decl));
- /* Why is this conditional? (mrs) */
- if (binfo && write_virtuals >= 0)
- DECL_VIRTUAL_P (decl) = 1;
+ DECL_VIRTUAL_P (decl) = 1;
DECL_CONTEXT (decl) = type;
binfo = TYPE_BINFO (type);
@@ -847,7 +870,7 @@ prepare_fresh_vtable (binfo, for_type)
buf2 = new_buf2;
}
- new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
+ new_decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
/* Remember which class this vtable is really for. */
DECL_CONTEXT (new_decl) = for_type;
@@ -1013,10 +1036,14 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
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. */
- if (*has_virtual == 0 && flag_vtable_thunks)
+ for the offset pointer, one for the tdesc pointer.
+ For ARM-style vtables, use the same slot for both. */
+ if (*has_virtual == 0 && ! CLASSTYPE_COM_INTERFACE (t))
{
- *has_virtual = 1;
+ if (flag_vtable_thunks)
+ *has_virtual = 2;
+ else
+ *has_virtual = 1;
}
/* Build a new INT_CST for this DECL_VINDEX. */
@@ -1024,7 +1051,7 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
static tree index_table[256];
tree idx;
/* We skip a slot for the offset/tdesc entry. */
- int i = ++(*has_virtual);
+ int i = (*has_virtual)++;
if (i >= 256 || index_table[i] == 0)
{
@@ -1058,122 +1085,230 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
struct obstack class_obstack;
extern struct obstack *current_obstack;
-/* Add method METHOD to class TYPE. This is used when a method
- has been defined which did not initially appear in the class definition,
- and helps cut down on spurious error messages.
+/* These are method vectors that were too small for the number of
+ methods in some class, and so were abandoned. */
+static tree free_method_vecs;
+
+/* Returns a method vector with enough room for N methods. N should
+ be a power of two. */
+
+static tree
+make_method_vec (n)
+ int n;
+{
+ tree new_vec;
+ tree* t;
+
+ for (t = &free_method_vecs; *t; t = &(TREE_CHAIN (*t)))
+ /* Note that we don't use >= n here because we don't want to
+ allocate a very large vector where it isn't needed. */
+ if (TREE_VEC_LENGTH (*t) == n)
+ {
+ new_vec = *t;
+ *t = TREE_CHAIN (new_vec);
+ TREE_CHAIN (new_vec) = NULL_TREE;
+ bzero ((PTR) &TREE_VEC_ELT (new_vec, 0), n * sizeof (tree));
+ return new_vec;
+ }
+
+ new_vec = make_tree_vec (n);
+ return new_vec;
+}
+
+/* Free the method vector VEC. */
- FIELDS is the entry in the METHOD_VEC vector entry of the class type where
- the method should be added. */
+static void
+free_method_vec (vec)
+ tree vec;
+{
+ TREE_CHAIN (vec) = free_method_vecs;
+ free_method_vecs = vec;
+}
+
+/* Add method METHOD to class TYPE.
+
+ If non-NULL, 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;
{
- push_obstacks (&permanent_obstack, &permanent_obstack);
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ /* Setting the DECL_CONTEXT and DECL_CLASS_CONTEXT here is probably
+ redundant. */
+ DECL_CONTEXT (method) = type;
+ DECL_CLASS_CONTEXT (method) = type;
+
if (fields && *fields)
- *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 (method))
- {
- /* ??? 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
- {
- /* ??? 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) + 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;
- }
- else
- {
- tree method_vec = CLASSTYPE_METHOD_VEC (type);
- int len = TREE_VEC_LENGTH (method_vec);
-
- /* 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 (method))
- {
- 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));
- }
+ *fields = build_overload (method, *fields);
+ else
+ {
+ int len;
+ int slot;
+ tree method_vec;
+
+ if (!CLASSTYPE_METHOD_VEC (type))
+ /* Make a new method vector. We start with 8 entries. We must
+ allocate at least two (for constructors and destructors), and
+ we're going to end up with an assignment operator at some
+ point as well.
+
+ We could use a TREE_LIST for now, and convert it to a
+ TREE_VEC in finish_struct, but we would probably waste more
+ memory making the links in the list than we would by
+ over-allocating the size of the vector here. Furthermore,
+ we would complicate all the code that expects this to be a
+ vector. We keep a free list of vectors that we outgrew so
+ that we don't really waste any memory. */
+ CLASSTYPE_METHOD_VEC (type) = make_method_vec (8);
+
+ method_vec = CLASSTYPE_METHOD_VEC (type);
+ len = TREE_VEC_LENGTH (method_vec);
+
+ if (DECL_NAME (method) == constructor_name (type))
+ /* A new constructor or destructor. Constructors go in
+ slot 0; destructors go in slot 1. */
+ slot = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0;
else
{
- /* This is trickier. We try to extend the TREE_VEC in-place,
- but if that does not work, we copy all its data to a new
- TREE_VEC that's large enough. */
- struct obstack *ob = &class_obstack;
- tree *end = (tree *)obstack_next_free (ob);
-
- if (end != TREE_VEC_END (method_vec))
+ /* See if we already have an entry with this name. */
+ for (slot = 2; slot < len; ++slot)
+ if (!TREE_VEC_ELT (method_vec, slot)
+ || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
+ slot)))
+ == DECL_NAME (method)))
+ break;
+
+ if (slot == len)
{
- ob = current_obstack;
- TREE_VEC_LENGTH (method_vec) += 1;
- TREE_VEC_ELT (method_vec, len) = NULL_TREE;
- method_vec = copy_node (method_vec);
- TREE_VEC_LENGTH (method_vec) -= 1;
+ /* We need a bigger method vector. */
+ tree new_vec = make_method_vec (2 * len);
+ bcopy ((PTR) &TREE_VEC_ELT (method_vec, 0),
+ (PTR) &TREE_VEC_ELT (new_vec, 0),
+ len * sizeof (tree));
+ free_method_vec (method_vec);
+ len = 2 * len;
+ method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
}
- else
+
+ if (DECL_CONV_FN_P (method) && !TREE_VEC_ELT (method_vec, slot))
{
- tree tmp_vec = (tree) obstack_base (ob);
- if (obstack_room (ob) < sizeof (tree))
+ /* Type conversion operators have to come before
+ ordinary methods; add_conversions depends on this to
+ speed up looking for conversion operators. So, if
+ necessary, we slide some of the vector elements up.
+ In theory, this makes this algorithm O(N^2) but we
+ don't expect many conversion operators. */
+ for (slot = 2; slot < len; ++slot)
{
- obstack_blank (ob, sizeof (struct tree_common)
- + tree_code_length[(int) TREE_VEC]
- * sizeof (char *)
- + len * sizeof (tree));
- tmp_vec = (tree) obstack_base (ob);
- bcopy ((char *) method_vec, (char *) tmp_vec,
- (sizeof (struct tree_common)
- + tree_code_length[(int) TREE_VEC] * sizeof (char *)
- + (len-1) * sizeof (tree)));
- method_vec = tmp_vec;
+ tree fn = TREE_VEC_ELT (method_vec, slot);
+
+ if (!fn)
+ /* There are no more entries in the vector, so we
+ can insert the new conversion operator here. */
+ break;
+
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+ /* We can insert the new function right at the
+ SLOTth position. */
+ break;
}
+
+ if (!TREE_VEC_ELT (method_vec, slot))
+ /* There is nothing in the Ith slot, so we can avoid
+ moving anything. */
+ ;
else
- obstack_blank (ob, sizeof (tree));
+ {
+ /* We know the last slot in the vector is empty
+ because we know that at this point there's room
+ for a new function. */
+ bcopy ((PTR) &TREE_VEC_ELT (method_vec, slot),
+ (PTR) &TREE_VEC_ELT (method_vec, slot + 1),
+ (len - slot - 1) * sizeof (tree));
+ TREE_VEC_ELT (method_vec, slot) = NULL_TREE;
+ }
}
+ }
+
+ if (template_class_depth (type))
+ /* TYPE is a template class. Don't issue any errors now; wait
+ until instantiation time to complain. */
+ ;
+ else
+ {
+ tree fns;
- obstack_finish (ob);
- TREE_VEC_ELT (method_vec, len) = method;
- TREE_VEC_LENGTH (method_vec) = len + 1;
- CLASSTYPE_METHOD_VEC (type) = method_vec;
-
- if (TYPE_BINFO_BASETYPES (type) && CLASSTYPE_BASELINK_VEC (type))
+ /* Check to see if we've already got this method. */
+ for (fns = TREE_VEC_ELT (method_vec, slot);
+ fns;
+ fns = OVL_NEXT (fns))
{
- /* ??? May be better to know whether these can be extended? */
- tree baselink_vec = CLASSTYPE_BASELINK_VEC (type);
+ tree fn = OVL_CURRENT (fns);
+
+ if (TREE_CODE (fn) != TREE_CODE (method))
+ continue;
+
+ if (TREE_CODE (method) != TEMPLATE_DECL)
+ {
+ /* [over.load] Member function declarations with the
+ same name and the same parameter types cannot be
+ overloaded if any of them is a static member
+ function declaration. */
+ if (DECL_STATIC_FUNCTION_P (fn)
+ != DECL_STATIC_FUNCTION_P (method))
+ {
+ tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
- TREE_VEC_LENGTH (baselink_vec) += 1;
- CLASSTYPE_BASELINK_VEC (type) = copy_node (baselink_vec);
- TREE_VEC_LENGTH (baselink_vec) -= 1;
+ if (! DECL_STATIC_FUNCTION_P (fn))
+ parms1 = TREE_CHAIN (parms1);
+ else
+ parms2 = TREE_CHAIN (parms2);
+
+ if (compparms (parms1, parms2))
+ cp_error ("`%#D' and `%#D' cannot be overloaded",
+ fn, method);
+ }
+
+ /* Since this is an ordinary function in a
+ non-template class, it's mangled name can be used
+ as a unique identifier. This technique is only
+ an optimization; we would get the same results if
+ we just used decls_match here. */
+ if (DECL_ASSEMBLER_NAME (fn)
+ != DECL_ASSEMBLER_NAME (method))
+ continue;
+ }
+ else if (!decls_match (fn, method))
+ continue;
- TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), len) = 0;
+ /* There has already been a declaration of this method
+ or member template. */
+ cp_error_at ("`%D' has already been declared in `%T'",
+ method, type);
+
+ /* We don't call duplicate_decls here to merge the
+ declarations because that will confuse things if the
+ methods have inline definitions. In particular, we
+ will crash while processing the definitions. */
+ return;
}
}
- }
- DECL_CONTEXT (method) = type;
- DECL_CLASS_CONTEXT (method) = type;
+ /* Actually insert the new method. */
+ TREE_VEC_ELT (method_vec, slot)
+ = build_overload (method, TREE_VEC_ELT (method_vec, slot));
+
+ /* Add the new binding. */
+ if (!DECL_CONSTRUCTOR_P (method)
+ && !DECL_DESTRUCTOR_P (method))
+ push_class_level_binding (DECL_NAME (method),
+ TREE_VEC_ELT (method_vec, slot));
+ }
pop_obstacks ();
}
@@ -1240,7 +1375,7 @@ delete_duplicate_fields_1 (field, fields)
else if (DECL_DECLARES_TYPE_P (field)
&& DECL_DECLARES_TYPE_P (x))
{
- if (comptypes (TREE_TYPE (field), TREE_TYPE (x), 1))
+ if (same_type_p (TREE_TYPE (field), TREE_TYPE (x)))
continue;
cp_error_at ("duplicate nested type `%D'", x);
}
@@ -1310,7 +1445,6 @@ alter_access (t, binfo, fdecl, access)
else
{
enforce_access (binfo, fdecl);
-
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
}
@@ -1318,10 +1452,9 @@ alter_access (t, binfo, fdecl, access)
}
/* 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. */
+ non-NULL, is the methods of T. The FIELDS are the fields of T. */
-void
+static void
handle_using_decl (using_decl, t, method_vec, fields)
tree using_decl;
tree t;
@@ -1346,8 +1479,11 @@ handle_using_decl (using_decl, t, method_vec, fields)
if (name == constructor_name (ctype)
|| name == constructor_name_full (ctype))
- cp_error_at ("using-declaration for constructor", using_decl);
-
+ {
+ cp_error_at ("using-declaration for constructor", using_decl);
+ return;
+ }
+
fdecl = lookup_member (binfo, name, 0, 0);
if (!fdecl)
@@ -1372,7 +1508,7 @@ handle_using_decl (using_decl, t, method_vec, fields)
name = DECL_NAME (fdecl);
n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
- for (i = 2; i < n_methods; i++)
+ for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); i++)
if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)))
== name)
{
@@ -1408,174 +1544,11 @@ handle_using_decl (using_decl, t, method_vec, fields)
else
alter_access (t, binfo, fdecl, access);
}
-
-/* If FOR_TYPE needs to reinitialize virtual function table pointers
- for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST.
- Returns BASE_INIT_LIST appropriately modified. */
-
-static tree
-maybe_fixup_vptrs (for_type, binfo, base_init_list)
- tree for_type, binfo, base_init_list;
-{
- /* Now reinitialize any slots that don't fall under our virtual
- function table pointer. */
- tree vfields = CLASSTYPE_VFIELDS (BINFO_TYPE (binfo));
- while (vfields)
- {
- tree basetype = VF_NORMAL_VALUE (vfields)
- ? TYPE_MAIN_VARIANT (VF_NORMAL_VALUE (vfields))
- : VF_BASETYPE_VALUE (vfields);
-
- tree base_binfo = get_binfo (basetype, for_type, 0);
- /* Punt until this is implemented. */
- if (1 /* BINFO_MODIFIED (base_binfo) */)
- {
- tree base_offset = get_vfield_offset (base_binfo);
- if (! tree_int_cst_equal (base_offset, get_vfield_offset (TYPE_BINFO (for_type)))
- && ! tree_int_cst_equal (base_offset, get_vfield_offset (binfo)))
- base_init_list = tree_cons (error_mark_node, base_binfo,
- base_init_list);
- }
- vfields = TREE_CHAIN (vfields);
- }
- return base_init_list;
-}
-
-/* If TYPE does not have a constructor, then the compiler must
- manually deal with all of the initialization this type requires.
-
- If a base initializer exists only to fill in the virtual function
- table pointer, then we mark that fact with the TREE_VIRTUAL bit.
- This way, we avoid multiple initializations of the same field by
- each virtual function table up the class hierarchy.
-
- Virtual base class pointers are not initialized here. They are
- initialized only at the "top level" of object creation. If we
- initialized them here, we would have to skip a lot of work. */
-
-static void
-build_class_init_list (type)
- tree type;
-{
- tree base_init_list = NULL_TREE;
- tree member_init_list = NULL_TREE;
-
- /* Since we build member_init_list and base_init_list using
- tree_cons, backwards fields the all through work. */
- tree x;
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (x = TYPE_FIELDS (type); x; x = TREE_CHAIN (x))
- {
- if (TREE_CODE (x) != FIELD_DECL)
- continue;
-
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (x))
- || DECL_INITIAL (x) != NULL_TREE)
- member_init_list = tree_cons (x, type, member_init_list);
- }
- member_init_list = nreverse (member_init_list);
-
- /* We will end up doing this last. Need special marker
- to avoid infinite regress. */
- if (TYPE_VIRTUAL_P (type))
- {
- base_init_list = build_tree_list (error_mark_node, TYPE_BINFO (type));
- if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (type) == 0)
- TREE_VALUE (base_init_list) = NULL_TREE;
- TREE_ADDRESSABLE (base_init_list) = 1;
- }
-
- /* Each base class which needs to have initialization
- of some kind gets to make such requests known here. */
- for (i = n_baseclasses-1; i >= 0; i--)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree blist;
-
- /* Don't initialize virtual baseclasses this way. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (base_binfo)))
- {
- /* ...and the last shall come first... */
- base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list);
- base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list);
- continue;
- }
-
- if ((blist = CLASSTYPE_BASE_INIT_LIST (BINFO_TYPE (base_binfo))) == NULL_TREE)
- /* Nothing to initialize. */
- continue;
-
- /* ...ditto... */
- base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list);
-
- /* This is normally true for single inheritance.
- The win is we can shrink the chain of initializations
- to be done by only converting to the actual type
- we are interested in. */
- if (TREE_VALUE (blist)
- && TREE_CODE (TREE_VALUE (blist)) == TREE_VEC
- && tree_int_cst_equal (BINFO_OFFSET (base_binfo),
- BINFO_OFFSET (TREE_VALUE (blist))))
- {
- if (base_init_list)
- {
- /* Does it do more than just fill in a
- virtual function table pointer? */
- if (! TREE_ADDRESSABLE (blist))
- base_init_list = build_tree_list (blist, base_init_list);
- /* Can we get by just with the virtual function table
- pointer that it fills in? */
- else if (TREE_ADDRESSABLE (base_init_list)
- && TREE_VALUE (base_init_list) == 0)
- base_init_list = blist;
- /* Maybe, but it is not obvious as the previous case. */
- else if (! CLASSTYPE_NEEDS_VIRTUAL_REINIT (type))
- {
- tree last = tree_last (base_init_list);
- while (TREE_VALUE (last)
- && TREE_CODE (TREE_VALUE (last)) == TREE_LIST)
- last = tree_last (TREE_VALUE (last));
- if (TREE_VALUE (last) == 0)
- base_init_list = build_tree_list (blist, base_init_list);
- }
- }
- else
- base_init_list = blist;
- }
- else
- {
- /* The function expand_aggr_init knows how to do the
- initialization of `basetype' without getting
- an explicit `blist'. */
- if (base_init_list)
- base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list);
- else
- base_init_list = CLASSTYPE_BINFO_AS_LIST (BINFO_TYPE (base_binfo));
- }
- }
-
- 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;
- }
- else if (member_init_list)
- CLASSTYPE_BASE_INIT_LIST (type) = member_init_list;
-}
struct base_info
{
int has_virtual;
int max_has_virtual;
- int n_ancestors;
tree vfield;
tree vfields;
tree rtti;
@@ -1658,7 +1631,6 @@ finish_base_struct (t, b)
&& !TYPE_HAS_CONST_ASSIGN_REF (basetype))
b->no_const_asn_ref = 1;
- b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype);
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
@@ -1668,8 +1640,20 @@ finish_base_struct (t, b)
TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
- if (! TREE_VIA_VIRTUAL (base_binfo))
- CLASSTYPE_N_SUPERCLASSES (t) += 1;
+ if (CLASSTYPE_COM_INTERFACE (basetype))
+ {
+ CLASSTYPE_COM_INTERFACE (t) = 1;
+ if (i > 0)
+ cp_error
+ ("COM interface type `%T' must be the leftmost base class",
+ basetype);
+ }
+ else if (CLASSTYPE_COM_INTERFACE (t))
+ {
+ cp_error ("COM interface type `%T' with non-COM base class `%T'",
+ t, basetype);
+ CLASSTYPE_COM_INTERFACE (t) = 0;
+ }
if (TYPE_VIRTUAL_P (basetype))
{
@@ -1766,35 +1750,6 @@ finish_base_struct (t, b)
}
}
- /* 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, 0, (tree*)0) == -2)
- {
- cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
- basetype, t);
- }
- }
- {
- tree v = get_vbase_types (t);
-
- for (; v; v = TREE_CHAIN (v))
- {
- tree basetype = BINFO_TYPE (v);
- 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);
- }
- }
- }
-
{
tree vfields;
/* Find the base class with the largest number of virtual functions. */
@@ -1854,24 +1809,15 @@ finish_struct_bits (t, max_has_virtual)
if (n_baseclasses && max_has_virtual)
{
- /* Done by `finish_struct' for classes without baseclasses. */
- int might_have_abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (t) != 0;
- tree binfos = TYPE_BINFO_BASETYPES (t);
- for (i = n_baseclasses-1; i >= 0; i--)
- {
- might_have_abstract_virtuals
- |= (CLASSTYPE_ABSTRACT_VIRTUALS (BINFO_TYPE (TREE_VEC_ELT (binfos, i))) != 0);
- if (might_have_abstract_virtuals)
- break;
- }
- if (might_have_abstract_virtuals)
- {
- /* We use error_mark_node from override_one_vtable to signal
- 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);
- }
+ /* For a class w/o baseclasses, `finish_struct' has set
+ CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by definition). Similarly
+ for a class who's base classes do not have vtables. When neither
+ of these is true, we might have removed abstract virtuals (by
+ providing a definition), added some (by declaring new ones), or
+ redeclared ones from a base class. We need to recalculate what's
+ really an abstract virtual at this point (by looking in the
+ vtables). */
+ CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t);
}
if (n_baseclasses)
@@ -1886,8 +1832,6 @@ finish_struct_bits (t, max_has_virtual)
basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
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;
}
}
@@ -1913,39 +1857,157 @@ finish_struct_bits (t, max_has_virtual)
}
}
-/* 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. */
+/* Issue warnings about T having private constructors, but no friends,
+ and so forth.
+
+ HAS_NONPRIVATE_METHOD is nonzero if T has any non-private methods or
+ static members. HAS_NONPRIVATE_STATIC_FN is nonzero if T has any
+ non-private static member functions. */
static void
-grow_method (fndecl, method_vec_ptr)
- tree fndecl;
- tree *method_vec_ptr;
+maybe_warn_about_overly_private_class (t)
+ tree t;
{
- tree method_vec = (tree)obstack_base (&class_obstack);
+ int has_member_fn = 0;
+ int has_nonprivate_method = 0;
+ tree fn;
+
+ if (!warn_ctor_dtor_privacy
+ /* If the class has friends, those entities might create and
+ access instances, so we should not warn. */
+ || (CLASSTYPE_FRIEND_CLASSES (t)
+ || DECL_FRIENDLIST (TYPE_MAIN_DECL (t)))
+ /* We will have warned when the template was declared; there's
+ no need to warn on every instantiation. */
+ || CLASSTYPE_TEMPLATE_INSTANTIATION (t))
+ /* There's no reason to even consider warning about this
+ class. */
+ return;
+
+ /* We only issue one warning, if more than one applies, because
+ otherwise, on code like:
+
+ class A {
+ // Oops - forgot `public:'
+ A();
+ A(const A&);
+ ~A();
+ };
+
+ we warn several times about essentially the same problem. */
+
+ /* Check to see if all (non-constructor, non-destructor) member
+ functions are private. (Since there are no friends or
+ non-private statics, we can't ever call any of the private member
+ functions.) */
+ for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
+ /* We're not interested in compiler-generated methods; they don't
+ provide any way to call private members. */
+ if (!DECL_ARTIFICIAL (fn))
+ {
+ if (!TREE_PRIVATE (fn))
+ {
+ if (DECL_STATIC_FUNCTION_P (fn))
+ /* A non-private static member function is just like a
+ friend; it can create and invoke private member
+ functions, and be accessed without a class
+ instance. */
+ return;
+
+ has_nonprivate_method = 1;
+ break;
+ }
+ else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn))
+ has_member_fn = 1;
+ }
+
+ if (!has_nonprivate_method && has_member_fn)
+ {
+ /* There are no non-private methods, and there's at least one
+ private member function that isn't a constructor or
+ destructor. (If all the private members are
+ constructors/destructors we want to use the code below that
+ issues error messages specifically referring to
+ constructors/destructors.) */
+ int i;
+ tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++)
+ if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i))
+ || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i)))
+ {
+ has_nonprivate_method = 1;
+ break;
+ }
+ if (!has_nonprivate_method)
+ {
+ cp_warning ("all member functions in class `%T' are private", t);
+ return;
+ }
+ }
- /* Start off past the constructors and destructor. */
- tree *testp = &TREE_VEC_ELT (method_vec, 2);
+ /* Even if some of the member functions are non-private, the class
+ won't be useful for much if all the constructors or destructors
+ are private: such an object can never be created or destroyed. */
+ if (TYPE_HAS_DESTRUCTOR (t))
+ {
+ tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1);
- while (testp < (tree *) obstack_next_free (&class_obstack)
- && (*testp == NULL_TREE || DECL_NAME (OVL_CURRENT (*testp)) != DECL_NAME (fndecl)))
- testp++;
+ if (TREE_PRIVATE (dtor))
+ {
+ cp_warning ("`%#T' only defines a private destructor and has no friends",
+ t);
+ return;
+ }
+ }
- if (testp < (tree *) obstack_next_free (&class_obstack))
- *testp = build_overload (fndecl, *testp);
- else
+ if (TYPE_HAS_CONSTRUCTOR (t))
{
- obstack_ptr_grow (&class_obstack, fndecl);
- *method_vec_ptr = (tree)obstack_base (&class_obstack);
+ int nonprivate_ctor = 0;
+
+ /* If a non-template class does not define a copy
+ constructor, one is defined for it, enabling it to avoid
+ this warning. For a template class, this does not
+ happen, and so we would normally get a warning on:
+
+ template <class T> class C { private: C(); };
+
+ To avoid this asymmetry, we check TYPE_HAS_INIT_REF. All
+ complete non-template or fully instantiated classes have this
+ flag set. */
+ if (!TYPE_HAS_INIT_REF (t))
+ nonprivate_ctor = 1;
+ else
+ for (fn = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
+ fn;
+ fn = OVL_NEXT (fn))
+ {
+ tree ctor = OVL_CURRENT (fn);
+ /* Ideally, we wouldn't count copy constructors (or, in
+ fact, any constructor that takes an argument of the
+ class type as a parameter) because such things cannot
+ be used to construct an instance of the class unless
+ you already have one. But, for now at least, we're
+ more generous. */
+ if (! TREE_PRIVATE (ctor))
+ {
+ nonprivate_ctor = 1;
+ break;
+ }
+ }
+
+ if (nonprivate_ctor == 0)
+ {
+ cp_warning ("`%#T' only defines private constructors and has no friends",
+ t);
+ return;
+ }
}
}
+
/* Warn about duplicate methods in fn_fields. Also compact method
lists so that lookup can be made faster.
- Algorithm: Outer loop builds lists by method name. Inner loop
- checks for redundant method names within a list.
-
Data Structure: List of method lists. The outer list is a
TREE_LIST, whose TREE_PURPOSE field is the field name and the
TREE_VALUE is the DECL_CHAIN of the FUNCTION_DECLs. TREE_CHAIN
@@ -1961,35 +2023,20 @@ grow_method (fndecl, method_vec_ptr)
We also link each field which has shares a name with its baseclass
to the head of the list of fields for that base class. This allows
us to reduce search time in places like `build_method_call' to
- consider only reasonably likely functions. */
+ consider only reasonably likely functions. */
-tree
-finish_struct_methods (t, fn_fields, nonprivate_method)
+static void
+finish_struct_methods (t)
tree t;
- tree fn_fields;
- int nonprivate_method;
{
- tree method_vec;
- tree save_fn_fields = fn_fields;
+ tree fn_fields;
+ tree method_vec = CLASSTYPE_METHOD_VEC (t);
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_tree_vec (2);
- current_obstack = ambient_obstack;
-
- /* Now make this a live vector. */
- obstack_free (&class_obstack, method_vec);
-
- /* 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 (; fn_fields; fn_fields = TREE_CHAIN (fn_fields))
+ for (fn_fields = TYPE_METHODS (t); fn_fields;
+ fn_fields = TREE_CHAIN (fn_fields))
{
tree fn_name = DECL_NAME (fn_fields);
@@ -2020,32 +2067,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
TYPE_HAS_NONPUBLIC_CTOR (t) = 2;
}
}
- 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))
- grow_method (fn_fields, &method_vec);
- }
-
- fn_fields = save_fn_fields;
- for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields))
- {
- tree fn_name = DECL_NAME (fn_fields);
-
- if (fn_name == ctor_name || IDENTIFIER_TYPENAME_P (fn_name))
- continue;
-
- if (fn_name == ansi_opname[(int) MODIFY_EXPR])
+ }
+ else if (fn_name == ansi_opname[(int) MODIFY_EXPR])
{
tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields));
@@ -2057,75 +2080,16 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 2;
}
}
-
- grow_method (fn_fields, &method_vec);
}
- TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack)
- - (&TREE_VEC_ELT (method_vec, 0));
- obstack_finish (&class_obstack);
- CLASSTYPE_METHOD_VEC (t) = method_vec;
-
- if (nonprivate_method == 0
- && CLASSTYPE_FRIEND_CLASSES (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++)
- if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i))
- || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i)))
- {
- nonprivate_method = 1;
- break;
- }
- if (nonprivate_method == 0
- && warn_ctor_dtor_privacy)
- cp_warning ("all member functions in class `%T' are private", t);
- }
-
- /* Warn if all destructors are private (in which case this class is
- effectively unusable. */
- if (TYPE_HAS_DESTRUCTOR (t))
- {
- 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 (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) > 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 = 2; i < len; i++)
- {
- TREE_VEC_ELT (baselink_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;
- }
- if (any_links != 0)
- CLASSTYPE_BASELINK_VEC (t) = baselink_vec;
- else
- obstack_free (current_obstack, baselink_vec);
- }
-
- return method_vec;
+ if (TYPE_HAS_DESTRUCTOR (t) && !TREE_VEC_ELT (method_vec, 1))
+ /* We thought there was a destructor, but there wasn't. Some
+ parse errors cause this anomalous situation. */
+ TYPE_HAS_DESTRUCTOR (t) = 0;
+
+ /* Issue warnings about private constructors and such. If there are
+ no methods, then some public defaults are generated. */
+ maybe_warn_about_overly_private_class (t);
}
/* Emit error when a duplicate definition of a type is seen. Patch up. */
@@ -2164,18 +2128,14 @@ duplicate_tag_error (t)
if (TYPE_LANG_SPECIFIC (t))
{
- tree as_list = CLASSTYPE_AS_LIST (t);
tree binfo = TYPE_BINFO (t);
- tree binfo_as_list = CLASSTYPE_BINFO_AS_LIST (t);
int interface_only = CLASSTYPE_INTERFACE_ONLY (t);
int interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (t);
bzero ((char *) TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type));
BINFO_BASETYPES(binfo) = NULL_TREE;
- CLASSTYPE_AS_LIST (t) = as_list;
TYPE_BINFO (t) = binfo;
- CLASSTYPE_BINFO_AS_LIST (t) = binfo_as_list;
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
TYPE_REDEFINED (t) = 1;
@@ -2209,8 +2169,7 @@ finish_vtbls (binfo, do_self, t)
decl = BINFO_VTABLE (binfo);
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = 0;
- if (write_virtuals >= 0
- && DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
+ if (DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
BINFO_VIRTUALS (binfo));
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
@@ -2255,9 +2214,9 @@ overrides (fndecl, base_fndecl)
#endif
types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
base_types = TYPE_ARG_TYPES (TREE_TYPE (base_fndecl));
- if ((TYPE_READONLY (TREE_TYPE (TREE_VALUE (base_types)))
- == TYPE_READONLY (TREE_TYPE (TREE_VALUE (types))))
- && compparms (TREE_CHAIN (base_types), TREE_CHAIN (types), 3))
+ if ((TYPE_QUALS (TREE_TYPE (TREE_VALUE (base_types)))
+ == TYPE_QUALS (TREE_TYPE (TREE_VALUE (types))))
+ && compparms (TREE_CHAIN (base_types), TREE_CHAIN (types)))
return 1;
}
return 0;
@@ -2347,11 +2306,14 @@ 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;
+skip_rtti_stuff (virtuals, t)
+ tree *virtuals, t;
{
int n;
+ if (CLASSTYPE_COM_INTERFACE (t))
+ return 0;
+
n = 0;
if (*virtuals)
{
@@ -2393,7 +2355,7 @@ modify_one_vtable (binfo, t, fndecl, pfn)
if (fndecl == NULL_TREE)
return;
- n = skip_rtti_stuff (&virtuals);
+ n = skip_rtti_stuff (&virtuals, t);
while (virtuals)
{
@@ -2421,10 +2383,6 @@ modify_one_vtable (binfo, t, fndecl, pfn)
BINFO_OFFSET (binfo));
this_offset = ssize_binop (MINUS_EXPR, offset, base_offset);
- /* Make sure we can modify the derived association with immunity. */
- if (TREE_USED (binfo))
- my_friendly_assert (0, 999);
-
if (binfo == TYPE_BINFO (t))
{
/* In this case, it is *type*'s vtable we are modifying.
@@ -2491,7 +2449,7 @@ fixup_vtable_deltas1 (binfo, t)
tree virtuals = BINFO_VIRTUALS (binfo);
unsigned HOST_WIDE_INT n;
- n = skip_rtti_stuff (&virtuals);
+ n = skip_rtti_stuff (&virtuals, t);
while (virtuals)
{
@@ -2524,9 +2482,6 @@ fixup_vtable_deltas1 (binfo, t)
if (! tree_int_cst_equal (this_offset, delta))
{
/* Make sure we can modify the derived association with immunity. */
- if (TREE_USED (binfo))
- my_friendly_assert (0, 999);
-
if (binfo == TYPE_BINFO (t))
{
/* In this case, it is *type*'s vtable we are modifying.
@@ -2667,8 +2622,8 @@ override_one_vtable (binfo, old, t)
if (BINFO_NEW_VTABLE_MARKED (binfo))
choose = NEITHER;
- skip_rtti_stuff (&virtuals);
- skip_rtti_stuff (&old_virtuals);
+ skip_rtti_stuff (&virtuals, t);
+ skip_rtti_stuff (&old_virtuals, t);
while (virtuals)
{
@@ -2729,13 +2684,11 @@ override_one_vtable (binfo, old, t)
}
{
/* This MUST be overridden, or the class is ill-formed. */
- /* For now, we just make it abstract. */
tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
tree vfn;
fndecl = copy_node (fndecl);
copy_lang_decl (fndecl);
- DECL_ABSTRACT_VIRTUAL_P (fndecl) = 1;
DECL_NEEDS_FINAL_OVERRIDER_P (fndecl) = 1;
/* Make sure we search for it later. */
if (! CLASSTYPE_ABSTRACT_VIRTUALS (t))
@@ -2832,18 +2785,18 @@ get_basefndecls (fndecl, t)
/* 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. */
+ no need to mark functions that are just hidden.
+
+ Subroutine of warn_hidden. */
static void
mark_overriders (fndecl, base_fndecls)
tree fndecl, base_fndecls;
{
- while (base_fndecls)
+ for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls))
{
- if (overrides (TREE_VALUE (base_fndecls), fndecl))
+ if (overrides (fndecl, TREE_VALUE (base_fndecls)))
TREE_PURPOSE (base_fndecls) = fndecl;
-
- base_fndecls = TREE_CHAIN (base_fndecls);
}
}
@@ -2858,17 +2811,18 @@ check_for_override (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);
+ int found_overriden_fn = 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)
+ if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo)))
{
tree tmp = get_matching_virtual
(base_binfo, decl,
DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
- if (tmp)
+
+ if (tmp && !found_overriden_fn)
{
/* If this function overrides some virtual in some base
class, then the function itself is also necessarily
@@ -2889,26 +2843,15 @@ check_for_override (decl, ctype)
}
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;
+
+ /* We now know that DECL overrides something,
+ which is all that is important. But, we must
+ continue to iterate through all the base-classes
+ in order to allow get_matching_virtual to check for
+ various illegal overrides. */
+ found_overriden_fn = 1;
}
}
}
@@ -2932,7 +2875,7 @@ warn_hidden (t)
int i;
/* We go through each separately named virtual function. */
- for (i = 2; i < n_methods; ++i)
+ for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); ++i)
{
tree fns = TREE_VEC_ELT (method_vec, i);
tree fndecl;
@@ -2941,8 +2884,15 @@ warn_hidden (t)
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)
+ /* First see if we have any virtual functions in this batch. */
+ for (; fns; fns = OVL_NEXT (fns))
+ {
+ fndecl = OVL_CURRENT (fns);
+ if (DECL_VINDEX (fndecl))
+ break;
+ }
+
+ if (fns == NULL_TREE)
continue;
/* First we get a list of all possible functions that might be
@@ -2957,38 +2907,28 @@ warn_hidden (t)
}
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)
+ for (; fns; fns = OVL_NEXT (fns))
{
- mark_overriders (fndecl, base_fndecls);
-
- fns = OVL_NEXT (fns);
- if (fns)
- fndecl = OVL_CURRENT (fns);
- else
- fndecl = NULL_TREE;
+ fndecl = OVL_CURRENT (fns);
+ if (DECL_VINDEX (fndecl))
+ mark_overriders (fndecl, base_fndecls);
}
/* Now give a warning for all base functions without overriders,
as they are hidden. */
- while (base_fndecls)
+ for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls))
{
- if (! overrides (TREE_VALUE (base_fndecls),
- TREE_PURPOSE (base_fndecls)))
+ if (! overrides (TREE_PURPOSE (base_fndecls),
+ TREE_VALUE (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);
}
}
}
@@ -3014,9 +2954,20 @@ finish_struct_anon (t)
tree* uelt = &TYPE_FIELDS (TREE_TYPE (field));
for (; *uelt; uelt = &TREE_CHAIN (*uelt))
{
- if (TREE_CODE (*uelt) != FIELD_DECL)
+ if (DECL_ARTIFICIAL (*uelt))
continue;
+ if (DECL_NAME (*uelt) == constructor_name (t))
+ cp_pedwarn_at ("ANSI C++ forbids member `%D' with same name as enclosing class",
+ *uelt);
+
+ if (TREE_CODE (*uelt) != FIELD_DECL)
+ {
+ cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members",
+ *uelt);
+ continue;
+ }
+
if (TREE_PRIVATE (*uelt))
cp_pedwarn_at ("private member `%#D' in anonymous union",
*uelt);
@@ -3033,6 +2984,90 @@ finish_struct_anon (t)
extern int interface_only, interface_unknown;
+/* Create default constructors, assignment operators, and so forth for
+ the type indicated by T, if they are needed.
+ CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and
+ CANT_HAVE_ASSIGNMENT are nonzero if, for whatever reason, the class
+ cannot have a default constructor, copy constructor taking a const
+ reference argument, or an assignment operator, respectively. If a
+ virtual destructor is created, its DECL is returned; otherwise the
+ return value is NULL_TREE. */
+
+static tree
+add_implicitly_declared_members (t, cant_have_default_ctor,
+ cant_have_const_cctor,
+ cant_have_assignment)
+ tree t;
+ int cant_have_default_ctor;
+ int cant_have_const_cctor;
+ int cant_have_assignment;
+{
+ tree default_fn;
+ tree implicit_fns = NULL_TREE;
+ tree name = TYPE_IDENTIFIER (t);
+ tree virtual_dtor = NULL_TREE;
+ tree *f;
+
+ /* Destructor. */
+ if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t)
+ && !IS_SIGNATURE (t))
+ {
+ default_fn = cons_up_default_function (t, name, 0);
+ check_for_override (default_fn, t);
+
+ /* If we couldn't make it work, then pretend we didn't need it. */
+ if (default_fn == void_type_node)
+ TYPE_NEEDS_DESTRUCTOR (t) = 0;
+ else
+ {
+ TREE_CHAIN (default_fn) = implicit_fns;
+ implicit_fns = default_fn;
+
+ if (DECL_VINDEX (default_fn))
+ virtual_dtor = default_fn;
+ }
+ }
+ TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
+
+ /* Default constructor. */
+ if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor
+ && ! IS_SIGNATURE (t))
+ {
+ default_fn = cons_up_default_function (t, name, 2);
+ TREE_CHAIN (default_fn) = implicit_fns;
+ implicit_fns = default_fn;
+ }
+
+ /* Copy constructor. */
+ 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 */
+ default_fn = cons_up_default_function (t, name,
+ 3 + cant_have_const_cctor);
+ TREE_CHAIN (default_fn) = implicit_fns;
+ implicit_fns = default_fn;
+ }
+
+ /* Assignment operator. */
+ if (! TYPE_HAS_ASSIGN_REF (t) && ! IS_SIGNATURE (t) && ! TYPE_FOR_JAVA (t))
+ {
+ default_fn = cons_up_default_function (t, name,
+ 5 + cant_have_assignment);
+ TREE_CHAIN (default_fn) = implicit_fns;
+ implicit_fns = default_fn;
+ }
+
+ /* Now, hook all of the new functions on to TYPE_METHODS,
+ and add them to the CLASSTYPE_METHOD_VEC. */
+ for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
+ add_method (t, 0, *f);
+ *f = TYPE_METHODS (t);
+ TYPE_METHODS (t) = implicit_fns;
+
+ return virtual_dtor;
+}
+
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
@@ -3058,54 +3093,17 @@ extern int interface_only, interface_unknown;
inheritance. Additional virtual function tables have different
DELTAs, which tell how to adjust `this' to point to the right thing.
- LIST_OF_FIELDLISTS is just that. The elements of the list are
- 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.
-
- If flag_all_virtual == 2, then we lay all functions into
- the virtual function table, such that virtual functions
- occupy a space by themselves, and then all functions
- of the class occupy a space by themselves. This is illustrated
- in the following diagram:
-
- class A; class B : A;
-
- Class A's vtbl: Class B's vtbl:
- --------------------------------------------------------------------
- | A's virtual functions| | B's virtual functions |
- | | | (may inherit some from A). |
- --------------------------------------------------------------------
- | All of A's functions | | All of A's functions |
- | (such as a->A::f). | | (such as b->A::f) |
- --------------------------------------------------------------------
- | B's new virtual functions |
- | (not defined in A.) |
- -------------------------------
- | All of B's functions |
- | (such as b->B::f) |
- -------------------------------
-
- this allows the program to make references to any function, virtual
- or otherwise in a type-consistent manner. */
+ ATTRIBUTES is the set of decl attributes to be applied, if any. */
-tree
+void
finish_struct_1 (t, warn_anon)
tree t;
int warn_anon;
{
int old;
- tree name = TYPE_IDENTIFIER (t);
enum tree_code code = TREE_CODE (t);
tree fields = TYPE_FIELDS (t);
- tree fn_fields = TYPE_METHODS (t);
tree x, last_x, method_vec;
- int all_virtual;
int has_virtual;
int max_has_virtual;
tree pending_virtuals = NULL_TREE;
@@ -3113,9 +3111,11 @@ finish_struct_1 (t, warn_anon)
tree abstract_virtuals = NULL_TREE;
tree vfield;
tree vfields;
+ tree virtual_dtor;
int cant_have_default_ctor;
int cant_have_const_ctor;
int no_const_asn_ref;
+ int has_mutable = 0;
/* The index of the first base class which has virtual
functions. Only applied to non-virtual baseclasses. */
@@ -3125,11 +3125,11 @@ finish_struct_1 (t, warn_anon)
int any_default_members = 0;
int const_sans_init = 0;
int ref_sans_init = 0;
- int nonprivate_method = 0;
tree access_decls = NULL_TREE;
int aggregate = 1;
int empty = 1;
int has_pointers = 0;
+ tree inline_friends;
if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
pedwarn ("anonymous class type not used to declare any objects");
@@ -3140,8 +3140,8 @@ finish_struct_1 (t, warn_anon)
cp_error ("redefinition of `%#T'", t);
else
my_friendly_abort (172);
- popclass (0);
- return t;
+ popclass ();
+ return;
}
GNU_xref_decl (current_function_decl, t);
@@ -3185,7 +3185,6 @@ finish_struct_1 (t, warn_anon)
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;
@@ -3223,25 +3222,14 @@ finish_struct_1 (t, warn_anon)
CLASSTYPE_VFIELDS (t) = vfields;
CLASSTYPE_VFIELD (t) = vfield;
- if (IS_SIGNATURE (t))
- all_virtual = 0;
- else if (flag_all_virtual == 1)
- all_virtual = 1;
- else
- all_virtual = 0;
-
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
GNU_xref_member (current_class_name, x);
- nonprivate_method |= ! TREE_PRIVATE (x);
-
/* If this was an evil function, don't keep it in class. */
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
continue;
- DECL_CLASS_CONTEXT (x) = t;
-
/* Do both of these, even though they're in the same union;
if the insn `r' member and the size `i' member are
different sizes, as on the alpha, the larger of the two
@@ -3255,8 +3243,7 @@ finish_struct_1 (t, warn_anon)
/* 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)))
+ if (DECL_VINDEX (x))
{
add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
&has_virtual, x, t);
@@ -3281,7 +3268,11 @@ finish_struct_1 (t, warn_anon)
if (TREE_CODE (x) == FIELD_DECL)
{
DECL_PACKED (x) |= TYPE_PACKED (t);
- empty = 0;
+
+ if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
+ /* A zero-width bitfield doesn't do the trick. */;
+ else
+ empty = 0;
}
if (TREE_CODE (x) == USING_DECL)
@@ -3387,8 +3378,11 @@ finish_struct_1 (t, warn_anon)
if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE)
has_pointers = 1;
+ if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (TREE_TYPE (x)))
+ has_mutable = 1;
+
/* If any field is const, the structure type is pseudo-const. */
- if (TREE_READONLY (x))
+ if (CP_TYPE_CONST_P (TREE_TYPE (x)))
{
C_TYPE_FIELDS_READONLY (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
@@ -3426,12 +3420,10 @@ finish_struct_1 (t, warn_anon)
}
}
- /* We set DECL_BIT_FIELD tentatively in grokbitfield.
- If the type and width are valid, we'll keep it set.
- Otherwise, the flag is cleared. */
- if (DECL_BIT_FIELD (x))
+ /* We set DECL_C_BIT_FIELD in grokbitfield.
+ If the type and width are valid, we'll also set DECL_BIT_FIELD. */
+ if (DECL_C_BIT_FIELD (x))
{
- DECL_BIT_FIELD (x) = 0;
/* Invalid bit-field size done by grokfield. */
/* Detect invalid bit-field type. */
if (DECL_INITIAL (x)
@@ -3499,23 +3491,24 @@ finish_struct_1 (t, warn_anon)
x, TREE_TYPE (x));
}
- if (DECL_INITIAL (x) == NULL_TREE)
- ;
- else if (width == 0)
+ if (DECL_INITIAL (x))
{
+ DECL_INITIAL (x) = NULL_TREE;
+ DECL_FIELD_SIZE (x) = width;
+ DECL_BIT_FIELD (x) = 1;
+
+ if (width == 0)
+ {
#ifdef EMPTY_FIELD_BOUNDARY
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x), 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),
- TYPE_ALIGN (TREE_TYPE (x)));
+ if (PCC_BITFIELD_TYPE_MATTERS)
+ DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
+ TYPE_ALIGN (TREE_TYPE (x)));
#endif
- }
- else
- {
- DECL_INITIAL (x) = NULL_TREE;
- DECL_FIELD_SIZE (x) = width;
- DECL_BIT_FIELD (x) = 1;
+ }
}
}
else
@@ -3543,7 +3536,7 @@ finish_struct_1 (t, warn_anon)
if (code == UNION_TYPE)
{
- char *fie = NULL;
+ const char *fie = NULL;
if (TYPE_NEEDS_CONSTRUCTING (type))
fie = "constructor";
else if (TYPE_NEEDS_DESTRUCTOR (type))
@@ -3604,36 +3597,7 @@ finish_struct_1 (t, warn_anon)
CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = const_sans_init;
CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init;
CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals;
-
- /* Synthesize any needed methods. Note that methods will be synthesized
- for anonymous unions; grok_x_components undoes that. */
-
- if (! fn_fields)
- nonprivate_method = 1;
-
- if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t)
- && !IS_SIGNATURE (t))
- {
- /* Here we must cons up a destructor on the fly. */
- 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. */
-
- TREE_CHAIN (dtor) = fn_fields;
- fn_fields = dtor;
-
- if (DECL_VINDEX (dtor))
- add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
- &has_virtual, dtor, t);
- nonprivate_method = 1;
- }
- }
+ CLASSTYPE_HAS_MUTABLE (t) = has_mutable;
/* Effective C++ rule 11. */
if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t)
@@ -3650,9 +3614,9 @@ finish_struct_1 (t, warn_anon)
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);
-
+
+ /* Do some bookkeeping that will guide the generation of implicitly
+ declared member functions. */
TYPE_HAS_COMPLEX_INIT_REF (t)
|= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
|| has_virtual || any_default_members);
@@ -3662,68 +3626,24 @@ finish_struct_1 (t, warn_anon)
if (! IS_SIGNATURE (t))
CLASSTYPE_NON_AGGREGATE (t)
= ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t);
-
- /* ARM $12.1: A default constructor will be generated for a class X
- only if no constructor has been declared for class X. So we
- check TYPE_HAS_CONSTRUCTOR also, to make sure we don't generate
- one if they declared a constructor in this class. */
- if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor
- && ! IS_SIGNATURE (t))
- {
- tree default_fn = cons_up_default_function (t, name, 2);
- TREE_CHAIN (default_fn) = fn_fields;
- fn_fields = default_fn;
- }
-
- /* Create default copy constructor, if needed. */
- 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 */
- tree default_fn = cons_up_default_function (t, name,
- 3 + cant_have_const_ctor);
- TREE_CHAIN (default_fn) = fn_fields;
- fn_fields = default_fn;
- }
-
- TYPE_HAS_REAL_ASSIGNMENT (t) |= TYPE_HAS_ASSIGNMENT (t);
TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (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);
- TREE_CHAIN (default_fn) = fn_fields;
- fn_fields = default_fn;
- }
+ /* Synthesize any needed methods. Note that methods will be synthesized
+ for anonymous unions; grok_x_components undoes that. */
+ virtual_dtor
+ = add_implicitly_declared_members (t, cant_have_default_ctor,
+ cant_have_const_ctor,
+ no_const_asn_ref);
+ if (virtual_dtor)
+ add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
+ &has_virtual, virtual_dtor, t);
- if (fn_fields)
+ if (TYPE_METHODS (t))
{
- 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_MAIN_DECL (t)) == NULL_TREE)
- {
- int nonprivate_ctor = 0;
- tree ctor;
-
- for (ctor = TREE_VEC_ELT (method_vec, 0);
- ctor;
- ctor = OVL_NEXT (ctor))
- if (! TREE_PRIVATE (OVL_CURRENT (ctor)))
- {
- nonprivate_ctor = 1;
- break;
- }
-
- if (nonprivate_ctor == 0 && warn_ctor_dtor_privacy)
- cp_warning ("`%#T' only defines private constructors and has no friends",
- t);
- }
+ finish_struct_methods (t);
+ method_vec = CLASSTYPE_METHOD_VEC (t);
}
else
{
@@ -3741,10 +3661,27 @@ finish_struct_1 (t, warn_anon)
if (vfield == NULL_TREE && has_virtual)
{
- /* We build this decl with ptr_type_node, and
- change the type when we know what it should be. */
+ /* We build this decl with vtbl_ptr_type_node, which is a
+ `vtable_entry_type*'. It might seem more precise to use
+ `vtable_entry_type (*)[N]' where N is the number of firtual
+ functions. However, that would require the vtable pointer in
+ base classes to have a different type than the vtable pointer
+ in derived classes. We could make that happen, but that
+ still wouldn't solve all the problems. In particular, the
+ type-based alias analysis code would decide that assignments
+ to the base class vtable pointer can't alias assignments to
+ the derived class vtable pointer, since they have different
+ types. Thus, in an derived class destructor, where the base
+ class constructor was inlined, we could generate bad code for
+ setting up the vtable pointer.
+
+ Therefore, we use one type for all vtable pointers. We still
+ use a type-correct type; it's just doesn't indicate the array
+ bounds. That's better than using `void*' or some such; it's
+ cleaner, and it let's the alias analysis code know that these
+ stores cannot alias stores to void*! */
vfield = build_lang_field_decl (FIELD_DECL, get_vfield_name (t),
- ptr_type_node);
+ vtbl_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. */
@@ -3776,57 +3713,17 @@ finish_struct_1 (t, warn_anon)
fields = vfield;
#endif
empty = 0;
- vfields = chainon (vfields, CLASSTYPE_AS_LIST (t));
+ vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
}
/* Now DECL_INITIAL is null on all members except for zero-width bit-fields.
- And they have already done their work.
C++: maybe we will support default field initialization some day... */
- /* Delete all zero-width bit-fields from the front of the fieldlist */
- while (fields && DECL_BIT_FIELD (fields)
- && DECL_INITIAL (fields))
- fields = TREE_CHAIN (fields);
- /* Delete all such fields from the rest of the fields. */
- for (x = fields; x;)
- {
- if (TREE_CHAIN (x) && DECL_BIT_FIELD (TREE_CHAIN (x))
- && DECL_INITIAL (TREE_CHAIN (x)))
- TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
- else
- x = TREE_CHAIN (x);
- }
/* Delete all duplicate fields from the fields */
delete_duplicate_fields (fields);
- /* Catch function/field name conflict. We don't need to do this for a
- signature, since it can only contain the fields constructed in
- append_signature_fields. */
- if (! IS_SIGNATURE (t))
- {
- int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
- for (x = fields; x; x = TREE_CHAIN (x))
- {
- tree name = DECL_NAME (x);
- int i = 2;
-
- if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))
- continue;
-
- for (; i < n_methods; ++i)
- 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'",
- OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
- break;
- }
- }
- }
-
- /* Now we have the final fieldlist for the data fields. Record it,
+ /* Now we have the nearly final fieldlist for the data fields. Record it,
then lay out the structure or union (including the fields). */
TYPE_FIELDS (t) = fields;
@@ -3840,6 +3737,13 @@ finish_struct_1 (t, warn_anon)
if (DECL_SIZE (x) != integer_zero_node)
empty = 0;
}
+
+ /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
+ we have to save this before we start modifying
+ TYPE_NONCOPIED_PARTS. */
+ inline_friends = CLASSTYPE_INLINE_FRIENDS (t);
+ CLASSTYPE_INLINE_FRIENDS (t) = NULL_TREE;
+
if (empty)
{
/* C++: do not let empty structures exist. */
@@ -3847,7 +3751,11 @@ finish_struct_1 (t, warn_anon)
(FIELD_DECL, NULL_TREE, char_type_node);
TREE_CHAIN (decl) = fields;
TYPE_FIELDS (t) = decl;
+ TYPE_NONCOPIED_PARTS (t)
+ = tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t));
+ TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
}
+
if (n_baseclasses)
TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t));
@@ -3880,15 +3788,31 @@ finish_struct_1 (t, warn_anon)
if (n_baseclasses)
/* layout_basetypes will remove the base subobject fields. */
max_has_virtual = layout_basetypes (t, max_has_virtual);
- else if (empty)
+ if (empty)
TYPE_FIELDS (t) = fields;
+ my_friendly_assert (TYPE_FIELDS (t) == fields, 981117);
+
+ /* Delete all zero-width bit-fields from the front of the fieldlist */
+ while (fields && DECL_C_BIT_FIELD (fields)
+ && DECL_INITIAL (fields))
+ fields = TREE_CHAIN (fields);
+ /* Delete all such fields from the rest of the fields. */
+ for (x = fields; x;)
+ {
+ if (TREE_CHAIN (x) && DECL_C_BIT_FIELD (TREE_CHAIN (x))
+ && DECL_INITIAL (TREE_CHAIN (x)))
+ TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
+ else
+ x = TREE_CHAIN (x);
+ }
+ TYPE_FIELDS (t) = fields;
+
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{
tree vbases;
vbases = CLASSTYPE_VBASECLASSES (t);
- CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases);
{
/* Now fixup overrides of all functions in vtables from all
@@ -3983,15 +3907,18 @@ finish_struct_1 (t, warn_anon)
/* We must enter these virtuals into the table. */
if (first_vfn_base_index < 0)
{
- /* 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);
+ if (! CLASSTYPE_COM_INTERFACE (t))
+ {
+ /* 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);
- /* The first slot is for the rtti offset. */
- pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
+ /* 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);
+ set_rtti_entry (pending_virtuals,
+ convert (ssizetype, integer_zero_node), t);
+ }
build_vtable (NULL_TREE, t);
}
else
@@ -4040,46 +3967,22 @@ finish_struct_1 (t, warn_anon)
else if (has_virtual)
{
TYPE_BINFO_VIRTUALS (t) = pending_virtuals;
- if (write_virtuals >= 0)
- DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)) = 1;
+ DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)) = 1;
}
}
/* Now lay out the virtual function table. */
if (has_virtual)
{
- tree atype, itype;
+ /* Use size_int so values are memoized in common cases. */
+ tree itype = build_index_type (size_int (has_virtual));
+ tree atype = build_cplus_array_type (vtable_entry_type, itype);
- if (TREE_TYPE (vfield) == ptr_type_node)
- {
- /* We must create a pointer to this table because
- the one inherited from base class does not exist.
- We will fill in the type when we know what it
- should really be. Use `size_int' so values are memoized
- in common cases. */
- itype = build_index_type (size_int (has_virtual));
- atype = build_array_type (vtable_entry_type, itype);
- layout_type (atype);
- TREE_TYPE (vfield) = build_pointer_type (atype);
- }
- else
- {
- atype = TREE_TYPE (TREE_TYPE (vfield));
-
- if (has_virtual != TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (atype))))
- {
- /* We must extend (or create) the boundaries on this array,
- because we picked up virtual functions from multiple
- base classes. */
- itype = build_index_type (size_int (has_virtual));
- atype = build_array_type (vtable_entry_type, itype);
- layout_type (atype);
- vfield = copy_node (vfield);
- TREE_TYPE (vfield) = build_pointer_type (atype);
- }
- }
+ layout_type (atype);
CLASSTYPE_VFIELD (t) = vfield;
+
+ /* We may have to grow the vtable. */
if (TREE_TYPE (TYPE_BINFO_VTABLE (t)) != atype)
{
TREE_TYPE (TYPE_BINFO_VTABLE (t)) = atype;
@@ -4123,15 +4026,10 @@ finish_struct_1 (t, warn_anon)
TREE_ADDRESSABLE (vfields) = 1;
vfields = TREE_CHAIN (vfields);
}
- if (any_default_members != 0)
- build_class_init_list (t);
}
- else if (TYPE_NEEDS_CONSTRUCTING (t))
- build_class_init_list (t);
/* Write out inline function definitions. */
- do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t));
- CLASSTYPE_INLINE_FRIENDS (t) = 0;
+ do_inline_function_hair (t, inline_friends);
if (CLASSTYPE_VSIZE (t) != 0)
{
@@ -4158,7 +4056,9 @@ finish_struct_1 (t, warn_anon)
/* 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);
+ TYPE_NONCOPIED_PARTS (t)
+ = tree_cons (default_conversion (TYPE_BINFO_VTABLE (t)),
+ vfield, TYPE_NONCOPIED_PARTS (t));
if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
&& DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE)
@@ -4207,14 +4107,9 @@ finish_struct_1 (t, warn_anon)
references between translation units. */
if (CLASSTYPE_METHOD_VEC (t))
{
- extern tree pending_vtables;
-
/* 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_MAIN_DECL (t))
- = (value_member (TYPE_IDENTIFIER (t), pending_vtables) == 0);
- else if (CLASSTYPE_INTERFACE_ONLY (t))
+ if (CLASSTYPE_INTERFACE_ONLY (t))
TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
#if 0
/* XXX do something about this. */
@@ -4230,23 +4125,50 @@ finish_struct_1 (t, warn_anon)
/* Finish debugging output for this type. */
rest_of_type_compilation (t, toplevel_bindings_p ());
- return t;
+ return;
+}
+
+/* When T was built up, the member declarations were added in reverse
+ order. Rearrange them to declaration order. */
+
+void
+unreverse_member_declarations (t)
+ tree t;
+{
+ tree next;
+ tree prev;
+ tree x;
+
+ /* The TYPE_FIELDS, TYPE_METHODS, and CLASSTYPE_TAGS are all in
+ reverse order. Put them in declaration order now. */
+ TYPE_METHODS (t) = nreverse (TYPE_METHODS (t));
+ CLASSTYPE_TAGS (t) = nreverse (CLASSTYPE_TAGS (t));
+
+ /* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in
+ reverse order, so we can't just use nreverse. */
+ prev = NULL_TREE;
+ for (x = TYPE_FIELDS (t);
+ x && TREE_CODE (x) != TYPE_DECL;
+ x = next)
+ {
+ next = TREE_CHAIN (x);
+ TREE_CHAIN (x) = prev;
+ prev = x;
+ }
+ if (prev)
+ {
+ TREE_CHAIN (TYPE_FIELDS (t)) = x;
+ if (prev)
+ TYPE_FIELDS (t) = prev;
+ }
}
tree
-finish_struct (t, list_of_fieldlists, attributes, warn_anon)
- tree t, list_of_fieldlists, attributes;
+finish_struct (t, attributes, warn_anon)
+ tree t, attributes;
int warn_anon;
{
- 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;
- tree access;
- tree dummy = NULL_TREE;
- tree next_x = NULL_TREE;
if (TREE_CODE (name) == TYPE_DECL)
{
@@ -4260,166 +4182,16 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
will fill in the right line number. (mrs) */
if (DECL_SOURCE_LINE (name))
DECL_SOURCE_LINE (name) = lineno;
- CLASSTYPE_SOURCE_LINE (t) = lineno;
name = DECL_NAME (name);
}
/* Append the fields we need for constructing signature tables. */
if (IS_SIGNATURE (t))
- append_signature_fields (list_of_fieldlists);
-
- /* 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)))
- {
- dummy = TREE_VALUE (list_of_fieldlists);
- list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
- }
-
- if (last_x && list_of_fieldlists)
- TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
-
- while (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 = next_x)
- {
- 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.
-
- Enums, types and static vars have already been checked. */
- 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);
- tree icv;
-
- /* Don't get confused by access decls. */
- if (name && TREE_CODE (name) == IDENTIFIER_NODE)
- icv = IDENTIFIER_CLASS_VALUE (name);
- else
- icv = NULL_TREE;
-
- if (icv
- && flag_optional_diags
- /* Don't complain about constructors. */
- && name != constructor_name (current_class_type)
- /* Or inherited names. */
- && id_in_current_class (name)
- /* Or shadowed tags. */
- && !(TREE_CODE (icv) == TYPE_DECL
- && DECL_CONTEXT (icv) == t))
- {
- cp_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
- || DECL_FUNCTION_TEMPLATE_P (x))
- {
- DECL_CLASS_CONTEXT (x) = t;
-
- if (last_x)
- 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);
- continue;
- }
+ append_signature_fields (t);
- if (TREE_CODE (x) != TYPE_DECL)
- DECL_FIELD_CONTEXT (x) = t;
-
- if (! fields)
- fields = x;
- last_x = x;
- }
- list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
- /* link the tail while we have it! */
- if (last_x)
- {
- TREE_CHAIN (last_x) = NULL_TREE;
-
- if (list_of_fieldlists
- && TREE_VALUE (list_of_fieldlists)
- && TREE_CODE (TREE_VALUE (list_of_fieldlists)) != FUNCTION_DECL)
- TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
- }
- }
-
- /* 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;
- TYPE_FIELDS (t) = fields;
+ /* Now that we've got all the field declarations, reverse everything
+ as necessary. */
+ unreverse_member_declarations (t);
cplus_decl_attributes (t, attributes, NULL_TREE);
@@ -4443,80 +4215,31 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
= tree_cons (NULL_TREE, d,
DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t)));
}
- CLASSTYPE_METHOD_VEC (t)
- = finish_struct_methods (t, TYPE_METHODS (t), 1);
+ finish_struct_methods (t);
TYPE_SIZE (t) = integer_zero_node;
}
else
- t = finish_struct_1 (t, warn_anon);
+ 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);
+ popclass ();
else
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.
+/* Return the dynamic type of INSTANCE, if known.
Used to determine whether the virtual function table is needed
or not.
*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)
+static tree
+fixed_type_or_null (instance, nonnull)
tree instance;
int *nonnull;
{
@@ -4534,9 +4257,9 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
- return 1;
+ return TREE_TYPE (instance);
}
- return 0;
+ return NULL_TREE;
case SAVE_EXPR:
/* This is a call to a constructor, hence it's never zero. */
@@ -4544,33 +4267,33 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
- return 1;
+ return TREE_TYPE (instance);
}
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
case RTL_EXPR:
- return 0;
+ return NULL_TREE;
case PLUS_EXPR:
case MINUS_EXPR:
if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
/* Propagate nonnull. */
- resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
+ fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
- return 0;
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
+ return NULL_TREE;
case NOP_EXPR:
case CONVERT_EXPR:
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
case ADDR_EXPR:
if (nonnull)
*nonnull = 1;
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
case COMPONENT_REF:
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 1), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull);
case VAR_DECL:
case FIELD_DECL:
@@ -4579,7 +4302,7 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
- return 1;
+ return TREE_TYPE (TREE_TYPE (instance));
}
/* fall through... */
case TARGET_EXPR:
@@ -4588,37 +4311,65 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
- return 1;
+ return TREE_TYPE (instance);
}
else if (nonnull)
{
if (instance == current_class_ptr
&& flag_this_is_variable <= 0)
{
- /* Some people still use `this = 0' inside destructors. */
- *nonnull = ! DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (current_function_decl));
- /* In a constructor, we know our type. */
+ /* Normally, 'this' must be non-null. */
+ if (flag_this_is_variable == 0)
+ *nonnull = 1;
+
+ /* <0 means we're in a constructor and we know our type. */
if (flag_this_is_variable < 0)
- return 1;
+ return TREE_TYPE (TREE_TYPE (instance));
}
else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
/* Reference variables should be references to objects. */
*nonnull = 1;
}
- return 0;
+ return NULL_TREE;
default:
- return 0;
+ return NULL_TREE;
}
}
+
+/* Return non-zero if the dynamic type of INSTANCE is known, and equivalent
+ to the static type. We also handle the case where INSTANCE is really
+ a pointer.
+
+ Used to determine whether the virtual function table is needed
+ or not.
+
+ *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;
+ int *nonnull;
+{
+ tree t = TREE_TYPE (instance);
+ tree fixed = fixed_type_or_null (instance, nonnull);
+ if (fixed == NULL_TREE)
+ return 0;
+ if (POINTER_TYPE_P (t))
+ t = TREE_TYPE (t);
+ return same_type_p (TYPE_MAIN_VARIANT (t), TYPE_MAIN_VARIANT (fixed));
+}
+
void
init_class_processing ()
{
current_class_depth = 0;
- current_class_stacksize = 10;
- current_class_base = (tree *)xmalloc(current_class_stacksize * sizeof (tree));
- current_class_stack = current_class_base;
+ current_class_stack_size = 10;
+ current_class_stack
+ = (class_stack_node_t) xmalloc (current_class_stack_size
+ * sizeof (struct class_stack_node));
current_lang_stacksize = 10;
current_lang_base = (tree *)xmalloc(current_lang_stacksize * sizeof (tree));
@@ -4680,34 +4431,56 @@ pushclass (type, modify)
int modify;
{
type = TYPE_MAIN_VARIANT (type);
- push_memoized_context (type, modify);
- current_class_depth++;
- *current_class_stack++ = current_class_name;
- *current_class_stack++ = current_class_type;
- if (current_class_stack >= current_class_base + current_class_stacksize)
+ /* Make sure there is enough room for the new entry on the stack. */
+ if (current_class_depth + 1 >= current_class_stack_size)
{
- 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;
+ current_class_stack_size *= 2;
+ current_class_stack
+ = (class_stack_node_t) xrealloc (current_class_stack,
+ current_class_stack_size
+ * sizeof (struct class_stack_node));
}
+ /* Insert a new entry on the class stack. */
+ current_class_stack[current_class_depth].name = current_class_name;
+ current_class_stack[current_class_depth].type = current_class_type;
+ current_class_stack[current_class_depth].access = current_access_specifier;
+ current_class_stack[current_class_depth].names_used = 0;
+ current_class_depth++;
+
+ /* Now set up the new type. */
current_class_name = TYPE_NAME (type);
if (TREE_CODE (current_class_name) == TYPE_DECL)
current_class_name = DECL_NAME (current_class_name);
current_class_type = type;
+ /* By default, things in classes are private, while things in
+ structures or unions are public. */
+ current_access_specifier = (CLASSTYPE_DECLARED_CLASS (type)
+ ? access_private_node
+ : access_public_node);
+
if (previous_class_type != NULL_TREE
- && (type != previous_class_type || TYPE_SIZE (previous_class_type) == NULL_TREE)
+ && (type != previous_class_type
+ || TYPE_SIZE (previous_class_type) == NULL_TREE)
&& current_class_depth == 1)
{
/* Forcibly remove any old class remnants. */
- popclass (-1);
- previous_class_type = NULL_TREE;
+ invalidate_class_lookup_cache ();
+
+ /* Now, free the obstack on which we cached all the values. */
+ if (class_cache_firstobj)
+ obstack_free (&class_cache_obstack, class_cache_firstobj);
+ class_cache_firstobj
+ = (char*) obstack_finish (&class_cache_obstack);
}
+ /* If we're about to enter a nested class, clear
+ IDENTIFIER_CLASS_VALUE for the enclosing classes. */
+ if (modify && current_class_depth > 1)
+ clear_identifier_class_values ();
+
pushlevel_class ();
#if 0
@@ -4717,122 +4490,70 @@ pushclass (type, modify)
if (modify)
{
- tree tags;
- tree this_fndecl = current_function_decl;
-
- if (current_function_decl
- && DECL_CONTEXT (current_function_decl)
- && TREE_CODE (DECL_CONTEXT (current_function_decl)) == FUNCTION_DECL)
- current_function_decl = DECL_CONTEXT (current_function_decl);
- else
- current_function_decl = NULL_TREE;
-
if (type != previous_class_type || current_class_depth > 1)
- {
-#ifdef MI_MATRIX
- build_mi_matrix (type);
- push_class_decls (type);
- free_mi_matrix ();
-#else
- push_class_decls (type);
-#endif
- }
+ push_class_decls (type);
else
{
tree item;
- /* Hooray, we successfully cached; let's just install the
- cached class_shadowed list, and walk through it to get the
- IDENTIFIER_TYPE_VALUEs correct. */
+ /* We are re-entering the same class we just left, so we
+ don't have to search the whole inheritance matrix to find
+ all the decls to bind again. Instead, we install the
+ cached class_shadowed list, and walk through it binding
+ names and setting up IDENTIFIER_TYPE_VALUEs. */
set_class_shadows (previous_class_values);
for (item = previous_class_values; item; item = TREE_CHAIN (item))
{
tree id = TREE_PURPOSE (item);
- tree decl = IDENTIFIER_CLASS_VALUE (id);
+ tree decl = TREE_TYPE (item);
+ push_class_binding (id, decl);
if (TREE_CODE (decl) == TYPE_DECL)
set_identifier_type_value (id, TREE_TYPE (decl));
}
unuse_fields (type);
}
- for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags))
- {
- tree tag_type = TREE_VALUE (tags);
+ storetags (CLASSTYPE_TAGS (type));
+ }
+}
- TREE_NONLOCAL_FLAG (tag_type) = 1;
- if (! TREE_PURPOSE (tags))
- continue;
- 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));
- }
+/* When we exit a toplevel class scope, we save the
+ IDENTIFIER_CLASS_VALUEs so that we can restore them quickly if we
+ reenter the class. Here, we've entered some other class, so we
+ must invalidate our cache. */
- current_function_decl = this_fndecl;
- }
+void
+invalidate_class_lookup_cache ()
+{
+ tree t;
+
+ /* This code can be seen as a cache miss. When we've cached a
+ class' scope's bindings and we can't use them, we need to reset
+ them. This is it! */
+ for (t = previous_class_values; t; t = TREE_CHAIN (t))
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
+
+ previous_class_type = NULL_TREE;
}
/* 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. */
+ previously, that is the one popped to. */
void
-popclass (modify)
- int modify;
+popclass ()
{
- if (modify < 0)
- {
- /* Back this old class out completely. */
- tree tags = CLASSTYPE_TAGS (previous_class_type);
- tree t;
-
- /* This code can be seen as a cache miss. When we've cached a
- class' scope's bindings and we can't use them, we need to reset
- them. This is it! */
- for (t = previous_class_values; t; t = TREE_CHAIN (t))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
- while (tags)
- {
- TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
- tags = TREE_CHAIN (tags);
- }
- goto ret;
- }
-
- if (modify)
- {
- /* Just remove from this class what didn't make
- it into IDENTIFIER_CLASS_VALUE. */
- tree tags = CLASSTYPE_TAGS (current_class_type);
-
- while (tags)
- {
- TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
- tags = TREE_CHAIN (tags);
- }
- }
-
- /* Force clearing of IDENTIFIER_CLASS_VALUEs after a class definition,
- since not all class decls make it there currently. */
- poplevel_class (! modify);
-
+ poplevel (1, 0, 0);
/* Since poplevel_class does the popping of class decls nowadays,
- 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 ();
+ this really only frees the obstack used for these decls. */
+ pop_class_decls ();
current_class_depth--;
- current_class_type = *--current_class_stack;
- current_class_name = *--current_class_stack;
-
- pop_memoized_context (modify);
-
- ret:
- ;
+ current_class_name = current_class_stack[current_class_depth].name;
+ current_class_type = current_class_stack[current_class_depth].type;
+ current_access_specifier = current_class_stack[current_class_depth].access;
+ if (current_class_stack[current_class_depth].names_used)
+ splay_tree_delete (current_class_stack[current_class_depth].names_used);
}
/* Returns 1 if current_class_type is either T or a nested type of T. */
@@ -4845,7 +4566,7 @@ currently_open_class (t)
if (t == current_class_type)
return 1;
for (i = 0; i < current_class_depth; ++i)
- if (current_class_stack [-i*2 - 1] == t)
+ if (current_class_stack [i].type == t)
return 1;
return 0;
}
@@ -4864,16 +4585,16 @@ push_nested_class (type, modify)
{
tree context;
- my_friendly_assert (!type || TREE_CODE (type) != NAMESPACE_DECL, 980711);
-
+ /* A namespace might be passed in error cases, like A::B:C. */
if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type)
+ || TREE_CODE (type) == NAMESPACE_DECL
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
return;
context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
- if (context && TREE_CODE (context) == RECORD_TYPE)
+ if (context && CLASS_TYPE_P (context))
push_nested_class (context, 2);
pushclass (type, modify);
}
@@ -4881,14 +4602,13 @@ push_nested_class (type, modify)
/* Undoes a push_nested_class call. MODIFY is passed on to popclass. */
void
-pop_nested_class (modify)
- int modify;
+pop_nested_class ()
{
tree context = DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type));
- popclass (modify);
- if (context && TREE_CODE (context) == RECORD_TYPE)
- pop_nested_class (modify);
+ popclass ();
+ if (context && CLASS_TYPE_P (context))
+ pop_nested_class ();
}
/* Set global variables CURRENT_LANG_NAME to appropriate value
@@ -4908,10 +4628,27 @@ push_lang_context (name)
current_lang_stacksize += 10;
}
- if (name == lang_name_cplusplus || name == lang_name_java)
+ if (name == lang_name_cplusplus)
+ {
+ strict_prototype = strict_prototypes_lang_cplusplus;
+ current_lang_name = name;
+ }
+ else if (name == lang_name_java)
{
strict_prototype = strict_prototypes_lang_cplusplus;
current_lang_name = name;
+ /* DECL_IGNORED_P is initially set for these types, to avoid clutter.
+ (See record_builtin_java_type in decl.c.) However, that causes
+ incorrect debug entries if these types are actually used.
+ So we re-enable debug output after extern "Java". */
+ DECL_IGNORED_P (java_byte_type_node) = 0;
+ DECL_IGNORED_P (java_short_type_node) = 0;
+ DECL_IGNORED_P (java_int_type_node) = 0;
+ DECL_IGNORED_P (java_long_type_node) = 0;
+ DECL_IGNORED_P (java_float_type_node) = 0;
+ DECL_IGNORED_P (java_double_type_node) = 0;
+ DECL_IGNORED_P (java_char_type_node) = 0;
+ DECL_IGNORED_P (java_boolean_type_node) = 0;
}
else if (name == lang_name_c)
{
@@ -4937,46 +4674,273 @@ pop_lang_context ()
/* Type instantiation routines. */
+/* Given an OVERLOAD and a TARGET_TYPE, return the function that
+ matches the TARGET_TYPE. If there is no satisfactory match, return
+ error_mark_node, and issue an error message if COMPLAIN is
+ non-zero. If TEMPLATE_ONLY, the name of the overloaded function
+ was a template-id, and EXPLICIT_TARGS are the explicitly provided
+ template arguments. */
+
static tree
-validate_lhs (lhstype, complain)
- tree lhstype;
+resolve_address_of_overloaded_function (target_type,
+ overload,
+ complain,
+ template_only,
+ explicit_targs)
+ tree target_type;
+ tree overload;
int complain;
+ int template_only;
+ tree explicit_targs;
{
- if (TYPE_PTRMEMFUNC_P (lhstype))
- lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
+ /* Here's what the standard says:
+
+ [over.over]
+
+ If the name is a function template, template argument deduction
+ is done, and if the argument deduction succeeds, the deduced
+ arguments are used to generate a single template function, which
+ is added to the set of overloaded functions considered.
+
+ Non-member functions and static member functions match targets of
+ type "pointer-to-function" or "reference-to-function." Nonstatic
+ member functions match targets of type "pointer-to-member
+ function;" the function type of the pointer to member is used to
+ select the member function from the set of overloaded member
+ functions. If a nonstatic member function is selected, the
+ reference to the overloaded function name is required to have the
+ form of a pointer to member as described in 5.3.1.
+
+ If more than one function is selected, any template functions in
+ the set are eliminated if the set also contains a non-template
+ function, and any given template function is eliminated if the
+ set contains a second template function that is more specialized
+ than the first according to the partial ordering rules 14.5.5.2.
+ After such eliminations, if any, there shall remain exactly one
+ selected function. */
+
+ int is_ptrmem = 0;
+ int is_reference = 0;
+ /* We store the matches in a TREE_LIST rooted here. The functions
+ are the TREE_PURPOSE, not the TREE_VALUE, in this list, for easy
+ interoperability with most_specialized_instantiation. */
+ tree matches = NULL_TREE;
+ tree fn;
+
+ /* By the time we get here, we should be seeing only real
+ pointer-to-member types, not the internal POINTER_TYPE to
+ METHOD_TYPE representation. */
+ my_friendly_assert (!(TREE_CODE (target_type) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (target_type))
+ == METHOD_TYPE)), 0);
+
+ /* Check that the TARGET_TYPE is reasonable. */
+ if (TYPE_PTRFN_P (target_type))
+ /* This is OK. */
+ ;
+ else if (TYPE_PTRMEMFUNC_P (target_type))
+ /* This is OK, too. */
+ is_ptrmem = 1;
+ else if (TREE_CODE (target_type) == FUNCTION_TYPE)
+ {
+ /* This is OK, too. This comes from a conversion to reference
+ type. */
+ target_type = build_reference_type (target_type);
+ is_reference = 1;
+ }
+ else
+ {
+ if (complain)
+ cp_error("cannot resolve overloaded function `%D' based on conversion to type `%T'",
+ DECL_NAME (OVL_FUNCTION (overload)), target_type);
+ return error_mark_node;
+ }
+
+ /* If we can find a non-template function that matches, we can just
+ use it. There's no point in generating template instantiations
+ if we're just going to throw them out anyhow. But, of course, we
+ can only do this when we don't *need* a template function. */
+ if (!template_only)
+ {
+ tree fns;
- if (TREE_CODE (lhstype) == POINTER_TYPE)
+ for (fns = overload; fns; fns = OVL_CHAIN (fns))
+ {
+ tree fn = OVL_FUNCTION (fns);
+ tree fntype;
+
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ /* We're not looking for templates just yet. */
+ continue;
+
+ if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+ != is_ptrmem)
+ /* We're looking for a non-static member, and this isn't
+ one, or vice versa. */
+ continue;
+
+ /* See if there's a match. */
+ fntype = TREE_TYPE (fn);
+ if (is_ptrmem)
+ fntype = build_ptrmemfunc_type (build_pointer_type (fntype));
+ else if (!is_reference)
+ fntype = build_pointer_type (fntype);
+
+ if (can_convert_arg (target_type, fntype, fn))
+ matches = scratch_tree_cons (fn, NULL_TREE, matches);
+ }
+ }
+
+ /* Now, if we've already got a match (or matches), there's no need
+ to proceed to the template functions. But, if we don't have a
+ match we need to look at them, too. */
+ if (!matches)
{
- if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
- lhstype = TREE_TYPE (lhstype);
+ tree target_fn_type;
+ tree target_arg_types;
+ tree fns;
+
+ if (is_ptrmem)
+ target_fn_type
+ = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (target_type));
else
+ target_fn_type = TREE_TYPE (target_type);
+ target_arg_types = TYPE_ARG_TYPES (target_fn_type);
+
+ for (fns = overload; fns; fns = OVL_CHAIN (fns))
{
- if (complain)
- error ("invalid type combination for overload");
- return error_mark_node;
+ tree fn = OVL_FUNCTION (fns);
+ tree instantiation;
+ tree instantiation_type;
+ tree targs;
+
+ if (TREE_CODE (fn) != TEMPLATE_DECL)
+ /* We're only looking for templates. */
+ continue;
+
+ if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+ != is_ptrmem)
+ /* We're not looking for a non-static member, and this is
+ one, or vice versa. */
+ continue;
+
+ /* Try to do argument deduction. */
+ targs = make_scratch_vec (DECL_NTPARMS (fn));
+ if (fn_type_unification (fn, explicit_targs, targs,
+ target_arg_types, NULL_TREE,
+ DEDUCE_EXACT) != 0)
+ /* Argument deduction failed. */
+ continue;
+
+ /* Instantiate the template. */
+ instantiation = instantiate_template (fn, targs);
+ if (instantiation == error_mark_node)
+ /* Instantiation failed. */
+ continue;
+
+ /* See if there's a match. */
+ instantiation_type = TREE_TYPE (instantiation);
+ if (is_ptrmem)
+ instantiation_type =
+ build_ptrmemfunc_type (build_pointer_type (instantiation_type));
+ else if (!is_reference)
+ instantiation_type = build_pointer_type (instantiation_type);
+ if (can_convert_arg (target_type, instantiation_type, instantiation))
+ matches = scratch_tree_cons (instantiation, fn, matches);
+ }
+
+ /* Now, remove all but the most specialized of the matches. */
+ if (matches)
+ {
+ tree match = most_specialized_instantiation (matches,
+ explicit_targs);
+
+ if (match != error_mark_node)
+ matches = scratch_tree_cons (match, NULL_TREE, NULL_TREE);
}
}
- return lhstype;
+
+ /* Now we should have exactly one function in MATCHES. */
+ if (matches == NULL_TREE)
+ {
+ /* There were *no* matches. */
+ if (complain)
+ {
+ cp_error ("no matches converting function `%D' to type `%#T'",
+ DECL_NAME (OVL_FUNCTION (overload)),
+ target_type);
+
+ /* print_candidates expects a chain with the functions in
+ TREE_VALUE slots, so we cons one up here (we're losing anyway,
+ so why be clever?). */
+ for (; overload; overload = OVL_NEXT (overload))
+ matches = scratch_tree_cons (NULL_TREE, OVL_CURRENT (overload),
+ matches);
+
+ print_candidates (matches);
+ }
+ return error_mark_node;
+ }
+ else if (TREE_CHAIN (matches))
+ {
+ /* There were too many matches. */
+
+ if (complain)
+ {
+ tree match;
+
+ cp_error ("converting overloaded function `%D' to type `%#T' is ambiguous",
+ DECL_NAME (OVL_FUNCTION (overload)),
+ target_type);
+
+ /* Since print_candidates expects the functions in the
+ TREE_VALUE slot, we flip them here. */
+ for (match = matches; match; match = TREE_CHAIN (match))
+ TREE_VALUE (match) = TREE_PURPOSE (match);
+
+ print_candidates (matches);
+ }
+
+ return error_mark_node;
+ }
+
+ /* Good, exactly one match. Now, convert it to the correct type. */
+ fn = TREE_PURPOSE (matches);
+
+ mark_used (fn);
+
+ if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
+ return build_unary_op (ADDR_EXPR, fn, 0);
+ else
+ {
+ /* The target must be a REFERENCE_TYPE. Above, build_unary_op
+ will mark the function as addressed, but here we must do it
+ explicitly. */
+ mark_addressable (fn);
+
+ return fn;
+ }
}
/* 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
+ error_mark_node. We 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. */
+ FLAGS is a bitmask, as we see at the top of the function.
+
+ For non-recursive calls, LHSTYPE should be a function, pointer to
+ function, or a pointer to member function. */
tree
-instantiate_type (lhstype, rhs, complain)
+instantiate_type (lhstype, rhs, flags)
tree lhstype, rhs;
- int complain;
+ int flags;
{
- tree explicit_targs = NULL_TREE;
- int template_only = 0;
+ int complain = (flags & 1);
+ int strict = (flags & 2) ? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
@@ -4987,7 +4951,7 @@ instantiate_type (lhstype, rhs, complain)
if (TREE_TYPE (rhs) != NULL_TREE && ! (type_unknown_p (rhs)))
{
- if (comptypes (lhstype, TREE_TYPE (rhs), 1))
+ if (comptypes (lhstype, TREE_TYPE (rhs), strict))
return rhs;
if (complain)
cp_error ("argument of type `%T' does not match `%T'",
@@ -5021,7 +4985,7 @@ instantiate_type (lhstype, rhs, complain)
tree new_rhs;
new_rhs = instantiate_type (build_pointer_type (lhstype),
- TREE_OPERAND (rhs, 0), complain);
+ TREE_OPERAND (rhs, 0), flags);
if (new_rhs == error_mark_node)
return error_mark_node;
@@ -5033,312 +4997,71 @@ instantiate_type (lhstype, rhs, complain)
case NOP_EXPR:
rhs = copy_node (TREE_OPERAND (rhs, 0));
TREE_TYPE (rhs) = unknown_type_node;
- return instantiate_type (lhstype, rhs, complain);
+ return instantiate_type (lhstype, rhs, flags);
case COMPONENT_REF:
{
tree field = TREE_OPERAND (rhs, 1);
- if (TREE_CODE (field) == TREE_LIST)
- {
- tree function = instantiate_type (lhstype, field, complain);
- if (function == error_mark_node)
- return error_mark_node;
- my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 185);
- if (DECL_VINDEX (function))
- {
- tree base = TREE_OPERAND (rhs, 0);
- tree base_ptr = build_unary_op (ADDR_EXPR, base, 0);
- if (base_ptr == error_mark_node)
- return error_mark_node;
- base_ptr = convert_pointer_to (DECL_CONTEXT (function), base_ptr);
- if (base_ptr == error_mark_node)
- return error_mark_node;
- return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function));
- }
- mark_used (function);
- return function;
- }
+ tree r;
- /* 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),
- 179);
-
- TREE_TYPE (rhs) = lhstype;
- /* First look for an exact match */
-
- while (field && TREE_TYPE (field) != lhstype)
- field = DECL_CHAIN (field);
- if (field)
- {
- TREE_OPERAND (rhs, 1) = field;
- mark_used (field);
- return rhs;
- }
+ r = instantiate_type (lhstype, field, flags);
- /* No exact match found, look for a compatible function. */
- field = TREE_OPERAND (rhs, 1);
- while (field && ! comptypes (lhstype, TREE_TYPE (field), 0))
- field = DECL_CHAIN (field);
- if (field)
+ if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype))
{
- TREE_OPERAND (rhs, 1) = field;
- field = DECL_CHAIN (field);
- while (field && ! comptypes (lhstype, TREE_TYPE (field), 0))
- field = DECL_CHAIN (field);
- if (field)
+ if (complain)
{
- if (complain)
- error ("ambiguous overload for COMPONENT_REF requested");
- return error_mark_node;
+ tree t = TYPE_PTRMEMFUNC_OBJECT_TYPE (lhstype);
+
+ if (TREE_CODE (field) == OVERLOAD)
+ field = OVL_FUNCTION (field);
+ if (TREE_CODE (field) == FUNCTION_DECL)
+ {
+ cp_pedwarn ("object-dependent reference `%E' can only be used in a call",
+ DECL_NAME (field));
+ cp_pedwarn (" to form a pointer to member function, say `&%T::%E'",
+ t, DECL_NAME (field));
+ }
+ else
+ cp_pedwarn ("object-dependent reference can only be used in a call");
}
+ return r;
}
- else
- {
- if (complain)
- error ("no appropriate overload exists for COMPONENT_REF");
- return error_mark_node;
- }
-#endif
- return rhs;
+
+ return r;
}
case OFFSET_REF:
+ rhs = TREE_OPERAND (rhs, 1);
+ if (BASELINK_P (rhs))
+ return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
+
/* 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. */
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);
+ return
+ resolve_address_of_overloaded_function (lhstype,
+ TREE_OPERAND (rhs, 0),
+ complain,
+ /*template_only=*/1,
+ TREE_OPERAND (rhs, 1));
case OVERLOAD:
- {
- tree elem, elems;
-
- /* 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) != FUNCTION_TYPE
- && TREE_CODE (lhstype) != METHOD_TYPE)
- {
- if (complain)
- cp_error("cannot resolve overloaded function `%D' "
- "based on non-function type",
- DECL_NAME (OVL_FUNCTION (rhs)));
- return error_mark_node;
- }
-
- /* 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 = OVL_FUNCTION (elems);
- if (comptypes (lhstype, TREE_TYPE (elem), 1))
- {
- mark_used (elem);
- return elem;
- }
- }
-
- /* 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)
- {
- 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;
- }
- }
- if (save_elem)
- {
- mark_used (save_elem);
- return save_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;
- 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_at (" and `%#D', at least", elem);
- }
- return error_mark_node;
- }
- mark_used (save_elem);
- return save_elem;
- }
- }
-
- /* We failed to find a match. */
- if (complain)
- {
- 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)));
- }
- return error_mark_node;
- }
+ return
+ resolve_address_of_overloaded_function (lhstype,
+ rhs,
+ complain,
+ /*template_only=*/0,
+ /*explicit_targs=*/NULL_TREE);
case TREE_LIST:
- {
- tree elem, baselink, name = NULL_TREE;
-
- if (TREE_PURPOSE (rhs) == error_mark_node)
- {
- /* 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. */
+ /* Now we should have a baselink. */
+ my_friendly_assert (BASELINK_P (rhs), 990412);
- 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 (OVL_CURRENT (elem)), 1))
- {
- mark_used (OVL_CURRENT (elem));
- return OVL_CURRENT (elem);
- }
- else
- elem = OVL_NEXT (elem);
- }
-
- /* No exact match found, look for a compatible method. */
- for (baselink = rhs; baselink;
- baselink = next_baselink (baselink))
- {
- elem = TREE_VALUE (baselink);
- for (; elem; elem = OVL_NEXT (elem))
- if (comp_target_types (lhstype,
- TREE_TYPE (OVL_CURRENT (elem)), 1) > 0)
- break;
- if (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 = 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)
- {
- /* Try to instantiate from non-member functions. */
- rhs = lookup_name_nonclass (name);
- if (rhs && TREE_CODE (rhs) == TREE_LIST)
- {
- /* This code seems to be missing a `return'. */
- my_friendly_abort (4);
- instantiate_type (lhstype, rhs, complain);
- }
- }
-#endif
- }
- if (complain)
- cp_error ("no compatible member functions named `%D'", name);
- return error_mark_node;
- }
+ return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
case CALL_EXPR:
/* This is too hard for now. */
@@ -5349,11 +5072,11 @@ instantiate_type (lhstype, rhs, complain)
case MINUS_EXPR:
case COMPOUND_EXPR:
TREE_OPERAND (rhs, 0)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
if (TREE_OPERAND (rhs, 0) == error_mark_node)
return error_mark_node;
TREE_OPERAND (rhs, 1)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
@@ -5421,11 +5144,11 @@ instantiate_type (lhstype, rhs, complain)
return error_mark_node;
}
TREE_OPERAND (rhs, 1)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
TREE_OPERAND (rhs, 2)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), flags);
if (TREE_OPERAND (rhs, 2) == error_mark_node)
return error_mark_node;
@@ -5434,7 +5157,7 @@ instantiate_type (lhstype, rhs, complain)
case MODIFY_EXPR:
TREE_OPERAND (rhs, 1)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
@@ -5442,30 +5165,7 @@ instantiate_type (lhstype, rhs, complain)
return rhs;
case ADDR_EXPR:
- if (TYPE_PTRMEMFUNC_P (lhstype))
- lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
- else if (TREE_CODE (lhstype) != POINTER_TYPE)
- {
- if (complain)
- error ("type for resolving address of overloaded function must be pointer type");
- return error_mark_node;
- }
- {
- 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;
+ return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
case ENTRY_VALUE_EXPR:
my_friendly_abort (184);
@@ -5524,16 +5224,24 @@ print_class_statistics ()
}
/* Push an obstack which is sufficiently long-lived to hold such class
- 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. */
+ decls that may be cached in the previous_class_values list. The
+ effect is undone by pop_obstacks. */
void
-maybe_push_cache_obstack ()
+push_cache_obstack ()
{
+ static int cache_obstack_initialized;
+
+ if (!cache_obstack_initialized)
+ {
+ gcc_obstack_init (&class_cache_obstack);
+ class_cache_firstobj
+ = (char*) obstack_finish (&class_cache_obstack);
+ cache_obstack_initialized = 1;
+ }
+
push_obstacks_nochange ();
- if (current_class_depth == 1)
- current_obstack = &permanent_obstack;
+ current_obstack = &class_cache_obstack;
}
/* Build a dummy reference to ourselves so Derived::Base (and A::A) works,
@@ -5542,19 +5250,22 @@ maybe_push_cache_obstack ()
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
+void
build_self_reference ()
{
tree name = constructor_name (current_class_type);
tree value = build_lang_decl (TYPE_DECL, name, current_class_type);
+ tree saved_cas;
+
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;
+ saved_cas = current_access_specifier;
+ current_access_specifier = access_public_node;
+ finish_member_declaration (value);
+ current_access_specifier = saved_cas;
}
/* Returns 1 if TYPE contains only padding bytes. */
@@ -5581,3 +5292,110 @@ is_empty_class (type)
t = TREE_CHAIN (t);
return (t == NULL_TREE);
}
+
+/* Find the enclosing class of the given NODE. NODE can be a *_DECL or
+ a *_TYPE node. NODE can also be a local class. */
+
+tree
+get_enclosing_class (type)
+ tree type;
+{
+ tree node = type;
+
+ while (node && TREE_CODE (node) != NAMESPACE_DECL)
+ {
+ switch (TREE_CODE_CLASS (TREE_CODE (node)))
+ {
+ case 'd':
+ node = DECL_CONTEXT (node);
+ break;
+
+ case 't':
+ if (node != type)
+ return node;
+ node = TYPE_CONTEXT (node);
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
+ }
+ return NULL_TREE;
+}
+
+/* Return 1 if TYPE or one of its enclosing classes is derived from BASE. */
+
+int
+is_base_of_enclosing_class (base, type)
+ tree base, type;
+{
+ while (type)
+ {
+ if (get_binfo (base, type, 0))
+ return 1;
+
+ type = get_enclosing_class (type);
+ }
+ return 0;
+}
+
+/* Note that NAME was looked up while the current class was being
+ defined and that the result of that lookup was DECL. */
+
+void
+maybe_note_name_used_in_class (name, decl)
+ tree name;
+ tree decl;
+{
+ splay_tree names_used;
+
+ /* If we're not defining a class, there's nothing to do. */
+ if (!current_class_type || !TYPE_BEING_DEFINED (current_class_type))
+ return;
+
+ /* If there's already a binding for this NAME, then we don't have
+ anything to worry about. */
+ if (IDENTIFIER_CLASS_VALUE (name))
+ return;
+
+ if (!current_class_stack[current_class_depth - 1].names_used)
+ current_class_stack[current_class_depth - 1].names_used
+ = splay_tree_new (splay_tree_compare_pointers, 0, 0);
+ names_used = current_class_stack[current_class_depth - 1].names_used;
+
+ splay_tree_insert (names_used,
+ (splay_tree_key) name,
+ (splay_tree_value) decl);
+}
+
+/* Note that NAME was declared (as DECL) in the current class. Check
+ to see that the declaration is legal. */
+
+void
+note_name_declared_in_class (name, decl)
+ tree name;
+ tree decl;
+{
+ splay_tree names_used;
+ splay_tree_node n;
+
+ /* Look to see if we ever used this name. */
+ names_used
+ = current_class_stack[current_class_depth - 1].names_used;
+ if (!names_used)
+ return;
+
+ n = splay_tree_lookup (names_used, (splay_tree_key) name);
+ if (n)
+ {
+ /* [basic.scope.class]
+
+ 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. */
+ cp_error ("declaration of `%#D'", decl);
+ cp_error_at ("changes meaning of `%s' from `%+#D'",
+ IDENTIFIER_POINTER (DECL_NAME (decl)),
+ (tree) n->value);
+ }
+}
diff --git a/contrib/gcc/cp/config-lang.in b/contrib/gcc/cp/config-lang.in
index 9b39d51..dd31af4 100644
--- a/contrib/gcc/cp/config-lang.in
+++ b/contrib/gcc/cp/config-lang.in
@@ -1,5 +1,5 @@
# Top level configure fragment for GNU C++.
-# Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
#This file is part of GNU CC.
diff --git a/contrib/gcc/cp/cp-tree.def b/contrib/gcc/cp/cp-tree.def
index dbbdb66..70801fc 100644
--- a/contrib/gcc/cp/cp-tree.def
+++ b/contrib/gcc/cp/cp-tree.def
@@ -1,7 +1,7 @@
/* 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.
+ Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -29,6 +29,11 @@ Boston, MA 02111-1307, USA. */
just won't work for us. */
DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
+/* A pointer-to-member constant. For a pointer-to-member constant
+ `X::Y' The PTRMEM_CST_CLASS is the RECORD_TYPE for `X' and the
+ PTRMEM_CST_MEMBER is the _DECL for `Y'. */
+DEFTREECODE (PTRMEM_CST, "ptrmem_cst", 'c', 1)
+
/* For NEW_EXPR, operand 0 is the placement list.
Operand 1 is the new-declarator.
Operand 2 is the initializer. */
@@ -138,9 +143,18 @@ DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", 't', 0)
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'. */
+/* A type designated by `typename T::t'. TYPE_CONTEXT is `T',
+ TYPE_NAME is an IDENTIFIER_NODE for `t'. If the type was named via
+ template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR.
+ If TREE_TYPE is present, this type was generated by the implicit
+ typename extension, and the TREE_TYPE is a _TYPE from a baseclass
+ of `T'. */
DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
+/* A type designated by `__typeof (expr)'. TYPE_FIELDS is the
+ expression in question. */
+DEFTREECODE (TYPEOF_TYPE, "typeof_type", 't', 0)
+
/* A thunk is a stub function.
Thunks are used to implement multiple inheritance:
@@ -158,17 +172,16 @@ 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. */
+/* A template-id, like foo<int>. The first operand is the template.
+ The second is the TREE_LIST or TREE_VEC of explicitly specified
+ arguments. The template will be a FUNCTION_DECL, TEMPLATE_DECL, or
+ an OVERLOAD. 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. */
+/* An association between name 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
@@ -182,9 +195,14 @@ DEFTREECODE (WRAPPER, "wrapper", 'x', 1)
/* A node to remember a source position. */
DEFTREECODE (SRCLOC, "srcloc", 'x', 2)
+/* Used to represent deferred name lookup for dependent names while
+ parsing a template declaration. The first argument is an
+ IDENTIFIER_NODE for the name in question. The TREE_TYPE is
+ unused. */
+DEFTREECODE (LOOKUP_EXPR, "lookup_expr", 'e', 1)
+
/* 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)
diff --git a/contrib/gcc/cp/cp-tree.h b/contrib/gcc/cp/cp-tree.h
index 7572921..7d64307 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, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -22,38 +22,37 @@ Boston, MA 02111-1307, USA. */
#ifndef _CP_TREE_H
#define _CP_TREE_H
-#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.
+ 0: BINFO_MARKED (BINFO nodes).
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.
+ TREE_INDIRECT_USING (in NAMESPACE_DECL).
+ IDENTIFIER_MARKED (used by search routines).
+ LOCAL_BINDING_P (in CPLUS_BINDING)
+ 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.
+ INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
+ BASELINK_P (in TREE_LIST)
2: IDENTIFIER_OPNAME_P.
+ BINFO_VBASE_MARKED.
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.
+ BINFO_PUSHDECLS_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.
+ 5: Not used.
6: Not used.
Usage of TYPE_LANG_FLAG_?:
@@ -67,13 +66,31 @@ Boston, MA 02111-1307, USA. */
Usage of DECL_LANG_FLAG_?:
0: DECL_ERROR_REPORTED (in VAR_DECL).
+ DECL_TEMPLATE_PARM_P (in CONST_DECL, TYPE_DECL, or TEMPLATE_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
+ DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
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).
+
+ Usage of language-independent fields in a language-dependent manner:
+
+ TYPE_ALIAS_SET
+ This field is used by TYPENAME_TYPEs, TEMPLATE_TYPE_PARMs, and so
+ forth as a substitute for the mark bits provided in `lang_type'.
+ At present, only the six low-order bits are used.
+
+ TYPE_BINFO
+ For an ENUMERAL_TYPE, this is ENUM_TEMPLATE_INFO.
+ For a TYPENAME_TYPE, this is TYPENAME_TYPE_FULLNAME.
+ For a TEMPLATE_TEMPLATE_PARM, this is
+ TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO.
+
+ DECL_SAVED_INSNS/DECL_FIELD_SIZE
+ For a static VAR_DECL, this is DECL_INIT_PRIORITY.
*/
/* Language-dependent contents of an identifier. */
@@ -81,7 +98,8 @@ Boston, MA 02111-1307, USA. */
struct lang_identifier
{
struct tree_identifier ignore;
- tree namespace_bindings, local_value;
+ tree namespace_bindings;
+ tree bindings;
tree class_value;
tree class_template_info;
struct lang_id2 *x;
@@ -90,7 +108,7 @@ struct lang_identifier
struct lang_id2
{
tree label_value, implicit_decl;
- tree type_desc, as_list, error_locus;
+ tree error_locus;
};
typedef struct
@@ -110,15 +128,34 @@ typedef struct
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)
+typedef struct ptrmem_cst
+{
+ char common[sizeof (struct tree_common)];
+ tree member;
+}* ptrmem_cst_t;
+
+/* Nonzero if this binding is for a local scope, as opposed to a class
+ or namespace scope. */
+#define LOCAL_BINDING_P(NODE) TREE_LANG_FLAG_0(NODE)
+
+/* Nonzero if BINDING_VALUE is from a base class of the class which is
+ currently being defined. */
+#define INHERITED_VALUE_BINDING_P(NODE) TREE_LANG_FLAG_1(NODE)
+
+/* For a binding between a name and an entity at a non-local scope,
+ defines the scope where the binding is declared. (Either a class
+ _TYPE node, or a NAMESPACE_DECL.) This macro should be used only
+ for namespace-level bindings; on the IDENTIFIER_BINDING list
+ BINDING_LEVEL is used instead. */
+#define BINDING_SCOPE(NODE) (((struct tree_binding*)NODE)->scope.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) \
@@ -131,7 +168,10 @@ typedef struct
struct tree_binding
{
char common[sizeof (struct tree_common)];
- tree scope;
+ union {
+ tree scope;
+ struct binding_level *level;
+ } scope;
tree value;
};
@@ -154,6 +194,14 @@ struct tree_overload
tree function;
};
+/* A `baselink' is a TREE_LIST whose TREE_PURPOSE is a BINFO
+ indicating a particular base class, and whose TREE_VALUE is a
+ (possibly overloaded) function from that base class. */
+#define BASELINK_P(NODE) \
+ (TREE_CODE ((NODE)) == TREE_LIST && TREE_LANG_FLAG_1 ((NODE)))
+#define SET_BASELINK_P(NODE) \
+ (TREE_LANG_FLAG_1 ((NODE)) = 1)
+
#define WRAPPER_PTR(NODE) (((struct tree_wrapper*)NODE)->u.ptr)
#define WRAPPER_INT(NODE) (((struct tree_wrapper*)NODE)->u.i)
@@ -183,13 +231,43 @@ struct tree_srcloc
#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) \
- (((struct lang_identifier *)(NODE))->local_value)
#define IDENTIFIER_TEMPLATE(NODE) \
(((struct lang_identifier *)(NODE))->class_template_info)
+/* The IDENTIFIER_BINDING is the innermost CPLUS_BINDING for the
+ identifier. It's TREE_CHAIN is the next outermost binding. Each
+ BINDING_VALUE is a DECL for the associated declaration. Thus,
+ name lookup consists simply of pulling off the node at the front
+ of the list (modulo oddities for looking up the names of types,
+ and such.) You can use BINDING_SCOPE or BINDING_LEVEL to
+ determine the scope that bound the name. */
+#define IDENTIFIER_BINDING(NODE) \
+ (((struct lang_identifier*) (NODE))->bindings)
+
+/* The IDENTIFIER_VALUE is the value of the IDENTIFIER_BINDING, or
+ NULL_TREE if there is no binding. */
+#define IDENTIFIER_VALUE(NODE) \
+ (IDENTIFIER_BINDING (NODE) \
+ ? BINDING_VALUE (IDENTIFIER_BINDING (NODE)) \
+ : NULL_TREE)
+
+/* If IDENTIFIER_CLASS_VALUE is set, then NODE is bound in the current
+ class, and IDENTIFIER_CLASS_VALUE is the value binding. This is
+ just a pointer to the BINDING_VALUE of one of the bindings in the
+ IDENTIFIER_BINDINGs list, so any time that this is non-NULL so is
+ IDENTIFIER_BINDING. */
+#define IDENTIFIER_CLASS_VALUE(NODE) \
+ (((struct lang_identifier *) (NODE))->class_value)
+
+/* The amount of time used by the file whose special "time identifier"
+ is NODE, represented as an INTEGER_CST. See get_time_identifier. */
+#define TIME_IDENTIFIER_TIME(NODE) IDENTIFIER_BINDING(NODE)
+
+/* For a "time identifier" this is a INTEGER_CST. The
+ TREE_INT_CST_LOW is 1 if the corresponding file is "interface only".
+ The TRE_INT_CST_HIGH is 1 if it is "interface unknown". */
+#define TIME_IDENTIFIER_FILEINFO(NODE) IDENTIFIER_CLASS_VALUE (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
@@ -216,14 +294,6 @@ struct tree_srcloc
#define SET_IDENTIFIER_IMPLICIT_DECL(NODE,VALUE) \
SET_LANG_ID(NODE, VALUE, implicit_decl)
-#define IDENTIFIER_AS_DESC(NODE) LANG_ID_FIELD(type_desc, NODE)
-#define SET_IDENTIFIER_AS_DESC(NODE,DESC) \
- SET_LANG_ID(NODE, DESC, type_desc)
-
-#define IDENTIFIER_AS_LIST(NODE) LANG_ID_FIELD(as_list, NODE)
-#define SET_IDENTIFIER_AS_LIST(NODE,LIST) \
- SET_LANG_ID(NODE, LIST, as_list)
-
#define IDENTIFIER_ERROR_LOCUS(NODE) LANG_ID_FIELD(error_locus, NODE)
#define SET_IDENTIFIER_ERROR_LOCUS(NODE,VALUE) \
SET_LANG_ID(NODE, VALUE, error_locus)
@@ -234,10 +304,12 @@ struct tree_srcloc
/* Nonzero if this identifier is the prefix for a mangled C++ operator name. */
#define IDENTIFIER_OPNAME_P(NODE) TREE_LANG_FLAG_2(NODE)
-#define IDENTIFIER_TYPENAME_P(NODE) \
- (! strncmp (IDENTIFIER_POINTER (NODE), \
- IDENTIFIER_POINTER (ansi_opname[(int) TYPE_EXPR]), \
- IDENTIFIER_LENGTH (ansi_opname[(int) TYPE_EXPR])))
+/* Nonzero if this identifier is the name of a type-conversion
+ operator. */
+#define IDENTIFIER_TYPENAME_P(NODE) \
+ (! strncmp (IDENTIFIER_POINTER (NODE), \
+ OPERATOR_TYPENAME_FORMAT, \
+ strlen (OPERATOR_TYPENAME_FORMAT)))
/* Nonzero means reject anything that ANSI standard C forbids. */
extern int pedantic;
@@ -278,7 +350,9 @@ 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;
+#if HOST_BITS_PER_WIDE_INT >= 64
extern tree intTI_type_node, unsigned_intTI_type_node;
+#endif
extern tree java_byte_type_node;
extern tree java_short_type_node;
@@ -321,10 +395,6 @@ extern int flag_gnu_xref;
extern int flag_gnu_binutils;
-/* Nonzero means ignore `#ident' directives. */
-
-extern int flag_no_ident;
-
/* Nonzero means warn about implicit declarations. */
extern int warn_implicit;
@@ -343,9 +413,13 @@ extern int warn_ctor_dtor_privacy;
extern int warn_return_type;
-/* 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. */
+/* Nonzero means give string constants the type `const char *', as mandated
+ by the standard. */
+
+extern int flag_const_strings;
+
+/* Nonzero means warn about deprecated conversion from string constant to
+ `char *'. */
extern int warn_write_strings;
@@ -472,6 +546,22 @@ extern int flag_do_squangling;
/* Nonzero if we want to issue diagnostics that the standard says are not
required. */
extern int flag_optional_diags;
+
+/* Nonzero means do not consider empty argument prototype to mean function
+ takes no arguments. */
+extern int flag_strict_prototype;
+
+/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
+extern int flag_vtable_gc;
+
+/* Nonzero means make the default pedwarns warnings instead of errors.
+ The value of this flag is ignored if -pedantic is specified. */
+extern int flag_permissive;
+
+/* Nonzero if we want to obey access control semantics. */
+
+extern int flag_access_control;
+
/* C++ language-specific tree codes. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
@@ -495,7 +585,26 @@ enum languages { lang_c, lang_cplusplus, lang_java };
/* The _DECL for this _TYPE. */
#define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE)))
-#define IS_AGGR_TYPE(t) (TYPE_LANG_FLAG_5 (t))
+/* Nonzero if T is a class (or struct or union) type. Also nonzero
+ for template type parameters and typename types. Despite its name,
+ this macro has nothing to do with the definition of aggregate given
+ in the standard. Think of this macro as MAYBE_CLASS_TYPE_P. */
+#define IS_AGGR_TYPE(t) \
+ (TREE_CODE (t) == TEMPLATE_TYPE_PARM \
+ || TREE_CODE (t) == TYPENAME_TYPE \
+ || TREE_CODE (t) == TYPEOF_TYPE \
+ || TYPE_LANG_FLAG_5 (t))
+
+/* Set IS_AGGR_TYPE for T to VAL. T must be a class, struct, or
+ union type. */
+#define SET_IS_AGGR_TYPE(T, VAL) \
+ (TYPE_LANG_FLAG_5 (T) = (VAL))
+
+/* Nonzero if T is a class type. Zero for template type parameters,
+ typename types, and so forth. */
+#define CLASS_TYPE_P(t) \
+ (IS_AGGR_TYPE_CODE (TREE_CODE (t)) && IS_AGGR_TYPE (t))
+
#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) \
@@ -509,6 +618,32 @@ enum languages { lang_c, lang_cplusplus, lang_java };
/* True if this a "Java" type, defined in 'extern "Java"'. */
#define TYPE_FOR_JAVA(NODE) TYPE_LANG_FLAG_3(NODE)
+/* The type qualifiers for this type, including the qualifiers on the
+ elements for an array type. */
+#define CP_TYPE_QUALS(NODE) \
+ ((TREE_CODE (NODE) != ARRAY_TYPE) \
+ ? TYPE_QUALS (NODE) : cp_type_quals (NODE))
+
+/* Nonzero if this type is const-qualified. */
+#define CP_TYPE_CONST_P(NODE) \
+ ((CP_TYPE_QUALS (NODE) & TYPE_QUAL_CONST) != 0)
+
+/* Nonzero if this type is volatile-qualified. */
+#define CP_TYPE_VOLATILE_P(NODE) \
+ ((CP_TYPE_QUALS (NODE) & TYPE_QUAL_VOLATILE) != 0)
+
+/* Nonzero if this type is restrict-qualified. */
+#define CP_TYPE_RESTRICT_P(NODE) \
+ ((CP_TYPE_QUALS (NODE) & TYPE_QUAL_RESTRICT) != 0)
+
+/* Nonzero if this type is const-qualified, but not
+ volatile-qualified. Other qualifiers are ignored. This macro is
+ used to test whether or not it is OK to bind an rvalue to a
+ reference. */
+#define CP_TYPE_CONST_NON_VOLATILE_P(NODE) \
+ ((CP_TYPE_QUALS (NODE) & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)) \
+ == TYPE_QUAL_CONST)
+
#define DELTA_FROM_VTABLE_ENTRY(ENTRY) \
(!flag_vtable_thunks ? \
TREE_VALUE (CONSTRUCTOR_ELTS (ENTRY)) \
@@ -537,23 +672,31 @@ enum languages { lang_c, lang_cplusplus, lang_java };
#define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 1, (tree *)0) >= 0)
#define DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) != -1)
-/* Statistics show that while the GNU C++ compiler may generate
- thousands of different types during a compilation run, it
- generates relatively few (tens) of classtypes. Because of this,
- it is not costly to store a generous amount of information
- in classtype nodes. This struct must fill out to a multiple of 4 bytes. */
+/* This structure provides additional information above and beyond
+ what is provide in the ordinary tree_type. In the past, we used it
+ for the types of class types, template parameters types, typename
+ types, and so forth. However, there can be many (tens to hundreds
+ of thousands) of template parameter types in a compilation, and
+ there's no need for this additional information in that case.
+ Therefore, we now use this data structure only for class types.
+
+ In the past, it was thought that there would be relatively few
+ class types. However, in the presence of heavy use of templates,
+ many (i.e., thousands) of classes can easily be generated.
+ Therefore, we should endeavor to keep the size of this structure to
+ a minimum. */
struct lang_type
{
struct
{
unsigned has_type_conversion : 1;
unsigned has_init_ref : 1;
- unsigned has_assignment : 1;
unsigned has_default_ctor : 1;
unsigned uses_multiple_inheritance : 1;
unsigned const_needs_init : 1;
unsigned ref_needs_init : 1;
unsigned has_const_assign_ref : 1;
+ unsigned anon_union : 1;
unsigned has_nonpublic_ctor : 2;
unsigned has_nonpublic_assign_ref : 2;
@@ -565,63 +708,54 @@ struct lang_type
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 marks: 6;
unsigned vec_delete_takes_size : 1;
unsigned declared_class : 1;
+
unsigned being_defined : 1;
unsigned redefined : 1;
- unsigned marked : 1;
- unsigned marked2 : 1;
- unsigned marked3 : 1;
-
- unsigned marked4 : 1;
- unsigned marked5 : 1;
- unsigned marked6 : 1;
unsigned debug_requested : 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_opaque_typedecls : 1;
unsigned sigtable_has_been_generated : 1;
unsigned was_anonymous : 1;
- unsigned has_real_assignment : 1;
unsigned has_real_assign_ref : 1;
-
unsigned has_const_init_ref : 1;
unsigned has_complex_init_ref : 1;
+
unsigned has_complex_assign_ref : 1;
unsigned has_abstract_assign_ref : 1;
unsigned non_aggregate : 1;
+ unsigned is_partial_instantiation : 1;
+ unsigned has_mutable : 1;
+ unsigned com_interface : 1;
+ /* When adding a flag here, consider whether or not it ought to
+ apply to a template instance if it applies to the template.
+ If so, make sure to copy it in instantiate_class_template! */
/* 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 : 11;
+ unsigned dummy : 10;
} 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 *baselink_vec;
union tree_node *vfields;
union tree_node *vbases;
union tree_node *tags;
- char *memoized_table_entry;
union tree_node *search_slot;
@@ -630,17 +764,9 @@ struct lang_type
union tree_node *size;
- union tree_node *base_init_list;
union tree_node *abstract_virtuals;
- union tree_node *as_list;
- union tree_node *id_as_list;
- union tree_node *binfo_as_list;
union tree_node *friend_classes;
-#ifdef MI_MATRIX
- char *mi_matrix;
-#endif
-
union tree_node *rtti;
union tree_node *methods;
@@ -648,14 +774,10 @@ struct lang_type
union tree_node *signature;
union tree_node *signature_pointer_to;
union tree_node *signature_reference_to;
-
union tree_node *template_info;
-
- int linenum;
+ tree befriending_classes;
};
-#define CLASSTYPE_SOURCE_LINE(NODE) (TYPE_LANG_SPECIFIC(NODE)->linenum)
-
/* Indicates whether or not (and how) a template was expanded for this class.
0=no information yet/non-template class
1=implicit template instantiation
@@ -669,13 +791,6 @@ struct lang_type
/* List of friends which were defined inline in this class definition. */
#define CLASSTYPE_INLINE_FRIENDS(NODE) (TYPE_NONCOPIED_PARTS (NODE))
-/* Nonzero for _CLASSTYPE means that the _CLASSTYPE either has
- a special meaning for the assignment operator ("operator="),
- or one of its fields (or base members) has a special meaning
- defined. */
-#define TYPE_HAS_ASSIGNMENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_assignment)
-#define TYPE_HAS_REAL_ASSIGNMENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assignment)
-
/* Nonzero for _CLASSTYPE means that operator new and delete are defined,
respectively. */
#define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new)
@@ -690,9 +805,6 @@ struct lang_type
(TYPE_NEEDS_DESTRUCTOR (NODE) \
|| (TYPE_LANG_SPECIFIC (NODE) && TYPE_VEC_DELETE_TAKES_SIZE (NODE)))
-/* 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 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)
@@ -751,7 +863,7 @@ struct lang_type
signature reference type. */
#define SIGNATURE_REFERENCE_TO(NODE) (TYPE_LANG_SPECIFIC(NODE)->signature_reference_to)
-/* The is the VAR_DECL that contains NODE's rtti. */
+/* The is the basetype that contains NODE's rtti. */
#define CLASSTYPE_RTTI(NODE) (TYPE_LANG_SPECIFIC(NODE)->rtti)
/* Nonzero means that this _CLASSTYPE node overloads operator(). */
@@ -773,7 +885,12 @@ struct lang_type
hierarchy, then we can use more efficient search techniques. */
#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE))
-/* List of lists of member functions defined in this class. */
+/* Vector member functions defined in this class. Each element is
+ either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. All
+ functions with the same name end up in the same slot. The first
+ two elements are for constructors, and destructors, respectively.
+ These are followed by ordinary member functions. There may be
+ empty entries at the end of the vector. */
#define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
/* The first type conversion operator in the class (the others can be
@@ -784,30 +901,46 @@ struct lang_type
? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 2) \
: NULL_TREE;
-/* Pointer from any member function to the head of the list of
- member functions of the type that member function belongs to. */
-#define CLASSTYPE_BASELINK_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->baselink_vec)
-
/* Mark bits for depth-first and breath-first searches. */
-#define CLASSTYPE_MARKED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked)
-#define CLASSTYPE_MARKED2(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked2)
-#define CLASSTYPE_MARKED3(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked3)
-#define CLASSTYPE_MARKED4(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked4)
-#define CLASSTYPE_MARKED5(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked5)
-#define CLASSTYPE_MARKED6(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked6)
+
+/* Get the value of the Nth mark bit. */
+#define CLASSTYPE_MARKED_N(NODE, N) \
+ (((CLASS_TYPE_P (NODE) ? TYPE_LANG_SPECIFIC (NODE)->type_flags.marks \
+ : TYPE_ALIAS_SET (NODE)) & (1 << N)) != 0)
+
+/* Set the Nth mark bit. */
+#define SET_CLASSTYPE_MARKED_N(NODE, N) \
+ (CLASS_TYPE_P (NODE) \
+ ? (TYPE_LANG_SPECIFIC (NODE)->type_flags.marks |= (1 << (N))) \
+ : (TYPE_ALIAS_SET (NODE) |= (1 << (N))))
+
+/* Clear the Nth mark bit. */
+#define CLEAR_CLASSTYPE_MARKED_N(NODE, N) \
+ (CLASS_TYPE_P (NODE) \
+ ? (TYPE_LANG_SPECIFIC (NODE)->type_flags.marks &= ~(1 << (N))) \
+ : (TYPE_ALIAS_SET (NODE) &= ~(1 << (N))))
+
+/* Get the value of the mark bits. */
+#define CLASSTYPE_MARKED(NODE) CLASSTYPE_MARKED_N(NODE, 0)
+#define CLASSTYPE_MARKED2(NODE) CLASSTYPE_MARKED_N(NODE, 1)
+#define CLASSTYPE_MARKED3(NODE) CLASSTYPE_MARKED_N(NODE, 2)
+#define CLASSTYPE_MARKED4(NODE) CLASSTYPE_MARKED_N(NODE, 3)
+#define CLASSTYPE_MARKED5(NODE) CLASSTYPE_MARKED_N(NODE, 4)
+#define CLASSTYPE_MARKED6(NODE) CLASSTYPE_MARKED_N(NODE, 5)
+
/* Macros to modify the above flags */
-#define SET_CLASSTYPE_MARKED(NODE) (CLASSTYPE_MARKED(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED(NODE) (CLASSTYPE_MARKED(NODE) = 0)
-#define SET_CLASSTYPE_MARKED2(NODE) (CLASSTYPE_MARKED2(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED2(NODE) (CLASSTYPE_MARKED2(NODE) = 0)
-#define SET_CLASSTYPE_MARKED3(NODE) (CLASSTYPE_MARKED3(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED3(NODE) (CLASSTYPE_MARKED3(NODE) = 0)
-#define SET_CLASSTYPE_MARKED4(NODE) (CLASSTYPE_MARKED4(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED4(NODE) (CLASSTYPE_MARKED4(NODE) = 0)
-#define SET_CLASSTYPE_MARKED5(NODE) (CLASSTYPE_MARKED5(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED5(NODE) (CLASSTYPE_MARKED5(NODE) = 0)
-#define SET_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 0)
+#define SET_CLASSTYPE_MARKED(NODE) SET_CLASSTYPE_MARKED_N(NODE, 0)
+#define CLEAR_CLASSTYPE_MARKED(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 0)
+#define SET_CLASSTYPE_MARKED2(NODE) SET_CLASSTYPE_MARKED_N(NODE, 1)
+#define CLEAR_CLASSTYPE_MARKED2(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 1)
+#define SET_CLASSTYPE_MARKED3(NODE) SET_CLASSTYPE_MARKED_N(NODE, 2)
+#define CLEAR_CLASSTYPE_MARKED3(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 2)
+#define SET_CLASSTYPE_MARKED4(NODE) SET_CLASSTYPE_MARKED_N(NODE, 3)
+#define CLEAR_CLASSTYPE_MARKED4(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 3)
+#define SET_CLASSTYPE_MARKED5(NODE) SET_CLASSTYPE_MARKED_N(NODE, 4)
+#define CLEAR_CLASSTYPE_MARKED5(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 4)
+#define SET_CLASSTYPE_MARKED6(NODE) SET_CLASSTYPE_MARKED_N(NODE, 5)
+#define CLEAR_CLASSTYPE_MARKED6(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 5)
/* 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
@@ -838,42 +971,15 @@ struct lang_type
#define CLASSTYPE_N_BASECLASSES(NODE) \
(TYPE_BINFO_BASETYPES (NODE) ? TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES(NODE)) : 0)
-/* Memoize the number of super classes (base classes) tha this node
- has. That way we can know immediately (albeit conservatively how
- 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)->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. */
-#define CLASSTYPE_MAX_DEPTH(NODE) (TYPE_LANG_SPECIFIC(NODE)->max_depth)
-
/* Used for keeping search-specific information. Any search routine
which uses this must define what exactly this slot is used for. */
#define CLASSTYPE_SEARCH_SLOT(NODE) (TYPE_LANG_SPECIFIC(NODE)->search_slot)
-/* Entry for keeping memoization tables for this type to
- hopefully speed up search routines. Since it is a pointer,
- it can mean almost anything. */
-#define CLASSTYPE_MTABLE_ENTRY(NODE) (TYPE_LANG_SPECIFIC(NODE)->memoized_table_entry)
-
/* 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_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align)
-/* 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,
- the TREE_PURPOSE and TREE_VALUE fields have different meanings:
-
- Member initialization: <FIELD_DECL, TYPE>
- Base class construction: <NULL_TREE, BASETYPE>
- Base class initialization: <BASE_INITIALIZATION, THESE_INITIALIZATIONS>
- Whole type: <MEMBER_INIT, BASE_INIT>. */
-#define CLASSTYPE_BASE_INIT_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->base_init_list)
-
/* A cons list of virtual functions which cannot be inherited by
derived classes. When deriving from this type, the derived
class must provide its own definition for each of these functions. */
@@ -892,9 +998,6 @@ struct lang_type
the virtual function table will be written out. */
#define CLASSTYPE_VTABLE_NEEDS_WRITING(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.vtable_needs_writing)
-/* Nonzero means that this type defines its own local type declarations. */
-#define CLASSTYPE_LOCAL_TYPEDECLS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.local_typedecls)
-
/* Nonzero means that this type has an X() constructor. */
#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_default_ctor)
@@ -906,26 +1009,22 @@ struct lang_type
/* Ditto, for operator=. */
#define TYPE_HAS_NONPUBLIC_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_nonpublic_assign_ref)
-/* Many routines need to cons up a list of basetypes for access
- checking. This field contains a TREE_LIST node whose TREE_VALUE
- is the main variant of the type, and whose TREE_VIA_PUBLIC
- and TREE_VIA_VIRTUAL bits are correctly set. */
-#define CLASSTYPE_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->as_list)
-/* Same, but cache a list whose value is the name of this type. */
-#define CLASSTYPE_ID_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->id_as_list)
-/* 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. The
+/* Nonzero means that this type contains a mutable member */
+#define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_mutable)
+#define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE))
+
+/* Nonzero means that this type is meant for communication via COM. */
+#define CLASSTYPE_COM_INTERFACE(NODE) \
+ (TYPE_LANG_SPECIFIC(NODE)->type_flags.com_interface)
+
+/* A list of class types of 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
+/* A list of the classes which grant friendship to this class. */
+#define CLASSTYPE_BEFRIENDING_CLASSES(NODE) \
+ (TYPE_LANG_SPECIFIC (NODE)->befriending_classes)
/* 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)
@@ -952,17 +1051,20 @@ struct lang_type
/* Additional macros for inheritance information. */
-/* When following an binfo-specific chain, this is the cumulative
- via-public flag. */
-#define BINFO_VIA_PUBLIC(NODE) TREE_LANG_FLAG_5 (NODE)
+/* The BINFO_INHERITANCE_CHAIN is used opposite to the description in
+ gcc/tree.h. In particular if D is derived from B then the BINFO
+ for B (in D) will have a BINFO_INHERITANCE_CHAIN pointing to
+ D. In tree.h, this pointer is described as pointing in other
+ direction. There is a different BINFO for each path to a virtual
+ base; BINFOs for virtual bases are not shared. In addition, shared
+ versions of each of the virtual class BINFOs are stored in
+ CLASSTYPE_VBASECLASSES.
-#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
+ We use TREE_VIA_PROTECTED and TREE_VIA_PUBLIC, but private
+ inheritance is indicated by the absence of the other two flags, not
+ by TREE_VIAR_PRIVATE, which is unused.
+
+ The TREE_CHAIN is for scratch space in search.c. */
/* Nonzero means marked by DFS or BFS search, including searches
by `get_binfo' and `get_base_distance'. */
@@ -972,12 +1074,6 @@ struct lang_type
#define SET_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=1))
#define CLEAR_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=0))
-/* Nonzero means marked in building initialization list. */
-#define BINFO_BASEINIT_MARKED(NODE) CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-/* Modifier macros */
-#define SET_BINFO_BASEINIT_MARKED(NODE) SET_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-#define CLEAR_BINFO_BASEINIT_MARKED(NODE) CLEAR_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-
/* Nonzero means marked in search through virtual inheritance hierarchy. */
#define BINFO_VBASE_MARKED(NODE) CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
/* Modifier macros */
@@ -1002,11 +1098,13 @@ struct lang_type
#define SET_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=1))
#define CLEAR_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=0))
-/* Nonzero means this class has initialized its virtual baseclasses. */
-#define BINFO_VBASE_INIT_MARKED(NODE) \
- (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED5(BINFO_TYPE(NODE)):TREE_LANG_FLAG_5(NODE))
-#define SET_BINFO_VBASE_INIT_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED5(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_5(NODE)=1))
-#define CLEAR_BINFO_VBASE_INIT_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED5(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_5(NODE)=0))
+/* Nonzero means this class has done dfs_pushdecls. */
+#define BINFO_PUSHDECLS_MARKED(NODE) BINFO_VTABLE_PATH_MARKED (NODE)
+#define SET_BINFO_PUSHDECLS_MARKED(NODE) SET_BINFO_VTABLE_PATH_MARKED (NODE)
+#define CLEAR_BINFO_PUSHDECLS_MARKED(NODE) CLEAR_BINFO_VTABLE_PATH_MARKED (NODE)
+
+/* Used by various search routines. */
+#define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
/* Accessor macros for the vfield slots in structures. */
@@ -1027,12 +1125,28 @@ struct lang_type
#define TREE_PARMLIST(NODE) ((NODE)->common.unsigned_flag) /* overloaded! */
/* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that
- this type can raise. */
+ this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE
+ will be NULL_TREE to indicate a throw specification of `(...)', or,
+ equivalently, no throw specification. */
#define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE)
+/* For FUNCTION_TYPE or METHOD_TYPE, return 1 iff it is declared `throw()'. */
+#define TYPE_NOTHROW_P(NODE) \
+ (TYPE_RAISES_EXCEPTIONS (NODE) \
+ && TREE_VALUE (TYPE_RAISES_EXCEPTIONS (NODE)) == NULL_TREE)
+
/* The binding level associated with the namespace. */
#define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level)
+
+/* If a DECL has DECL_LANG_SPECIFIC, it is either a lang_decl_flags or
+ a lang_decl (which has lang_decl_flags as its initial prefix). A
+ FUNCTION_DECL, NAMESPACE_DECL, TYPE_DECL, or USING_DECL may have a
+ full lang_decl. A FIELD_DECL, or a static data member VAR_DECL,
+ will have only lang_decl_flags. Thus, one should only access the
+ members of lang_decl that are not in lang_decl_flags for DECLs that
+ are not FIELD_DECLs or VAR_DECLs. */
+
struct lang_decl_flags
{
#ifdef ONLY_INT_FIELDS
@@ -1043,8 +1157,6 @@ struct lang_decl_flags
unsigned operator_attr : 1;
unsigned constructor_attr : 1;
- unsigned returns_first_arg : 1;
- unsigned preserves_first_arg : 1;
unsigned friend_attr : 1;
unsigned static_function : 1;
unsigned const_memfunc : 1;
@@ -1061,9 +1173,10 @@ struct lang_decl_flags
unsigned nonconverting : 1;
unsigned declared_inline : 1;
unsigned not_really_extern : 1;
- unsigned comdat : 1;
unsigned needs_final_overrider : 1;
- unsigned dummy : 3;
+ unsigned bitfield : 1;
+ unsigned defined_in_class : 1;
+ unsigned dummy : 4;
tree access;
tree context;
@@ -1077,6 +1190,7 @@ struct lang_decl
struct lang_decl_flags decl_flags;
tree main_decl_variant;
+ tree befriending_classes;
struct pending_inline *pending_inline_info;
};
@@ -1098,26 +1212,34 @@ struct lang_decl
/* 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)))
+
+/* There ought to be a better way to find out whether or not something is
+ a destructor. */
+#define DECL_DESTRUCTOR_P(NODE) \
+ (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (NODE)) \
+ && DECL_LANGUAGE (NODE) == lang_cplusplus)
+
+#define DECL_CONV_FN_P(NODE) \
+ (IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)) && TREE_TYPE (DECL_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)
+/* Non-zero for a FUNCTION_DECL that declares a type-info function. */
+#define DECL_TINFO_FN_P(NODE) \
+ (TREE_CODE (NODE) == FUNCTION_DECL \
+ && DECL_ARTIFICIAL (NODE) \
+ && DECL_LANG_SPECIFIC(NODE)->decl_flags.mutable_flag)
+
+/* Mark NODE as a type-info function. */
+#define SET_DECL_TINFO_FN_P(NODE) \
+ (DECL_LANG_SPECIFIC((NODE))->decl_flags.mutable_flag = 1)
+
/* For FUNCTION_DECLs: nonzero means that this function is a default
implementation of a signature method. */
#define IS_DEFAULT_IMPLEMENTATION(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.is_default_implementation)
-/* For FUNCTION_DECLs: nonzero means that the constructor
- is known to return a non-zero `this' unchanged. */
-#define DECL_RETURNS_FIRST_ARG(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.returns_first_arg)
-
-/* 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_ptr'
- after performing base initializations. */
-#define DECL_PRESERVES_THIS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.preserves_first_arg)
-
/* Nonzero for _DECL means that this decl appears in (or will appear
in) as a member in a RECORD_TYPE or UNION_TYPE node. It is also for
detecting circularity in case members are multiply defined. In the
@@ -1125,11 +1247,20 @@ struct lang_decl
should be allocated. */
#define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3(NODE))
+/* Nonzero if the DECL was defined in the class definition itself,
+ rather than outside the class. */
+#define DECL_DEFINED_IN_CLASS_P(DECL) \
+ (DECL_LANG_SPECIFIC (DECL)->decl_flags.defined_in_class)
+
/* Nonzero for FUNCTION_DECL means that this decl is just a
friend declaration, and should not be added to the list of
member functions for this class. */
#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.friend_attr)
+/* A TREE_LIST of the types which have befriended this FUNCTION_DECL. */
+#define DECL_BEFRIENDING_CLASSES(NODE) \
+ (DECL_LANG_SPECIFIC(NODE)->befriending_classes)
+
/* Nonzero for FUNCTION_DECL means that this decl is a static
member function. */
#define DECL_STATIC_FUNCTION_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.static_function)
@@ -1158,6 +1289,12 @@ struct lang_decl
has `this' as volatile X *const. */
#define DECL_VOLATILE_MEMFUNC_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.volatile_memfunc)
+/* Nonzero for a DECL means that this member is a non-static member. */
+#define DECL_NONSTATIC_MEMBER_P(NODE) \
+ ((TREE_CODE (NODE) == FUNCTION_DECL \
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE)) \
+ || TREE_CODE (NODE) == FIELD_DECL)
+
/* Nonzero for _DECL means that this member object type
is mutable. */
#define DECL_MUTABLE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.mutable_flag)
@@ -1190,6 +1327,10 @@ struct lang_decl
(DECL_CONTEXT (NODE) ? DECL_CONTEXT (NODE) : global_namespace)
#define FROB_CONTEXT(NODE) ((NODE) == global_namespace ? NULL_TREE : (NODE))
+/* For a virtual function, the base where we find its vtable entry.
+ For a non-virtual function, the base where it is defined. */
+#define DECL_VIRTUAL_CONTEXT(NODE) DECL_CONTEXT (NODE)
+
/* 1 iff NODE has namespace scope, including the global namespace. */
#define DECL_NAMESPACE_SCOPE_P(NODE) \
(DECL_CONTEXT (NODE) == NULL_TREE \
@@ -1200,6 +1341,11 @@ struct lang_decl
(DECL_CONTEXT (NODE) \
&& TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (NODE))) == 't')
+/* 1 iff NODE is function-local. */
+#define DECL_FUNCTION_SCOPE_P(NODE) \
+ (DECL_CONTEXT (NODE) \
+ && TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL)
+
/* 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. */
@@ -1215,6 +1361,11 @@ struct lang_decl
#define ORIGINAL_NAMESPACE(NODE) \
(DECL_NAMESPACE_ALIAS (NODE) ? DECL_NAMESPACE_ALIAS (NODE) : (NODE))
+/* In a non-local VAR_DECL with static storage duration, this is the
+ initialization priority. If this value is zero, the NODE will be
+ initialized at the DEFAULT_INIT_PRIORITY. */
+#define DECL_INIT_PRIORITY(NODE) (DECL_FIELD_SIZE ((NODE)))
+
/* In a TREE_LIST concatenating using directives, indicate indirekt
directives */
#define TREE_INDIRECT_USING(NODE) ((NODE)->common.lang_flag_0)
@@ -1246,23 +1397,86 @@ struct lang_decl
/* For a VAR_DECL or FUNCTION_DECL: template-specific information. */
#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.template_info)
+
+/* Template information for a RECORD_TYPE or UNION_TYPE. */
#define CLASSTYPE_TEMPLATE_INFO(NODE) (TYPE_LANG_SPECIFIC(NODE)->template_info)
+
+/* Template information for an ENUMERAL_TYPE. Although an enumeration may
+ not be a primary template, it may be declared within the scope of a
+ primary template and the enumeration constants may depend on
+ non-type template parameters. */
+#define ENUM_TEMPLATE_INFO(NODE) (TYPE_BINFO (NODE))
+
+/* Template information for a template template parameter. */
+#define TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO(NODE) (TYPE_BINFO (NODE))
+
+/* Template information for an ENUMERAL_, RECORD_, or UNION_TYPE. */
+#define TYPE_TEMPLATE_INFO(NODE) \
+ (TREE_CODE (NODE) == ENUMERAL_TYPE \
+ ? ENUM_TEMPLATE_INFO (NODE) : \
+ (TREE_CODE (NODE) == TEMPLATE_TEMPLATE_PARM \
+ ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE) \
+ : CLASSTYPE_TEMPLATE_INFO (NODE)))
+
+/* Set the template information for an ENUMERAL_, RECORD_, or
+ UNION_TYPE to VAL. */
+#define SET_TYPE_TEMPLATE_INFO(NODE, VAL) \
+ (TREE_CODE (NODE) == ENUMERAL_TYPE \
+ ? (ENUM_TEMPLATE_INFO (NODE) = VAL) \
+ : (CLASSTYPE_TEMPLATE_INFO (NODE) = VAL))
+
#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)
+
+/* The TEMPLATE_DECL instantiated or specialized by NODE. This
+ TEMPLATE_DECL will be the immediate parent, not the most general
+ template. For example, in:
+
+ template <class T> struct S { template <class U> void f(U); }
+
+ the FUNCTION_DECL for S<int>::f<double> will have, as its
+ DECL_TI_TEMPLATE, `template <class U> S<int>::f<U>'.
+
+ As a special case, for a member friend template of a template
+ class, this value will not be a TEMPLATE_DECL, but rather a
+ LOOKUP_EXPR or IDENTIFIER_NODE indicating the name of the template
+ and any explicit template arguments provided. For example, in:
+
+ template <class T> struct S { friend void f<int>(int, double); }
+
+ the DECL_TI_TEMPLATE will be a LOOKUP_EXPR for `f' and the
+ DECL_TI_ARGS will be {int}. */
#define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE))
+
+/* The template arguments used to obtain this decl from the most
+ general form of DECL_TI_TEMPLATE. For the example given for
+ DECL_TI_TEMPLATE, the DECL_TI_ARGS will be {int, double}. These
+ are always the full set of arguments required to instantiate this
+ declaration from the most general template specialized here. */
#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 ENUM_TI_TEMPLATE(NODE) \
+ TI_TEMPLATE (ENUM_TEMPLATE_INFO (NODE))
+#define ENUM_TI_ARGS(NODE) \
+ TI_ARGS (ENUM_TEMPLATE_INFO (NODE))
+
+/* Like DECL_TI_TEMPLATE, but for an ENUMERAL_, RECORD_, or UNION_TYPE. */
+#define TYPE_TI_TEMPLATE(NODE) \
+ (TI_TEMPLATE (TYPE_TEMPLATE_INFO (NODE)))
+
+/* Like DECL_TI_ARGS, , but for an ENUMERAL_, RECORD_, or UNION_TYPE. */
+#define TYPE_TI_ARGS(NODE) \
+ (TI_ARGS (TYPE_TEMPLATE_INFO (NODE)))
+
#define INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE(NODE)
+/* Nonzero if the NODE corresponds to the template parameters for a
+ member template, whose inline definition is being processed after
+ the class definition is complete. */
#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
#define DECL_SAVED_TREE(NODE) DECL_MEMFUNC_POINTER_TO (NODE)
@@ -1281,7 +1495,15 @@ struct lang_decl
&& !CLASSTYPE_USE_TEMPLATE (NODE) \
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))
-#define TYPENAME_TYPE_FULLNAME(NODE) CLASSTYPE_SIZE (NODE)
+/* The name used by the user to name the typename type. Typically,
+ this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the
+ corresponding TYPE_DECL. However, this may also be a
+ TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'. */
+#define TYPENAME_TYPE_FULLNAME(NODE) TYPE_BINFO (NODE)
+
+/* Nonzero if NODE is an implicit typename. */
+#define IMPLICIT_TYPENAME_P(NODE) \
+ (TREE_CODE (NODE) == TYPENAME_TYPE && TREE_TYPE (NODE))
/* Nonzero in INTEGER_CST means that this int is negative by dint of
using a twos-complement negated operand. */
@@ -1302,7 +1524,7 @@ struct lang_decl
/* 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))
+#define TREE_MANGLED(NODE) (FOO)
#endif
#if 0 /* UNUSED */
@@ -1338,6 +1560,12 @@ extern int flag_new_for_scope;
/* Record whether a typedef for type `int' was actually `signed int'. */
#define C_TYPEDEF_EXPLICITLY_SIGNED(exp) DECL_LANG_FLAG_1 ((exp))
+/* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */
+#define DECL_C_BIT_FIELD(NODE) \
+ (DECL_LANG_SPECIFIC (NODE) && DECL_LANG_SPECIFIC (NODE)->decl_flags.bitfield)
+#define SET_DECL_C_BIT_FIELD(NODE) \
+ (DECL_LANG_SPECIFIC (NODE)->decl_flags.bitfield = 1)
+
/* Nonzero if the type T promotes to itself.
ANSI C states explicitly the list of types that promote;
in particular, short promotes to int even if they have the same width. */
@@ -1377,8 +1605,9 @@ extern int flag_new_for_scope;
has been duly initialized in its constructor. */
#define TREE_HAS_CONSTRUCTOR(NODE) (TREE_LANG_FLAG_4(NODE))
-#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \
- && CONSTRUCTOR_ELTS (NODE) == NULL_TREE)
+#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \
+ && CONSTRUCTOR_ELTS (NODE) == NULL_TREE \
+ && ! TREE_HAS_CONSTRUCTOR (NODE))
#if 0
/* Indicates that a NON_LVALUE_EXPR came from a C++ reference.
@@ -1442,8 +1671,63 @@ extern int flag_new_for_scope;
/* Nonzero for _TYPE node means that this type is a pointer to member
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)
+#define TYPE_PTRMEMFUNC_P(NODE) \
+ (TREE_CODE(NODE) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (NODE))
+#define TYPE_PTRMEMFUNC_FLAG(NODE) \
+ (TYPE_LANG_SPECIFIC(NODE)->type_flags.ptrmemfunc_flag)
+
+/* A pointer-to-function member type looks like:
+
+ struct {
+ short __delta;
+ short __index;
+ union {
+ P __pfn;
+ short __delta2;
+ } __pfn_or_delta2;
+ };
+
+ where P is a POINTER_TYPE to a METHOD_TYPE appropriate for the
+ pointer to member. The fields are used as follows:
+
+ If __INDEX is -1, then the function to call is non-virtual, and
+ is located at the address given by __PFN.
+
+ If __INDEX is zero, then this a NULL pointer-to-member.
+
+ Otherwise, the function to call is virtual. Then, __DELTA2 gives
+ the offset from an instance of the object to the virtual function
+ table, and __INDEX - 1 is the index into the vtable to use to
+ find the function.
+
+ The value to use for the THIS parameter is the address of the
+ object plus __DELTA.
+
+ For example, given:
+
+ struct B1 {
+ int i;
+ };
+
+ struct B2 {
+ double d;
+ void f();
+ };
+
+ struct S : public B1, B2 {};
+
+ the pointer-to-member for `&S::f' looks like:
+
+ { 4, -1, { &f__2B2 } };
+
+ The `4' means that given an `S*' you have to add 4 bytes to get to
+ the address of the `B2*'. Then, the -1 indicates that this is a
+ non-virtual function. Of course, `&f__2B2' is the name of that
+ function.
+
+ (Of course, the exactl values may differ depending on the mangling
+ scheme, sizes of types, and such.). */
+
/* 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. */
@@ -1458,8 +1742,19 @@ extern int flag_new_for_scope;
#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, 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))
+#define DELTA2_FROM_PTRMEMFUNC(NODE) delta2_from_ptrmemfunc ((NODE))
+#define PFN_FROM_PTRMEMFUNC(NODE) pfn_from_ptrmemfunc ((NODE))
+
+/* For a pointer-to-member constant `X::Y' this is the RECORD_TYPE for
+ `X'. */
+#define PTRMEM_CST_CLASS(NODE) \
+ (TYPE_PTRMEM_P (TREE_TYPE (NODE)) \
+ ? TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (NODE))) \
+ : TYPE_PTRMEMFUNC_OBJECT_TYPE (TREE_TYPE (NODE)))
+
+/* For a pointer-to-member constant `X::Y' this is the _DECL for
+ `Y'. */
+#define PTRMEM_CST_MEMBER(NODE) (((ptrmem_cst_t) NODE)->member)
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
specified in its declaration. */
@@ -1469,19 +1764,20 @@ extern int flag_new_for_scope;
specified in its declaration. */
#define DECL_THIS_STATIC(NODE) (DECL_LANG_FLAG_6(NODE))
-/* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL. */
-#define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE))
-
/* Nonzero in FUNCTION_DECL means it is really an operator.
Just used to communicate formatting information to dbxout.c. */
#define DECL_OPERATOR(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.operator_attr)
#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)))
+/* Nonzero if TYPE is an anonymous union type. We have to use a flag for
+ this because "A union for which objects or pointers are declared is not
+ an anonymous union" [class.union]. */
+#define ANON_UNION_TYPE_P(NODE) \
+ (TYPE_LANG_SPECIFIC (NODE) \
+ && TYPE_LANG_SPECIFIC (NODE)->type_flags.anon_union)
+#define SET_ANON_UNION_TYPE_P(NODE) \
+ (TYPE_LANG_SPECIFIC (NODE)->type_flags.anon_union = 1)
#define UNKNOWN_TYPE LANG_TYPE
@@ -1515,9 +1811,15 @@ extern int flag_new_for_scope;
the TREE_PUROSE will be the class type, and the TREE_VALUE will be
NULL_TREE. */
#define DECL_FRIENDLIST(NODE) (DECL_INITIAL (NODE))
+#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
+#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
-/* The DECL_ACCESS is used to record under which context
- special access rules apply. */
+/* The DECL_ACCESS, if non-NULL, is a TREE_LIST. The TREE_PURPOSE of
+ each node is a type; the TREE_VALUE is the access granted for this
+ DECL in that type. The DECL_ACCESS is set by access declarations.
+ For example, if a member that would normally be public in a
+ derived class is made protected, then the derived class and the
+ protected_access_node will appear in the DECL_ACCESS for the node. */
#define DECL_ACCESS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.access)
/* C++: all of these are overloaded!
@@ -1528,32 +1830,88 @@ extern int flag_new_for_scope;
/* Accessor macros for C++ template decl nodes. */
/* 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). */
+ is a INT_CST whose TREE_INT_CST_HIGH 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_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
/* For function, method, class-data templates. */
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE)
+/* For a static member variable template, the
+ DECL_TEMPLATE_INSTANTIATIONS list contains the explicitly and
+ implicitly generated instantiations of the variable. There are no
+ partial instantiations of static member variables, so all of these
+ will be full instantiations.
+
+ For a class template the DECL_TEMPLATE_INSTANTIATIONS lists holds
+ all instantiations and specializations of the class type, including
+ partial instantiations and partial specializations.
+
+ In both cases, the TREE_PURPOSE of each node contains the arguments
+ used; the TREE_VALUE contains the generated variable. The template
+ arguments are always complete. For example, given:
+
+ template <class T> struct S1 {
+ template <class U> struct S2 {};
+ template <class U> struct S2<U*> {};
+ };
+
+ the record for the partial specialization will contain, as its
+ argument list, { {T}, {U*} }, and will be on the
+ DECL_TEMPLATE_INSTANTIATIONS list for `template <class T> template
+ <class U> struct S1<T>::S2'.
+
+ This list is not used for function templates. */
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
+/* For a function template, the DECL_TEMPLATE_SPECIALIZATIONS lists
+ contains all instantiations and specializations of the function,
+ including partial instantiations. For a partial instantiation
+ which is a specialization, this list holds only full
+ specializations of the template that are instantiations of the
+ partial instantiation. For example, given:
+
+ template <class T> struct S {
+ template <class U> void f(U);
+ template <> void f(T);
+ };
+
+ the `S<int>::f<int>(int)' function will appear on the
+ DECL_TEMPLATE_SPECIALIZATIONS list for both `template <class T>
+ template <class U> void S<T>::f(U)' and `template <class T> void
+ S<int>::f(T)'. In the latter case, however, it will have only the
+ innermost set of arguments (T, in this case). The DECL_TI_TEMPLATE
+ for the function declaration will point at the specialization, not
+ the fully general template.
+
+ For a class template, this list contains the partial
+ specializations of this template. (Full specializations are not
+ recorded on this list.) The TREE_PURPOSE holds the innermost
+ arguments used in the partial specialization (e.g., for `template
+ <class T> struct S<T*, int>' this will be `T*'.) The TREE_VALUE
+ holds the innermost template parameters for the specialization
+ (e.g., `T' in the example above.) The TREE_TYPE is the _TYPE node
+ for the partial specialization.
+
+ This list is not used for static variable templates. */
+#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
#define DECL_TEMPLATE_INJECT(NODE) DECL_INITIAL(NODE)
-/* Nonzero for TEMPLATE_DECL nodes that represents template template
- parameters */
+/* Nonzero for a DECL which is actually a template parameter. */
+#define DECL_TEMPLATE_PARM_P(NODE) \
+ DECL_LANG_FLAG_0 (NODE)
+
#define DECL_TEMPLATE_TEMPLATE_PARM_P(NODE) \
- (TREE_CODE (NODE) == TEMPLATE_DECL && TREE_TYPE (NODE) \
- && TREE_CODE (TREE_TYPE (NODE)) == TEMPLATE_TEMPLATE_PARM)
+ (TREE_CODE (NODE) == TEMPLATE_DECL && DECL_TEMPLATE_PARM_P (NODE))
#define DECL_FUNCTION_TEMPLATE_P(NODE) \
(TREE_CODE (NODE) == TEMPLATE_DECL \
@@ -1616,8 +1974,36 @@ extern int flag_new_for_scope;
#define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) = 3)
+/* Non-zero if DECL is a friend function which is an instantiation
+ from the point of view of the compiler, but not from the point of
+ view of the language. For example given:
+ template <class T> struct S { friend void f(T) {}; };
+ the declaration of `void f(int)' generated when S<int> is
+ instantiated will not be a DECL_TEMPLATE_INSTANTIATION, but will be
+ a DECL_FRIEND_PSUEDO_TEMPLATE_INSTANTIATION. */
+#define DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION(DECL) \
+ (DECL_TEMPLATE_INFO (DECL) && !DECL_USE_TEMPLATE (DECL))
+
+/* Non-zero if TYPE is a partial instantiation of a template class,
+ i.e., an instantiation whose instantiation arguments involve
+ template types. */
+#define PARTIAL_INSTANTIATION_P(TYPE) \
+ (TYPE_LANG_SPECIFIC (TYPE)->type_flags.is_partial_instantiation)
+
+/* Non-zero iff we are currently processing a declaration for an
+ entity with its own template parameter list, and which is not a
+ full specialization. */
+#define PROCESSING_REAL_TEMPLATE_DECL_P() \
+ (processing_template_decl > template_class_depth (current_class_type))
+
/* This function may be a guiding decl for a template. */
#define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE)
+
+/* Nonzero if this VAR_DECL or FUNCTION_DECL has already been
+ instantiated, i.e. its definition has been generated from the
+ pattern given in the the template. */
+#define DECL_TEMPLATE_INSTANTIATED(NODE) DECL_LANG_FLAG_1(NODE)
+
/* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
@@ -1636,10 +2022,6 @@ extern int flag_new_for_scope;
#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)
/* ...and for unexpanded-parameterized-type nodes. */
@@ -1710,6 +2092,11 @@ extern int warn_overloaded_virtual;
/* Nonzero means warn about use of multicharacter literals. */
extern int warn_multichar;
+/* Non-zero means warn if a non-templatized friend function is
+ declared in a templatized class. This behavior is warned about with
+ flag_guiding_decls in do_friend. */
+extern int warn_nontemplate_friend;
+
/* in c-common.c */
extern void declare_function_name PROTO((void));
extern void decl_attributes PROTO((tree, tree, tree));
@@ -1719,7 +2106,7 @@ extern void check_function_format PROTO((tree, tree, tree));
/* Print an error message for invalid operands to arith operation CODE.
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 cp_build_qualified_type PROTO((tree, 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. */
@@ -1730,6 +2117,8 @@ extern void constant_expression_warning PROTO((tree));
extern tree convert_and_check PROTO((tree, tree));
extern void overflow_warning PROTO((tree));
extern void unsigned_conversion_warning PROTO((tree, tree));
+extern void c_apply_type_quals_to_decl PROTO((int, tree));
+
/* Read the rest of the current #-directive line. */
#if USE_CPPLIB
extern char *get_directive_line PROTO((void));
@@ -1789,8 +2178,10 @@ extern tree opaque_type_node, signature_type_node;
#define vfunc_ptr_type_node \
(flag_vtable_thunks ? vtable_entry_type : ptr_type_node)
-/* Array type `(void *)[]' */
+/* The type of a vtbl, i.e., an array of vtable entries. */
extern tree vtbl_type_node;
+/* The type of a class vtbl pointer, i.e., a pointer to a vtable entry. */
+extern tree vtbl_ptr_type_node;
extern tree delta_type_node;
extern tree std_node;
@@ -1801,6 +2192,12 @@ extern tree boolean_type_node, boolean_true_node, boolean_false_node;
extern tree null_node;
+extern tree anonymous_namespace_name;
+
+/* The FUNCTION_DECL for the default `::operator delete'. */
+
+extern tree global_delete_fndecl;
+
/* in pt.c */
/* These values are used for the `STRICT' parameter to type_unfication and
@@ -1832,6 +2229,13 @@ extern int minimal_parse_mode;
extern void maybe_print_template_context PROTO ((void));
/* in class.c */
+
+/* When parsing a class definition, the access specifier most recently
+ given by the user, or, if no access specifier was given, the
+ default value appropriate for the kind of class (i.e., struct,
+ class, or union). */
+extern tree current_access_specifier;
+
extern tree current_class_name;
extern tree current_class_type;
extern tree current_class_ptr;
@@ -1842,6 +2246,9 @@ extern int current_class_depth;
extern tree current_lang_name;
extern tree lang_name_cplusplus, lang_name_c, lang_name_java;
+/* The low-water mark on the class-cache obstack. */
+extern char *class_cache_firstobj;
+
/* 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;
@@ -1858,12 +2265,6 @@ extern int current_function_parms_stored;
#define OPERATOR_ASSIGN_FORMAT "__a%s"
#define OPERATOR_FORMAT "__%s"
#define OPERATOR_TYPENAME_FORMAT "__op"
-#define OPERATOR_TYPENAME_P(ID_NODE) \
- (IDENTIFIER_POINTER (ID_NODE)[0] == '_' \
- && IDENTIFIER_POINTER (ID_NODE)[1] == '_' \
- && IDENTIFIER_POINTER (ID_NODE)[2] == 'o' \
- && IDENTIFIER_POINTER (ID_NODE)[3] == 'p')
-
/* Cannot use '$' up front, because this confuses gdb
(names beginning with '$' are gdb-local identifiers).
@@ -1986,9 +2387,9 @@ extern int current_function_parms_stored;
#define SIGNATURE_OPTR_NAME "__optr"
#define SIGNATURE_SPTR_NAME "__sptr"
#define SIGNATURE_POINTER_NAME "__sp_"
-#define SIGNATURE_POINTER_NAME_FORMAT "__%s%ssp_%s"
+#define SIGNATURE_POINTER_NAME_FORMAT "__%s%s%ssp_%s"
#define SIGNATURE_REFERENCE_NAME "__sr_"
-#define SIGNATURE_REFERENCE_NAME_FORMAT "__%s%ssr_%s"
+#define SIGNATURE_REFERENCE_NAME_FORMAT "__%s%s%ssr_%s"
#define SIGTABLE_PTR_TYPE "__sigtbl_ptr_type"
#define SIGTABLE_NAME_FORMAT "__st_%s_%s"
@@ -2028,6 +2429,14 @@ extern int current_function_parms_stored;
&& IDENTIFIER_POINTER (ID_NODE)[1] <= '9')
#endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */
+/* Store the vbase pointer field name for type TYPE into pointer BUF. */
+#define FORMAT_VBASE_NAME(BUF,TYPE) do { \
+ char *wbuf = (char *) alloca (TYPE_ASSEMBLER_NAME_LENGTH (TYPE) \
+ + sizeof (VBASE_NAME) + 1); \
+ sprintf (wbuf, VBASE_NAME_FORMAT, TYPE_ASSEMBLER_NAME_STRING (TYPE)); \
+ (BUF) = wbuf; \
+} while (0)
+
/* Returns non-zero iff ID_NODE is an IDENTIFIER_NODE whose name is
`main'. */
#define MAIN_NAME_P(ID_NODE) \
@@ -2037,7 +2446,7 @@ extern int current_function_parms_stored;
`main'. */
#define DECL_MAIN_P(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL \
- && DECL_CONTEXT (NODE) == NULL_TREE \
+ && DECL_LANGUAGE (NODE) == lang_c \
&& DECL_NAME (NODE) != NULL_TREE \
&& MAIN_NAME_P (DECL_NAME (NODE)))
@@ -2077,24 +2486,11 @@ struct pending_inline
/* in method.c */
extern struct pending_inline *pending_inlines;
-/* 1 for -fall-virtual: make every member function (except
- constructors) lay down in the virtual function table.
- Calls can then either go through the virtual function table or not,
- depending on whether we know what function will actually be called. */
-
-extern int flag_all_virtual;
-
/* Positive values means that we cannot make optimizing assumptions about
`this'. Negative values means we know `this' to be of static type. */
extern int flag_this_is_variable;
-/* Controls whether enums and ints freely convert.
- 1 means with complete freedom.
- 0 means enums can convert to ints, but not vice-versa. */
-
-extern int flag_int_enum_equivalence;
-
/* Nonzero means generate 'rtti' that give run-time type information. */
extern int flag_rtti;
@@ -2138,7 +2534,6 @@ 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 */
-extern tree current_class_type; /* _TYPE: the type of the current class */
/* Some macros for char-based bitfields. */
#define B_SET(a,x) (a[x>>3] |= (1 << (x&7)))
@@ -2233,11 +2628,47 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define WANT_ENUM 4 /* enumerated types */
#define WANT_POINTER 8 /* pointer types */
#define WANT_NULL 16 /* null pointer constant */
-
#define WANT_ARITH (WANT_INT | WANT_FLOAT)
-#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
-#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
+/* Used with comptypes, and related functions, to guide type
+ comparison. */
+
+#define COMPARE_STRICT 0 /* Just check if the types are the
+ same. */
+#define COMPARE_BASE 1 /* Check to see if the second type is
+ derived from the first, or if both
+ are pointers (or references) and
+ the types pointed to by the second
+ type is derived from the pointed to
+ by the first. */
+#define COMPARE_RELAXED 2 /* Like COMPARE_DERIVED, but in
+ reverse. Also treat enmeration
+ types as the same as integer types
+ of the same width. */
+#define COMPARE_REDECLARATION 4 /* The comparsion is being done when
+ another declaration of an existing
+ entity is seen. */
+#define COMPARE_NO_ATTRIBUTES 8 /* The comparison should ignore
+ extra-linguistic type attributes. */
+
+/* Used with push_overloaded_decl. */
+#define PUSH_GLOBAL 0 /* Push the DECL into namespace scope,
+ regardless of the current scope. */
+#define PUSH_LOCAL 1 /* Push the DECL into the current
+ scope. */
+#define PUSH_USING 2 /* We are pushing this DECL as the
+ result of a using declaration. */
+
+/* Returns nonzero iff TYPE1 and TYPE2 are the same type, in the usual
+ sense of `same'. */
+#define same_type_p(type1, type2) \
+ comptypes ((type1), (type2), COMPARE_STRICT)
+
+/* Returns nonzero iff TYPE1 and TYPE2 are the same type, or if TYPE2
+ is derived from TYPE1, or if TYPE2 is a pointer (reference) to a
+ class derived from the type pointed to (referred to) by TYPE1. */
+#define same_or_base_type_p(type1, type2) \
+ comptypes ((type1), (type2), COMPARE_BASE)
/* These macros are used to access a TEMPLATE_PARM_INDEX. */
#define TEMPLATE_PARM_IDX(NODE) (((template_parm_index*) NODE)->index)
@@ -2283,9 +2714,10 @@ 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 int enforce_access PROTO((tree, tree));
+extern tree convert_default_arg PROTO((tree, tree, tree));
extern tree convert_arg_to_ellipsis PROTO((tree));
+extern int is_properly_derived_from PROTO((tree, tree));
/* in class.c */
extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int));
@@ -2295,24 +2727,29 @@ 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, tree, int));
-extern tree finish_struct_1 PROTO((tree, int));
-extern tree finish_struct_methods PROTO((tree, tree, int));
+extern tree finish_struct PROTO((tree, tree, int));
+extern void finish_struct_1 PROTO((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 popclass PROTO((void));
extern void push_nested_class PROTO((tree, int));
-extern void pop_nested_class PROTO((int));
+extern void pop_nested_class PROTO((void));
extern void push_lang_context PROTO((tree));
extern void pop_lang_context 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 push_cache_obstack PROTO((void));
+extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *, tree));
+extern void build_self_reference PROTO((void));
extern void warn_hidden PROTO((tree));
+extern tree get_enclosing_class PROTO((tree));
+int is_base_of_enclosing_class PROTO((tree, tree));
+extern void unreverse_member_declarations PROTO((tree));
+extern void invalidate_class_lookup_cache PROTO((void));
+extern void maybe_note_name_used_in_class PROTO((tree, tree));
+extern void note_name_declared_in_class PROTO((tree, tree));
/* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
@@ -2323,15 +2760,17 @@ extern tree ocp_convert PROTO((tree, tree, int, int));
extern tree cp_convert PROTO((tree, tree));
extern tree convert PROTO((tree, tree));
extern tree convert_force PROTO((tree, tree, int));
-extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int));
+extern tree build_type_conversion PROTO((tree, tree, int));
extern tree build_expr_type_conversion PROTO((int, tree, int));
extern tree type_promotes_to PROTO((tree));
extern tree perform_qualification_conversions PROTO((tree, tree));
/* decl.c */
/* resume_binding_level */
+extern void set_identifier_local_value PROTO((tree, tree));
extern int global_bindings_p PROTO((void));
extern int toplevel_bindings_p PROTO((void));
+extern int namespace_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));
@@ -2348,7 +2787,6 @@ 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));
extern void print_binding_stack PROTO((void));
extern void print_binding_level PROTO((struct binding_level *));
extern void push_namespace PROTO((tree));
@@ -2358,7 +2796,6 @@ 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 void pushtag PROTO((tree, tree, int));
extern tree make_anon_name PROTO((void));
@@ -2367,7 +2804,7 @@ 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 tree pushdecl_class_level PROTO((tree));
+extern void pushdecl_class_level PROTO((tree));
#if 0
extern void pushdecl_nonclass_level PROTO((tree));
#endif
@@ -2375,14 +2812,13 @@ 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 void define_case_label PROTO((void));
extern tree getdecls PROTO((void));
extern tree gettags PROTO((void));
#if 0
@@ -2392,6 +2828,7 @@ 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 build_typename_type PROTO((tree, tree, 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));
@@ -2408,8 +2845,9 @@ extern tree auto_function PROTO((tree, tree, enum built_in_function));
extern void init_decl_processing PROTO((void));
extern int init_type_desc PROTO((void));
extern tree define_function
- PROTO((char *, tree, enum built_in_function,
- void (*) (tree), char *));
+ PROTO((const char *, tree, enum built_in_function,
+ void (*) (tree), const char *));
+extern tree check_tag_decl PROTO((tree));
extern void shadow_tag PROTO((tree));
extern tree groktypename PROTO((tree));
extern tree start_decl PROTO((tree, tree, int, tree, tree));
@@ -2424,44 +2862,60 @@ 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 PROTO((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));
+extern tree finish_enum PROTO((tree));
+extern tree build_enumerator PROTO((tree, tree, tree));
extern int start_function PROTO((tree, tree, tree, int));
extern void expand_start_early_try_stmts PROTO((void));
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));
+extern tree start_method PROTO((tree, 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 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));
+extern void fixup_anonymous_union PROTO((tree));
+extern int check_static_variable_definition PROTO((tree, tree));
+extern void push_local_binding PROTO((tree, tree, int));
+extern int push_class_binding PROTO((tree, tree));
+extern tree check_default_argument PROTO((tree, tree));
+extern tree push_overloaded_decl PROTO((tree, int));
+extern void clear_identifier_class_values PROTO((void));
+extern void storetags PROTO((tree));
+extern int vtable_decl_p PROTO((tree, void *));
+extern int vtype_decl_p PROTO((tree, void *));
+extern int sigtable_decl_p PROTO((tree, void *));
+typedef int (*walk_globals_pred) PROTO((tree, void *));
+typedef int (*walk_globals_fn) PROTO((tree *, void *));
+extern int walk_globals PROTO((walk_globals_pred,
+ walk_globals_fn,
+ void *));
+typedef int (*walk_namespaces_fn) PROTO((tree, void *));
+extern int walk_namespaces PROTO((walk_namespaces_fn,
+ void *));
+extern int wrapup_globals_for_namespace PROTO((tree, void *));
/* in decl2.c */
-extern int check_java_method PROTO((tree, tree));
-extern int flag_assume_nonnull_objects;
+extern int check_java_method PROTO((tree));
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 grok_x_components PROTO((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 void grokclassfn PROTO((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));
@@ -2482,17 +2936,13 @@ extern tree get_temp_name PROTO((tree, int));
extern tree get_temp_regvar PROTO((tree, tree));
extern void finish_anon_union PROTO((tree));
extern tree finish_table PROTO((tree, tree, tree, int));
-extern void finish_builtin_type PROTO((tree, char *, tree *, int, tree));
+extern void finish_builtin_type PROTO((tree, const char *,
+ tree *, int, tree));
extern tree coerce_new_type PROTO((tree));
extern tree coerce_delete_type PROTO((tree));
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));
@@ -2502,10 +2952,12 @@ 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 check_cp_case_value PROTO((tree));
-extern void set_decl_namespace PROTO((tree, tree));
+extern void set_decl_namespace PROTO((tree, tree, int));
extern tree current_decl_namespace PROTO((void));
extern void push_decl_namespace PROTO((tree));
extern void pop_decl_namespace PROTO((void));
+extern void push_scope PROTO((tree));
+extern void pop_scope PROTO((tree));
extern void do_namespace_alias PROTO((tree, tree));
extern void do_toplevel_using_decl PROTO((tree));
extern void do_local_using_decl PROTO((tree));
@@ -2515,16 +2967,19 @@ 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));
+extern void finish_static_data_member_decl PROTO((tree, tree, tree, int, int));
/* 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 ();
+/* The cp_* functions aren't suitable for ATTRIBUTE_PRINTF. */
+extern void cp_error PVPROTO((const char *, ...));
+extern void cp_error_at PVPROTO((const char *, ...));
+extern void cp_warning PVPROTO((const char *, ...));
+extern void cp_warning_at PVPROTO((const char *, ...));
+extern void cp_pedwarn PVPROTO((const char *, ...));
+extern void cp_pedwarn_at PVPROTO((const char *, ...));
+extern void cp_compiler_error PVPROTO((const char *, ...));
+extern void cp_sprintf PVPROTO((const char *, ...));
+extern void cp_deprecated PROTO((const char*));
/* in error.c */
extern void init_error PROTO((void));
@@ -2566,7 +3021,9 @@ 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));
+extern void add_friend PROTO((tree, tree));
+extern void add_friends PROTO((tree, tree, tree));
+extern tree do_friend PROTO((tree, tree, tree, tree, tree, enum overload_flags, tree, int));
/* in init.c */
extern void init_init_processing PROTO((void));
@@ -2574,7 +3031,7 @@ 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_member_init PROTO((tree, tree, tree));
-extern void expand_aggr_init PROTO((tree, tree, int, int));
+extern void expand_aggr_init PROTO((tree, tree, 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));
@@ -2586,7 +3043,7 @@ extern tree decl_constant_value PROTO((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_x_delete PROTO((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, int));
@@ -2594,7 +3051,7 @@ 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 char *file_name_nondirectory PROTO((const 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));
@@ -2602,7 +3059,6 @@ 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));
#endif
@@ -2629,12 +3085,14 @@ 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 void retrofit_lang_decl PROTO((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 dump_time_statistics PROTO((void));
-/* extern void compiler_error PROTO((char *, HOST_WIDE_INT, HOST_WIDE_INT)); */
-extern void yyerror PROTO((char *));
+extern void compiler_error PVPROTO((const char *, ...))
+ ATTRIBUTE_PRINTF_1;
+extern void yyerror PROTO((const char *));
extern void clear_inline_text_obstack PROTO((void));
extern void maybe_snarf_defarg PROTO((void));
extern tree snarf_defarg PROTO((void));
@@ -2642,6 +3100,7 @@ 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));
+extern int cp_type_qual_from_rid PROTO((tree));
/* in method.c */
extern void init_method PROTO((void));
@@ -2649,7 +3108,9 @@ extern void do_inline_function_hair PROTO((tree, tree));
extern char *build_overload_name PROTO((tree, int, int));
extern tree build_static_name PROTO((tree, 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_decl_overload_real PROTO((tree, tree, tree, tree,
+ tree, int));
+extern void set_mangled_name_for_decl PROTO((tree));
extern tree build_typename_overload PROTO((tree));
extern tree build_overload_with_type PROTO((tree, tree));
extern tree build_destructor_name PROTO((tree));
@@ -2661,22 +3122,21 @@ extern void synthesize_method PROTO((tree));
extern tree get_id_2 PROTO((char *, tree));
/* in pt.c */
-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 check_template_shadow PROTO ((tree));
+extern tree innermost_args PROTO ((tree));
+extern tree tsubst PROTO ((tree, tree, int, tree));
+extern tree tsubst_expr PROTO ((tree, tree, int, tree));
+extern tree tsubst_copy PROTO ((tree, tree, int, tree));
extern 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 maybe_end_member_template_processing PROTO((void));
+extern tree finish_member_template_decl PROTO((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 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((void));
@@ -2684,14 +3144,13 @@ 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_class PROTO((tree, tree, tree, tree, int));
extern tree lookup_template_function PROTO((tree, tree));
extern int uses_template_parms PROTO((tree));
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));
+extern int fn_type_unification PROTO((tree, tree, tree, tree, tree, unification_kind_t));
struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int));
extern int more_specialized PROTO((tree, tree, tree));
@@ -2699,7 +3158,6 @@ 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 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 ... */
@@ -2708,15 +3166,19 @@ 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 template_parms_equal PROTO((tree, 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 void maybe_process_partial_specialization PROTO((tree));
+extern void maybe_check_template_type PROTO((tree));
+extern tree most_specialized_instantiation PROTO((tree, tree));
+extern void print_candidates PROTO((tree));
+extern int instantiate_pending_templates PROTO((void));
extern int processing_specialization;
extern int processing_explicit_instantiation;
@@ -2725,7 +3187,7 @@ 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 init_repo PROTO((const char *));
extern void finish_repo PROTO((void));
/* in rtti.c */
@@ -2735,46 +3197,43 @@ 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 get_typeid_1 PROTO((tree));
extern tree build_dynamic_cast PROTO((tree, tree));
extern void synthesize_tinfo_fn PROTO((tree));
/* in search.c */
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 tree compute_access PROTO((tree, tree));
+extern int accessible_p PROTO((tree, tree));
extern tree lookup_field PROTO((tree, tree, int, int));
-extern tree lookup_nested_field PROTO((tree, int));
+extern int lookup_fnfields_1 PROTO((tree, tree));
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 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));
extern void clear_search_slots PROTO((tree));
extern tree get_vbase_types PROTO((tree));
-extern void build_mi_matrix PROTO((tree));
-extern void free_mi_matrix PROTO((void));
-extern void build_mi_virtuals PROTO((int, int));
-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((void));
extern void unuse_fields PROTO((tree));
-extern void unmark_finished_struct PROTO((tree));
extern void print_search_statistics PROTO((void));
extern void init_search_processing PROTO((void));
extern void reinit_search_statistics PROTO((void));
extern tree current_scope PROTO((void));
extern tree lookup_conversions PROTO((tree));
-extern tree get_template_base PROTO((tree, tree));
+extern tree binfo_for_vtable PROTO((tree));
+extern tree dfs_walk PROTO((tree,
+ tree (*)(tree, void *),
+ tree (*) (tree, void *),
+ void *));
+extern tree dfs_unmark PROTO((tree, void *));
+extern tree markedp PROTO((tree, void *));
/* in semantics.c */
extern void finish_expr_stmt PROTO((tree));
@@ -2821,7 +3280,7 @@ 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_qualified_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));
@@ -2835,14 +3294,22 @@ 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 tree finish_class_definition PROTO((tree, tree, int, int));
extern void finish_default_args PROTO((void));
extern void begin_inline_definitions PROTO((void));
-extern tree finish_member_class_template PROTO((tree, tree));
+extern void finish_inline_definitions PROTO((void));
+extern tree finish_member_class_template PROTO((tree));
+extern void finish_template_decl PROTO((tree));
+extern tree finish_template_type PROTO((tree, tree, int));
+extern void enter_scope_of PROTO((tree));
+extern tree finish_base_specifier PROTO((tree, tree, int));
+extern void finish_member_declaration PROTO((tree));
+extern void check_multiple_declarators PROTO((void));
+extern tree finish_typeof PROTO((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_type PROTO((tree));
+extern tree build_signature_reference_type PROTO((tree));
extern tree build_signature_pointer_constructor PROTO((tree, tree));
extern tree build_signature_method_call PROTO((tree, tree));
extern tree build_optr_ref PROTO((tree));
@@ -2855,13 +3322,15 @@ extern int yylex PROTO((void));
extern tree arbitrate_lookup PROTO((tree, tree, tree));
/* in tree.c */
+extern int pod_type_p PROTO((tree));
+extern void unshare_base_binfos PROTO((tree));
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 int lvalue_or_else PROTO((tree, const char *));
extern tree build_cplus_new PROTO((tree, tree));
extern tree get_target_expr PROTO((tree));
extern tree break_out_cleanups PROTO((tree));
@@ -2872,17 +3341,17 @@ extern tree build_cplus_array_type PROTO((tree, 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_cons PROTO((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 make_binfo PROTO((tree, tree, tree, tree, tree));
+extern tree make_binfo PROTO((tree, tree, tree, tree));
extern tree binfo_value PROTO((tree, tree));
extern tree reverse_path PROTO((tree));
extern int count_functions PROTO((tree));
extern int is_overloaded_fn PROTO((tree));
extern tree get_first_fn PROTO((tree));
extern tree binding_init PROTO((struct tree_binding*));
+extern int bound_pmf_p PROTO((tree));
extern tree ovl_cons PROTO((tree, tree));
extern tree scratch_ovl_cons PROTO((tree, tree));
extern int ovl_member PROTO((tree, tree));
@@ -2895,6 +3364,7 @@ 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 tree permanent_p PROTO((tree));
extern void print_lang_statistics PROTO((void));
extern void __eprintf
PROTO((const char *, const char *, unsigned, const char *));
@@ -2904,21 +3374,29 @@ extern tree break_out_target_exprs PROTO((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 decl_namespace_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 tree no_linkage_check PROTO((tree));
extern void debug_binfo PROTO((tree));
extern void push_expression_obstack PROTO((void));
+extern tree build_dummy_object PROTO((tree));
+extern tree maybe_dummy_object PROTO((tree, tree *));
+extern int is_dummy_object PROTO((tree));
+extern tree search_tree PROTO((tree, tree (*)(tree)));
+extern int cp_valid_lang_attribute PROTO((tree, tree, tree, tree));
+extern tree make_ptrmem_cst PROTO((tree, tree));
+
#define scratchalloc expralloc
#define scratch_tree_cons expr_tree_cons
#define build_scratch_list build_expr_list
@@ -2926,21 +3404,22 @@ extern void push_expression_obstack PROTO((void));
#define push_scratch_obstack push_expression_obstack
/* in typeck.c */
+extern int string_conv_p PROTO((tree, tree, int));
extern tree condition_conversion PROTO((tree));
extern tree target_type PROTO((tree));
extern tree require_complete_type PROTO((tree));
+extern tree require_complete_type_in_void PROTO((tree));
extern tree complete_type PROTO((tree));
-extern tree complete_type_or_else PROTO((tree));
+extern tree complete_type_or_else PROTO((tree, 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));
extern int comptypes PROTO((tree, tree, int));
extern int comp_target_types PROTO((tree, tree, int));
-extern int compparms PROTO((tree, tree, int));
+extern int compparms PROTO((tree, tree));
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));
@@ -2959,19 +3438,18 @@ 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_indirect_ref PROTO((tree, const char *));
+extern tree build_indirect_ref PROTO((tree, const char *));
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));
-extern tree convert_arguments PROTO((tree, tree, tree, tree, int));
+extern tree convert_arguments PROTO((tree, tree, tree, int));
extern tree build_x_binary_op PROTO((enum tree_code, tree, tree));
-extern tree build_binary_op PROTO((enum tree_code, tree, tree, int));
+extern tree build_binary_op PROTO((enum tree_code, tree, tree));
extern tree build_binary_op_nodefault PROTO((enum tree_code, tree, tree, enum tree_code));
-extern tree build_component_addr PROTO((tree, tree, char *));
extern tree build_x_unary_op PROTO((enum tree_code, tree));
extern tree build_unary_op PROTO((enum tree_code, tree, int));
extern tree unary_complex_lvalue PROTO((enum tree_code, tree));
@@ -2986,24 +3464,31 @@ extern tree build_const_cast PROTO((tree, tree));
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));
-extern tree convert_for_initialization PROTO((tree, tree, tree, int, char *, tree, int));
+extern tree convert_for_initialization PROTO((tree, tree, tree, int, const char *, tree, int));
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 int comp_ptr_ttypes PROTO((tree, tree));
extern int ptr_reasonably_similar PROTO((tree, tree));
extern tree build_ptrmemfunc PROTO((tree, tree, int));
+extern int cp_type_quals PROTO((tree));
+extern int cp_has_mutable_p PROTO((tree));
+extern int at_least_as_qualified_p PROTO((tree, tree));
+extern int more_qualified_p PROTO((tree, tree));
+extern tree build_ptrmemfunc1 PROTO((tree, tree, tree, tree, tree));
+extern void expand_ptrmemfunc_cst PROTO((tree, tree *, tree *, tree *, tree *));
+extern tree delta2_from_ptrmemfunc PROTO((tree));
+extern tree pfn_from_ptrmemfunc PROTO((tree));
/* in typeck2.c */
extern tree error_not_base_type PROTO((tree, tree));
extern tree binfo_or_else PROTO((tree, tree));
-extern void readonly_error PROTO((tree, char *, int));
+extern void readonly_error PROTO((tree, const 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_abort PROTO((int))
+ ATTRIBUTE_NORETURN;
extern void my_friendly_assert PROTO((int, int));
extern tree store_init_value PROTO((tree, tree));
extern tree digest_init PROTO((tree, tree, tree *));
@@ -3013,18 +3498,18 @@ 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 void check_for_new_type PROTO((const 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_begin PROTO((const char *));
extern void GNU_xref_end PROTO((int));
-extern void GNU_xref_file PROTO((char *));
+extern void GNU_xref_file PROTO((const 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));
-extern void GNU_xref_ref PROTO((tree, char *));
+extern void GNU_xref_ref PROTO((tree, const char *));
extern void GNU_xref_decl PROTO((tree, tree));
-extern void GNU_xref_call PROTO((tree, char *));
+extern void GNU_xref_call PROTO((tree, const char *));
extern void GNU_xref_function PROTO((tree, tree));
extern void GNU_xref_assign PROTO((tree));
extern void GNU_xref_hier PROTO((tree, tree, int, int, int));
diff --git a/contrib/gcc/cp/cvt.c b/contrib/gcc/cp/cvt.c
index 18b7d8b..7082726 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-96, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -31,12 +31,12 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "cp-tree.h"
#include "convert.h"
-
-extern tree static_aggregates;
+#include "toplev.h"
+#include "decl.h"
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));
+static tree build_up_reference PROTO((tree, tree, int));
/* Change of width--truncation and extension of integers or reals--
is represented with NOP_EXPR. Proper functioning of many things
@@ -85,7 +85,7 @@ cp_convert_to_pointer (type, expr)
return error_mark_node;
}
- rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);
+ rval = build_type_conversion (type, expr, 1);
if (rval)
{
if (rval == error_mark_node)
@@ -95,9 +95,6 @@ cp_convert_to_pointer (type, expr)
}
}
- 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
@@ -107,21 +104,8 @@ cp_convert_to_pointer (type, expr)
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;
-
+ tree decl = maybe_dummy_object (TYPE_METHOD_BASETYPE (fntype), 0);
expr = build (OFFSET_REF, fntype, decl, expr);
}
@@ -141,20 +125,26 @@ cp_convert_to_pointer (type, expr)
intype = TREE_TYPE (expr);
}
- if (TYPE_PTRMEMFUNC_P (intype))
- intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
-
form = TREE_CODE (intype);
- if (form == POINTER_TYPE || form == REFERENCE_TYPE)
+ if (POINTER_TYPE_P (intype))
{
intype = TYPE_MAIN_VARIANT (intype);
if (TYPE_MAIN_VARIANT (type) != intype
+ && TREE_CODE (type) == POINTER_TYPE
&& 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)
+ && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE
+ /* If EXPR is NULL, then we don't need to do any arithmetic
+ to convert it:
+
+ [conv.ptr]
+
+ The null pointer value is converted to the null pointer
+ value of the destination type. */
+ && !integer_zerop (expr))
{
enum tree_code code = PLUS_EXPR;
tree binfo = get_binfo (TREE_TYPE (type), TREE_TYPE (intype), 1);
@@ -186,13 +176,8 @@ 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 build_ptrmemfunc (type, expr, 1);
- if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
- && TREE_CODE (TREE_TYPE (intype)) == OFFSET_TYPE)
+ if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
{
tree b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
tree b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype));
@@ -210,10 +195,7 @@ cp_convert_to_pointer (type, expr)
if (binfo && ! TREE_VIA_VIRTUAL (binfo))
expr = size_binop (code, expr, BINFO_OFFSET (binfo));
}
-
- if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
- || (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
+ else if (TYPE_PTRMEMFUNC_P (type))
{
cp_error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type);
@@ -224,6 +206,14 @@ cp_convert_to_pointer (type, expr)
TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
return rval;
}
+ else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
+ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 1);
+ else if (TYPE_PTRMEMFUNC_P (intype))
+ {
+ cp_error ("cannot convert `%E' from type `%T' to type `%T'",
+ expr, intype, type);
+ return error_mark_node;
+ }
my_friendly_assert (form != OFFSET_TYPE, 186);
@@ -233,8 +223,8 @@ cp_convert_to_pointer (type, expr)
if (integer_zerop (expr))
{
- if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
- return build_ptrmemfunc (type, expr, 0);
+ if (TYPE_PTRMEMFUNC_P (type))
+ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
expr = build_int_2 (0, 0);
TREE_TYPE (expr) = type;
return expr;
@@ -254,6 +244,9 @@ cp_convert_to_pointer (type, expr)
return convert_to_pointer (type, expr);
}
+ if (type_unknown_p (expr))
+ return instantiate_type (type, expr, 1);
+
cp_error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type);
return error_mark_node;
@@ -335,9 +328,9 @@ convert_to_pointer_force (type, expr)
DIRECT_BIND in FLAGS controls how any temporaries are generated. */
static tree
-build_up_reference (type, arg, flags, checkconst)
+build_up_reference (type, arg, flags)
tree type, arg;
- int flags, checkconst;
+ int flags;
{
tree rval;
tree argtype = TREE_TYPE (arg);
@@ -356,11 +349,13 @@ build_up_reference (type, arg, flags, checkconst)
DECL_ARTIFICIAL (arg) = 1;
}
DECL_INITIAL (arg) = targ;
- cp_finish_decl (arg, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
+ cp_finish_decl (arg, targ, NULL_TREE, 0,
+ LOOKUP_ONLYCONVERTING|DIRECT_BIND);
}
else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
{
tree slot = build_decl (VAR_DECL, NULL_TREE, argtype);
+ DECL_ARTIFICIAL (slot) = 1;
arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (arg) = 1;
}
@@ -369,6 +364,9 @@ build_up_reference (type, arg, flags, checkconst)
address, transform all occurrences of the register, into a memory
reference we could win better. */
rval = build_unary_op (ADDR_EXPR, arg, 1);
+ if (rval == error_mark_node)
+ return error_mark_node;
+
if ((flags & LOOKUP_PROTECT)
&& TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
&& IS_AGGR_TYPE (argtype)
@@ -409,6 +407,16 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
tree rval_as_conversion = NULL_TREE;
int i;
+ if (TREE_CODE (type) == FUNCTION_TYPE && intype == unknown_type_node)
+ {
+ expr = instantiate_type (type, expr,
+ (flags & LOOKUP_COMPLAIN) != 0);
+ if (expr == error_mark_node)
+ return error_mark_node;
+
+ intype = TREE_TYPE (expr);
+ }
+
if (TREE_CODE (intype) == REFERENCE_TYPE)
my_friendly_abort (364);
@@ -422,7 +430,7 @@ 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, reftype, expr, 1);
+ = build_type_conversion (reftype, expr, 1);
if (rval_as_conversion && rval_as_conversion != error_mark_node
&& real_lvalue_p (rval_as_conversion))
@@ -440,37 +448,35 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
if (flags & LOOKUP_COMPLAIN)
{
tree ttl = TREE_TYPE (reftype);
- tree ttr;
-
- {
- int r = TREE_READONLY (expr);
- int v = TREE_THIS_VOLATILE (expr);
- ttr = cp_build_type_variant (TREE_TYPE (expr), r, v);
- }
+ tree ttr = lvalue_type (expr);
- if (! real_lvalue_p (expr) && ! TYPE_READONLY (ttl))
+ /* [dcl.init.ref] says that if an rvalue is used to
+ initialize a reference, then the reference must be to a
+ non-volatile const type. */
+ if (! real_lvalue_p (expr)
+ && !CP_TYPE_CONST_NON_VOLATILE_P (ttl))
{
- if (decl)
- /* Ensure semantics of [dcl.init.ref] */
- cp_pedwarn ("initialization of non-const reference `%#T' from rvalue `%T'",
- reftype, intype);
+ const char *msg;
+
+ if (CP_TYPE_VOLATILE_P (ttl) && decl)
+ msg = "initialization of volatile reference type `%#T'";
+ else if (CP_TYPE_VOLATILE_P (ttl))
+ msg = "conversion to volatile reference type `%#T'";
+ else if (decl)
+ msg = "initialization of non-const reference type `%#T'";
else
- cp_pedwarn ("conversion to non-const `%T' from rvalue `%T'",
- reftype, intype);
- }
- else if (! (convtype & CONV_CONST))
- {
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- cp_pedwarn ("conversion from `%T' to `%T' discards const",
- ttr, reftype);
- else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
- cp_pedwarn ("conversion from `%T' to `%T' discards volatile",
- ttr, reftype);
+ msg = "conversion to non-const reference type `%#T'";
+
+ cp_pedwarn (msg, reftype);
+ cp_pedwarn ("from rvalue of type `%T'", intype);
}
+ else if (! (convtype & CONV_CONST)
+ && !at_least_as_qualified_p (ttl, ttr))
+ cp_pedwarn ("conversion from `%T' to `%T' discards qualifiers",
+ ttr, reftype);
}
- return build_up_reference (reftype, expr, flags,
- ! (convtype & CONV_CONST));
+ return build_up_reference (reftype, expr, flags);
}
else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr))
{
@@ -482,7 +488,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
/* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they
meant. */
if (TREE_CODE (intype) == POINTER_TYPE
- && (comptypes (TREE_TYPE (intype), type, -1)))
+ && (comptypes (TREE_TYPE (intype), type,
+ COMPARE_BASE | COMPARE_RELAXED )))
cp_warning ("casting `%T' to `%T' does not dereference pointer",
intype, reftype);
@@ -497,11 +504,11 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
{
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 == NULL_TREE || rval == error_mark_node)
+ return rval;
+ rval = build_up_reference (reftype, rval, flags);
- if (rval && ! TYPE_READONLY (TREE_TYPE (reftype)))
+ if (rval && ! CP_TYPE_CONST_P (TREE_TYPE (reftype)))
cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary",
reftype, intype);
}
@@ -569,29 +576,29 @@ convert_pointer_to_real (binfo, expr)
binfo = NULL_TREE;
}
- ptr_type = cp_build_type_variant (type, TYPE_READONLY (TREE_TYPE (intype)),
- TYPE_VOLATILE (TREE_TYPE (intype)));
+ ptr_type = cp_build_qualified_type (type,
+ CP_TYPE_QUALS (TREE_TYPE (intype)));
ptr_type = build_pointer_type (ptr_type);
- if (ptr_type == TYPE_MAIN_VARIANT (intype))
+ if (same_type_p (ptr_type, TYPE_MAIN_VARIANT (intype)))
return expr;
my_friendly_assert (!integer_zerop (expr), 191);
+ intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype));
if (TREE_CODE (type) == RECORD_TYPE
- && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE
- && type != TYPE_MAIN_VARIANT (TREE_TYPE (intype)))
+ && TREE_CODE (intype) == RECORD_TYPE
+ && type != intype)
{
tree path;
int distance
- = get_base_distance (binfo, TYPE_MAIN_VARIANT (TREE_TYPE (intype)),
- 0, &path);
+ = get_base_distance (binfo, intype, 0, &path);
/* This function shouldn't be called with unqualified arguments
but if it is, give them an error message that they can read. */
if (distance < 0)
{
cp_error ("cannot convert a pointer of type `%T' to a pointer of type `%T'",
- TREE_TYPE (intype), type);
+ intype, type);
if (distance == -2)
cp_error ("because `%T' is an ambiguous base class", type);
@@ -663,11 +670,27 @@ ocp_convert (type, expr, convtype, flags)
&& 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. */
- return fold (build1 (NOP_EXPR, type, e));
-
+ {
+ if (same_type_p (type, TREE_TYPE (e)))
+ /* The call to fold will not always remove the NOP_EXPR as
+ might be expected, since if one of the types is a typedef;
+ the comparsion in fold is just equality of pointers, not a
+ call to comptypes. We don't call fold in this case because
+ that can result in infinite recursion; fold will call
+ convert, which will call ocp_convert, etc. */
+ return e;
+ else
+ return fold (build1 (NOP_EXPR, type, e));
+ }
+
if (code == VOID_TYPE && (convtype & CONV_STATIC))
- return build1 (CONVERT_EXPR, type, e);
+ {
+ e = require_complete_type_in_void (e);
+ if (e != error_mark_node)
+ e = build1 (CONVERT_EXPR, void_type_node, e);
+
+ return e;
+ }
#if 0
/* This is incorrect. A truncation can't be stripped this way.
@@ -698,8 +721,7 @@ ocp_convert (type, expr, convtype, flags)
tree intype = TREE_TYPE (e);
/* enum = enum, enum = int, enum = float, (enum)pointer are all
errors. */
- if (flag_int_enum_equivalence == 0
- && TREE_CODE (type) == ENUMERAL_TYPE
+ if (TREE_CODE (type) == ENUMERAL_TYPE
&& ((ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC))
|| (TREE_CODE (intype) == POINTER_TYPE)))
{
@@ -711,7 +733,7 @@ ocp_convert (type, expr, convtype, flags)
if (IS_AGGR_TYPE (intype))
{
tree rval;
- rval = build_type_conversion (CONVERT_EXPR, type, e, 1);
+ rval = build_type_conversion (type, e, 1);
if (rval)
return rval;
if (flags & LOOKUP_COMPLAIN)
@@ -738,7 +760,7 @@ ocp_convert (type, expr, convtype, flags)
if (IS_AGGR_TYPE (TREE_TYPE (e)))
{
tree rval;
- rval = build_type_conversion (CONVERT_EXPR, type, e, 1);
+ rval = build_type_conversion (type, e, 1);
if (rval)
return rval;
else
@@ -794,6 +816,12 @@ ocp_convert (type, expr, convtype, flags)
ctor = e;
+ if (IS_AGGR_TYPE (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type))
+ {
+ abstract_virtuals_error (NULL_TREE, type);
+ return error_mark_node;
+ }
+
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
@@ -918,8 +946,7 @@ convert_force (type, expr, convtype)
(jason 8/9/95) */
tree
-build_type_conversion (code, xtype, expr, for_sure)
- enum tree_code code;
+build_type_conversion (xtype, expr, for_sure)
tree xtype, expr;
int for_sure;
{
@@ -941,10 +968,15 @@ build_expr_type_conversion (desires, expr, complain)
int complain;
{
tree basetype = TREE_TYPE (expr);
- tree conv;
+ tree conv = NULL_TREE;
tree winner = NULL_TREE;
- if (TREE_CODE (basetype) == OFFSET_TYPE)
+ if (expr == null_node
+ && (desires & WANT_INT)
+ && !(desires & WANT_NULL))
+ cp_warning ("converting NULL to non-pointer type");
+
+ if (TREE_CODE (expr) == OFFSET_REF)
expr = resolve_offset_ref (expr);
expr = convert_from_reference (expr);
basetype = TREE_TYPE (expr);
@@ -953,8 +985,7 @@ build_expr_type_conversion (desires, expr, complain)
switch (TREE_CODE (basetype))
{
case INTEGER_TYPE:
- if ((desires & WANT_NULL) && TREE_CODE (expr) == INTEGER_CST
- && integer_zerop (expr))
+ if ((desires & WANT_NULL) && null_ptr_cst_p (expr))
return expr;
/* else fall through... */
@@ -1045,13 +1076,12 @@ tree
type_promotes_to (type)
tree type;
{
- int constp, volatilep;
+ int type_quals;
if (type == error_mark_node)
return error_mark_node;
- constp = TYPE_READONLY (type);
- volatilep = TYPE_VOLATILE (type);
+ type_quals = CP_TYPE_QUALS (type);
type = TYPE_MAIN_VARIANT (type);
/* bool always promotes to int (not unsigned), even if it's the same
@@ -1085,10 +1115,9 @@ type_promotes_to (type)
else if (type == float_type_node)
type = double_type_node;
- return cp_build_type_variant (type, constp, volatilep);
+ return cp_build_qualified_type (type, type_quals);
}
-
/* 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
@@ -1103,7 +1132,9 @@ perform_qualification_conversions (type, expr)
tree type;
tree expr;
{
- if (comp_target_types (type, TREE_TYPE (expr), 0) == 1)
+ if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
+ && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (expr))))
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 68f62ae..c60acc7 100644
--- a/contrib/gcc/cp/decl.c
+++ b/contrib/gcc/cp/decl.c
@@ -1,5 +1,5 @@
/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "toplev.h"
+#include "../hash.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -60,9 +61,8 @@ extern tree current_namespace;
extern tree global_namespace;
extern void (*print_error_function) PROTO((char *));
+extern int (*valid_lang_attribute) PROTO ((tree, tree, tree, tree));
-/* 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"
@@ -133,8 +133,7 @@ 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 tree push_overloaded_decl PROTO((tree, int));
+static const char *redeclaration_error_message PROTO((tree, tree));
static struct stack_level *push_decl_level PROTO((struct stack_level *,
struct obstack *));
@@ -144,11 +143,9 @@ 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 signal_catch PROTO((int)) ATTRIBUTE_NORETURN;
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));
@@ -162,20 +159,39 @@ 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));
+ 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,
+static void record_builtin_type PROTO((enum rid, const char *, tree));
+static void record_unknown_type PROTO((tree, const char *));
+static int member_function_or_else PROTO((tree, tree, const char *));
+static void bad_specifiers PROTO((tree, const char *, int, int, int, int,
int));
static void lang_print_error_function PROTO((char *));
+static tree maybe_process_template_type_declaration PROTO((tree, int, struct binding_level*));
+static void check_for_uninitialized_const_var PROTO((tree));
+static unsigned long typename_hash PROTO((hash_table_key));
+static boolean typename_compare PROTO((hash_table_key, hash_table_key));
+static void push_binding PROTO((tree, tree, struct binding_level*));
+static int add_binding PROTO((tree, tree));
+static void pop_binding PROTO((tree, tree));
+static tree local_variable_p PROTO((tree));
+static tree find_binding PROTO((tree, tree));
+static tree select_decl PROTO((tree, int));
+static tree unqualified_namespace_lookup PROTO((tree, int));
+static int lookup_flags PROTO((int, int));
+static tree qualify_lookup PROTO((tree, int));
+static tree record_builtin_java_type PROTO((const char *, int));
+static const char *tag_name PROTO((enum tag_types code));
+static void find_class_binding_level PROTO((void));
+static struct binding_level *innermost_nonclass_level PROTO((void));
+static tree poplevel_class PROTO((void));
+static void warn_about_implicit_typename_lookup PROTO((tree, tree));
+static int walk_namespaces_r PROTO((tree, walk_namespaces_fn, void *));
+static int walk_globals_r PROTO((tree, void *));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
@@ -228,13 +244,17 @@ tree intQI_type_node;
tree intHI_type_node;
tree intSI_type_node;
tree intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
tree intTI_type_node;
+#endif
tree unsigned_intQI_type_node;
tree unsigned_intHI_type_node;
tree unsigned_intSI_type_node;
tree unsigned_intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
tree unsigned_intTI_type_node;
+#endif
tree java_byte_type_node;
tree java_short_type_node;
@@ -328,6 +348,7 @@ tree sigtable_entry_type;
/* Array type `vtable_entry_type[]' */
tree vtbl_type_node;
+tree vtbl_ptr_type_node;
/* namespace std */
tree std_node;
@@ -364,6 +385,10 @@ tree ctor_label;
tree abort_fndecl;
+/* A FUNCTION_DECL for the default `::operator delete'. */
+
+tree global_delete_fndecl;
+
extern rtx cleanup_label, return_label;
/* If original DECL_RESULT of current function was a register,
@@ -428,9 +453,8 @@ tree static_aggregates;
tree integer_zero_node;
tree null_pointer_node;
-/* The value for __null (NULL), either of type `void *' or, with -ansi,
- an integer type of the same size. */
-
+/* The value for __null (NULL), namely, a zero of an integer type with
+ the same number of bits as a pointer. */
tree null_node;
/* A node for the integer constants 1, 2, and 3. */
@@ -496,11 +520,6 @@ int current_function_returns_null;
tree current_function_return_value;
-/* Set to nonzero by `grokdeclarator' for a function
- whose return type is defaulted, if warnings for this are desired. */
-
-static int warn_about_return_type;
-
/* Nonzero means give `double' the same size as `float'. */
extern int flag_short_double;
@@ -559,6 +578,10 @@ extern tree previous_class_values;
node, but signed. */
tree signed_size_zero_node;
+/* The name of the anonymous namespace, throughout this translation
+ unit. */
+tree anonymous_namespace_name;
+
/* Allocate a level of searching. */
@@ -590,7 +613,10 @@ push_decl_level (stack, obstack)
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. */
+ run when exceptions occur. Thus, to see whether a name is bound in
+ the current scope, it is not enough to look in the
+ CURRENT_BINDING_LEVEL. You should use lookup_name_current_level
+ instead. */
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
@@ -599,7 +625,8 @@ 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. */
+ supplied. There may be OVERLOADs on this list, too, but they
+ are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD. */
tree names;
/* A list of structure, union and enum definitions, for looking up
@@ -619,16 +646,17 @@ struct binding_level
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
- whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
- tree shadowed;
-
- /* Same, for IDENTIFIER_CLASS_VALUE. */
+ /* If this binding level is the binding level for a class, then
+ class_shadowed is a TREE_LIST. The TREE_PURPOSE of each node
+ is the name of an entity bound in the class; the TREE_VALUE is
+ the IDENTIFIER_CLASS_VALUE before we entered the class. Thus,
+ when leaving class scope, we can restore the
+ IDENTIFIER_CLASS_VALUE by walking this list. The TREE_TYPE is
+ the DECL bound by this name in the class. */
tree class_shadowed;
- /* Same, for IDENTIFIER_TYPE_VALUE. */
+ /* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and
+ is used for all binding levels. */
tree type_shadowed;
/* For each level (except not the global one),
@@ -649,7 +677,8 @@ 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 ARM-era code. */
+ be referenced in ARM-era code. These are stored in a
+ TREE_LIST; the TREE_VALUE is the actual declaration. */
tree dead_vars_from_for;
/* 1 for the level that holds the parameters of a function.
@@ -691,7 +720,7 @@ struct binding_level
#define NULL_BINDING_LEVEL ((struct binding_level *) NULL)
-/* The (non-class) binding level currently in effect. */
+/* The binding level currently in effect. */
static struct binding_level *current_binding_level;
@@ -699,11 +728,6 @@ static struct binding_level *current_binding_level;
static struct binding_level *class_binding_level;
-/* The current (class or non-class) binding level currently in effect. */
-
-#define inner_binding_level \
- (class_binding_level ? class_binding_level : current_binding_level)
-
/* A chain of binding_level structures awaiting reuse. */
static struct binding_level *free_binding_level;
@@ -746,15 +770,7 @@ push_binding_level (newlevel, tag_transparent, keep)
/* Add this level to the front of the chain (stack) of levels that
are active. */
*newlevel = clear_binding_level;
- if (class_binding_level)
- {
- newlevel->level_chain = class_binding_level;
- class_binding_level = (struct binding_level *)0;
- }
- else
- {
- newlevel->level_chain = current_binding_level;
- }
+ newlevel->level_chain = current_binding_level;
current_binding_level = newlevel;
newlevel->tag_transparent = tag_transparent;
newlevel->more_cleanups_ok = 1;
@@ -769,12 +785,25 @@ push_binding_level (newlevel, tag_transparent, keep)
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
}
+/* Find the innermost enclosing class scope, and reset
+ CLASS_BINDING_LEVEL appropriately. */
+
+static void
+find_class_binding_level ()
+{
+ struct binding_level *level = current_binding_level;
+
+ while (level && level->parm_flag != 2)
+ level = level->level_chain;
+ if (level && level->parm_flag == 2)
+ class_binding_level = level;
+ else
+ class_binding_level = 0;
+}
+
static void
pop_binding_level ()
{
- if (class_binding_level)
- current_binding_level = class_binding_level;
-
if (global_binding_level)
{
/* Cannot pop a level, if there are none left to pop. */
@@ -803,13 +832,8 @@ pop_binding_level ()
if (level->binding_depth != binding_depth)
abort ();
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
- free_binding_level = level;
-
- class_binding_level = current_binding_level;
- if (class_binding_level->parm_flag != 2)
- class_binding_level = 0;
- while (current_binding_level->parm_flag == 2)
- current_binding_level = current_binding_level->level_chain;
+ free_binding_level = level;
+ find_class_binding_level ();
}
}
@@ -839,14 +863,8 @@ suspend_binding_level ()
}
is_class_level = 0;
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
- {
- current_binding_level = current_binding_level->level_chain;
- class_binding_level = current_binding_level;
- if (class_binding_level->parm_flag != 2)
- class_binding_level = 0;
- while (current_binding_level->parm_flag == 2)
- current_binding_level = current_binding_level->level_chain;
- }
+ current_binding_level = current_binding_level->level_chain;
+ find_class_binding_level ();
}
static void
@@ -887,25 +905,44 @@ global_bindings_p ()
return current_binding_level == global_binding_level;
}
+/* Return the innermost binding level that is not for a class scope. */
+
+static struct binding_level *
+innermost_nonclass_level ()
+{
+ struct binding_level *b;
+
+ b = current_binding_level;
+ while (b->parm_flag == 2)
+ b = b->level_chain;
+
+ return b;
+}
+
/* 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.
- Since there are no non-toplevel namespace levels, this really
- means any namespace or pseudo-global level. */
+ binding level. Since there are no non-toplevel namespace levels,
+ this really means any namespace or pseudo-global level. We also
+ include a class whose context is toplevel. */
int
toplevel_bindings_p ()
{
- return current_binding_level->namespace_p
- || current_binding_level->pseudo_global;
+ struct binding_level *b = innermost_nonclass_level ();
+
+ return b->namespace_p || b->pseudo_global;
}
-/* Nonzero if this is a namespace scope. */
+/* Nonzero if this is a namespace scope, or if we are defining a class
+ which is itself at namespace scope, or whose enclosing class is
+ such a class, etc. */
-static int
+int
namespace_bindings_p ()
{
- return current_binding_level->namespace_p;
+ struct binding_level *b = innermost_nonclass_level ();
+
+ return b->namespace_p;
}
void
@@ -949,7 +986,9 @@ declare_namespace_level ()
int
pseudo_global_level_p ()
{
- return current_binding_level->pseudo_global;
+ struct binding_level *b = innermost_nonclass_level ();
+
+ return b->pseudo_global;
}
void
@@ -1018,6 +1057,255 @@ pushlevel_temporary (tag_transparent)
expand_start_bindings (0);
}
+/* For a binding between a name and an entity at a block scope,
+ this is the `struct binding_level' for the block. */
+#define BINDING_LEVEL(NODE) \
+ (((struct tree_binding*)NODE)->scope.level)
+
+/* These are currently unused, but permanent, CPLUS_BINDING nodes.
+ They are kept here because they are allocated from the permanent
+ obstack and cannot be easily freed. */
+static tree free_binding_nodes;
+
+/* Make DECL the innermost binding for ID. The LEVEL is the binding
+ level at which this declaration is being bound. */
+
+static void
+push_binding (id, decl, level)
+ tree id;
+ tree decl;
+ struct binding_level* level;
+{
+ tree binding;
+
+ if (!free_binding_nodes)
+ {
+ /* There are no free nodes, so we must build one here. */
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ binding = make_node (CPLUS_BINDING);
+ pop_obstacks ();
+ }
+ else
+ {
+ /* There are nodes on the free list. Grab the first one. */
+ binding = free_binding_nodes;
+
+ /* And update the free list. */
+ free_binding_nodes = TREE_CHAIN (free_binding_nodes);
+ }
+
+ /* Now, fill in the binding information. */
+ BINDING_VALUE (binding) = decl;
+ BINDING_TYPE (binding) = NULL_TREE;
+ BINDING_LEVEL (binding) = level;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ LOCAL_BINDING_P (binding) = (level != class_binding_level);
+
+ /* And put it on the front of the list of bindings for ID. */
+ TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
+ IDENTIFIER_BINDING (id) = binding;
+}
+
+/* ID is already bound in the current scope. But, DECL is an
+ additional binding for ID in the same scope. This is the `struct
+ stat' hack whereby a non-typedef class-name or enum-name can be
+ bound at the same level as some other kind of entity. It's the
+ responsibility of the caller to check that inserting this name is
+ legal here. Returns nonzero if the new binding was successful. */
+static int
+add_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ tree binding = IDENTIFIER_BINDING (id);
+ int ok = 1;
+
+ if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+ /* The new name is the type name. */
+ BINDING_TYPE (binding) = decl;
+ else if (!BINDING_VALUE (binding))
+ /* This situation arises when push_class_level_binding moves an
+ inherited type-binding out of the way to make room for a new
+ value binding. */
+ BINDING_VALUE (binding) = decl;
+ else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+ && DECL_ARTIFICIAL (BINDING_VALUE (binding)))
+ {
+ /* The old binding was a type name. It was placed in
+ BINDING_VALUE because it was thought, at the point it was
+ declared, to be the only entity with such a name. Move the
+ type name into the type slot; it is now hidden by the new
+ binding. */
+ BINDING_TYPE (binding) = BINDING_VALUE (binding);
+ BINDING_VALUE (binding) = decl;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ }
+ else
+ {
+ cp_error ("declaration of `%#D'", decl);
+ cp_error_at ("conflicts with previous declaration `%#D'",
+ BINDING_VALUE (binding));
+ ok = 0;
+ }
+
+ return ok;
+}
+
+/* Bind DECL to ID in the current_binding_level.
+ If PUSH_USING is set in FLAGS, we know that DECL doesn't really belong
+ to this binding level, that it got here through a using-declaration. */
+
+void
+push_local_binding (id, decl, flags)
+ tree id;
+ tree decl;
+ int flags;
+{
+ struct binding_level *b;
+
+ /* Skip over any local classes. This makes sense if we call
+ push_local_binding with a friend decl of a local class. */
+ b = current_binding_level;
+ while (b->parm_flag == 2)
+ b = b->level_chain;
+
+ if (lookup_name_current_level (id))
+ {
+ /* Supplement the existing binding. */
+ if (!add_binding (id, decl))
+ /* It didn't work. Something else must be bound at this
+ level. Do not add DECL to the list of things to pop
+ later. */
+ return;
+ }
+ else
+ /* Create a new binding. */
+ push_binding (id, decl, b);
+
+ if (TREE_CODE (decl) == OVERLOAD || (flags & PUSH_USING))
+ /* We must put the OVERLOAD into a TREE_LIST since the
+ TREE_CHAIN of an OVERLOAD is already used. Similarly for
+ decls that got here through a using-declaration. */
+ decl = build_tree_list (NULL_TREE, decl);
+
+ /* And put DECL on the list of things declared by the current
+ binding level. */
+ TREE_CHAIN (decl) = b->names;
+ b->names = decl;
+}
+
+/* Bind DECL to ID in the class_binding_level. Returns nonzero if the
+ binding was successful. */
+
+int
+push_class_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ int result = 1;
+ tree binding = IDENTIFIER_BINDING (id);
+ tree context;
+
+ /* Note that we declared this value so that we can issue an error if
+ this an illegal redeclaration of a name already used for some
+ other purpose. */
+ note_name_declared_in_class (id, decl);
+
+ if (binding && BINDING_LEVEL (binding) == class_binding_level)
+ /* Supplement the existing binding. */
+ result = add_binding (id, decl);
+ else
+ /* Create a new binding. */
+ push_binding (id, decl, class_binding_level);
+
+ /* Update the IDENTIFIER_CLASS_VALUE for this ID to be the
+ class-level declaration. Note that we do not use DECL here
+ because of the possibility of the `struct stat' hack; if DECL is
+ a class-name or enum-name we might prefer a field-name, or some
+ such. */
+ IDENTIFIER_CLASS_VALUE (id) = BINDING_VALUE (IDENTIFIER_BINDING (id));
+
+ /* If this is a binding from a base class, mark it as such. */
+ binding = IDENTIFIER_BINDING (id);
+ if (BINDING_VALUE (binding) == decl && TREE_CODE (decl) != TREE_LIST)
+ {
+ /* Any implicit typename must be from a base-class. The
+ context for an implicit typename declaration is always
+ the derived class in which the lookup was done, so the checks
+ based on the context of DECL below will not trigger. */
+ if (TREE_CODE (decl) == TYPE_DECL
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (decl)))
+ INHERITED_VALUE_BINDING_P (binding) = 1;
+ else
+ {
+ if (TREE_CODE (decl) == OVERLOAD)
+ context = DECL_REAL_CONTEXT (OVL_CURRENT (decl));
+ else
+ {
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd',
+ 0);
+ context = DECL_REAL_CONTEXT (decl);
+ }
+
+ if (is_properly_derived_from (current_class_type, context))
+ INHERITED_VALUE_BINDING_P (binding) = 1;
+ else
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ }
+ }
+ else if (BINDING_VALUE (binding) == decl)
+ /* We only encounter a TREE_LIST when push_class_decls detects an
+ ambiguity. Such an ambiguity can be overridden by a definition
+ in this class. */
+ INHERITED_VALUE_BINDING_P (binding) = 1;
+
+ return result;
+}
+
+/* Remove the binding for DECL which should be the innermost binding
+ for ID. */
+
+static void
+pop_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ tree binding;
+
+ if (id == NULL_TREE)
+ /* It's easiest to write the loops that call this function without
+ checking whether or not the entities involved have names. We
+ get here for such an entity. */
+ return;
+
+ /* Get the innermost binding for ID. */
+ binding = IDENTIFIER_BINDING (id);
+
+ /* The name should be bound. */
+ my_friendly_assert (binding != NULL_TREE, 0);
+
+ /* The DECL will be either the ordinary binding or the type
+ binding for this identifier. Remove that binding. */
+ if (BINDING_VALUE (binding) == decl)
+ BINDING_VALUE (binding) = NULL_TREE;
+ else if (BINDING_TYPE (binding) == decl)
+ BINDING_TYPE (binding) = NULL_TREE;
+ else
+ my_friendly_abort (0);
+
+ if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
+ {
+ /* We're completely done with the innermost binding for this
+ identifier. Unhook it from the list of bindings. */
+ IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+
+ /* And place it on the free list. */
+ TREE_CHAIN (binding) = free_binding_nodes;
+ free_binding_nodes = binding;
+ }
+}
+
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
@@ -1026,12 +1314,6 @@ pushlevel_temporary (tag_transparent)
and create a "block" (a BLOCK node) for the level
to record its declarations and subblocks for symbol table output.
- If KEEP == 2, this level's subblocks go to the front,
- not the back of the current binding level. This happens,
- for instance, when code for constructors and destructors
- need to generate code at the end of a function which must
- be moved up to the front of the function.
-
If FUNCTIONBODY is nonzero, this level is the body of a function,
so create a block as if KEEP were set and also clear out all
label names.
@@ -1057,6 +1339,18 @@ poplevel (keep, reverse, functionbody)
tree block = NULL_TREE;
tree decl;
int block_previously_created;
+ int leaving_for_scope;
+
+ if (current_binding_level->parm_flag == 2)
+ return poplevel_class ();
+
+ my_friendly_assert (!current_binding_level->class_shadowed,
+ 19990414);
+
+ /* We used to use KEEP == 2 to indicate that the new block should go
+ at the beginning of the list of blocks at this binding level,
+ rather than the end. This hack is no longer used. */
+ my_friendly_assert (keep == 0 || keep == 1, 0);
GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain,
@@ -1116,9 +1410,8 @@ poplevel (keep, reverse, functionbody)
if (decls || tags || subblocks)
{
if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block))
- {
- warning ("internal compiler error: debugging info corrupted");
- }
+ warning ("internal compiler error: debugging info corrupted");
+
BLOCK_VARS (block) = decls;
BLOCK_TYPE_TAGS (block) = tags;
@@ -1137,7 +1430,8 @@ poplevel (keep, reverse, functionbody)
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. */
+ /* Otherwise, for a new block, install a new BLOCK_END_NOTE
+ value. */
remember_end_note (block);
}
}
@@ -1148,92 +1442,123 @@ poplevel (keep, reverse, functionbody)
for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
- /* Clear out the meanings of the local variables of this level. */
+ /* We still support the old for-scope rules, whereby the variables
+ in a for-init statement were in scope after the for-statement
+ ended. We only use the new rules in flag_new_for_scope is
+ nonzero. */
+ leaving_for_scope
+ = current_binding_level->is_for_scope && flag_new_for_scope == 1;
- if (current_binding_level->is_for_scope && flag_new_for_scope == 1)
+ /* Remove declarations for all the DECLs in this level. */
+ for (link = decls; link; link = TREE_CHAIN (link))
{
- struct binding_level *outer = current_binding_level->level_chain;
- for (link = decls; link; link = TREE_CHAIN (link))
+ if (leaving_for_scope && TREE_CODE (link) == VAR_DECL)
{
- 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. */
+ tree outer_binding
+ = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
+ tree ns_binding;
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- {
- tree id = TREE_PURPOSE (link);
- tree decl = IDENTIFIER_LOCAL_VALUE (id);
+ if (!outer_binding)
+ ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link));
+ else
+ ns_binding = NULL_TREE;
- 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;
- }
+ if (outer_binding
+ && (BINDING_LEVEL (outer_binding)
+ == current_binding_level->level_chain))
+ /* We have something like:
+
+ int i;
+ for (int i; ;);
+
+ and we are leaving the `for' scope. There's no reason to
+ keep the binding of the inner `i' in this case. */
+ pop_binding (DECL_NAME (link), link);
+ else if ((outer_binding
+ && (TREE_CODE (BINDING_VALUE (outer_binding))
+ == TYPE_DECL))
+ || (ns_binding
+ && TREE_CODE (ns_binding) == TYPE_DECL))
+ /* Here, we have something like:
+
+ typedef int I;
+
+ void f () {
+ for (int I; ;);
+ }
+
+ We must pop the for-scope binding so we know what's a
+ type and what isn't. */
+ pop_binding (DECL_NAME (link), link);
else
- IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link);
- }
- }
- else /* Not special for scope. */
- {
- for (link = decls; link; link = TREE_CHAIN (link))
- {
- if (DECL_NAME (link) != NULL_TREE)
{
- /* 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;
- }
- }
-
- /* 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);
-
- /* 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
+ /* Mark this VAR_DECL as dead so that we can tell we left it
+ there only for backward compatibility. */
+ DECL_DEAD_FOR_LOCAL (link) = 1;
+
+ /* Keep track of what should of have happenned when we
+ popped the binding. */
+ if (outer_binding && BINDING_VALUE (outer_binding))
+ DECL_SHADOWED_FOR_VAR (link)
+ = BINDING_VALUE (outer_binding);
+
+ /* Add it to the list of dead variables in the next
+ outermost binding to that we can remove these when we
+ leave that binding. */
+ current_binding_level->level_chain->dead_vars_from_for
+ = tree_cons (NULL_TREE, link,
+ current_binding_level->level_chain->
+ dead_vars_from_for);
+
+ /* Although we don't pop the CPLUS_BINDING, we do clear
+ its BINDING_LEVEL since the level is going away now. */
+ BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
+ = 0;
+ }
+ }
+ else
+ {
+ /* Remove the binding. */
+ decl = link;
+ if (TREE_CODE (decl) == TREE_LIST)
+ decl = TREE_VALUE (decl);
+ if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+ pop_binding (DECL_NAME (decl), decl);
+ else if (TREE_CODE (decl) == OVERLOAD)
+ pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
+ else
+ my_friendly_abort (0);
+ }
+ }
+
+ /* Remove declarations for any `for' variables from inner scopes
+ that we kept around. */
+ for (link = current_binding_level->dead_vars_from_for;
+ link; link = TREE_CHAIN (link))
+ pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
- 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. */
+ /* Restore the IDENTIFIER_TYPE_VALUEs. */
+ for (link = current_binding_level->type_shadowed;
+ link; link = TREE_CHAIN (link))
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
+
+ /* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
+ list if a `using' declaration put them there. The debugging
+ back-ends won't understand OVERLOAD, so we remove them here.
+ Because the BLOCK_VARS are (temporarily) shared with
+ CURRENT_BINDING_LEVEL->NAMES we must do this fixup after we have
+ popped all the bindings. */
+ if (block)
+ {
+ tree* d;
- link = current_binding_level->dead_vars_from_for;
- for (; link != NULL_TREE; link = TREE_CHAIN (link))
+ for (d = &BLOCK_VARS (block); *d; )
{
- tree id = DECL_NAME (link);
- if (IDENTIFIER_LOCAL_VALUE (id) == link)
- IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link);
+ if (TREE_CODE (*d) == TREE_LIST)
+ *d = TREE_CHAIN (*d);
+ else
+ d = &TREE_CHAIN (*d);
}
-
- 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));
}
/* If the level being exited is the top level of a function,
@@ -1308,14 +1633,8 @@ poplevel (keep, reverse, functionbody)
must be carried forward so they will later become subblocks
of something else. */
else if (subblocks)
- {
- if (keep == 2)
- current_binding_level->blocks
- = chainon (subblocks, current_binding_level->blocks);
- else
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, subblocks);
- }
+ current_binding_level->blocks
+ = chainon (current_binding_level->blocks, subblocks);
/* Take care of compiler's internal binding structures. */
if (tmp == 2)
@@ -1402,9 +1721,7 @@ pushlevel_class ()
free_binding_level = free_binding_level->level_chain;
}
else
- {
- newlevel = make_binding_level ();
- }
+ newlevel = make_binding_level ();
#if defined(DEBUG_CP_BINDING_LEVELS)
is_class_level = 1;
@@ -1415,42 +1732,56 @@ pushlevel_class ()
decl_stack = push_decl_level (decl_stack, &decl_obstack);
class_binding_level = current_binding_level;
class_binding_level->parm_flag = 2;
- /* We have just pushed into a new binding level. Now, fake out the rest
- of the compiler. Set the `current_binding_level' back to point to
- the most closely containing non-class binding level. */
- do
- {
- current_binding_level = current_binding_level->level_chain;
- }
- while (current_binding_level->parm_flag == 2);
}
-/* ...and a poplevel for class declarations. FORCE is used to force
- clearing out of CLASS_VALUEs after a class definition. */
+/* ...and a poplevel for class declarations. */
-tree
-poplevel_class (force)
- int force;
+static tree
+poplevel_class ()
{
register struct binding_level *level = class_binding_level;
- tree block = NULL_TREE;
tree shadowed;
my_friendly_assert (level != 0, 354);
decl_stack = pop_stack_level (decl_stack);
- for (shadowed = level->shadowed; shadowed; shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
/* If we're leaving a toplevel class, don't bother to do the setting
of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot
shouldn't even be used when current_class_type isn't set, and second,
if we don't touch it here, we're able to use the cache effect if the
next time we're entering a class scope, it is the same class. */
- if (current_class_depth != 1 || force)
- for (shadowed = level->class_shadowed;
- shadowed;
- shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
+ if (current_class_depth != 1)
+ {
+ struct binding_level* b;
+
+ /* Clear out our IDENTIFIER_CLASS_VALUEs. */
+ for (shadowed = level->class_shadowed;
+ shadowed;
+ shadowed = TREE_CHAIN (shadowed))
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = NULL_TREE;
+
+ /* Find the next enclosing class, and recreate
+ IDENTIFIER_CLASS_VALUEs appropriate for that class. */
+ b = level->level_chain;
+ while (b && b->parm_flag != 2)
+ b = b->level_chain;
+
+ if (b)
+ for (shadowed = b->class_shadowed;
+ shadowed;
+ shadowed = TREE_CHAIN (shadowed))
+ {
+ tree t;
+
+ t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
+ while (t && BINDING_LEVEL (t) != b)
+ t = TREE_CHAIN (t);
+
+ if (t)
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
+ = BINDING_VALUE (t);
+ }
+ }
else
/* Remember to save what IDENTIFIER's were bound in this scope so we
can recover from cache misses. */
@@ -1463,14 +1794,17 @@ poplevel_class (force)
shadowed = TREE_CHAIN (shadowed))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed));
+ /* Remove the bindings for all of the class-level declarations. */
+ for (shadowed = level->class_shadowed;
+ shadowed;
+ shadowed = TREE_CHAIN (shadowed))
+ pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (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);
- if (class_binding_level->parm_flag != 2)
- class_binding_level = (struct binding_level *)0;
-
/* Now, pop out of the binding level which we created up in the
`pushlevel_class' routine. */
#if defined(DEBUG_CP_BINDING_LEVELS)
@@ -1479,8 +1813,224 @@ poplevel_class (force)
pop_binding_level ();
- return block;
+ return NULL_TREE;
+}
+
+/* We are entering the scope of a class. Clear IDENTIFIER_CLASS_VALUE
+ for any names in enclosing classes. */
+
+void
+clear_identifier_class_values ()
+{
+ tree t;
+
+ if (!class_binding_level)
+ return;
+
+ for (t = class_binding_level->class_shadowed;
+ t;
+ t = TREE_CHAIN (t))
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
+}
+
+/* Returns non-zero if T is a virtual function table. */
+
+int
+vtable_decl_p (t, data)
+ tree t;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
+}
+
+/* Returns non-zero if T is a TYPE_DECL for a type with virtual
+ functions. */
+
+int
+vtype_decl_p (t, data)
+ tree t;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (TREE_CODE (t) == TYPE_DECL
+ && TREE_TYPE (t) != error_mark_node
+ && TYPE_LANG_SPECIFIC (TREE_TYPE (t))
+ && CLASSTYPE_VSIZE (TREE_TYPE (t)));
+}
+
+/* Returns non-zero if T is a signature table. */
+
+int
+sigtable_decl_p (t, data)
+ tree t;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (TREE_CODE (t) == VAR_DECL
+ && TREE_TYPE (t) != error_mark_node
+ && IS_SIGNATURE (TREE_TYPE (t)));
+}
+
+/* Walk all the namespaces contained NAMESPACE, including NAMESPACE
+ itself, calling F for each. The DATA is passed to F as well. */
+
+static int
+walk_namespaces_r (namespace, f, data)
+ tree namespace;
+ walk_namespaces_fn f;
+ void *data;
+{
+ tree current;
+ int result = 0;
+
+ result |= (*f) (namespace, data);
+
+ for (current = NAMESPACE_LEVEL (namespace)->names;
+ current;
+ current = TREE_CHAIN (current))
+ {
+ if (TREE_CODE (current) != NAMESPACE_DECL
+ || DECL_NAMESPACE_ALIAS (current))
+ continue;
+ if (!DECL_LANG_SPECIFIC (current))
+ {
+ /* Hmm. std. */
+ my_friendly_assert (current == std_node, 393);
+ continue;
+ }
+
+ /* We found a namespace. */
+ result |= walk_namespaces_r (current, f, data);
+ }
+
+ return result;
+}
+
+/* Walk all the namespaces, calling F for each. The DATA is passed to
+ F as well. */
+
+int
+walk_namespaces (f, data)
+ walk_namespaces_fn f;
+ void *data;
+{
+ return walk_namespaces_r (global_namespace, f, data);
+}
+
+struct walk_globals_data {
+ walk_globals_pred p;
+ walk_globals_fn f;
+ void *data;
+};
+
+/* Walk the global declarations in NAMESPACE. Whenever one is found
+ for which P returns non-zero, call F with its address. If any call
+ to F returns a non-zero value, return a non-zero value. */
+
+static int
+walk_globals_r (namespace, data)
+ tree namespace;
+ void *data;
+{
+ struct walk_globals_data* wgd = (struct walk_globals_data *) data;
+ walk_globals_pred p = wgd->p;
+ walk_globals_fn f = wgd->f;
+ void *d = wgd->data;
+ tree *t;
+ int result = 0;
+
+ t = &NAMESPACE_LEVEL (namespace)->names;
+
+ while (*t)
+ {
+ tree glbl = *t;
+
+ if ((*p) (glbl, d))
+ result |= (*f) (t, d);
+
+ /* If F changed *T, then *T still points at the next item to
+ examine. */
+ if (*t == glbl)
+ t = &TREE_CHAIN (*t);
+ }
+
+ return result;
+}
+
+/* Walk the global declarations. Whenever one is found for which P
+ returns non-zero, call F with its address. If any call to F
+ returns a non-zero value, return a non-zero value. */
+
+int
+walk_globals (p, f, data)
+ walk_globals_pred p;
+ walk_globals_fn f;
+ void *data;
+{
+ struct walk_globals_data wgd;
+ wgd.p = p;
+ wgd.f = f;
+ wgd.data = data;
+
+ return walk_namespaces (walk_globals_r, &wgd);
}
+
+/* Call wrapup_globals_declarations for the globals in NAMESPACE. If
+ DATA is non-NULL, this is the last time we will call
+ wrapup_global_declarations for this NAMESPACE. */
+
+int
+wrapup_globals_for_namespace (namespace, data)
+ tree namespace;
+ void *data;
+{
+ tree globals = NAMESPACE_LEVEL (namespace)->names;
+ int len = list_length (globals);
+ tree *vec = (tree *) alloca (sizeof (tree) * len);
+ int i;
+ int result;
+ tree decl;
+ int last_time = (data != 0);
+
+ if (last_time && namespace == global_namespace)
+ /* Let compile_file handle the global namespace. */
+ return 0;
+
+ /* Process the decls in reverse order--earliest first.
+ Put them into VEC from back to front, then take out from front. */
+
+ for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
+ vec[len - i - 1] = decl;
+
+ if (last_time)
+ {
+ check_global_declarations (vec, len);
+ return 0;
+ }
+
+ /* Temporarily mark vtables as external. That prevents
+ wrapup_global_declarations from writing them out; we must process
+ them ourselves in finish_vtable_vardecl. */
+ for (i = 0; i < len; ++i)
+ if (vtable_decl_p (vec[i], /*data=*/0) && !DECL_EXTERNAL (vec[i]))
+ {
+ DECL_NOT_REALLY_EXTERN (vec[i]) = 1;
+ DECL_EXTERNAL (vec[i]) = 1;
+ }
+
+ /* Write out any globals that need to be output. */
+ result = wrapup_global_declarations (vec, len);
+
+ /* Undo the hack to DECL_EXTERNAL above. */
+ for (i = 0; i < len; ++i)
+ if (vtable_decl_p (vec[i], /*data=*/0)
+ && DECL_NOT_REALLY_EXTERN (vec[i]))
+ {
+ DECL_NOT_REALLY_EXTERN (vec[i]) = 0;
+ DECL_EXTERNAL (vec[i]) = 0;
+ }
+
+ return result;
+}
+
/* For debugging. */
static int no_print_functions = 0;
@@ -1569,15 +2119,6 @@ print_binding_level (lvl)
if (i)
fprintf (stderr, "\n");
}
- if (lvl->shadowed)
- {
- fprintf (stderr, " shadowed:");
- for (t = lvl->shadowed; t; t = TREE_CHAIN (t))
- {
- fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- }
- fprintf (stderr, "\n");
- }
if (lvl->class_shadowed)
{
fprintf (stderr, " class-shadowed:");
@@ -1769,7 +2310,7 @@ void
push_namespace (name)
tree name;
{
- tree d;
+ tree d = NULL_TREE;
int need_new = 1;
int implicit_use = 0;
int global = 0;
@@ -1783,10 +2324,9 @@ push_namespace (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;
+ if (!anonymous_namespace_name)
+ anonymous_namespace_name = get_file_function_name ('N');
+ name = anonymous_namespace_name;
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d)
/* Reopening anonymous namespace. */
@@ -1854,34 +2394,6 @@ pop_namespace ()
suspend_binding_level ();
}
-/* Concatenate the binding levels of all namespaces. */
-
-void
-cat_namespace_levels()
-{
- tree current;
- tree last;
- struct binding_level *b;
-
- 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 (TREE_CODE (current) != NAMESPACE_DECL
- || DECL_NAMESPACE_ALIAS (current))
- continue;
- if (!DECL_LANG_SPECIFIC (current))
- {
- /* 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;
- }
-}
/* Subroutines for reverting temporarily to top-level for instantiation
of templates and such. We actually need to clear out the class- and
@@ -1893,7 +2405,9 @@ struct saved_scope {
tree old_bindings;
tree old_namespace;
struct saved_scope *prev;
- tree class_name, class_type, function_decl;
+ tree class_name, class_type;
+ tree access_specifier;
+ tree function_decl;
struct binding_level *class_bindings;
tree *lang_base, *lang_stack, lang_name;
int lang_stacksize;
@@ -1904,6 +2418,7 @@ struct saved_scope {
tree previous_class_type, previous_class_values;
int processing_specialization;
int processing_explicit_instantiation;
+ char *class_cache_firstobj;
};
static struct saved_scope *current_saved_scope;
@@ -1926,9 +2441,11 @@ store_bindings (names, old_bindings)
else
id = DECL_NAME (t);
- if (!id
- || (!IDENTIFIER_LOCAL_VALUE (id)
- && !IDENTIFIER_CLASS_VALUE (id)))
+ if (!id
+ /* Note that we may have an IDENTIFIER_CLASS_VALUE even when
+ we have no IDENTIFIER_BINDING if we have left the class
+ scope, but cached the class-level declarations. */
+ || !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
continue;
for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
@@ -1948,9 +2465,9 @@ store_bindings (names, old_bindings)
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, 2) = IDENTIFIER_BINDING (id);
TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
- IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
+ IDENTIFIER_BINDING (id) = NULL_TREE;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
}
TREE_CHAIN (binding) = old_bindings;
@@ -1968,11 +2485,10 @@ maybe_push_to_top_level (pseudo)
extern int current_lang_stacksize;
struct saved_scope *s
= (struct saved_scope *) xmalloc (sizeof (struct saved_scope));
- struct binding_level *b = inner_binding_level;
+ struct binding_level *b = current_binding_level;
tree old_bindings = NULL_TREE;
- if (current_function_decl)
- push_cp_function_context (NULL_TREE);
+ push_cp_function_context (NULL_TREE);
if (previous_class_type)
old_bindings = store_bindings (previous_class_values, old_bindings);
@@ -2007,6 +2523,7 @@ maybe_push_to_top_level (pseudo)
s->old_namespace = current_namespace;
s->class_name = current_class_name;
s->class_type = current_class_type;
+ s->access_specifier = current_access_specifier;
s->function_decl = current_function_decl;
s->class_bindings = class_binding_level;
s->lang_stack = current_lang_stack;
@@ -2019,6 +2536,7 @@ maybe_push_to_top_level (pseudo)
s->processing_template_decl = processing_template_decl;
s->previous_class_type = previous_class_type;
s->previous_class_values = previous_class_values;
+ s->class_cache_firstobj = class_cache_firstobj;
s->processing_specialization = processing_specialization;
s->processing_explicit_instantiation = processing_explicit_instantiation;
@@ -2034,6 +2552,7 @@ maybe_push_to_top_level (pseudo)
shadowed_labels = NULL_TREE;
minimal_parse_mode = 0;
previous_class_type = previous_class_values = NULL_TREE;
+ class_cache_firstobj = 0;
processing_specialization = 0;
processing_explicit_instantiation = 0;
current_template_parms = NULL_TREE;
@@ -2062,10 +2581,7 @@ pop_from_top_level ()
/* Clear out class-level bindings cache. */
if (previous_class_type)
- {
- popclass (-1);
- previous_class_type = NULL_TREE;
- }
+ invalidate_class_lookup_cache ();
pop_obstacks ();
@@ -2078,7 +2594,7 @@ pop_from_top_level ()
if (id)
{
SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
- IDENTIFIER_LOCAL_VALUE (id) = TREE_VEC_ELT (t, 2);
+ IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
}
t = TREE_CHAIN (t);
@@ -2088,6 +2604,7 @@ pop_from_top_level ()
current_namespace = s->old_namespace;
current_class_name = s->class_name;
current_class_type = s->class_type;
+ current_access_specifier = s->access_specifier;
current_function_decl = s->function_decl;
class_binding_level = s->class_bindings;
free (current_lang_base);
@@ -2107,11 +2624,11 @@ pop_from_top_level ()
previous_class_values = s->previous_class_values;
processing_specialization = s->processing_specialization;
processing_explicit_instantiation = s->processing_explicit_instantiation;
+ class_cache_firstobj = s->class_cache_firstobj;
free (s);
- if (current_function_decl)
- pop_cp_function_context (NULL_TREE);
+ pop_cp_function_context (NULL_TREE);
}
/* Push a definition of struct, union or enum tag "name".
@@ -2151,34 +2668,14 @@ set_identifier_type_value_with_scope (id, type, b)
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 current_binding_level. */
void
set_identifier_type_value (id, type)
tree id;
tree type;
{
- set_identifier_type_value_with_scope (id, type, inner_binding_level);
-}
-
-static void
-set_identifier_local_value_with_scope (id, val, b)
- tree id, val;
- struct binding_level *b;
-{
- tree oldlocal;
- my_friendly_assert (! b->namespace_p, 980716);
-
- oldlocal = IDENTIFIER_LOCAL_VALUE (id);
- b->shadowed = tree_cons (id, oldlocal, b->shadowed);
- IDENTIFIER_LOCAL_VALUE (id) = val;
-}
-
-void
-set_identifier_local_value (id, val)
- tree id, val;
-{
- set_identifier_local_value_with_scope (id, val, current_binding_level);
+ set_identifier_type_value_with_scope (id, type, current_binding_level);
}
/* Return the type associated with id. */
@@ -2211,10 +2708,10 @@ pop_everything ()
#ifdef DEBUG_CP_BINDING_LEVELS
fprintf (stderr, "XXX entering pop_everything ()\n");
#endif
- while (! toplevel_bindings_p () && ! pseudo_global_level_p ())
+ while (!toplevel_bindings_p ())
{
- if (class_binding_level)
- pop_nested_class (1);
+ if (current_binding_level->parm_flag == 2)
+ pop_nested_class ();
else
poplevel (0, 0, 0);
}
@@ -2223,6 +2720,90 @@ pop_everything ()
#endif
}
+/* The type TYPE is being declared. If it is a class template, or a
+ specialization of a class template, do any processing required and
+ perform error-checking. If IS_FRIEND is non-zero, this TYPE is
+ being declared a friend. B is the binding level at which this TYPE
+ should be bound.
+
+ Returns the TYPE_DECL for TYPE, which may have been altered by this
+ processing. */
+
+static tree
+maybe_process_template_type_declaration (type, globalize, b)
+ tree type;
+ int globalize;
+ struct binding_level* b;
+{
+ tree decl = TYPE_NAME (type);
+
+ 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
+ {
+ maybe_check_template_type (type);
+
+ my_friendly_assert (IS_AGGR_TYPE (type)
+ || TREE_CODE (type) == ENUMERAL_TYPE, 0);
+
+
+ if (/* 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_REAL_TEMPLATE_DECL_P ())
+ {
+ /* This may change after the call to
+ push_template_decl_real, but we want the original value. */
+ tree name = DECL_NAME (decl);
+
+ decl = push_template_decl_real (decl, 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 (TREE_CODE (type) != ENUMERAL_TYPE
+ && !globalize && b->pseudo_global
+ && b->level_chain->parm_flag == 2)
+ {
+ finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
+ /* 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);
+ if (TYPE_SIZE (current_class_type) == NULL_TREE)
+ CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
+ }
+ }
+ }
+
+ return decl;
+}
+
/* Push a tag name NAME for struct/class/union/enum type TYPE.
Normally put it into the inner-most non-tag-transparent scope,
but if GLOBALIZE is true, put it in the inner-most non-class scope.
@@ -2234,10 +2815,8 @@ pushtag (name, type, globalize)
int globalize;
{
register struct binding_level *b;
- tree context = 0;
- tree c_decl = 0;
- b = inner_binding_level;
+ b = current_binding_level;
while (b->tag_transparent
|| (globalize && b->parm_flag == 2))
b = b->level_chain;
@@ -2249,32 +2828,34 @@ pushtag (name, type, globalize)
if (name)
{
- context = type ? TYPE_CONTEXT (type) : NULL_TREE;
- 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 (!context)
- context = current_namespace;
-
/* Do C++ gratuitous typedefing. */
if (IDENTIFIER_TYPE_VALUE (name) != type)
{
register tree d = NULL_TREE;
int newdecl = 0, in_class = 0;
+ tree context;
+ tree c_decl = NULL_TREE;
+
+ context = type ? TYPE_CONTEXT (type) : NULL_TREE;
+ 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 (!context)
+ context = current_namespace;
if ((b->pseudo_global && b->level_chain->parm_flag == 2)
|| b->parm_flag == 2)
@@ -2298,66 +2879,20 @@ pushtag (name, type, globalize)
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;
- };
+ d = maybe_process_template_type_declaration (type,
+ globalize, b);
- declares S2 to be at global scope. */
- || (processing_template_decl >
- template_class_depth (current_class_type))))
+ if (b->parm_flag == 2)
{
- 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)
- {
- 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;
- }
+ if (newdecl && !PROCESSING_REAL_TEMPLATE_DECL_P ())
+ /* Put this TYPE_DECL on the TYPE_FIELDS list for the
+ class. But if it's a member template class, we
+ want the TEMPLATE_DECL, not the TYPE_DECL, so this
+ is done later. */
+ finish_member_declaration (d);
+ else
+ pushdecl_class_level (d);
}
-
- if (b->parm_flag == 2)
- d = pushdecl_class_level (d);
else
d = pushdecl_with_scope (d, b);
@@ -2368,13 +2903,13 @@ pushtag (name, type, globalize)
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));
+ if (!uses_template_parms (type))
+ DECL_ASSEMBLER_NAME (d)
+ = get_identifier (build_overload_name (type, 1, 1));
}
}
if (b->parm_flag == 2)
{
- TREE_NONLOCAL_FLAG (type) = 1;
if (TYPE_SIZE (current_class_type) == NULL_TREE)
CLASSTYPE_TAGS (current_class_type) = b->tags;
}
@@ -2458,8 +2993,15 @@ decls_match (newdecl, olddecl)
{
int types_match;
- if (TREE_CODE (newdecl) == FUNCTION_DECL
- && TREE_CODE (olddecl) == FUNCTION_DECL)
+ if (newdecl == olddecl)
+ return 1;
+
+ if (TREE_CODE (newdecl) != TREE_CODE (olddecl))
+ /* If the two DECLs are not even the same kind of thing, we're not
+ interested in their types. */
+ return 0;
+
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
tree f1 = TREE_TYPE (newdecl);
tree f2 = TREE_TYPE (olddecl);
@@ -2494,7 +3036,7 @@ decls_match (newdecl, olddecl)
return 0;
}
- if (comptypes (TREE_TYPE (f1), TREE_TYPE (f2), 1))
+ if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
{
if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c
&& p2 == NULL_TREE)
@@ -2510,13 +3052,12 @@ decls_match (newdecl, olddecl)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
else
- types_match = compparms (p1, p2, 3);
+ types_match = compparms (p1, p2);
}
else
types_match = 0;
}
- else if (TREE_CODE (newdecl) == TEMPLATE_DECL
- && TREE_CODE (olddecl) == TEMPLATE_DECL)
+ else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
@@ -2536,20 +3077,10 @@ 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 = 0;
+ types_match = comptypes (TREE_TYPE (newdecl),
+ TREE_TYPE (olddecl),
+ COMPARE_REDECLARATION);
}
return types_match;
@@ -2571,9 +3102,9 @@ warn_extern_redeclared_static (newdecl, olddecl)
{
tree name;
- static char *explicit_extern_static_warning
+ static const char *explicit_extern_static_warning
= "`%D' was declared `extern' and later `static'";
- static char *implicit_extern_static_warning
+ static const char *implicit_extern_static_warning
= "`%D' was declared implicitly `extern' and later `static'";
if (TREE_CODE (newdecl) == TYPE_DECL)
@@ -2709,6 +3240,11 @@ duplicate_decls (newdecl, olddecl)
}
else if (!types_match)
{
+ if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl))
+ /* These are certainly not duplicate declarations; they're
+ from different scopes. */
+ return 0;
+
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
/* The name of a class template may not be declared to refer to
@@ -2724,7 +3260,7 @@ duplicate_decls (newdecl, 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)
+ TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
&& comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
{
@@ -2743,7 +3279,7 @@ duplicate_decls (newdecl, olddecl)
cp_error_at ("previous declaration `%#D' here", olddecl);
}
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
- TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 3))
+ TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
cp_error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
@@ -2793,7 +3329,7 @@ duplicate_decls (newdecl, olddecl)
return 1;
else
{
- char *errmsg = redeclaration_error_message (newdecl, olddecl);
+ const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
cp_error (errmsg, newdecl);
@@ -2873,13 +3409,6 @@ duplicate_decls (newdecl, olddecl)
olddecl);
}
}
- /* These bits are logically part of the type for non-functions. */
- else if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
- || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
- {
- cp_pedwarn ("type qualifiers for `%#D'", newdecl);
- cp_pedwarn_at ("conflict with previous decl `%#D'", olddecl);
- }
}
/* If new decl is `static' and an `extern' was seen previously,
@@ -2945,17 +3474,13 @@ duplicate_decls (newdecl, olddecl)
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);
+ 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_SPECIALIZATIONS (olddecl)
+ = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
+ DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
return 1;
}
@@ -2991,7 +3516,8 @@ duplicate_decls (newdecl, olddecl)
TREE_TYPE (olddecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (oldtype));
- if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
+ if ((pedantic || (! DECL_IN_SYSTEM_HEADER (olddecl)
+ && ! DECL_IN_SYSTEM_HEADER (newdecl)))
&& DECL_SOURCE_LINE (olddecl) != 0
&& flag_exceptions
&& ! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
@@ -3004,7 +3530,7 @@ duplicate_decls (newdecl, olddecl)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
- if (newtype != canonical_type_variant (oldtype)
+ if (! same_type_p (newtype, oldtype)
&& TREE_TYPE (newdecl) != error_mark_node
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_type (TREE_TYPE (newdecl));
@@ -3030,6 +3556,9 @@ duplicate_decls (newdecl, olddecl)
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
+ if (DECL_LANG_SPECIFIC (newdecl)
+ && DECL_LANG_SPECIFIC (olddecl))
+ DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
}
/* Merge the section attribute.
@@ -3076,17 +3605,22 @@ duplicate_decls (newdecl, 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);
+ DECL_TEMPLATE_INSTANTIATED (newdecl)
+ |= DECL_TEMPLATE_INSTANTIATED (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);
- }
+ DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
olddecl_friend = DECL_FRIEND_P (olddecl);
+
+ /* Only functions have DECL_BEFRIENDING_CLASSES. */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (newdecl))
+ DECL_BEFRIENDING_CLASSES (newdecl)
+ = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
+ DECL_BEFRIENDING_CLASSES (olddecl));
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -3292,23 +3826,30 @@ pushdecl (x)
{
register tree t;
register tree name = DECL_ASSEMBLER_NAME (x);
- register struct binding_level *b = current_binding_level;
+ int need_new_binding = 1;
- 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;
- if (!DECL_CONTEXT (x))
- DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
+ if (DECL_TEMPLATE_PARM_P (x))
+ /* Template parameters have no context; they are not X::T even
+ when declared within a class or namespace. */
+ ;
+ else
+ {
+ 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;
+ 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. */
if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
- || TREE_CODE (x) == NAMESPACE_DECL || TREE_CODE (x) == TEMPLATE_TYPE_PARM
- || TREE_CODE (x) == TEMPLATE_TEMPLATE_PARM)
+ || TREE_CODE (x) == NAMESPACE_DECL)
name = DECL_NAME (x);
if (name)
@@ -3422,14 +3963,30 @@ pushdecl (x)
}
}
+ check_template_shadow (x);
+
+ /* If this is a function conjured up by the backend, massage it
+ so it looks friendly. */
+ if (TREE_CODE (x) == FUNCTION_DECL
+ && ! DECL_LANG_SPECIFIC (x))
+ {
+ retrofit_lang_decl (x);
+ DECL_LANGUAGE (x) = lang_c;
+ }
+
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
{
- t = push_overloaded_decl (x, 1);
+ t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x || DECL_LANGUAGE (x) == lang_c)
return t;
+ if (!namespace_bindings_p ())
+ /* We do not need to create a binding for this name;
+ push_overloaded_decl will have already done so if
+ necessary. */
+ need_new_binding = 0;
}
else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
- return push_overloaded_decl (x, 0);
+ return push_overloaded_decl (x, PUSH_GLOBAL);
/* 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
@@ -3442,7 +3999,12 @@ pushdecl (x)
if (TYPE_NAME (type) == 0)
TYPE_NAME (type) = x;
}
- else if (type != error_mark_node && TYPE_NAME (type) != x)
+ else if (type != error_mark_node && TYPE_NAME (type) != x
+ /* We don't want to copy the type when all we're
+ doing is making a TYPE_DECL for the purposes of
+ inlining. */
+ && (!TYPE_NAME (type)
+ || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x)))
{
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
@@ -3458,7 +4020,9 @@ pushdecl (x)
if (type != error_mark_node
&& TYPE_NAME (type)
&& TYPE_IDENTIFIER (type))
- set_identifier_type_value_with_scope (DECL_NAME (x), type, b);
+ set_identifier_type_value_with_scope (DECL_NAME (x), type,
+ current_binding_level);
+
}
/* Multiple external decls of the same identifier ought to match.
@@ -3470,19 +4034,18 @@ pushdecl (x)
if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL)
{
tree decl;
- tree bindings = binding_for_name (name, current_namespace);
- if (BINDING_VALUE (bindings) != NULL_TREE
- && (DECL_EXTERNAL (BINDING_VALUE (bindings))
- || TREE_PUBLIC (BINDING_VALUE (bindings))))
- decl = BINDING_VALUE (bindings);
+ if (IDENTIFIER_NAMESPACE_VALUE (name) != NULL_TREE
+ && (DECL_EXTERNAL (IDENTIFIER_NAMESPACE_VALUE (name))
+ || TREE_PUBLIC (IDENTIFIER_NAMESPACE_VALUE (name))))
+ decl = IDENTIFIER_NAMESPACE_VALUE (name);
else
decl = NULL_TREE;
if (decl
/* If different sort of thing, we already gave an error. */
&& TREE_CODE (decl) == TREE_CODE (x)
- && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl), 1))
+ && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
{
cp_pedwarn ("type mismatch with previous external decl", x);
cp_pedwarn_at ("previous external decl of `%#D'", decl);
@@ -3494,23 +4057,20 @@ pushdecl (x)
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 (BINDING_VALUE (bindings) == NULL_TREE && TREE_PUBLIC (x))
+ if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
- /* 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))
+ if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
+ && t != NULL_TREE))
{
if (TREE_CODE (x) == FUNCTION_DECL)
- my_friendly_assert ((BINDING_VALUE (bindings) == NULL_TREE)
- || BINDING_VALUE (bindings) == x, 378);
- BINDING_VALUE (bindings) = x;
+ my_friendly_assert
+ ((IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE)
+ || (IDENTIFIER_GLOBAL_VALUE (name) == x), 378);
+ SET_IDENTIFIER_NAMESPACE_VALUE (name, x);
}
/* Don't forget if the function was used via an implicit decl. */
@@ -3539,61 +4099,65 @@ pushdecl (x)
else
{
/* Here to install a non-global value. */
- tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
- tree oldglobal = binding_for_name (name, current_namespace);
+ tree oldlocal = IDENTIFIER_VALUE (name);
+ tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name);
- /* 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))
- set_identifier_local_value_with_scope (name, x, b);
+ if (need_new_binding)
+ {
+ push_local_binding (name, x, 0);
+ /* Because push_local_binding will hook X on to the
+ current_binding_level's name list, we don't want to
+ do that again below. */
+ need_new_binding = 0;
+ }
/* If this is a TYPE_DECL, push it into the type value slot. */
if (TREE_CODE (x) == TYPE_DECL)
- set_identifier_type_value_with_scope (name, TREE_TYPE (x), b);
+ set_identifier_type_value_with_scope (name, TREE_TYPE (x),
+ current_binding_level);
/* Clear out any TYPE_DECL shadowed by a namespace so that
we won't think this is a type. The C struct hack doesn't
go through namespaces. */
if (TREE_CODE (x) == NAMESPACE_DECL)
- set_identifier_type_value_with_scope (name, NULL_TREE, b);
+ set_identifier_type_value_with_scope (name, NULL_TREE,
+ current_binding_level);
/* If this is an extern function declaration, see if we
have a global definition or declaration for the function. */
if (oldlocal == NULL_TREE
&& DECL_EXTERNAL (x)
- && BINDING_VALUE (oldglobal) != NULL_TREE
+ && oldglobal != NULL_TREE
&& TREE_CODE (x) == FUNCTION_DECL
- && TREE_CODE (BINDING_VALUE (oldglobal)) == FUNCTION_DECL)
+ && TREE_CODE (oldglobal) == FUNCTION_DECL)
{
/* We have one. Their types must agree. */
- if (decls_match (x, BINDING_VALUE (oldglobal)))
+ if (decls_match (x, oldglobal))
/* OK */;
else
{
cp_warning ("extern declaration of `%#D' doesn't match", x);
- cp_warning_at ("global declaration `%#D'", BINDING_VALUE (oldglobal));
+ cp_warning_at ("global declaration `%#D'", 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
- && BINDING_VALUE (oldglobal) == NULL_TREE
+ && oldglobal == NULL_TREE
&& DECL_EXTERNAL (x)
&& TREE_PUBLIC (x))
- {
- TREE_PUBLIC (name) = 1;
- }
+ TREE_PUBLIC (name) = 1;
if (DECL_FROM_INLINE (x))
/* Inline decls shadow nothing. */;
/* Warn if shadowing an argument at the top level of the body. */
else if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
- && TREE_CODE (oldlocal) == PARM_DECL
- && TREE_CODE (x) != PARM_DECL)
+ && TREE_CODE (oldlocal) == PARM_DECL
+ /* Don't complain if it's from an enclosing function. */
+ && DECL_CONTEXT (oldlocal) == current_function_decl
+ && TREE_CODE (x) != PARM_DECL)
{
/* Go to where the parms should be and see if we
find them there. */
@@ -3606,7 +4170,8 @@ pushdecl (x)
if (b->parm_flag == 1)
cp_error ("declaration of `%#D' shadows a parameter", name);
}
- else if (warn_shadow && oldlocal != NULL_TREE && b->is_for_scope
+ else if (warn_shadow && oldlocal != NULL_TREE
+ && current_binding_level->is_for_scope
&& !DECL_DEAD_FOR_LOCAL (oldlocal))
{
warning ("variable `%s' shadows local",
@@ -3620,7 +4185,7 @@ pushdecl (x)
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
- char *warnstring = NULL;
+ const char *warnstring = NULL;
if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
warnstring = "declaration of `%s' shadows a parameter";
@@ -3630,7 +4195,7 @@ pushdecl (x)
warnstring = "declaration of `%s' shadows a member of `this'";
else if (oldlocal != NULL_TREE)
warnstring = "declaration of `%s' shadows previous local";
- else if (BINDING_VALUE (oldglobal) != NULL_TREE)
+ else if (oldglobal != NULL_TREE)
/* XXX shadow warnings in outer-more namespaces */
warnstring = "declaration of `%s' shadows global declaration";
@@ -3650,15 +4215,20 @@ pushdecl (x)
/* RTTI TD entries are created while defining the type_info. */
|| (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
&& TYPE_BEING_DEFINED (TREE_TYPE (x)))))
- b->incomplete = tree_cons (NULL_TREE, x, b->incomplete);
+ current_binding_level->incomplete
+ = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
}
- /* Put decls on list in reverse order.
- We will reverse them later if necessary. */
- TREE_CHAIN (x) = b->names;
- b->names = x;
- if (! (b != global_binding_level || TREE_PERMANENT (x)))
- my_friendly_abort (124);
+ if (need_new_binding)
+ {
+ /* Put decls on list in reverse order.
+ We will reverse them later if necessary. */
+ TREE_CHAIN (x) = current_binding_level->names;
+ current_binding_level->names = x;
+ if (current_binding_level == global_binding_level
+ && !TREE_PERMANENT (x))
+ my_friendly_abort (124);
+ }
return x;
}
@@ -3700,7 +4270,7 @@ tree
pushdecl_namespace_level (x)
tree x;
{
- register struct binding_level *b = inner_binding_level;
+ register struct binding_level *b = current_binding_level;
register tree t;
t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
@@ -3755,46 +4325,33 @@ pushdecl_top_level (x)
/* Make the declaration of X appear in CLASS scope. */
-tree
+void
pushdecl_class_level (x)
tree x;
{
/* Don't use DECL_ASSEMBLER_NAME here! Everything that looks in class
scope looks for the pre-mangled name. */
- register tree name = DECL_NAME (x);
+ register tree name;
+
+ if (TREE_CODE (x) == OVERLOAD)
+ x = OVL_CURRENT (x);
+ name = DECL_NAME (x);
if (name)
{
- if (TYPE_BEING_DEFINED (current_class_type))
- {
- /* 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 && icv != x
- && flag_optional_diags
- /* Don't complain about inherited names. */
- && id_in_current_class (name)
- /* Or shadowed tags. */
- && !(DECL_DECLARES_TYPE_P (icv)
- && DECL_CONTEXT (icv) == current_class_type))
- {
- cp_pedwarn ("declaration of identifier `%D' as `%#D'", name, x);
- cp_pedwarn_at ("conflicts with previous use in class as `%#D'",
- icv);
- }
- }
-
push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
- {
- set_identifier_type_value (name, TREE_TYPE (x));
- }
+ set_identifier_type_value (name, TREE_TYPE (x));
+ }
+ else if (ANON_UNION_TYPE_P (TREE_TYPE (x)))
+ {
+ tree f;
+
+ for (f = TYPE_FIELDS (TREE_TYPE (x));
+ f;
+ f = TREE_CHAIN (f))
+ pushdecl_class_level (f);
}
- return x;
}
#if 0
@@ -3828,22 +4385,78 @@ push_class_level_binding (name, x)
tree name;
tree x;
{
+ tree binding;
/* 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;
+ /* Make sure that this new member does not have the same name
+ as a template parameter. */
+ if (TYPE_BEING_DEFINED (current_class_type))
+ check_template_shadow (x);
+
+ /* If this declaration shadows a declaration from an enclosing
+ class, then we will need to restore IDENTIFIER_CLASS_VALUE when
+ we leave this class. Record the shadowed declaration here. */
+ binding = IDENTIFIER_BINDING (name);
+ if (binding
+ && ((TREE_CODE (x) == OVERLOAD
+ && BINDING_VALUE (binding)
+ && is_overloaded_fn (BINDING_VALUE (binding)))
+ || INHERITED_VALUE_BINDING_P (binding)))
+ {
+ tree shadow;
+ tree old_decl;
+
+ /* If the old binding was from a base class, and was for a tag
+ name, slide it over to make room for the new binding. The
+ old binding is still visible if explicitly qualified with a
+ class-key. */
+ if (INHERITED_VALUE_BINDING_P (binding)
+ && BINDING_VALUE (binding)
+ && TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+ && DECL_ARTIFICIAL (BINDING_VALUE (binding))
+ && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
+ {
+ old_decl = BINDING_TYPE (binding);
+ BINDING_TYPE (binding) = BINDING_VALUE (binding);
+ BINDING_VALUE (binding) = NULL_TREE;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ }
+ else
+ old_decl = BINDING_VALUE (binding);
+
+ /* There was already a binding for X containing fewer
+ functions than are named in X. Find the previous
+ declaration of X on the class-shadowed list, and update it. */
+ for (shadow = class_binding_level->class_shadowed;
+ shadow;
+ shadow = TREE_CHAIN (shadow))
+ if (TREE_PURPOSE (shadow) == name
+ && TREE_TYPE (shadow) == old_decl)
+ {
+ BINDING_VALUE (binding) = x;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ TREE_TYPE (shadow) = x;
+ return;
+ }
+ }
- maybe_push_cache_obstack ();
- class_binding_level->class_shadowed
- = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
- class_binding_level->class_shadowed);
- pop_obstacks ();
- IDENTIFIER_CLASS_VALUE (name) = x;
- obstack_ptr_grow (&decl_obstack, x);
+ /* If we didn't replace an existing binding, put the binding on the
+ stack of bindings for the identifier, and update
+ IDENTIFIER_CLASS_VALUE. */
+ if (push_class_binding (name, x))
+ {
+ push_cache_obstack ();
+ class_binding_level->class_shadowed
+ = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
+ class_binding_level->class_shadowed);
+ pop_obstacks ();
+ /* Record the value we are binding NAME to so that we can know
+ what to pop later. */
+ TREE_TYPE (class_binding_level->class_shadowed) = x;
+ }
}
/* Insert another USING_DECL into the current binding level,
@@ -3897,31 +4510,38 @@ push_using_directive (used)
return ud;
}
-/* DECL is a FUNCTION_DECL which may have other definitions already in
- place. We get around this by making the value of the identifier point
- to a list of all the things that want to be referenced by that name. It
- is then up to the users of that name to decide what to do with that
- list.
+/* DECL is a FUNCTION_DECL for a non-member function, which may have
+ other definitions already in place. We get around this by making
+ the value of the identifier point to a list of all the things that
+ want to be referenced by that name. It is then up to the users of
+ that name to decide what to do with that list.
DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
slot. It is dealt with the same way.
+ FLAGS is a bitwise-or of the following values:
+ PUSH_LOCAL: Bind DECL in the current scope, rather than at
+ namespace scope.
+ PUSH_USING: DECL is being pushed as the result of a using
+ declaration.
+
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). */
-static tree
-push_overloaded_decl (decl, forgettable)
+tree
+push_overloaded_decl (decl, flags)
tree decl;
- int forgettable;
+ int flags;
{
- tree orig_name = DECL_NAME (decl);
+ tree name = DECL_NAME (decl);
tree old;
- int doing_global = (namespace_bindings_p () || ! forgettable);
+ tree new_binding;
+ int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
if (doing_global)
{
- old = namespace_binding (orig_name, DECL_CONTEXT (decl));
+ old = namespace_binding (name, DECL_CONTEXT (decl));
if (old && TREE_CODE (old) == FUNCTION_DECL
&& DECL_ARTIFICIAL (old)
&& (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
@@ -3932,16 +4552,7 @@ push_overloaded_decl (decl, forgettable)
}
}
else
- {
- old = IDENTIFIER_LOCAL_VALUE (orig_name);
-
- if (! purpose_member (orig_name, current_binding_level->shadowed))
- {
- current_binding_level->shadowed
- = tree_cons (orig_name, old, current_binding_level->shadowed);
- old = NULL_TREE;
- }
- }
+ old = lookup_name_current_level (name);
if (old)
{
@@ -3959,9 +4570,19 @@ push_overloaded_decl (decl, forgettable)
tree tmp;
for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
- if (decl == OVL_CURRENT (tmp)
- || duplicate_decls (decl, OVL_CURRENT (tmp)))
- return OVL_CURRENT (tmp);
+ {
+ tree fn = OVL_CURRENT (tmp);
+
+ if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
+ && !(flags & PUSH_USING)
+ && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
+ TYPE_ARG_TYPES (TREE_TYPE (decl))))
+ cp_error ("`%#D' conflicts with previous using declaration `%#D'",
+ decl, fn);
+
+ if (duplicate_decls (decl, fn))
+ return fn;
+ }
}
else
{
@@ -3974,17 +4595,57 @@ push_overloaded_decl (decl, forgettable)
if (old || TREE_CODE (decl) == TEMPLATE_DECL)
{
if (old && TREE_CODE (old) != OVERLOAD)
- old = ovl_cons (old, NULL_TREE);
- old = ovl_cons (decl, old);
+ new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE));
+ else
+ new_binding = ovl_cons (decl, old);
+ if (flags & PUSH_USING)
+ OVL_USED (new_binding) = 1;
}
else
- /* orig_name is not ambiguous. */
- old = decl;
+ /* NAME is not ambiguous. */
+ new_binding = decl;
if (doing_global)
- set_namespace_binding (orig_name, current_namespace, old);
+ set_namespace_binding (name, current_namespace, new_binding);
else
- IDENTIFIER_LOCAL_VALUE (orig_name) = old;
+ {
+ /* We only create an OVERLOAD if there was a previous binding at
+ this level, or if decl is a template. In the former case, we
+ need to remove the old binding and replace it with the new
+ binding. We must also run through the NAMES on the binding
+ level where the name was bound to update the chain. */
+
+ if (TREE_CODE (new_binding) == OVERLOAD && old)
+ {
+ tree *d;
+
+ for (d = &BINDING_LEVEL (IDENTIFIER_BINDING (name))->names;
+ *d;
+ d = &TREE_CHAIN (*d))
+ if (*d == old
+ || (TREE_CODE (*d) == TREE_LIST
+ && TREE_VALUE (*d) == old))
+ {
+ if (TREE_CODE (*d) == TREE_LIST)
+ /* Just replace the old binding with the new. */
+ TREE_VALUE (*d) = new_binding;
+ else
+ /* Build a TREE_LIST to wrap the OVERLOAD. */
+ *d = build_tree_list (NULL_TREE, new_binding);
+
+ /* And update the CPLUS_BINDING node. */
+ BINDING_VALUE (IDENTIFIER_BINDING (name))
+ = new_binding;
+ return decl;
+ }
+
+ /* We should always find a previous binding in this case. */
+ my_friendly_abort (0);
+ }
+
+ /* Install the new binding. */
+ push_local_binding (name, new_binding, flags);
+ }
return decl;
}
@@ -4040,7 +4701,7 @@ implicitly_declare (functionid)
Otherwise return an error message format string with a %s
where the identifier should go. */
-static char *
+static const char *
redeclaration_error_message (newdecl, olddecl)
tree newdecl, olddecl;
{
@@ -4049,7 +4710,7 @@ redeclaration_error_message (newdecl, olddecl)
/* Because C++ can put things into name space for free,
constructs like "typedef struct foo { ... } foo"
would look like an erroneous redeclaration. */
- if (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
+ if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
return 0;
else
return "redefinition of `%#D'";
@@ -4279,20 +4940,42 @@ define_label (filename, line, name)
and they should be cleaned up
by the time we get to the label. */
&& ! DECL_ARTIFICIAL (new_decls)
- && ((DECL_INITIAL (new_decls) != NULL_TREE
- && DECL_INITIAL (new_decls) != error_mark_node)
- || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
+ && !(DECL_INITIAL (new_decls) == NULL_TREE
+ && pod_type_p (TREE_TYPE (new_decls))))
{
- if (! identified)
+ /* This is really only important if we're crossing
+ an initialization. The POD stuff is just
+ pedantry; why should it matter if the class
+ contains a field of pointer to member type? */
+ int problem = (DECL_INITIAL (new_decls)
+ || (TYPE_NEEDS_CONSTRUCTING
+ (TREE_TYPE (new_decls))));
+
+ if (! identified)
{
- cp_error ("jump to label `%D'", decl);
- error_with_file_and_line (uses->filename_o_goto,
- uses->lineno_o_goto,
- " from here");
+ if (problem)
+ {
+ cp_error ("jump to label `%D'", decl);
+ error_with_file_and_line
+ (uses->filename_o_goto,
+ uses->lineno_o_goto, " from here");
+ }
+ else
+ {
+ cp_pedwarn ("jump to label `%D'", decl);
+ pedwarn_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);
+
+ if (problem)
+ cp_error_at (" crosses initialization of `%#D'",
+ new_decls);
+ else
+ cp_pedwarn_at (" enters scope of non-POD `%#D'",
+ new_decls);
}
new_decls = TREE_CHAIN (new_decls);
}
@@ -4346,8 +5029,7 @@ pop_switch ()
/* XXX Note decl is never actually used. (bpk) */
void
-define_case_label (decl)
- tree decl;
+define_case_label ()
{
tree cleanup = last_cleanup_this_contour ();
struct binding_level *b = current_binding_level;
@@ -4429,7 +5111,7 @@ storedecls (decls)
/* Similarly, store the list of tags of the current level. */
-static void
+void
storetags (tags)
tree tags;
{
@@ -4455,6 +5137,9 @@ lookup_tag (form, name, binding_level, thislevel_only)
int thislevel_only;
{
register struct binding_level *level;
+ /* Non-zero if, we should look past a pseudo-global level, even if
+ THISLEVEL_ONLY. */
+ int allow_pseudo_global = 1;
for (level = binding_level; level; level = level->level_chain)
{
@@ -4469,10 +5154,21 @@ lookup_tag (form, name, binding_level, thislevel_only)
}
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));
+ tree old = binding_for_name (name, tail);
+
+ /* If we just skipped past a pseudo global level, even
+ though THISLEVEL_ONLY, and we find a template class
+ declaration, then we use the _TYPE node for the
+ template. See the example below. */
+ if (thislevel_only && !allow_pseudo_global
+ && old && BINDING_VALUE (old)
+ && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old)))
+ old = TREE_TYPE (BINDING_VALUE (old));
+ else
+ old = BINDING_TYPE (old);
+
/* If it has an original type, it is a typedef, and we
should not return it. */
if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old)))
@@ -4509,16 +5205,24 @@ lookup_tag (form, name, binding_level, thislevel_only)
}
if (thislevel_only && ! level->tag_transparent)
{
- 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);
+ if (level->pseudo_global && allow_pseudo_global)
+ {
+ /* We must deal with cases like this:
+
+ template <class T> struct S;
+ template <class T> struct S {};
+
+ When looking up `S', for the second declaration, we
+ would like to find the first declaration. But, we
+ are in the pseudo-global level created for the
+ template parameters, rather than the (surrounding)
+ namespace level. Thus, we keep going one more level,
+ even though THISLEVEL_ONLY is non-zero. */
+ allow_pseudo_global = 0;
+ continue;
}
- return NULL_TREE;
+ else
+ return NULL_TREE;
}
if (current_class_type && level->level_chain->namespace_p)
{
@@ -4668,6 +5372,20 @@ lookup_namespace_name (namespace, name)
tree val;
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
+
+ if (TREE_CODE (name) == NAMESPACE_DECL)
+ /* This happens for A::B<int> when B is a namespace. */
+ return name;
+ else if (TREE_CODE (name) == TEMPLATE_DECL)
+ {
+ /* This happens for A::B where B is a template, and there are no
+ template arguments. */
+ cp_error ("invalid use of `%D'", name);
+ return error_mark_node;
+ }
+
+ namespace = ORIGINAL_NAMESPACE (namespace);
+
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
val = binding_init (&_b);
@@ -4688,15 +5406,130 @@ lookup_namespace_name (namespace, name)
return error_mark_node;
}
+/* Hash a TYPENAME_TYPE. K is really of type `tree'. */
+
+static unsigned long
+typename_hash (k)
+ hash_table_key k;
+{
+ unsigned long hash;
+ tree t;
+
+ t = (tree) k;
+ hash = (((unsigned long) TYPE_CONTEXT (t))
+ ^ ((unsigned long) DECL_NAME (TYPE_NAME (t))));
+
+ return hash;
+}
+
+/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
+
+static boolean
+typename_compare (k1, k2)
+ hash_table_key k1;
+ hash_table_key k2;
+{
+ tree t1;
+ tree t2;
+ tree d1;
+ tree d2;
+
+ t1 = (tree) k1;
+ t2 = (tree) k2;
+ d1 = TYPE_NAME (t1);
+ d2 = TYPE_NAME (t2);
+
+ return (DECL_NAME (d1) == DECL_NAME (d2)
+ && same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2))
+ && ((TREE_TYPE (t1) != NULL_TREE)
+ == (TREE_TYPE (t2) != NULL_TREE))
+ && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
+ && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
+}
+
+/* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is
+ the type of `T', NAME is the IDENTIFIER_NODE for `t'. If BASE_TYPE
+ is non-NULL, this type is being created by the implicit typename
+ extension, and BASE_TYPE is a type named `t' in some base class of
+ `T' which depends on template parameters.
+
+ Returns the new TYPENAME_TYPE. */
+
+tree
+build_typename_type (context, name, fullname, base_type)
+ tree context;
+ tree name;
+ tree fullname;
+ tree base_type;
+{
+ tree t;
+ tree d;
+ struct hash_entry* e;
+
+ static struct hash_table ht;
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+
+ if (!ht.table
+ && !hash_table_init (&ht, &hash_newfunc, &typename_hash,
+ &typename_compare))
+ fatal ("virtual memory exhausted");
+
+ /* The FULLNAME needs to exist for the life of the hash table, i.e.,
+ for the entire compilation. */
+ if (!TREE_PERMANENT (fullname))
+ fullname = copy_to_permanent (fullname);
+
+ /* Build the TYPENAME_TYPE. */
+ t = make_lang_type (TYPENAME_TYPE);
+ TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+ TYPENAME_TYPE_FULLNAME (t) = fullname;
+ TREE_TYPE (t) = base_type;
+
+ /* Build the corresponding TYPE_DECL. */
+ d = build_decl (TYPE_DECL, name, t);
+ TYPE_NAME (TREE_TYPE (d)) = d;
+ TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ DECL_ARTIFICIAL (d) = 1;
+
+ /* See if we already have this type. */
+ e = hash_lookup (&ht, t, /*create=*/false, /*copy=*/0);
+ if (e)
+ {
+ /* This will free not only TREE_TYPE, but the lang-specific data
+ and the TYPE_DECL as well. */
+ obstack_free (&permanent_obstack, t);
+ t = (tree) e->key;
+ }
+ else
+ /* Insert the type into the table. */
+ hash_lookup (&ht, t, /*create=*/true, /*copy=*/0);
+
+ pop_obstacks ();
+
+ return t;
+}
+
tree
make_typename_type (context, name)
tree context, name;
{
- tree t, d;
+ tree t;
tree fullname;
if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
- name = TYPE_IDENTIFIER (name);
+ {
+ if (!(TYPE_LANG_SPECIFIC (name)
+ && (CLASSTYPE_IS_TEMPLATE (name)
+ || CLASSTYPE_USE_TEMPLATE (name))))
+ name = TYPE_IDENTIFIER (name);
+ else
+ /* Create a TEMPLATE_ID_EXPR for the type. */
+ name = build_nt (TEMPLATE_ID_EXPR,
+ CLASSTYPE_TI_TEMPLATE (name),
+ CLASSTYPE_TI_ARGS (name));
+ }
else if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
@@ -4711,59 +5544,60 @@ make_typename_type (context, name)
if (TREE_CODE (name) != IDENTIFIER_NODE)
my_friendly_abort (2000);
+ if (TREE_CODE (context) == NAMESPACE_DECL)
+ {
+ /* We can get here from typename_sub0 in the explicit_template_type
+ expansion. Just fail. */
+ cp_error ("no class template named `%#T' in `%#T'",
+ name, context);
+ return error_mark_node;
+ }
+
if (! uses_template_parms (context)
|| currently_open_class (context))
{
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
{
+ tree tmpl = NULL_TREE;
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)
+ tmpl = lookup_field (context, name, 0, 0);
+ if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
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);
+ return lookup_template_class (tmpl,
+ TREE_OPERAND (fullname, 1),
+ NULL_TREE, context,
+ /*entering_scope=*/0);
}
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 (t)
+ 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;
+ /* If the CONTEXT is not a template type, then either the field is
+ there now or its never going to be. */
+ if (!uses_template_parms (context) && !t)
+ {
+ cp_error ("no type named `%#T' in `%#T'", name, context);
+ return error_mark_node;
+ }
+
+
+ return build_typename_type (context, name, fullname, NULL_TREE);
}
/* Select the right _DECL from multiple choices. */
@@ -4791,7 +5625,8 @@ select_decl (binding, flags)
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))
+ && (TREE_CODE (val) != TEMPLATE_DECL
+ || !DECL_CLASS_TEMPLATE_P (val)))
val = NULL_TREE;
return val;
@@ -4828,7 +5663,7 @@ unqualified_namespace_lookup (name, flags)
if (!lookup_using_namespace (name, b, level->using_directives,
scope, flags))
/* Give up because of error. */
- return NULL_TREE;
+ return error_mark_node;
/* Add all _DECLs seen through global using-directives. */
/* XXX local and global using lists should work equally. */
@@ -4838,7 +5673,7 @@ unqualified_namespace_lookup (name, flags)
if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
scope, flags))
/* Give up because of error. */
- return NULL_TREE;
+ return error_mark_node;
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
@@ -4888,6 +5723,32 @@ qualify_lookup (val, flags)
return val;
}
+/* Any other BINDING overrides an implicit TYPENAME. Warn about
+ that. */
+
+static void
+warn_about_implicit_typename_lookup (typename, binding)
+ tree typename;
+ tree binding;
+{
+ tree subtype = TREE_TYPE (TREE_TYPE (typename));
+ tree name = DECL_NAME (typename);
+
+ if (! (TREE_CODE (binding) == TEMPLATE_DECL
+ && CLASSTYPE_TEMPLATE_INFO (subtype)
+ && CLASSTYPE_TI_TEMPLATE (subtype) == binding)
+ && ! (TREE_CODE (binding) == TYPE_DECL
+ && same_type_p (TREE_TYPE (binding), subtype)))
+ {
+ cp_warning ("lookup of `%D' finds `%#D'",
+ name, binding);
+ cp_warning (" instead of `%D' from dependent base class",
+ typename);
+ cp_warning (" (use `typename %T::%D' if that's what you meant)",
+ constructor_name (current_class_type), name);
+ }
+}
+
/* Look up NAME in the current binding level and its superiors in the
namespace of variables, functions and typedefs. Return a ..._DECL
node of some kind representing its definition if there is only one
@@ -4907,11 +5768,12 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
tree name;
int prefer_type, nonclass, namespaces_only;
{
- register tree val;
+ tree t;
+ tree val = NULL_TREE;
int yylex = 0;
tree from_obj = NULL_TREE;
- tree locval, classval;
int flags;
+ int val_is_implicit_typename = 0;
/* Hack: copy flag set by parser, if set. */
if (only_namespace_names)
@@ -4926,8 +5788,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
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;
@@ -4957,6 +5817,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
{
struct tree_binding b;
val = binding_init (&b);
+ flags |= LOOKUP_COMPLAIN;
if (!qualified_lookup_using_namespace (name, type, val, flags))
return NULL_TREE;
val = select_decl (val, flags);
@@ -4967,26 +5828,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
|| TREE_CODE (type) == TYPENAME_TYPE)
/* Someone else will give an error about this if needed. */
val = NULL_TREE;
- else if (TYPE_BEING_DEFINED (type))
- {
- val = IDENTIFIER_CLASS_VALUE (name);
- if (val && DECL_CONTEXT (val) != type)
- {
- struct binding_level *b = class_binding_level;
- for (val = NULL_TREE; b; b = b->level_chain)
- {
- tree t = purpose_member (name, b->class_shadowed);
- if (t && TREE_VALUE (t)
- && DECL_CONTEXT (TREE_VALUE (t)) == type)
- {
- val = TREE_VALUE (t);
- break;
- }
- }
- }
- if (val == NULL_TREE)
- val = lookup_field (type, name, 0, 1);
- }
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
@@ -5001,73 +5842,56 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
from_obj = val;
}
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. */
- if (current_class_type && ! nonclass)
{
- 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. */
- 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);
+ flags = lookup_flags (prefer_type, namespaces_only);
+ /* If we're not parsing, we need to complain. */
+ flags |= LOOKUP_COMPLAIN;
+ }
- /* 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 (classval == NULL_TREE)
- classval = lookup_nested_field (name, ! yylex);
+ /* First, look in non-namespace scopes. */
+ for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t))
+ {
+ tree binding;
- classval = qualify_lookup (classval, flags);
+ if (!LOCAL_BINDING_P (t) && nonclass)
+ /* We're not looking for class-scoped bindings, so keep going. */
+ continue;
+
+ /* If this is the kind of thing we're looking for, we're done. */
+ if (qualify_lookup (BINDING_VALUE (t), flags))
+ binding = BINDING_VALUE (t);
+ else if ((flags & LOOKUP_PREFER_TYPES)
+ && qualify_lookup (BINDING_TYPE (t), flags))
+ binding = BINDING_TYPE (t);
+ else
+ binding = NULL_TREE;
+
+ if (binding
+ && (!val || !(TREE_CODE (binding) == TYPE_DECL
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (binding)))))
+ {
+ if (val_is_implicit_typename && !yylex)
+ warn_about_implicit_typename_lookup (val, binding);
+ val = binding;
+ val_is_implicit_typename
+ = (TREE_CODE (val) == TYPE_DECL
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (val)));
+ if (!val_is_implicit_typename)
+ break;
+ }
}
- if (locval && classval)
+ /* Now lookup in namespace scopes. */
+ if (!val || val_is_implicit_typename)
{
- if (current_scope () == current_function_decl
- && ! hack_decl_function_context (current_function_decl))
- /* Not in a nested function. */
- val = locval;
- else
+ t = unqualified_namespace_lookup (name, flags);
+ if (t)
{
- /* 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;
+ if (val_is_implicit_typename && !yylex)
+ warn_about_implicit_typename_lookup (val, t);
+ val = t;
}
}
- else if (locval)
- val = locval;
- else if (classval)
- val = classval;
- else
- val = unqualified_namespace_lookup (name, flags);
done:
if (val)
@@ -5092,17 +5916,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
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_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);
@@ -5144,15 +5957,21 @@ lookup_name (name, prefer_type)
return lookup_name_real (name, prefer_type, 0, 0);
}
-/* Similar to `lookup_name' but look only at current binding level. */
+/* Similar to `lookup_name' but look only in the innermost non-class
+ binding level. */
tree
lookup_name_current_level (name)
tree name;
{
- register tree t = NULL_TREE;
+ struct binding_level *b;
+ tree t = NULL_TREE;
+
+ b = current_binding_level;
+ while (b->parm_flag == 2)
+ b = b->level_chain;
- if (current_binding_level->namespace_p)
+ if (b->namespace_p)
{
t = IDENTIFIER_NAMESPACE_VALUE (name);
@@ -5160,13 +5979,14 @@ lookup_name_current_level (name)
if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST)
t = TREE_VALUE (t);
}
- else if (IDENTIFIER_LOCAL_VALUE (name) != NULL_TREE)
+ else if (IDENTIFIER_BINDING (name)
+ && LOCAL_BINDING_P (IDENTIFIER_BINDING (name)))
{
- struct binding_level *b = current_binding_level;
while (1)
{
- if (purpose_member (name, b->shadowed))
- return IDENTIFIER_LOCAL_VALUE (name);
+ if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
+ return IDENTIFIER_VALUE (name);
+
if (b->keep == 2)
b = b->level_chain;
else
@@ -5260,7 +6080,7 @@ static int builtin_type_tdescs_len, builtin_type_tdescs_max;
static void
record_builtin_type (rid_index, name, type)
enum rid rid_index;
- char *name;
+ const char *name;
tree type;
{
tree rname = NULL_TREE, tname = NULL_TREE;
@@ -5303,7 +6123,7 @@ record_builtin_type (rid_index, name, type)
static tree
record_builtin_java_type (name, size)
- char *name;
+ const char *name;
int size;
{
tree type, decl;
@@ -5322,7 +6142,12 @@ record_builtin_java_type (name, size)
}
record_builtin_type (RID_MAX, name, type);
decl = TYPE_NAME (type);
+
+ /* Suppress generate debug symbol entries for these types,
+ since for normal C++ they are just clutter.
+ However, push_lang_context undoes this if extern "Java" is seen. */
DECL_IGNORED_P (decl) = 1;
+
TYPE_FOR_JAVA (type) = 1;
return type;
}
@@ -5332,7 +6157,7 @@ record_builtin_java_type (name, size)
static void
record_unknown_type (type, name)
tree type;
- char *name;
+ const char *name;
{
tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
/* Make sure the "unknown type" typedecl gets ignored for debug info. */
@@ -5350,7 +6175,7 @@ static void
push_overloaded_decl_1 (x)
tree x;
{
- push_overloaded_decl (x, 0);
+ push_overloaded_decl (x, PUSH_GLOBAL);
}
#ifdef __GNUC__
@@ -5382,13 +6207,12 @@ init_decl_processing ()
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;
+ tree void_ftype, void_ftype_int, void_ftype_ptr;
/* Have to make these distinct before we try using them. */
lang_name_cplusplus = get_identifier ("C++");
@@ -5404,12 +6228,11 @@ init_decl_processing ()
current_lang_name = NULL_TREE;
if (flag_strict_prototype == 2)
- {
- if (pedantic)
- strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
- }
- else
- strict_prototypes_lang_c = flag_strict_prototype;
+ flag_strict_prototype = pedantic;
+ if (! flag_permissive && ! pedantic)
+ flag_pedantic_errors = 1;
+
+ strict_prototypes_lang_c = flag_strict_prototype;
/* Initially, C. */
current_lang_name = lang_name_c;
@@ -5420,7 +6243,6 @@ init_decl_processing ()
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. */
@@ -5442,13 +6264,6 @@ 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);
@@ -5496,6 +6311,9 @@ init_decl_processing ()
: make_unsigned_type (CHAR_TYPE_SIZE));
record_builtin_type (RID_CHAR, "char", char_type_node);
+ /* `signed' is the same as `int' */
+ record_builtin_type (RID_SIGNED, NULL_PTR, integer_type_node);
+
long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
record_builtin_type (RID_LONG, "long int", long_integer_type_node);
@@ -5545,8 +6363,10 @@ 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));
+#if HOST_BITS_PER_WIDE_INT >= 64
intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("__int128_t"), intTI_type_node));
+#endif
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));
@@ -5555,8 +6375,10 @@ 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));
+#if HOST_BITS_PER_WIDE_INT >= 64
unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("__uint128_t"), unsigned_intTI_type_node));
+#endif
float_type_node = make_node (REAL_TYPE);
TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
@@ -5652,7 +6474,8 @@ init_decl_processing ()
string_type_node = build_pointer_type (char_type_node);
const_string_type_node
- = build_pointer_type (build_type_variant (char_type_node, 1, 0));
+ = build_pointer_type (build_qualified_type (char_type_node,
+ TYPE_QUAL_CONST));
#if 0
record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
#endif
@@ -5682,7 +6505,8 @@ init_decl_processing ()
ptr_type_node = build_pointer_type (void_type_node);
const_ptr_type_node
- = build_pointer_type (build_type_variant (void_type_node, 1, 0));
+ = build_pointer_type (build_qualified_type (void_type_node,
+ TYPE_QUAL_CONST));
#if 0
record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node);
#endif
@@ -5779,10 +6603,6 @@ init_decl_processing ()
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", ptr_ftype_sizetype,
BUILT_IN_ALLOCA, "alloca");
builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
@@ -5951,10 +6771,7 @@ init_decl_processing ()
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
TREE_TYPE (unknown_type_node) = unknown_type_node;
- if (flag_ansi)
- TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0);
- else
- TREE_TYPE (null_node) = build_pointer_type (unknown_type_node);
+ TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0);
/* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same
result. */
@@ -6018,15 +6835,19 @@ init_decl_processing ()
DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node);
TREE_UNSIGNED (fields[3]) = 0;
TREE_CHAIN (fields[2]) = fields[3];
- vtable_entry_type = build_type_variant (vtable_entry_type, 1, 0);
+ vtable_entry_type = build_qualified_type (vtable_entry_type,
+ TYPE_QUAL_CONST);
}
record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
vtbl_type_node
- = build_array_type (vtable_entry_type, NULL_TREE);
+ = build_cplus_array_type (vtable_entry_type, NULL_TREE);
layout_type (vtbl_type_node);
- vtbl_type_node = cp_build_type_variant (vtbl_type_node, 1, 0);
+ vtbl_type_node = build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST);
record_builtin_type (RID_MAX, NULL_PTR, vtbl_type_node);
+ vtbl_ptr_type_node = build_pointer_type (vtable_entry_type);
+ layout_type (vtbl_ptr_type_node);
+ record_builtin_type (RID_MAX, NULL_PTR, vtbl_ptr_type_node);
/* Simplify life by making a "sigtable_entry_type". Give its
fields names so that the debugger can use them. */
@@ -6061,7 +6882,8 @@ init_decl_processing ()
TREE_UNSIGNED (fields[5]) = 0;
TREE_CHAIN (fields[4]) = fields[5];
- sigtable_entry_type = build_type_variant (sigtable_entry_type, 1, 0);
+ sigtable_entry_type = build_qualified_type (sigtable_entry_type,
+ TYPE_QUAL_CONST);
record_builtin_type (RID_MAX, SIGTABLE_PTR_TYPE, sigtable_entry_type);
}
@@ -6081,7 +6903,7 @@ init_decl_processing ()
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);
+ (class_type_node, get_identifier ("bad_alloc"), 1);
if (flag_honor_std)
pop_namespace ();
newtype = build_exception_variant
@@ -6090,7 +6912,8 @@ init_decl_processing ()
(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);
+ global_delete_fndecl
+ = auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN);
auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype, NOT_BUILT_IN);
}
@@ -6126,6 +6949,12 @@ init_decl_processing ()
print_error_function = lang_print_error_function;
lang_get_alias_set = &c_get_alias_set;
+ valid_lang_attribute = cp_valid_lang_attribute;
+
+ /* Maintain consistency. Perhaps we should just complain if they
+ say -fwritable-strings? */
+ if (flag_writable_strings)
+ flag_const_strings = 0;
}
/* Function to print any language-specific context for an error message. */
@@ -6148,11 +6977,11 @@ lang_print_error_function (file)
tree
define_function (name, type, function_code, pfn, library_name)
- char *name;
+ const char *name;
tree type;
enum built_in_function function_code;
void (*pfn) PROTO((tree));
- char *library_name;
+ const char *library_name;
{
tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
@@ -6177,52 +7006,80 @@ define_function (name, type, function_code, pfn, library_name)
return decl;
}
-/* Called when a declaration is seen that contains no names to declare.
- If its type is a reference to a structure, union or enum inherited
- from a containing scope, shadow that tag name for the current scope
- with a forward reference.
- If its type defines a new named structure or union
- or defines an enum, it is valid but we need not do anything here.
- Otherwise, it is an error.
+/* When we call finish_struct for an anonymous union, we create
+ default copy constructors and such. But, an anonymous union
+ shouldn't have such things; this function undoes the damage to the
+ anonymous union type T.
- C++: may have to grok the declspecs to learn about static,
- complain for anonymous unions. */
+ (The reason that we create the synthesized methods is that we don't
+ distinguish `union { int i; }' from `typedef union { int i; } U'.
+ The first is an anonymous union; the second is just an ordinary
+ union type.) */
void
-shadow_tag (declspecs)
+fixup_anonymous_union (t)
+ tree t;
+{
+ 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_CONST_ASSIGN_REF (t) = 0;
+
+ /* Splice the implicitly generated functions out of the TYPE_METHODS
+ list. */
+ 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");
+}
+
+/* Make sure that a declaration with no declarator is well-formed, i.e.
+ just defines a tagged type or anonymous union.
+
+ Returns the type defined, if any. */
+
+tree
+check_tag_decl (declspecs)
tree declspecs;
{
- int found_tag = 0;
+ int found_type = 0;
tree ob_modifier = NULL_TREE;
register tree link;
- register enum tree_code code, ok_code = ERROR_MARK;
register tree t = NULL_TREE;
for (link = declspecs; link; link = TREE_CHAIN (link))
{
register tree value = TREE_VALUE (link);
- code = TREE_CODE (value);
- if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE)
+ if (TYPE_P (value))
{
- my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
+ ++found_type;
- if (IS_AGGR_TYPE (value) && CLASSTYPE_USE_TEMPLATE (value))
+ if (IS_AGGR_TYPE (value) || TREE_CODE (value) == ENUMERAL_TYPE)
{
- 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);
+ my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
+ t = value;
}
-
- t = value;
- ok_code = code;
- found_tag++;
+ }
+ else if (value == ridpointers[(int) RID_FRIEND])
+ {
+ if (current_class_type == NULL_TREE
+ || current_scope () != current_class_type)
+ ob_modifier = value;
}
else if (value == ridpointers[(int) RID_STATIC]
|| value == ridpointers[(int) RID_EXTERN]
@@ -6230,47 +7087,77 @@ shadow_tag (declspecs)
|| value == ridpointers[(int) RID_REGISTER]
|| value == ridpointers[(int) RID_INLINE]
|| value == ridpointers[(int) RID_VIRTUAL]
+ || value == ridpointers[(int) RID_CONST]
+ || value == ridpointers[(int) RID_VOLATILE]
|| value == ridpointers[(int) RID_EXPLICIT])
ob_modifier = value;
}
+ if (found_type > 1)
+ error ("multiple types in one declaration");
+
+ /* Inside a class, we might be in a friend or access declaration.
+ Until we have a good way of detecting the latter, don't warn. */
+ if (t == NULL_TREE && ! current_class_type)
+ pedwarn ("declaration does not declare anything");
+
+ /* Check for an anonymous union. We're careful
+ accessing TYPE_IDENTIFIER because some built-in types, like
+ pointer-to-member types, do not have TYPE_NAME. */
+ else if (t && TREE_CODE (t) == UNION_TYPE
+ && TYPE_NAME (t)
+ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ {
+ /* Anonymous unions are objects, so they can have specifiers. */;
+ SET_ANON_UNION_TYPE_P (t);
+ }
+
+ else if (ob_modifier)
+ {
+ if (ob_modifier == ridpointers[(int) RID_INLINE]
+ || ob_modifier == ridpointers[(int) RID_VIRTUAL])
+ cp_error ("`%D' can only be specified for functions", ob_modifier);
+ else if (ob_modifier == ridpointers[(int) RID_FRIEND])
+ cp_error ("`%D' can only be specified inside a class", ob_modifier);
+ else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
+ cp_error ("`%D' can only be specified for constructors",
+ ob_modifier);
+ else
+ cp_error ("`%D' can only be specified for objects and functions",
+ ob_modifier);
+ }
+
+ return t;
+}
+
+/* Called when a declaration is seen that contains no names to declare.
+ If its type is a reference to a structure, union or enum inherited
+ from a containing scope, shadow that tag name for the current scope
+ with a forward reference.
+ If its type defines a new named structure or union
+ or defines an enum, it is valid but we need not do anything here.
+ Otherwise, it is an error.
+
+ C++: may have to grok the declspecs to learn about static,
+ complain for anonymous unions. */
+
+void
+shadow_tag (declspecs)
+ tree declspecs;
+{
+ tree t = check_tag_decl (declspecs);
+
+ if (t)
+ maybe_process_partial_specialization (t);
+
/* This is where the variables in an anonymous union are
declared. An anonymous union declaration looks like:
union { ... } ;
because there is no declarator after the union, the parser
sends that declaration here. */
- if (ok_code == UNION_TYPE
- && t != NULL_TREE
- && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE
- && ANON_AGGRNAME_P (TYPE_NAME (t)))
- || (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 (t && ANON_UNION_TYPE_P (t))
+ {
+ fixup_anonymous_union (t);
if (TYPE_FIELDS (t))
{
@@ -6279,29 +7166,6 @@ shadow_tag (declspecs)
finish_anon_union (decl);
}
}
- else
- {
- /* Anonymous unions are objects, that's why we only check for
- inappropriate specifiers in this branch. */
-
- if (ob_modifier)
- {
- if (ob_modifier == ridpointers[(int) RID_INLINE]
- || ob_modifier == ridpointers[(int) RID_VIRTUAL])
- cp_error ("`%D' can only be specified for functions", ob_modifier);
- else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
- cp_error ("`%D' can only be specified for constructors",
- ob_modifier);
- else
- cp_error ("`%D' can only be specified for objects and functions",
- ob_modifier);
- }
-
- if (found_tag == 0)
- cp_error ("abstract declarator used as declaration");
- else if (found_tag > 1)
- pedwarn ("multiple types in one declaration");
- }
}
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
@@ -6347,6 +7211,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree context;
extern int have_extern_spec;
extern int used_extern_spec;
+ tree attrlist;
#if 0
/* See code below that used this. */
@@ -6361,13 +7226,22 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
used_extern_spec = 1;
}
+ if (attributes || prefix_attributes)
+ attrlist = build_scratch_list (attributes, prefix_attributes);
+ else
+ attrlist = NULL_TREE;
+
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
- NULL_TREE);
+ attrlist);
+
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return NULL_TREE;
type = TREE_TYPE (decl);
+ if (type == error_mark_node)
+ return NULL_TREE;
+
/* Don't lose if destructors must be executed at file-level. */
if (! processing_template_decl && TREE_STATIC (decl)
&& TYPE_NEEDS_DESTRUCTOR (complete_type (type))
@@ -6468,8 +7342,17 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
DECL_INITIAL (decl) = error_mark_node;
}
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+ SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes);
+#endif
+
+ /* Set attributes here so if duplicate decl, will have proper attributes. */
+ cplus_decl_attributes (decl, attributes, prefix_attributes);
+
if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE)
{
+ push_nested_class (context, 2);
+
if (TREE_CODE (decl) == VAR_DECL)
{
tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
@@ -6506,18 +7389,23 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
DECL_IN_AGGR_P (decl) = 0;
if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
|| CLASSTYPE_USE_TEMPLATE (context))
- SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ {
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ /* [temp.expl.spec] An explicit specialization of a static data
+ member of a template is a definition if the declaration
+ includes an initializer; otherwise, it is a declaration.
+
+ We check for processing_specialization so this only applies
+ to the new specialization syntax. */
+ if (DECL_INITIAL (decl) == NULL_TREE && processing_specialization)
+ DECL_EXTERNAL (decl) = 1;
+ }
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. */
@@ -6557,7 +7445,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
data segment. */
DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem);
#endif
-
+
if (! processing_template_decl)
start_decl_1 (tem);
@@ -6600,6 +7488,9 @@ start_decl_1 (decl)
tree type = TREE_TYPE (decl);
int initialized = (DECL_INITIAL (decl) != NULL_TREE);
+ if (type == error_mark_node)
+ return;
+
/* 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. */
@@ -6614,9 +7505,7 @@ start_decl_1 (decl)
{
/* Don't allow initializations for incomplete types except for
arrays which might be completed by the initialization. */
- if (type == error_mark_node)
- ; /* Don't complain again. */
- else if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
+ if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
@@ -6716,10 +7605,6 @@ grok_reference_init (decl, type, init)
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);
@@ -6800,6 +7685,25 @@ obscure_complex_init (decl, init)
return init;
}
+/* Issue an error message if DECL is an uninitialized const variable. */
+
+static void
+check_for_uninitialized_const_var (decl)
+ tree decl;
+{
+ tree type = TREE_TYPE (decl);
+
+ /* ``Unless explicitly declared extern, a const object does not have
+ external linkage and must be initialized. ($8.4; $12.1)'' ARM
+ 7.1.6 */
+ if (TREE_CODE (decl) == VAR_DECL
+ && TREE_CODE (type) != REFERENCE_TYPE
+ && CP_TYPE_CONST_P (type)
+ && !TYPE_NEEDS_CONSTRUCTING (type)
+ && !DECL_INITIAL (decl))
+ cp_error ("uninitialized const `%D'", decl);
+}
+
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
@@ -6836,6 +7740,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
char *asmspec = NULL;
int was_readonly = 0;
int already_used = 0;
+ tree core_type;
/* If this is 0, then we did not change obstacks. */
if (! decl)
@@ -6856,6 +7761,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
init = NULL_TREE;
}
+ if (current_class_type
+ && DECL_REAL_CONTEXT (decl) == current_class_type
+ && TYPE_BEING_DEFINED (current_class_type)
+ && (DECL_INITIAL (decl) || init))
+ DECL_DEFINED_IN_CLASS_P (decl) = 1;
+
if (TREE_CODE (decl) == VAR_DECL
&& DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
@@ -6882,6 +7793,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
return;
}
+ if (TYPE_HAS_MUTABLE_P (type))
+ TREE_READONLY (decl) = 0;
+
if (processing_template_decl)
{
if (init && DECL_INITIAL (decl))
@@ -6982,6 +7896,10 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
GNU_xref_decl (current_function_decl, decl);
+ core_type = type;
+ while (TREE_CODE (core_type) == ARRAY_TYPE)
+ core_type = TREE_TYPE (core_type);
+
if (TREE_CODE (decl) == FIELD_DECL)
;
else if (TREE_CODE (decl) == CONST_DECL)
@@ -7000,7 +7918,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
{
if (TREE_CODE (type) == ARRAY_TYPE)
init = digest_init (type, init, (tree *) 0);
- else if (TREE_CODE (init) == CONSTRUCTOR)
+ else if (TREE_CODE (init) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (init))
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
@@ -7029,44 +7948,25 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't'
&& (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
{
- tree ctype = type;
- while (TREE_CODE (ctype) == ARRAY_TYPE)
- ctype = TREE_TYPE (ctype);
- if (! TYPE_NEEDS_CONSTRUCTING (ctype))
+ if (! TYPE_NEEDS_CONSTRUCTING (core_type))
{
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (ctype))
+ if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
cp_error ("structure `%D' with uninitialized const members", decl);
- if (CLASSTYPE_REF_FIELDS_NEED_INIT (ctype))
+ if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
cp_error ("structure `%D' with uninitialized reference members",
decl);
}
- if (TREE_CODE (decl) == VAR_DECL
- && !DECL_INITIAL (decl)
- && !TYPE_NEEDS_CONSTRUCTING (type)
- && (TYPE_READONLY (type) || TREE_READONLY (decl)))
- cp_error ("uninitialized const `%D'", decl);
+ check_for_uninitialized_const_var (decl);
if (TYPE_SIZE (type) != NULL_TREE
&& TYPE_NEEDS_CONSTRUCTING (type))
init = obscure_complex_init (decl, NULL_TREE);
- }
- else if (TREE_CODE (decl) == VAR_DECL
- && TREE_CODE (type) != REFERENCE_TYPE
- && (TYPE_READONLY (type) || TREE_READONLY (decl)))
- {
- /* ``Unless explicitly declared extern, a const object does not have
- external linkage and must be initialized. ($8.4; $12.1)'' ARM 7.1.6
- However, if it's `const int foo = 1; const int foo;', don't complain
- about the second decl, since it does have an initializer before.
- We deliberately don't complain about arrays, because they're
- supposed to be initialized by a constructor. */
- if (! DECL_INITIAL (decl)
- && TREE_CODE (type) != ARRAY_TYPE
- && (!pedantic || !current_class_type))
- cp_error ("uninitialized const `%#D'", decl);
- }
+ }
+ else
+ check_for_uninitialized_const_var (decl);
+
/* For top-level declaration, the initial value was read in
the temporary obstack. MAXINDEX, rtl, etc. to be made below
must go in the permanent obstack; but don't discard the
@@ -7234,7 +8134,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
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;
+ cp_warning_at (" you can work around this by removing the initializer", decl);
}
}
}
@@ -7242,31 +8142,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
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;
- }
- }
- }
+ /* Set it up again; we might have set DECL_INITIAL since the
+ last time. */
+ comdat_linkage (decl);
if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
make_decl_rtl (decl, NULL_PTR, toplev);
@@ -7343,17 +8221,17 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
resume_temporary_allocation ();
if (type != error_mark_node
- && TYPE_LANG_SPECIFIC (type)
- && CLASSTYPE_ABSTRACT_VIRTUALS (type))
- abstract_virtuals_error (decl, type);
+ && TYPE_LANG_SPECIFIC (core_type)
+ && CLASSTYPE_ABSTRACT_VIRTUALS (core_type))
+ abstract_virtuals_error (decl, core_type);
else if ((TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
&& TYPE_LANG_SPECIFIC (TREE_TYPE (type))
&& CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (type)))
abstract_virtuals_error (decl, TREE_TYPE (type));
- if (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE (type))
- signature_error (decl, type);
+ if (TYPE_LANG_SPECIFIC (core_type) && IS_SIGNATURE (core_type))
+ signature_error (decl, core_type);
else if ((TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
&& TYPE_LANG_SPECIFIC (TREE_TYPE (type))
@@ -7414,7 +8292,8 @@ 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;
+ 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,
@@ -7426,36 +8305,20 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
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))
+ tree outer_binding
+ = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
+
+ if (outer_binding && BINDING_LEVEL (outer_binding) == outer
+ && (TREE_CODE (BINDING_VALUE (outer_binding))
+ == VAR_DECL)
+ && DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
{
- 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;
- }
+ BINDING_VALUE (outer_binding)
+ = DECL_SHADOWED_FOR_VAR (BINDING_VALUE (outer_binding));
+ current_binding_level->is_for_scope = 0;
}
+ else if (DECL_IN_MEMORY_P (decl))
+ preserve_temp_slots (DECL_RTL (decl));
}
expand_start_target_temps ();
@@ -7470,7 +8333,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
{
emit_line_note (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl));
- expand_aggr_init (decl, init, 0, flags);
+ expand_aggr_init (decl, init, flags);
}
/* Set this to 0 so we can tell whether an aggregate which
@@ -7524,7 +8387,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
the binding level.. */
&& TYPE_SIZE (context) != NULL_TREE
&& context == current_class_type)
- popclass (1);
+ pop_nested_class ();
}
}
@@ -7582,7 +8445,7 @@ expand_static_init (decl, init)
if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
cp_error ("multiple initializations given for `%D'", decl);
}
- else if (! toplevel_bindings_p () && ! pseudo_global_level_p ())
+ else if (! toplevel_bindings_p ())
{
/* Emit code to perform this initialization but once. */
tree temp;
@@ -7590,30 +8453,65 @@ expand_static_init (decl, init)
/* Remember this information until end of file. */
push_obstacks (&permanent_obstack, &permanent_obstack);
- /* Emit code to perform this initialization but once. */
+ /* Emit code to perform this initialization but once. This code
+ looks like:
+
+ static int temp = 0;
+ if (!temp) {
+ // Do initialization.
+ temp = 1;
+ // Register variable for destruction at end of program.
+ }
+
+ Note that the `temp' variable is only set to 1 *after* the
+ initialization is complete. This ensures that an exception,
+ thrown during the construction, will cause the variable to
+ reinitialized when we pass through this code again, as per:
+
+ [stmt.dcl]
+
+ If the initialization exits by throwing an exception, the
+ initialization is not complete, so it will be tried again
+ the next time control enters the declaration.
+
+ In theory, this process should be thread-safe, too; multiple
+ threads should not be able to initialize the variable more
+ than once. We don't yet attempt to ensure thread-safety. */
temp = get_temp_name (integer_type_node, 1);
rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
+
+ /* Begin the conditional initialization. */
expand_start_cond (build_binary_op (EQ_EXPR, temp,
- integer_zero_node, 1), 0);
+ integer_zero_node), 0);
expand_start_target_temps ();
- expand_assignment (temp, integer_one_node, 0, 0);
+ /* Do the initialization itself. */
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
|| (init && TREE_CODE (init) == TREE_LIST))
{
- expand_aggr_init (decl, init, 0, 0);
+ expand_aggr_init (decl, init, 0);
do_pending_stack_adjust ();
}
else if (init)
expand_assignment (decl, init, 0, 0);
- /* Cleanup any temporaries needed for the initial value. */
+ /* Set TEMP to 1. */
+ expand_assignment (temp, integer_one_node, 0, 0);
+
+ /* Cleanup any temporaries needed for the initial value. If
+ destroying one of the temporaries causes an exception to be
+ thrown, then the object itself has still been fully
+ constructed. */
expand_end_target_temps ();
+ /* Use atexit to register a function for destroying this static
+ variable. */
if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
{
tree cleanup, fcall;
static tree Atexit = 0;
+ int saved_flag_access_control;
+
if (Atexit == 0)
{
tree atexit_fndecl, PFV, pfvlist;
@@ -7630,38 +8528,55 @@ expand_static_init (decl, init)
build_function_type (void_type_node,
pfvlist),
NOT_BUILT_IN, NULL_PTR);
- assemble_external (atexit_fndecl);
+ mark_used (atexit_fndecl);
Atexit = default_conversion (atexit_fndecl);
pop_lang_context ();
pop_obstacks ();
}
+ /* Call build_cleanup before we enter the anonymous function
+ so that any access checks will be done relative to the
+ current scope, rather than the scope of the anonymous
+ function. */
+ build_cleanup (decl);
+
+ /* Now start the function. */
cleanup = start_anon_func ();
- expand_expr_stmt (build_cleanup (decl));
+
+ /* Now, recompute the cleanup. It may contain SAVE_EXPRs
+ that refer to the original function, rather than the
+ anonymous one. That will make the back-end think that
+ nested functions are in use, which causes confusion. */
+ saved_flag_access_control = flag_access_control;
+ flag_access_control = 0;
+ fcall = build_cleanup (decl);
+ flag_access_control = saved_flag_access_control;
+
+ /* Finish off the function. */
+ expand_expr_stmt (fcall);
end_anon_func ();
+
+ /* Call atexit with the cleanup function. */
mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
- fcall = build_function_call (Atexit, expr_tree_cons (NULL_TREE, cleanup, NULL_TREE));
+ 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)))
- {
- static_aggregates = perm_tree_cons (temp, decl, static_aggregates);
- TREE_STATIC (static_aggregates) = 1;
- }
-
/* Resume old (possibly temporary) allocation. */
pop_obstacks ();
}
else
{
- /* This code takes into account memory allocation
- policy of `start_decl'. Namely, if TYPE_NEEDS_CONSTRUCTING
- does not hold for this object, then we must make permanent
- the storage currently in the temporary obstack. */
- if (! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ /* This code takes into account memory allocation policy of
+ `start_decl'. Namely, if TYPE_NEEDS_CONSTRUCTING does not
+ hold for this object, then we must make permanent the storage
+ currently in the temporary obstack. */
+ if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
preserve_initializer ();
static_aggregates = perm_tree_cons (init, decl, static_aggregates);
}
@@ -7669,7 +8584,7 @@ expand_static_init (decl, init)
/* Make TYPE a complete type based on INITIAL_VALUE.
Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
- 2 if there was no information (in which case assume 1 if DO_DEFAULT). */
+ 2 if there was no information (in which case assume 0 if DO_DEFAULT). */
int
complete_array_type (type, initial_value, do_default)
@@ -7678,7 +8593,10 @@ complete_array_type (type, initial_value, do_default)
{
register tree maxindex = NULL_TREE;
int value = 0;
-
+
+ /* Allocate on the same obstack as TYPE. */
+ push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
+
if (initial_value)
{
/* Note MAXINDEX is really the maximum index,
@@ -7708,6 +8626,8 @@ complete_array_type (type, initial_value, do_default)
/* Make an error message unless that happened already. */
if (initial_value != error_mark_node)
value = 1;
+ else
+ initial_value = NULL_TREE;
/* Prevent further error messages. */
maxindex = build_int_2 (0, 0);
@@ -7724,23 +8644,28 @@ complete_array_type (type, initial_value, do_default)
if (maxindex)
{
tree itype;
+ tree domain;
+
+ domain = build_index_type (maxindex);
+ TYPE_DOMAIN (type) = domain;
- TYPE_DOMAIN (type) = build_index_type (maxindex);
if (! TREE_TYPE (maxindex))
- TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
+ TREE_TYPE (maxindex) = domain;
if (initial_value)
itype = TREE_TYPE (initial_value);
else
itype = NULL;
if (itype && !TYPE_DOMAIN (itype))
- TYPE_DOMAIN (itype) = TYPE_DOMAIN (type);
+ TYPE_DOMAIN (itype) = domain;
/* The type of the main variant should never be used for arrays
of different sizes. It should only ever be completed with the
size of the array. */
if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)))
- TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = TYPE_DOMAIN (type);
+ TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain;
}
+ pop_obstacks();
+
/* Lay out the type now that we can get the real answer. */
layout_type (type);
@@ -7755,7 +8680,7 @@ complete_array_type (type, initial_value, do_default)
static int
member_function_or_else (ctype, cur_type, string)
tree ctype, cur_type;
- char *string;
+ const char *string;
{
if (ctype && ctype != cur_type)
{
@@ -7773,7 +8698,7 @@ member_function_or_else (ctype, cur_type, string)
static void
bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
tree object;
- char *type;
+ const char *type;
int virtualp, quals, friendp, raises, inlinep;
{
if (virtualp)
@@ -7799,23 +8724,27 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
or `volatile'.
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. */
+ not look, and -1 if we should not call `grokclassfn' at all.
+
+ Returns `NULL_TREE' if something goes wrong, after issuing
+ applicable error messages. */
static tree
grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
- raises, attrlist, check, friendp, publicp, inlinep, funcdef_flag,
+ raises, 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;
+ tree quals, raises;
int check, friendp, publicp, inlinep, funcdef_flag, template_count;
tree in_namespace;
{
tree cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
+ int has_default_arg = 0;
tree t;
if (ctype)
@@ -7834,9 +8763,23 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
- /* This decl is not from the current namespace. */
+ /* If this decl has namespace scope, set that up. */
if (in_namespace)
- set_decl_namespace (decl, in_namespace);
+ set_decl_namespace (decl, in_namespace, friendp);
+ else if (publicp && ! ctype)
+ DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+
+ /* `main' and builtins have implicit 'C' linkage. */
+ if ((MAIN_NAME_P (declarator)
+ || (IDENTIFIER_LENGTH (declarator) > 10
+ && IDENTIFIER_POINTER (declarator)[0] == '_'
+ && IDENTIFIER_POINTER (declarator)[1] == '_'
+ && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
+ && current_lang_name == lang_name_cplusplus
+ && ctype == NULL_TREE
+ /* NULL_TREE means global namespace. */
+ && DECL_CONTEXT (decl) == NULL_TREE)
+ DECL_LANGUAGE (decl) = lang_c;
/* Should probably propagate const out from type to decl I bet (mrs). */
if (staticp)
@@ -7848,8 +8791,10 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (ctype)
DECL_CLASS_CONTEXT (decl) = ctype;
- if (ctype == NULL_TREE && MAIN_NAME_P (declarator))
+ if (ctype == NULL_TREE && DECL_MAIN_P (decl))
{
+ if (processing_template_decl)
+ error ("cannot declare `main' to be a template");
if (inlinep)
error ("cannot declare `main' to be inline");
else if (! publicp)
@@ -7857,7 +8802,37 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
inlinep = 0;
publicp = 1;
}
-
+
+ /* Members of anonymous types and local classes have no linkage; make
+ them internal. */
+ if (ctype && (ANON_AGGRNAME_P (TYPE_IDENTIFIER (ctype))
+ || hack_decl_function_context (TYPE_MAIN_DECL (ctype))))
+ publicp = 0;
+
+ if (publicp)
+ {
+ /* [basic.link]: A name with no linkage (notably, the name of a class
+ or enumeration declared in a local scope) shall not be used to
+ declare an entity with linkage.
+
+ Only check this for public decls for now. */
+ t = no_linkage_check (TREE_TYPE (decl));
+ if (t)
+ {
+ if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ {
+ if (DECL_LANGUAGE (decl) == lang_c)
+ /* Allow this; it's pretty common in C. */;
+ else
+ cp_pedwarn ("non-local function `%#D' uses anonymous type",
+ decl);
+ }
+ else
+ cp_pedwarn ("non-local function `%#D' uses local type `%T'",
+ decl, t);
+ }
+ }
+
TREE_PUBLIC (decl) = publicp;
if (! publicp)
{
@@ -7886,7 +8861,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (TREE_PURPOSE (t)
&& TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
{
- add_defarg_fn (decl);
+ has_default_arg = 1;
break;
}
@@ -7899,6 +8874,15 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
orig_declarator);
else
{
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ {
+ /* Something like `template <class T> friend void f<T>()'. */
+ cp_error ("template-id `%D' in declaration of primary template",
+ orig_declarator);
+ return NULL_TREE;
+ }
+
+
/* A friend declaration of the form friend void f<>(). Record
the information in the TEMPLATE_ID_EXPR. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
@@ -7906,9 +8890,37 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
= perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
TREE_OPERAND (orig_declarator, 1),
NULL_TREE);
+
+ if (has_default_arg)
+ {
+ cp_error ("default arguments are not allowed in declaration of friend template specialization `%D'",
+ decl);
+ return NULL_TREE;
+ }
+
+ if (inlinep)
+ {
+ cp_error ("`inline' is not allowed in declaration of friend template specialization `%D'",
+ decl);
+ return NULL_TREE;
+ }
}
}
+ if (has_default_arg)
+ add_defarg_fn (decl);
+
+ /* Plain overloading: will not be grok'd by grokclassfn. */
+ if (! ctype && ! processing_template_decl
+ && DECL_LANGUAGE (decl) != lang_c
+ && (! DECL_USE_TEMPLATE (decl) || name_mangling_version < 1))
+ set_mangled_name_for_decl (decl);
+
+ if (funcdef_flag)
+ /* Make the init_value nonzero so pushdecl knows this is not
+ tentative. error_mark_node is replaced later with the BLOCK. */
+ DECL_INITIAL (decl) = error_mark_node;
+
/* Caller will do the rest of this. */
if (check < 0)
return decl;
@@ -7926,14 +8938,16 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
the following calls is supposed to do. */
DECL_CONSTRUCTOR_P (decl) = 1;
- grokclassfn (ctype, declarator, decl, flags, quals);
+ grokclassfn (ctype, decl, flags, quals);
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
+ if (decl == error_mark_node)
+ return NULL_TREE;
- if ((! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
+ if ((! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
&& check)
{
tmp = check_classfn (ctype, decl);
@@ -7948,22 +8962,6 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
}
if (! grok_ctor_properties (ctype, decl))
return NULL_TREE;
-
- if (check == 0 && ! current_function_decl)
- {
- /* Assembler names live in the global namespace. */
- tmp = IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl));
- 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;
- }
- make_decl_rtl (decl, NULL_PTR, 1);
- }
}
else
{
@@ -7973,14 +8971,17 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
This call may change the type of the function (because
of default parameters)! */
if (ctype != NULL_TREE)
- grokclassfn (ctype, cname, decl, flags, quals);
+ grokclassfn (ctype, decl, flags, quals);
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
+ if (decl == error_mark_node)
+ return NULL_TREE;
+
if (ctype != NULL_TREE
- && (! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
+ && (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
&& check)
{
tmp = check_classfn (ctype, decl);
@@ -8000,8 +9001,11 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp)
{
+ /* Attempt to merge the declarations. This can fail, in
+ the case of some illegal specialization declarations. */
if (!duplicate_decls (decl, tmp))
- my_friendly_abort (892);
+ cp_error ("no `%#D' member function declared in class `%T'",
+ decl, ctype);
return tmp;
}
}
@@ -8009,37 +9013,6 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (ctype == NULL_TREE || check)
return decl;
- /* Now install the declaration of this function so that others may
- find it (esp. its DECL_FRIENDLIST). Don't do this for local class
- methods, though. */
- if (! current_function_decl)
- {
- if (!DECL_TEMPLATE_SPECIALIZATION (decl))
- {
- /* 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)
- cplus_decl_attributes (decl, TREE_PURPOSE (attrlist),
- TREE_VALUE (attrlist));
- make_decl_rtl (decl, NULL_PTR, 1);
- }
if (virtualp)
{
DECL_VIRTUAL_P (decl) = 1;
@@ -8078,16 +9051,27 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
}
else
{
- tree context = in_namespace ? in_namespace : current_namespace;
+ tree context;
+
+ if (in_namespace)
+ context = in_namespace;
+ else if (namespace_bindings_p () || RIDBIT_SETP (RID_EXTERN, specbits))
+ context = current_namespace;
+ else
+ context = NULL_TREE;
+
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);
+
+ if (context)
+ set_decl_namespace (decl, context, 0);
+
+ context = DECL_CONTEXT (decl);
+ if (declarator && context && current_lang_name != lang_name_c)
+ DECL_ASSEMBLER_NAME (decl) = build_static_name (context, declarator);
}
if (in_namespace)
- set_decl_namespace (decl, in_namespace);
+ set_decl_namespace (decl, in_namespace, 0);
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
@@ -8117,10 +9101,30 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
TREE_STATIC (decl) = !! RIDBIT_SETP (RID_STATIC, specbits);
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
+
+ if (TREE_PUBLIC (decl))
+ {
+ /* [basic.link]: A name with no linkage (notably, the name of a class
+ or enumeration declared in a local scope) shall not be used to
+ declare an entity with linkage.
+
+ Only check this for public decls for now. */
+ tree t = no_linkage_check (TREE_TYPE (decl));
+ if (t)
+ {
+ if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ /* Ignore for now; `enum { foo } e' is pretty common. */;
+ else
+ cp_pedwarn ("non-local variable `%#D' uses local type `%T'",
+ decl, t);
+ }
+ }
+
return decl;
}
-/* Create a canonical pointer to member function type. */
+/* Create and return a canonical pointer to member function type, for
+ TYPE, which is a POINTER_TYPE to a METHOD_TYPE. */
tree
build_ptrmemfunc_type (type)
@@ -8140,7 +9144,7 @@ build_ptrmemfunc_type (type)
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
u = make_lang_type (UNION_TYPE);
- IS_AGGR_TYPE (u) = 0;
+ SET_IS_AGGR_TYPE (u, 0);
fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type);
fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier,
delta_type_node);
@@ -8152,7 +9156,7 @@ build_ptrmemfunc_type (type)
/* Let the front-end know this is a pointer to member function... */
TYPE_PTRMEMFUNC_FLAG (t) = 1;
/* ... and not really an aggregate. */
- IS_AGGR_TYPE (t) = 0;
+ SET_IS_AGGR_TYPE (t, 0);
fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
delta_type_node);
@@ -8174,6 +9178,41 @@ build_ptrmemfunc_type (type)
return t;
}
+/* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
+ Check to see that the definition is valid. Issue appropriate error
+ messages. Return 1 if the definition is particularly bad, or 0
+ otherwise. */
+
+int
+check_static_variable_definition (decl, type)
+ tree decl;
+ tree type;
+{
+ /* 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 declaration (within the class), or in
+ the definition, but not both. If it appears in the class, the
+ member is a member constant. The file-scope definition is always
+ required. */
+ if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ cp_error ("in-class initialization of static data member of non-integral type `%T'",
+ type);
+ /* If we just return the declaration, crashes will sometimes
+ occur. We therefore return void_type_node, as if this was a
+ friend declaration, to cause callers to completely ignore
+ this declaration. */
+ return 1;
+ }
+ else if (!CP_TYPE_CONST_P (type))
+ cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
+ decl);
+ else if (pedantic && !INTEGRAL_TYPE_P (type))
+ cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
+
+ return 0;
+}
+
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
@@ -8201,6 +9240,9 @@ build_ptrmemfunc_type (type)
BITFIELD for a field with specified width.
INITIALIZED is 1 if the decl has an initializer.
+ ATTRLIST is a TREE_LIST node with prefix attributes in TREE_VALUE and
+ normal attributes in TREE_PURPOSE, or NULL_TREE.
+
In the TYPENAME case, DECLARATOR is really an absolute declarator.
It may also be so in the PARM case, for a prototype where the
argument type is specified but not the name.
@@ -8246,7 +9288,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree type = NULL_TREE;
int longlong = 0;
int constp;
+ int restrictp;
int volatilep;
+ int type_quals;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
@@ -8279,6 +9323,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree raises = NULL_TREE;
int template_count = 0;
tree in_namespace = NULL_TREE;
+ tree inner_attrs;
+ int ignore_attrs;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
@@ -8300,6 +9346,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
decl = *next;
switch (TREE_CODE (decl))
{
+ case TREE_LIST:
+ /* For attributes. */
+ next = &TREE_VALUE (decl);
+ break;
+
case COND_EXPR:
ctype = NULL_TREE;
next = &TREE_OPERAND (decl, 0);
@@ -8359,18 +9410,38 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
case CALL_EXPR:
if (parmlist_is_exprlist (TREE_OPERAND (decl, 1)))
{
- /* 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... */
+ /* 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... */
+
+ tree attributes, prefix_attributes;
*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);
+ if (attrlist)
+ {
+ attributes = TREE_PURPOSE (attrlist);
+ prefix_attributes = TREE_VALUE (attrlist);
+ }
+ else
+ {
+ attributes = NULL_TREE;
+ prefix_attributes = NULL_TREE;
+ }
+
+ decl = start_decl (declarator, declspecs, 1,
+ attributes, prefix_attributes);
+ if (decl)
+ {
+ /* Look for __unused__ attribute */
+ if (TREE_USED (TREE_TYPE (decl)))
+ TREE_USED (decl) = 1;
+ finish_decl (decl, init, NULL_TREE);
+ }
+ else
+ cp_error ("invalid declarator");
return 0;
}
innermost_code = TREE_CODE (decl);
@@ -8403,12 +9474,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
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
- my_friendly_abort (0);
+ dname = fns;
+ if (TREE_CODE (dname) == COMPONENT_REF)
+ dname = TREE_OPERAND (dname, 1);
+ if (TREE_CODE (dname) != IDENTIFIER_NODE)
+ {
+ my_friendly_assert (is_overloaded_fn (dname),
+ 19990331);
+ dname = DECL_NAME (get_first_fn (dname));
+ }
}
/* Fall through. */
@@ -8747,24 +9821,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else
{
- if (funcdef_flag)
- {
- if (warn_return_type
- && return_type == return_normal)
- /* Save warning until we know what is really going on. */
- warn_about_return_type = 1;
- }
- else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
- pedwarn ("ANSI C++ forbids typedef which does not specify a type");
- 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);
- }
+ /* We handle `main' specially here, because 'main () { }' is so
+ common. With no options, it is allowed. With -Wreturn-type,
+ it is a warning. It is only an error with -pedantic-errors. */
+ int is_main = (funcdef_flag
+ && MAIN_NAME_P (dname)
+ && ctype == NULL_TREE
+ && in_namespace == NULL_TREE
+ && current_namespace == global_namespace);
+
+ if (in_system_header)
+ /* Allow it, sigh. */;
+ else if (pedantic || ! is_main)
+ cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type",
+ dname);
+ else if (warn_return_type)
+ cp_warning ("ANSI C++ forbids declaration `%D' with no type",
+ dname);
+
type = integer_type_node;
}
}
@@ -8780,7 +9854,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else if (return_type == return_conversion)
{
- if (comptypes (type, ctor_return_type, 1) == 0)
+ if (!same_type_p (type, ctor_return_type))
cp_error ("operator `%T' declared to return `%T'",
ctor_return_type, type);
else
@@ -8801,8 +9875,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& TYPE_MAIN_VARIANT (type) == double_type_node)
{
RIDBIT_RESET (RID_LONG, specbits);
- type = build_type_variant (long_double_type_node, TYPE_READONLY (type),
- TYPE_VOLATILE (type));
+ type = build_qualified_type (long_double_type_node,
+ CP_TYPE_QUALS (type));
}
/* Check all other uses of type modifiers. */
@@ -8924,17 +9998,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (return_type == return_conversion
&& (RIDBIT_SETP (RID_CONST, specbits)
- || RIDBIT_SETP (RID_VOLATILE, specbits)))
- cp_error ("`operator %T' cannot be cv-qualified",
+ || RIDBIT_SETP (RID_VOLATILE, specbits)
+ || RIDBIT_SETP (RID_RESTRICT, specbits)))
+ cp_error ("qualifiers are not allowed on declaration of `operator %T'",
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);
+ constp = !! RIDBIT_SETP (RID_CONST, specbits) + CP_TYPE_CONST_P (type);
+ restrictp =
+ !! RIDBIT_SETP (RID_RESTRICT, specbits) + CP_TYPE_RESTRICT_P (type);
+ volatilep =
+ !! RIDBIT_SETP (RID_VOLATILE, specbits) + CP_TYPE_VOLATILE_P (type);
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
+ type = cp_build_qualified_type (type, type_quals);
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
@@ -8954,6 +10035,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
friendp = RIDBIT_SETP (RID_FRIEND, specbits);
RIDBIT_RESET (RID_FRIEND, specbits);
+ /* $7.1.2, Function specifiers */
+ if (friendp && explicitp)
+ error ("only declarations of constructors can be `explicit'");
+
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
if (decl_context == PARM)
@@ -9011,16 +10096,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& IS_SIGNATURE (current_class_type)
&& RIDBIT_NOTSETP (RID_TYPEDEF, specbits))
{
- if (constp)
+ if (type_quals != TYPE_UNQUALIFIED)
{
- error ("`const' specified for signature member function `%s'", name);
- constp = 0;
- }
- if (volatilep)
- {
- error ("`volatile' specified for signature member function `%s'",
- name);
- volatilep = 0;
+ error ("type qualifiers specified for signature member function `%s'", name);
+ type_quals = TYPE_UNQUALIFIED;
}
if (inlinep)
{
@@ -9107,7 +10186,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
/* It's common practice (and completely valid) to have a const
be initialized and declared extern. */
- if (! constp)
+ if (!(type_quals & TYPE_QUAL_CONST))
warning ("`%s' initialized and declared `extern'", name);
}
else
@@ -9129,6 +10208,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
Descend through it, creating more complex types, until we reach
the declared identifier (or NULL_TREE, in an absolute declarator). */
+ inner_attrs = NULL_TREE;
+ ignore_attrs = 0;
+
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
&& TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
{
@@ -9175,8 +10257,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
quals = NULL_TREE;
}
}
+
+ /* See the comment for the TREE_LIST case, below. */
+ if (ignore_attrs)
+ ignore_attrs = 0;
+ else if (inner_attrs)
+ {
+ decl_attributes (type, inner_attrs, NULL_TREE);
+ inner_attrs = NULL_TREE;
+ }
+
switch (TREE_CODE (declarator))
{
+ case TREE_LIST:
+ {
+ /* We encode a declarator with embedded attributes using
+ a TREE_LIST. The attributes apply to the declarator
+ directly inside them, so we have to skip an iteration
+ before applying them to the type. If the declarator just
+ inside is the declarator-id, we apply the attrs to the
+ decl itself. */
+ inner_attrs = TREE_PURPOSE (declarator);
+ ignore_attrs = 1;
+ declarator = TREE_VALUE (declarator);
+ }
+ break;
+
case ARRAY_REF:
{
register tree itype = NULL_TREE;
@@ -9230,10 +10336,27 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (size == error_mark_node)
type = error_mark_node;
+ else if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
+ {
+ /* [dcl.array]
+
+ the constant expressions that specify the bounds of
+ the arrays can be omitted only for the first member
+ of the sequence. */
+ cp_error ("declaration of `%D' as multidimensional array",
+ dname);
+ cp_error ("must have bounds for all dimensions except the first");
+ type = error_mark_node;
+ }
if (type == error_mark_node)
continue;
+ /* VC++ spells a zero-sized array with []. */
+ if (size == NULL_TREE && decl_context == FIELD && ! staticp
+ && ! RIDBIT_SETP (RID_TYPEDEF, specbits))
+ size = integer_zero_node;
+
if (size)
{
/* Must suspend_momentary here because the index
@@ -9248,19 +10371,33 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0)))
size = TREE_OPERAND (size, 0);
- /* If this involves a template parameter, it'll be
- constant, but we don't know what the value is yet. */
+ /* If this involves a template parameter, it will be a
+ constant at instantiation time, but we don't know
+ what the value is yet. Even if no template
+ parameters are involved, we may an expression that
+ is not a constant; we don't even simplify `1 + 2'
+ when processing a template. */
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);
+ /* Resolve a qualified reference to an enumerator or
+ static const data member of ours. */
+ if (TREE_CODE (size) == SCOPE_REF
+ && TREE_OPERAND (size, 0) == current_class_type)
+ {
+ tree t = lookup_field (current_class_type,
+ TREE_OPERAND (size, 1), 0, 0);
+ if (t)
+ size = t;
+ }
+
+ itype = build_index_type (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)
+ && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE
+ && TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
{
cp_error ("size of array `%D' has non-integer type",
dname);
@@ -9301,7 +10438,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
= fold (build_binary_op (MINUS_EXPR,
cp_convert (index_type, size),
cp_convert (index_type,
- integer_one_node), 1));
+ integer_one_node)));
if (! TREE_CONSTANT (itype))
itype = variable_size (itype);
else if (TREE_OVERFLOW (itype))
@@ -9328,15 +10465,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
resume_momentary (yes);
}
- /* Build the array type itself, then merge any constancy or
- volatility into the target type. We must do it in this order
- to ensure that the TYPE_MAIN_VARIANT field of the array type
- is set correctly. */
-
type = build_cplus_array_type (type, itype);
- if (constp || volatilep)
- type = cp_build_type_variant (type, constp, volatilep);
-
ctype = NULL_TREE;
}
break;
@@ -9350,23 +10479,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Declaring a function type.
Make sure we have a valid type for the function to return. */
-#if 0
- /* Is this an error? Should they be merged into TYPE here? */
- if (pedantic && (constp || volatilep))
- pedwarn ("function declared to return const or volatile result");
-#else
- /* Merge any constancy or volatility into the function return
- type. */
- if (constp || volatilep)
- {
- type = cp_build_type_variant (type, constp, volatilep);
- if (IS_AGGR_TYPE (type))
- build_pointer_type (type);
- constp = 0;
- volatilep = 0;
- }
-#endif
+ /* We now know that the TYPE_QUALS don't apply to the
+ decl, but to its return type. */
+ type_quals = TYPE_UNQUALIFIED;
/* Warn about some types functions can't return. */
@@ -9574,21 +10690,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Merge any constancy or volatility into the target type
for the pointer. */
- if (constp || volatilep)
- {
- /* A const or volatile signature pointer/reference is
- pointing to a const or volatile object, i.e., the
- `optr' is const or volatile, respectively, not the
- signature pointer/reference itself. */
- if (! IS_SIGNATURE (type))
- {
- type = cp_build_type_variant (type, constp, volatilep);
- if (IS_AGGR_TYPE (type))
- build_pointer_type (type);
- constp = 0;
- volatilep = 0;
- }
- }
+ /* We now know that the TYPE_QUALS don't apply to the decl,
+ but to the target of the pointer. */
+ type_quals = TYPE_UNQUALIFIED;
if (IS_SIGNATURE (type))
{
@@ -9599,8 +10703,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
cp_warning ("empty signature `%T' used in signature reference declaration",
type);
#if 0
- type = build_signature_reference_type (type,
- constp, volatilep);
+ type = build_signature_reference_type (type);
#else
sorry ("signature reference");
return NULL_TREE;
@@ -9612,31 +10715,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& TYPE_SIZE (type))
cp_warning ("empty signature `%T' used in signature pointer declaration",
type);
- type = build_signature_pointer_type (type,
- constp, volatilep);
+ type = build_signature_pointer_type (type);
}
- constp = 0;
- volatilep = 0;
}
else if (TREE_CODE (declarator) == ADDR_EXPR)
{
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("cannot declare references to functions; use pointer to function instead");
- type = build_pointer_type (type);
- }
+ if (TREE_CODE (type) == VOID_TYPE)
+ error ("invalid type: `void &'");
else
- {
- if (TREE_CODE (type) == VOID_TYPE)
- error ("invalid type: `void &'");
- else
- type = build_reference_type (type);
- }
+ type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
- {
- type = build_ptrmemfunc_type (build_pointer_type (type));
- }
+ type = build_ptrmemfunc_type (build_pointer_type (type));
else
type = build_pointer_type (type);
@@ -9647,25 +10737,37 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
register tree typemodlist;
int erred = 0;
+
+ constp = 0;
+ volatilep = 0;
+ restrictp = 0;
for (typemodlist = TREE_TYPE (declarator); typemodlist;
typemodlist = TREE_CHAIN (typemodlist))
{
- if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_CONST])
+ tree qualifier = TREE_VALUE (typemodlist);
+
+ if (qualifier == ridpointers[(int) RID_CONST])
constp++;
- else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE])
+ else if (qualifier == ridpointers[(int) RID_VOLATILE])
volatilep++;
+ else if (qualifier == ridpointers[(int) RID_RESTRICT])
+ restrictp++;
else if (!erred)
{
erred = 1;
- error ("invalid type modifier within %s declarator",
- TREE_CODE (declarator) == ADDR_EXPR
- ? "reference" : "pointer");
+ error ("invalid type modifier within pointer declarator");
}
}
if (constp > 1)
pedwarn ("duplicate `const'");
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
+ if (restrictp > 1)
+ pedwarn ("duplicate `restrict'");
+
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
if (TREE_CODE (declarator) == ADDR_EXPR
&& (constp || volatilep))
{
@@ -9673,8 +10775,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
pedwarn ("discarding `const' applied to a reference");
if (volatilep)
pedwarn ("discarding `volatile' applied to a reference");
- constp = volatilep = 0;
+ type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
}
+ type = cp_build_qualified_type (type, type_quals);
}
declarator = TREE_OPERAND (declarator, 0);
ctype = NULL_TREE;
@@ -9718,14 +10821,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& uses_template_parms (current_class_type))
{
tree args = current_template_args ();
- type = tsubst (type, args, NULL_TREE);
+ type = tsubst (type, args, /*complain=*/1, 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
qualified_id. */
- pop_nested_class (1);
+ pop_nested_class ();
TREE_COMPLEXITY (declarator) = current_class_depth;
}
else
@@ -9743,7 +10846,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
ctype = TREE_OPERAND (declarator, 0);
t = ctype;
- while (t != NULL_TREE)
+ while (t != NULL_TREE && CLASS_TYPE_P (t))
{
if (CLASSTYPE_TEMPLATE_INFO (t) &&
!CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
@@ -9779,8 +10882,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
if (current_class_type == NULL_TREE
|| friendp)
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
- TREE_TYPE (type), TYPE_ARG_TYPES (type));
+ type = build_cplus_method_type (ctype, TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
else
{
cp_error ("cannot declare member function `%T::%s' within `%T'",
@@ -9808,10 +10911,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
if (TREE_CODE (type) == FUNCTION_TYPE)
type
- = build_cplus_method_type (build_type_variant (ctype,
- constp,
- volatilep),
- TREE_TYPE (type),
+ = build_cplus_method_type (ctype, TREE_TYPE (type),
TYPE_ARG_TYPES (type));
}
else
@@ -9834,7 +10934,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
else
{
if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), TREE_TYPE (type), TYPE_ARG_TYPES (type));
+ type = build_cplus_method_type (ctype, TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
else
type = build_offset_type (ctype, type);
}
@@ -9861,19 +10962,28 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
- if (explicitp == 1)
+ /* See the comment for the TREE_LIST case, above. */
+ if (inner_attrs)
{
- error ("only constructors can be declared `explicit'");
- explicitp = 0;
+ if (! ignore_attrs)
+ decl_attributes (type, inner_attrs, NULL_TREE);
+ else if (attrlist)
+ TREE_VALUE (attrlist) = chainon (inner_attrs, TREE_VALUE (attrlist));
+ else
+ attrlist = build_decl_list (NULL_TREE, inner_attrs);
}
/* Now TYPE has the actual type. */
- /* If this is declaring a typedef name, return a TYPE_DECL. */
+ if (explicitp == 1)
+ {
+ error ("only constructors can be declared `explicit'");
+ explicitp = 0;
+ }
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
- if (constp)
+ if (type_quals & TYPE_QUAL_CONST)
{
error ("const `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
@@ -9885,20 +10995,35 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
+ if (declarator == NULL_TREE
+ || TREE_CODE (declarator) == IDENTIFIER_NODE
+ || (TREE_CODE (declarator) == TEMPLATE_ID_EXPR
+ && (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)))
+ /* OK */;
+ else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+ {
+ cp_error ("template-id `%D' used as a declarator", declarator);
+ declarator = dname;
+ }
+ else
+ /* Unexpected declarator format. */
+ my_friendly_abort (990210);
+
+ /* If this is declaring a typedef name, return a TYPE_DECL. */
+
if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
{
tree decl;
/* Note that the grammar rejects storage classes
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)
+ if (declarator == constructor_name (current_class_type))
cp_pedwarn ("ANSI C++ forbids nested type `%D' with same name as enclosing class",
declarator);
decl = build_lang_decl (TYPE_DECL, declarator, type);
@@ -9921,18 +11046,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
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)))
{
+ tree oldname = TYPE_NAME (type);
+ tree t;
+
+ /* FIXME: This is bogus; we should not be doing this for
+ cv-qualified types. */
+
/* Replace the anonymous name with the real name everywhere. */
lookup_tag_reverse (type, declarator);
- TYPE_NAME (type) = decl;
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ if (TYPE_NAME (t) == oldname)
+ TYPE_NAME (t) = decl;
if (TYPE_LANG_SPECIFIC (type))
TYPE_WAS_ANONYMOUS (type) = 1;
+ /* If this is a typedef within a template class, the nested
+ type is a (non-primary) template. The name for the
+ template needs updating as well. */
+ if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_TEMPLATE_INFO (type))
+ DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
+ = TYPE_IDENTIFIER (type);
+
/* XXX Temporarily set the scope.
When returning, start_decl expects it as NULL_TREE,
and will then then set it using pushdecl. */
@@ -9946,6 +11085,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
DECL_ASSEMBLER_NAME (decl)
= get_identifier (build_overload_name (type, 1, 1));
DECL_CONTEXT (decl) = NULL_TREE;
+
+ /* FIXME remangle member functions; member functions of a
+ type with external linkage have external linkage. */
}
if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE)
@@ -9971,9 +11113,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
if (RIDBIT_SETP (RID_MUTABLE, specbits))
- {
- error ("non-object member `%s' cannot be declared mutable", name);
- }
+ error ("non-object member `%s' cannot be declared mutable", name);
bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -10003,21 +11143,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
/* Note that the grammar rejects storage classes
in typenames, fields or parameters. */
- if (constp || volatilep)
+ if (type_quals != TYPE_UNQUALIFIED)
{
if (IS_SIGNATURE (type))
- error ("`const' or `volatile' specified with signature type");
- else
- type = cp_build_type_variant (type, constp, volatilep);
+ error ("type qualifiers specified for signature type");
+ type_quals = TYPE_UNQUALIFIED;
}
/* Special case: "friend class foo" looks like a TYPENAME context. */
if (friendp)
{
- if (volatilep)
+ if (type_quals != TYPE_UNQUALIFIED)
{
- cp_error ("`volatile' specified for friend class declaration");
- volatilep = 0;
+ cp_error ("type qualifiers specified for friend class declaration");
+ type_quals = TYPE_UNQUALIFIED;
}
if (inlinep)
{
@@ -10084,36 +11223,38 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Now create the decl, which may be a VAR_DECL, a PARM_DECL
or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
+ if (decl_context == PARM || decl_context == CATCHPARM)
+ {
+ if (ctype || in_namespace)
+ error ("cannot use `::' in parameter declaration");
+
+ /* A parameter declared as an array of T is really a pointer to T.
+ One declared as a function is really a pointer to a function.
+ One declared as a member is really a pointer to member. */
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ /* Transfer const-ness of array into that of type pointed to. */
+ type = build_pointer_type (TREE_TYPE (type));
+ type_quals = TYPE_UNQUALIFIED;
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ type = build_pointer_type (type);
+ else if (TREE_CODE (type) == OFFSET_TYPE)
+ type = build_pointer_type (type);
+ else if (TREE_CODE (type) == VOID_TYPE && declarator)
+ {
+ error ("declaration of `%s' as void", name);
+ return NULL_TREE;
+ }
+ }
+
{
register tree decl;
if (decl_context == PARM)
{
- if (ctype)
- error ("cannot use `::' in parameter declaration");
-
- /* A parameter declared as an array of T is really a pointer to T.
- One declared as a function is really a pointer to a function.
- One declared as a member is really a pointer to member. */
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- /* 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;
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_pointer_type (type);
- else if (TREE_CODE (type) == OFFSET_TYPE)
- type = build_pointer_type (type);
- else if (TREE_CODE (type) == VOID_TYPE && declarator)
- {
- error ("declaration of `%s' as void", name);
- return NULL_TREE;
- }
-
- decl = build_decl (PARM_DECL, declarator, complete_type (type));
+ decl = build_decl (PARM_DECL, declarator, type);
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -10143,6 +11284,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
are error_mark_node, for example. */
decl = NULL_TREE;
}
+ else if (in_namespace && !friendp)
+ {
+ /* Something like struct S { int N::j; }; */
+ cp_error ("invalid use of `::'");
+ decl = NULL_TREE;
+ }
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
int publicp = 0;
@@ -10191,8 +11338,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
else if (staticp < 2)
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
- TREE_TYPE (type), TYPE_ARG_TYPES (type));
+ type = build_cplus_method_type (ctype, TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
@@ -10204,19 +11351,48 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
? declarator : dname,
declarator,
- virtualp, flags, quals, raises, attrlist,
+ virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, publicp, inlinep,
funcdef_flag, template_count, in_namespace);
if (decl == NULL_TREE)
- return NULL_TREE;
+ return decl;
#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
+ /* [class.conv.ctor]
+
+ A constructor declared without the function-specifier
+ explicit that can be called with a single parameter
+ specifies a conversion from the type of its first
+ parameter to the type of its class. Such a constructor
+ is called a converting constructor. */
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
+ else if (DECL_CONSTRUCTOR_P (decl))
+ {
+ /* The constructor can be called with exactly one
+ parameter if there is at least one parameter, and
+ any subsequent parameters have default arguments.
+ We don't look at the first parameter, which is
+ really just the `this' parameter for the new
+ object. */
+ tree arg_types =
+ TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)));
+
+ /* Skip the `in_chrg' argument too, if present. */
+ if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (decl)))
+ arg_types = TREE_CHAIN (arg_types);
+
+ if (arg_types == void_list_node
+ || (arg_types
+ && TREE_CHAIN (arg_types)
+ && TREE_CHAIN (arg_types) != void_list_node
+ && !TREE_PURPOSE (TREE_CHAIN (arg_types))))
+ DECL_NONCONVERTING_P (decl) = 1;
+ }
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
@@ -10225,7 +11401,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* All method decls are public, so tell grokfndecl to set
TREE_PUBLIC, also. */
decl = grokfndecl (ctype, type, declarator, declarator,
- virtualp, flags, quals, raises, attrlist,
+ virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
template_count, in_namespace);
if (decl == NULL_TREE)
@@ -10273,9 +11449,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
tree t = NULL_TREE;
if (decl && DECL_NAME (decl))
- t = do_friend (ctype, declarator, decl,
- last_function_parms, flags, quals,
- funcdef_flag);
+ {
+ if (template_class_depth (current_class_type) == 0)
+ {
+ decl
+ = check_explicit_specialization
+ (declarator, decl,
+ template_count, 2 * (funcdef_flag != 0) + 4);
+ if (decl == error_mark_node)
+ return error_mark_node;
+ }
+
+ t = do_friend (ctype, declarator, decl,
+ last_function_parms, attrlist, flags, quals,
+ funcdef_flag);
+ }
if (t && funcdef_flag)
return t;
@@ -10303,42 +11491,39 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
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",
+ cp_pedwarn ("ANSI C++ forbids initialization of member `%D'",
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
- declaration (within the class), or in the definition,
- but not both. If it appears in the class, the member is
- a member constant. The file-scope definition is always
- required. */
- 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 (uses_template_parms (type))
+ /* We'll check at instantiation time. */
+ ;
+ else if (check_static_variable_definition (declarator,
+ type))
+ /* If we just return the declaration, crashes
+ will sometimes occur. We therefore return
+ void_type_node, as if this was a friend
+ declaration, to cause callers to completely
+ ignore this declaration. */
+ return void_type_node;
}
+ /* 9.2p13 [class.mem] */
+ if (declarator == constructor_name (current_class_type)
+ /* Divergence from the standard: In extern "C", we
+ allow non-static data members here, because C does
+ and /usr/include/netinet/in.h uses that. */
+ && (staticp || ! in_system_header))
+ cp_pedwarn ("ANSI C++ forbids data member `%D' with same name as enclosing class",
+ declarator);
+
if (staticp)
{
- /* ANSI C++ Apr '95 wp 9.2 */
- if (declarator == current_class_name)
- cp_pedwarn ("ANSI C++ forbids static member `%D' with same name as enclosing class",
- declarator);
-
/* C++ allows static class members.
All other work for this is done by grokfield.
- This VAR_DECL is built by build_lang_field_decl.
+ This VAR_DCL is built by build_lang_field_decl.
All other VAR_DECLs are built by build_decl. */
decl = build_lang_field_decl (VAR_DECL, declarator, type);
TREE_STATIC (decl) = 1;
@@ -10398,22 +11583,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
error ("virtual non-class function `%s'", name);
virtualp = 0;
}
-
- if (current_lang_name == lang_name_cplusplus
- && ! 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. */
- 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));
+ type = build_cplus_method_type (ctype, TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
/* Record presence of `static'. */
publicp = (ctype != NULL_TREE
@@ -10421,23 +11594,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|| !RIDBIT_SETP (RID_STATIC, specbits));
decl = grokfndecl (ctype, type, original_name, declarator,
- virtualp, flags, quals, raises, attrlist,
+ virtualp, flags, quals, raises,
1, friendp,
publicp, inlinep, funcdef_flag,
template_count, in_namespace);
if (decl == NULL_TREE)
return NULL_TREE;
- /* 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;
@@ -10467,35 +11630,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
/* It's a variable. */
- if (decl_context == CATCHPARM)
- {
- if (ctype)
- {
- ctype = NULL_TREE;
- error ("cannot use `::' in parameter declaration");
- }
-
- /* A parameter declared as an array of T is really a pointer to T.
- One declared as a function is really a pointer to a function.
- One declared as a member is really a pointer to member. */
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- /* 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;
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_pointer_type (type);
- else if (TREE_CODE (type) == OFFSET_TYPE)
- type = build_pointer_type (type);
- }
-
/* An uninitialized decl with `extern' is a reference. */
decl = grokvardecl (type, declarator, &specbits,
- initialized, constp, in_namespace);
+ initialized,
+ (type_quals & TYPE_QUAL_CONST) != 0,
+ in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -10540,14 +11679,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
DECL_THIS_STATIC (decl) = 1;
/* Record constancy and volatility. */
-
- if (constp)
- TREE_READONLY (decl) = TREE_CODE (type) != REFERENCE_TYPE;
- if (volatilep)
- {
- TREE_SIDE_EFFECTS (decl) = 1;
- TREE_THIS_VOLATILE (decl) = 1;
- }
+ /* FIXME: Disallow `restrict' pointer-to-member declarations. */
+ c_apply_type_quals_to_decl (type_quals, decl);
return decl;
}
@@ -10580,18 +11713,14 @@ parmlist_is_exprlist (exprs)
return 1;
}
-/* Subroutine of `grokparms'. In a fcn definition, arg types must
- be complete.
-
- C++: also subroutine of `start_function'. */
+/* Subroutine of start_function. Ensure that each of the parameter
+ types (as listed in PARMS) is complete, as is required for a
+ function definition. */
static void
require_complete_types_for_parms (parms)
tree parms;
{
- if (processing_template_decl)
- return;
-
while (parms)
{
tree type = TREE_TYPE (parms);
@@ -10604,35 +11733,110 @@ require_complete_types_for_parms (parms)
error ("parameter has incomplete type");
TREE_TYPE (parms) = error_mark_node;
}
-#if 0
- /* If the arg types are incomplete in a declaration,
- they must include undefined tags.
- These tags can never be defined in the scope of the declaration,
- so the types can never be completed,
- and no call can be compiled successfully. */
- /* This is not the right behavior for C++, but not having
- it is also probably wrong. */
else
- {
- /* Now warn if is a pointer to an incomplete type. */
- while (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
- type = TYPE_MAIN_VARIANT (type);
- if (TYPE_SIZE (type) == NULL_TREE)
- {
- if (DECL_NAME (parm) != NULL_TREE)
- warning ("parameter `%s' points to incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (parm)));
- else
- warning ("parameter points to incomplete type");
- }
- }
-#endif
+ layout_decl (parms, 0);
+
parms = TREE_CHAIN (parms);
}
}
+/* Returns DECL if DECL is a local variable (or parameter). Returns
+ NULL_TREE otherwise. */
+
+static tree
+local_variable_p (t)
+ tree t;
+{
+ if ((TREE_CODE (t) == VAR_DECL
+ /* A VAR_DECL with a context that is a _TYPE is a static data
+ member. */
+ && !TYPE_P (CP_DECL_CONTEXT (t))
+ /* Any other non-local variable must be at namespace scope. */
+ && TREE_CODE (CP_DECL_CONTEXT (t)) != NAMESPACE_DECL)
+ || (TREE_CODE (t) == PARM_DECL))
+ return t;
+
+ return NULL_TREE;
+}
+
+/* Check that ARG, which is a default-argument expression for a
+ parameter DECL, is legal. Returns ARG, or ERROR_MARK_NODE, if
+ something goes wrong. DECL may also be a _TYPE node, rather than a
+ DECL, if there is no DECL available. */
+
+tree
+check_default_argument (decl, arg)
+ tree decl;
+ tree arg;
+{
+ tree var;
+ tree decl_type;
+
+ if (TREE_CODE (arg) == DEFAULT_ARG)
+ /* We get a DEFAULT_ARG when looking at an in-class declaration
+ with a default argument. Ignore the argument for now; we'll
+ deal with it after the class is complete. */
+ return arg;
+
+ if (processing_template_decl || uses_template_parms (arg))
+ /* We don't do anything checking until instantiation-time. Note
+ that there may be uninstantiated arguments even for an
+ instantiated function, since default arguments are not
+ instantiated until they are needed. */
+ return arg;
+
+ if (TYPE_P (decl))
+ {
+ decl_type = decl;
+ decl = NULL_TREE;
+ }
+ else
+ decl_type = TREE_TYPE (decl);
+
+ if (arg == error_mark_node
+ || decl == error_mark_node
+ || TREE_TYPE (arg) == error_mark_node
+ || decl_type == error_mark_node)
+ /* Something already went wrong. There's no need to check
+ further. */
+ return error_mark_node;
+
+ /* [dcl.fct.default]
+
+ A default argument expression is implicitly converted to the
+ parameter type. */
+ if (!TREE_TYPE (arg)
+ || !can_convert_arg (decl_type, TREE_TYPE (arg), arg))
+ {
+ if (decl)
+ cp_error ("default argument for `%#D' has type `%T'",
+ decl, TREE_TYPE (arg));
+ else
+ cp_error ("default argument for paramter of type `%T' has type `%T'",
+ decl_type, TREE_TYPE (arg));
+
+ return error_mark_node;
+ }
+
+ /* [dcl.fct.default]
+
+ Local variables shall not be used in default argument
+ expressions.
+
+ The keyword `this' shall not be used in a default argument of a
+ member function. */
+ var = search_tree (arg, local_variable_p);
+ if (var)
+ {
+ cp_error ("default argument `%E' uses local variable `%D'",
+ arg, var);
+ return error_mark_node;
+ }
+
+ /* All is well. */
+ return arg;
+}
+
/* Decode the list of parameter types for a function type.
Given the list of things declared inside the parens,
return a list of types.
@@ -10725,9 +11929,13 @@ grokparms (first_parm, funcdef_flag)
TREE_PURPOSE (decl),
PARM, init != NULL_TREE,
NULL_TREE);
- if (! decl)
+ if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
- type = TREE_TYPE (decl);
+
+ /* Top-level qualifiers on the parameters are
+ ignored for function types. */
+ type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
+
if (TREE_CODE (type) == VOID_TYPE)
decl = void_type_node;
else if (TREE_CODE (type) == METHOD_TYPE)
@@ -10766,6 +11974,18 @@ grokparms (first_parm, funcdef_flag)
signature_error (decl, type);
any_error = 1; /* Seems like a good idea. */
}
+ else if (POINTER_TYPE_P (type))
+ {
+ tree t = type;
+ while (POINTER_TYPE_P (t)
+ || (TREE_CODE (t) == ARRAY_TYPE
+ && TYPE_DOMAIN (t) != NULL_TREE))
+ t = TREE_TYPE (t);
+ if (TREE_CODE (t) == ARRAY_TYPE)
+ cp_error ("parameter type `%T' includes %s to array of unknown bound",
+ type,
+ TYPE_PTR_P (type) ? "pointer" : "reference");
+ }
}
if (TREE_CODE (decl) == VOID_TYPE)
@@ -10794,43 +12014,10 @@ grokparms (first_parm, funcdef_flag)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (decl) = integer_type_node;
#endif
- if (!any_error)
+ if (!any_error && init)
{
- if (init)
- {
- 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)
- {
- if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init)))
- {
- /* ``Local variables may not be used in default
- 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. */
- cp_error ("local variable `%D' may not be used as a default argument", init);
- any_error = 1;
- }
- else if (TREE_READONLY_DECL_P (init))
- init = decl_constant_value (init);
- }
- else
- init = require_instantiated_type (type, init, integer_zero_node);
- 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);
- }
+ any_init++;
+ init = check_default_argument (decl, init);
}
else
init = NULL_TREE;
@@ -10875,10 +12062,6 @@ grokparms (first_parm, funcdef_flag)
last_function_parms = decls;
- /* In a fcn definition, arg types must be complete. */
- if (funcdef_flag > 0)
- require_complete_types_for_parms (last_function_parms);
-
return result;
}
@@ -10943,19 +12126,45 @@ grok_ctor_properties (ctype, decl)
parmtype = TREE_VALUE (parmtypes);
}
+ /* [class.copy]
+
+ A non-template constructor for class X is a copy constructor if
+ its first parameter is of type X&, const X&, volatile X& or const
+ volatile X&, and either there are no other parameters or else all
+ other parameters have default arguments. */
if (TREE_CODE (parmtype) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype
&& (TREE_CHAIN (parmtypes) == NULL_TREE
|| TREE_CHAIN (parmtypes) == void_list_node
- || TREE_PURPOSE (TREE_CHAIN (parmtypes))))
+ || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
{
TYPE_HAS_INIT_REF (ctype) = 1;
- if (TYPE_READONLY (TREE_TYPE (parmtype)))
+ if (CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_INIT_REF (ctype) = 1;
}
+ /* [class.copy]
+
+ A declaration of a constructor for a class X is ill-formed if its
+ first parameter is of type (optionally cv-qualified) X and either
+ there are no other parameters or else all other parameters have
+ default arguments.
+
+ We *don't* complain about member template instantiations that
+ have this form, though; they can occur as we try to decide what
+ constructor to use during overload resolution. Since overload
+ resolution will never prefer such a constructor to the
+ non-template copy constructor (which is either explicitly or
+ implicitly defined), there's no need to worry about their
+ existence. Theoretically, they should never even be
+ instantiated, but that's hard to forestall. */
else if (TYPE_MAIN_VARIANT (parmtype) == ctype
- && TREE_CHAIN (parmtypes) != NULL_TREE
- && TREE_CHAIN (parmtypes) == void_list_node)
+ && (TREE_CHAIN (parmtypes) == NULL_TREE
+ || TREE_CHAIN (parmtypes) == void_list_node
+ || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
{
cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
ctype, ctype);
@@ -10992,7 +12201,7 @@ unary_op_p (name)
return (name == ansi_opname [(int) TRUTH_NOT_EXPR]
|| name == ansi_opname [(int) BIT_NOT_EXPR]
|| name == ansi_opname [(int) COMPONENT_REF]
- || OPERATOR_TYPENAME_P (name));
+ || IDENTIFIER_TYPENAME_P (name));
}
/* Do a little sanity-checking on how they declared their operator. */
@@ -11011,8 +12220,16 @@ grok_op_properties (decl, virtualp, friendp)
if (! friendp)
{
- if (name == ansi_opname[(int) MODIFY_EXPR])
- TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
+ /* [class.copy]
+
+ A user-declared copy assignment operator X::operator= is a
+ non-static non-template member function of class X with
+ exactly one parameter of type X, X&, const X&, volatile X& or
+ const volatile X&. */
+ if (name == ansi_opname[(int) MODIFY_EXPR]
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
+ ;
else if (name == ansi_opname[(int) CALL_EXPR])
TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
else if (name == ansi_opname[(int) ARRAY_REF])
@@ -11075,7 +12292,7 @@ grok_op_properties (decl, virtualp, friendp)
an enumeration, or a reference to an enumeration. 13.4.0.6 */
if (! methodp || DECL_STATIC_FUNCTION_P (decl))
{
- if (OPERATOR_TYPENAME_P (name)
+ if (IDENTIFIER_TYPENAME_P (name)
|| name == ansi_opname[(int) CALL_EXPR]
|| name == ansi_opname[(int) MODIFY_EXPR]
|| name == ansi_opname[(int) COMPONENT_REF]
@@ -11121,7 +12338,7 @@ grok_op_properties (decl, virtualp, friendp)
else if (! friendp)
{
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
- char *what = 0;
+ const char *what = 0;
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
@@ -11155,7 +12372,7 @@ grok_op_properties (decl, virtualp, friendp)
{
TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
if (TREE_CODE (parmtype) != REFERENCE_TYPE
- || TYPE_READONLY (TREE_TYPE (parmtype)))
+ || CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1;
}
}
@@ -11175,7 +12392,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)
+ && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
{
if (methodp)
cp_error ("postfix `%D' must take `int' as its argument",
@@ -11207,14 +12424,14 @@ grok_op_properties (decl, virtualp, friendp)
if (list_length (argtypes) == 2)
{
if (TREE_CODE (ret) != REFERENCE_TYPE
- || !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
- arg, 1))
+ || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
+ arg))
cp_warning ("prefix `%D' should return `%T'", decl,
build_reference_type (arg));
}
else
{
- if (!comptypes (TYPE_MAIN_VARIANT (ret), arg, 1))
+ if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
cp_warning ("postfix `%D' should return `%T'", decl, arg);
}
}
@@ -11276,6 +12493,27 @@ grok_op_properties (decl, virtualp, friendp)
}
}
+static const char *
+tag_name (code)
+ enum tag_types code;
+{
+ switch (code)
+ {
+ case record_type:
+ return "struct";
+ case class_type:
+ return "class";
+ case union_type:
+ return "union ";
+ case enum_type:
+ return "enum";
+ case signature_type:
+ return "signature";
+ default:
+ my_friendly_abort (981122);
+ }
+}
+
/* Get the struct, enum or union (CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
@@ -11287,18 +12525,19 @@ grok_op_properties (decl, virtualp, friendp)
scope.) */
tree
-xref_tag (code_type_node, name, binfo, globalize)
+xref_tag (code_type_node, name, globalize)
tree code_type_node;
- tree name, binfo;
+ tree name;
int globalize;
{
enum tag_types tag_code;
enum tree_code code;
int temp = 0;
register tree ref, t;
- struct binding_level *b = inner_binding_level;
+ struct binding_level *b = current_binding_level;
int got_type = 0;
tree attributes = NULL_TREE;
+ tree context = NULL_TREE;
/* If we are called from the parser, code_type_node will sometimes be a
TREE_LIST. This indicates that the user wrote
@@ -11338,37 +12577,41 @@ xref_tag (code_type_node, name, binfo, globalize)
}
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 (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
- {
- /* 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);
- }
+ /* 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
{
if (t)
- ref = t;
- else
- ref = lookup_tag (code, name, b, 0);
+ {
+ /* [dcl.type.elab] If the identifier resolves to a
+ typedef-name or a template type-parameter, the
+ elaborated-type-specifier is ill-formed. */
+ if (t != TYPE_MAIN_VARIANT (t)
+ || (CLASS_TYPE_P (t) && TYPE_WAS_ANONYMOUS (t)))
+ cp_pedwarn ("using typedef-name `%D' after `%s'",
+ TYPE_NAME (t), tag_name (tag_code));
+ else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ cp_error ("using template type parameter `%T' after `%s'",
+ t, tag_name (tag_code));
+ ref = t;
+ }
+ else
+ ref = lookup_tag (code, name, b, 0);
+
if (! ref)
{
- /* Try finding it as a type declaration. If that wins, use it. */
+ /* Try finding it as a type declaration. If that wins,
+ use it. */
ref = lookup_name (name, 1);
if (ref != NULL_TREE
@@ -11385,6 +12628,50 @@ xref_tag (code_type_node, name, binfo, globalize)
else
ref = NULL_TREE;
}
+
+ if (ref && current_class_type
+ && template_class_depth (current_class_type)
+ && PROCESSING_REAL_TEMPLATE_DECL_P ())
+ {
+ /* Since GLOBALIZE is non-zero, we are not looking at a
+ definition of this tag. Since, in addition, we are currently
+ processing a (member) template declaration of a template
+ class, we must be very careful; consider:
+
+ template <class X>
+ struct S1
+
+ template <class U>
+ struct S2
+ { template <class V>
+ friend struct S1; };
+
+ Here, the S2::S1 declaration should not be confused with the
+ outer declaration. In particular, the inner version should
+ have a template parameter of level 2, not level 1. This
+ would be particularly important if the member declaration
+ were instead:
+
+ template <class V = U> friend struct S1;
+
+ say, when we should tsubst into `U' when instantiating
+ S2. On the other hand, when presented with:
+
+ template <class T>
+ struct S1 {
+ template <class U>
+ struct S2 {};
+ template <class U>
+ friend struct S2;
+ };
+
+ we must find the inner binding eventually. We
+ accomplish this by making sure that the new type we
+ create to represent this declaration has the right
+ TYPE_CONTEXT. */
+ context = TYPE_CONTEXT (ref);
+ ref = NULL_TREE;
+ }
}
push_obstacks_nochange ();
@@ -11430,6 +12717,7 @@ xref_tag (code_type_node, name, binfo, globalize)
struct binding_level *old_b = class_binding_level;
ref = make_lang_type (code);
+ TYPE_CONTEXT (ref) = context;
if (tag_code == signature_type)
{
@@ -11466,9 +12754,6 @@ xref_tag (code_type_node, name, binfo, globalize)
redeclare_class_template (ref, current_template_parms);
}
- if (binfo)
- xref_basetypes (code_type_node, name, ref, binfo);
-
/* Until the type is defined, tentatively accept whatever
structure tag the user hands us. */
if (TYPE_SIZE (ref) == NULL_TREE
@@ -11505,9 +12790,15 @@ xref_tag_from_type (old, id, globalize)
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
- return xref_tag (code_type_node, id, NULL_TREE, globalize);
+ return xref_tag (code_type_node, id, globalize);
}
+/* REF is a type (named NAME), for which we have just seen some
+ baseclasses. BINFO is a list of those baseclasses; the
+ TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of
+ the base-class. CODE_TYPE_NODE indicates whether REF is a class,
+ struct, or union. */
+
void
xref_basetypes (code_type_node, name, ref, binfo)
tree code_type_node;
@@ -11517,6 +12808,8 @@ xref_basetypes (code_type_node, name, ref, binfo)
/* In the declaration `A : X, Y, ... Z' we mark all the types
(A, X, Y, ..., Z) so we can check for duplicates. */
tree binfos;
+ tree base;
+
int i, len;
enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
@@ -11529,6 +12822,13 @@ xref_basetypes (code_type_node, name, ref, binfo)
len = list_length (binfo);
push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref));
+ /* First, make sure that any templates in base-classes are
+ instantiated. This ensures that if we call ourselves recursively
+ we do not get confused about which classes are marked and which
+ are not. */
+ for (base = binfo; base; base = TREE_CHAIN (base))
+ complete_type (TREE_VALUE (base));
+
SET_CLASSTYPE_MARKED (ref);
BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
@@ -11567,16 +12867,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
GNU_xref_hier (name, basetype, via_public, via_virtual, 0);
-#if 1
/* 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
+ if (TYPE_SIZE (basetype) == NULL_TREE
&& ! (current_template_parms && uses_template_parms (basetype)))
{
cp_error ("base class `%T' has incomplete type", basetype);
continue;
}
-#endif
else
{
if (CLASSTYPE_MARKED (basetype))
@@ -11600,9 +12898,12 @@ xref_basetypes (code_type_node, name, ref, binfo)
individual inheritance contains flags which say what
the `accessibility' of that particular inheritance is.) */
- base_binfo = make_binfo (integer_zero_node, basetype,
- TYPE_BINFO_VTABLE (basetype),
- TYPE_BINFO_VIRTUALS (basetype), NULL_TREE);
+ base_binfo
+ = make_binfo (integer_zero_node, basetype,
+ CLASS_TYPE_P (basetype)
+ ? TYPE_BINFO_VTABLE (basetype) : NULL_TREE,
+ CLASS_TYPE_P (basetype)
+ ? TYPE_BINFO_VIRTUALS (basetype) : NULL_TREE);
TREE_VEC_ELT (binfos, i) = base_binfo;
TREE_VIA_PUBLIC (base_binfo) = via_public;
@@ -11610,6 +12911,10 @@ xref_basetypes (code_type_node, name, ref, binfo)
TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
+ /* We need to unshare the binfos now so that lookups during class
+ definition work. */
+ unshare_base_binfos (base_binfo);
+
SET_CLASSTYPE_MARKED (basetype);
/* We are free to modify these bits because they are meaningless
@@ -11620,9 +12925,12 @@ xref_basetypes (code_type_node, name, ref, binfo)
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
}
- TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
- TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
- CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
+ if (CLASS_TYPE_P (basetype))
+ {
+ TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
+ TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+ }
+
i += 1;
}
}
@@ -11634,8 +12942,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
if (i > 1)
TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
else if (i == 1)
- TYPE_USES_MULTIPLE_INHERITANCE (ref)
- = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0)));
+ {
+ tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, 0));
+
+ if (CLASS_TYPE_P (basetype))
+ TYPE_USES_MULTIPLE_INHERITANCE (ref)
+ = TYPE_USES_MULTIPLE_INHERITANCE (basetype);
+ }
+
if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
@@ -11644,12 +12958,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
CLEAR_CLASSTYPE_MARKED (ref);
+ /* Now that we know all the base-classes, set up the list of virtual
+ bases. */
+ CLASSTYPE_VBASECLASSES (ref) = get_vbase_types (ref);
+
pop_obstacks ();
}
-tree current_local_enum = NULL_TREE;
-
/* Begin compiling the definition of an enumeration type.
NAME is its name (or null if anonymous).
Returns the type object, as yet incomplete.
@@ -11661,15 +12977,11 @@ start_enum (name)
tree name;
{
register tree enumtype = NULL_TREE;
- struct binding_level *b = inner_binding_level;
+ struct binding_level *b = current_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 ();
+ push_obstacks (&permanent_obstack, &permanent_obstack);
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
@@ -11686,14 +12998,9 @@ start_enum (name)
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;
-
/* We don't copy this value because build_enumerator needs to do it. */
enum_next_value = integer_zero_node;
enum_overflow = 0;
@@ -11708,39 +13015,63 @@ start_enum (name)
Returns ENUMTYPE. */
tree
-finish_enum (enumtype, values)
- register tree enumtype, values;
+finish_enum (enumtype)
+ tree enumtype;
{
register tree minnode = NULL_TREE, maxnode = NULL_TREE;
/* Calculate the maximum value of any enumerator in this type. */
+ tree values = TYPE_VALUES (enumtype);
if (values)
{
- register tree pair;
- register tree value = DECL_INITIAL (TREE_VALUE (values));
+ tree pair;
- 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;
-
- for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
+ for (pair = values; pair; pair = TREE_CHAIN (pair))
{
- value = DECL_INITIAL (TREE_VALUE (pair));
- if (! processing_template_decl)
- {
- TREE_TYPE (TREE_VALUE (pair)) = enumtype;
+ tree decl;
+ tree value;
+
+ /* The TREE_VALUE is a CONST_DECL for this enumeration
+ constant. */
+ decl = TREE_VALUE (pair);
+
+ /* The DECL_INITIAL will be NULL if we are processing a
+ template declaration and this enumeration constant had no
+ explicit initializer. */
+ value = DECL_INITIAL (decl);
+ if (value && !processing_template_decl)
+ {
+ /* Set the TREE_TYPE for the VALUE as well. That's so
+ that when we call decl_constant_value we get an
+ entity of the right type (but with the constant
+ value). Since we shouldn't ever call
+ decl_constant_value on a template type, there's no
+ reason to do that when processing_template_decl.
+ And, if the expression is something like a
+ TEMPLATE_PARM_INDEX or a CAST_EXPR doing so will
+ wreak havoc on the intended type of the expression.
+
+ Of course, there's also no point in trying to compute
+ minimum or maximum values if we're in a template. */
TREE_TYPE (value) = enumtype;
- if (tree_int_cst_lt (maxnode, value))
+
+ if (!minnode)
+ minnode = maxnode = value;
+ else if (tree_int_cst_lt (maxnode, value))
maxnode = value;
else if (tree_int_cst_lt (value, minnode))
minnode = value;
}
- TREE_VALUE (pair) = value;
+
+ if (processing_template_decl)
+ /* If this is just a template, leave the CONST_DECL
+ alone. That way tsubst_copy will find CONST_DECLs for
+ CONST_DECLs, and not INTEGER_CSTs. */
+ ;
+ else
+ /* In the list we're building up, we want the enumeration
+ values, not the CONST_DECLs. */
+ TREE_VALUE (pair) = value;
}
}
else
@@ -11750,76 +13081,76 @@ finish_enum (enumtype, values)
if (processing_template_decl)
{
- if (current_function_decl)
- {
- add_tree (build_min (TAG_DEFN, enumtype));
- resume_temporary_allocation ();
- }
- return enumtype;
+ tree scope = current_scope ();
+ if (scope && TREE_CODE (scope) == FUNCTION_DECL)
+ add_tree (build_min (TAG_DEFN, enumtype));
}
+ else
+ {
+ int unsignedp = tree_int_cst_sgn (minnode) >= 0;
+ int lowprec = min_precision (minnode, unsignedp);
+ int highprec = min_precision (maxnode, unsignedp);
+ int precision = MAX (lowprec, highprec);
+ tree tem;
- {
- int unsignedp = tree_int_cst_sgn (minnode) >= 0;
- int lowprec = min_precision (minnode, unsignedp);
- int highprec = min_precision (maxnode, unsignedp);
- int precision = MAX (lowprec, highprec);
-
- TYPE_SIZE (enumtype) = NULL_TREE;
-
- /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
+ TYPE_SIZE (enumtype) = NULL_TREE;
- TYPE_PRECISION (enumtype) = precision;
- if (unsignedp)
- fixup_unsigned_type (enumtype);
- else
- fixup_signed_type (enumtype);
+ /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
- 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));
- else
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+ TYPE_PRECISION (enumtype) = precision;
+ if (unsignedp)
+ fixup_unsigned_type (enumtype);
+ else
+ fixup_signed_type (enumtype);
- TYPE_SIZE (enumtype) = 0;
- layout_type (enumtype);
- }
+ 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));
+ else
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
- {
- register tree tem;
+ TYPE_SIZE (enumtype) = 0;
+ layout_type (enumtype);
- /* Fix up all variant types of this enum type. */
- for (tem = TYPE_MAIN_VARIANT (enumtype); tem;
- tem = TYPE_NEXT_VARIANT (tem))
- {
- TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
- 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);
- TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
- }
- }
+ /* Fix up all variant types of this enum type. */
+ for (tem = TYPE_MAIN_VARIANT (enumtype); tem;
+ tem = TYPE_NEXT_VARIANT (tem))
+ {
+ TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
+ 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);
+ TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
+ }
- /* Finish debugging output for this type. */
- rest_of_type_compilation (enumtype, namespace_bindings_p ());
+ /* Finish debugging output for this type. */
+ rest_of_type_compilation (enumtype, namespace_bindings_p ());
+ }
+
+ /* In start_enum we pushed obstacks. Here, we must pop them. */
+ pop_obstacks ();
return enumtype;
}
-/* Build and install a CONST_DECL for one value of the
- current enumeration type (one that was begun with start_enum).
- Return a tree-list containing the name and its value.
+/* Build and install a CONST_DECL for an enumeration constant of the
+ enumeration type TYPE whose NAME and VALUE (if any) are provided.
Assignment of sequential values by default is handled here. */
tree
-build_enumerator (name, value)
- tree name, value;
+build_enumerator (name, value, type)
+ tree name;
+ tree value;
+ tree type;
{
tree decl, result;
+ tree context;
/* Remove no-op casts from the value. */
if (value)
@@ -11856,41 +13187,43 @@ build_enumerator (name, value)
/* 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. */
-
- decl = current_scope ();
- if (decl && decl == current_class_type)
- {
- /* This enum declaration is local to the class, so we must put
- it in that class's list of decls. */
- decl = build_lang_field_decl (CONST_DECL, name, integer_type_node);
- DECL_INITIAL (decl) = value;
- TREE_READONLY (decl) = 1;
- pushdecl_class_level (decl);
- TREE_CHAIN (decl) = current_local_enum;
- current_local_enum = decl;
- }
- else
- {
- /* It's a global enum, or it's local to a function. (Note local to
- 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;
+ /* We always have to copy here; not all INTEGER_CSTs are unshared.
+ Even in other cases, we will later (in finish_enum) be setting the
+ type of VALUE. */
+ if (value != NULL_TREE)
+ value = copy_node (value);
- pushdecl (decl);
- GNU_xref_decl (current_function_decl, decl);
- }
+ /* C++ associates enums with global, function, or class declarations. */
+
+ context = current_scope ();
+ if (context && context == current_class_type)
+ /* This enum declaration is local to the class. */
+ decl = build_lang_field_decl (CONST_DECL, name, type);
+ else
+ /* It's a global enum, or it's local to a function. (Note local to
+ a function could mean local to a class method. */
+ decl = build_decl (CONST_DECL, name, type);
+
+ DECL_CONTEXT (decl) = FROB_CONTEXT (context);
+ DECL_INITIAL (decl) = value;
+ TREE_READONLY (decl) = 1;
+
+ if (context && context == current_class_type)
+ /* In something like `struct S { enum E { i = 7 }; };' we put `i'
+ on the TYPE_FIELDS list for `S'. (That's so that you can say
+ things like `S::i' later.) */
+ finish_member_declaration (decl);
+ else
+ {
+ pushdecl (decl);
+ GNU_xref_decl (current_function_decl, decl);
+ }
if (! processing_template_decl)
{
@@ -11904,30 +13237,6 @@ build_enumerator (name, value)
return result;
}
-tree
-grok_enum_decls (decl)
- tree decl;
-{
- tree d = current_local_enum;
-
- if (d == NULL_TREE)
- return decl;
-
- while (1)
- {
- if (TREE_CHAIN (d) == NULL_TREE)
- {
- TREE_CHAIN (d) = decl;
- break;
- }
- d = TREE_CHAIN (d);
- }
-
- decl = current_local_enum;
- current_local_enum = NULL_TREE;
-
- return decl;
-}
static int function_depth;
@@ -11936,6 +13245,15 @@ static int function_depth;
they describe the function's name and the type it returns,
but twisted together in a fashion that parallels the syntax of C.
+ If PRE_PARSED_P is non-zero then DECLARATOR is really the DECL for
+ the function we are about to process; DECLSPECS are ignored. For
+ example, we set PRE_PARSED_P when processing the definition of
+ inline function that was defined in-class; the definition is
+ actually processed when the class is complete. In this case,
+ PRE_PARSED_P is 2. We also set PRE_PARSED_P when instanting the
+ body of a template function, and when constructing thunk functions
+ and such; in these cases PRE_PARSED_P is 1.
+
This function creates a binding context for the function body
as well as setting up the FUNCTION_DECL in current_function_decl.
@@ -11972,7 +13290,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
/* Assume, until we see it does. */
current_function_returns_value = 0;
current_function_returns_null = 0;
- warn_about_return_type = 0;
named_labels = 0;
shadowed_labels = 0;
current_function_assigns_this = 0;
@@ -12037,17 +13354,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
doing_friend = 1;
}
- /* In a fcn definition, arg types must be complete. */
- 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 = 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;
}
@@ -12061,8 +13367,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
fntype = TREE_TYPE (decl1);
restype = TREE_TYPE (fntype);
- if (IS_AGGR_TYPE (restype) && ! TYPE_PTRMEMFUNC_P (restype)
- && ! CLASSTYPE_GOT_SEMICOLON (restype))
+ if (CLASS_TYPE_P (restype) && !CLASSTYPE_GOT_SEMICOLON (restype))
{
cp_error ("semicolon missing after declaration of `%#T'", restype);
shadow_tag (build_expr_list (NULL_TREE, restype));
@@ -12088,7 +13393,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
pedwarn ("return type for `main' changed to `int'");
TREE_TYPE (decl1) = fntype = default_function_type;
}
- warn_about_return_type = 0;
}
}
@@ -12098,16 +13402,37 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
&& IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
+ announce_function (decl1);
+
+ /* Set up current_class_type, and enter the scope of the class, if
+ appropriate. */
+ if (ctype)
+ push_nested_class (ctype, 1);
+ else if (DECL_STATIC_FUNCTION_P (decl1))
+ push_nested_class (DECL_CONTEXT (decl1), 2);
+
+ /* Now that we have entered the scope of the class, we must restore
+ the bindings for any template parameters surrounding DECL1, if it
+ is an inline member template. (Order is important; consider the
+ case where a template parameter has the same name as a field of
+ the class.) It is not until after this point that
+ PROCESSING_TEMPLATE_DECL is guaranteed to be set up correctly. */
+ if (pre_parsed_p == 2)
+ maybe_begin_member_template_processing (decl1);
+
+ /* We are now in the scope of the function being defined. */
current_function_decl = decl1;
+
/* Save the parm names or decls from this function's declarator
where store_parm_decls will find them. */
current_function_parms = last_function_parms;
current_function_parm_tags = last_function_parm_tags;
- announce_function (decl1);
-
if (! processing_template_decl)
{
+ /* In a function definition, arg types must be complete. */
+ require_complete_types_for_parms (current_function_parms);
+
if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE)
{
cp_error ("return-type `%#T' is an incomplete type",
@@ -12128,8 +13453,10 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
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));
+ TREE_READONLY (DECL_RESULT (decl1))
+ = CP_TYPE_CONST_P (TREE_TYPE (fntype));
+ TREE_THIS_VOLATILE (DECL_RESULT (decl1))
+ = CP_TYPE_VOLATILE_P (TREE_TYPE (fntype));
}
if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
@@ -12137,9 +13464,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
abstract_virtuals_error (decl1, TREE_TYPE (fntype));
}
- if (warn_about_return_type)
- 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]
@@ -12150,17 +13474,25 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
error_mark_node is replaced below (in poplevel) with the BLOCK. */
DECL_INITIAL (decl1) = error_mark_node;
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+ SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
+#endif
+
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
+ /* We must call push_template_decl after current_class_type is set
+ up. (If we are processing inline definitions after exiting a
+ class scope, current_class_type will be NULL_TREE until set above
+ by push_nested_class.) */
+ if (processing_template_decl)
+ decl1 = push_template_decl (decl1);
+
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */
-
- if (processing_template_decl)
- decl1 = push_template_decl (decl1);
- else if (pre_parsed_p == 0)
+ if (!processing_template_decl && pre_parsed_p == 0)
{
/* A specialization is not used to guide overload resolution. */
if ((flag_guiding_decls
@@ -12196,21 +13528,41 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
}
/* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external.
- It doesn't matter whether it's inline or not. */
+ This only affects inlines and template instantiations. */
else if (interface_unknown == 0
&& (! DECL_TEMPLATE_INSTANTIATION (decl1)
|| flag_alt_external_templates))
{
if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)
|| processing_template_decl)
- DECL_EXTERNAL (decl1)
- = (interface_only
- || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
+ {
+ DECL_EXTERNAL (decl1)
+ = (interface_only
+ || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines
+ && !DECL_VINDEX (decl1)));
+
+ /* For WIN32 we also want to put these in linkonce sections. */
+ maybe_make_one_only (decl1);
+ }
else
DECL_EXTERNAL (decl1) = 0;
DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
}
+ else if (interface_unknown && interface_only
+ && (! DECL_TEMPLATE_INSTANTIATION (decl1)
+ || flag_alt_external_templates))
+ {
+ /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
+ interface, we will have interface_only set but not
+ interface_known. In that case, we don't want to use the normal
+ heuristics because someone will supply a #pragma implementation
+ elsewhere, and deducing it here would produce a conflict. */
+ comdat_linkage (decl1);
+ DECL_EXTERNAL (decl1) = 0;
+ DECL_INTERFACE_KNOWN (decl1) = 1;
+ DECL_DEFER_OUTPUT (decl1) = 1;
+ }
else
{
/* This is a definition, not a reference.
@@ -12240,8 +13592,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (ctype)
{
- push_nested_class (ctype, 1);
-
/* If we're compiling a friend function, neither of the variables
current_class_ptr nor current_class_type will have values. */
if (! doing_friend)
@@ -12258,13 +13608,24 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
{
- int i = suspend_momentary ();
+ int i;
- /* Fool build_indirect_ref. */
+ if (! hack_decl_function_context (decl1))
+ temporary_allocation ();
+ i = suspend_momentary ();
+
+ /* Normally, build_indirect_ref returns
+ current_class_ref whenever current_class_ptr is
+ dereferenced. This time, however, we want it to
+ *create* current_class_ref, so we temporarily clear
+ current_class_ptr to fool it. */
current_class_ptr = NULL_TREE;
current_class_ref = build_indirect_ref (t, NULL_PTR);
current_class_ptr = t;
+
resume_momentary (i);
+ if (! hack_decl_function_context (decl1))
+ end_temporary_allocation ();
}
else
/* We're having a signature pointer here. */
@@ -12273,13 +13634,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
}
}
else
- {
- if (DECL_STATIC_FUNCTION_P (decl1))
- push_nested_class (DECL_CONTEXT (decl1), 2);
- else
- push_memoized_context (0, 1);
- current_class_ptr = current_class_ref = NULL_TREE;
- }
+ current_class_ptr = current_class_ref = NULL_TREE;
pushlevel (0);
current_binding_level->parm_flag = 1;
@@ -12288,6 +13643,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (attrs)
cplus_decl_attributes (decl1, NULL_TREE, attrs);
+
make_function_rtl (decl1);
/* Promote the value to int before returning it. */
@@ -12303,8 +13659,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
{
DECL_RESULT (decl1)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
- TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (restype);
- TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (restype);
+ TREE_READONLY (DECL_RESULT (decl1)) = CP_TYPE_CONST_P (restype);
+ TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = CP_TYPE_VOLATILE_P (restype);
}
/* Allocate further tree nodes temporarily during compilation
@@ -12381,9 +13737,6 @@ store_parm_decls ()
/* Initialize RTL machinery. */
init_function_start (fndecl, input_filename, lineno);
- /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
- declare_function_name ();
-
/* Create a binding level for the parms. */
expand_start_bindings (0);
@@ -12469,6 +13822,9 @@ store_parm_decls ()
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
+ /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
+ declare_function_name ();
+
/* Initialize the RTL code for the function. */
DECL_SAVED_INSNS (fndecl) = NULL_RTX;
if (! processing_template_decl)
@@ -12579,18 +13935,23 @@ store_return_init (return_id, init)
This is called after parsing the body of the function definition.
LINENO is the current line number.
- 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.
+ FLAGS is a bitwise or of the following values:
+ 1 - CALL_POPLEVEL
+ 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.
+ 2 - INCLASS_INLINE
+ We just finished processing the body of an in-class inline
+ function definition. (This processing will have taken place
+ after the class definition is complete.)
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)
+finish_function (lineno, flags, nested)
int lineno;
- int call_poplevel;
+ int flags;
int nested;
{
register tree fndecl = current_function_decl;
@@ -12599,13 +13960,16 @@ finish_function (lineno, call_poplevel, nested)
/* Label to use if this function is supposed to return a value. */
tree no_return_label = NULL_TREE;
tree decls = NULL_TREE;
+ int call_poplevel = (flags & 1) != 0;
+ int inclass_inline = (flags & 2) != 0;
+ int in_template;
/* When we get some parse errors, we can end up without a
current_function_decl, so cope. */
if (fndecl == NULL_TREE)
return;
- if (! nested && function_depth > 1)
+ if (function_depth > 1)
nested = 1;
fntype = TREE_TYPE (fndecl);
@@ -12698,7 +14062,8 @@ finish_function (lineno, call_poplevel, nested)
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. */
+ code we have to have at the end of this destructor.
+ `build_delete' will set the flag again. */
TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
/* These are two cases where we cannot delegate deletion. */
@@ -12757,8 +14122,6 @@ finish_function (lineno, call_poplevel, nested)
expand_end_cond ();
}
- TYPE_HAS_DESTRUCTOR (current_class_type) = 1;
-
virtual_size = c_sizeof (current_class_type);
/* At the end, call delete if that's what's requested. */
@@ -12792,7 +14155,7 @@ finish_function (lineno, call_poplevel, nested)
/* End of destructor. */
expand_end_bindings (NULL_TREE, getdecls () != NULL_TREE, 0);
- poplevel (2, 0, 0); /* XXX change to 1 */
+ poplevel (getdecls () != NULL_TREE, 0, 0);
/* Back to the top of destructor. */
/* Don't execute destructor code if `this' is NULL. */
@@ -12822,7 +14185,7 @@ finish_function (lineno, call_poplevel, nested)
if (! ok_to_optimize_dtor)
{
cond = build_binary_op (NE_EXPR,
- current_class_ptr, integer_zero_node, 1);
+ current_class_ptr, integer_zero_node);
expand_start_cond (cond, 0);
}
@@ -12877,12 +14240,10 @@ finish_function (lineno, call_poplevel, nested)
tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type);
CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE;
- DECL_RETURNS_FIRST_ARG (fndecl) = 1;
-
if (flag_this_is_variable > 0)
{
cond = build_binary_op (EQ_EXPR,
- current_class_ptr, integer_zero_node, 1);
+ current_class_ptr, integer_zero_node);
thenclause = build_modify_expr (current_class_ptr, NOP_EXPR,
build_new (NULL_TREE, current_class_type, void_type_node, 0));
}
@@ -13005,6 +14366,20 @@ finish_function (lineno, call_poplevel, nested)
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 1);
}
+
+ /* If we're processing a template, squirrel away the definition
+ until we do an instantiation. */
+ if (processing_template_decl)
+ {
+ --minimal_parse_mode;
+ DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
+ /* We have to save this value here in case
+ maybe_end_member_template_processing decides to pop all the
+ template parameters. */
+ in_template = 1;
+ }
+ else
+ in_template = 0;
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
@@ -13013,6 +14388,13 @@ finish_function (lineno, call_poplevel, nested)
my_friendly_abort (122);
poplevel (1, 0, 1);
+ /* If this is a in-class inline definition, we may have to pop the
+ bindings for the template parameters that we added in
+ maybe_begin_member_template_processing when start_function was
+ called. */
+ if (inclass_inline)
+ maybe_end_member_template_processing ();
+
/* 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
@@ -13021,10 +14403,8 @@ finish_function (lineno, call_poplevel, nested)
if (current_class_name)
{
ctype = current_class_type;
- pop_nested_class (1);
+ pop_nested_class ();
}
- else
- pop_memoized_context (1);
/* Must mark the RESULT_DECL as being in this function. */
DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
@@ -13033,7 +14413,7 @@ finish_function (lineno, call_poplevel, nested)
to the FUNCTION_DECL node itself. */
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
- if (! processing_template_decl)
+ if (!in_template)
{
int saved_flag_keep_inline_functions =
flag_keep_inline_functions;
@@ -13117,12 +14497,6 @@ finish_function (lineno, call_poplevel, nested)
/* 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);
@@ -13157,8 +14531,6 @@ finish_function (lineno, call_poplevel, nested)
}
/* Create the FUNCTION_DECL for a function definition.
- LINE1 is the line number that the definition absolutely begins on.
- LINE2 is the line number that the name of the function appears on.
DECLSPECS and DECLARATOR are the parts of the declaration;
they describe the return type and the name of the function,
but twisted together in a fashion that parallels the syntax of C.
@@ -13180,11 +14552,11 @@ finish_function (lineno, call_poplevel, nested)
CHANGES TO CODE IN `grokfield'. */
tree
-start_method (declspecs, declarator)
- tree declarator, declspecs;
+start_method (declspecs, declarator, attrlist)
+ tree declarator, declspecs, attrlist;
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
- NULL_TREE);
+ attrlist);
/* Something too ugly to handle. */
if (fndecl == NULL_TREE)
@@ -13213,12 +14585,15 @@ start_method (declspecs, declarator)
return void_type_node;
}
+ check_template_shadow (fndecl);
+
DECL_THIS_INLINE (fndecl) = 1;
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
- if (processing_template_decl)
+ /* We process method specializations in finish_struct_1. */
+ if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
fndecl = push_template_decl (fndecl);
/* We read in the parameters on the maybepermanent_obstack,
@@ -13293,23 +14668,11 @@ finish_method (decl)
for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
{
if (DECL_NAME (link) != NULL_TREE)
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
+ pop_binding (DECL_NAME (link), link);
my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
DECL_CONTEXT (link) = NULL_TREE;
}
- /* 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))
- 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,
@@ -13390,7 +14753,7 @@ maybe_build_cleanup_1 (decl, auto_delete)
tree decl, auto_delete;
{
tree type = TREE_TYPE (decl);
- if (TYPE_NEEDS_DESTRUCTOR (type))
+ if (type != error_mark_node && TYPE_NEEDS_DESTRUCTOR (type))
{
int temp = 0, flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
tree rval;
@@ -13467,38 +14830,30 @@ cplus_expand_expr_stmt (exp)
/* Arrange for all temps to disappear. */
expand_start_target_temps ();
- if (TREE_TYPE (exp) == unknown_type_node)
+ exp = require_complete_type_in_void (exp);
+
+ if (TREE_CODE (exp) == FUNCTION_DECL)
{
- if (TREE_CODE (exp) == ADDR_EXPR || TREE_CODE (exp) == TREE_LIST)
- error ("address of overloaded function with no contextual type information");
- else if (TREE_CODE (exp) == COMPONENT_REF)
- warning ("useless reference to a member function name, did you forget the ()?");
+ cp_warning ("reference, not call, to function `%D'", exp);
+ warning ("at this point in file");
}
- else
- {
- if (TREE_CODE (exp) == FUNCTION_DECL)
- {
- cp_warning ("reference, not call, to function `%D'", exp);
- warning ("at this point in file");
- }
#if 0
- /* We should do this eventually, but right now this causes regex.o from
- libg++ to miscompile, and tString to core dump. */
- exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
+ /* We should do this eventually, but right now this causes regex.o from
+ libg++ to miscompile, and tString to core dump. */
+ exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
#endif
- /* 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);
+ /* 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));
- }
+ /* 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. */
@@ -13547,15 +14902,14 @@ revert_static_member_fn (decl, fn, argtypes)
tree function = fn ? *fn : TREE_TYPE (*decl);
tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function);
- if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (args))))
- cp_error ("static member function `%#D' declared const", *decl);
- if (TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (args))))
- cp_error ("static member function `%#D' declared volatile", *decl);
+ if (CP_TYPE_QUALS (TREE_TYPE (TREE_VALUE (args)))
+ != TYPE_UNQUALIFIED)
+ cp_error ("static member function `%#D' declared with type qualifiers",
+ *decl);
args = TREE_CHAIN (args);
tmp = build_function_type (TREE_TYPE (function), args);
- tmp = build_type_variant (tmp, TYPE_READONLY (function),
- TYPE_VOLATILE (function));
+ tmp = build_qualified_type (tmp, CP_TYPE_QUALS (function));
tmp = build_exception_variant (tmp,
TYPE_RAISES_EXCEPTIONS (function));
TREE_TYPE (*decl) = tmp;
@@ -13568,23 +14922,16 @@ revert_static_member_fn (decl, fn, argtypes)
*argtypes = args;
}
-int
-id_in_current_class (id)
- tree id;
-{
- return !!purpose_member (id, class_binding_level->class_shadowed);
-}
-
struct cp_function
{
int returns_value;
int returns_null;
- int warn_about_return_type;
int assigns_this;
int just_assigned_this;
int parms_stored;
int temp_name_counter;
tree named_labels;
+ struct named_label_list *named_label_uses;
tree shadowed_labels;
tree ctor_label;
tree dtor_label;
@@ -13621,10 +14968,10 @@ push_cp_function_context (context)
cp_function_chain = p;
p->named_labels = named_labels;
+ p->named_label_uses = named_label_uses;
p->shadowed_labels = shadowed_labels;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
- p->warn_about_return_type = warn_about_return_type;
p->binding_level = current_binding_level;
p->ctor_label = ctor_label;
p->dtor_label = dtor_label;
@@ -13663,10 +15010,10 @@ pop_cp_function_context (context)
cp_function_chain = p->next;
named_labels = p->named_labels;
+ named_label_uses = p->named_label_uses;
shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
- warn_about_return_type = p->warn_about_return_type;
current_binding_level = p->binding_level;
ctor_label = p->ctor_label;
dtor_label = p->dtor_label;
diff --git a/contrib/gcc/cp/decl.h b/contrib/gcc/cp/decl.h
index f55dca5..fcb247e 100644
--- a/contrib/gcc/cp/decl.h
+++ b/contrib/gcc/cp/decl.h
@@ -42,11 +42,6 @@ extern tree this_identifier, in_charge_identifier;
or a chain or parameter decls here. */
extern tree last_function_parms;
-/* A list of static class variables. This is needed, because a
- static class variable can be declared inside the class without
- an initializer, and then initialized, staticly, outside the class. */
-extern tree pending_statics;
-
/* A list of objects which have constructors or destructors
which reside in the global scope. The decl is stored in
the TREE_VALUE slot and the initializer is stored
diff --git a/contrib/gcc/cp/decl2.c b/contrib/gcc/cp/decl2.c
index c87c607..84f491f 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, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -42,26 +42,60 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "dwarf2out.h"
#include "dwarfout.h"
+#include "splay-tree.h"
+#include "varray.h"
#if USE_CPPLIB
#include "cpplib.h"
extern cpp_reader parse_in;
-extern cpp_options parse_options;
-static int cpp_initialized;
#endif
+/* This structure contains information about the initializations
+ and/or destructions required for a particular priority level. */
+typedef struct priority_info_s {
+ /* A label indicating where we should generate the next
+ initialization with this priority. */
+ rtx initialization_sequence;
+ /* A label indicating where we should generate the next destruction
+ with this priority. */
+ rtx destruction_sequence;
+ /* Non-zero if there have been any initializations at this priority
+ throughout the translation unit. */
+ int initializations_p;
+ /* Non-zero if there have been any destructions at this priority
+ throughout the translation unit. */
+ int destructions_p;
+} *priority_info;
+
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 finish_vtable_vardecl PROTO((tree *, void *));
+static int prune_vtable_vardecl PROTO((tree *, void *));
+static int finish_sigtable_vardecl PROTO((tree *, void *));
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));
-
+static int acceptable_java_type PROTO((tree));
+static void output_vtable_inherit PROTO((tree));
+static void start_objects PROTO((int, int));
+static void finish_objects PROTO((int, int));
+static tree merge_functions PROTO((tree, tree));
+static tree decl_namespace PROTO((tree));
+static tree validate_nonmember_using_decl PROTO((tree, tree *, tree *));
+static void do_nonmember_using_decl PROTO((tree, tree, tree, tree,
+ tree *, tree *));
+static void start_static_storage_duration_function PROTO((void));
+static int generate_inits_for_priority PROTO((splay_tree_node, void *));
+static void finish_static_storage_duration_function PROTO((void));
+static priority_info get_priority_info PROTO((int));
+static void do_static_initialization PROTO((tree, tree, tree, int));
+static void do_static_destruction PROTO((tree, tree, int));
+static void do_static_initialization_and_destruction PROTO((tree, tree));
+static void generate_ctor_or_dtor_function PROTO((int, int));
+static int generate_ctor_and_dtor_functions_for_priority
+ PROTO((splay_tree_node, void *));
extern int current_class_depth;
/* A list of virtual function tables we must make sure to write out. */
@@ -70,11 +104,13 @@ tree pending_vtables;
/* A list of static class variables. This is needed, because a
static class variable can be declared inside the class without
an initializer, and then initialized, staticly, outside the class. */
-tree pending_statics;
+static varray_type pending_statics;
+static size_t pending_statics_used;
/* A list of functions which were declared inline, but which we
may need to emit outline anyway. */
-static tree saved_inlines;
+static varray_type saved_inlines;
+static size_t saved_inlines_used;
/* Used to help generate temporary names which are unique within
a function. Reset to 0 by start_function. */
@@ -144,10 +180,6 @@ int flag_traditional;
int flag_signed_bitfields = 1;
-/* Nonzero means handle `#ident' directives. 0 means ignore them. */
-
-int flag_no_ident;
-
/* Nonzero means enable obscure ANSI features and disable GNU extensions
that might cause ANSI-compliant code to be miscompiled. */
@@ -173,6 +205,12 @@ int flag_alt_external_templates;
int flag_implicit_templates = 1;
+/* Nonzero means that implicit instantiations of inline templates will be
+ emitted if needed, even if instantiations of non-inline templates
+ aren't. */
+
+int flag_implicit_inline_templates = 1;
+
/* Nonzero means warn about implicit declarations. */
int warn_implicit = 1;
@@ -203,9 +241,13 @@ int flag_use_repository;
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. */
+/* Nonzero means give string constants the type `const char *', as mandated
+ by the standard. */
+
+int flag_const_strings = 1;
+
+/* Nonzero means warn about deprecated conversion from string constant to
+ `char *'. */
int warn_write_strings;
@@ -295,6 +337,15 @@ int warn_unknown_pragmas; /* Tri state variable. */
int warn_multichar = 1;
+/* Nonzero means warn when non-templatized friend functions are
+ declared within a template */
+
+int warn_nontemplate_friend = 1;
+
+/* Nonzero means complain about deprecated features. */
+
+int warn_deprecated = 1;
+
/* Nonzero means `$' can be in an identifier. */
#ifndef DOLLARS_IN_IDENTIFIERS
@@ -318,40 +369,22 @@ int flag_labels_ok;
int flag_detailed_statistics;
/* C++ specific flags. */
-/* Nonzero for -fall-virtual: make every member function (except
- constructors) lay down in the virtual function table. Calls
- can then either go through the virtual function table or not,
- depending. */
-
-int flag_all_virtual;
-
/* Zero means that `this' is a *const. This gives nice behavior in the
2.0 world. 1 gives 1.2-compatible behavior. 2 gives Spring behavior.
-2 means we're constructing an object and it has fixed type. */
int flag_this_is_variable;
-/* Nonzero means memoize our member lookups. */
-
-int flag_memoize_lookups; int flag_save_memoized_contexts;
-
/* 3 means write out only virtuals function tables `defined'
in this implementation file.
- 2 means write out only specific virtual function tables
- and give them (C) public access.
- 1 means write out virtual function tables and give them
- (C) public access.
0 means write out virtual function tables and give them
- (C) static access (default).
- -1 means declare virtual function tables extern. */
+ (C) static access (default). */
int write_virtuals;
-/* 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. */
+/* Nonzero means we should attempt to elide constructors when possible. */
-int flag_elide_constructors;
+int flag_elide_constructors = 1;
/* Nonzero means recognize and handle signature language constructs. */
@@ -362,11 +395,6 @@ int flag_handle_signatures;
int flag_default_inline = 1;
-/* Controls whether enums and ints freely convert.
- 1 means with complete freedom.
- 0 means enums can convert to ints, but not vice-versa. */
-int flag_int_enum_equivalence;
-
/* Controls whether compiler generates 'type descriptor' that give
run-time type information. */
int flag_rtti = 1;
@@ -375,18 +403,6 @@ int flag_rtti = 1;
for the GNU class browser. */
extern int flag_gnu_xref;
-/* Nonzero if compiler can make `reasonable' assumptions about
- references and objects. For example, the compiler must be
- conservative about the following and not assume that `a' is nonnull:
-
- obj &a = g ();
- a.f (2);
-
- In general, it is `reasonable' to assume that for many programs,
- and better code can be generated in that case. */
-
-int flag_assume_nonnull_objects = 1;
-
/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
objects. */
@@ -453,6 +469,14 @@ int flag_guiding_decls;
and class qualifiers. */
int flag_do_squangling;
+/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
+
+int flag_vtable_gc;
+
+/* Nonzero means make the default pedwarns warnings instead of errors.
+ The value of this flag is ignored if -pedantic is specified. */
+
+int flag_permissive;
/* Table of language-dependent -f options.
STRING is the option name. VARIABLE is the address of the variable.
@@ -460,8 +484,10 @@ int flag_do_squangling;
if `-fSTRING' is seen as an option.
(If `-fno-STRING' is seen as an option, the opposite value is stored.) */
-static struct { char *string; int *variable; int on_value;} lang_f_options[] =
+static struct { const char *string; int *variable; int on_value;}
+lang_f_options[] =
{
+ /* C/C++ options. */
{"signed-char", &flag_signed_char, 1},
{"unsigned-char", &flag_signed_char, 0},
{"signed-bitfields", &flag_signed_bitfields, 1},
@@ -469,41 +495,42 @@ 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},
- {"labels-ok", &flag_labels_ok, 1},
- {"stats", &flag_detailed_statistics, 1},
- {"this-is-variable", &flag_this_is_variable, 1},
- {"strict-prototype", &flag_strict_prototype, 1},
- {"all-virtual", &flag_all_virtual, 1},
- {"memoize-lookups", &flag_memoize_lookups, 1},
+
+ /* C++-only options. */
+ {"access-control", &flag_access_control, 1},
+ {"check-new", &flag_check_new, 1},
+ {"conserve-space", &flag_conserve_space, 1},
+ {"const-strings", &flag_const_strings, 1},
+ {"default-inline", &flag_default_inline, 1},
+ {"dollars-in-identifiers", &dollars_in_ident, 1},
{"elide-constructors", &flag_elide_constructors, 1},
+ {"external-templates", &flag_external_templates, 1},
+ {"for-scope", &flag_new_for_scope, 2},
+ {"gnu-keywords", &flag_no_gnu_keywords, 0},
{"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},
{"honor-std", &flag_honor_std, 1},
- {"rtti", &flag_rtti, 1},
- {"xref", &flag_gnu_xref, 1},
- {"nonnull-objects", &flag_assume_nonnull_objects, 1},
+ {"huge-objects", &flag_huge_objects, 1},
{"implement-inlines", &flag_implement_inlines, 1},
- {"external-templates", &flag_external_templates, 1},
+ {"implicit-inline-templates", &flag_implicit_inline_templates, 1},
{"implicit-templates", &flag_implicit_templates, 1},
- {"huge-objects", &flag_huge_objects, 1},
- {"conserve-space", &flag_conserve_space, 1},
- {"vtable-thunks", &flag_vtable_thunks, 1},
- {"access-control", &flag_access_control, 1},
+ {"labels-ok", &flag_labels_ok, 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},
+ {"permissive", &flag_permissive, 1},
{"repo", &flag_use_repository, 1},
- {"for-scope", &flag_new_for_scope, 2},
- {"weak", &flag_weak, 1}
+ {"rtti", &flag_rtti, 1},
+ {"squangle", &flag_do_squangling, 1},
+ {"stats", &flag_detailed_statistics, 1},
+ {"strict-prototype", &flag_strict_prototype, 1},
+ {"this-is-variable", &flag_this_is_variable, 1},
+ {"vtable-gc", &flag_vtable_gc, 1},
+ {"vtable-thunks", &flag_vtable_thunks, 1},
+ {"weak", &flag_weak, 1},
+ {"xref", &flag_gnu_xref, 1}
};
/* Decode the string P as a language-specific option.
@@ -512,44 +539,24 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
int
lang_decode_option (argc, argv)
- int argc;
+ int argc
+#if !USE_CPPLIB
+ ATTRIBUTE_UNUSED
+#endif
+ ;
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_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. */
- else if (p[0] == '-' && p[1] == '+' && p[2] == 'e')
- {
- int old_write_virtuals = write_virtuals;
- if (p[3] == '1')
- write_virtuals = 1;
- else if (p[3] == '0')
- write_virtuals = -1;
- else if (p[3] == '2')
- write_virtuals = 2;
- else error ("invalid +e option");
- if (old_write_virtuals != 0
- && write_virtuals != old_write_virtuals)
- error ("conflicting +e options given");
- }
+ /* ignore */;
else if (p[0] == '-' && p[1] == 'f')
{
/* Some kind of -f option.
@@ -565,16 +572,24 @@ lang_decode_option (argc, argv)
|| !strcmp (p, "no-handle-exceptions"))
warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)");
- if (!strcmp (p, "save-memoized"))
+ if (!strcmp (p, "memoize-lookups")
+ || !strcmp (p, "no-memoize-lookups")
+ || !strcmp (p, "save-memoized")
+ || !strcmp (p, "no-save-memoized")
+ || !strcmp (p, "no-all-virtual")
+ || !strcmp (p, "no-enum-int-equiv")
+ || !strcmp (p, "nonnull-objects")
+ || !strcmp (p, "ansi-overloading"))
{
- flag_memoize_lookups = 1;
- flag_save_memoized_contexts = 1;
+ /* ignore */
found = 1;
}
- else if (!strcmp (p, "no-save-memoized"))
+ else if (!strcmp (p, "all-virtual")
+ || !strcmp (p, "enum-int-equiv")
+ || !strcmp (p, "no-nonnull-objects")
+ || !strcmp (p, "no-ansi-overloading"))
{
- flag_memoize_lookups = 0;
- flag_save_memoized_contexts = 0;
+ warning ("-f%s is no longer supported", p);
found = 1;
}
else if (! strcmp (p, "alt-external-templates"))
@@ -582,6 +597,7 @@ lang_decode_option (argc, argv)
flag_external_templates = 1;
flag_alt_external_templates = 1;
found = 1;
+ cp_deprecated ("-falt-external-templates");
}
else if (! strcmp (p, "no-alt-external-templates"))
{
@@ -605,13 +621,24 @@ lang_decode_option (argc, argv)
flag_guiding_decls = 0;
found = 1;
}
- else if (!strcmp (p, "ansi-overloading"))
- found = 1;
- else if (!strcmp (p, "no-ansi-overloading"))
- {
- error ("-fno-ansi-overloading is no longer supported");
- found = 1;
- }
+ else if (!strcmp (p, "this-is-variable"))
+ {
+ flag_this_is_variable = 1;
+ found = 1;
+ cp_deprecated ("-fthis-is-variable");
+ }
+ else if (!strcmp (p, "external-templates"))
+ {
+ flag_external_templates = 1;
+ found = 1;
+ cp_deprecated ("-fexternal-templates");
+ }
+ else if (!strcmp (p, "handle-signatures"))
+ {
+ flag_handle_signatures = 1;
+ found = 1;
+ cp_deprecated ("-fhandle-signatures");
+ }
else if (!strcmp (p, "new-abi"))
{
flag_new_abi = 1;
@@ -627,35 +654,13 @@ lang_decode_option (argc, argv)
}
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: ;
+ max_tinst_depth =
+ read_integral_parameter (p + 15, p - 2, max_tinst_depth);
}
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: ;
+ name_mangling_version =
+ read_integral_parameter (p + 22, p - 2, name_mangling_version);
}
else for (j = 0;
!found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]);
@@ -741,6 +746,10 @@ lang_decode_option (argc, argv)
/* 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, "non-template-friend"))
+ warn_nontemplate_friend = setting;
+ else if (!strcmp (p, "deprecated"))
+ warn_deprecated = setting;
else if (!strcmp (p, "comment"))
; /* cpp handles this one. */
else if (!strcmp (p, "comments"))
@@ -754,25 +763,26 @@ lang_decode_option (argc, argv)
warn_return_type = setting;
warn_unused = setting;
warn_implicit = setting;
- warn_ctor_dtor_privacy = setting;
warn_switch = setting;
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_reorder = setting;
- warn_sign_promo = setting;
/* Only warn about unknown pragmas that are not in system
headers. */
- warn_unknown_pragmas = 1;
+ warn_unknown_pragmas = 1;
+
+ /* C++-specific warnings. */
+ warn_ctor_dtor_privacy = setting;
+ warn_nonvdtor = setting;
+ warn_reorder = setting;
+ warn_nontemplate_friend = setting;
}
else return strings_processed;
}
@@ -802,36 +812,27 @@ grok_method_quals (ctype, function, quals)
{
tree fntype = TREE_TYPE (function);
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
+ int type_quals = TYPE_UNQUALIFIED;
+ int dup_quals = TYPE_UNQUALIFIED;
do
{
- extern tree ridpointers[];
-
- if (TREE_VALUE (quals) == ridpointers[(int)RID_CONST])
- {
- if (TYPE_READONLY (ctype))
- error ("duplicate `%s' %s",
- IDENTIFIER_POINTER (TREE_VALUE (quals)),
- (TREE_CODE (function) == FUNCTION_DECL
- ? "for member function" : "in type declaration"));
- ctype = build_type_variant (ctype, 1, TYPE_VOLATILE (ctype));
- build_pointer_type (ctype);
- }
- else if (TREE_VALUE (quals) == ridpointers[(int)RID_VOLATILE])
- {
- if (TYPE_VOLATILE (ctype))
- error ("duplicate `%s' %s",
- IDENTIFIER_POINTER (TREE_VALUE (quals)),
- (TREE_CODE (function) == FUNCTION_DECL
- ? "for member function" : "in type declaration"));
- ctype = build_type_variant (ctype, TYPE_READONLY (ctype), 1);
- build_pointer_type (ctype);
- }
+ int tq = cp_type_qual_from_rid (TREE_VALUE (quals));
+
+ if (type_quals & tq)
+ dup_quals |= tq;
else
- my_friendly_abort (20);
+ type_quals |= tq;
quals = TREE_CHAIN (quals);
- }
+ }
while (quals);
+
+ if (dup_quals != TYPE_UNQUALIFIED)
+ cp_error ("duplicate type qualifiers in %s declaration",
+ TREE_CODE (function) == FUNCTION_DECL
+ ? "member function" : "type");
+
+ ctype = cp_build_qualified_type (ctype, type_quals);
fntype = build_cplus_method_type (ctype, TREE_TYPE (fntype),
(TREE_CODE (fntype) == METHOD_TYPE
? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
@@ -878,121 +879,34 @@ warn_if_unknown_interface (decl)
/* A subroutine of the parser, to handle a component list. */
-tree
-grok_x_components (specs, components)
- tree specs, components;
+void
+grok_x_components (specs)
+ tree specs;
{
- register tree t, x, tcode;
-
- /* We just got some friends. They have been recorded elsewhere. */
- if (components == void_type_node)
- return NULL_TREE;
-
- if (components == NULL_TREE)
- {
- t = groktypename (build_decl_list (specs, NULL_TREE));
-
- if (t == NULL_TREE)
- {
- error ("error in component specification");
- return NULL_TREE;
- }
-
- switch (TREE_CODE (t))
- {
- case VAR_DECL:
- /* Static anonymous unions come out as VAR_DECLs. */
- if (ANON_UNION_TYPE_P (TREE_TYPE (t)))
- return t;
-
- /* We return SPECS here, because in the parser it was ending
- up with not doing anything to $$, which is what SPECS
- represents. */
- return specs;
- break;
-
- case RECORD_TYPE:
- /* This code may be needed for UNION_TYPEs as
- well. */
- tcode = record_type_node;
- if (CLASSTYPE_DECLARED_CLASS (t))
- tcode = class_type_node;
- else if (IS_SIGNATURE (t))
- tcode = signature_type_node;
-
- 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;
+ struct pending_inline **p;
+ tree t;
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- if (TREE_CODE (t) == UNION_TYPE)
- tcode = union_type_node;
- else
- tcode = enum_type_node;
+ specs = strip_attrs (specs);
- t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
- 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 */
- 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);
- }
- if (TYPE_METHODS (t))
- error ("an anonymous union cannot have function members");
+ check_tag_decl (specs);
+ t = groktypename (build_decl_list (specs, NULL_TREE));
- 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 (NULL_TREE);
- else
- x = NULL_TREE;
- return x;
- break;
+ /* The only case where we need to do anything additional here is an
+ anonymous union field, e.g.: `struct S { union { int i; }; };'. */
+ if (t == NULL_TREE || !ANON_UNION_TYPE_P (t))
+ return;
- default:
- if (t != void_type_node)
- error ("empty component declaration");
- return NULL_TREE;
- }
- }
- else
- /* 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);
+ fixup_anonymous_union (t);
+ finish_member_declaration (build_lang_field_decl (FIELD_DECL,
+ NULL_TREE,
+ t));
+
+ /* Ignore any inline function definitions in the anonymous union
+ since an anonymous union may not have function members. */
+ p = &pending_inlines;
+ for (; *p; *p = (*p)->next)
+ if (DECL_CONTEXT ((*p)->fndecl) != t)
+ break;
}
/* Constructors for types with virtual baseclasses need an "in-charge" flag
@@ -1067,8 +981,8 @@ maybe_retrofit_in_chrg (fn)
QUALS are the qualifiers for the this pointer. */
void
-grokclassfn (ctype, cname, function, flags, quals)
- tree ctype, cname, function;
+grokclassfn (ctype, function, flags, quals)
+ tree ctype, function;
enum overload_flags flags;
tree quals;
{
@@ -1132,16 +1046,7 @@ grokclassfn (ctype, cname, function, flags, quals)
TYPE_HAS_DESTRUCTOR (ctype) = 1;
}
else
- {
- if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
- /* Only true for static member functions. */
- arg_types = hash_tree_chain (build_pointer_type (qualtype),
- arg_types);
-
- DECL_ASSEMBLER_NAME (function)
- = build_decl_overload (fn_name, arg_types,
- 1 + DECL_CONSTRUCTOR_P (function));
- }
+ set_mangled_name_for_decl (function);
}
/* Work on the expr used by alignof (this is only called by the parser). */
@@ -1157,7 +1062,7 @@ grok_alignof (expr)
return build_min (ALIGNOF_EXPR, sizetype, expr);
if (TREE_CODE (expr) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
+ && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
error ("`__alignof__' applied to a bit-field");
if (TREE_CODE (expr) == INDIRECT_REF)
@@ -1223,7 +1128,9 @@ grok_array_decl (array_expr, index_exp)
return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
array_expr, index_exp, NULL_TREE);
- /* Otherwise, create an ARRAY_REF for a pointer or array type. */
+ /* Otherwise, create an ARRAY_REF for a pointer or array type. It
+ is a little-known fact that, if `a' is an array and `i' is an
+ int, you can write `i[a]', which means the same thing as `a[i]'. */
if (TREE_CODE (type) == ARRAY_TYPE)
p1 = array_expr;
@@ -1302,7 +1209,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
if (doing_vec == 2)
{
- maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
+ maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node);
pedwarn ("anachronistic use of array size in vector delete");
}
@@ -1317,6 +1224,10 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
return error_mark_node;
}
+ /* Deleting ptr to void is undefined behaviour [expr.delete/3]. */
+ if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
+ cp_warning ("`%T' is not a pointer-to-object type", type);
+
/* 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
@@ -1329,7 +1240,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
if (doing_vec)
return build_vec_delete (t, maxindex, integer_one_node,
- integer_two_node, use_global_delete);
+ integer_zero_node, use_global_delete);
else
{
if (IS_AGGR_TYPE (TREE_TYPE (type))
@@ -1392,7 +1303,7 @@ check_member_template (tmpl)
/* Return true iff TYPE is a valid Java parameter or return type. */
-int
+static int
acceptable_java_type (type)
tree type;
{
@@ -1403,8 +1314,22 @@ acceptable_java_type (type)
type = TREE_TYPE (type);
if (TREE_CODE (type) == RECORD_TYPE)
{
- complete_type (type);
- return TYPE_FOR_JAVA (type);
+ tree args; int i;
+ if (! TYPE_FOR_JAVA (type))
+ return 0;
+ if (! CLASSTYPE_TEMPLATE_INFO (type))
+ return 1;
+ args = CLASSTYPE_TI_ARGS (type);
+ i = TREE_VEC_LENGTH (args);
+ while (--i >= 0)
+ {
+ type = TREE_VEC_ELT (args, i);
+ if (TREE_CODE (type) == POINTER_TYPE)
+ type = TREE_TYPE (type);
+ if (! TYPE_FOR_JAVA (type))
+ return 0;
+ }
+ return 1;
}
}
return 0;
@@ -1415,8 +1340,8 @@ acceptable_java_type (type)
Otherwise, print appropriate error messages, and return 0. */
int
-check_java_method (ctype, method)
- tree ctype, method;
+check_java_method (method)
+ tree method;
{
int jerr = 0;
tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (method));
@@ -1453,8 +1378,21 @@ check_classfn (ctype, function)
tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
tree *methods = 0;
tree *end = 0;
- tree templates = NULL_TREE;
-
+
+ if (DECL_USE_TEMPLATE (function)
+ && is_member_template (DECL_TI_TEMPLATE (function)))
+ /* Since this is a specialization of a member template,
+ we're not going to find the declaration in the class.
+ For example, in:
+
+ struct S { template <typename T> void f(T); };
+ template <> void S::f(int);
+
+ we're not going to find `S::f(int)', but there's no
+ reason we should, either. We let our callers know we didn't
+ find the method, but we don't complain. */
+ return NULL_TREE;
+
if (method_vec != 0)
{
methods = &TREE_VEC_ELT (method_vec, 0);
@@ -1468,7 +1406,7 @@ check_classfn (ctype, function)
&& DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
goto got_it;
- while (++methods != end)
+ while (++methods != end && *methods)
{
fndecl = *methods;
if (fn_name == DECL_NAME (OVL_CURRENT (*methods)))
@@ -1478,14 +1416,19 @@ check_classfn (ctype, function)
fndecls = OVL_NEXT (fndecls))
{
fndecl = OVL_CURRENT (fndecls);
- /* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL is
+ /* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL, or
+ for a for member function of a template class, 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))
+ 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.
+ (It's not legal to declare arguments for a
+ destructor, but some people try.) */
+ if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))
+ && (DECL_ASSEMBLER_NAME (function)
+ != DECL_NAME (function))
+ && (DECL_ASSEMBLER_NAME (fndecl)
+ != DECL_NAME (fndecl))
&& (DECL_ASSEMBLER_NAME (function)
== DECL_ASSEMBLER_NAME (fndecl)))
return fndecl;
@@ -1505,48 +1448,23 @@ check_classfn (ctype, function)
&& 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 (same_type_p (TREE_TYPE (TREE_TYPE (function)),
+ TREE_TYPE (TREE_TYPE (fndecl)))
+ && compparms (p1, p2)
&& (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);
}
}
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)
+ if (methods != end && *methods)
{
tree fndecl = *methods;
cp_error ("prototype for `%#D' does not match any in class `%T'",
@@ -1559,16 +1477,86 @@ check_classfn (ctype, function)
else
{
methods = 0;
- cp_error ("no `%#D' member function declared in class `%T'",
- function, ctype);
+ if (TYPE_SIZE (ctype) == 0)
+ incomplete_type_error (function, ctype);
+ else
+ cp_error ("no `%#D' member function declared in class `%T'",
+ function, ctype);
}
/* If we did not find the method in the class, add it to avoid
- spurious errors. */
- add_method (ctype, methods, function);
+ spurious errors (unless the CTYPE is not yet defined, in which
+ case we'll only confuse ourselves when the function is declared
+ properly within the class. */
+ if (TYPE_SIZE (ctype))
+ add_method (ctype, methods, function);
return NULL_TREE;
}
+/* We have just processed the DECL, which is a static data member.
+ Its initializer, if present, is INIT. The ASMSPEC_TREE, if
+ present, is the assembly-language name for the data member.
+ NEED_POP and FLAGS are as for cp_finish_decl. */
+
+void
+finish_static_data_member_decl (decl, init, asmspec_tree, need_pop, flags)
+ tree decl;
+ tree init;
+ tree asmspec_tree;
+ int need_pop;
+ int flags;
+{
+ char* asmspec = 0;
+
+ if (asmspec_tree)
+ asmspec = TREE_STRING_POINTER (asmspec_tree);
+
+ my_friendly_assert (TREE_PUBLIC (decl), 0);
+
+ /* We cannot call pushdecl here, because that would fill in the
+ decl of our TREE_CHAIN. Instead, we modify cp_finish_decl to do
+ the right thing, namely, to put this decl out straight away. */
+ /* current_class_type can be NULL_TREE in case of error. */
+ if (!asmspec && current_class_type)
+ {
+ DECL_INITIAL (decl) = error_mark_node;
+ DECL_ASSEMBLER_NAME (decl)
+ = build_static_name (current_class_type, DECL_NAME (decl));
+ }
+ if (! processing_template_decl)
+ {
+ if (!pending_statics)
+ VARRAY_TREE_INIT (pending_statics, 32, "pending_statics");
+
+ if (pending_statics_used == pending_statics->num_elements)
+ VARRAY_GROW (pending_statics,
+ 2 * pending_statics->num_elements);
+ VARRAY_TREE (pending_statics, pending_statics_used) = decl;
+ ++pending_statics_used;
+ }
+
+ /* Static consts need not be initialized in the class definition. */
+ if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ {
+ 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 (CP_TYPE_CONST_P (TREE_TYPE (decl)) && init == 0)
+ TREE_USED (decl) = 1;
+ DECL_INITIAL (decl) = init;
+ DECL_IN_AGGR_P (decl) = 1;
+ DECL_CONTEXT (decl) = current_class_type;
+ DECL_CLASS_CONTEXT (decl) = current_class_type;
+
+ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags);
+}
+
/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
of a structure component, returning a FIELD_DECL node.
QUALS is a list of type qualifiers for this decl (such as for declaring
@@ -1618,7 +1606,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0))))
;
else if (TREE_COMPLEXITY (declarator) == current_class_depth)
- pop_nested_class (1);
+ pop_nested_class ();
return do_class_using_decl (declarator);
}
@@ -1628,9 +1616,10 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
&& TREE_CHAIN (init) == NULL_TREE)
init = NULL_TREE;
- value = grokdeclarator (declarator, declspecs, FIELD, init != 0, NULL_TREE);
- if (! value)
- return value; /* friend or constructor went bad. */
+ value = grokdeclarator (declarator, declspecs, FIELD, init != 0, attrlist);
+ if (! value || value == error_mark_node)
+ /* friend or constructor went bad. */
+ return value;
/* Pass friendly classes back. */
if (TREE_CODE (value) == VOID_TYPE)
@@ -1648,15 +1637,14 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
DECL_CLASS_CONTEXT (value) = current_class_type;
- CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
/* 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));
+ if (!uses_template_parms (value))
+ DECL_ASSEMBLER_NAME (value) =
+ get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
- pushdecl_class_level (value);
return value;
}
@@ -1669,8 +1657,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
if (DECL_IN_AGGR_P (value))
{
- cp_error ("`%D' is already defined in the class %T", value,
- DECL_CONTEXT (value));
+ cp_error ("`%D' is already defined in `%T'", value,
+ DECL_CONTEXT (value));
return void_type_node;
}
@@ -1748,44 +1736,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
if (TREE_CODE (value) == VAR_DECL)
{
- my_friendly_assert (TREE_PUBLIC (value), 0);
-
- /* We cannot call pushdecl here, because that would
- fill in the value of our TREE_CHAIN. Instead, we
- modify cp_finish_decl to do the right thing, namely, to
- put this decl out straight away. */
- /* current_class_type can be NULL_TREE in case of error. */
- if (asmspec == 0 && current_class_type)
- {
- TREE_PUBLIC (value) = 1;
- DECL_INITIAL (value) = error_mark_node;
- DECL_ASSEMBLER_NAME (value)
- = build_static_name (current_class_type, DECL_NAME (value));
- }
- if (! processing_template_decl)
- pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics);
-
- /* Static consts need not be initialized in the class definition. */
- if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (value)))
- {
- static int explanation = 0;
-
- error ("initializer invalid for static member with constructor");
- if (explanation++ == 0)
- error ("(you really want to initialize it separately)");
- init = 0;
- }
- /* Force the compiler to know when an uninitialized static
- const member is being used. */
- if (TYPE_READONLY (value) && init == 0)
- TREE_USED (value) = 1;
- 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);
+ finish_static_data_member_decl (value, init, asmspec_tree,
+ /*need_pop=*/1, flags);
return value;
}
if (TREE_CODE (value) == FIELD_DECL)
@@ -1855,6 +1807,17 @@ grokbitfield (declarator, declspecs, width)
return NULL_TREE;
}
+ /* Usually, finish_struct_1 catches bitifields with invalid types.
+ But, in the case of bitfields with function type, we confuse
+ ourselves into thinking they are member functions, so we must
+ check here. */
+ if (TREE_CODE (value) == FUNCTION_DECL)
+ {
+ cp_error ("cannot declare bitfield `%D' with funcion type",
+ DECL_NAME (value));
+ return NULL_TREE;
+ }
+
if (IS_SIGNATURE (current_class_type))
{
error ("field declaration not allowed in signature");
@@ -1881,7 +1844,7 @@ grokbitfield (declarator, declspecs, width)
{
constant_expression_warning (width);
DECL_INITIAL (value) = width;
- DECL_BIT_FIELD (value) = 1;
+ SET_DECL_C_BIT_FIELD (value);
}
DECL_IN_AGGR_P (value) = 1;
@@ -1934,7 +1897,7 @@ grokoptypename (declspecs, declarator)
int
copy_assignment_arg_p (parmtype, virtualp)
tree parmtype;
- int virtualp;
+ int virtualp ATTRIBUTE_UNUSED;
{
if (current_class_type == NULL_TREE)
return 0;
@@ -2093,28 +2056,14 @@ mark_inline_for_output (decl)
return;
my_friendly_assert (TREE_PERMANENT (decl), 363);
DECL_SAVED_INLINE (decl) = 1;
-#if 0
- if (DECL_PENDING_INLINE_INFO (decl) != 0
- && ! DECL_PENDING_INLINE_INFO (decl)->deja_vu)
- {
- struct pending_inline *t = pending_inlines;
- my_friendly_assert (DECL_SAVED_INSNS (decl) == 0, 198);
- while (t)
- {
- if (t == DECL_PENDING_INLINE_INFO (decl))
- break;
- t = t->next;
- }
- if (t == 0)
- {
- t = DECL_PENDING_INLINE_INFO (decl);
- t->next = pending_inlines;
- pending_inlines = t;
- }
- DECL_PENDING_INLINE_INFO (decl) = 0;
- }
-#endif
- saved_inlines = perm_tree_cons (NULL_TREE, decl, saved_inlines);
+ if (!saved_inlines)
+ VARRAY_TREE_INIT (saved_inlines, 32, "saved_inlines");
+
+ if (saved_inlines_used == saved_inlines->num_elements)
+ VARRAY_GROW (saved_inlines,
+ 2 * saved_inlines->num_elements);
+ VARRAY_TREE (saved_inlines, saved_inlines_used) = decl;
+ ++saved_inlines_used;
}
void
@@ -2198,7 +2147,7 @@ get_temp_regvar (type, init)
returns a VAR_DECL whose size is the same as the size of the
ANON_DECL, if one is available. */
-tree
+static tree
build_anon_union_vars (anon_decl, elems, static_p, external_p)
tree anon_decl;
tree* elems;
@@ -2214,8 +2163,15 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p)
field = TREE_CHAIN (field))
{
tree decl;
- if (TREE_CODE (field) != FIELD_DECL)
+
+ if (DECL_ARTIFICIAL (field))
continue;
+ if (TREE_CODE (field) != FIELD_DECL)
+ {
+ cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members",
+ field);
+ continue;
+ }
if (TREE_PRIVATE (field))
cp_pedwarn_at ("private member `%#D' in anonymous union", field);
@@ -2229,6 +2185,8 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p)
if (!decl)
continue;
}
+ else if (DECL_NAME (field) == NULL_TREE)
+ continue;
else
{
decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
@@ -2297,18 +2255,16 @@ finish_anon_union (anon_union_decl)
main_decl = build_anon_union_vars (anon_union_decl, &elems,
static_p, external_p);
+ if (main_decl == NULL_TREE)
+ {
+ warning ("anonymous union with no members");
+ return;
+ }
+
if (static_p)
{
- if (main_decl)
- {
- make_decl_rtl (main_decl, 0, toplevel_bindings_p ());
- DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
- }
- else
- {
- warning ("anonymous union with no members");
- return;
- }
+ make_decl_rtl (main_decl, 0, toplevel_bindings_p ());
+ DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
}
/* The following call assumes that there are never any cleanups
@@ -2326,7 +2282,7 @@ finish_anon_union (anon_union_decl)
void
finish_builtin_type (type, name, fields, len, align_type)
tree type;
- char *name;
+ const char *name;
tree fields[];
int len;
tree align_type;
@@ -2365,15 +2321,14 @@ coerce_new_type (type)
if (TREE_CODE (type) == METHOD_TYPE)
type = build_function_type (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type)));
- if (TREE_TYPE (type) != ptr_type_node)
+ if (! same_type_p (TREE_TYPE (type), ptr_type_node))
e1 = 1, error ("`operator new' must return type `void *'");
/* Technically the type must be `size_t', but we may not know
what that is. */
if (TYPE_ARG_TYPES (type) == NULL_TREE)
e1 = 1, error ("`operator new' takes type `size_t' parameter");
- else if (TREE_CODE (TREE_VALUE (TYPE_ARG_TYPES (type))) != INTEGER_TYPE
- || TYPE_PRECISION (TREE_VALUE (TYPE_ARG_TYPES (type))) != TYPE_PRECISION (sizetype))
+ else if (! same_type_p (TREE_VALUE (TYPE_ARG_TYPES (type)), sizetype))
e2 = 1, error ("`operator new' takes type `size_t' as first parameter");
if (e2)
type = build_function_type (ptr_type_node, tree_cons (NULL_TREE, sizetype, TREE_CHAIN (TYPE_ARG_TYPES (type))));
@@ -2402,7 +2357,7 @@ coerce_delete_type (type)
e1 = 1, error ("`operator delete' must return type `void'");
if (arg_types == NULL_TREE
- || TREE_VALUE (arg_types) != ptr_type_node)
+ || ! same_type_p (TREE_VALUE (arg_types), ptr_type_node))
e2 = 1, error ("`operator delete' takes type `void *' as first parameter");
#if 0
@@ -2413,8 +2368,7 @@ coerce_delete_type (type)
/* Again, technically this argument must be `size_t', but again
we may not know what that is. */
tree t2 = TREE_VALUE (TREE_CHAIN (arg_types));
- if (TREE_CODE (t2) != INTEGER_TYPE
- || TYPE_PRECISION (t2) != TYPE_PRECISION (sizetype))
+ if (! same_type_p (t2, sizetype))
e3 = 1, error ("second argument to `operator delete' must be of type `size_t'");
else if (TREE_CHAIN (TREE_CHAIN (arg_types)) != void_list_node)
{
@@ -2456,21 +2410,19 @@ mark_vtable_entries (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 = (flag_vtable_thunks ? TREE_VALUE (entries)
- : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
- tree fn = TREE_OPERAND (fnaddr, 0);
+ tree fnaddr;
+ tree fn;
+
+ fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries)
+ : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
+
+ if (TREE_CODE (fnaddr) == NOP_EXPR)
+ /* RTTI offset. */
+ continue;
+
+ fn = TREE_OPERAND (fnaddr, 0);
TREE_ADDRESSABLE (fn) = 1;
if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn))
{
@@ -2496,8 +2448,30 @@ comdat_linkage (decl)
{
if (flag_weak)
make_decl_one_only (decl);
- else
+ else if (TREE_CODE (decl) == FUNCTION_DECL || DECL_VIRTUAL_P (decl))
+ /* We can just emit functions and vtables statically; it doesn't really
+ matter if we have multiple copies. */
TREE_PUBLIC (decl) = 0;
+ else
+ {
+ /* Static data member template instantiations, however, cannot
+ have multiple copies. */
+ if (DECL_INITIAL (decl) == 0
+ || 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
+ {
+ /* We can't do anything useful; leave vars for explicit
+ instantiation. */
+ DECL_EXTERNAL (decl) = 1;
+ DECL_NOT_REALLY_EXTERN (decl) = 0;
+ }
+ }
if (DECL_LANG_SPECIFIC (decl))
DECL_COMDAT (decl) = 1;
@@ -2517,14 +2491,14 @@ maybe_make_one_only (decl)
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. */
+ we can get away with not emitting them if they aren't used. We need
+ to for variables so that cp_finish_decl will update their linkage,
+ 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);
+ make_decl_one_only (decl);
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_LANG_SPECIFIC (decl))
+ DECL_COMDAT (decl) = 1;
}
/* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
@@ -2541,12 +2515,10 @@ import_export_vtable (decl, type, final)
if (DECL_INTERFACE_KNOWN (decl))
return;
- /* +e0 or +e1 */
- if (write_virtuals < 2 && write_virtuals != 0)
+ if (TYPE_FOR_JAVA (type))
{
TREE_PUBLIC (decl) = 1;
- if (write_virtuals < 0)
- DECL_EXTERNAL (decl) = 1;
+ DECL_EXTERNAL (decl) = 1;
DECL_INTERFACE_KNOWN (decl) = 1;
}
else if (CLASSTYPE_INTERFACE_KNOWN (type))
@@ -2554,11 +2526,6 @@ 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
{
@@ -2567,7 +2534,6 @@ import_export_vtable (decl, type, final)
int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type);
-#ifndef MULTIPLE_SYMBOL_SPACES
if (! found && ! final)
{
tree method;
@@ -2581,7 +2547,6 @@ import_export_vtable (decl, type, final)
break;
}
}
-#endif
if (final || ! found)
{
@@ -2609,10 +2574,20 @@ import_export_class (ctype)
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
return;
+ /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma interface,
+ we will have CLASSTYPE_INTERFACE_ONLY set but not
+ CLASSTYPE_INTERFACE_KNOWN. In that case, we don't want to use this
+ heuristic because someone will supply a #pragma implementation
+ elsewhere, and deducing it here would produce a conflict. */
+ if (CLASSTYPE_INTERFACE_ONLY (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;
+ else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
+ import_export = 1;
#endif
/* If we got -fno-implicit-templates, we import template classes that
@@ -2622,7 +2597,6 @@ import_export_class (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
@@ -2642,6 +2616,10 @@ import_export_class (ctype)
}
}
}
+
+#ifdef MULTIPLE_SYMBOL_SPACES
+ if (import_export == -1)
+ import_export = 0;
#endif
if (import_export)
@@ -2652,18 +2630,45 @@ import_export_class (ctype)
}
}
+/* We need to describe to the assembler the relationship between
+ a vtable and the vtable of the parent class. */
+
+static void
+output_vtable_inherit (vars)
+ tree vars;
+{
+ tree parent;
+ rtx op[2];
+
+ op[0] = XEXP (DECL_RTL (vars), 0); /* strip the mem ref */
+
+ parent = binfo_for_vtable (vars);
+
+ if (parent == TYPE_BINFO (DECL_CONTEXT (vars)))
+ op[1] = const0_rtx;
+ else if (parent)
+ {
+ parent = TYPE_BINFO_VTABLE (BINFO_TYPE (parent));
+ op[1] = XEXP (DECL_RTL (parent), 0); /* strip the mem ref */
+ }
+ else
+ my_friendly_abort (980826);
+
+ output_asm_insn (".vtable_inherit %c0, %c1", op);
+}
+
static int
-finish_vtable_vardecl (prev, vars)
- tree prev, vars;
+finish_vtable_vardecl (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
+ tree vars = *t;
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) && ! DECL_WEAK (vars) && ! DECL_ONE_ONLY (vars))
- || CLASSTYPE_EXPLICIT_INSTANTIATION (DECL_CONTEXT (vars))
+ if (! DECL_EXTERNAL (vars)
+ && (DECL_INTERFACE_KNOWN (vars)
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars))
|| (hack_decl_function_context (vars) && TREE_USED (vars)))
&& ! TREE_ASM_WRITTEN (vars))
@@ -2699,101 +2704,46 @@ finish_vtable_vardecl (prev, vars)
DECL_IGNORED_P (vars) = 1;
}
+ /* Always make vtables weak. */
+ if (flag_weak)
+ comdat_linkage (vars);
+
rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
+
+ if (flag_vtable_gc)
+ output_vtable_inherit (vars);
+
return 1;
}
else if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars)))
/* We don't know what to do with this one yet. */
return 0;
- /* We know that PREV must be non-zero here. */
- TREE_CHAIN (prev) = TREE_CHAIN (vars);
+ *t = TREE_CHAIN (vars);
return 0;
}
static int
-prune_vtable_vardecl (prev, vars)
- tree prev, vars;
+prune_vtable_vardecl (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
- /* We know that PREV must be non-zero here. */
- TREE_CHAIN (prev) = TREE_CHAIN (vars);
+ *t = TREE_CHAIN (*t);
return 1;
}
-int
-walk_vtables (typedecl_fn, 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))
- {
- register tree type = TREE_TYPE (vars);
-
- if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars))
- {
- if (vardecl_fn)
- flag |= (*vardecl_fn) (prev, vars);
-
- if (prev && TREE_CHAIN (prev) != vars)
- continue;
- }
- else if (TREE_CODE (vars) == TYPE_DECL
- && type != error_mark_node
- && TYPE_LANG_SPECIFIC (type)
- && CLASSTYPE_VSIZE (type))
- {
- if (typedecl_fn) (*typedecl_fn) (prev, vars);
- }
-
- prev = vars;
- }
-
- return flag;
-}
-
-static void
-finish_sigtable_vardecl (prev, vars)
- tree prev, vars;
+static int
+finish_sigtable_vardecl (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
/* We don't need to mark sigtable entries as addressable here as is done
for vtables. Since sigtables, unlike vtables, are always written out,
that was already done in build_signature_table_constructor. */
- rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
-
- /* We know that PREV must be non-zero here. */
- TREE_CHAIN (prev) = TREE_CHAIN (vars);
-}
-
-void
-walk_sigtables (typedecl_fn, vardecl_fn)
- register void (*typedecl_fn) PROTO((tree, tree));
- register void (*vardecl_fn) PROTO((tree, tree));
-{
- tree prev, vars;
-
- for (prev = 0, vars = getdecls (); vars; vars = TREE_CHAIN (vars))
- {
- register tree type = TREE_TYPE (vars);
-
- if (TREE_CODE (vars) == TYPE_DECL
- && type != error_mark_node
- && IS_SIGNATURE (type))
- {
- if (typedecl_fn) (*typedecl_fn) (prev, vars);
- }
- else if (TREE_CODE (vars) == VAR_DECL
- && TREE_TYPE (vars) != error_mark_node
- && IS_SIGNATURE (TREE_TYPE (vars)))
- {
- if (vardecl_fn) (*vardecl_fn) (prev, vars);
- }
- else
- prev = vars;
- }
+ rest_of_decl_compilation (*t, NULL_PTR, 1, 1);
+ *t = TREE_CHAIN (*t);
+ return 1;
}
/* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an
@@ -2806,20 +2756,21 @@ import_export_decl (decl)
if (DECL_INTERFACE_KNOWN (decl))
return;
- if (DECL_TEMPLATE_INSTANTIATION (decl))
+ if (DECL_TEMPLATE_INSTANTIATION (decl)
+ || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
{
DECL_NOT_REALLY_EXTERN (decl) = 1;
- if (DECL_IMPLICIT_INSTANTIATION (decl)
- && (flag_implicit_templates || DECL_THIS_INLINE (decl)))
+ if ((DECL_IMPLICIT_INSTANTIATION (decl)
+ || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
+ && (flag_implicit_templates
+ || (flag_implicit_inline_templates && DECL_THIS_INLINE (decl))))
{
if (!TREE_PUBLIC (decl))
/* Templates are allowed to have internal linkage. See
[basic.link]. */
;
- else if (TREE_CODE (decl) == FUNCTION_DECL)
- comdat_linkage (decl);
else
- DECL_COMDAT (decl) = 1;
+ comdat_linkage (decl);
}
else
DECL_NOT_REALLY_EXTERN (decl) = 0;
@@ -2833,13 +2784,19 @@ import_export_decl (decl)
{
DECL_NOT_REALLY_EXTERN (decl)
= ! (CLASSTYPE_INTERFACE_ONLY (ctype)
- || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
+ || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines
+ && !DECL_VINDEX (decl)));
+
+ /* Always make artificials weak. */
+ if (DECL_ARTIFICIAL (decl) && flag_weak)
+ comdat_linkage (decl);
+ else
+ maybe_make_one_only (decl);
}
else
comdat_linkage (decl);
}
- /* tinfo function */
- else if (DECL_ARTIFICIAL (decl) && DECL_MUTABLE_P (decl))
+ else if (DECL_TINFO_FN_P (decl))
{
tree ctype = TREE_TYPE (DECL_NAME (decl));
@@ -2853,18 +2810,19 @@ import_export_decl (decl)
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))
+ && same_type_p (ctype, TYPE_MAIN_VARIANT (ctype)))
{
DECL_NOT_REALLY_EXTERN (decl)
= ! (CLASSTYPE_INTERFACE_ONLY (ctype)
- || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
+ || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines
+ && !DECL_VINDEX (decl)));
- /* For WIN32 we also want to put explicit instantiations in
- linkonce sections. */
- if (CLASSTYPE_EXPLICIT_INSTANTIATION (ctype))
- maybe_make_one_only (decl);
+ /* Always make artificials weak. */
+ if (flag_weak)
+ comdat_linkage (decl);
}
- else if (TYPE_BUILT_IN (ctype) && ctype == TYPE_MAIN_VARIANT (ctype))
+ else if (TYPE_BUILT_IN (ctype)
+ && same_type_p (ctype, TYPE_MAIN_VARIANT (ctype)))
DECL_NOT_REALLY_EXTERN (decl) = 0;
else
comdat_linkage (decl);
@@ -2896,8 +2854,6 @@ build_cleanup (decl)
}
extern int parse_time, varconst_time;
-extern tree pending_templates;
-extern tree maybe_templates;
static tree
get_sentry (base)
@@ -2929,14 +2885,30 @@ get_sentry (base)
or destructors. Subroutine of do_[cd]tors. */
static void
-start_objects (method_type)
- int method_type;
+start_objects (method_type, initp)
+ int method_type, initp;
{
tree fnname;
+ char type[10];
/* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
- fnname = get_file_function_name (method_type);
+ if (initp != DEFAULT_INIT_PRIORITY)
+ {
+ char joiner;
+
+#ifdef JOINER
+ joiner = JOINER;
+#else
+ joiner = '_';
+#endif
+
+ sprintf (type, "%c%c%.5u", method_type, joiner, initp);
+ }
+ else
+ sprintf (type, "%c", method_type);
+
+ fnname = get_file_function_name_long (type);
start_function (void_list_node,
make_call_declarator (fnname, void_list_node, NULL_TREE,
@@ -2954,29 +2926,23 @@ start_objects (method_type)
clear_last_expr ();
push_momentary ();
expand_start_bindings (0);
+
+ /* We cannot allow these functions to be elided, even if they do not
+ have external linkage. And, there's no point in deferring
+ copmilation of thes functions; they're all going to have to be
+ out anyhow. */
+ current_function_cannot_inline
+ = "static constructors and destructors cannot be inlined";
}
/* Finish the process of running a particular set of global constructors
or destructors. Subroutine of do_[cd]tors. */
static void
-finish_objects (method_type)
- int method_type;
+finish_objects (method_type, initp)
+ int method_type, initp;
{
- 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);
+ char *fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
/* Finish up. */
expand_end_bindings (getdecls (), 1, 0);
@@ -2984,422 +2950,790 @@ finish_objects (method_type)
pop_momentary ();
finish_function (lineno, 0, 0);
- if (method_type == 'I')
- assemble_constructor (fnname);
+ if (initp == DEFAULT_INIT_PRIORITY)
+ {
+ if (method_type == 'I')
+ assemble_constructor (fnname);
+ else
+ assemble_destructor (fnname);
+ }
+
+#if defined (ASM_OUTPUT_SECTION_NAME) && defined (ASM_OUTPUT_CONSTRUCTOR)
+ /* If we're using init priority we can't use assemble_*tor, but on ELF
+ targets we can stick the references into named sections for GNU ld
+ to collect. */
else
- assemble_destructor (fnname);
+ {
+ char buf[15];
+ sprintf (buf, ".%ctors.%.5u", method_type == 'I' ? 'c' : 'd',
+ /* invert the numbering so the linker puts us in the proper
+ order; constructors are run from right to left, and the
+ linker sorts in increasing order. */
+ MAX_INIT_PRIORITY - initp);
+ named_section (NULL_TREE, buf, 0);
+ assemble_integer (gen_rtx_SYMBOL_REF (Pmode, fnname),
+ POINTER_SIZE / BITS_PER_UNIT, 1);
+ }
+#endif
}
-/* Generate a function to run a set of global destructors. Subroutine of
- finish_file. */
+/* The names of the parameters to the function created to handle
+ initializations and destructions for objects with static storage
+ duration. */
+#define INITIALIZE_P_IDENTIFIER "__initialize_p"
+#define PRIORITY_IDENTIFIER "__priority"
+
+/* The name of the function we create to handle initializations and
+ destructions for objects with static storage duration. */
+#define SSDF_IDENTIFIER "__static_initialization_and_destruction"
+
+/* The declaration for the __INITIALIZE_P argument. */
+static tree initialize_p_decl;
+
+/* The declaration for the __PRIORITY argument. */
+static tree priority_decl;
+
+/* The declaration for the static storage duration function. */
+static tree ssdf_decl;
+
+/* All the static storage duration functions created in this
+ translation unit. */
+static varray_type ssdf_decls;
+static size_t ssdf_decls_used;
+
+/* A map from priority levels to information about that priority
+ level. There may be many such levels, so efficient lookup is
+ important. */
+static splay_tree priority_info_map;
+
+/* Begins the generation of the function that will handle all
+ initialization and destruction of objects with static storage
+ duration. The function generated takes two parameters of type
+ `int': __INITIALIZE_P and __PRIORITY. If __INITIALIZE_P is
+ non-zero, it performs initializations. Otherwise, it performs
+ destructions. It only performs those initializations or
+ destructions with the indicated __PRIORITY. The generated function
+ returns no value.
+
+ It is assumed that this function will only be called once per
+ translation unit. */
static void
-do_dtors ()
+start_static_storage_duration_function ()
{
- tree vars = static_aggregates;
+ static unsigned ssdf_number;
+
+ tree parm_types;
+ tree type;
+ char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
- for (; vars; vars = TREE_CHAIN (vars))
+ /* Create the identifier for this function. It will be of the form
+ SSDF_IDENTIFIER_<number>. */
+ sprintf (id, "%s_%u", SSDF_IDENTIFIER, ssdf_number++);
+ if (ssdf_number == 0)
{
- tree decl = TREE_VALUE (vars);
- tree type = TREE_TYPE (decl);
- tree temp;
+ /* Overflow occurred. That means there are at least 4 billion
+ initialization functions. */
+ sorry ("too many initialization functions required");
+ my_friendly_abort (19990430);
+ }
- 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)));
+ /* Create the parameters. */
+ parm_types = void_list_node;
+ parm_types = perm_tree_cons (NULL_TREE, integer_type_node, parm_types);
+ parm_types = perm_tree_cons (NULL_TREE, integer_type_node, parm_types);
+ type = build_function_type (void_type_node, parm_types);
+
+ /* Create the FUNCTION_DECL itself. */
+ ssdf_decl = build_lang_decl (FUNCTION_DECL,
+ get_identifier (id),
+ type);
+ TREE_PUBLIC (ssdf_decl) = 0;
+ DECL_ARTIFICIAL (ssdf_decl) = 1;
+
+ /* Put this function in the list of functions to be called from the
+ static constructors and destructors. */
+ if (!ssdf_decls)
+ {
+ VARRAY_TREE_INIT (ssdf_decls, 32, "ssdf_decls");
+
+ /* Take this opportunity to initialize the map from priority
+ numbers to information about that priority level. */
+ priority_info_map = splay_tree_new (splay_tree_compare_ints,
+ /*delete_key_fn=*/0,
+ /*delete_value_fn=*/
+ (splay_tree_delete_value_fn) &free);
+
+ /* We always need to generate functions for the
+ DEFAULT_INIT_PRIORITY so enter it now. That way when we walk
+ priorities later, we'll be sure to find the
+ DEFAULT_INIT_PRIORITY. */
+ get_priority_info (DEFAULT_INIT_PRIORITY);
+ }
- if (! current_function_decl)
- start_objects ('D');
+ if (ssdf_decls_used == ssdf_decls->num_elements)
+ VARRAY_GROW (ssdf_decls, 2 * ssdf_decls_used);
+ VARRAY_TREE (ssdf_decls, ssdf_decls_used) = ssdf_decl;
+ ++ssdf_decls_used;
+
+ /* Create the argument list. */
+ initialize_p_decl = build_decl (PARM_DECL,
+ get_identifier (INITIALIZE_P_IDENTIFIER),
+ integer_type_node);
+ DECL_CONTEXT (initialize_p_decl) = ssdf_decl;
+ DECL_ARG_TYPE (initialize_p_decl) = integer_type_node;
+ TREE_USED (initialize_p_decl) = 1;
+ priority_decl = build_decl (PARM_DECL, get_identifier (PRIORITY_IDENTIFIER),
+ integer_type_node);
+ DECL_CONTEXT (priority_decl) = ssdf_decl;
+ DECL_ARG_TYPE (priority_decl) = integer_type_node;
+ TREE_USED (priority_decl) = 1;
+
+ TREE_CHAIN (initialize_p_decl) = priority_decl;
+ DECL_ARGUMENTS (ssdf_decl) = initialize_p_decl;
+
+ /* Start the function itself. This is equivalent to declarating the
+ function as:
+
+ static void __ssdf (int __initialize_p, init __priority_p);
+
+ It is static because we only need to call this function from the
+ various constructor and destructor functions for this module. */
+ start_function (/*specs=*/NULL_TREE,
+ ssdf_decl,
+ /*attrs=*/NULL_TREE,
+ /*pre_parsed_p=*/1);
+
+ /* Set up the scope of the outermost block in the function. */
+ store_parm_decls ();
+ pushlevel (0);
+ clear_last_expr ();
+ push_momentary ();
+ expand_start_bindings (0);
- temp = build_cleanup (decl);
+ /* This function must not be deferred because we are depending on
+ its compilation to tell us what is TREE_SYMBOL_REFERENCED. */
+ current_function_cannot_inline
+ = "static storage duration functions cannot be inlined";
+}
- 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);
- }
+/* Generate the initialization code for the priority indicated in N. */
- expand_expr_stmt (temp);
+static int
+generate_inits_for_priority (n, data)
+ splay_tree_node n;
+ void *data ATTRIBUTE_UNUSED;
+{
+ int priority = (int) n->key;
+ priority_info pi = (priority_info) n->value;
+
+ /* For each priority N which has been used generate code which looks
+ like:
+
+ if (__priority == N) {
+ if (__initialize_p)
+ ...
+ else
+ ...
+ }
+
+ We use the sequences we've accumulated to fill in the `...'s. */
+ expand_start_cond (build_binary_op (EQ_EXPR,
+ priority_decl,
+ build_int_2 (priority, 0)),
+ /*exit_flag=*/0);
+
+ /* Do the initializations. */
+ expand_start_cond (build_binary_op (NE_EXPR,
+ initialize_p_decl,
+ integer_zero_node),
+ /*exit_flag=*/0);
+ if (pi->initialization_sequence)
+ {
+ rtx insns;
- if (protect)
- expand_end_cond ();
- }
+ push_to_sequence (pi->initialization_sequence);
+ insns = gen_sequence ();
+ end_sequence ();
+
+ emit_insn (insns);
+ pi->initialization_sequence = NULL_RTX;
+ pi->initializations_p = 1;
+ }
+
+ /* Do the destructions. */
+ expand_start_else ();
+ if (pi->destruction_sequence)
+ {
+ rtx insns;
+
+ push_to_sequence (pi->destruction_sequence);
+ insns = gen_sequence ();
+ end_sequence ();
+
+ emit_insn (insns);
+ pi->destruction_sequence = NULL_RTX;
+ pi->destructions_p = 1;
}
+
+ /* Close out the conditionals. */
+ expand_end_cond ();
+ expand_end_cond ();
- finish_objects ('D');
+ /* Don't stop iterating. */
+ return 0;
}
-/* Generate a function to run a set of global constructors. Subroutine of
- finish_file. */
+/* Finish the generation of the function which performs initialization
+ and destruction of objects with static storage duration. After
+ this point, no more such objects can be created. */
static void
-do_ctors ()
+finish_static_storage_duration_function ()
{
- tree vars = static_aggregates;
+ splay_tree_foreach (priority_info_map,
+ generate_inits_for_priority,
+ /*data=*/0);
- /* Reverse the list so it's in the right order for ctors. */
- vars = nreverse (vars);
+ /* Close out the function. */
+ expand_end_bindings (getdecls (), 1, 0);
+ poplevel (1, 0, 0);
+ pop_momentary ();
+ finish_function (lineno, 0, 0);
+}
- for (; vars; vars = TREE_CHAIN (vars))
+/* Return the information about the indicated PRIORITY level. If no
+ code to handle this level has yet been generated, generate the
+ appropriate prologue. */
+
+static priority_info
+get_priority_info (priority)
+ int priority;
+{
+ priority_info pi;
+ splay_tree_node n;
+
+ n = splay_tree_lookup (priority_info_map,
+ (splay_tree_key) priority);
+ if (!n)
{
- 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;
+ /* Create a new priority information structure, and insert it
+ into the map. */
+ pi = (priority_info) xmalloc (sizeof (struct priority_info_s));
+ pi->initialization_sequence = NULL_RTX;
+ pi->destruction_sequence = NULL_RTX;
+ pi->initializations_p = 0;
+ pi->destructions_p = 0;
+ splay_tree_insert (priority_info_map,
+ (splay_tree_key) priority,
+ (splay_tree_value) pi);
+ }
+ else
+ pi = (priority_info) n->value;
- 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;
- }
+ return pi;
+}
- 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);
- }
+/* Generate code to do the static initialization of DECL. The
+ initialization is INIT. If DECL may be initialized more than once
+ in different object files, SENTRY is the guard variable to
+ check. PRIORITY is the priority for the initialization. */
- expand_start_target_temps ();
+static void
+do_static_initialization (decl, init, sentry, priority)
+ tree decl;
+ tree init;
+ tree sentry;
+ int priority;
+{
+ priority_info pi;
- 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 ();
+ /* Get the priority information for this PRIORITY, */
+ pi = get_priority_info (priority);
+ if (!pi->initialization_sequence)
+ start_sequence ();
+ else
+ push_to_sequence (pi->initialization_sequence);
+
+ /* Tell the debugger that we are at the location of the static
+ variable in question. */
+ emit_note (input_filename, lineno);
+
+ /* If there's a SENTRY, we only do the initialization if it is
+ zero, i.e., if we are the first to initialize it. */
+ if (sentry)
+ expand_start_cond (build_binary_op (EQ_EXPR,
+ build_unary_op (PREINCREMENT_EXPR,
+ sentry,
+ /*noconvert=*/0),
+ integer_one_node),
+ /*exit_flag=*/0);
+
+ /* Prepare a binding level for temporaries created during the
+ initialization. */
+ expand_start_target_temps ();
+
+ if (IS_AGGR_TYPE (TREE_TYPE (decl))
+ || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ expand_aggr_init (decl, init, 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 ();
+ /* Cleanup any temporaries needed for the initial value. */
+ expand_end_target_temps ();
- if (protect)
- expand_end_cond ();
+ /* Cleanup any deferred pops from function calls. This would be done
+ by expand_end_cond, but we also need it when !SENTRY, since we are
+ constructing these sequences by parts. */
+ do_pending_stack_adjust ();
- 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);
- }
+ /* Close the conditional opened above. */
+ if (sentry)
+ expand_end_cond ();
- finish_objects ('I');
+ /* Save the sequence for later use. */
+ pi->initialization_sequence = get_insns ();
+ end_sequence ();
}
-/* This routine is called from the last rule in yyparse ().
- Its job is to create all the code needed to initialize and
- destroy the global aggregates. We do the destruction
- first, since that way we only need to reverse the decls once. */
+/* Generate code to do the static destruction of DECL. If DECL may be
+ initialized more than once in different object files, SENTRY is the
+ guard variable to check. PRIORITY is the priority for the
+ destruction. */
-void
-finish_file ()
+static void
+do_static_destruction (decl, sentry, priority)
+ tree decl;
+ tree sentry;
+ int priority;
{
- extern int lineno;
- int start_time, this_time;
+ rtx new_insns;
+ priority_info pi;
- tree fnname;
- tree vars;
- int needs_cleaning = 0, needs_messing_up = 0;
+ /* If we don't need a destructor, there's nothing to do. */
+ if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
+ return;
+
+ /* Get the priority information for this PRIORITY, */
+ pi = get_priority_info (priority);
+ if (!pi->destruction_sequence)
+ start_sequence ();
+ else
+ push_to_sequence (pi->destruction_sequence);
- at_eof = 1;
+ /* Start a new sequence to handle just this destruction. */
+ start_sequence ();
- /* Bad parse errors. Just forget about it. */
- if (! global_bindings_p () || current_class_type)
- return;
+ /* Tell the debugger that we are at the location of the static
+ variable in question. */
+ emit_note (input_filename, lineno);
+
+ /* If there's a SENTRY, we only do the destruction if it is one,
+ i.e., if we are the last to destroy it. */
+ if (sentry)
+ expand_start_cond (build_binary_op (EQ_EXPR,
+ build_unary_op (PREDECREMENT_EXPR,
+ sentry,
+ /*nonconvert=*/1),
+ integer_zero_node),
+ /*exit_flag=*/0);
+
+ /* Actually to the destruction. */
+ expand_expr_stmt (build_cleanup (decl));
+
+ /* Cleanup any deferred pops from function calls. This would be done
+ by expand_end_cond, but we also need it when !SENTRY, since we are
+ constructing these sequences by parts. */
+ do_pending_stack_adjust ();
+
+ /* Close the conditional opened above. */
+ if (sentry)
+ expand_end_cond ();
+
+ /* Insert the NEW_INSNS before the current insns. (Destructions are
+ run in reverse order of initializations.) */
+ new_insns = gen_sequence ();
+ end_sequence ();
+ if (pi->destruction_sequence)
+ emit_insn_before (new_insns, pi->destruction_sequence);
+ else
+ emit_insn (new_insns);
- check_decl_namespace ();
+ /* Save the sequence for later use. */
+ pi->destruction_sequence = get_insns ();
+ end_sequence ();
+}
- start_time = get_run_time ();
+/* Add code to the static storage duration function that will handle
+ DECL (a static variable that needs initializing and/or destruction)
+ with the indicated PRIORITY. If DECL needs initializing, INIT is
+ the initializer. */
- /* Otherwise, GDB can get confused, because in only knows
- about source for LINENO-1 lines. */
- lineno -= 1;
+static void
+do_static_initialization_and_destruction (decl, init)
+ tree decl;
+ tree init;
+{
+ tree sentry = NULL_TREE;
+ int priority;
- interface_unknown = 1;
- interface_only = 0;
+ /* Deal gracefully with error. */
+ if (decl == error_mark_node)
+ return;
- for (fnname = pending_templates; fnname; fnname = TREE_CHAIN (fnname))
- {
- tree srcloc = TREE_PURPOSE (fnname);
- tree decl = TREE_VALUE (fnname);
+ /* The only things that can be initialized are variables. */
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420);
- input_filename = SRCLOC_FILE (srcloc);
- lineno = SRCLOC_LINE (srcloc);
+ /* If this object is not defined, we don't need to do anything
+ here. */
+ if (DECL_EXTERNAL (decl))
+ return;
- 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);
- }
+ /* Also, if the initializer already contains errors, we can bail out
+ now. */
+ if (init && TREE_CODE (init) == TREE_LIST
+ && value_member (error_mark_node, init))
+ return;
- for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
- {
- tree args, fn, decl = TREE_VALUE (fnname);
+ /* Trick the compiler into thinking we are at the file and line
+ where DECL was declared so that error-messages make sense, and so
+ that the debugger will show somewhat sensible file and line
+ information. */
+ input_filename = DECL_SOURCE_FILE (decl);
+ lineno = DECL_SOURCE_LINE (decl);
- if (DECL_INITIAL (decl))
- continue;
+ /* Because of:
- fn = TREE_PURPOSE (fnname);
- args = get_bindings (fn, decl, NULL_TREE);
- fn = instantiate_template (fn, args);
- instantiate_decl (fn);
- }
+ [class.access.spec]
- cat_namespace_levels();
+ Access control for implicit calls to the constructors,
+ the conversion functions, or the destructor called to
+ create and destroy a static data member is performed as
+ if these calls appeared in the scope of the member's
+ class.
- /* Push into C language context, because that's all
- we'll need here. */
- push_lang_context (lang_name_c);
+ we pretend we are in a static member function of the class of
+ which the DECL is a member. */
+ if (member_p (decl))
+ {
+ DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
+ DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
+ }
+
+ /* We need a sentry if this is an object with external linkage that
+ might be initialized in more than one place. */
+ if (TREE_PUBLIC (decl) && (DECL_COMMON (decl)
+ || DECL_ONE_ONLY (decl)
+ || DECL_WEAK (decl)))
+ sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
+
+ /* Generate the code to actually do the intialization and
+ destruction. */
+ priority = DECL_INIT_PRIORITY (decl);
+ if (!priority)
+ priority = DEFAULT_INIT_PRIORITY;
+ do_static_initialization (decl, init, sentry, priority);
+ do_static_destruction (decl, sentry, priority);
+
+ /* Now that we're done with DECL we don't need to pretend to be a
+ member of its class any longer. */
+ DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
+ DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
+}
-#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
- tables. If the last thing pushed onto the global_binding_level was a
- virtual function table, then slicing it out would slice away all the
- decls (i.e., we lose the head of the chain).
-
- There are several ways of getting the same effect, from changing the
- way that iterators over the chain treat the elements that pertain to
- 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. */
-
- /* Make last thing in global scope not be a virtual function table. */
-#if 0 /* not yet, should get fixed properly later */
- vars = make_type_decl (get_identifier (" @%$#@!"), integer_type_node);
-#else
- vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node);
-#endif
- DECL_IGNORED_P (vars) = 1;
- SET_DECL_ARTIFICIAL (vars);
- pushdecl (vars);
-#endif
+/* Generate a static constructor (if CONSTRUCTOR_P) or destructor
+ (otherwise) that will initialize all gobal objects with static
+ storage duration having the indicated PRIORITY. */
- 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;
+static void
+generate_ctor_or_dtor_function (constructor_p, priority)
+ int constructor_p;
+ int priority;
+{
+ char function_key;
+ tree arguments;
+ size_t i;
+
+ /* We use `I' to indicate initialization and `D' to indicate
+ destruction. */
+ if (constructor_p)
+ function_key = 'I';
+ else
+ function_key = 'D';
- if (static_ctors || vars)
- needs_messing_up = 1;
- if (static_dtors || vars)
- needs_cleaning = 1;
+ /* Begin the function. */
+ start_objects (function_key, priority);
- /* The aggregates are listed in reverse declaration order, for cleaning. */
- if (needs_cleaning)
+ /* Call the static storage duration function with appropriate
+ arguments. */
+ for (i = 0; i < ssdf_decls_used; ++i)
{
- do_dtors ();
+ arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0),
+ NULL_TREE);
+ arguments = tree_cons (NULL_TREE, build_int_2 (constructor_p, 0),
+ arguments);
+ expand_expr_stmt (build_function_call (VARRAY_TREE (ssdf_decls, i),
+ arguments));
}
- /* do_ctors will reverse the lists for messing up. */
- if (needs_messing_up)
+ /* If we're generating code for the DEFAULT_INIT_PRIORITY, throw in
+ calls to any functions marked with attributes indicating that
+ they should be called at initialization- or destruction-time. */
+ if (priority == DEFAULT_INIT_PRIORITY)
{
- do_ctors ();
+ tree fns;
+
+ for (fns = constructor_p ? static_ctors : static_dtors;
+ fns;
+ fns = TREE_CHAIN (fns))
+ expand_expr_stmt (build_function_call (TREE_VALUE (fns), NULL_TREE));
}
- permanent_allocation (1);
+ /* Close out the function. */
+ finish_objects (function_key, priority);
+}
- /* Done with C language context needs. */
- pop_lang_context ();
+/* Generate constructor and destructor functions for the priority
+ indicated by N. */
- /* Now write out any static class variables (which may have since
- learned how to be initialized). */
- while (pending_statics)
- {
- tree decl = TREE_VALUE (pending_statics);
+static int
+generate_ctor_and_dtor_functions_for_priority (n, data)
+ splay_tree_node n;
+ void *data ATTRIBUTE_UNUSED;
+{
+ int priority = (int) n->key;
+ priority_info pi = (priority_info) n->value;
+
+ /* Generate the functions themselves, but only if they are really
+ needed. */
+ if (pi->initializations_p
+ || (priority == DEFAULT_INIT_PRIORITY && static_ctors))
+ generate_ctor_or_dtor_function (/*constructor_p=*/1,
+ priority);
+ if (pi->destructions_p
+ || (priority == DEFAULT_INIT_PRIORITY && static_dtors))
+ generate_ctor_or_dtor_function (/*constructor_p=*/0,
+ priority);
+
+ /* Keep iterating. */
+ return 0;
+}
- /* 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
+/* This routine is called from the last rule in yyparse ().
+ Its job is to create all the code needed to initialize and
+ destroy the global aggregates. We do the destruction
+ first, since that way we only need to reverse the decls once. */
- DECL_DEFER_OUTPUT (decl) = 0;
- rest_of_decl_compilation
- (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1);
+void
+finish_file ()
+{
+ extern int lineno;
+ int start_time, this_time;
+ tree vars;
+ int reconsider;
+ size_t i;
- pending_statics = TREE_CHAIN (pending_statics);
- }
+ at_eof = 1;
- this_time = get_run_time ();
- parse_time -= this_time - start_time;
- varconst_time += this_time - start_time;
+ /* Bad parse errors. Just forget about it. */
+ if (! global_bindings_p () || current_class_type || decl_namespace_list)
+ return;
start_time = get_run_time ();
- if (flag_handle_signatures)
- walk_sigtables ((void (*) PROTO ((tree, tree))) 0,
- finish_sigtable_vardecl);
+ /* Otherwise, GDB can get confused, because in only knows
+ about source for LINENO-1 lines. */
+ lineno -= 1;
- for (fnname = saved_inlines; fnname; fnname = TREE_CHAIN (fnname))
- {
- tree decl = TREE_VALUE (fnname);
- import_export_decl (decl);
- }
+ interface_unknown = 1;
+ interface_only = 0;
- mark_all_runtime_matches ();
+ /* We now have to write out all the stuff we put off writing out.
+ These include:
- /* Now write out inline functions which had their addresses taken and
- which were not declared virtual and which were not declared `extern
- inline'. */
- {
- int reconsider = 1; /* More may be referenced; check again */
+ o Template specializations that we have not yet instantiated,
+ but which are needed.
+ o Initialization and destruction for non-local objects with
+ static storage duration. (Local objects with static storage
+ duration are initialized when their scope is first entered,
+ and are cleaned up via atexit.)
+ o Virtual function tables.
- while (reconsider)
- {
- tree *p = &saved_inlines;
- reconsider = 0;
+ All of these may cause others to be needed. For example,
+ instantiating one function may cause another to be needed, and
+ generating the intiailzer for an object may cause templates to be
+ instantiated, etc., etc. */
- /* 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);
+ this_time = get_run_time ();
+ parse_time -= this_time - start_time;
+ varconst_time += this_time - start_time;
+ start_time = get_run_time ();
+ permanent_allocation (1);
- reconsider |= walk_vtables ((void (*) PROTO((tree, tree))) 0,
- finish_vtable_vardecl);
+ do
+ {
+ /* Non-zero if we need a static storage duration function on
+ this iteration through the loop. */
+ int need_ssdf_p = 0;
+
+ reconsider = 0;
+
+ /* If there are templates that we've put off instantiating, do
+ them now. */
+ instantiate_pending_templates ();
+
+ /* Write out signature-tables and virtual tables as required.
+ Note that writing out the virtual table for a template class
+ may cause the instantiation of members of that class. */
+ if (flag_handle_signatures
+ && walk_globals (sigtable_decl_p,
+ finish_sigtable_vardecl,
+ /*data=*/0))
+ reconsider = 1;
+ if (walk_globals (vtable_decl_p,
+ finish_vtable_vardecl,
+ /*data=*/0))
+ reconsider = 1;
+
+ /* The list of objects with static storage duration is built up
+ in reverse order, so we reverse it here. We also clear
+ STATIC_AGGREGATES so that any new aggregates added during the
+ initialization of these will be initialized in the correct
+ order when we next come around the loop. */
+ vars = nreverse (static_aggregates);
+ static_aggregates = NULL_TREE;
+ while (vars)
+ {
+ if (! TREE_ASM_WRITTEN (TREE_VALUE (vars)))
+ rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1);
+ if (!need_ssdf_p)
+ {
+ /* We need to start a new initialization function each
+ time through the loop. That's because we need to
+ know which vtables have been referenced, and
+ TREE_SYMBOL_REFERENCED isn't computed until a
+ function is finished, and written out. That's a
+ deficiency in the back-end. When this is fixed,
+ these initialization functions could all become
+ inline, with resulting performance improvements. */
+ start_static_storage_duration_function ();
+ need_ssdf_p = 1;
+ }
- while (*p)
- {
- tree decl = TREE_VALUE (*p);
+ do_static_initialization_and_destruction (TREE_VALUE (vars),
+ TREE_PURPOSE (vars));
+ reconsider = 1;
+ vars = TREE_CHAIN (vars);
+ }
+
+ /* Finish up the static storage duration function for this
+ round. */
+ if (need_ssdf_p)
+ finish_static_storage_duration_function ();
+
+ /* Go through the various inline functions, and see if any need
+ synthesizing. */
+ for (i = 0; i < saved_inlines_used; ++i)
+ {
+ tree decl = VARRAY_TREE (saved_inlines, i);
+ import_export_decl (decl);
+ if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
+ && TREE_USED (decl)
+ && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
+ {
+ /* Even though we're already at the top-level, we push
+ there again. That way, when we pop back a few lines
+ hence, all of our state is restored. Otherwise,
+ finish_function doesn't clean things up, and we end
+ up with CURRENT_FUNCTION_DECL set. */
+ push_to_top_level ();
+ if (DECL_TINFO_FN_P (decl))
+ synthesize_tinfo_fn (decl);
+ else
+ synthesize_method (decl);
+ pop_from_top_level ();
+ reconsider = 1;
+ }
+ }
- if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
- && TREE_USED (decl)
- && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
- {
- if (DECL_MUTABLE_P (decl))
- synthesize_tinfo_fn (decl);
- else
- synthesize_method (decl);
- reconsider = 1;
- }
+ /* Mark all functions that might deal with exception-handling as
+ referenced. */
+ mark_all_runtime_matches ();
- /* Catch new template instantiations. */
- if (decl != TREE_VALUE (*p))
- continue;
-
- 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)
- {
- if (DECL_NOT_REALLY_EXTERN (decl))
- {
- DECL_EXTERNAL (decl) = 0;
- reconsider = 1;
- /* 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);
- }
-
- *p = TREE_CHAIN (*p);
- }
- else
- p = &TREE_CHAIN (*p);
- }
- }
+ /* We lie to the back-end, pretending that some functions are
+ not defined when they really are. This keeps these functions
+ from being put out unncessarily. But, we must stop lying
+ when the functions are referenced, or if they are not comdat
+ since they need to be put out now. */
+ for (i = 0; i < saved_inlines_used; ++i)
+ {
+ tree decl = VARRAY_TREE (saved_inlines, i);
+
+ if (DECL_NOT_REALLY_EXTERN (decl)
+ && DECL_INITIAL (decl)
+ && (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
+ || !DECL_COMDAT (decl)))
+ DECL_EXTERNAL (decl) = 0;
+ }
- /* 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.
+ if (saved_inlines_used
+ && wrapup_global_declarations (&VARRAY_TREE (saved_inlines, 0),
+ saved_inlines_used))
+ reconsider = 1;
+ if (walk_namespaces (wrapup_globals_for_namespace, /*data=*/0))
+ reconsider = 1;
- 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);
+ /* Static data members are just like namespace-scope globals. */
+ for (i = 0; i < pending_statics_used; ++i)
+ {
+ tree decl = VARRAY_TREE (pending_statics, i);
+ if (TREE_ASM_WRITTEN (decl))
+ continue;
+ import_export_decl (decl);
+ if (DECL_NOT_REALLY_EXTERN (decl) && ! DECL_IN_AGGR_P (decl))
+ DECL_EXTERNAL (decl) = 0;
+ }
+ if (pending_statics
+ && wrapup_global_declarations (&VARRAY_TREE (pending_statics, 0),
+ pending_statics_used))
+ reconsider = 1;
+ }
+ while (reconsider);
- if (DECL_NOT_REALLY_EXTERN (decl)
- && !DECL_COMDAT (decl)
- && DECL_INITIAL (decl) != NULL_TREE)
- DECL_EXTERNAL (decl) = 0;
- }
- }
+ /* We give C linkage to static constructors and destructors. */
+ push_lang_context (lang_name_c);
- /* Now delete from the chain of variables all virtual function tables.
- We output them all ourselves, because each will be treated specially. */
+ /* Generate initialization and destruction functions for all
+ priorities for which they are required. */
+ if (priority_info_map)
+ splay_tree_foreach (priority_info_map,
+ generate_ctor_and_dtor_functions_for_priority,
+ /*data=*/0);
- walk_vtables ((void (*) PROTO((tree, tree))) 0,
- prune_vtable_vardecl);
+ /* We're done with the splay-tree now. */
+ if (priority_info_map)
+ splay_tree_delete (priority_info_map);
- if (write_virtuals == 2)
- {
- /* Now complain about an virtual function tables promised
- but not delivered. */
- while (pending_vtables)
- {
- if (TREE_PURPOSE (pending_vtables) == NULL_TREE)
- error ("virtual function table for `%s' not defined",
- IDENTIFIER_POINTER (TREE_VALUE (pending_vtables)));
- pending_vtables = TREE_CHAIN (pending_vtables);
- }
- }
+ /* We're done with static constructors, so we can go back to "C++"
+ linkage now. */
+ pop_lang_context ();
+
+ /* Now delete from the chain of variables all virtual function tables.
+ We output them all ourselves, because each will be treated
+ specially. */
+ walk_globals (vtable_decl_p, prune_vtable_vardecl, /*data=*/0);
+
+ /* Now, issue warnings about static, but not defined, functions,
+ etc. */
+ walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
finish_repo ();
@@ -3432,11 +3766,13 @@ reparse_absdcl_as_expr (type, decl)
return build_functional_cast (type, NULL_TREE);
/* recurse */
- decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0));
+ decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0));
decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
- if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node)
+ if (TREE_CODE (decl) == CALL_EXPR
+ && (! TREE_TYPE (decl)
+ || TREE_CODE (TREE_TYPE (decl)) != VOID_TYPE))
decl = require_complete_type (decl);
return decl;
@@ -3484,7 +3820,8 @@ reparse_absdcl_as_casts (decl, expr)
expr = build_c_cast (type, expr);
}
- if (warn_old_style_cast)
+ if (warn_old_style_cast && ! in_system_header
+ && current_lang_name != lang_name_c)
warning ("use of old-style cast");
return expr;
@@ -3655,11 +3992,30 @@ build_expr_from_tree (t)
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);
+ else
+ {
+ tree fn = TREE_OPERAND (t, 0);
+
+ /* We can get a TEMPLATE_ID_EXPR here on code like:
+
+ x->f<2>();
+
+ so we must resolve that. However, we can also get things
+ like a BIT_NOT_EXPR here, when referring to a destructor,
+ and things like that are not correctly resolved by
+ build_expr_from_tree. So, just use build_expr_from_tree
+ when we really need it. */
+ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+ fn = lookup_template_function
+ (TREE_OPERAND (fn, 0),
+ build_expr_from_tree (TREE_OPERAND (fn, 1)));
+
+ return build_method_call
+ (build_expr_from_tree (TREE_OPERAND (t, 1)),
+ fn,
+ build_expr_from_tree (TREE_OPERAND (t, 2)),
+ NULL_TREE, LOOKUP_NORMAL);
+ }
case CALL_EXPR:
if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
@@ -3716,10 +4072,22 @@ build_expr_from_tree (t)
}
case COMPONENT_REF:
- return build_x_component_ref
- (build_expr_from_tree (TREE_OPERAND (t, 0)),
- TREE_OPERAND (t, 1), NULL_TREE, 1);
-
+ {
+ tree object = build_expr_from_tree (TREE_OPERAND (t, 0));
+ tree field = TREE_OPERAND (t, 1);
+
+ /* We use a COMPONENT_REF to indicate things of the form `x.b'
+ and `x.A::b'. We must distinguish between those cases
+ here. */
+ if (TREE_CODE (field) == SCOPE_REF)
+ return build_object_ref (object,
+ TREE_OPERAND (field, 0),
+ TREE_OPERAND (field, 1));
+ else
+ return build_x_component_ref (object, field,
+ NULL_TREE, 1);
+ }
+
case THROW_EXPR:
return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0)));
@@ -3733,6 +4101,7 @@ build_expr_from_tree (t)
r = build_nt (CONSTRUCTOR, NULL_TREE,
build_expr_from_tree (CONSTRUCTOR_ELTS (t)));
+ TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
if (TREE_TYPE (t))
return digest_init (TREE_TYPE (t), r, 0);
@@ -3800,6 +4169,10 @@ finish_decl_parsing (decl)
case ARRAY_REF:
TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
return decl;
+ case TREE_LIST:
+ /* For attribute handling. */
+ TREE_VALUE (decl) = finish_decl_parsing (TREE_VALUE (decl));
+ return decl;
default:
my_friendly_abort (5);
return NULL_TREE;
@@ -3916,7 +4289,9 @@ add_using_namespace (user, used, indirect)
/* 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). */
+ The algorithm is O(n^2). We could get this down to O(n log n) by
+ doing a sort on the addresses of the functions, if that becomes
+ necessary. */
static tree
merge_functions (s1, s2)
@@ -3958,8 +4333,7 @@ ambiguous_decl (name, old, new, flags)
/* 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)))
+ && !DECL_CLASS_TEMPLATE_P (val))
val = NULL_TREE;
break;
case TYPE_DECL:
@@ -3990,9 +4364,15 @@ ambiguous_decl (name, old, new, flags)
/* 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));
+ /* If we've already given this error for this lookup,
+ BINDING_VALUE (old) is error_mark_node, so let's not
+ repeat ourselves. */
+ if (BINDING_VALUE (old) != error_mark_node)
+ {
+ 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;
@@ -4086,9 +4466,10 @@ qualified_lookup_using_namespace (name, scope, result, flags)
outside scope. */
void
-set_decl_namespace (decl, scope)
+set_decl_namespace (decl, scope, friendp)
tree decl;
tree scope;
+ int friendp;
{
tree old;
if (scope == std_node)
@@ -4096,7 +4477,8 @@ set_decl_namespace (decl, scope)
/* Get rid of namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
- if (!is_namespace_ancestor (current_namespace, scope))
+ /* It is ok for friends to be qualified in parallel space. */
+ if (!friendp && !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);
@@ -4115,6 +4497,12 @@ set_decl_namespace (decl, scope)
/* Since decl is a function, old should contain a function decl. */
if (!is_overloaded_fn (old))
goto complain;
+ if (processing_template_decl || processing_specialization)
+ /* We have not yet called push_template_decl to turn the
+ FUNCTION_DECL into a TEMPLATE_DECL, so the declarations
+ won't match. But, we'll check later, when we construct the
+ template. */
+ return;
for (; old; old = OVL_NEXT (old))
if (decls_match (decl, OVL_CURRENT (old)))
return;
@@ -4128,7 +4516,7 @@ set_decl_namespace (decl, scope)
/* Compute the namespace where a declaration is defined. */
-tree
+static tree
decl_namespace (decl)
tree decl;
{
@@ -4181,10 +4569,28 @@ pop_decl_namespace ()
decl_namespace_list = TREE_CHAIN (decl_namespace_list);
}
-static void
-check_decl_namespace ()
+/* Enter a class or namespace scope. */
+
+void
+push_scope (t)
+ tree t;
{
- my_friendly_assert (decl_namespace_list == NULL_TREE, 980711);
+ if (TREE_CODE (t) == NAMESPACE_DECL)
+ push_decl_namespace (t);
+ else
+ pushclass (t, 2);
+}
+
+/* Leave scope pushed by push_scope. */
+
+void
+pop_scope (t)
+ tree t;
+{
+ if (TREE_CODE (t) == NAMESPACE_DECL)
+ pop_decl_namespace ();
+ else
+ popclass ();
}
/* [basic.lookup.koenig] */
@@ -4201,6 +4607,10 @@ struct arg_lookup
static int arg_assoc PROTO((struct arg_lookup*, tree));
static int arg_assoc_args PROTO((struct arg_lookup*, tree));
+static int arg_assoc_type PROTO((struct arg_lookup*, tree));
+static int add_function PROTO((struct arg_lookup *, tree));
+static int arg_assoc_namespace PROTO((struct arg_lookup *, tree));
+static int arg_assoc_class PROTO((struct arg_lookup *, tree));
/* Add a function to the lookup structure.
Returns 1 on error. */
@@ -4300,7 +4710,7 @@ arg_assoc_class (k, type)
/* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type))
{
- list = innermost_args (CLASSTYPE_TI_ARGS (type), 0);
+ list = innermost_args (CLASSTYPE_TI_ARGS (type));
for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
arg_assoc (k, TREE_VEC_ELT (list, i));
}
@@ -4351,6 +4761,7 @@ arg_assoc_type (k, type)
/* Associate the return type. */
return arg_assoc_type (k, TREE_TYPE (type));
case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
return 0;
case LANG_TYPE:
if (type == unknown_type_node)
@@ -4393,14 +4804,80 @@ arg_assoc (k, n)
if (TREE_CODE (n) == ADDR_EXPR)
n = TREE_OPERAND (n, 0);
+ if (TREE_CODE (n) == COMPONENT_REF)
+ n = TREE_OPERAND (n, 1);
+ if (TREE_CODE (n) == OFFSET_REF)
+ n = TREE_OPERAND (n, 1);
while (TREE_CODE (n) == TREE_LIST)
n = TREE_VALUE (n);
- my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
+ if (TREE_CODE (n) == FUNCTION_DECL)
+ return arg_assoc_type (k, TREE_TYPE (n));
+ if (TREE_CODE (n) == TEMPLATE_ID_EXPR)
+ {
+ /* [basic.lookup.koenig]
+
+ If T is a template-id, its associated namespaces and classes
+ are the namespace in which the template is defined; for
+ member templates, the member template's class; the namespaces
+ and classes associated with the types of the template
+ arguments provided for template type parameters (excluding
+ template template parameters); the namespaces in which any
+ template template arguments are defined; and the classes in
+ which any member templates used as template template
+ arguments are defined. [Note: non-type template arguments do
+ not contribute to the set of associated namespaces. ] */
+ tree template = TREE_OPERAND (n, 0);
+ tree args = TREE_OPERAND (n, 1);
+ tree ctx;
+ tree arg;
+
+ /* First, the template. There may actually be more than one if
+ this is an overloaded function template. But, in that case,
+ we only need the first; all the functions will be in the same
+ namespace. */
+ template = OVL_CURRENT (template);
+
+ ctx = CP_DECL_CONTEXT (template);
+
+ if (TREE_CODE (ctx) == NAMESPACE_DECL)
+ {
+ if (arg_assoc_namespace (k, ctx) == 1)
+ return 1;
+ }
+ /* It must be a member template. */
+ else if (arg_assoc_class (k, ctx) == 1)
+ return 1;
+
+ /* Now the arguments. */
+ for (arg = args; arg != NULL_TREE; arg = TREE_CHAIN (arg))
+ {
+ tree t = TREE_VALUE (arg);
- for (; n; n = TREE_CHAIN (n))
- if (arg_assoc (k, OVL_FUNCTION (n)))
- return 1;
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ {
+ ctx = CP_DECL_CONTEXT (t);
+ if (TREE_CODE (ctx) == NAMESPACE_DECL)
+ {
+ if (arg_assoc_namespace (k, ctx) == 1)
+ return 1;
+ }
+ else if (arg_assoc_class (k, ctx) == 1)
+ return 1;
+ }
+ else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't'
+ && arg_assoc_type (k, t) == 1)
+ return 1;
+ }
+ }
+ else
+ {
+ my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
+
+ for (; n; n = OVL_CHAIN (n))
+ if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n))))
+ return 1;
+ }
return 0;
}
@@ -4432,9 +4909,6 @@ 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. */
@@ -4462,6 +4936,16 @@ validate_nonmember_using_decl (decl, scope, name)
if (TREE_CODE (decl) == SCOPE_REF
&& TREE_OPERAND (decl, 0) == std_node)
{
+ if (namespace_bindings_p ()
+ && current_namespace == global_namespace)
+ /* There's no need for a using declaration at all, here,
+ since `std' is the same as `::'. We can't just pass this
+ on because we'll complain later about declaring something
+ in the same scope as a using declaration with the same
+ name. We return NULL_TREE which indicates to the caller
+ that there's no need to do any further processing. */
+ return NULL_TREE;
+
*scope = global_namespace;
*name = TREE_OPERAND (decl, 1);
}
@@ -4469,9 +4953,23 @@ validate_nonmember_using_decl (decl, scope, name)
{
*scope = TREE_OPERAND (decl, 0);
*name = TREE_OPERAND (decl, 1);
+
+ /* [namespace.udecl]
+
+ A using-declaration for a class member shall be a
+ member-declaration. */
+ if (TREE_CODE (*scope) != NAMESPACE_DECL)
+ {
+ if (TYPE_P (*scope))
+ cp_error ("`%T' is not a namespace", *scope);
+ else
+ cp_error ("`%D' is not a namespace", *scope);
+ return NULL_TREE;
+ }
}
else if (TREE_CODE (decl) == IDENTIFIER_NODE
- || TREE_CODE (decl) == TYPE_DECL)
+ || TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == TEMPLATE_DECL)
{
*scope = global_namespace;
*name = decl;
@@ -4521,17 +5019,37 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
*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. */
+ tree new_fn = OVL_CURRENT (tmp);
+
+ /* [namespace.udecl]
+
+ If a function declaration in namespace scope or block
+ scope has the same name and the same parameter types as a
+ function introduced by a using declaration the program is
+ ill-formed. */
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;
+ {
+ tree old_fn = OVL_CURRENT (tmp1);
+
+ if (!OVL_USED (tmp1)
+ && compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
+ TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
+ {
+ /* There was already a non-using declaration in
+ this scope with the same parameter types. */
+ cp_error ("`%D' is already declared in this scope",
+ name);
+ break;
+ }
+ else if (duplicate_decls (new_fn, old_fn))
+ /* We're re-using something we already used
+ before. We don't need to add it again. */
+ break;
+ }
- /* Duplicate use, ignore */
+ /* If we broke out of the loop, there's no reason to add
+ this function to the using declarations for this
+ scope. */
if (tmp1)
continue;
@@ -4604,7 +5122,27 @@ do_local_using_decl (decl)
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval)
- set_identifier_local_value (name, newval);
+ {
+ if (is_overloaded_fn (newval))
+ {
+ tree fn, term;
+
+ /* We only need to push declarations for those functions
+ that were not already bound in the current level.
+ The old value might be NULL_TREE, it might be a single
+ function, or an OVERLOAD. */
+ if (oldval && TREE_CODE (oldval) == OVERLOAD)
+ term = OVL_FUNCTION (oldval);
+ else
+ term = oldval;
+ for (fn = newval; fn && OVL_CURRENT (fn) != term;
+ fn = OVL_NEXT (fn))
+ push_overloaded_decl (OVL_CURRENT (fn),
+ PUSH_LOCAL | PUSH_USING);
+ }
+ else
+ push_local_binding (name, newval, PUSH_USING);
+ }
if (newtype)
set_identifier_type_value (name, newtype);
}
@@ -4694,31 +5232,61 @@ mark_used (decl)
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))
+
+ /* If this is a function or variable that is an instance of some
+ template, we now know that we will need to actually do the
+ instantiation. A TEMPLATE_DECL may also have DECL_TEMPLATE_INFO,
+ if it's a partial instantiation, but there's no need to
+ instantiate such a thing. We check that DECL is not an explicit
+ instantiation because that is not checked in instantiate_decl. */
+ if (TREE_CODE (decl) != TEMPLATE_DECL
+ && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
+ && !DECL_EXPLICIT_INSTANTIATION (decl))
instantiate_decl (decl);
}
-/* Helper function for named_class_head_sans_basetype nonterminal. */
+/* Helper function for named_class_head_sans_basetype nonterminal. We
+ have just seen something of the form `AGGR SCOPE::ID'. Return a
+ TYPE_DECL for the type declared by ID in SCOPE. */
tree
handle_class_head (aggr, scope, id)
tree aggr, scope, id;
{
+ tree decl;
+
if (TREE_CODE (id) == TYPE_DECL)
- return id;
+ decl = id;
+ else if (DECL_CLASS_TEMPLATE_P (id))
+ decl = DECL_TEMPLATE_RESULT (id);
+ else
+ {
+ 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);
+
+ decl = TYPE_MAIN_DECL (xref_tag (aggr, make_anon_name (), 1));
+ }
- 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);
+ /* This syntax is only allowed when we're defining a type, so we
+ enter the SCOPE. */
+ push_scope (CP_DECL_CONTEXT (decl));
+
+ /* If we see something like:
- id = xref_tag
- (aggr, make_anon_name (), NULL_TREE, 1);
- return TYPE_MAIN_DECL (id);
+ template <typename T> struct S::I ....
+
+ we must create a TEMPLATE_DECL for the nested type. */
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ decl = push_template_decl (decl);
+
+ return decl;
}
diff --git a/contrib/gcc/cp/errfn.c b/contrib/gcc/cp/errfn.c
index 8d20682..b5d3eec 100644
--- a/contrib/gcc/cp/errfn.c
+++ b/contrib/gcc/cp/errfn.c
@@ -1,5 +1,5 @@
/* Provide a call-back mechanism for handling error output.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94-98, 1999 Free Software Foundation, Inc.
Contributed by Jason Merrill (jason@cygnus.com)
This file is part of GNU CC.
@@ -22,14 +22,9 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "tree.h"
+#include "cp-tree.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
@@ -45,25 +40,19 @@ int cp_silent = 0;
typedef void errorfn (); /* deliberately vague */
-extern char* cp_file_of PROTO((tree));
-extern int cp_line_of PROTO((tree));
+static void cp_thing PROTO ((errorfn *, int, const char *, va_list));
#define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
/* 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, ap)
errorfn *errfn;
int atarg1;
const char *format;
va_list ap;
-#endif
{
static char *buf;
static long buflen;
@@ -155,18 +144,15 @@ cp_thing (errfn, atarg1, format, ap)
}
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. */
+ /* A `%%' has occurred in the input string. Replace it with
+ a `%' in the formatted message buf. */
- len += 2;
- if (len > buflen)
+ if (++len > buflen)
{
buflen = len;
buf = xrealloc (buf, len);
}
- strcpy (buf + offset, "%%");
- offset += 2;
+ buf[offset++] = '%';
}
else
{
@@ -196,88 +182,170 @@ cp_thing (errfn, atarg1, format, ap)
{
char *file = cp_file_of (atarg);
int line = cp_line_of (atarg);
- (*errfn) (file, line, buf);
+ (*errfn) (file, line, "%s", buf);
}
else
- (*errfn) (buf);
+ (*errfn) ("%s", buf);
}
-#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)
+void
+cp_error VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
cp_thing ((errorfn *) error, 0, format, ap);
va_end (ap);
}
-DECLARE (cp_warning)
+void
+cp_warning VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
cp_thing ((errorfn *) warning, 0, format, ap);
va_end (ap);
}
-DECLARE (cp_pedwarn)
+void
+cp_pedwarn VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
cp_thing ((errorfn *) pedwarn, 0, format, ap);
va_end (ap);
}
-DECLARE (cp_compiler_error)
+void
+cp_compiler_error VPROTO((const char *format, ...))
{
- extern errorfn compiler_error;
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
- cp_thing (compiler_error, 0, format, ap);
+ cp_thing ((errorfn *) compiler_error, 0, format, ap);
va_end (ap);
}
-DECLARE (cp_sprintf)
+void
+cp_deprecated (msg)
+ const char *msg;
{
+ extern int warn_deprecated;
+ if (!warn_deprecated)
+ return;
+ cp_warning ("%s is deprecated.", msg);
+ cp_warning ("Please see the documentation for details.");
+}
+
+void
+cp_sprintf VPROTO((const char *format, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
cp_thing ((errorfn *) sprintf, 0, format, ap);
va_end (ap);
}
-DECLARE (cp_error_at)
+void
+cp_error_at VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
cp_thing ((errorfn *) error_with_file_and_line, 1, format, ap);
va_end (ap);
}
-DECLARE (cp_warning_at)
+void
+cp_warning_at VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
cp_thing ((errorfn *) warning_with_file_and_line, 1, format, ap);
va_end (ap);
}
-DECLARE (cp_pedwarn_at)
+void
+cp_pedwarn_at VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
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 bb21bcb..4da1d2f 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, 94-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94-97, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -32,6 +32,7 @@ typedef char* cp_printer ();
#define C code_as_string
#define D decl_as_string
#define E expr_as_string
+#define F fndecl_as_string
#define L language_as_string
#define O op_as_string
#define P parm_as_string
@@ -47,7 +48,7 @@ cp_printer * cp_printers[256] =
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 */
+ o, A, o, C, D, E, F, 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 */
@@ -55,6 +56,7 @@ cp_printer * cp_printers[256] =
#undef C
#undef D
#undef E
+#undef F
#undef L
#undef O
#undef P
@@ -84,6 +86,11 @@ static char *scratch_firstobj;
OB_PUTCP (digit_buffer); } while (0)
# define OB_UNPUT(N) obstack_blank (&scratch_obstack, - (N));
+# define OB_END_TEMPLATE_ID() \
+ ((obstack_next_free (&scratch_obstack) != obstack_base (&scratch_obstack) \
+ && obstack_next_free (&scratch_obstack)[-1] == '>') \
+ ? OB_PUTC2 (' ', '>') : OB_PUTC ('>'))
+
# define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t)))
enum pad { none, before, after };
@@ -102,10 +109,13 @@ 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_qualifiers PROTO((tree, enum pad));
static void dump_char PROTO((int));
+static void dump_parameters PROTO((tree, int, int));
+static void dump_exception_spec PROTO((tree, int));
static char *aggr_variety PROTO((tree));
static tree ident_fndecl PROTO((tree));
+static int interesting_scope_p PROTO((tree));
void
init_error ()
@@ -114,20 +124,61 @@ init_error ()
scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
}
+/* Returns nonzero if SCOPE is something we want to print for random decls. */
+
+static int
+interesting_scope_p (scope)
+ tree scope;
+{
+ if (scope == NULL_TREE
+ || scope == global_namespace)
+ return 0;
+
+ return (TREE_CODE (scope) == NAMESPACE_DECL
+ || AGGREGATE_TYPE_P (scope));
+}
+
static void
-dump_readonly_or_volatile (t, p)
+dump_qualifiers (t, p)
tree t;
enum pad p;
{
- if (TYPE_READONLY (t) || TYPE_VOLATILE (t))
+ if (TYPE_QUALS (t))
{
if (p == before) OB_PUTC (' ');
- if (TYPE_READONLY (t))
- OB_PUTS ("const");
- if (TYPE_READONLY (t) && TYPE_VOLATILE (t))
- OB_PUTC (' ');
- if (TYPE_VOLATILE (t))
- OB_PUTS ("volatile");
+ switch (TYPE_QUALS (t))
+ {
+ case TYPE_QUAL_CONST:
+ OB_PUTS ("const");
+ break;
+
+ case TYPE_QUAL_VOLATILE:
+ OB_PUTS ("volatile");
+ break;
+
+ case TYPE_QUAL_RESTRICT:
+ OB_PUTS ("__restrict");
+ break;
+
+ case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
+ OB_PUTS ("const volatile");
+ break;
+
+ case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
+ OB_PUTS ("const __restrict");
+ break;
+
+ case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
+ OB_PUTS ("volatile __restrict");
+ break;
+
+ case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
+ OB_PUTS ("const volatile __restrict");
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
if (p == after) OB_PUTC (' ');
}
}
@@ -161,26 +212,8 @@ dump_type_real (t, v, canonical_name)
break;
case TREE_LIST:
- /* i.e. function taking no arguments */
- if (t != void_list_node)
- {
- 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), 0);
- }
- if (TREE_CHAIN (t))
- {
- if (TREE_CHAIN (t) != void_list_node)
- {
- OB_PUTC2 (',', ' ');
- dump_type_real (TREE_CHAIN (t), v, canonical_name);
- }
- }
- else OB_PUTS (" ...");
- }
+ /* A list of function parms. */
+ dump_parameters (t, 0, canonical_name);
break;
case IDENTIFIER_NODE:
@@ -197,8 +230,7 @@ dump_type_real (t, v, canonical_name)
if (TYPE_LANG_SPECIFIC (t)
&& (IS_SIGNATURE_POINTER (t) || IS_SIGNATURE_REFERENCE (t)))
{
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t, after);
+ dump_qualifiers (t, after);
dump_type_real (SIGNATURE_TYPE (t), v, canonical_name);
if (IS_SIGNATURE_POINTER (t))
OB_PUTC ('*');
@@ -211,6 +243,7 @@ dump_type_real (t, v, canonical_name)
case TYPE_DECL:
case TEMPLATE_DECL:
+ case NAMESPACE_DECL:
dump_decl (t, v);
break;
@@ -231,7 +264,7 @@ dump_type_real (t, v, canonical_name)
case BOOLEAN_TYPE:
{
tree type;
- dump_readonly_or_volatile (t, after);
+ dump_qualifiers (t, after);
type = canonical_name ? TYPE_MAIN_VARIANT (t) : t;
if (TYPE_NAME (type) && TYPE_IDENTIFIER (type))
OB_PUTID (TYPE_IDENTIFIER (type));
@@ -244,7 +277,7 @@ dump_type_real (t, v, canonical_name)
break;
case TEMPLATE_TEMPLATE_PARM:
- if (!CLASSTYPE_TEMPLATE_INFO (t))
+ if (!TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
{
/* For parameters inside template signature. */
if (TYPE_IDENTIFIER (t))
@@ -255,7 +288,7 @@ dump_type_real (t, v, canonical_name)
else
{
int i;
- tree args = CLASSTYPE_TI_ARGS (t);
+ tree args = TYPE_TI_ARGS (t);
OB_PUTID (TYPE_IDENTIFIER (t));
OB_PUTC ('<');
for (i = 0; i < TREE_VEC_LENGTH (args); i++)
@@ -269,12 +302,12 @@ dump_type_real (t, v, canonical_name)
if (i < TREE_VEC_LENGTH (args)-1)
OB_PUTC2 (',', ' ');
}
- OB_PUTC ('>');
+ OB_END_TEMPLATE_ID ();
}
break;
case TEMPLATE_TYPE_PARM:
- dump_readonly_or_volatile (t, after);
+ dump_qualifiers (t, after);
if (TYPE_IDENTIFIER (t))
OB_PUTID (TYPE_IDENTIFIER (t));
else
@@ -298,7 +331,13 @@ dump_type_real (t, v, canonical_name)
OB_PUTS ("typename ");
dump_type_real (TYPE_CONTEXT (t), 0, canonical_name);
OB_PUTS ("::");
- OB_PUTID (TYPE_IDENTIFIER (t));
+ dump_decl (TYPENAME_TYPE_FULLNAME (t), v);
+ break;
+
+ case TYPEOF_TYPE:
+ OB_PUTS ("__typeof (");
+ dump_expr (TYPE_FIELDS (t), 1);
+ OB_PUTC (')');
break;
default:
@@ -342,7 +381,7 @@ dump_aggr_type (t, v, canonical_name)
tree name;
char *variety = aggr_variety (t);
- dump_readonly_or_volatile (t, after);
+ dump_qualifiers (t, after);
if (v > 0)
{
@@ -352,7 +391,7 @@ dump_aggr_type (t, v, canonical_name)
name = TYPE_NAME (canonical_name ? TYPE_MAIN_VARIANT (t) : t);
- if (name && DECL_CONTEXT (name) && DECL_CONTEXT (name) != global_namespace)
+ if (name && CP_DECL_CONTEXT (name) != global_namespace)
{
/* FUNCTION_DECL or RECORD_TYPE */
dump_decl (DECL_CONTEXT (name), 0);
@@ -403,13 +442,14 @@ dump_type_prefix (t, v, canonical_name)
switch (TREE_CODE (t))
{
case POINTER_TYPE:
+ case REFERENCE_TYPE:
{
tree sub = TREE_TYPE (t);
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)
+ if (!TYPE_PTRMEM_P (t))
{
switch (TREE_CODE (sub))
{
@@ -424,42 +464,20 @@ dump_type_prefix (t, v, canonical_name)
case POINTER_TYPE:
/* We don't want "char * *" */
- if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub)))
+ if (TYPE_QUALS (sub) == TYPE_UNQUALIFIED)
break;
/* But we do want "char *const *" */
default:
OB_PUTC (' ');
}
- OB_PUTC ('*');
- dump_readonly_or_volatile (t, none);
- }
- }
- break;
-
- case REFERENCE_TYPE:
- {
- tree sub = TREE_TYPE (t);
- dump_type_prefix (sub, v, canonical_name);
-
- switch (TREE_CODE (sub))
- {
- case ARRAY_TYPE:
- OB_PUTC2 (' ', '(');
- break;
-
- case POINTER_TYPE:
- /* We don't want "char * &" */
- if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub)))
- break;
- /* But we do want "char *const &" */
-
- default:
- OB_PUTC (' ');
+ if (TREE_CODE (t) == POINTER_TYPE)
+ OB_PUTC ('*');
+ else
+ OB_PUTC ('&');
+ dump_qualifiers (t, none);
}
}
- OB_PUTC ('&');
- dump_readonly_or_volatile (t, none);
break;
case OFFSET_TYPE:
@@ -472,7 +490,7 @@ dump_type_prefix (t, v, canonical_name)
OB_PUTC2 (':', ':');
}
OB_PUTC ('*');
- dump_readonly_or_volatile (t, none);
+ dump_qualifiers (t, none);
break;
/* Can only be reached through function pointer -- this would not be
@@ -543,20 +561,20 @@ dump_type_suffix (t, v, canonical_name)
case METHOD_TYPE:
{
tree arg;
- OB_PUTC2 (')', '(');
+ OB_PUTC (')');
arg = TYPE_ARG_TYPES (t);
if (TREE_CODE (t) == METHOD_TYPE)
arg = TREE_CHAIN (arg);
- if (arg)
- dump_type (arg, v);
- else
- OB_PUTS ("...");
- OB_PUTC (')');
+ /* Function pointers don't have default args. Not in standard C++,
+ anyway; they may in g++, but we'll just pretend otherwise. */
+ dump_parameters (arg, 0, canonical_name);
+
if (TREE_CODE (t) == METHOD_TYPE)
- dump_readonly_or_volatile
+ dump_qualifiers
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before);
dump_type_suffix (TREE_TYPE (t), v, canonical_name);
+ dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), canonical_name);
break;
}
@@ -571,7 +589,7 @@ dump_type_suffix (t, v, canonical_name)
else
dump_expr (fold (build_binary_op
(PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)),
- integer_one_node, 1)), 0);
+ integer_one_node)), 0);
}
OB_PUTC (']');
dump_type_suffix (TREE_TYPE (t), v, canonical_name);
@@ -666,12 +684,11 @@ dump_simple_decl (t, type, v)
{
dump_type_prefix (type, v, 0);
OB_PUTC (' ');
- dump_readonly_or_volatile (t, after);
}
- if (DECL_CLASS_SCOPE_P (t))
+ if (interesting_scope_p (DECL_CONTEXT (t)))
{
- dump_type (DECL_CONTEXT (t), 0);
- OB_PUTC2 (':', ':');
+ dump_decl (DECL_CONTEXT (t), 0);
+ OB_PUTC2 (':',':');
}
if (DECL_NAME (t))
dump_decl (DECL_NAME (t), v);
@@ -718,7 +735,13 @@ dump_decl (t, v)
if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
{
OB_PUTS ("vtable for ");
- dump_type (DECL_CONTEXT (t), v);
+ if (TYPE_P (DECL_CONTEXT (t)))
+ dump_type (DECL_CONTEXT (t), v);
+ else
+ /* This case can arise with -fno-vtable-thunks. See
+ expand_upcast_fixups. It's not clear what to print
+ here. */
+ OB_PUTS ("{unknown type}");
break;
}
/* else fall through */
@@ -728,12 +751,15 @@ dump_decl (t, v)
break;
case NAMESPACE_DECL:
- if (DECL_CONTEXT (t) != global_namespace)
+ if (CP_DECL_CONTEXT (t) != global_namespace)
{
dump_decl (DECL_CONTEXT (t), v);
OB_PUTC2 (':',':');
}
- OB_PUTID (DECL_NAME (t));
+ if (DECL_NAME (t) == anonymous_namespace_name)
+ OB_PUTS ("{anonymous}");
+ else
+ OB_PUTID (DECL_NAME (t));
break;
case SCOPE_REF:
@@ -790,6 +816,10 @@ dump_decl (t, v)
}
break;
+ case OVERLOAD:
+ t = OVL_CURRENT (t);
+ /* Fall through. */
+
case FUNCTION_DECL:
if (GLOBAL_IORD_P (DECL_ASSEMBLER_NAME (t)))
dump_global_iord (DECL_ASSEMBLER_NAME (t));
@@ -843,12 +873,15 @@ dump_decl (t, v)
}
if (len != 0)
OB_UNPUT (2);
- OB_PUTC2 ('>', ' ');
+ OB_END_TEMPLATE_ID ();
+ OB_PUTC (' ');
}
nreverse(orig_args);
if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
dump_type (TREE_TYPE (t), v);
+ else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
+ dump_decl (DECL_TEMPLATE_RESULT (t), v);
else if (TREE_TYPE (t) == NULL_TREE)
my_friendly_abort (353);
else switch (NEXT_CODE (t))
@@ -883,7 +916,7 @@ dump_decl (t, v)
if (TREE_CHAIN (args))
OB_PUTC2 (',', ' ');
}
- OB_PUTC ('>');
+ OB_END_TEMPLATE_ID ();
}
break;
@@ -921,9 +954,15 @@ dump_decl (t, v)
}
}
-/* Pretty printing for announce_function. T is the declaration of the
- function we are interested in seeing. V is non-zero if we should print
- the type that this function returns. */
+/* Pretty print a function decl. There are several ways we want to print a
+ function declaration. We use V to tell us what.
+ V - 01 23
+ args - ++ ++
+ retval - -+ ++
+ default- -+ -+
+ throw - -- ++
+ As cp_error can only apply the '#' flag once to give 0 and 1 for V, there
+ is %D which doesn't print the throw specs, and %F which does. */
static void
dump_function_decl (t, v)
@@ -943,28 +982,28 @@ dump_function_decl (t, v)
parmtypes = TYPE_ARG_TYPES (fntype);
/* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT. */
- if (DECL_CONTEXT (t))
+ if (DECL_CLASS_SCOPE_P (t))
cname = DECL_CLASS_CONTEXT (t);
/* this is for partially instantiated template methods */
else if (TREE_CODE (fntype) == METHOD_TYPE)
cname = TREE_TYPE (TREE_VALUE (parmtypes));
- v = (v > 0);
-
- if (v)
+ /* Print the return type. */
+ if (v > 0)
{
if (DECL_STATIC_FUNCTION_P (t))
OB_PUTS ("static ");
- if (! IDENTIFIER_TYPENAME_P (name)
+ if (! DECL_CONV_FN_P (t)
&& ! DECL_CONSTRUCTOR_P (t)
- && ! DESTRUCTOR_NAME_P (name))
+ && ! DECL_DESTRUCTOR_P (t))
{
dump_type_prefix (TREE_TYPE (fntype), 1, 0);
OB_PUTC (' ');
}
}
+ /* Print the function name. */
if (cname)
{
dump_type (cname, 0);
@@ -975,34 +1014,98 @@ dump_function_decl (t, v)
/* Skip past "in_charge" identifier. */
parmtypes = TREE_CHAIN (parmtypes);
}
+ else if (CP_DECL_CONTEXT (t) != global_namespace)
+ {
+ dump_decl (DECL_CONTEXT (t), 0);
+ OB_PUTC2 (':',':');
+ }
if (DESTRUCTOR_NAME_P (name) && DECL_LANGUAGE (t) == lang_cplusplus)
parmtypes = TREE_CHAIN (parmtypes);
dump_function_name (t);
-
- OB_PUTC ('(');
-
- if (parmtypes)
- dump_type (parmtypes, v);
- else
- OB_PUTS ("...");
- OB_PUTC (')');
+ /* If V is negative, we don't print the argument types. */
+ if (v < 0)
+ return;
- if (v && ! IDENTIFIER_TYPENAME_P (name))
+ dump_parameters (parmtypes, v & 1, 0);
+
+ if (v && ! DECL_CONV_FN_P (t))
dump_type_suffix (TREE_TYPE (fntype), 1, 0);
if (TREE_CODE (fntype) == METHOD_TYPE)
{
if (IS_SIGNATURE (cname))
/* We look at the type pointed to by the `optr' field of `this.' */
- dump_readonly_or_volatile
+ dump_qualifiers
(TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (TYPE_ARG_TYPES (fntype))))), before);
else
- dump_readonly_or_volatile
+ dump_qualifiers
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))), before);
}
+
+ if (v >= 2)
+ dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), 0);
+}
+
+/* Print a parameter list. V indicates if we show default values or not. If
+ these are for a member function, the member object ptr
+ (and any other hidden args) should have already been removed. */
+
+static void
+dump_parameters (parmtypes, v, canonical_name)
+ tree parmtypes;
+ int v;
+ int canonical_name;
+{
+ int first;
+ OB_PUTC ('(');
+
+ for (first = 1; parmtypes != void_list_node;
+ parmtypes = TREE_CHAIN (parmtypes))
+ {
+ if (!first)
+ OB_PUTC2 (',', ' ');
+ first = 0;
+ if (!parmtypes)
+ {
+ OB_PUTS ("...");
+ break;
+ }
+ dump_type_real (TREE_VALUE (parmtypes), 0, canonical_name);
+
+ if (TREE_PURPOSE (parmtypes) && v)
+ {
+ OB_PUTS (" = ");
+ dump_expr (TREE_PURPOSE (parmtypes), 0);
+ }
+ }
+
+ OB_PUTC (')');
+}
+
+/* Print an exception specification. T is the exception specification. */
+
+static void
+dump_exception_spec (t, canonical_name)
+ tree t;
+ int canonical_name;
+{
+ if (t)
+ {
+ OB_PUTS (" throw (");
+ if (TREE_VALUE (t) != NULL_TREE)
+ while (1)
+ {
+ dump_type_real (TREE_VALUE (t), 0, canonical_name);
+ t = TREE_CHAIN (t);
+ if (!t)
+ break;
+ OB_PUTC2 (',', ' ');
+ }
+ OB_PUTC (')');
+ }
}
/* Handle the function name for a FUNCTION_DECL node, grokking operators
@@ -1014,15 +1117,12 @@ dump_function_name (t)
{
tree name = DECL_NAME (t);
- /* There ought to be a better way to find out whether or not something is
- a destructor. */
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t))
- && DECL_LANGUAGE (t) == lang_cplusplus)
+ if (DECL_DESTRUCTOR_P (t))
{
OB_PUTC ('~');
dump_decl (name, 0);
}
- else if (IDENTIFIER_TYPENAME_P (name))
+ else if (DECL_CONV_FN_P (t))
{
/* This cannot use the hack that the operator's return
type is stashed off of its name because it may be
@@ -1042,91 +1142,75 @@ dump_function_name (t)
else
dump_decl (name, 0);
- if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t))
+ if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t)
+ && DECL_TEMPLATE_INFO (t)
+ && (DECL_TEMPLATE_SPECIALIZATION (t)
+ || TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL
+ || DECL_TEMPLATE_SPECIALIZATION (DECL_TI_TEMPLATE (t))
+ || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
{
tree args = DECL_TEMPLATE_INFO (t) ? DECL_TI_ARGS (t) : NULL_TREE;
+ OB_PUTC ('<');
- 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
+ /* Be careful only to print things when we have them, so as not
+ to crash producing error messages. */
+ if (args)
{
- 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)
{
- if (TREE_CODE (args) == TREE_LIST)
+ tree arg;
+ int need_comma = 0;
+
+ for (arg = args; arg; arg = TREE_CHAIN (arg))
{
- 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);
- }
+ tree a = TREE_VALUE (arg);
+
+ if (need_comma)
+ OB_PUTS (", ");
- need_comma = 1;
+ 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)
+ }
+ 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++)
{
- 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);
- }
+ tree a = TREE_VEC_ELT (args, i);
+
+ if (need_comma)
+ OB_PUTS (", ");
- need_comma = 1;
+ 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 ('>');
}
+ OB_END_TEMPLATE_ID ();
}
}
@@ -1278,6 +1362,13 @@ dump_expr (t, nop)
OB_PUTCP (digit_buffer);
break;
+ case PTRMEM_CST:
+ OB_PUTC ('&');
+ dump_type (PTRMEM_CST_CLASS (t), 0);
+ OB_PUTS ("::");
+ OB_PUTID (DECL_NAME (PTRMEM_CST_MEMBER (t)));
+ break;
+
case STRING_CST:
{
char *p = TREE_STRING_POINTER (t);
@@ -1310,7 +1401,6 @@ dump_expr (t, nop)
{
OB_PUTS ("new ");
dump_type (TREE_TYPE (TREE_TYPE (t)), 0);
- PARM_DECL_EXPR (t) = 1;
}
else
{
@@ -1485,6 +1575,7 @@ dump_expr (t, nop)
else
{
if (TREE_OPERAND (t,0) != NULL_TREE
+ && TREE_TYPE (TREE_OPERAND (t, 0))
&& NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
dump_expr (TREE_OPERAND (t, 0), nop);
else
@@ -1544,11 +1635,20 @@ dump_expr (t, nop)
if (integer_all_onesp (idx))
{
tree pfn = PFN_FROM_PTRMEMFUNC (t);
- dump_expr (pfn, 0);
+ dump_unary_op ("&", pfn, 0);
break;
}
- if (TREE_CODE (idx) == INTEGER_CST
- && TREE_INT_CST_HIGH (idx) == 0)
+ else if (TREE_CODE (idx) == INTEGER_CST
+ && tree_int_cst_equal (idx, integer_zero_node))
+ {
+ /* A NULL pointer-to-member constant. */
+ OB_PUTS ("((");
+ dump_type (TREE_TYPE (t), 0);
+ OB_PUTS (") 0)");
+ break;
+ }
+ else if (TREE_CODE (idx) == INTEGER_CST
+ && TREE_INT_CST_HIGH (idx) == 0)
{
tree virtuals;
unsigned HOST_WIDE_INT n;
@@ -1583,15 +1683,29 @@ dump_expr (t, nop)
case OFFSET_REF:
{
tree ob = TREE_OPERAND (t, 0);
- if (TREE_CODE (ob) == NOP_EXPR
- && TREE_OPERAND (ob, 0) == error_mark_node
- && TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
- /* A::f */
- dump_expr (TREE_OPERAND (t, 1), 0);
+ if (is_dummy_object (ob))
+ {
+ t = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == FUNCTION_DECL)
+ /* A::f */
+ dump_expr (t, 0);
+ else if (BASELINK_P (t))
+ dump_expr (OVL_CURRENT (TREE_VALUE (t)), 0);
+ else
+ dump_decl (t, 0);
+ }
else
{
- dump_expr (TREE_OPERAND (t, 0), 0);
- OB_PUTS (" .* ");
+ if (TREE_CODE (ob) == INDIRECT_REF)
+ {
+ dump_expr (TREE_OPERAND (ob, 0), 0);
+ OB_PUTS (" ->* ");
+ }
+ else
+ {
+ dump_expr (ob, 0);
+ OB_PUTS (" .* ");
+ }
dump_expr (TREE_OPERAND (t, 1), 0);
}
break;
@@ -1666,6 +1780,10 @@ dump_expr (t, nop)
dump_expr (TREE_OPERAND (t, 0), nop);
break;
+ case TEMPLATE_ID_EXPR:
+ dump_decl (t, 0);
+ break;
+
case TREE_LIST:
if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
{
@@ -1714,12 +1832,20 @@ dump_unary_op (opstring, t, nop)
if (!nop) OB_PUTC (')');
}
+/* Print a function decl with exception specification included. */
+
char *
-fndecl_as_string (fndecl, print_ret_type_p)
+fndecl_as_string (fndecl, print_default_args_p)
tree fndecl;
- int print_ret_type_p;
+ int print_default_args_p;
{
- return decl_as_string (fndecl, print_ret_type_p);
+ OB_INIT ();
+
+ dump_function_decl (fndecl, 2 + print_default_args_p);
+
+ OB_FINISH ();
+
+ return (char *)obstack_base (&scratch_obstack);
}
/* Same, but handle a _TYPE.
@@ -1825,6 +1951,8 @@ cp_file_of (t)
return DECL_SOURCE_FILE (DECL_CONTEXT (t));
else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
return DECL_SOURCE_FILE (TYPE_MAIN_DECL (t));
+ else if (TREE_CODE (t) == OVERLOAD)
+ return DECL_SOURCE_FILE (OVL_FUNCTION (t));
else
return DECL_SOURCE_FILE (t);
}
@@ -1836,11 +1964,14 @@ cp_line_of (t)
int line = 0;
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))
+ if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)
+ && TYPE_MAIN_DECL (TREE_TYPE (t)))
t = TREE_TYPE (t);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
line = DECL_SOURCE_LINE (TYPE_MAIN_DECL (t));
+ else if (TREE_CODE (t) == OVERLOAD)
+ line = DECL_SOURCE_LINE (OVL_FUNCTION (t));
else
line = DECL_SOURCE_LINE (t);
@@ -1954,7 +2085,7 @@ cv_as_string (p, v)
{
OB_INIT ();
- dump_readonly_or_volatile (p, before);
+ dump_qualifiers (p, before);
OB_FINISH ();
diff --git a/contrib/gcc/cp/except.c b/contrib/gcc/cp/except.c
index d294497..9e2d6af 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, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1989, 92-97, 1998, 1999 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.
@@ -52,12 +52,13 @@ 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));
+#if 0
static tree get_eh_type PROTO((void));
static tree get_eh_caught PROTO((void));
static tree get_eh_handlers PROTO((void));
+#endif
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));
@@ -248,14 +249,14 @@ call_eh_info ()
{
tree fn;
- fn = get_identifier ("__cp_eh_info");
+ fn = get_identifier ("__start_cp_handler");
if (IDENTIFIER_GLOBAL_VALUE (fn))
fn = IDENTIFIER_GLOBAL_VALUE (fn);
else
{
tree t1, t, fields[7];
- /* Declare cp_eh_info * __cp_eh_info (void),
+ /* Declare cp_eh_info * __start_cp_handler (void),
as defined in exception.cc. */
push_obstacks_nochange ();
end_temporary_allocation ();
@@ -269,9 +270,11 @@ call_eh_info ()
get_identifier ("dynamic_handler_chain"), ptr_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL,
get_identifier ("info"), ptr_type_node);
+ fields[3] = build_lang_field_decl (FIELD_DECL,
+ get_identifier ("table_index"), 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);
+ finish_builtin_type (t1, "eh_context", fields, 3, ptr_type_node);
t1 = build_pointer_type (t1);
t1= make_lang_type (RECORD_TYPE);
@@ -315,9 +318,9 @@ call_eh_info ()
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
return build_function_call (fn, NULL_TREE);
}
@@ -360,6 +363,7 @@ get_eh_value ()
/* Returns a reference to the current exception type. */
+#if 0
static tree
get_eh_type ()
{
@@ -386,6 +390,7 @@ get_eh_handlers ()
return build_component_ref (get_eh_info (), get_identifier ("handlers"),
NULL_TREE, 0);
}
+#endif
/* Build a type value for use at runtime for a type that is matched
against by the exception handling system. */
@@ -394,7 +399,7 @@ static tree
build_eh_type_type (type)
tree type;
{
- char *typestring;
+ const char *typestring;
tree exp;
if (type == error_mark_node)
@@ -408,9 +413,7 @@ build_eh_type_type (type)
type = TYPE_MAIN_VARIANT (type);
if (flag_rtti)
- {
- return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
- }
+ return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));
typestring = build_overload_name (type, 1, 1);
exp = combine_strings (build_string (strlen (typestring)+1, typestring));
@@ -424,7 +427,7 @@ static tree
build_eh_type_type_ref (type)
tree type;
{
- char *typestring;
+ const char *typestring;
tree exp;
if (type == error_mark_node)
@@ -528,10 +531,10 @@ do_pop_exception ()
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
/* 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
@@ -546,9 +549,6 @@ 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 ());
@@ -597,135 +597,14 @@ expand_start_catch_block (declspecs, declarator)
if (! doing_eh (1))
return;
- if (flag_new_exceptions)
- process_start_catch_block (declspecs, declarator);
- else
- process_start_catch_block_old (declspecs, declarator);
+ process_start_catch_block (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 ();
- 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;
-
- /* 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);
-
- exp = expr_tree_cons (NULL_TREE,
- build_eh_type_type (TREE_TYPE (decl)),
- 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);
-
- return_value_rtx = hard_function_value (ptr_type_node, exp);
-
- /* did the throw type match function return TRUE? */
- emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
- GET_MODE (return_value_rtx), 0, 0);
-
- /* if it returned FALSE, jump over the catch block, else fall into it */
- emit_jump_insn (gen_beq (false_label_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 ());
- }
-
- /* Let `cp_finish_decl' know that this initializer is ok. */
- DECL_INITIAL (decl) = init;
- decl = pushdecl (decl);
-
- start_decl_1 (decl);
- cp_finish_decl (decl, DECL_INITIAL (decl),
- 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. */
- }
-
- 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. */
+ nothing additional. */
static void
process_start_catch_block (declspecs, declarator)
@@ -806,7 +685,9 @@ process_start_catch_block (declspecs, declarator)
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, init, NULL_TREE, 0,
+ LOOKUP_ONLYCONVERTING|DIRECT_BIND);
}
else
{
@@ -819,14 +700,10 @@ process_start_catch_block (declspecs, declarator)
/* Fall into the catch all section. */
}
- 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. */
@@ -850,10 +727,7 @@ expand_end_catch_block ()
documentation. */
expand_goto (top_label_entry (&caught_return_label_stack));
- /* label we emit to jump to if this catch block didn't match. */
- /* This the closing } in the `if (eq) {' of the documentation. */
- if (! flag_new_exceptions)
- emit_label (pop_label_entry (&false_label_stack));
+ end_catch_handler ();
}
/* An exception spec is implemented more or less like:
@@ -895,7 +769,7 @@ expand_end_eh_spec (raises)
TREE_HAS_CONSTRUCTOR (types) = 1;
/* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
- tmp = build_array_type (const_ptr_type_node, NULL_TREE);
+ tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);
decl = build_decl (VAR_DECL, NULL_TREE, tmp);
DECL_ARTIFICIAL (decl) = 1;
DECL_INITIAL (decl) = types;
@@ -923,10 +797,10 @@ expand_end_eh_spec (raises)
TREE_THIS_VOLATILE (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
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);
@@ -1065,10 +939,10 @@ alloc_eh_object (type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
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);
@@ -1118,11 +992,8 @@ expand_throw (exp)
pop_obstacks ();
}
- if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
- {
- throw_type = build_eh_type (exp);
- exp = build_reinterpret_cast (ptr_type_node, exp);
- }
+ if (TYPE_PTR_P (TREE_TYPE (exp)))
+ throw_type = build_eh_type (exp);
else
{
tree object, ptr;
@@ -1153,13 +1024,11 @@ expand_throw (exp)
ourselves into expand_call. */
if (TREE_SIDE_EFFECTS (exp))
{
- tree temp = build (VAR_DECL, TREE_TYPE (exp));
+ tree temp = build_decl (VAR_DECL, NULL_TREE, 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));
+ DECL_INITIAL (temp) = exp;
+ cp_finish_decl (temp, exp, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
exp = temp;
}
#endif
@@ -1196,6 +1065,10 @@ expand_throw (exp)
exp = ptr;
}
+ /* Cast EXP to `void *' so that it will match the prototype for
+ __cp_push_exception. */
+ exp = convert (ptr_type_node, exp);
+
if (cleanup == NULL_TREE)
{
cleanup = build_int_2 (0, 0);
@@ -1223,10 +1096,10 @@ expand_throw (exp)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
e = expr_tree_cons (NULL_TREE, exp, expr_tree_cons
(NULL_TREE, throw_type, expr_tree_cons
(NULL_TREE, cleanup, NULL_TREE)));
@@ -1254,10 +1127,10 @@ expand_throw (exp)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
exp = build_function_call (fn, NULL_TREE);
expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
@@ -1277,11 +1150,8 @@ build_throw (e)
if (processing_template_decl)
return build_min (THROW_EXPR, void_type_node, e);
- if (! flag_ansi && e == null_node)
- {
- cp_warning ("throwing NULL");
- e = integer_zero_node;
- }
+ if (e == null_node)
+ cp_warning ("throwing NULL, which has integral, not pointer type");
e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1;
diff --git a/contrib/gcc/cp/exception.cc b/contrib/gcc/cp/exception.cc
index 4c10404..8e8f35f 100644
--- a/contrib/gcc/cp/exception.cc
+++ b/contrib/gcc/cp/exception.cc
@@ -1,5 +1,5 @@
// Functions for Exception Support for -*- C++ -*-
-// Copyright (C) 1994, 1995, 1996, 1998 Free Software Foundation
+// Copyright (C) 1994, 95-97, 1998 Free Software Foundation
// This file is part of GNU CC.
@@ -30,6 +30,7 @@
#include "typeinfo"
#include "exception"
#include <stddef.h>
+#include "gansidecl.h" /* Needed to support macros used in eh-common.h. */
#include "eh-common.h"
/* Define terminate, unexpected, set_terminate, set_unexpected as
@@ -116,13 +117,29 @@ __cp_exception_info (void)
return &((*__get_eh_info ())->value);
}
-/* Compiler hook to return a pointer to the info for the current exception.
+#define CP_EH_INFO ((cp_eh_info *) *__get_eh_info ())
+
+/* Old 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 ();
+ cp_eh_info *p = CP_EH_INFO;
+ return p;
+}
+
+/* Compiler hook to return a pointer to the info for the current exception,
+ Set the caught bit, and increment the number of handlers that are
+ looking at this exception. This makes handlers smaller. */
+
+extern "C" cp_eh_info *
+__start_cp_handler (void)
+{
+ cp_eh_info *p = CP_EH_INFO;
+ p->caught = 1;
+ p->handlers++;
+ return p;
}
/* Allocate a buffer for a cp_eh_info and an exception object of size SIZE,
@@ -157,7 +174,9 @@ __cplus_type_matcher (cp_eh_info *info, rtimetype match_info,
{
void *ret;
- if (exception_table->lang.language != EH_LANG_C_plus_plus)
+ /* No exception table implies the old style mechanism, so don't check. */
+ if (exception_table != NULL
+ && exception_table->lang.language != EH_LANG_C_plus_plus)
return NULL;
if (match_info == CATCH_ALL_TYPE)
@@ -231,7 +250,7 @@ __cp_pop_exception (cp_eh_info *p)
p->cleanup (p->value, 2);
if (! __is_pointer (p->type))
- __eh_free (p->value);
+ __eh_free (p->original_value); // value may have been co-erced.
__eh_free (p);
}
@@ -239,7 +258,7 @@ __cp_pop_exception (cp_eh_info *p)
extern "C" void
__uncatch_exception (void)
{
- cp_eh_info *p = __cp_eh_info ();
+ cp_eh_info *p = CP_EH_INFO;
if (p == 0)
terminate ();
p->caught = false;
@@ -260,7 +279,7 @@ __uncatch_exception (void)
extern "C" void
__check_eh_spec (int n, const void **spec)
{
- cp_eh_info *p = __cp_eh_info ();
+ cp_eh_info *p = CP_EH_INFO;
for (int i = 0; i < n; ++i)
{
@@ -313,7 +332,7 @@ __throw_bad_typeid (void)
bool
std::uncaught_exception ()
{
- cp_eh_info *p = __cp_eh_info ();
+ cp_eh_info *p = CP_EH_INFO;
return p && ! p->caught;
}
diff --git a/contrib/gcc/cp/expr.c b/contrib/gcc/cp/expr.c
index 4c3d8b6..83bdff9 100644
--- a/contrib/gcc/cp/expr.c
+++ b/contrib/gcc/cp/expr.c
@@ -1,6 +1,6 @@
/* Convert language-specific tree expression to rtl instructions,
for GNU compiler.
- Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -36,6 +36,62 @@ static tree extract_scalar_init PROTO((tree, tree));
static rtx cplus_expand_expr PROTO((tree, rtx, enum machine_mode,
enum expand_modifier));
+/* Hook used by output_constant to expand language-specific
+ constants. */
+
+static tree
+cplus_expand_constant (cst)
+ tree cst;
+{
+ switch (TREE_CODE (cst))
+ {
+ case PTRMEM_CST:
+ {
+ tree type = TREE_TYPE (cst);
+ tree member;
+ tree offset;
+
+ /* Find the member. */
+ member = PTRMEM_CST_MEMBER (cst);
+
+ if (TREE_CODE (member) == FIELD_DECL)
+ {
+ /* Find the offset for the field. */
+ offset = convert (sizetype,
+ size_binop (EASY_DIV_EXPR,
+ DECL_FIELD_BITPOS (member),
+ size_int (BITS_PER_UNIT)));
+
+ /* 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));
+
+ cst = cp_convert (type, offset);
+ }
+ else
+ {
+ tree delta;
+ tree idx;
+ tree pfn;
+ tree delta2;
+
+ expand_ptrmemfunc_cst (cst, &delta, &idx, &pfn, &delta2);
+
+ cst = build_ptrmemfunc1 (type, delta, idx,
+ pfn, delta2);
+ }
+ }
+ break;
+
+ default:
+ /* There's nothing to do. */
+ break;
+ }
+
+ return cst;
+}
+
/* Hook used by expand_expr to expand language-specific tree codes. */
static rtx
@@ -148,7 +204,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
init = convert_from_reference (init);
flag_access_control = 0;
- expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
+ expand_aggr_init (slot, init, LOOKUP_ONLYCONVERTING);
flag_access_control = old_ac;
if (TYPE_NEEDS_DESTRUCTOR (type))
@@ -162,19 +218,14 @@ cplus_expand_expr (exp, target, tmode, modifier)
return DECL_RTL (slot);
}
+ case PTRMEM_CST:
+ return expand_expr (cplus_expand_constant (exp),
+ target, tmode, modifier);
+
case OFFSET_REF:
{
-#if 1
return expand_expr (default_conversion (resolve_offset_ref (exp)),
target, tmode, EXPAND_NORMAL);
-#else
- /* This is old crusty code, and does not handle all that the
- resolve_offset_ref function does. (mrs) */
- tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
- tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
- return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
- target, tmode, EXPAND_NORMAL);
-#endif
}
case THUNK_DECL:
@@ -189,7 +240,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
(expand_vec_init
(NULL_TREE, TREE_OPERAND (exp, 0),
build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2),
- integer_one_node, 1),
+ integer_one_node),
TREE_OPERAND (exp, 1), 0), target, tmode, modifier);
case NEW_EXPR:
@@ -207,6 +258,7 @@ void
init_cplus_expand ()
{
lang_expand_expr = cplus_expand_expr;
+ lang_expand_constant = cplus_expand_constant;
}
/* If DECL had its rtl moved from where callers expect it
@@ -304,7 +356,7 @@ extract_scalar_init (decl, init)
int
extract_init (decl, init)
- tree decl, init;
+ tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED;
{
return 0;
@@ -405,8 +457,5 @@ do_case (start, end)
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);
+ define_case_label ();
}
diff --git a/contrib/gcc/cp/friend.c b/contrib/gcc/cp/friend.c
index 58747ef..5085ebc 100644
--- a/contrib/gcc/cp/friend.c
+++ b/contrib/gcc/cp/friend.c
@@ -1,5 +1,5 @@
/* Help friends in C++.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -27,11 +27,10 @@ Boston, MA 02111-1307, USA. */
#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. */
+/* Returns non-zero if SUPPLICANT is a friend of TYPE. */
+
int
is_friend (type, supplicant)
tree type, supplicant;
@@ -59,32 +58,40 @@ is_friend (type, supplicant)
for (; list ; list = TREE_CHAIN (list))
{
- if (name == TREE_PURPOSE (list))
+ if (name == FRIEND_NAME (list))
{
- tree friends = TREE_VALUE (list);
+ tree friends = FRIEND_DECLS (list);
for (; friends ; friends = TREE_CHAIN (friends))
{
- if (comptypes (ctype, TREE_PURPOSE (friends), 1))
+ if (same_type_p (ctype, TREE_PURPOSE (friends)))
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))
+ if (supplicant == TREE_VALUE (friends))
+ return 1;
+
+ /* With -fguiding-decls we are more lenient about
+ friendship. This is bogus in general since two
+ specializations of a template with non-type
+ template parameters may have the same type, but
+ be different.
+
+ Temporarily, we are also more lenient to deal
+ with nested friend functions, for which there can
+ be more than one FUNCTION_DECL, despite being the
+ same function. When that's fixed, the
+ FUNCTION_MEMBER_P bit can go. */
+ if ((flag_guiding_decls
+ || DECL_FUNCTION_MEMBER_P (supplicant))
+ && same_type_p (TREE_TYPE (supplicant),
+ TREE_TYPE (TREE_VALUE (friends))))
+ return 1;
+
+ if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL
+ && is_specialization_of (supplicant,
+ TREE_VALUE (friends)))
return 1;
}
break;
@@ -104,7 +111,7 @@ is_friend (type, supplicant)
if (TREE_CODE (t) == TEMPLATE_DECL ?
is_specialization_of (TYPE_MAIN_DECL (supplicant), t) :
- comptypes (supplicant, t, 1))
+ same_type_p (supplicant, t))
return 1;
}
}
@@ -130,19 +137,27 @@ is_friend (type, supplicant)
/* Add a new friend to the friends of the aggregate type TYPE.
DECL is the FUNCTION_DECL of the friend being added. */
-static void
+void
add_friend (type, decl)
tree type, decl;
{
- tree typedecl = TYPE_MAIN_DECL (type);
- tree list = DECL_FRIENDLIST (typedecl);
- tree name = DECL_NAME (decl);
+ tree typedecl;
+ tree list;
+ tree name;
+
+ if (decl == error_mark_node)
+ return;
+
+ typedecl = TYPE_MAIN_DECL (type);
+ list = DECL_FRIENDLIST (typedecl);
+ name = DECL_NAME (decl);
+ type = TREE_TYPE (typedecl);
while (list)
{
- if (name == TREE_PURPOSE (list))
+ if (name == FRIEND_NAME (list))
{
- tree friends = TREE_VALUE (list);
+ tree friends = FRIEND_DECLS (list);
for (; friends ; friends = TREE_CHAIN (friends))
{
if (decl == TREE_VALUE (friends))
@@ -160,27 +175,20 @@ add_friend (type, decl)
}
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;
- }
- }
+ if (!uses_template_parms (type))
+ DECL_BEFRIENDING_CLASSES (decl)
+ = tree_cons (NULL_TREE, type,
+ DECL_BEFRIENDING_CLASSES (decl));
}
/* Declare that every member function NAME in FRIEND_TYPE
(which may be NULL_TREE) is a friend of type TYPE. */
-static void
+void
add_friends (type, name, friend_type)
tree type, name, friend_type;
{
@@ -189,9 +197,9 @@ add_friends (type, name, friend_type)
while (list)
{
- if (name == TREE_PURPOSE (list))
+ if (name == FRIEND_NAME (list))
{
- tree friends = TREE_VALUE (list);
+ tree friends = FRIEND_DECLS (list);
while (friends && TREE_PURPOSE (friends) != friend_type)
friends = TREE_CHAIN (friends);
if (friends)
@@ -216,13 +224,6 @@ add_friends (type, name, friend_type)
= 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
@@ -247,18 +248,31 @@ make_friend_class (type, friend_type)
error ("`friend' declaration in signature definition");
return;
}
- if (IS_SIGNATURE (friend_type))
+ if (IS_SIGNATURE (friend_type) || ! IS_AGGR_TYPE (friend_type))
{
- error ("signature type `%s' declared `friend'",
- IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type)));
+ cp_error ("invalid type `%T' declared `friend'", friend_type);
return;
}
+
+ if (CLASS_TYPE_P (friend_type)
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
+ && uses_template_parms (friend_type))
+ {
+ /* [temp.friend]
+
+ Friend declarations shall not declare partial
+ specializations. */
+ cp_error ("partial specialization `%T' declared `friend'",
+ 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))
+ else if (same_type_p (type, friend_type))
{
pedwarn ("class `%s' is implicitly friends with itself",
TYPE_NAME_STRING (type));
@@ -277,7 +291,7 @@ make_friend_class (type, friend_type)
/* 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)))
+ same_type_p (TREE_VALUE (classes), friend_type)))
classes = TREE_CHAIN (classes);
if (classes)
cp_warning ("`%T' is already a friend of `%T'",
@@ -286,6 +300,12 @@ make_friend_class (type, friend_type)
{
CLASSTYPE_FRIEND_CLASSES (type)
= tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
+ if (is_template_friend)
+ friend_type = TREE_TYPE (friend_type);
+ if (!uses_template_parms (type))
+ CLASSTYPE_BEFRIENDING_CLASSES (friend_type)
+ = tree_cons (NULL_TREE, type,
+ CLASSTYPE_BEFRIENDING_CLASSES (friend_type));
}
}
@@ -310,13 +330,15 @@ make_friend_class (type, friend_type)
pointed to by `this'. */
tree
-do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
- tree ctype, declarator, decl, parmdecls;
+do_friend (ctype, declarator, decl, parmdecls, attrlist,
+ flags, quals, funcdef_flag)
+ tree ctype, declarator, decl, parmdecls, attrlist;
enum overload_flags flags;
tree quals;
int funcdef_flag;
{
int is_friend_template = 0;
+ tree prefix_attributes, attributes;
/* Every decl that gets here is a friend of something. */
DECL_FRIEND_P (decl) = 1;
@@ -330,9 +352,10 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
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 (TREE_CODE (decl) != FUNCTION_DECL)
+ my_friendly_abort (990513);
+
+ is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P ();
if (ctype)
{
@@ -341,62 +364,35 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
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, decl, flags, quals);
+
+ if (is_friend_template)
+ decl = DECL_TI_TEMPLATE (push_template_decl (decl));
+ else if (template_class_depth (current_class_type))
+ decl = push_template_decl_real (decl, /*is_friend=*/1);
+
+ /* We can't do lookup in a type that involves template
+ parameters. Instead, we rely on tsubst_friend_function
+ to check the validity of the declaration later. */
+ if (uses_template_parms (ctype))
+ add_friend (current_class_type, decl);
+ /* A nested class may declare a member of an enclosing class
+ to be a friend, so we do lookup here even if CTYPE is in
+ the process of being defined. */
+ else if (TYPE_SIZE (ctype) != 0 || TYPE_BEING_DEFINED (ctype))
{
- if (flags == NO_SPECIAL && ctype && declarator == cname)
- DECL_CONSTRUCTOR_P (decl) = 1;
+ decl = check_classfn (ctype, decl);
- /* 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);
- }
+ if (decl)
+ add_friend (current_class_type, decl);
}
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;
+ cp_error ("member `%D' declared as friend before type `%T' defined",
+ decl, ctype);
}
/* A global friend.
@@ or possibly a friend from a base class ?!? */
@@ -407,9 +403,6 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
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;
@@ -417,22 +410,20 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
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);
- }
+ FUNCTION_DECL is not needed for other purposes. Don't do
+ this for a template instantiation. 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 (!is_friend_template
+ && template_class_depth (current_class_type) == 0)
+ decl = pushdecl (decl);
else
- decl = push_template_decl (decl);
+ decl = push_template_decl_real (decl, /*is_friend=*/1);
- if (! funcdef_flag && ! flag_guiding_decls && ! is_friend_template
+ if (warn_nontemplate_friend
+ && ! funcdef_flag && ! flag_guiding_decls && ! is_friend_template
&& current_template_parms && uses_template_parms (decl))
{
static int explained;
@@ -443,6 +434,7 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
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)");
+ warning (" -Wno-non-template-friend disables this warning.");
explained = 1;
}
}
@@ -453,32 +445,28 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
is_friend_template ? DECL_TI_TEMPLATE (decl) : decl);
DECL_FRIEND_P (decl) = 1;
}
+
+ /* Unfortunately, we have to handle attributes here. Normally we would
+ handle them in start_decl_1, but since this is a friend decl start_decl_1
+ never gets to see it. */
+
+ if (attrlist)
+ {
+ attributes = TREE_PURPOSE (attrlist);
+ prefix_attributes = TREE_VALUE (attrlist);
+ }
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);
- }
+ attributes = NULL_TREE;
+ prefix_attributes = NULL_TREE;
+ }
- /* 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));
- }
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+ SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes);
+#endif
+
+ /* Set attributes here so if duplicate decl, will have proper attributes. */
+ cplus_decl_attributes (decl, attributes, prefix_attributes);
- 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++spec.c b/contrib/gcc/cp/g++spec.c
index 542ca06..806b90e 100644
--- a/contrib/gcc/cp/g++spec.c
+++ b/contrib/gcc/cp/g++spec.c
@@ -1,5 +1,5 @@
/* Specific flags and argument handling of the C++ front-end.
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,11 +19,8 @@ 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'. */
@@ -34,11 +31,10 @@ Boston, MA 02111-1307, USA. */
#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));
+#ifndef LIBSTDCXX
+#define LIBSTDCXX "-lstdc++"
+#endif
void
lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
@@ -83,8 +79,8 @@ lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
LANGSPEC, MATHLIB, or WITHLIBC. */
int *args;
- /* By default, we throw on the math library. */
- int need_math = NEED_MATH_LIBRARY;
+ /* By default, we throw on the math library if we have one. */
+ int need_math = (MATH_LIBRARY[0] != '\0');
/* The total number of arguments with the new stuff. */
int argc;
@@ -128,6 +124,7 @@ lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
}
else if (strcmp (argv[i], "-lm") == 0
|| strcmp (argv[i], "-lmath") == 0
+ || strcmp (argv[i], MATH_LIBRARY) == 0
#ifdef ALT_LIBM
|| strcmp (argv[i], ALT_LIBM) == 0
#endif
@@ -239,7 +236,7 @@ lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
/* Add `-lstdc++' if we haven't already done so. */
if (library)
{
- arglist[j++] = "-lstdc++";
+ arglist[j++] = LIBSTDCXX;
added_libraries++;
}
if (saw_math)
diff --git a/contrib/gcc/cp/gxx.gperf b/contrib/gcc/cp/gxx.gperf
index 71538567..1e621c4 100644
--- a/contrib/gcc/cp/gxx.gperf
+++ b/contrib/gcc/cp/gxx.gperf
@@ -1,7 +1,7 @@
%{
-/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
+/* Command-line: gperf -L KR-C -F ', 0, 0' -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
%}
-struct resword { char *name; short token; enum rid rid;};
+struct resword { const char *name; short token; enum rid rid;};
%%
__alignof, ALIGNOF, NORID
__alignof__, ALIGNOF, NORID
@@ -22,6 +22,8 @@ __label__, LABEL, NORID
__null, CONSTANT, RID_NULL
__real, REALPART, NORID
__real__, REALPART, NORID
+__restrict, CV_QUALIFIER, RID_RESTRICT
+__restrict__, CV_QUALIFIER, RID_RESTRICT
__signature__, AGGR, RID_SIGNATURE /* Extension */,
__signed, TYPESPEC, RID_SIGNED
__signed__, TYPESPEC, RID_SIGNED
@@ -55,6 +57,7 @@ dynamic_cast, DYNAMIC_CAST, NORID,
else, ELSE, NORID,
enum, ENUM, NORID,
explicit, SCSPEC, RID_EXPLICIT,
+export, SCSPEC, RID_EXPORT,
extern, SCSPEC, RID_EXTERN,
false, CXX_FALSE, NORID,
float, TYPESPEC, RID_FLOAT,
@@ -78,7 +81,7 @@ protected, VISSPEC, RID_PROTECTED,
public, VISSPEC, RID_PUBLIC,
register, SCSPEC, RID_REGISTER,
reinterpret_cast, REINTERPRET_CAST, NORID,
-return, RETURN, NORID,
+return, RETURN_KEYWORD, NORID,
short, TYPESPEC, RID_SHORT,
signature, AGGR, RID_SIGNATURE /* Extension */,
signed, TYPESPEC, RID_SIGNED,
diff --git a/contrib/gcc/cp/gxxint.texi b/contrib/gcc/cp/gxxint.texi
index 7cb57f2..05f1373 100644
--- a/contrib/gcc/cp/gxxint.texi
+++ b/contrib/gcc/cp/gxxint.texi
@@ -23,7 +23,6 @@ Questions and comments to Benjamin Kosnik @code{<bkoz@@cygnus.com>}.
* Access Control::
* Error Reporting::
* Parser::
-* Copying Objects::
* Exception Handling::
* Free Store::
* Mangling:: Function name mangling for C++ and Java
@@ -167,77 +166,6 @@ class foo @{ public: int b; int a; foo (); @};
Thus, @samp{b} will be initialized with 2 first, then @samp{a} will be
initialized with 1, regardless of how they're listed in the mem-initializer.
-@item Argument Matching
-
-In early 1993, the argument matching scheme in @sc{gnu} C++ changed
-significantly. The original code was completely replaced with a new
-method that will, hopefully, be easier to understand and make fixing
-specific cases much easier.
-
-The @samp{-fansi-overloading} option is used to enable the new code; at
-some point in the future, it will become the default behavior of the
-compiler.
-
-The file @file{cp-call.c} contains all of the new work, in the functions
-@code{rank_for_overload}, @code{compute_harshness},
-@code{compute_conversion_costs}, and @code{ideal_candidate}.
-
-Instead of using obscure numerical values, the quality of an argument
-match is now represented by clear, individual codes. The new data
-structure @code{struct harshness} (it used to be an @code{unsigned}
-number) contains:
-
-@enumerate a
-@item the @samp{code} field, to signify what was involved in matching two
-arguments;
-@item the @samp{distance} field, used in situations where inheritance
-decides which function should be called (one is ``closer'' than
-another);
-@item and the @samp{int_penalty} field, used by some codes as a tie-breaker.
-@end enumerate
-
-The @samp{code} field is a number with a given bit set for each type of
-code, OR'd together. The new codes are:
-
-@itemize @bullet
-@item @code{EVIL_CODE}
-The argument was not a permissible match.
-
-@item @code{CONST_CODE}
-Currently, this is only used by @code{compute_conversion_costs}, to
-distinguish when a non-@code{const} member function is called from a
-@code{const} member function.
-
-@item @code{ELLIPSIS_CODE}
-A match against an ellipsis @samp{...} is considered worse than all others.
-
-@item @code{USER_CODE}
-Used for a match involving a user-defined conversion.
-
-@item @code{STD_CODE}
-A match involving a standard conversion.
-
-@item @code{PROMO_CODE}
-A match involving an integral promotion. For these, the
-@code{int_penalty} field is used to handle the ARM's rule (XXX cite)
-that a smaller @code{unsigned} type should promote to a @code{int}, not
-to an @code{unsigned int}.
-
-@item @code{QUAL_CODE}
-Used to mark use of qualifiers like @code{const} and @code{volatile}.
-
-@item @code{TRIVIAL_CODE}
-Used for trivial conversions. The @samp{int_penalty} field is used by
-@code{convert_harshness} to communicate further penalty information back
-to @code{build_overload_call_real} when deciding which function should
-be call.
-@end itemize
-
-The functions @code{convert_to_aggr} and @code{build_method_call} use
-@code{compute_conversion_costs} to rate each argument's suitability for
-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}
@@ -1002,7 +930,7 @@ To have the line number on the error message indicate the line of the
DECL, use @code{cp_error_at} and its ilk; to indicate which argument you want,
use @code{%+D}, or it will default to the first.
-@node Parser, Copying Objects, Error Reporting, Top
+@node Parser, Exception Handling, Error Reporting, Top
@section Parser
Some comments on the parser:
@@ -1093,33 +1021,7 @@ conflicts.
Unlike the others, this ambiguity is not recognized by the Working Paper.
-@node Copying Objects, Exception Handling, Parser, Top
-@section Copying Objects
-
-The generated copy assignment operator in g++ does not currently do the
-right thing for multiple inheritance involving virtual bases; it just
-calls the copy assignment operators for its direct bases. What it
-should probably do is:
-
-1) Split up the copy assignment operator for all classes that have
-vbases into "copy my vbases" and "copy everything else" parts. Or do
-the trickiness that the constructors do to ensure that vbases don't get
-initialized by intermediate bases.
-
-2) Wander through the class lattice, find all vbases for which no
-intermediate base has a user-defined copy assignment operator, and call
-their "copy everything else" routines. If not all of my vbases satisfy
-this criterion, warn, because this may be surprising behavior.
-
-3) Call the "copy everything else" routine for my direct bases.
-
-If we only have one direct base, we can just foist everything off onto
-them.
-
-This issue is currently under discussion in the core reflector
-(2/28/94).
-
-@node Exception Handling, Free Store, Copying Objects, Top
+@node Exception Handling, Free Store, Parser, Top
@section Exception Handling
Note, exception handling in g++ is still under development.
@@ -1666,18 +1568,18 @@ 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
+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}, @samp{U} and @samp{u} codes, denoting
+constant, volatile, pointer, array, reference, unsigned, and restrict.
+These codes may precede a @samp{B} type in order to make the required
modifications to the type.
For example:
@@ -1845,6 +1747,14 @@ Used to indicate a template function.
@item i
Encodes the C++ and Java @code{int} types.
+@item I
+Encodes typedef names of the form @code{int@var{n}_t}, where @var{n} is a
+positive decimal number. The @samp{I} is followed by either two
+hexidecimal digits, which encode the value of @var{n}, or by an
+arbitrary number of hexidecimal digits between underscores. For
+example, @samp{I40} encodes the type @code{int64_t}, and @samp{I_200_}
+encodes the type @code{int512_t}.
+
@item J
Indicates a complex type.
@@ -1854,12 +1764,21 @@ Used by squangling to compress qualified names.
@item l
Encodes the C++ @code{long} type.
+@item n
+Immediate repeated type. Followed by the repeat count.
+
+@item N
+Repeated type. Followed by the repeat count of the repeated type,
+followed by the type index of the repeated type. Due to a bug in
+g++ 2.7.2, this is only generated if index is 0. Superceded by
+@samp{n} when squangling.
+
@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 (?).
+Also used for namespaces.
In Java used to mangle package-qualified names, and inner classes.
@item r
@@ -1888,11 +1807,14 @@ 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 u
+The @code{restrict} type qualifier.
+
@item v
Encodes the C++ and Java @code{void} types.
@item V
-A modified for a @code{const} type or method.
+A modifier for a @code{volatile} type or method.
@item w
Encodes the C++ @code{wchar_t} type, and the Java @code{char} types.
diff --git a/contrib/gcc/cp/inc/exception b/contrib/gcc/cp/inc/exception
index 9954146..32efb9f 100644
--- a/contrib/gcc/cp/inc/exception
+++ b/contrib/gcc/cp/inc/exception
@@ -1,5 +1,5 @@
// Exception Handling support header for -*- C++ -*-
-// Copyright (C) 1995, 1996 Free Software Foundation
+// Copyright (C) 1995, 96-97, 1998 Free Software Foundation
#ifndef __EXCEPTION__
#define __EXCEPTION__
@@ -8,9 +8,7 @@
extern "C++" {
-#ifdef __HONOR_STD
namespace std {
-#endif
class exception {
public:
@@ -34,9 +32,7 @@ unexpected_handler set_unexpected (unexpected_handler);
void unexpected () __attribute__ ((__noreturn__));
bool uncaught_exception ();
-#ifdef __HONOR_STD
} // namespace std
-#endif
} // extern "C++"
diff --git a/contrib/gcc/cp/inc/new b/contrib/gcc/cp/inc/new
index 0f25a5c..b66673d 100644
--- a/contrib/gcc/cp/inc/new
+++ b/contrib/gcc/cp/inc/new
@@ -1,5 +1,5 @@
// The -*- C++ -*- dynamic memory management header.
-// Copyright (C) 1994, 1996 Free Software Foundation
+// Copyright (C) 1994, 96-97, 1998 Free Software Foundation
#ifndef __NEW__
#define __NEW__
@@ -10,9 +10,7 @@
extern "C++" {
-#ifdef __HONOR_STD
namespace std {
-#endif
class bad_alloc : public exception {
public:
@@ -24,9 +22,7 @@ namespace std {
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);
diff --git a/contrib/gcc/cp/inc/new.h b/contrib/gcc/cp/inc/new.h
index 799db7e..006be7e 100644
--- a/contrib/gcc/cp/inc/new.h
+++ b/contrib/gcc/cp/inc/new.h
@@ -5,9 +5,7 @@
#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
index e46acb9..9347849 100644
--- a/contrib/gcc/cp/inc/typeinfo
+++ b/contrib/gcc/cp/inc/typeinfo
@@ -1,5 +1,5 @@
// RTTI support for -*- C++ -*-
-// Copyright (C) 1994, 1995, 1996 Free Software Foundation
+// Copyright (C) 1994, 95-97, 1998 Free Software Foundation
#ifndef __TYPEINFO__
#define __TYPEINFO__
@@ -10,9 +10,7 @@
extern "C++" {
-#ifdef __HONOR_STD
namespace std {
-#endif
class type_info {
private:
@@ -21,7 +19,7 @@ private:
type_info (const type_info&);
protected:
- type_info (const char *n): _name (n) { }
+ explicit type_info (const char *n): _name (n) { }
const char *_name;
@@ -54,9 +52,7 @@ class bad_typeid : public exception {
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 931d033..38bf248 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-96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -32,8 +32,6 @@ Boston, MA 02111-1307, USA. */
#include "expr.h"
#include "toplev.h"
-extern void compiler_error ();
-
/* In C++, structures with well-defined constructors are initialized by
those constructors, unasked. CURRENT_BASE_INIT_LIST
holds a list of stmts for a BASE_INIT term in the grammar.
@@ -46,25 +44,22 @@ extern void compiler_error ();
tree current_base_init_list, current_member_init_list;
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 void construct_virtual_bases PROTO((tree, tree, tree, tree, tree));
+static void expand_aggr_init_1 PROTO((tree, tree, tree, tree, int));
+static void expand_default_init PROTO((tree, tree, tree, tree, 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 tree build_builtin_delete_call PROTO((tree));
+static int member_init_ok_or_else PROTO((tree, tree, const char *));
static void expand_virtual_init PROTO((tree, tree));
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;
+static void expand_vec_init_try_block PROTO((tree));
+static void expand_vec_init_catch_clause PROTO((tree, tree, tree, tree));
+static tree build_java_class_ref PROTO((tree));
+static void expand_cleanup_for_base PROTO((tree, tree));
/* Cache the identifier nodes for the magic field of a new cookie. */
static tree nc_nelts_field_id;
@@ -80,15 +75,6 @@ void init_init_processing ()
{
tree fields[1];
- /* Define implicit `operator new' and `operator delete' functions. */
- BIN = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) NEW_EXPR])));
- TREE_USED (TREE_OPERAND (BIN, 0)) = 0;
- BID = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) DELETE_EXPR])));
- TREE_USED (TREE_OPERAND (BID, 0)) = 0;
- BIVN = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_NEW_EXPR])));
- TREE_USED (TREE_OPERAND (BIVN, 0)) = 0;
- BIVD = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_DELETE_EXPR])));
- TREE_USED (TREE_OPERAND (BIVD, 0)) = 0;
minus_one = build_int_2 (-1, -1);
/* Define the structure that holds header information for
@@ -189,7 +175,7 @@ perform_member_init (member, name, init, explicit)
array_type_nelts (type), TREE_VALUE (init), 1);
}
else
- expand_aggr_init (decl, init, 0, 0);
+ expand_aggr_init (decl, init, 0);
}
else
{
@@ -492,17 +478,6 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
*vbase_ptr = vbases;
}
-/* Perform partial cleanups for a base for exception handling. */
-
-static tree
-build_partial_cleanup_for (binfo)
- tree binfo;
-{
- 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
class of the class variable. These actions are in the global
variable CURRENT_BASE_INIT_LIST. Such an action could be
@@ -562,14 +537,13 @@ emit_base_init (t, immediately)
sort_base_init (t, &rbase_init_list, &vbase_init_list);
current_base_init_list = NULL_TREE;
+ /* First, initialize the virtual base classes, if we are
+ constructing the most-derived object. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{
tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
-
- expand_start_cond (first_arg, 0);
- expand_aggr_vbase_init (t_binfo, current_class_ref, current_class_ptr,
- vbase_init_list);
- expand_end_cond ();
+ construct_virtual_bases (t, current_class_ref, current_class_ptr,
+ vbase_init_list, first_arg);
}
/* Now, perform initialization of non-virtual base classes. */
@@ -581,11 +555,8 @@ emit_base_init (t, immediately)
if (TREE_VIA_VIRTUAL (base_binfo))
continue;
-#if 0 /* Once unsharing happens soon enough. */
- my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo, 999);
-#else
- BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo;
-#endif
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo,
+ 999);
if (TREE_PURPOSE (rbase_init_list))
init = TREE_VALUE (rbase_init_list);
@@ -604,24 +575,13 @@ emit_base_init (t, immediately)
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);
+ LOOKUP_NORMAL);
expand_end_target_temps ();
free_temp_slots ();
}
- if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
- {
- 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);
- }
-
+ expand_cleanup_for_base (base_binfo, NULL_TREE);
rbase_init_list = TREE_CHAIN (rbase_init_list);
}
@@ -783,6 +743,39 @@ expand_virtual_init (binfo, decl)
expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
}
+/* If an exception is thrown in a constructor, those base classes already
+ constructed must be destroyed. This function creates the cleanup
+ for BINFO, which has just been constructed. If FLAG is non-NULL,
+ it is a DECL which is non-zero when this base needs to be
+ destroyed. */
+
+static void
+expand_cleanup_for_base (binfo, flag)
+ tree binfo;
+ tree flag;
+{
+ tree expr;
+
+ if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
+ return;
+
+ /* All cleanups must be on the function_obstack. */
+ push_obstacks_nochange ();
+ resume_temporary_allocation ();
+
+ /* Call the destructor. */
+ expr = (build_scoped_method_call
+ (current_class_ref, binfo, dtor_identifier,
+ build_expr_list (NULL_TREE, integer_zero_node)));
+ if (flag)
+ expr = fold (build (COND_EXPR, void_type_node,
+ truthvalue_conversion (flag),
+ expr, integer_zero_node));
+
+ pop_obstacks ();
+ add_partial_entry (expr);
+}
+
/* 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. */
@@ -799,42 +792,66 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
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_aggr_init_1 (binfo, exp, ref, init, LOOKUP_COMPLAIN);
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. */
+/* Construct the virtual base-classes of THIS_REF (whose address is
+ THIS_PTR). The object has the indicated TYPE. The construction
+ actually takes place only if FLAG is non-zero. INIT_LIST is list
+ of initialization for constructor to perform. */
static void
-expand_aggr_vbase_init (binfo, exp, addr, init_list)
- tree binfo;
- tree exp;
- tree addr;
+construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
+ tree type;
+ tree this_ref;
+ tree this_ptr;
tree init_list;
+ tree flag;
{
- tree type = BINFO_TYPE (binfo);
+ tree vbases;
+ tree result;
- if (TYPE_USES_VIRTUAL_BASECLASSES (type))
- {
- tree result = init_vbase_pointers (type, addr);
- tree vbases;
+ /* If there are no virtual baseclasses, we shouldn't even be here. */
+ my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
- if (result)
- expand_expr_stmt (build_compound_expr (result));
+ /* First set the pointers in our object that tell us where to find
+ our virtual baseclasses. */
+ expand_start_cond (flag, 0);
+ result = init_vbase_pointers (type, this_ptr);
+ if (result)
+ expand_expr_stmt (build_compound_expr (result));
+ expand_end_cond ();
- for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
- vbases = TREE_CHAIN (vbases))
- {
- tree tmp = purpose_member (vbases, result);
- expand_aggr_vbase_init_1 (vbases, exp,
- TREE_OPERAND (TREE_VALUE (tmp), 0),
- init_list);
- }
+ /* Now, run through the baseclasses, initializing each. */
+ for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ tree tmp = purpose_member (vbases, result);
+
+ /* If there are virtual base classes with destructors, we need to
+ emit cleanups to destroy them if an exception is thrown during
+ the construction process. These exception regions (i.e., the
+ period during which the cleanups must occur) begin from the time
+ the construction is complete to the end of the function. If we
+ create a conditional block in which to initialize the
+ base-classes, then the cleanup region for the virtual base begins
+ inside a block, and ends outside of that block. This situation
+ confuses the sjlj exception-handling code. Therefore, we do not
+ create a single conditional block, but one for each
+ initialization. (That way the cleanup regions always begin
+ in the outer block.) We trust the back-end to figure out
+ that the FLAG will not change across initializations, and
+ avoid doing multiple tests. */
+ expand_start_cond (flag, 0);
+ expand_aggr_vbase_init_1 (vbases, this_ref,
+ TREE_OPERAND (TREE_VALUE (tmp), 0),
+ init_list);
+ expand_end_cond ();
+
+ expand_cleanup_for_base (vbases, flag);
}
}
@@ -864,7 +881,7 @@ static int
member_init_ok_or_else (field, type, member_name)
tree field;
tree type;
- char *member_name;
+ const char *member_name;
{
if (field == error_mark_node)
return 0;
@@ -914,7 +931,7 @@ expand_member_init (exp, name, init)
if (name && TREE_CODE (name) == TYPE_DECL)
{
- basetype = TREE_TYPE (name);
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
name = DECL_NAME (name);
}
@@ -1052,9 +1069,8 @@ expand_member_init (exp, name, init)
perform the initialization, but not both, as it would be ambiguous. */
void
-expand_aggr_init (exp, init, alias_this, flags)
+expand_aggr_init (exp, init, flags)
tree exp, init;
- int alias_this;
int flags;
{
tree type = TREE_TYPE (exp);
@@ -1075,7 +1091,7 @@ expand_aggr_init (exp, init, alias_this, flags)
/* Must arrange to initialize each element of EXP
from elements of INIT. */
tree itype = init ? TREE_TYPE (init) : NULL_TREE;
- if (TYPE_READONLY (TREE_TYPE (type)) || TYPE_VOLATILE (TREE_TYPE (type)))
+ if (CP_TYPE_QUALS (type) != TYPE_UNQUALIFIED)
{
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
if (init)
@@ -1099,7 +1115,8 @@ expand_aggr_init (exp, init, alias_this, flags)
return;
}
expand_vec_init (exp, exp, array_type_nelts (type), init,
- init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1));
+ init && same_type_p (TREE_TYPE (init),
+ TREE_TYPE (exp)));
TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile;
TREE_TYPE (exp) = type;
@@ -1123,18 +1140,17 @@ expand_aggr_init (exp, init, alias_this, flags)
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
- init, alias_this, LOOKUP_NORMAL|flags);
+ init, LOOKUP_NORMAL|flags);
TREE_TYPE (exp) = type;
TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile;
}
static void
-expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
+expand_default_init (binfo, true_exp, exp, init, flags)
tree binfo;
tree true_exp, exp;
tree init;
- int alias_this;
int flags;
{
tree type = TREE_TYPE (exp);
@@ -1155,14 +1171,13 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
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))
+ if (flags & DIRECT_BIND)
+ /* Do nothing. We hit this in two cases: Reference initialization,
+ where we aren't initializing a real variable, so we don't want
+ to run a new constructor; and catching an exception, where we
+ have already built up the constructor call so we could wrap it
+ in an exception region. */;
+ else
init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
if (TREE_CODE (init) == TRY_CATCH_EXPR)
@@ -1227,11 +1242,10 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
its description. */
static void
-expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
+expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
tree binfo;
tree true_exp, exp;
tree init;
- int alias_this;
int flags;
{
tree type = TREE_TYPE (exp);
@@ -1262,7 +1276,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
/* 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);
+ expand_default_init (binfo, true_exp, exp, init, flags);
}
/* Report an error if NAME is not the name of a user-defined,
@@ -1379,7 +1393,6 @@ build_member_call (type, name, parmlist)
tree t;
tree method_name;
int dtor = 0;
- int dont_use_this = 0;
tree basetype_path, decl;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR
@@ -1387,7 +1400,18 @@ build_member_call (type, name, parmlist)
{
/* '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);
+ method_name = TREE_OPERAND (name, 0);
+ /* FIXME: Since we don't do independent names right yet, the
+ name might also be a LOOKUP_EXPR. Once we resolve this to a
+ real decl earlier, this can go. This may happen during
+ tsubst'ing. */
+ if (TREE_CODE (method_name) == LOOKUP_EXPR)
+ {
+ method_name = lookup_namespace_name
+ (type, TREE_OPERAND (method_name, 0));
+ TREE_OPERAND (name, 0) = method_name;
+ }
+ my_friendly_assert (is_overloaded_fn (method_name), 980519);
return build_x_function_call (name, parmlist, current_class_ref);
}
@@ -1398,10 +1422,17 @@ build_member_call (type, name, parmlist)
return build_x_function_call (lookup_namespace_name (type, name),
parmlist, current_class_ref);
- if (TREE_CODE (name) != TEMPLATE_ID_EXPR)
- method_name = name;
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ method_name = TREE_OPERAND (name, 0);
+ if (TREE_CODE (method_name) == COMPONENT_REF)
+ method_name = TREE_OPERAND (method_name, 1);
+ if (is_overloaded_fn (method_name))
+ method_name = DECL_NAME (OVL_CURRENT (method_name));
+ TREE_OPERAND (name, 0) = method_name;
+ }
else
- method_name = TREE_OPERAND (name, 0);
+ method_name = name;
if (TREE_CODE (method_name) == BIT_NOT_EXPR)
{
@@ -1435,42 +1466,29 @@ build_member_call (type, name, parmlist)
return error_mark_node;
}
- /* No object? Then just fake one up, and let build_method_call
- figure out what to do. */
- if (current_class_type == 0
- || get_base_distance (type, current_class_type, 0, &basetype_path) == -1)
- dont_use_this = 1;
+ decl = maybe_dummy_object (type, &basetype_path);
- if (dont_use_this)
- {
- basetype_path = TYPE_BINFO (type);
- decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
- }
- else if (current_class_ptr == 0)
- {
- dont_use_this = 1;
- decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
- }
- else
+ /* Convert 'this' to the specified type to disambiguate conversion
+ to the function's context. Apparently Standard C++ says that we
+ shouldn't do this. */
+ if (decl == current_class_ref
+ && ! pedantic
+ && ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type))
{
tree olddecl = current_class_ptr;
tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
if (oldtype != type)
{
- tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),
- TYPE_VOLATILE (oldtype));
+ tree newtype = build_qualified_type (type, TYPE_QUALS (oldtype));
decl = convert_force (build_pointer_type (newtype), olddecl, 0);
+ decl = build_indirect_ref (decl, NULL_PTR);
}
- else
- decl = olddecl;
}
- decl = build_indirect_ref (decl, NULL_PTR);
-
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)))
+ if (lookup_fnfields (basetype_path, method_name, 0))
return build_method_call (decl,
TREE_CODE (name) == TEMPLATE_ID_EXPR
? name : method_name,
@@ -1483,7 +1501,7 @@ build_member_call (type, name, parmlist)
return error_mark_node;
if (TREE_CODE (t) == FIELD_DECL)
{
- if (dont_use_this)
+ if (is_dummy_object (decl))
{
cp_error ("invalid use of non-static field `%D'", t);
return error_mark_node;
@@ -1523,7 +1541,8 @@ tree
build_offset_ref (type, name)
tree type, name;
{
- tree decl, fnfields, fields, t = error_mark_node;
+ tree decl, t = error_mark_node;
+ tree member;
tree basebinfo = NULL_TREE;
tree orig_name = name;
@@ -1541,7 +1560,7 @@ build_offset_ref (type, name)
if (TREE_CODE (type) == NAMESPACE_DECL)
{
t = lookup_namespace_name (type, name);
- if (! type_unknown_p (t))
+ if (t != error_mark_node && ! type_unknown_p (t))
{
mark_used (t);
t = convert_from_reference (t);
@@ -1559,6 +1578,11 @@ build_offset_ref (type, name)
part, we treat this just like a.f. We do remember, however,
the template-id that was used. */
name = TREE_OPERAND (orig_name, 0);
+
+ if (TREE_CODE (name) == LOOKUP_EXPR)
+ /* This can happen during tsubst'ing. */
+ name = TREE_OPERAND (name, 0);
+
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
}
@@ -1576,57 +1600,27 @@ build_offset_ref (type, name)
name = ctor_identifier;
#endif
- if (TYPE_SIZE (complete_type (type)) == 0)
+ if (TYPE_SIZE (complete_type (type)) == 0
+ && !TYPE_BEING_DEFINED (type))
{
- 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,
- name);
- return error_mark_node;
- }
- if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL
- || TREE_CODE (t) == CONST_DECL)
- {
- mark_used (t);
- return t;
- }
- if (TREE_CODE (t) == FIELD_DECL)
- sorry ("use of member in incomplete aggregate type");
- else if (TREE_CODE (t) == FUNCTION_DECL)
- sorry ("use of member function in incomplete aggregate type");
- else
- my_friendly_abort (52);
+ cp_error ("incomplete type `%T' does not have member `%D'", type,
+ name);
return error_mark_node;
}
- if (current_class_type == 0
- || get_base_distance (type, current_class_type, 0, &basebinfo) == -1)
- {
- basebinfo = TYPE_BINFO (type);
- decl = build1 (NOP_EXPR, type, error_mark_node);
- }
- else if (current_class_ptr == 0)
- decl = build1 (NOP_EXPR, type, error_mark_node);
- else
- decl = current_class_ref;
+ decl = maybe_dummy_object (type, &basebinfo);
- fnfields = lookup_fnfields (basebinfo, name, 1);
- fields = lookup_field (basebinfo, name, 0, 0);
+ member = lookup_member (basebinfo, name, 1, 0);
- if (fields == error_mark_node || fnfields == error_mark_node)
+ if (member == error_mark_node)
return error_mark_node;
/* A lot of this logic is now handled in lookup_field and
lookup_fnfield. */
- if (fnfields)
+ if (member && BASELINK_P (member))
{
- extern int flag_save_memoized_contexts;
-
/* Go from the TREE_BASELINK to the member function info. */
+ tree fnfields = member;
t = TREE_VALUE (fnfields);
if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
@@ -1644,7 +1638,7 @@ build_offset_ref (type, name)
t = ovl_cons (t, NULL_TREE);
return build (OFFSET_REF,
- build_offset_type (type, unknown_type_node),
+ unknown_type_node,
decl,
build (TEMPLATE_ID_EXPR,
TREE_TYPE (t),
@@ -1654,56 +1648,35 @@ build_offset_ref (type, name)
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)
- {
- cp_error_at ("member function `%#D' is protected", t);
- error ("in this context");
- return error_mark_node;
- }
- if (access == access_private_node)
- {
- cp_error_at ("member function `%#D' is private", t);
- error ("in this context");
- return error_mark_node;
- }
+ if (!enforce_access (basebinfo, t))
+ return error_mark_node;
mark_used (t);
+ if (DECL_STATIC_FUNCTION_P (t))
+ return t;
return build (OFFSET_REF, TREE_TYPE (t), decl, t);
}
/* 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.
+ to save this value for later (i.e. 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 && toplevel_bindings_p ())
- || ! allocation_temporary_p ()))
+ && ! allocation_temporary_p ())
fnfields = copy_list (fnfields);
- t = build_tree_list (error_mark_node, fnfields);
- TREE_TYPE (t) = build_offset_type (type, unknown_type_node);
- return t;
+ TREE_TYPE (fnfields) = unknown_type_node;
+ return build (OFFSET_REF, unknown_type_node, decl, fnfields);
}
- /* 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 (basebinfo, name, 1, 0);
-
- if (t == error_mark_node)
- return error_mark_node;
+ t = member;
if (t == NULL_TREE)
{
@@ -1724,7 +1697,7 @@ build_offset_ref (type, name)
return convert_from_reference (t);
}
- if (TREE_CODE (t) == FIELD_DECL && DECL_BIT_FIELD (t))
+ if (TREE_CODE (t) == FIELD_DECL && DECL_C_BIT_FIELD (t))
{
cp_error ("illegal pointer to bit field `%D'", t);
return error_mark_node;
@@ -1753,12 +1726,6 @@ resolve_offset_ref (exp)
tree member;
tree basetype, addr;
- if (TREE_CODE (exp) == TREE_LIST)
- {
- cp_pedwarn ("assuming & on overloaded member function");
- return build_unary_op (ADDR_EXPR, exp, 0);
- }
-
if (TREE_CODE (exp) == OFFSET_REF)
{
member = TREE_OPERAND (exp, 1);
@@ -1777,10 +1744,22 @@ resolve_offset_ref (exp)
base = current_class_ref;
}
+ if (BASELINK_P (member))
+ {
+ cp_pedwarn ("assuming & on overloaded member function");
+ return build_unary_op (ADDR_EXPR, exp, 0);
+ }
+
+ if (TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
+ {
+ cp_pedwarn ("assuming & on `%E'", member);
+ return build_unary_op (ADDR_EXPR, exp, 0);
+ }
+
if ((TREE_CODE (member) == VAR_DECL
- && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member)))
- || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
+ && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member))
+ && ! TYPE_PTRMEM_P (TREE_TYPE (member)))
+ || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE)
{
/* These were static members. */
if (mark_addressable (member) == 0)
@@ -1808,11 +1787,10 @@ resolve_offset_ref (exp)
/* The first case is really just a reference to a member of `this'. */
if (TREE_CODE (member) == FIELD_DECL
- && (base == current_class_ref
- || (TREE_CODE (base) == NOP_EXPR
- && TREE_OPERAND (base, 0) == error_mark_node)))
+ && (base == current_class_ref || is_dummy_object (base)))
{
- tree basetype_path, access;
+ tree basetype_path;
+ tree expr;
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
basetype = TYPE_OFFSET_BASETYPE (type);
@@ -1828,40 +1806,28 @@ resolve_offset_ref (exp)
}
/* Kludge: we need to use basetype_path now, because
convert_pointer_to will bash it. */
- access = compute_access (basetype_path, member);
+ enforce_access (basetype_path, member);
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_node)
- {
- cp_error_at ("member `%D' is protected", member);
- error ("in this context");
- return error_mark_node;
- }
- if (access == access_private_node)
- {
- cp_error_at ("member `%D' is private", member);
- error ("in this context");
- return error_mark_node;
- }
- my_friendly_abort (55);
+
+ /* Even in the case of illegal access, we form the
+ COMPONENT_REF; that will allow better error recovery than
+ just feeding back error_mark_node. */
+ expr = build (COMPONENT_REF, TREE_TYPE (member),
+ build_indirect_ref (addr, NULL_PTR), member);
+ return convert_from_reference (expr);
}
/* Ensure that we have an object. */
- if (TREE_CODE (base) == NOP_EXPR
- && TREE_OPERAND (base, 0) == error_mark_node)
+ if (is_dummy_object (base))
addr = error_mark_node;
else
- {
- /* 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 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)) == OFFSET_TYPE)
+ if (TYPE_PTRMEM_P (TREE_TYPE (member)))
{
if (addr == error_mark_node)
{
@@ -1869,17 +1835,15 @@ resolve_offset_ref (exp)
return error_mark_node;
}
- basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member));
+ basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member)));
addr = convert_pointer_to (basetype, addr);
- member = cp_convert (ptrdiff_type_node,
- build_unary_op (ADDR_EXPR, member, 0));
+ member = cp_convert (ptrdiff_type_node, member);
/* 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);
+ cp_convert (ptrdiff_type_node, integer_one_node));
return build1 (INDIRECT_REF, type,
build (PLUS_EXPR, build_pointer_type (type),
@@ -1901,48 +1865,29 @@ decl_constant_value (decl)
tree decl;
{
if (! TREE_THIS_VOLATILE (decl)
-#if 0
- /* These may be necessary for C, but they break C++. */
- ! TREE_PUBLIC (decl)
- /* Don't change a variable array bound or initial value to a constant
- in a place where a variable is invalid. */
- && ! pedantic
-#endif /* 0 */
- && DECL_INITIAL (decl) != 0
+ && DECL_INITIAL (decl)
&& 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. */
&& TREE_CONSTANT (DECL_INITIAL (decl))
/* Check for cases where this is sub-optimal, even though valid. */
- && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
-#if 0
- /* We must allow this to work outside of functions so that
- static constants can be used for array sizes. */
- && current_function_decl != 0
- && DECL_MODE (decl) != BLKmode
-#endif
- )
+ && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
return DECL_INITIAL (decl);
return decl;
}
/* Common subroutines of build_new and build_vec_delete. */
-/* Common interface for calling "builtin" functions that are not
- really builtin. */
+/* Call the global __builtin_delete to delete ADDR. */
static tree
-build_builtin_call (type, node, arglist)
- tree type;
- tree node;
- tree arglist;
+build_builtin_delete_call (addr)
+ tree addr;
{
- 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;
- return rval;
+ mark_used (global_delete_fndecl);
+ return build_call (global_delete_fndecl,
+ void_type_node, build_expr_list (NULL_TREE, addr));
}
/* Generate a C++ "new" expression. DECL is either a TREE_LIST
@@ -2036,6 +1981,11 @@ build_new (placement, decl, init, use_global_new)
}
else
{
+ int flags = pedantic ? WANT_INT : (WANT_INT | WANT_ENUM);
+ if (build_expr_type_conversion (flags, this_nelts, 0)
+ == NULL_TREE)
+ pedwarn ("size in array new must have integral type");
+
this_nelts = save_expr (cp_convert (sizetype, this_nelts));
absdcl = TREE_OPERAND (absdcl, 0);
if (this_nelts == integer_zero_node)
@@ -2044,7 +1994,7 @@ build_new (placement, decl, init, use_global_new)
nelts = integer_zero_node;
}
else
- nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
+ nelts = build_binary_op (MULT_EXPR, nelts, this_nelts);
}
}
else
@@ -2155,6 +2105,46 @@ build_new (placement, decl, init, use_global_new)
return rval;
}
+/* If non-NULL, a POINTER_TYPE equivalent to (java::lang::Class*). */
+
+static tree jclass_node = NULL_TREE;
+
+/* Given a Java class, return a decl for the corresponding java.lang.Class. */
+
+static tree
+build_java_class_ref (type)
+ tree type;
+{
+ tree name, class_decl;
+ static tree CL_prefix = NULL_TREE;
+ if (CL_prefix == NULL_TREE)
+ CL_prefix = get_identifier("_CL_");
+ if (jclass_node == NULL_TREE)
+ {
+ jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier("jclass"));
+ if (jclass_node == NULL_TREE)
+ fatal("call to Java constructor, while `jclass' undefined");
+ jclass_node = TREE_TYPE (jclass_node);
+ }
+ name = build_overload_with_type (CL_prefix, type);
+ class_decl = IDENTIFIER_GLOBAL_VALUE (name);
+ if (class_decl == NULL_TREE)
+ {
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
+ TREE_STATIC (class_decl) = 1;
+ DECL_EXTERNAL (class_decl) = 1;
+ TREE_PUBLIC (class_decl) = 1;
+ DECL_ARTIFICIAL (class_decl) = 1;
+ DECL_IGNORED_P (class_decl) = 1;
+ pushdecl_top_level (class_decl);
+ make_decl_rtl (class_decl, NULL_PTR, 1);
+ pop_obstacks ();
+ }
+ return class_decl;
+}
+
/* Called from cplus_expand_expr when expanding a NEW_EXPR. The return
value is immediately handed to expand_expr. */
@@ -2170,6 +2160,7 @@ build_new_1 (exp)
enum tree_code code = NEW_EXPR;
int use_cookie, nothrow, check_new;
int use_global_new;
+ int use_java_new = 0;
placement = TREE_OPERAND (exp, 0);
type = TREE_OPERAND (exp, 1);
@@ -2184,7 +2175,7 @@ build_new_1 (exp)
}
true_type = type;
- if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
+ if (CP_TYPE_QUALS (type))
type = TYPE_MAIN_VARIANT (type);
/* If our base type is an array, then make sure we know how many elements
@@ -2192,16 +2183,16 @@ build_new_1 (exp)
while (TREE_CODE (true_type) == ARRAY_TYPE)
{
tree this_nelts = array_type_nelts_top (true_type);
- nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
+ nelts = build_binary_op (MULT_EXPR, nelts, this_nelts);
true_type = TREE_TYPE (true_type);
}
- if (!complete_type_or_else (true_type))
+ if (!complete_type_or_else (true_type, exp))
return error_mark_node;
if (has_array)
size = fold (build_binary_op (MULT_EXPR, size_in_bytes (true_type),
- nelts, 1));
+ nelts));
else
size = size_in_bytes (type);
@@ -2223,21 +2214,21 @@ build_new_1 (exp)
signature_error (NULL_TREE, true_type);
return error_mark_node;
}
+
+ /* When we allocate an array, and the corresponding deallocation
+ function takes a second argument of type size_t, and that's the
+ "usual deallocation function", we allocate some extra space at
+ the beginning of the array to store the size of the array.
-#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. */
+ Well, that's what we should do. For backwards compatibility, we
+ have to do this whenever there's a two-argument array-delete
+ operator.
+ FIXME: For -fnew-abi, we don't have to maintain backwards
+ compatibility and we should fix this. */
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 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)
{
@@ -2267,9 +2258,26 @@ build_new_1 (exp)
return error_mark_node;
}
}
+ else if (! placement && TYPE_FOR_JAVA (true_type))
+ {
+ tree class_addr, alloc_decl;
+ tree class_decl = build_java_class_ref (true_type);
+ tree class_size = size_in_bytes (true_type);
+ static char alloc_name[] = "_Jv_AllocObject";
+ use_java_new = 1;
+ alloc_decl = IDENTIFIER_GLOBAL_VALUE (get_identifier (alloc_name));
+ if (alloc_decl == NULL_TREE)
+ fatal("call to Java constructor, while `%s' undefined", alloc_name);
+ class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
+ rval = build_function_call (alloc_decl,
+ tree_cons (NULL_TREE, class_addr,
+ build_tree_list (NULL_TREE,
+ class_size)));
+ rval = cp_convert (build_pointer_type (true_type), rval);
+ }
else
{
- int susp;
+ int susp = 0;
if (flag_exceptions)
/* We will use RVAL when generating an exception handler for
@@ -2302,12 +2310,9 @@ build_new_1 (exp)
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;
+ nothrow = TYPE_NOTHROW_P (TREE_TYPE (t));
}
- check_new = flag_check_new || nothrow;
+ check_new = (flag_check_new || nothrow) && ! use_java_new;
if ((check_new || flag_exceptions) && rval)
{
@@ -2326,7 +2331,7 @@ build_new_1 (exp)
tree extra = BI_header_size;
tree cookie, exp1;
rval = convert (string_type_node, rval); /* for ptr arithmetic */
- rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra, 1));
+ rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra));
/* Store header info. */
cookie = build_indirect_ref (build (MINUS_EXPR,
build_pointer_type (BI_header_type),
@@ -2354,12 +2359,26 @@ build_new_1 (exp)
if (! TYPE_NEEDS_CONSTRUCTING (type)
&& ! IS_AGGR_TYPE (type) && ! has_array)
{
- /* New 2.0 interpretation: `new int (10)' means
- allocate an int, and initialize it with 10. */
+ /* We are processing something like `new int (10)', which
+ means allocate an int, and initialize it with 10. */
tree deref;
+ tree deref_type;
+ /* At present RVAL is a temporary variable, created to hold
+ the value from the call to `operator new'. We transform
+ it to (*RVAL = INIT, RVAL). */
rval = save_expr (rval);
deref = build_indirect_ref (rval, NULL_PTR);
+
+ /* Even for something like `new const int (10)' we must
+ allow the expression to be non-const while we do the
+ initialization. */
+ deref_type = TREE_TYPE (deref);
+ if (CP_TYPE_CONST_P (deref_type))
+ TREE_TYPE (deref)
+ = cp_build_qualified_type (deref_type,
+ CP_TYPE_QUALS (deref_type)
+ & ~TYPE_QUAL_CONST);
TREE_READONLY (deref) = 0;
if (TREE_CHAIN (init) != NULL_TREE)
@@ -2393,6 +2412,8 @@ build_new_1 (exp)
flags |= LOOKUP_HAS_IN_CHARGE;
}
+ if (use_java_new)
+ rval = save_expr (rval);
newrval = rval;
if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE)
@@ -2404,6 +2425,10 @@ build_new_1 (exp)
if (newrval == NULL_TREE || newrval == error_mark_node)
return error_mark_node;
+ /* Java constructors compiled by jc1 do not return this. */
+ if (use_java_new)
+ newrval = build (COMPOUND_EXPR, TREE_TYPE (newrval),
+ newrval, rval);
rval = newrval;
TREE_HAS_CONSTRUCTOR (rval) = 1;
}
@@ -2411,11 +2436,15 @@ build_new_1 (exp)
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)
+ /* If any part of the object initialization terminates by throwing an
+ exception and a suitable deallocation function can be found, the
+ deallocation function is called to free the memory in which the
+ object was being constructed, after which the exception continues
+ to propagate in the context of the new-expression. If no
+ unambiguous matching deallocation function can be found,
+ propagating the exception does not cause the object's memory to be
+ freed. */
+ if (flag_exceptions && alloc_expr && ! use_java_new)
{
enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
tree cleanup, fn = NULL_TREE;
@@ -2435,7 +2464,7 @@ build_new_1 (exp)
}
/* Copy size to the saveable obstack. */
- size = copy_node (size);
+ size = mapcar (size, permanent_p);
cleanup = build_op_delete_call (dcode, alloc_node, size, flags, fn);
@@ -2448,9 +2477,6 @@ build_new_1 (exp)
if (cleanup)
{
-#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);
@@ -2473,18 +2499,10 @@ build_new_1 (exp)
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
}
}
}
- else if (TYPE_READONLY (true_type))
+ else if (CP_TYPE_CONST_P (true_type))
cp_error ("uninitialized const in `new' of `%#T'", true_type);
done:
@@ -2499,7 +2517,7 @@ build_new_1 (exp)
{
/* Did we modify the storage? */
tree ifexp = build_binary_op (NE_EXPR, alloc_node,
- integer_zero_node, 1);
+ integer_zero_node);
rval = build_conditional_expr (ifexp, rval, alloc_node);
}
@@ -2569,12 +2587,11 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
tree base_tbd = cp_convert (ptype,
build_binary_op (MINUS_EXPR,
cp_convert (ptr_type_node, base),
- BI_header_size,
- 1));
+ BI_header_size));
/* This is the real size */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
body = build_expr_list (NULL_TREE,
- build_x_delete (ptype, base_tbd,
+ build_x_delete (base_tbd,
2 | use_global_delete,
virtual_size));
body = build (COND_EXPR, void_type_node,
@@ -2608,8 +2625,7 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
no_destructor:
/* If the delete flag is one, or anything else with the low bit set,
delete the storage. */
- if (auto_delete_vec == integer_zero_node
- || auto_delete_vec == integer_two_node)
+ if (auto_delete_vec == integer_zero_node)
deallocate_expr = integer_zero_node;
else
{
@@ -2626,12 +2642,11 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
base_tbd = cp_convert (ptype,
build_binary_op (MINUS_EXPR,
cp_convert (string_type_node, base),
- BI_header_size,
- 1));
+ BI_header_size));
/* True size with header. */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
}
- deallocate_expr = build_x_delete (ptype, base_tbd,
+ deallocate_expr = build_x_delete (base_tbd,
2 | use_global_delete,
virtual_size);
if (auto_delete_vec != integer_one_node)
@@ -2665,18 +2680,80 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
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. */
+/* Protect the vector initialization with a try-block so that we can
+ destroy the first few elements if constructing a later element
+ causes an exception to be thrown. TYPE is the type of the array
+ elements. */
-static tree
-build_array_eh_cleanup (base, count, type)
- tree base, count, type;
+static void
+expand_vec_init_try_block (type)
+ tree type;
+{
+ if (!TYPE_NEEDS_DESTRUCTOR (type) || !flag_exceptions)
+ return;
+
+ /* The code we generate looks like:
+
+ try {
+ // Initialize the vector.
+ } catch (...) {
+ // Destory the elements that need destroying.
+ throw;
+ }
+
+ Here we're just beginning the `try'. */
+
+ expand_eh_region_start ();
+}
+
+/* Add code to destroy the array elements constructed so far if the
+ construction of some element in the array causes an exception to be
+ thrown. RVAL is the address of the last element in the array.
+ TYPE is the type of the array elements. MAXINDEX is the maximum
+ allowable index into the array. ITERATOR is an integer variable
+ indicating how many elements remain to be constructed. */
+
+static void
+expand_vec_init_catch_clause (rval, type, maxindex, iterator)
+ tree rval;
+ tree type;
+ tree maxindex;
+ tree iterator;
{
- tree expr = build_vec_delete_1 (base, count, type, integer_two_node,
- integer_zero_node, 0);
- return expr;
+ tree e;
+ tree cleanup;
+
+ if (!TYPE_NEEDS_DESTRUCTOR (type) || !flag_exceptions)
+ return;
+
+ /* 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 ();
+
+ 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);
+
+ e = build_vec_delete_1 (rval,
+ build_binary_op (MINUS_EXPR, maxindex,
+ iterator),
+ type,
+ /*auto_delete_vec=*/integer_zero_node,
+ /*auto_delete=*/integer_zero_node,
+ /*use_global_delete=*/0);
+ expand_expr (e, 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_vec_init' performs initialization of a vector of aggregate
@@ -2702,9 +2779,12 @@ expand_vec_init (decl, base, maxindex, init, from_array)
int from_array;
{
tree rval;
- tree iterator, base2 = NULL_TREE;
+ tree base2 = NULL_TREE;
tree type = TREE_TYPE (TREE_TYPE (base));
tree size;
+ tree itype = NULL_TREE;
+ tree iterator;
+ int num_initialized_elts = 0;
maxindex = cp_convert (ptrdiff_type_node, maxindex);
if (maxindex == error_mark_node)
@@ -2721,104 +2801,100 @@ expand_vec_init (decl, base, maxindex, init, from_array)
size = size_in_bytes (type);
- /* 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),
- cp_convert (build_pointer_type (type), null_pointer_node));
base = default_conversion (base);
base = cp_convert (build_pointer_type (type), base);
- expand_assignment (rval, base, 0, 0);
+ rval = get_temp_regvar (build_pointer_type (type), base);
base = get_temp_regvar (build_pointer_type (type), base);
+ iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
- if (init != NULL_TREE
- && TREE_CODE (init) == CONSTRUCTOR
- && (! decl || TREE_TYPE (init) == TREE_TYPE (decl)))
+ /* Protect the entire array initialization so that we can destroy
+ the partially constructed array if an exception is thrown. */
+ expand_vec_init_try_block (type);
+
+ if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR
+ && (!decl || same_type_p (TREE_TYPE (init), TREE_TYPE (decl))))
{
- /* Initialization of array from {...}. */
- tree elts = CONSTRUCTOR_ELTS (init);
+ /* Do non-default initialization resulting from brace-enclosed
+ initializers. */
+
+ tree elts;
tree baseref = build1 (INDIRECT_REF, type, base);
- tree baseinc = build (PLUS_EXPR, build_pointer_type (type), base, size);
- int host_i = TREE_INT_CST_LOW (maxindex);
- if (IS_AGGR_TYPE (type))
+ from_array = 0;
+
+ for (elts = CONSTRUCTOR_ELTS (init); elts; elts = TREE_CHAIN (elts))
{
- while (elts)
- {
- host_i -= 1;
- expand_aggr_init (baseref, TREE_VALUE (elts), 0, 0);
+ tree elt = TREE_VALUE (elts);
- expand_assignment (base, baseinc, 0, 0);
- elts = TREE_CHAIN (elts);
- }
- /* Initialize any elements by default if possible. */
- if (host_i >= 0)
- {
- if (TYPE_NEEDS_CONSTRUCTING (type) == 0)
- {
- if (obey_regdecls)
- use_variable (DECL_RTL (base));
- goto done_init;
- }
+ num_initialized_elts++;
- iterator = get_temp_regvar (ptrdiff_type_node,
- build_int_2 (host_i, 0));
- init = NULL_TREE;
- goto init_by_default;
- }
+ if (IS_AGGR_TYPE (type) || TREE_CODE (type) == ARRAY_TYPE)
+ expand_aggr_init (baseref, elt, 0);
+ else
+ expand_assignment (baseref, elt, 0, 0);
+
+ expand_assignment (base,
+ build (PLUS_EXPR, build_pointer_type (type),
+ base, size),
+ 0, 0);
+ expand_assignment (iterator,
+ build (MINUS_EXPR, ptrdiff_type_node,
+ iterator, integer_one_node),
+ 0, 0);
}
- else
- while (elts)
- {
- expand_assignment (baseref, TREE_VALUE (elts), 0, 0);
- expand_assignment (base, baseinc, 0, 0);
- elts = TREE_CHAIN (elts);
- }
+ /* Clear out INIT so that we don't get confused below. */
+ init = NULL_TREE;
if (obey_regdecls)
use_variable (DECL_RTL (base));
}
- else
+ else if (from_array)
{
- tree itype;
+ /* If initializing one array from another, initialize element by
+ element. We rely upon the below calls the do argument
+ checking. */
+ if (decl == NULL_TREE)
+ {
+ sorry ("initialization of array from dissimilar array type");
+ return error_mark_node;
+ }
+ if (init)
+ {
+ base2 = default_conversion (init);
+ itype = TREE_TYPE (base2);
+ base2 = get_temp_regvar (itype, base2);
+ itype = TREE_TYPE (itype);
+ }
+ else if (TYPE_LANG_SPECIFIC (type)
+ && TYPE_NEEDS_CONSTRUCTING (type)
+ && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+ {
+ error ("initializer ends prematurely");
+ return error_mark_node;
+ }
+ }
- iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
+ /* Now, default-initialize any remaining elements. We don't need to
+ do that if a) the type does not need constructing, or b) we've
+ already initialized all the elements.
- init_by_default:
- itype = NULL_TREE;
+ We do need to keep going if we're copying an array. */
- /* If initializing one array from another,
- initialize element by element. */
- if (from_array)
- {
- /* We rely upon the below calls the do argument checking */
- if (decl == NULL_TREE)
- {
- sorry ("initialization of array from dissimilar array type");
- return error_mark_node;
- }
- if (init)
- {
- base2 = default_conversion (init);
- itype = TREE_TYPE (base2);
- base2 = get_temp_regvar (itype, base2);
- itype = TREE_TYPE (itype);
- }
- else if (TYPE_LANG_SPECIFIC (type)
- && TYPE_NEEDS_CONSTRUCTING (type)
- && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
- {
- error ("initializer ends prematurely");
- return error_mark_node;
- }
- }
+ if (from_array
+ || (TYPE_NEEDS_CONSTRUCTING (type)
+ && !(TREE_CODE (maxindex) == INTEGER_CST
+ && num_initialized_elts == TREE_INT_CST_LOW (maxindex) + 1)))
+ {
+ /* If the ITERATOR is equal to -1, then we don't have to loop;
+ we've already initialized all the elements. */
+ expand_start_cond (build (NE_EXPR, boolean_type_node,
+ iterator, minus_one),
+ 0);
- expand_start_cond (build (GE_EXPR, boolean_type_node,
- iterator, integer_zero_node), 0);
- if (TYPE_NEEDS_DESTRUCTOR (type))
- expand_eh_region_start ();
+ /* Otherwise, loop through the elements. */
expand_start_loop_continue_elsewhere (1);
-
+
/* The initialization of each array element is a full-expression. */
expand_start_target_temps ();
@@ -2835,7 +2911,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
if (from_array == 2)
expand_expr_stmt (build_modify_expr (to, NOP_EXPR, from));
else if (TYPE_NEEDS_CONSTRUCTING (type))
- expand_aggr_init (to, from, 0, 0);
+ expand_aggr_init (to, from, 0);
else if (from)
expand_assignment (to, from, 0, 0);
else
@@ -2845,70 +2921,55 @@ expand_vec_init (decl, base, maxindex, init, from_array)
{
if (init != 0)
sorry ("cannot initialize multi-dimensional array with initializer");
- expand_vec_init (decl, build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), base),
+ expand_vec_init (decl,
+ build1 (NOP_EXPR,
+ build_pointer_type (TREE_TYPE
+ (type)),
+ base),
array_type_nelts (type), 0, 0);
}
else
- expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0, 0);
+ expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0);
expand_assignment (base,
- build (PLUS_EXPR, build_pointer_type (type), base, size),
- 0, 0);
+ build (PLUS_EXPR, build_pointer_type (type),
+ base, size), 0, 0);
if (base2)
expand_assignment (base2,
- build (PLUS_EXPR, build_pointer_type (type), base2, size), 0, 0);
+ 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, ptrdiff_type_node, iterator, integer_one_node), minus_one));
-
+ build (PREDECREMENT_EXPR,
+ ptrdiff_type_node,
+ iterator,
+ integer_one_node),
+ minus_one));
+
if (obey_regdecls)
{
use_variable (DECL_RTL (base));
if (base2)
use_variable (DECL_RTL (base2));
}
+
expand_end_loop ();
- 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));
}
- done_init:
+
+ /* Make sure to cleanup any partially constructed elements. */
+ expand_vec_init_catch_clause (rval, type, maxindex, iterator);
if (obey_regdecls)
- use_variable (DECL_RTL (rval));
+ {
+ use_variable (DECL_RTL (iterator));
+ use_variable (DECL_RTL (rval));
+ }
+
return rval;
}
@@ -2927,8 +2988,8 @@ expand_vec_init (decl, base, maxindex, init, from_array)
This does not call any destructors. */
tree
-build_x_delete (type, addr, which_delete, virtual_size)
- tree type, addr;
+build_x_delete (addr, which_delete, virtual_size)
+ tree addr;
int which_delete;
tree virtual_size;
{
@@ -2976,15 +3037,14 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
if (TREE_CODE (type) == POINTER_TYPE)
{
type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- if (!complete_type_or_else (type))
+ if (type != void_type_node && !complete_type_or_else (type, addr))
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_expr_list (NULL_TREE, addr));
+ return build_builtin_delete_call (addr);
}
if (TREE_SIDE_EFFECTS (addr))
addr = save_expr (addr);
@@ -3004,7 +3064,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
return error_mark_node;
}
return build_vec_delete (addr, array_type_nelts (type),
- auto_delete, integer_two_node,
+ auto_delete, integer_zero_node,
use_global_delete);
}
else
@@ -3050,8 +3110,7 @@ build_delete (type, addr, auto_delete, flags, 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_expr_list (NULL_TREE, addr));
+ tree call = build_builtin_delete_call (addr);
cond = fold (build (COND_EXPR, void_type_node, cond,
call, void_zero_node));
@@ -3076,7 +3135,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
ifexp = integer_one_node;
else
/* Handle deleting a null pointer. */
- ifexp = fold (build_binary_op (NE_EXPR, addr, integer_zero_node, 1));
+ ifexp = fold (build_binary_op (NE_EXPR, addr, integer_zero_node));
if (ifexp != integer_one_node)
expr = build (COND_EXPR, void_type_node,
@@ -3094,6 +3153,10 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
tree parent_auto_delete = auto_delete;
tree cond;
+ /* Set this again before we call anything, as we might get called
+ recursively. */
+ TYPE_HAS_DESTRUCTOR (type) = 1;
+
/* If we have member delete or vbases, we call delete in
finish_function. */
if (auto_delete == integer_zero_node)
@@ -3103,8 +3166,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
{
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_expr_list (NULL_TREE, addr)),
+ build_builtin_delete_call (addr),
void_zero_node);
}
else
diff --git a/contrib/gcc/cp/input.c b/contrib/gcc/cp/input.c
index 5a73fea..9148c86 100644
--- a/contrib/gcc/cp/input.c
+++ b/contrib/gcc/cp/input.c
@@ -1,5 +1,5 @@
/* Input handling for G++.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
This file is part of GNU CC.
@@ -53,12 +53,6 @@ static struct input_source *input, *free_inputs;
extern char *input_filename;
extern int lineno;
-#ifdef __GNUC__
-#define inline __inline__
-#else
-#define inline
-#endif
-
#if USE_CPPLIB
extern unsigned char *yy_cur, *yy_lim;
extern int yy_get_token ();
diff --git a/contrib/gcc/cp/lang-options.h b/contrib/gcc/cp/lang-options.h
index 5c50332..cfc6456 100644
--- a/contrib/gcc/cp/lang-options.h
+++ b/contrib/gcc/cp/lang-options.h
@@ -1,5 +1,5 @@
/* Definitions for switches for C++.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -23,9 +23,6 @@ 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", "Do not obey access control semantics" },
{ "-fall-virtual", "Make all member functions virtual" },
@@ -38,8 +35,10 @@ DEFINE_LANG_NAME ("C++")
{ "-fno-check-new", "" },
{ "-fconserve-space", "Reduce size of object files" },
{ "-fno-conserve-space", "" },
+ { "-fconst-strings", "" },
+ { "-fno-const-strings", "Make string literals `char[]' instead of `const char[]'" },
{ "-fdefault-inline", "" },
- { "-fno-default-inline", "Do not inline mmeber functions be default"},
+ { "-fno-default-inline", "Do not inline member functions by default"},
{ "-frtti", "" },
{ "-fno-rtti", "Do not generate run time type descriptor information" },
{ "-felide-constructors", "" },
@@ -54,23 +53,27 @@ DEFINE_LANG_NAME ("C++")
{ "-fno-guiding-decls", "" },
{ "-fgnu-keywords", "" },
{ "-fno-gnu-keywords", "Do not recognise GNU defined keywords" },
- { "-fhandle-exceptions", "Enable exception handling" },
+ { "-fhandle-exceptions", "" },
{ "-fno-handle-exceptions", "" },
{ "-fhandle-signatures", "Handle signature language constructs" },
{ "-fno-handle-signatures", "" },
- { "-fhonor-std", "Do not ignore the namespace standard" },
+ { "-fhonor-std", "Treat the namespace `std' as a normal namespace" },
{ "-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", "" },
+ { "-fimplicit-templates", "" },
+ { "-fno-implicit-templates", "Only emit explicit template instatiations" },
+ { "-fimplicit-inline-templates", "" },
+ { "-fno-implicit-inline-templates", "Only emit explicit instatiations of inline templates" },
+ { "-finit-priority", "Handle the init_priority attribute" },
+ { "-fno-init-priority", "" },
{ "-flabels-ok", "Labels can be used as first class objects" },
{ "-fno-labels-ok", "" },
- { "-fmemoize-lookups", "Enable caching of member function resolutions" },
+ { "-fmemoize-lookups", "" },
{ "-fno-memoize-lookups", "" },
- { "-fname-mangling-version-", "Set the version of name mangling to use" },
+ { "-fname-mangling-version-", "" },
{ "-fnew-abi", "Enable experimental ABI changes" },
{ "-fno-new-abi", "" },
{ "-fnonnull-objects", "" },
@@ -79,9 +82,11 @@ DEFINE_LANG_NAME ("C++")
{ "-fno-operator-names", "" },
{ "-foptional-diags", "" },
{ "-fno-optional-diags", "Disable optional diagnostics" },
+ { "-fpermissive", "Downgrade conformance errors to warnings" },
+ { "-fno-permissive", "" },
{ "-frepo", "Enable automatic template instantiation" },
{ "-fno-repo", "" },
- { "-fsave-memoized", "Save cache of member function resolutions" },
+ { "-fsave-memoized", "" },
{ "-fno-save-memoized", "" },
{ "-fsquangle", "Enable squashed name mangling" },
{ "-fno-squangle", "" },
@@ -92,6 +97,8 @@ DEFINE_LANG_NAME ("C++")
{ "-ftemplate-depth-", "Specify maximum template instantiation depth"},
{ "-fthis-is-variable", "Make 'this' not be type '* const'" },
{ "-fno-this-is-variable", "" },
+ { "-fvtable-gc", "Discard unused virtual functions" },
+ { "-fno-vtable-gc", "" },
{ "-fvtable-thunks", "Implement vtables using thunks" },
{ "-fno-vtable-thunks", "" },
{ "-fweak", "Emit common-like symbols as weak symbols" },
@@ -103,8 +110,8 @@ DEFINE_LANG_NAME ("C++")
{ "-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", "" },
+ { "-Wctor-dtor-privacy", "" },
+ { "-Wno-ctor-dtor-privacy", "Don't warn when all ctors/dtors are private" },
{ "-Wnon-virtual-dtor", "Warn about non virtual destructors" },
{ "-Wno-non-virtual-dtor", "" },
{ "-Wextern-inline", "Warn when a function is declared extern, then inline" },
@@ -113,11 +120,15 @@ DEFINE_LANG_NAME ("C++")
{ "-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", "" },
+ { "-Wpmf-conversions", "" },
+ { "-Wno-pmf-conversions", "Don't warn when type converting pointers to member functions" },
{ "-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", "" },
+ { "-Wnon-template-friend", "" },
+ { "-Wno-non-template-friend", "Don't warn when non-templatized friend functions are declared within a template" },
+ { "-Wdeprecated", "" },
+ { "-Wno-deprecated", "Don't announce deprecation of compiler features" },
diff --git a/contrib/gcc/cp/lang-specs.h b/contrib/gcc/cp/lang-specs.h
index b208ca1..648bc1f 100644
--- a/contrib/gcc/cp/lang-specs.h
+++ b/contrib/gcc/cp/lang-specs.h
@@ -1,5 +1,5 @@
/* Definitions for specs for C++.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -30,51 +30,54 @@ Boston, MA 02111-1307, USA. */
{"@c++",
#if USE_CPPLIB
{
- "%{E|M|MM:cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ "%{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\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\
+ -D__cplusplus\
%{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}\
+ %{ffast-math:-D__FAST_MATH__}\
%{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\
+ -lang-c++ %{nostdinc*} %{C} %{A*} %{I*} %{P} %{$} %I\
+ %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1\
+ -D__GNUC_MINOR__=%v2} -D__cplusplus\
%{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__}}\
+ %{ffast-math:-D__FAST_MATH__}\
%{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*}\
+ %{f*} %{+e*} %{aux-info*} %{Qn:-fno-ident}\
%{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\
+ {"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\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\
+ -D__cplusplus\
%{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}\
+ %{ffast-math:-D__FAST_MATH__}\
%{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\
%{!Q:-quiet} -dumpbase %b.cc %{d*} %{m*} %{a}\
%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
%{v:-version} %{pg:-p} %{p}\
- %{f*} %{+e*} %{aux-info*}\
+ %{f*} %{+e*} %{aux-info*} %{Qn:-fno-ident}\
%{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\
@@ -86,7 +89,7 @@ Boston, MA 02111-1307, USA. */
{"%{!M:%{!MM:%{!E:cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\
%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
%{v:-version} %{pg:-p} %{p}\
- %{f*} %{+e*} %{aux-info*}\
+ %{f*} %{+e*} %{aux-info*} %{Qn:-fno-ident}\
%{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\
diff --git a/contrib/gcc/cp/lex.c b/contrib/gcc/cp/lex.c
index 57639ad..d9f2262 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-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
-#include <setjmp.h>
#include "input.h"
#include "tree.h"
#include "lex.h"
@@ -39,14 +38,8 @@ Boston, MA 02111-1307, USA. */
#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 "mbchar.h"
#include <locale.h>
#endif
@@ -61,28 +54,26 @@ extern struct obstack permanent_obstack;
extern struct obstack *current_obstack, *saveable_obstack;
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 tree get_time_identifier PROTO((const 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 interface_strcmp PROTO((const char *));
static int readescape PROTO((int *));
-static char *extend_token_buffer PROTO((char *));
+static char *extend_token_buffer PROTO((const char *));
static void consume_string PROTO((struct obstack *, int));
-static void set_typedecl_interface_info PROTO((tree, tree));
+static int set_typedecl_interface_info PROTO((tree *, void *));
static void feed_defarg PROTO((tree, tree));
-static int set_vardecl_interface_info PROTO((tree, tree));
+static int set_vardecl_interface_info PROTO((tree *, void *));
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));
+static int handle_cp_pragma PROTO((const char *));
+#ifdef HANDLE_GENERIC_PRAGMAS
+static int handle_generic_pragma PROTO((int));
#endif
#ifdef GATHER_STATISTICS
#ifdef REDUCE_LENGTH
@@ -90,12 +81,16 @@ static int reduce_cmp PROTO((int *, int *));
static int token_cmp PROTO((int *, int *));
#endif
#endif
+static void begin_definition_of_inclass_inline PROTO((struct pending_inline*));
+static void parse_float PROTO((PTR));
+static int is_global PROTO((tree));
+static void init_filename_times PROTO((void));
/* Given a file name X, return the nondirectory portion.
Keep in mind that X can be computed more than once. */
char *
file_name_nondirectory (x)
- char *x;
+ const char *x;
{
char *tmp = (char *) rindex (x, '/');
if (DIR_SEPARATOR != '/' && ! tmp)
@@ -103,7 +98,7 @@ file_name_nondirectory (x)
if (tmp)
return (char *) (tmp + 1);
else
- return x;
+ return (char *) x;
}
/* This obstack is needed to hold text. It is not safe to use
@@ -319,7 +314,7 @@ static int ignore_escape_flag = 0;
static tree
get_time_identifier (name)
- char *name;
+ const char *name;
{
tree time_identifier;
int len = strlen (name);
@@ -328,12 +323,13 @@ get_time_identifier (name)
bcopy (name, buf+5, len);
buf[len+5] = '\0';
time_identifier = get_identifier (buf);
- if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE)
+ if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
{
push_obstacks_nochange ();
end_temporary_allocation ();
- IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
- IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
+ TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
+ TIME_IDENTIFIER_FILEINFO (time_identifier)
+ = build_int_2 (0, 1);
SET_IDENTIFIER_GLOBAL_VALUE (time_identifier, filename_times);
filename_times = time_identifier;
pop_obstacks ();
@@ -383,7 +379,7 @@ int cplus_tree_code_length[] = {
Used for printing out the tree and error messages. */
#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
-char *cplus_tree_code_name[] = {
+const char *cplus_tree_code_name[] = {
"@@dummy",
#include "cp-tree.def"
};
@@ -394,6 +390,12 @@ char *cplus_tree_code_name[] = {
void
lang_init_options ()
{
+#if USE_CPPLIB
+ cpp_reader_init (&parse_in);
+ parse_in.opts = &parse_options;
+ cpp_options_init (&parse_options);
+#endif
+
/* Default exceptions on. */
flag_exceptions = 1;
}
@@ -401,11 +403,14 @@ lang_init_options ()
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. */
+#if ! USE_CPPLIB
put_back (check_newline ());
+#else
+ check_newline ();
+ yy_cur--;
#endif
if (flag_gnu_xref) GNU_xref_begin (input_filename);
init_repo (input_filename);
@@ -424,7 +429,7 @@ lang_identify ()
return "cplusplus";
}
-void
+static void
init_filename_times ()
{
this_filename_time = get_time_identifier ("<top level>");
@@ -432,7 +437,8 @@ init_filename_times ()
{
header_time = 0;
body_time = my_get_run_time ();
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time)) = body_time;
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+ = body_time;
}
}
@@ -474,13 +480,22 @@ init_parse (filename)
int i;
-#if USE_CPPLIB
- yy_cur = "\n";
- yy_lim = yy_cur + 1;
+#ifdef MULTIBYTE_CHARS
+ /* Change to the native locale for multibyte conversions. */
+ setlocale (LC_CTYPE, "");
+ literal_codeset = getenv ("LANG");
+#endif
+#if USE_CPPLIB
parse_in.show_column = 1;
if (! cpp_start_read (&parse_in, filename))
abort ();
+
+ /* cpp_start_read always puts at least one line directive into the
+ token buffer. We must arrange to read it out here. */
+ yy_cur = parse_in.token_buffer;
+ yy_lim = CPP_PWRITTEN (&parse_in);
+
#else
/* Open input file. */
if (filename == 0 || !strcmp (filename, "-"))
@@ -635,7 +650,7 @@ init_parse (filename)
IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_NEW_EXPR]) = 1;
ansi_opname[(int) VEC_DELETE_EXPR] = get_identifier ("__vd");
IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_DELETE_EXPR]) = 1;
- ansi_opname[(int) TYPE_EXPR] = get_identifier ("__op");
+ ansi_opname[(int) TYPE_EXPR] = get_identifier (OPERATOR_TYPENAME_FORMAT);
IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1;
/* This is not true: these operators are not defined in ANSI,
@@ -664,67 +679,28 @@ init_parse (filename)
token_buffer = (char *) xmalloc (maxtoken + 2);
ridpointers[(int) RID_INT] = get_identifier ("int");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]));
ridpointers[(int) RID_BOOL] = get_identifier ("bool");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_BOOL],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_BOOL]));
ridpointers[(int) RID_CHAR] = get_identifier ("char");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CHAR],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]));
ridpointers[(int) RID_VOID] = get_identifier ("void");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOID],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]));
ridpointers[(int) RID_FLOAT] = get_identifier ("float");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FLOAT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_FLOAT]));
ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_DOUBLE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_DOUBLE]));
ridpointers[(int) RID_SHORT] = get_identifier ("short");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SHORT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_SHORT]));
ridpointers[(int) RID_LONG] = get_identifier ("long");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_LONG],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]));
ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_UNSIGNED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]));
ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SIGNED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_SIGNED]));
ridpointers[(int) RID_INLINE] = get_identifier ("inline");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INLINE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_INLINE]));
ridpointers[(int) RID_CONST] = get_identifier ("const");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CONST],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_CONST]));
ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOLATILE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VOLATILE]));
+ ridpointers[(int) RID_RESTRICT] = get_identifier ("__restrict");
ridpointers[(int) RID_AUTO] = get_identifier ("auto");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_AUTO],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_AUTO]));
ridpointers[(int) RID_STATIC] = get_identifier ("static");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_STATIC],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]));
ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXTERN],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]));
ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TYPEDEF],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_TYPEDEF]));
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. */
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]));
class_type_node = build_int_2 (class_type, 0);
TREE_TYPE (class_type_node) = class_type_node;
ridpointers[(int) RID_CLASS] = class_type_node;
@@ -742,37 +718,26 @@ init_parse (filename)
ridpointers[(int) RID_ENUM] = enum_type_node;
ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VIRTUAL],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VIRTUAL]));
ridpointers[(int) RID_EXPLICIT] = get_identifier ("explicit");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXPLICIT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_EXPLICIT]));
+ ridpointers[(int) RID_EXPORT] = get_identifier ("export");
ridpointers[(int) RID_FRIEND] = get_identifier ("friend");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FRIEND],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_FRIEND]));
ridpointers[(int) RID_PUBLIC] = get_identifier ("public");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PUBLIC],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PUBLIC]));
ridpointers[(int) RID_PRIVATE] = get_identifier ("private");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PRIVATE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PRIVATE]));
ridpointers[(int) RID_PROTECTED] = get_identifier ("protected");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PROTECTED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PROTECTED]));
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++. */
ridpointers[(int) RID_MUTABLE] = get_identifier ("mutable");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_MUTABLE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_MUTABLE]));
/* Signature handling extensions. */
signature_type_node = build_int_2 (signature_type, 0);
TREE_TYPE (signature_type_node) = signature_type_node;
ridpointers[(int) RID_SIGNATURE] = signature_type_node;
+ /* Create the built-in __null node. Note that we can't yet call for
+ type_for_size here because integer_type_node and so forth are not
+ set up. Therefore, we don't set the type of these nodes until
+ init_decl_processing. */
null_node = build_int_2 (0, 0);
ridpointers[RID_NULL] = null_node;
@@ -1123,7 +1088,7 @@ extract_interface_info ()
}
if (!fileinfo)
fileinfo = get_time_identifier (input_filename);
- fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
+ fileinfo = TIME_IDENTIFIER_FILEINFO (fileinfo);
interface_only = TREE_INT_CST_LOW (fileinfo);
interface_unknown = TREE_INT_CST_HIGH (fileinfo);
}
@@ -1133,15 +1098,15 @@ extract_interface_info ()
static int
interface_strcmp (s)
- char *s;
+ const char *s;
{
/* Set the interface/implementation bits for this scope. */
struct impl_files *ifiles;
- char *s1;
+ const char *s1;
for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next)
{
- char *t1 = ifiles->filename;
+ const char *t1 = ifiles->filename;
s1 = s;
if (*s1 != *t1 || *s1 == 0)
@@ -1169,37 +1134,71 @@ interface_strcmp (s)
return 1;
}
-static void
-set_typedecl_interface_info (prev, vars)
- tree prev, vars;
+static int
+set_typedecl_interface_info (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
- tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
- tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
- tree type = TREE_TYPE (vars);
+ tree id = get_time_identifier (DECL_SOURCE_FILE (*t));
+ tree fileinfo = TIME_IDENTIFIER_FILEINFO (id);
+ tree type = TREE_TYPE (*t);
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 (*t)));
+ return 0;
}
static int
-set_vardecl_interface_info (prev, vars)
- tree prev, vars;
+set_vardecl_interface_info (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
- tree type = DECL_CONTEXT (vars);
+ tree type = DECL_CONTEXT (*t);
if (CLASSTYPE_INTERFACE_KNOWN (type))
{
if (CLASSTYPE_INTERFACE_ONLY (type))
- set_typedecl_interface_info (prev, TYPE_MAIN_DECL (type));
+ set_typedecl_interface_info (&TYPE_MAIN_DECL (type), data);
else
CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
- DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
- TREE_PUBLIC (vars) = 1;
+ DECL_EXTERNAL (*t) = CLASSTYPE_INTERFACE_ONLY (type);
+ TREE_PUBLIC (*t) = 1;
return 1;
}
return 0;
}
+/* Set up the state required to correctly handle the definition of the
+ inline function whose preparsed state has been saved in PI. */
+
+static void
+begin_definition_of_inclass_inline (pi)
+ struct pending_inline* pi;
+{
+ tree context;
+
+ if (!pi->fndecl)
+ return;
+
+ /* If this is an inline function in a local class, we must make sure
+ that we save all pertinent information about the function
+ surrounding the local class. */
+ context = hack_decl_function_context (pi->fndecl);
+ if (context)
+ push_cp_function_context (context);
+
+ feed_input (pi->buf, pi->len);
+ lineno = pi->lineno;
+ input_filename = pi->filename;
+ yychar = PRE_PARSED_FUNCTION_DECL;
+ yylval.ttype = build_tree_list ((tree) pi, pi->fndecl);
+ /* Pass back a handle to the rest of the inline functions, so that they
+ can be processed later. */
+ DECL_PENDING_INLINE_INFO (pi->fndecl) = 0;
+ interface_unknown = pi->interface == 1;
+ interface_only = pi->interface == 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
@@ -1209,7 +1208,6 @@ 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)
@@ -1236,32 +1234,7 @@ do_pending_inlines ()
return;
/* Now start processing the first inline function. */
- 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);
- lineno = t->lineno;
-#if 0
- if (input_filename != t->filename)
- {
- input_filename = t->filename;
- /* Get interface/implementation back in sync. */
- extract_interface_info ();
- }
-#else
- input_filename = t->filename;
- interface_unknown = t->interface == 1;
- interface_only = t->interface == 0;
-#endif
- yychar = PRE_PARSED_FUNCTION_DECL;
- }
- /* 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);
- DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
+ begin_definition_of_inclass_inline (t);
}
static int nextchar = -1;
@@ -1277,7 +1250,6 @@ process_next_inline (t)
tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
context = hack_decl_function_context (i->fndecl);
- maybe_end_member_template_processing (i->fndecl);
if (context)
pop_cp_function_context (context);
i = i->next;
@@ -1295,24 +1267,8 @@ process_next_inline (t)
}
yychar = YYEMPTY;
end_input ();
- if (i && i->fndecl != NULL_TREE)
- {
- 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);
- DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
- }
if (i)
- {
- interface_unknown = i->interface == 1;
- interface_only = i->interface == 0;
- }
+ begin_definition_of_inclass_inline (i);
else
extract_interface_info ();
}
@@ -1538,10 +1494,12 @@ reinit_parse_for_block (pyychar, obstackp)
else if (pyychar == ':')
{
obstack_1grow (obstackp, pyychar);
+ /* Add a space so we don't get confused by ': ::A(20)'. */
+ obstack_1grow (obstackp, ' ');
look_for_lbrac = 1;
blev = 0;
}
- else if (pyychar == RETURN)
+ else if (pyychar == RETURN_KEYWORD)
{
obstack_grow (obstackp, "return", 6);
look_for_lbrac = 1;
@@ -1928,12 +1886,12 @@ do_pending_defargs ()
if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
{
- maybe_end_member_template_processing (defarg_fn);
+ maybe_end_member_template_processing ();
check_default_args (defarg_fn);
}
poplevel (0, 0, 0);
- pop_nested_class (1);
+ pop_nested_class ();
}
}
@@ -1977,7 +1935,7 @@ cons_up_default_function (type, full_name, kind)
break;
case 3:
- type = build_type_variant (type, 1, 0);
+ type = build_qualified_type (type, TYPE_QUAL_CONST);
/* Fall through... */
case 4:
/* According to ARM $12.8, the default copy ctor will be declared, but
@@ -1995,7 +1953,7 @@ cons_up_default_function (type, full_name, kind)
declspecs = build_decl_list (NULL_TREE, type);
if (kind == 5)
- type = build_type_variant (type, 1, 0);
+ type = build_qualified_type (type, TYPE_QUAL_CONST);
name = ansi_opname [(int) MODIFY_EXPR];
@@ -2113,7 +2071,7 @@ note_got_semicolon (type)
{
if (TREE_CODE_CLASS (TREE_CODE (type)) != 't')
my_friendly_abort (60);
- if (IS_AGGR_TYPE (type))
+ if (CLASS_TYPE_P (type))
CLASSTYPE_GOT_SEMICOLON (type) = 1;
}
@@ -2182,7 +2140,7 @@ skip_white_space (c)
static char *
extend_token_buffer (p)
- char *p;
+ const char *p;
{
int offset = p - token_buffer;
@@ -2208,6 +2166,32 @@ get_last_nonwhite_on_line ()
return c;
}
+#if defined HANDLE_PRAGMA
+/* Local versions of these macros, that can be passed as function pointers. */
+static int
+pragma_getc ()
+{
+ int c;
+
+ if (nextchar != EOF)
+ {
+ c = nextchar;
+ nextchar = EOF;
+ }
+ else
+ c = getch ();
+
+ return c;
+}
+
+static void
+pragma_ungetc (arg)
+ int arg;
+{
+ yyungetc (arg, 0);
+}
+#endif /* HANDLE_PRAGMA */
+
/* At the beginning of a line, increment the line number
and process any #-directive on this line.
If the line is a #-directive, read the entire line and return a newline.
@@ -2215,13 +2199,12 @@ get_last_nonwhite_on_line ()
int linemode;
-static int handle_cp_pragma PROTO((char *));
-
static int
check_newline ()
{
register int c;
register int token;
+ int saw_line = 0;
/* Read first nonwhite char on the line. Do this before incrementing the
line number, in case we're at the end of saved text. */
@@ -2251,7 +2234,7 @@ check_newline ()
it and ignore it; otherwise, ignore the line, with an error
if the word isn't `pragma'. */
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
+ if (ISALPHA (c))
{
if (c == 'p')
{
@@ -2274,21 +2257,29 @@ check_newline ()
else if (token == END_OF_LINE)
goto skipline;
-#ifdef HANDLE_SYSV_PRAGMA
- if (handle_sysv_pragma (token))
- goto skipline;
-#else
#ifdef HANDLE_PRAGMA
-#if USE_CPPLIB
- /* TODO: ??? */
- goto skipline;
-#else
- if (HANDLE_PRAGMA (finput, yylval.ttype))
- goto skipline;
-#endif /* !USE_CPPLIB */
-#endif
-#endif
+ /* We invoke HANDLE_PRAGMA before HANDLE_GENERIC_PRAGMAS
+ (if both are defined), in order to give the back
+ end a chance to override the interpretation of
+ SYSV style pragmas. */
+ if (HANDLE_PRAGMA (pragma_getc, pragma_ungetc,
+ IDENTIFIER_POINTER (yylval.ttype)))
+ goto skipline;
+#endif /* HANDLE_PRAGMA */
+
+#ifdef HANDLE_GENERIC_PRAGMAS
+ if (handle_generic_pragma (token))
+ goto skipline;
+#endif /* HANDLE_GENERIC_PRAGMAS */
+
+ /* Issue a warning message if we have been asked to do so.
+ Ignoring unknown pragmas in system header file unless
+ an explcit -Wunknown-pragmas has been given. */
+ if (warn_unknown_pragmas > 1
+ || (warn_unknown_pragmas && ! in_system_header))
+ warning ("ignoring pragma: %s", token_buffer);
}
+
goto skipline;
}
else if (c == 'd')
@@ -2322,7 +2313,10 @@ check_newline ()
&& getch () == 'n'
&& getch () == 'e'
&& ((c = getch ()) == ' ' || c == '\t'))
- goto linenum;
+ {
+ saw_line = 1;
+ goto linenum;
+ }
}
else if (c == 'i')
{
@@ -2419,9 +2413,16 @@ linenum:
/* More follows: it must be a string constant (filename). */
- /* Read the string constant, but don't treat \ as special. */
- ignore_escape_flag = 1;
+ if (saw_line)
+ {
+ /* Don't treat \ as special if we are processing #line 1 "...".
+ If you want it to be treated specially, use # 1 "...". */
+ ignore_escape_flag = 1;
+ }
+
+ /* Read the string constant. */
token = real_yylex ();
+
ignore_escape_flag = 0;
if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
@@ -2438,7 +2439,7 @@ linenum:
int this_time = my_get_run_time ();
tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
header_time += this_time - body_time;
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+= this_time - body_time;
this_filename_time = time_identifier;
body_time = this_time;
@@ -2463,7 +2464,14 @@ linenum:
main_input_filename = input_filename;
if (write_virtuals == 3)
- walk_vtables (set_typedecl_interface_info, set_vardecl_interface_info);
+ {
+ walk_globals (vtable_decl_p,
+ set_vardecl_interface_info,
+ /*data=*/0);
+ walk_globals (vtype_decl_p,
+ set_typedecl_interface_info,
+ /*data=*/0);
+ }
}
extract_interface_info ();
@@ -2662,7 +2670,8 @@ readescape (ignore_ptr)
;
else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
|| (count > 1
- && ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
+ && (((unsigned)1 <<
+ (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
<= firstdig)))
pedwarn ("hex escape out of range");
return code;
@@ -2727,7 +2736,7 @@ readescape (ignore_ptr)
pedwarn ("unknown escape sequence `\\%c'", c);
return c;
}
- if (c >= 040 && c < 0177)
+ if (ISGRAPH (c))
pedwarn ("unknown escape sequence `\\%c'", c);
else
pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c);
@@ -2746,6 +2755,7 @@ int
identifier_type (decl)
tree decl;
{
+ tree t;
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
@@ -2755,7 +2765,10 @@ identifier_type (decl)
}
if (looking_for_template && really_overloaded_fn (decl))
{
- tree t;
+ /* See through a baselink. */
+ if (TREE_CODE (decl) == TREE_LIST)
+ decl = TREE_VALUE (decl);
+
for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t))
if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
return PFUNCNAME;
@@ -2764,10 +2777,20 @@ identifier_type (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))
+ if (DECL_ARTIFICIAL (decl) && TREE_TYPE (decl) == current_class_type)
return SELFNAME;
+
+ /* A constructor declarator for a template type will get here as an
+ implicit typename, a TYPENAME_TYPE with a type. */
+ t = got_scope;
+ if (t && TREE_CODE (t) == TYPENAME_TYPE)
+ t = TREE_TYPE (t);
+ decl = TREE_TYPE (decl);
+ if (TREE_CODE (decl) == TYPENAME_TYPE)
+ decl = TREE_TYPE (decl);
+ if (t && t == decl)
+ return SELFNAME;
+
return TYPENAME;
}
@@ -2801,6 +2824,9 @@ is_global (d)
while (1)
switch (TREE_CODE (d))
{
+ case ERROR_MARK:
+ return 1;
+
case OVERLOAD: d = OVL_FUNCTION (d); continue;
case TREE_LIST: d = TREE_VALUE (d); continue;
default:
@@ -2843,12 +2869,19 @@ do_identifier (token, parsing, args)
|| TREE_CODE (field) == CONST_DECL
|| TREE_CODE (field) == TEMPLATE_DECL)
id = field;
+ else if (TREE_CODE (field) == TYPE_DECL
+ && DECL_ARTIFICIAL (field)
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (field)))
+ /* When we did name-lookup before, we will have eschewed
+ implicit typenames in favor of global bindings. Therefore,
+ if lookup_field returns an implicit typename, but ID is not
+ an implicit typename, then we should skip this one, too. */
+ ;
else if (TREE_CODE (field) != FIELD_DECL)
my_friendly_abort (61);
else
{
- cp_error ("invalid use of member `%D' from base class `%T'", field,
- DECL_FIELD_CONTEXT (field));
+ cp_error ("invalid use of member `%D'", field);
id = error_mark_node;
return id;
}
@@ -2857,44 +2890,41 @@ do_identifier (token, parsing, args)
/* 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);
- }
+ /* 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 && parsing
- && TYPE_BEING_DEFINED (current_class_type)
- && ! IDENTIFIER_CLASS_VALUE (token)
+ if (id && parsing
/* 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)
- {
- if (id == error_mark_node && current_class_type != NULL_TREE)
- {
- id = lookup_nested_field (token, 1);
- /* In lookup_nested_field(), we marked this so we can gracefully
- leave this whole mess. */
- if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node)
- return id;
- }
+ maybe_note_name_used_in_class (token, id);
+ if (id == error_mark_node)
+ {
+ /* lookup_name quietly returns error_mark_node if we're parsing,
+ as we don't want to complain about an identifier that ends up
+ being used as a declarator. So we call it again to get the error
+ message. */
+ id = lookup_name (token, 0);
+ return error_mark_node;
+ }
+
+ if (!id)
+ {
if (current_template_parms)
- return build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
+ return build_min_nt (LOOKUP_EXPR, token);
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)
+ else if (in_call && ! flag_strict_prototype)
{
id = implicitly_declare (token);
}
@@ -2968,37 +2998,39 @@ do_identifier (token, parsing, args)
/* TREE_USED is set in `hack_identifier'. */
if (TREE_CODE (id) == CONST_DECL)
{
+ /* Check access. */
if (IDENTIFIER_CLASS_VALUE (token) == id)
- {
- /* Check access. */
- 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'. */
- }
- if (! processing_template_decl
- || (DECL_INITIAL (id)
- && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
+ enforce_access (DECL_REAL_CONTEXT(id), id);
+ if (!processing_template_decl || DECL_TEMPLATE_PARM_P (id))
id = DECL_INITIAL (id);
}
else
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 */
- }
+ /* We must look up dependent names when the template is
+ instantiated, not while parsing it. For now, we don't
+ distinguish between dependent and independent names. So, for
+ example, we look up all overloaded functions at
+ instantiation-time, even though in some cases we should just use
+ the DECL we have here. We also use LOOKUP_EXPRs to find things
+ like local variables, rather than creating TEMPLATE_DECLs for the
+ local variables and then finding matching instantiations. */
+ if (current_template_parms
+ && (is_overloaded_fn (id)
+ /* If it's not going to be around at instantiation time, we
+ look it up then. This is a hack, and should go when we
+ really get dependent/independent name lookup right. */
+ || !TREE_PERMANENT (id)
+ /* Some local VAR_DECLs (such as those for local variables
+ in member functions of local classes) are built on the
+ permanent obstack. */
+ || (TREE_CODE (id) == VAR_DECL
+ && CP_DECL_CONTEXT (id)
+ && TREE_CODE (CP_DECL_CONTEXT (id)) == FUNCTION_DECL)
+ || TREE_CODE (id) == PARM_DECL
+ || TREE_CODE (id) == RESULT_DECL
+ || TREE_CODE (id) == USING_DECL))
+ id = build_min_nt (LOOKUP_EXPR, token);
return id;
}
@@ -3027,17 +3059,17 @@ do_scoped_id (token, parsing)
{
if (processing_template_decl)
{
- id = build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
+ id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
return id;
}
- if (parsing && (yychar == '(' || yychar == LEFT_RIGHT))
+ if (parsing && (yychar == '(' || yychar == LEFT_RIGHT)
+ && ! flag_strict_prototype)
id = implicitly_declare (token);
else
{
if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node)
- error ("undeclared variable `%s' (first use here)",
- IDENTIFIER_POINTER (token));
+ cp_error ("`::%D' undeclared (first use here)", token);
id = error_mark_node;
/* Prevent repeated error messages. */
SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node);
@@ -3064,9 +3096,9 @@ do_scoped_id (token, parsing)
{
if (is_overloaded_fn (id))
{
- id = build_min (LOOKUP_EXPR, unknown_type_node,
- token, get_first_fn (id));
+ id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
+ return id;
}
/* else just use the decl */
}
@@ -3081,16 +3113,20 @@ identifier_typedecl_value (node)
type = IDENTIFIER_TYPE_VALUE (node);
if (type == NULL_TREE)
return NULL_TREE;
-#define do(X) \
- { \
- t = (X); \
- if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \
- return t; \
- }
- do (IDENTIFIER_LOCAL_VALUE (node));
- do (IDENTIFIER_CLASS_VALUE (node));
- do (IDENTIFIER_NAMESPACE_VALUE (node));
-#undef do
+
+ if (IDENTIFIER_BINDING (node))
+ {
+ t = IDENTIFIER_VALUE (node);
+ if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
+ return t;
+ }
+ if (IDENTIFIER_NAMESPACE_VALUE (node))
+ {
+ t = IDENTIFIER_NAMESPACE_VALUE (node);
+ if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
+ return t;
+ }
+
/* Will this one ever happen? */
if (TYPE_MAIN_DECL (type))
return TYPE_MAIN_DECL (type);
@@ -3100,6 +3136,103 @@ identifier_typedecl_value (node)
return NULL_TREE;
}
+struct pf_args
+{
+ /* Input */
+ /* I/O */
+ char *p;
+ int c;
+ int imag;
+ tree type;
+ /* Output */
+ REAL_VALUE_TYPE value;
+};
+
+static void
+parse_float (data)
+ PTR data;
+{
+ struct pf_args * args = (struct pf_args *) data;
+ 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 (args->p - token_buffer + 1);
+ bcopy (token_buffer, copy, args->p - token_buffer + 1);
+
+ while (1)
+ {
+ int lose = 0;
+
+ /* Read the suffixes to choose a data type. */
+ switch (args->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 (args->imag)
+ error ("more than one `i' or `j' in numeric constant");
+ else if (pedantic)
+ pedwarn ("ANSI C++ forbids imaginary numeric constants");
+ args->imag = 1;
+ break;
+
+ default:
+ lose = 1;
+ }
+
+ if (lose)
+ break;
+
+ if (args->p >= token_buffer + maxtoken - 3)
+ args->p = extend_token_buffer (args->p);
+ *(args->p++) = args->c;
+ *(args->p) = 0;
+ args->c = getch ();
+ }
+
+ /* The second argument, machine_mode, of REAL_VALUE_ATOF
+ tells the desired precision of the binary result
+ of decimal-to-binary conversion. */
+
+ if (fflag)
+ {
+ if (lflag)
+ error ("both `f' and `l' in floating constant");
+
+ args->type = float_type_node;
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->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 (args->value) && pedantic)
+ warning ("floating point number exceeds range of `float'");
+ }
+ else if (lflag)
+ {
+ args->type = long_double_type_node;
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `long double'");
+ }
+ else
+ {
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `double'");
+ }
+}
+
int
real_yylex ()
{
@@ -3635,7 +3768,7 @@ real_yylex ()
int exceeds_double = 0;
int imag = 0;
REAL_VALUE_TYPE value;
- jmp_buf handler;
+ struct pf_args args;
/* Read explicit exponent if any, and put it in tokenbuf. */
@@ -3664,97 +3797,31 @@ real_yylex ()
*p = 0;
errno = 0;
+ /* Setup input for parse_float() */
+ args.p = p;
+ args.c = c;
+ args.imag = imag;
+ args.type = type;
+
/* Convert string to a double, checking for overflow. */
- if (setjmp (handler))
+ if (do_float_handler (parse_float, (PTR) &args))
{
- error ("floating constant out of range");
- value = dconst0;
+ /* Receive output from parse_float() */
+ value = args.value;
}
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);
-
- while (1)
- {
- int lose = 0;
-
- /* 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. */
-
- 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);
+ /* We got an exception from parse_float() */
+ error ("floating constant out of range");
+ value = dconst0;
}
+
+ /* Receive output from parse_float() */
+ p = args.p;
+ c = args.c;
+ imag = args.imag;
+ type = args.type;
+
#ifdef ERANGE
if (errno == ERANGE && pedantic)
{
@@ -3808,7 +3875,7 @@ real_yylex ()
{
if (spec_long_long)
error ("three `l's in integer constant");
- else if (pedantic)
+ else if (pedantic && ! in_system_header && warn_long_long)
pedwarn ("ANSI C++ forbids long long integer constants");
spec_long_long = 1;
}
@@ -3922,30 +3989,27 @@ real_yylex ()
{
register int result = 0;
register int num_chars = 0;
+ int chars_seen = 0;
unsigned width = TYPE_PRECISION (char_type_node);
int max_chars;
-
- if (wide_flag)
- {
- width = WCHAR_TYPE_SIZE;
#ifdef MULTIBYTE_CHARS
- max_chars = MB_CUR_MAX;
-#else
- max_chars = 1;
+ int longest_char = local_mb_cur_max ();
+ (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
#endif
- }
- else
- max_chars = TYPE_PRECISION (integer_type_node) / width;
+
+ max_chars = TYPE_PRECISION (integer_type_node) / width;
+ if (wide_flag)
+ width = WCHAR_TYPE_SIZE;
while (1)
{
tryagain:
-
c = getch ();
if (c == '\'' || c == EOF)
break;
+ ++chars_seen;
if (c == '\\')
{
int ignore = 0;
@@ -3953,8 +4017,8 @@ real_yylex ()
if (ignore)
goto tryagain;
if (width < HOST_BITS_PER_INT
- && (unsigned) c >= (1 << width))
- warning ("escape sequence out of range for character");
+ && (unsigned) c >= ((unsigned)1 << width))
+ pedwarn ("escape sequence out of range for character");
#ifdef MAP_CHARACTER
if (ISPRINT (c))
c = MAP_CHARACTER (c);
@@ -3963,21 +4027,79 @@ real_yylex ()
else if (c == '\n')
{
if (pedantic)
- pedwarn ("ANSI C++ forbids newline in character constant");
+ pedwarn ("ANSI C forbids newline in character constant");
lineno++;
}
-#ifdef MAP_CHARACTER
else
- c = MAP_CHARACTER (c);
+ {
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int i;
+ int char_len = -1;
+ for (i = 1; i <= longest_char; ++i)
+ {
+ if (i > maxtoken - 4)
+ extend_token_buffer (token_buffer);
+
+ token_buffer[i] = c;
+ char_len = local_mbtowc (& wc,
+ token_buffer + 1,
+ i);
+ if (char_len != -1)
+ break;
+ c = getch ();
+ }
+ if (char_len > 1)
+ {
+ /* mbtowc sometimes needs an extra char before accepting */
+ if (char_len < i)
+ put_back (c);
+ if (! wide_flag)
+ {
+ /* Merge character into result; ignore excess chars. */
+ for (i = 1; i <= char_len; ++i)
+ {
+ if (i > max_chars)
+ break;
+ if (width < HOST_BITS_PER_INT)
+ result = (result << width)
+ | (token_buffer[i]
+ & ((1 << width) - 1));
+ else
+ result = token_buffer[i];
+ }
+ num_chars += char_len;
+ goto tryagain;
+ }
+ c = wc;
+ }
+ else
+ {
+ if (char_len == -1)
+ warning ("Ignoring invalid multibyte character");
+ if (wide_flag)
+ c = wc;
+#ifdef MAP_CHARACTER
+ else
+ c = MAP_CHARACTER (c);
#endif
+ }
+#else /* ! MULTIBYTE_CHARS */
+#ifdef MAP_CHARACTER
+ c = MAP_CHARACTER (c);
+#endif
+#endif /* ! MULTIBYTE_CHARS */
+ }
- num_chars++;
- if (num_chars > maxtoken - 4)
- extend_token_buffer (token_buffer);
-
- token_buffer[num_chars] = c;
+ if (wide_flag)
+ {
+ if (chars_seen == 1) /* only keep the first one */
+ result = c;
+ goto tryagain;
+ }
/* Merge character into result; ignore excess chars. */
+ num_chars++;
if (num_chars < max_chars + 1)
{
if (width < HOST_BITS_PER_INT)
@@ -3987,19 +4109,16 @@ real_yylex ()
}
}
- token_buffer[num_chars + 1] = '\'';
- token_buffer[num_chars + 2] = 0;
-
if (c != '\'')
error ("malformatted character constant");
- else if (num_chars == 0)
+ else if (chars_seen == 0)
error ("empty character constant");
else if (num_chars > max_chars)
{
num_chars = max_chars;
error ("character constant too long");
}
- else if (num_chars != 1 && warn_multichar)
+ else if (chars_seen != 1 && warn_multichar)
warning ("multi-character character constant");
/* If char type is signed, sign-extend the constant. */
@@ -4012,37 +4131,21 @@ real_yylex ()
else if (TREE_UNSIGNED (char_type_node)
|| ((result >> (num_bits - 1)) & 1) == 0)
yylval.ttype
- = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0
+ = build_int_2 (result & (~(unsigned HOST_WIDE_INT) 0
>> (HOST_BITS_PER_WIDE_INT - num_bits)),
0);
else
yylval.ttype
- = build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0
+ = build_int_2 (result | ~(~(unsigned HOST_WIDE_INT) 0
>> (HOST_BITS_PER_WIDE_INT - num_bits)),
-1);
- if (num_chars<=1)
+ if (chars_seen <= 1)
TREE_TYPE (yylval.ttype) = char_type_node;
else
TREE_TYPE (yylval.ttype) = integer_type_node;
}
else
{
-#ifdef MULTIBYTE_CHARS
- /* Set the initial shift state and convert the next sequence. */
- result = 0;
- /* In all locales L'\0' is zero and mbtowc will return zero,
- so don't use it. */
- if (num_chars > 1
- || (num_chars == 1 && token_buffer[1] != '\0'))
- {
- wchar_t wc;
- (void) mbtowc (NULL, NULL, 0);
- if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars)
- result = wc;
- else
- warning ("Ignoring invalid multibyte character");
- }
-#endif
yylval.ttype = build_int_2 (result, 0);
TREE_TYPE (yylval.ttype) = wchar_type_node;
}
@@ -4055,6 +4158,12 @@ real_yylex ()
string_constant:
{
register char *p;
+ unsigned width = wide_flag ? WCHAR_TYPE_SIZE
+ : TYPE_PRECISION (char_type_node);
+#ifdef MULTIBYTE_CHARS
+ int longest_char = local_mb_cur_max ();
+ (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
+#endif
c = getch ();
p = token_buffer + 1;
@@ -4068,9 +4177,8 @@ real_yylex ()
c = readescape (&ignore);
if (ignore)
goto skipnewline;
- if (!wide_flag
- && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
- && c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node)))
+ if (width < HOST_BITS_PER_INT
+ && (unsigned) c >= ((unsigned)1 << width))
warning ("escape sequence out of range for character");
}
else if (c == '\n')
@@ -4079,10 +4187,72 @@ real_yylex ()
pedwarn ("ANSI C++ forbids newline in string constant");
lineno++;
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int i;
+ int char_len = -1;
+ for (i = 0; i < longest_char; ++i)
+ {
+ if (p + i >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ p[i] = c;
- if (p == token_buffer + maxtoken)
- p = extend_token_buffer (p);
- *p++ = c;
+ char_len = local_mbtowc (& wc, p, i + 1);
+ if (char_len != -1)
+ break;
+ c = getch ();
+ }
+ if (char_len == -1)
+ warning ("Ignoring invalid multibyte character");
+ else
+ {
+ /* mbtowc sometimes needs an extra char before accepting */
+ if (char_len <= i)
+ put_back (c);
+ if (! wide_flag)
+ {
+ p += (i + 1);
+ c = getch ();
+ continue;
+ }
+ c = wc;
+ }
+#endif /* MULTIBYTE_CHARS */
+ }
+
+ /* Add this single character into the buffer either as a wchar_t
+ or as a single byte. */
+ if (wide_flag)
+ {
+ unsigned width = TYPE_PRECISION (char_type_node);
+ unsigned bytemask = (1 << width) - 1;
+ int byte;
+
+ if (p + WCHAR_BYTES > token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+
+ for (byte = 0; byte < WCHAR_BYTES; ++byte)
+ {
+ int value;
+ if (byte >= (int) sizeof(c))
+ value = 0;
+ else
+ value = (c >> (byte * width)) & bytemask;
+ if (BYTES_BIG_ENDIAN)
+ p[WCHAR_BYTES - byte - 1] = value;
+ else
+ p[byte] = value;
+ }
+ p += WCHAR_BYTES;
+ }
+ else
+ {
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ *p++ = c;
+ }
skipnewline:
c = getch ();
@@ -4091,56 +4261,36 @@ real_yylex ()
break;
}
}
- *p = 0;
-
- /* We have read the entire constant.
- Construct a STRING_CST for the result. */
+ /* Terminate the string value, either with a single byte zero
+ or with a wide zero. */
if (wide_flag)
{
- /* If this is a L"..." wide-string, convert the multibyte string
- to a wide character string. */
- char *widep = (char *) alloca ((p - token_buffer) * WCHAR_BYTES);
- int len;
-
-#ifdef MULTIBYTE_CHARS
- len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer);
- if (len < 0 || len >= (p - token_buffer))
- {
- warning ("Ignoring invalid multibyte string");
- len = 0;
- }
- bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);
-#else
- {
- char *wp, *cp;
-
- 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;
+ if (p + WCHAR_BYTES > token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ bzero (p, WCHAR_BYTES);
+ p += WCHAR_BYTES;
}
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;
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ *p++ = 0;
}
- *p++ = '"';
- *p = 0;
+ /* We have read the entire constant.
+ Construct a STRING_CST for the result. */
+
+ if (processing_template_decl)
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ yylval.ttype = build_string (p - (token_buffer + 1), token_buffer + 1);
+ if (processing_template_decl)
+ pop_obstacks ();
+
+ if (wide_flag)
+ TREE_TYPE (yylval.ttype) = wchar_array_type_node;
+ else
+ TREE_TYPE (yylval.ttype) = char_array_type_node;
value = STRING; break;
}
@@ -4392,6 +4542,17 @@ build_lang_decl (code, name, type)
tree type;
{
register tree t = build_decl (code, name, type);
+ retrofit_lang_decl (t);
+ return t;
+}
+
+/* Add DECL_LANG_SPECIFIC info to T. Called from build_lang_decl
+ and pushdecl (for functions generated by the backend). */
+
+void
+retrofit_lang_decl (t)
+ tree t;
+{
struct obstack *obstack = current_obstack;
register int i = sizeof (struct lang_decl) / sizeof (int);
register int *pi;
@@ -4440,8 +4601,6 @@ build_lang_decl (code, name, type)
tree_node_counts[(int)lang_decl] += 1;
tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
#endif
-
- return t;
}
tree
@@ -4503,39 +4662,49 @@ make_lang_type (code)
{
extern struct obstack *current_obstack, *saveable_obstack;
register tree t = make_node (code);
- struct obstack *obstack = current_obstack;
- register int i = sizeof (struct lang_type) / sizeof (int);
- register int *pi;
/* Set up some flags that give proper default behavior. */
- IS_AGGR_TYPE (t) = 1;
+ if (IS_AGGR_TYPE_CODE (code))
+ {
+ struct obstack *obstack = current_obstack;
+ struct lang_type *pi;
- if (! TREE_PERMANENT (t))
- obstack = saveable_obstack;
- else
- my_friendly_assert (obstack == &permanent_obstack, 236);
+ SET_IS_AGGR_TYPE (t, 1);
- pi = (int *) obstack_alloc (obstack, sizeof (struct lang_type));
- while (i > 0)
- pi[--i] = 0;
+ if (! TREE_PERMANENT (t))
+ obstack = saveable_obstack;
+ else
+ my_friendly_assert (obstack == &permanent_obstack, 236);
+
+ pi = (struct lang_type *) obstack_alloc (obstack, sizeof (struct lang_type));
+ bzero ((char *) pi, (int) sizeof (struct lang_type));
- TYPE_LANG_SPECIFIC (t) = (struct lang_type *) pi;
- CLASSTYPE_AS_LIST (t) = build_expr_list (NULL_TREE, t);
- SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
- CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- 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));
+ TYPE_LANG_SPECIFIC (t) = pi;
+ SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
+ CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- /* Make sure this is laid out, for ease of use later.
- In the presence of parse errors, the normal was of assuring
- this might not ever get executed, so we lay it out *immediately*. */
- build_pointer_type (t);
+ /* Make sure this is laid out, for ease of use later. In the
+ presence of parse errors, the normal was of assuring this
+ might not ever get executed, so we lay it out *immediately*. */
+ build_pointer_type (t);
#ifdef GATHER_STATISTICS
- tree_node_counts[(int)lang_type] += 1;
- tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
+ tree_node_counts[(int)lang_type] += 1;
+ tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
#endif
+ }
+ else
+ /* We use TYPE_ALIAS_SET for the CLASSTYPE_MARKED bits. But,
+ TYPE_ALIAS_SET is initialized to -1 by default, so we must
+ clear it here. */
+ TYPE_ALIAS_SET (t) = 0;
+
+ /* We need to allocate a TYPE_BINFO even for TEMPALTE_TYPE_PARMs
+ since they can be virtual base types, and we then need a
+ canonical binfo for them. Ideally, this would be done lazily for
+ all types. */
+ if (IS_AGGR_TYPE_CODE (code) || code == TEMPLATE_TYPE_PARM)
+ TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE);
return t;
}
@@ -4545,7 +4714,7 @@ dump_time_statistics ()
{
register tree prev = 0, decl, next;
int this_time = my_get_run_time ();
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+= this_time - body_time;
fprintf (stderr, "\n******\n");
@@ -4564,22 +4733,31 @@ dump_time_statistics ()
for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
print_time (IDENTIFIER_POINTER (decl),
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl)));
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (decl)));
}
void
-compiler_error (s, v, v2)
- char *s;
- HOST_WIDE_INT v, v2; /* @@also used as pointer */
+compiler_error VPROTO ((const char *msg, ...))
{
+#ifndef ANSI_PROTOTYPES
+ const char *msg;
+#endif
char buf[1024];
- sprintf (buf, s, v, v2);
+ va_list ap;
+
+ VA_START (ap, msg);
+
+#ifndef ANSI_PROTOTYPES
+ msg = va_arg (ap, const char *);
+#endif
+
+ vsprintf (buf, msg, ap);
error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
}
void
yyerror (string)
- char *string;
+ const char *string;
{
extern int end_of_file;
char buf[200];
@@ -4598,7 +4776,7 @@ yyerror (string)
strcat (buf, " before string constant");
else if (token_buffer[0] == '\'')
strcat (buf, " before character constant");
- else if (token_buffer[0] < 040 || (unsigned char) token_buffer[0] >= 0177)
+ else if (!ISGRAPH ((unsigned char)token_buffer[0]))
sprintf (buf + strlen (buf), " before character 0%o",
(unsigned char) token_buffer[0]);
else
@@ -4609,7 +4787,7 @@ yyerror (string)
static int
handle_cp_pragma (pname)
- char *pname;
+ const char *pname;
{
register int token;
@@ -4655,7 +4833,8 @@ handle_cp_pragma (pname)
}
else if (! strcmp (pname, "interface"))
{
- tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+ tree fileinfo
+ = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename));
char *main_filename = input_filename;
main_filename = file_name_nondirectory (main_filename);
@@ -4677,7 +4856,6 @@ handle_cp_pragma (pname)
if (token != END_OF_LINE)
warning ("garbage after `#pragma interface' ignored");
-#ifndef NO_LINKAGE_HEURISTICS
write_virtuals = 3;
if (impl_file_chain == 0)
@@ -4690,7 +4868,7 @@ handle_cp_pragma (pname)
#ifdef AUTO_IMPLEMENT
filename = file_name_nondirectory (main_input_filename);
fi = get_time_identifier (filename);
- fi = IDENTIFIER_CLASS_VALUE (fi);
+ fi = TIME_IDENTIFIER_FILEINFO (fi);
TREE_INT_CST_LOW (fi) = 0;
TREE_INT_CST_HIGH (fi) = 1;
/* Get default. */
@@ -4701,16 +4879,21 @@ handle_cp_pragma (pname)
}
interface_only = interface_strcmp (main_filename);
+#ifdef MULTIPLE_SYMBOL_SPACES
+ if (! interface_only)
+ interface_unknown = 0;
+#else /* MULTIPLE_SYMBOL_SPACES */
interface_unknown = 0;
+#endif /* MULTIPLE_SYMBOL_SPACES */
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));
+ tree fileinfo
+ = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename));
char *main_filename = main_input_filename ? main_input_filename : input_filename;
main_filename = file_name_nondirectory (main_filename);
@@ -4730,7 +4913,6 @@ handle_cp_pragma (pname)
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;
@@ -4775,25 +4957,43 @@ handle_cp_pragma (pname)
#endif
TREE_INT_CST_LOW (fileinfo) = interface_only;
TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
-#endif /* NO_LINKAGE_HEURISTICS */
return 1;
}
return 0;
}
+
+/* Return the type-qualifier corresponding to the identifier given by
+ RID. */
+
+int
+cp_type_qual_from_rid (rid)
+ tree rid;
+{
+ if (rid == ridpointers[(int) RID_CONST])
+ return TYPE_QUAL_CONST;
+ else if (rid == ridpointers[(int) RID_VOLATILE])
+ return TYPE_QUAL_VOLATILE;
+ else if (rid == ridpointers[(int) RID_RESTRICT])
+ return TYPE_QUAL_RESTRICT;
+
+ my_friendly_abort (0);
+ return TYPE_UNQUALIFIED;
+}
+
-#ifdef HANDLE_SYSV_PRAGMA
+#ifdef HANDLE_GENERIC_PRAGMAS
-/* Handle a #pragma directive. INPUT is the current input stream,
- and C is a character to reread. Processes the entire input line
- and returns a character for the caller to reread: either \n or EOF. */
+/* Handle a #pragma directive. TOKEN is the type of the word following
+ the #pragma directive on the line. Process the entire input line and
+ return non-zero iff the directive successfully parsed. */
/* This function has to be in this file, in order to get at
the token types. */
static int
-handle_sysv_pragma (token)
+handle_generic_pragma (token)
register int token;
{
for (;;)
@@ -4802,32 +5002,24 @@ handle_sysv_pragma (token)
{
case IDENTIFIER:
case TYPENAME:
- case STRING:
- case CONSTANT:
- handle_pragma_token ("ignored", yylval.ttype);
- break;
- case '(':
- handle_pragma_token ("(", NULL_TREE);
- break;
- case ')':
- handle_pragma_token (")", NULL_TREE);
- break;
- case ',':
- handle_pragma_token (",", NULL_TREE);
- break;
- case '=':
- handle_pragma_token ("=", NULL_TREE);
+ case STRING:
+ case CONSTANT:
+ handle_pragma_token (token_buffer, yylval.ttype);
break;
+
case LEFT_RIGHT:
handle_pragma_token ("(", NULL_TREE);
handle_pragma_token (")", NULL_TREE);
break;
+
case END_OF_LINE:
+ return handle_pragma_token (NULL_PTR, NULL_TREE);
+
default:
- handle_pragma_token (NULL_PTR, NULL_TREE);
- return 1;
+ handle_pragma_token (token_buffer, NULL_TREE);
}
+
token = real_yylex ();
}
}
-#endif /* HANDLE_SYSV_PRAGMA */
+#endif /* HANDLE_GENERIC_PRAGMAS */
diff --git a/contrib/gcc/cp/lex.h b/contrib/gcc/cp/lex.h
index 8df6b76..249eef9 100644
--- a/contrib/gcc/cp/lex.h
+++ b/contrib/gcc/cp/lex.h
@@ -1,5 +1,5 @@
/* Define constants and variables for communication with parse.y.
- Copyright (C) 1987, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92-97, 1998 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
and by Brendan Kehoe (brendan@cygnus.com).
@@ -59,10 +59,12 @@ enum rid
RID_FRIEND,
RID_VIRTUAL,
RID_EXPLICIT,
+ RID_EXPORT,
RID_SIGNED,
RID_AUTO,
RID_MUTABLE,
RID_COMPLEX,
+ RID_RESTRICT,
/* This is where grokdeclarator ends its search when setting the
specbits. */
diff --git a/contrib/gcc/cp/method.c b/contrib/gcc/cp/method.c
index 29b31c4..d4a667b 100644
--- a/contrib/gcc/cp/method.c
+++ b/contrib/gcc/cp/method.c
@@ -1,6 +1,6 @@
/* Handle the hair of processing (but not expanding) inline functions.
Also manage function and variable name overloading.
- Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-97, 1998, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -57,7 +57,8 @@ 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 int old_backref_index PROTO((tree));
+static int 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));
@@ -71,8 +72,6 @@ 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));
@@ -82,6 +81,9 @@ 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));
+#if HOST_BITS_PER_WIDE_INT >= 64
+static void build_mangled_C9x_name PROTO((int));
+#endif
static int is_back_referenceable_type PROTO((tree));
static int check_btype PROTO((tree));
static void build_mangled_name_for_type PROTO((tree));
@@ -298,15 +300,48 @@ dicat (lo, hi)
OB_PUTC ('0' + ulo);
}
-static __inline void
+/* Returns the index of TYPE in the typevec, or -1 if it's not there. */
+
+static __inline int
+old_backref_index (type)
+ tree type;
+{
+ int tindex = 0;
+
+ if (! is_back_referenceable_type (type))
+ return -1;
+
+ /* The entry for this parm is at maxtype-1, so don't look there for
+ something to repeat. */
+ for (tindex = 0; tindex < maxtype - 1; ++tindex)
+ if (same_type_p (typevec[tindex], type))
+ break;
+
+ if (tindex == maxtype - 1)
+ return -1;
+
+ return tindex;
+}
+
+/* Old mangling style: If TYPE has already been used in the parameter list,
+ emit a backward reference and return non-zero; otherwise, return 0.
+
+ NREPEATS is the number of repeats we've recorded of this type, or 0 if
+ this is the first time we've seen it and we're just looking to see if
+ it had been used before. */
+
+static __inline int
flush_repeats (nrepeats, type)
int nrepeats;
tree type;
{
- int tindex = 0;
+ int tindex = old_backref_index (type);
- while (typevec[tindex] != type)
- tindex++;
+ if (tindex == -1)
+ {
+ my_friendly_assert (nrepeats == 0, 990316);
+ return 0;
+ }
if (nrepeats > 1)
{
@@ -320,25 +355,33 @@ flush_repeats (nrepeats, type)
icat (tindex);
if (tindex > 9)
OB_PUTC ('_');
+
+ return 1;
}
/* Returns nonzero iff this is a type to which we will want to make
back-references (using the `B' code). */
-int
+static int
is_back_referenceable_type (type)
tree type;
{
- if (btypelist == NULL)
- /* We're not generating any back-references. */
+ /* For some reason, the Java folks don't want back refs on these. */
+ if (TYPE_FOR_JAVA (type))
return 0;
switch (TREE_CODE (type))
{
+ case BOOLEAN_TYPE:
+ if (!flag_do_squangling)
+ /* Even though the mangling of this is just `b', we did
+ historically generate back-references for it. */
+ return 1;
+ /* Fall through. */
+
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;
@@ -376,8 +419,10 @@ issue_nrepeats (nrepeats, type)
}
}
-/* 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 */
+/* Check to see if a tree node has been entered into the Kcode typelist.
+ If not, add it. Returns -1 if it isn't found, otherwise returns the
+ index. */
+
static int
check_ktype (node, add)
tree node;
@@ -394,10 +439,10 @@ check_ktype (node, add)
for (x=0; x < maxktype; x++)
{
- if (localnode == ktypelist[x])
- return x ;
+ if (same_type_p (localnode, ktypelist[x]))
+ return x;
}
- /* Didn't find it, so add it here */
+ /* Didn't find it, so add it here. */
if (add)
{
if (maxksize <= maxktype)
@@ -625,20 +670,53 @@ build_mangled_template_parm_index (s, index)
}
+/* Mangling for C9X integer types (and Cygnus extensions for 128-bit
+ and other types) is based on the letter "I" followed by the hex
+ representations of the bitsize for the type in question. For
+ encodings that result in larger than two digits, a leading and
+ trailing underscore is added.
+
+ Thus:
+ int1_t = 001 = I01
+ int8_t = 008 = I08
+ int16_t = 010 = I10
+ int24_t = 018 = I18
+ int32_t = 020 = I20
+ int64_t = 040 = I40
+ int80_t = 050 = I50
+ int128_t = 080 = I80
+ int256_t = 100 = I_100_
+ int512_t = 200 = I_200_
+
+ Given an integer in decimal format, mangle according to this scheme. */
+
+#if HOST_BITS_PER_WIDE_INT >= 64
+static void
+build_mangled_C9x_name (bits)
+ int bits;
+{
+ char mangled[10] = "";
+
+ if (bits > 255)
+ sprintf (mangled, "I_%x_", bits);
+ else
+ sprintf (mangled, "I%.2x", bits);
+
+ OB_PUTCP (mangled);
+}
+#endif
+
static void
build_overload_value (type, value, in_template)
tree type, value;
int in_template;
{
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0);
+
while (TREE_CODE (value) == NON_LVALUE_EXPR
|| TREE_CODE (value) == NOP_EXPR)
value = TREE_OPERAND (value, 0);
- 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)
{
OB_PUTC ('_');
@@ -651,21 +729,21 @@ build_overload_value (type, value, in_template)
return;
}
- if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
+ if (TYPE_PTRMEM_P (type))
{
- /* Handle a pointer to data member as a template instantiation
- parameter, boy, what fun! */
- type = integer_type_node;
- if (TREE_CODE (value) != INTEGER_CST)
- {
- sorry ("unknown pointer to member constant");
- return;
- }
- }
+ if (TREE_CODE (value) != PTRMEM_CST)
+ /* We should have already rejected this pointer to member,
+ since it is not a constant. */
+ my_friendly_abort (0);
- if (TYPE_PTRMEMFUNC_P (type))
- type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+ /* Get the actual FIELD_DECL. */
+ value = PTRMEM_CST_MEMBER (value);
+ my_friendly_assert (TREE_CODE (value) == FIELD_DECL, 0);
+
+ /* Output the name of the field. */
+ build_overload_identifier (DECL_NAME (value));
+ return;
+ }
switch (TREE_CODE (type))
{
@@ -743,46 +821,6 @@ build_overload_value (type, value, in_template)
return;
}
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. */
- tree args = CONSTRUCTOR_ELTS (value);
- tree a1 = TREE_VALUE (args);
- tree a2 = TREE_VALUE (TREE_CHAIN (args));
- tree a3 = CONSTRUCTOR_ELTS (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args))));
- a3 = TREE_VALUE (a3);
- STRIP_NOPS (a3);
- if (TREE_CODE (a1) == INTEGER_CST
- && TREE_CODE (a2) == INTEGER_CST)
- {
- build_overload_int (a1, in_template);
- OB_PUTC ('_');
- build_overload_int (a2, in_template);
- OB_PUTC ('_');
- if (TREE_CODE (a3) == ADDR_EXPR)
- {
- a3 = TREE_OPERAND (a3, 0);
- if (TREE_CODE (a3) == FUNCTION_DECL)
- {
- numeric_output_need_bar = 0;
- build_overload_identifier (DECL_ASSEMBLER_NAME (a3));
- return;
- }
- }
- else if (TREE_CODE (a3) == INTEGER_CST)
- {
- OB_PUTC ('i');
- build_overload_int (a3, in_template);
- return;
- }
- }
- }
- sorry ("template instantiation with pointer to method that is too complex");
- return;
- }
if (TREE_CODE (value) == INTEGER_CST)
{
build_overload_int (value, in_template);
@@ -796,6 +834,10 @@ build_overload_value (type, value, in_template)
}
value = TREE_OPERAND (value, 0);
+
+ /* Fall through. */
+
+ case REFERENCE_TYPE:
if (TREE_CODE (value) == VAR_DECL)
{
my_friendly_assert (DECL_NAME (value) != 0, 245);
@@ -814,6 +856,51 @@ build_overload_value (type, value, in_template)
my_friendly_abort (71);
break; /* not really needed */
+ case RECORD_TYPE:
+ {
+ tree delta;
+ tree idx;
+ tree pfn;
+ tree delta2;
+
+ my_friendly_assert (TYPE_PTRMEMFUNC_P (type), 0);
+
+ /* We'll get a ADDR_EXPR of a SCOPE_REF here if we're
+ mangling, an instantiation of something like:
+
+ template <class T, void (T::*fp)()> class C {};
+ template <class T> C<T, &T::f> x();
+
+ We mangle the return type of the function, and that
+ contains template parameters. */
+ if (TREE_CODE (value) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (value, 0)) == SCOPE_REF)
+ {
+ build_overload_scope_ref (TREE_OPERAND (value, 0));
+ break;
+ }
+
+ my_friendly_assert (TREE_CODE (value) == PTRMEM_CST, 0);
+
+ expand_ptrmemfunc_cst (value, &delta, &idx, &pfn, &delta2);
+ build_overload_int (delta, in_template);
+ OB_PUTC ('_');
+ build_overload_int (idx, in_template);
+ OB_PUTC ('_');
+ if (pfn)
+ {
+ numeric_output_need_bar = 0;
+ build_overload_identifier (DECL_ASSEMBLER_NAME
+ (PTRMEM_CST_MEMBER (value)));
+ }
+ else
+ {
+ OB_PUTC ('i');
+ build_overload_int (delta2, in_template);
+ }
+ }
+ break;
+
default:
sorry ("conversion of %s as template parameter",
tree_code_name [(int) TREE_CODE (type)]);
@@ -823,7 +910,7 @@ build_overload_value (type, value, in_template)
/* Add encodings for the declaration of template template parameters.
- PARMLIST must be a TREE_VEC */
+ PARMLIST must be a TREE_VEC. */
static void
build_template_template_parm_names (parmlist)
@@ -864,13 +951,14 @@ build_template_parm_names (parmlist, arglist)
tree arglist;
{
int i, nparms;
-
+ tree inner_args = innermost_args (arglist);
+
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);
+ tree arg = TREE_VEC_ELT (inner_args, i);
if (TREE_CODE (parm) == TYPE_DECL)
{
/* This parameter is a type. */
@@ -879,9 +967,9 @@ build_template_parm_names (parmlist, arglist)
}
else if (TREE_CODE (parm) == TEMPLATE_DECL)
{
- /* This parameter is a template. */
+ /* This parameter is a template. */
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
- /* Output parameter declaration, argument index and level */
+ /* Output parameter declaration, argument index and level. */
build_mangled_name_for_type (arg);
else
{
@@ -889,17 +977,19 @@ build_template_parm_names (parmlist, arglist)
and template name */
OB_PUTC ('z');
- build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm));
+ 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);
+ parm = tsubst (parm, arglist, /*complain=*/1, NULL_TREE);
/* It's a PARM_DECL. */
build_mangled_name_for_type (TREE_TYPE (parm));
- build_overload_value (parm, arg, uses_template_parms (arglist));
+ build_overload_value (TREE_TYPE (parm), arg,
+ uses_template_parms (arglist));
}
}
}
@@ -912,7 +1002,7 @@ build_overload_identifier (name)
tree name;
{
if (TREE_CODE (name) == TYPE_DECL
- && IS_AGGR_TYPE (TREE_TYPE (name))
+ && CLASS_TYPE_P (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
@@ -921,9 +1011,8 @@ build_overload_identifier (name)
{
/* NAME is the TYPE_DECL for a template specialization. */
tree template, parmlist, arglist, tname;
- template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
- arglist = innermost_args (TREE_VALUE (template), 0);
- template = TREE_PURPOSE (template);
+ template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name));
+ arglist = CLASSTYPE_TI_ARGS (TREE_TYPE (name));
tname = DECL_NAME (template);
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
OB_PUTC ('t');
@@ -970,15 +1059,18 @@ build_qualified_name (decl)
}
context = decl;
- /* if we can't find a Ktype, do it the hard way */
+ /* 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)
+ /* Count type and namespace scopes. */
+ while (1)
{
+ context = CP_DECL_CONTEXT (context);
+ if (context == global_namespace)
+ break;
i += 1;
- context = DECL_CONTEXT (context);
- if (check_ktype (context, FALSE) != -1) /* found it! */
+ if (check_ktype (context, FALSE) != -1)
+ /* Found one! */
break;
if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
context = TYPE_NAME (context);
@@ -998,14 +1090,13 @@ build_qualified_name (decl)
non-zero, mangled names for structure/union types are intentionally
mangled differently from the method described in the ARM. */
-void
+static 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);
}
@@ -1013,7 +1104,7 @@ build_mangled_name_for_type_with_Gcode (type, extra_Gcode)
/* Like build_mangled_name_for_type_with_Gcode, but never outputs the
`G'. */
-void
+static void
build_mangled_name_for_type (type)
tree type;
{
@@ -1069,7 +1160,11 @@ build_mangled_name (parmtypes, begin, end)
for (; parmtypes && parmtypes != void_list_node;
parmtypes = TREE_CHAIN (parmtypes))
{
- tree parmtype = canonical_type_variant (TREE_VALUE (parmtypes));
+ /* We used to call canonical_type_variant here, but that isn't
+ good enough; it doesn't handle pointers to typedef types. So
+ we can't just set TREE_USED to say we've seen a type already;
+ we have to check each of the earlier types with same_type_p. */
+ tree parmtype = TREE_VALUE (parmtypes);
if (old_style_repeats)
{
@@ -1078,11 +1173,11 @@ build_mangled_name (parmtypes, begin, end)
typevec[maxtype++] = parmtype;
}
- if (parmtype == last_type)
+ if (last_type && same_type_p (parmtype, last_type))
{
if (flag_do_squangling
- || (old_style_repeats && TREE_USED (parmtype)
- && !TYPE_FOR_JAVA (parmtype)))
+ || (old_style_repeats
+ && is_back_referenceable_type (parmtype)))
{
/* The next type is the same as this one. Keep
track of the repetition, and output the repeat
@@ -1104,35 +1199,11 @@ build_mangled_name (parmtypes, begin, end)
last_type = parmtype;
- if (old_style_repeats)
- {
- 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;
- }
+ /* Note that for bug-compatibility with 2.7.2, we can't build up
+ repeats of types other than the most recent one. So we call
+ flush_repeats every round, if we get this far. */
+ if (old_style_repeats && flush_repeats (0, parmtype))
+ continue;
/* Output the PARMTYPE. */
build_mangled_name_for_type_with_Gcode (parmtype, 1);
@@ -1159,27 +1230,37 @@ build_mangled_name (parmtypes, begin, end)
return (char *)obstack_base (&scratch_obstack);
}
-/* handles emitting modifiers such as Constant, read-only, and volatile */
-void
+/* Emit modifiers such as constant, read-only, and volatile. */
+
+static void
process_modifiers (parmtype)
tree parmtype;
{
- if (TREE_READONLY (parmtype))
+ /* Note that here we do not use CP_TYPE_CONST_P and friends because
+ we describe types recursively; we will get the `const' in
+ `const int ()[10]' when processing the `const int' part. */
+ if (TYPE_READONLY (parmtype))
OB_PUTC ('C');
if (TREE_CODE (parmtype) == INTEGER_TYPE
+ && parmtype != char_type_node
+ && parmtype != wchar_type_node
&& (TYPE_MAIN_VARIANT (parmtype)
== unsigned_type (TYPE_MAIN_VARIANT (parmtype)))
&& ! TYPE_FOR_JAVA (parmtype))
OB_PUTC ('U');
if (TYPE_VOLATILE (parmtype))
OB_PUTC ('V');
+ /* It would be better to use `R' for `restrict', but that's already
+ used for reference types. And `r' is used for `long double'. */
+ if (TYPE_RESTRICT (parmtype))
+ OB_PUTC ('u');
}
/* 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
+static int
check_btype (type)
tree type;
{
@@ -1191,12 +1272,8 @@ check_btype (type)
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])
+ if (same_type_p (type, btypelist[x]))
{
OB_PUTC ('B');
icat (x);
@@ -1218,7 +1295,8 @@ check_btype (type)
return 0;
}
-/* handle emitting the correct code for various node types */
+/* Emit the correct code for various node types. */
+
static void
process_overload_item (parmtype, extra_Gcode)
tree parmtype;
@@ -1226,9 +1304,17 @@ process_overload_item (parmtype, 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 */
+ /* Our caller should have already handed any qualifiers, so pull out the
+ TYPE_MAIN_VARIANT to avoid typedef confusion. Except we can't do that
+ for arrays, because they are transparent to qualifiers. Sigh. */
+ if (TREE_CODE (parmtype) == ARRAY_TYPE)
+ parmtype = canonical_type_variant (parmtype);
+ else
+ parmtype = TYPE_MAIN_VARIANT (parmtype);
+
+ /* 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))
{
@@ -1239,11 +1325,9 @@ process_overload_item (parmtype, extra_Gcode)
case ARRAY_TYPE:
#if PARM_CAN_BE_ARRAY_TYPE
{
- tree length;
-
OB_PUTC ('A');
if (TYPE_DOMAIN (parmtype) == NULL_TREE)
- error("pointer/reference to array of unknown bound in parm type");
+ OB_PUTC ('_');
else
{
tree length = array_type_nelts (parmtype);
@@ -1331,7 +1415,6 @@ process_overload_item (parmtype, extra_Gcode)
}
case INTEGER_TYPE:
- parmtype = TYPE_MAIN_VARIANT (parmtype);
if (parmtype == integer_type_node
|| parmtype == unsigned_type_node
|| parmtype == java_int_type_node)
@@ -1359,15 +1442,18 @@ process_overload_item (parmtype, extra_Gcode)
|| 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');
-#endif
else if (parmtype == java_boolean_type_node)
OB_PUTC ('b');
+#if HOST_BITS_PER_WIDE_INT >= 64
+ else if (parmtype == intTI_type_node
+ || parmtype == unsigned_intTI_type_node)
+ {
+ /* Should just check a flag here instead of specific
+ *_type_nodes, because all C9x types could use this. */
+ int bits = TREE_INT_CST_LOW (TYPE_SIZE (parmtype));
+ build_mangled_C9x_name (bits);
+ }
+#endif
else
my_friendly_abort (73);
break;
@@ -1377,7 +1463,6 @@ process_overload_item (parmtype, extra_Gcode)
break;
case REAL_TYPE:
- parmtype = TYPE_MAIN_VARIANT (parmtype);
if (parmtype == long_double_type_node)
OB_PUTC ('r');
else if (parmtype == double_type_node
@@ -1413,11 +1498,6 @@ process_overload_item (parmtype, extra_Gcode)
{
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);
@@ -1432,14 +1512,14 @@ process_overload_item (parmtype, extra_Gcode)
case TEMPLATE_TEMPLATE_PARM:
/* Find and output the original template parameter
declaration. */
- if (CLASSTYPE_TEMPLATE_INFO (parmtype))
+ if (TEMPLATE_TEMPLATE_PARM_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));
+ (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (parmtype)),
+ TYPE_TI_ARGS (parmtype));
}
else
{
@@ -1499,7 +1579,10 @@ build_static_name (context, name)
return get_identifier ((char *)obstack_base (&scratch_obstack));
}
-static tree
+/* FOR_METHOD should be 1 if the declaration in question is for a member
+ of a class (including a static member) and 2 if the declaration is
+ for a constructor. */
+tree
build_decl_overload_real (dname, parms, ret_type, tparms, targs,
for_method)
tree dname;
@@ -1557,12 +1640,13 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
OB_PUTC ('v');
else
{
- if (!flag_do_squangling) /* Allocate typevec array. */
+ 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 */
+ /* The namespace of a global function needs one slot. */
typevec_size++;
typevec = (tree *)alloca (typevec_size * sizeof (tree));
}
@@ -1583,12 +1667,6 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
{
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))
@@ -1609,20 +1687,9 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
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 (!flag_do_squangling)
+ /* Deallocate typevec array. */
+ typevec = NULL;
}
if (ret_type != NULL_TREE && for_method != 2)
@@ -1661,38 +1728,38 @@ build_decl_overload (dname, parms, for_method)
NULL_TREE, for_method);
}
+/* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */
-/* Like build_decl_overload, but for template functions. */
-
-tree
-build_template_decl_overload (decl, parms, ret_type, tparms, targs,
- for_method)
+void
+set_mangled_name_for_decl (decl)
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. */
+ tree parm_types;
- my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702);
- saved_ctx = current_namespace;
- current_namespace = CP_DECL_CONTEXT (decl);
+ if (processing_template_decl)
+ /* There's no need to mangle the name of a template function. */
+ return;
- res = build_decl_overload_real (DECL_NAME (decl), parms, ret_type,
- tparms, targs, for_method);
+ parm_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
- current_namespace = saved_ctx;
- return res;
+ if (DECL_STATIC_FUNCTION_P (decl))
+ parm_types =
+ hash_tree_chain (build_pointer_type (DECL_CLASS_CONTEXT (decl)),
+ parm_types);
+ else
+ /* The only member functions whose type is a FUNCTION_TYPE, rather
+ than a METHOD_TYPE, should be static members. */
+ my_friendly_assert (!DECL_CONTEXT (decl)
+ || !IS_AGGR_TYPE_CODE (TREE_CODE (DECL_CONTEXT (decl)))
+ || TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE,
+ 0);
+
+ DECL_ASSEMBLER_NAME (decl)
+ = build_decl_overload (DECL_NAME (decl), parm_types,
+ DECL_FUNCTION_MEMBER_P (decl)
+ + DECL_CONSTRUCTOR_P (decl));
}
-
/* Build an overload name for the type expression TYPE. */
tree
@@ -1851,8 +1918,16 @@ hack_identifier (value, name)
{
if (current_class_ptr == NULL_TREE)
{
- error ("request for member `%s' in static member function",
- IDENTIFIER_POINTER (DECL_NAME (value)));
+ if (current_function_decl
+ && DECL_STATIC_FUNCTION_P (current_function_decl))
+ cp_error ("invalid use of member `%D' in static member function",
+ value);
+ else
+ /* We can get here when processing a bad default
+ argument, like:
+ struct S { int a; void f(int i = a); } */
+ cp_error ("invalid use of member `%D'", value);
+
return error_mark_node;
}
TREE_USED (current_class_ptr) = 1;
@@ -1863,24 +1938,24 @@ hack_identifier (value, name)
TREE_USED (value) = 1;
value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
}
- 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))
+ else if ((TREE_CODE (value) == FUNCTION_DECL
+ && DECL_FUNCTION_MEMBER_P (value))
+ || (TREE_CODE (value) == OVERLOAD
+ && DECL_FUNCTION_MEMBER_P (OVL_CURRENT (value))))
{
-#if 0
- tree t = get_first_fn (value);
- for (; t; t = DECL_CHAIN (t))
- {
- if (TREE_CODE (t) == TEMPLATE_DECL)
- continue;
+ tree decl;
- assemble_external (t);
- TREE_USED (t) = 1;
- }
-#endif
+ if (TREE_CODE (value) == OVERLOAD)
+ value = OVL_CURRENT (value);
+
+ if (IS_SIGNATURE (DECL_CLASS_CONTEXT (value)))
+ return value;
+
+ decl = maybe_dummy_object (DECL_CLASS_CONTEXT (value), 0);
+ value = build_component_ref (decl, name, NULL_TREE, 1);
}
+ else if (really_overloaded_fn (value))
+ ;
else if (TREE_CODE (value) == OVERLOAD)
/* not really overloaded function */
mark_used (OVL_FUNCTION (value));
@@ -1907,7 +1982,8 @@ hack_identifier (value, name)
else
mark_used (value);
- if (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL)
+ if (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL
+ || TREE_CODE (value) == RESULT_DECL)
{
tree context = decl_function_context (value);
if (context != NULL_TREE && context != current_function_decl
@@ -1926,44 +2002,27 @@ hack_identifier (value, name)
if (DECL_LANG_SPECIFIC (value)
&& DECL_CLASS_CONTEXT (value) != current_class_type)
{
- tree path, access;
+ tree path;
register tree context
= (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value))
? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value);
get_base_distance (context, current_class_type, 0, &path);
- if (path)
- {
- access = compute_access (path, value);
- 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");
- else
- error ("enum `%s' is from private base class",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- }
+ if (path && !enforce_access (current_class_type, value))
+ return error_mark_node;
}
}
- else if (TREE_CODE (value) == TREE_LIST && TREE_NONLOCAL_FLAG (value))
+ else if (TREE_CODE (value) == TREE_LIST
+ && TREE_TYPE (value) == error_mark_node)
{
- if (type == 0)
- {
- error ("request for member `%s' is ambiguous in multiple inheritance lattice",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
-
- return value;
+ error ("request for member `%s' is ambiguous in multiple inheritance lattice",
+ IDENTIFIER_POINTER (name));
+ print_candidates (value);
+ return error_mark_node;
}
- if (TREE_CODE (type) == REFERENCE_TYPE && ! processing_template_decl)
+ if (! processing_template_decl)
value = convert_from_reference (value);
return value;
}
@@ -2172,42 +2231,21 @@ do_build_copy_constructor (fndecl)
tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
int i;
+ /* Initialize all the base-classes. */
for (t = CLASSTYPE_VBASECLASSES (current_class_type); t;
t = TREE_CHAIN (t))
- {
- tree basetype = BINFO_TYPE (t);
- tree p = convert_to_reference
- (build_reference_type (basetype), parm,
- CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
- p = convert_from_reference (p);
-
- if (p == error_mark_node)
- cp_error ("in default copy constructor");
- else
- current_base_init_list = tree_cons (basetype,
- p, current_base_init_list);
- }
-
+ current_base_init_list
+ = tree_cons (BINFO_TYPE (t), parm, current_base_init_list);
for (i = 0; i < n_bases; ++i)
{
- tree p, basetype = TREE_VEC_ELT (binfos, i);
- if (TREE_VIA_VIRTUAL (basetype))
+ t = TREE_VEC_ELT (binfos, i);
+ if (TREE_VIA_VIRTUAL (t))
continue;
- basetype = BINFO_TYPE (basetype);
- p = convert_to_reference
- (build_reference_type (basetype), parm,
- CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
-
- 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);
- }
+ current_base_init_list
+ = tree_cons (BINFO_TYPE (t), parm, current_base_init_list);
}
+
for (; fields; fields = TREE_CHAIN (fields))
{
tree init, t;
@@ -2305,7 +2343,7 @@ do_build_assign_ref (fndecl)
if (TREE_CODE (field) != FIELD_DECL)
continue;
- if (TREE_READONLY (field))
+ if (CP_TYPE_CONST_P (TREE_TYPE (field)))
{
if (DECL_NAME (field))
cp_error ("non-static const member `%#D', can't use default assignment operator", field);
diff --git a/contrib/gcc/cp/new.cc b/contrib/gcc/cp/new.cc
index 28187a4..3197012 100644
--- a/contrib/gcc/cp/new.cc
+++ b/contrib/gcc/cp/new.cc
@@ -1,5 +1,5 @@
// Implementation file for the -*- C++ -*- dynamic memory management header.
-// Copyright (C) 1996 Free Software Foundation
+// Copyright (C) 1996, 1997, 1998 Free Software Foundation
// This file is part of GNU CC.
diff --git a/contrib/gcc/cp/new1.cc b/contrib/gcc/cp/new1.cc
index 5bb85c9..73fbcd2 100644
--- a/contrib/gcc/cp/new1.cc
+++ b/contrib/gcc/cp/new1.cc
@@ -1,5 +1,5 @@
// Support routines for the -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997 Free Software Foundation
+// Copyright (C) 1997, 1998 Free Software Foundation
// This file is part of GNU CC.
diff --git a/contrib/gcc/cp/new2.cc b/contrib/gcc/cp/new2.cc
index 0be1c0d..2833ea2 100644
--- a/contrib/gcc/cp/new2.cc
+++ b/contrib/gcc/cp/new2.cc
@@ -1,5 +1,5 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997 Free Software Foundation
+// Copyright (C) 1997, 1998 Free Software Foundation
// This file is part of GNU CC.
diff --git a/contrib/gcc/cp/parse.y b/contrib/gcc/cp/parse.y
index 279cec3..7b5d3bd 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, 89, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1988, 89, 93-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -60,9 +60,10 @@ extern int end_of_file;
/* Contains the statement keyword (if/while/do) to include in an
error message if the user supplies an empty conditional expression. */
-static char *cond_stmt_keyword;
+static const char *cond_stmt_keyword;
static tree empty_parms PROTO((void));
+static int parse_decl PROTO((tree, tree, tree, int, tree *));
/* Nonzero if we have an `extern "C"' acting as an extern specifier. */
int have_extern_spec;
@@ -130,7 +131,7 @@ empty_parms ()
/* the reserved words */
/* 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 TYPEOF ALIGNOF
+%token BREAK CONTINUE RETURN_KEYWORD GOTO ASM_KEYWORD TYPEOF ALIGNOF
%token SIGOF
%token ATTRIBUTE EXTENSION LABEL
%token REALPART IMAGPART
@@ -203,11 +204,12 @@ empty_parms ()
%type <ttype> compstmt implicitly_scoped_stmt
%type <ttype> declarator notype_declarator after_type_declarator
+%type <ttype> notype_declarator_intern absdcl_intern
+%type <ttype> after_type_declarator_intern
%type <ttype> direct_notype_declarator direct_after_type_declarator
-
-%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 self_reference
+%type <itype> components notype_components
+%type <ttype> component_decl component_decl_1
+%type <ttype> component_declarator component_declarator0
%type <ttype> notype_component_declarator notype_component_declarator0
%type <ttype> after_type_component_declarator after_type_component_declarator0
%type <ttype> enumlist enumerator
@@ -217,7 +219,8 @@ empty_parms ()
%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> expr_or_declarator expr_or_declarator_intern
+%type <ttype> 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
@@ -235,11 +238,12 @@ empty_parms ()
%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 <itype> ctor_initializer_opt function_try_block
+%type <ttype> named_class_head_sans_basetype
+%type <ftype> class_head named_class_head
+%type <ftype> named_complex_class_head_sans_basetype
%type <ttype> unnamed_class_head
-%type <ttype> class_head base_class_list
+%type <ttype> base_class_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
@@ -252,6 +256,7 @@ empty_parms ()
%type <ttype> template_header template_parm_list template_parm
%type <ttype> template_type_parm template_template_parm
%type <code> template_close_bracket
+%type <ttype> apparent_template_type
%type <ttype> template_type template_arg_list template_arg_list_opt
%type <ttype> template_arg
%type <ttype> condition xcond paren_cond_or_null
@@ -267,7 +272,7 @@ empty_parms ()
%type <ttype> named_class_head_sans_basetype_defn
%type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
-%type <ttype> self_template_type
+%type <ttype> self_template_type .finish_template_type
%token NSNAME
%type <ttype> NSNAME
@@ -290,9 +295,13 @@ static tree current_declspecs;
a declspec list have been updated. */
static tree prefix_attributes;
-/* When defining an aggregate, this is the most recent one being defined. */
+/* When defining an aggregate, this is the kind of the most recent one
+ being defined. (For example, this might be class_type_node.) */
static tree current_aggr;
+/* When defining an enumeration, this is the type of the enumeration. */
+static tree current_enum_type;
+
/* Tell yyparse how to print a token's value, if yydebug is set. */
#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
@@ -312,7 +321,7 @@ parse_decl(declarator, specs_attrs, attributes, initialized, decl)
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);
+ current_declspecs = build_decl_list (NULL_TREE, current_declspecs);
if (have_extern_spec && !used_extern_spec)
{
current_declspecs = decl_tree_cons (NULL_TREE,
@@ -556,22 +565,38 @@ template_parm:
;
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 ();
- }
+ template_header template_extdef
+ { finish_template_decl ($1); }
+ | template_header error %prec EMPTY
+ { finish_template_decl ($1); }
+ ;
+
+template_extdef:
+ fndef eat_saved_input
+ { if (pending_inlines) do_pending_inlines (); }
+ | template_datadef
+ { if (pending_inlines) do_pending_inlines (); }
+ | template_def
+ { if (pending_inlines) do_pending_inlines (); }
+ | 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 template_datadef .warning_ok
+ { if (pending_inlines) do_pending_inlines ();
+ pop_lang_context (); }
+ | extension template_extdef
+ { pedantic = $<itype>1; }
+ ;
+
+template_datadef:
+ nomods_initdecls ';'
+ | declmods notype_initdecls ';'
+ {}
+ | typed_declspecs initdecls ';'
+ { note_list_got_semicolon ($1.t); }
+ | structsp ';'
+ { maybe_process_partial_specialization ($1.t);
+ note_got_semicolon ($1.t); }
;
datadef:
@@ -579,9 +604,7 @@ datadef:
| declmods notype_initdecls ';'
{}
| typed_declspecs initdecls ';'
- {
- note_list_got_semicolon ($1.t);
- }
+ { note_list_got_semicolon ($1.t); }
| declmods ';'
{ pedwarn ("empty declaration"); }
| explicit_instantiation ';'
@@ -619,7 +642,11 @@ fndef:
fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
{ finish_function (lineno, (int)$3, 0); }
| fn.def1 maybe_return_init function_try_block
- { }
+ {
+ int nested = (hack_decl_function_context
+ (current_function_decl) != NULL_TREE);
+ finish_function (lineno, (int)$3, nested);
+ }
| fn.def1 maybe_return_init error
{ }
;
@@ -692,8 +719,10 @@ component_constructor_declarator:
reduce/reduce conflict introduced by these rules. */
fn.def2:
declmods component_constructor_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2);
+ { tree specs, attrs;
+ split_specs_attrs ($1, &specs, &attrs);
+ attrs = build_tree_list (attrs, NULL_TREE);
+ $$ = start_method (specs, $2, attrs);
rest_of_mdef:
if (! $$)
YYERROR1;
@@ -701,24 +730,33 @@ fn.def2:
yychar = YYLEX;
reinit_parse_for_method (yychar, $$); }
| component_constructor_declarator
- { $$ = start_method (NULL_TREE, $1); goto rest_of_mdef; }
+ { $$ = start_method (NULL_TREE, $1, NULL_TREE);
+ goto rest_of_mdef; }
| typed_declspecs declarator
- { tree specs = strip_attrs ($1.t);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { tree specs, attrs;
+ split_specs_attrs ($1.t, &specs, &attrs);
+ attrs = build_tree_list (attrs, NULL_TREE);
+ $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| declmods notype_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { tree specs, attrs;
+ split_specs_attrs ($1, &specs, &attrs);
+ attrs = build_tree_list (attrs, NULL_TREE);
+ $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| notype_declarator
- { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
+ { $$ = start_method (NULL_TREE, $$, NULL_TREE);
+ goto rest_of_mdef; }
| declmods constructor_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { tree specs, attrs;
+ split_specs_attrs ($1, &specs, &attrs);
+ attrs = build_tree_list (attrs, NULL_TREE);
+ $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| constructor_declarator
- { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
+ { $$ = start_method (NULL_TREE, $$, NULL_TREE);
+ goto rest_of_mdef; }
;
return_id:
- RETURN IDENTIFIER
+ RETURN_KEYWORD IDENTIFIER
{
if (! current_function_parms_stored)
store_parm_decls ();
@@ -870,29 +908,35 @@ end_explicit_instantiation:
template_type:
PTYPENAME '<' template_arg_list_opt template_close_bracket
- {
- $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
- if ($$ != error_mark_node)
- $$ = TYPE_STUB_DECL ($$);
- }
+ .finish_template_type
+ { $$ = $5; }
| TYPENAME '<' template_arg_list_opt template_close_bracket
- {
- $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
- if ($$ != error_mark_node)
- $$ = TYPE_STUB_DECL ($$);
- }
+ .finish_template_type
+ { $$ = $5; }
| self_template_type
;
+apparent_template_type:
+ template_type
+ | identifier '<' template_arg_list_opt '>'
+ .finish_template_type
+ { $$ = $5; }
+
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 ($$);
- }
+ .finish_template_type
+ { $$ = $5; }
;
+.finish_template_type:
+ {
+ if (yychar == YYEMPTY)
+ yychar = YYLEX;
+
+ $$ = finish_template_type ($<ttype>-3, $<ttype>-1,
+ yychar == SCOPE);
+ }
+
template_close_bracket:
'>'
| RSHIFT
@@ -1056,7 +1100,8 @@ unary_expr:
| SIZEOF unary_expr %prec UNARY
{ $$ = expr_sizeof ($2); }
| SIZEOF '(' type_id ')' %prec HYPERUNARY
- { $$ = c_sizeof (groktypename ($3.t)); }
+ { $$ = c_sizeof (groktypename ($3.t));
+ check_for_new_type ("sizeof", $3); }
| ALIGNOF unary_expr %prec UNARY
{ $$ = grok_alignof ($2); }
| ALIGNOF '(' type_id ')' %prec HYPERUNARY
@@ -1265,6 +1310,8 @@ expr_no_commas:
notype_unqualified_id:
'~' see_typename identifier
{ $$ = build_parse_node (BIT_NOT_EXPR, $3); }
+ | '~' see_typename template_type
+ { $$ = build_parse_node (BIT_NOT_EXPR, $3); }
| template_id
| operator_name
| IDENTIFIER
@@ -1273,7 +1320,16 @@ notype_unqualified_id:
;
do_id:
- { $$ = do_identifier ($<ttype>-1, 1, NULL_TREE); }
+ {
+ /* If lastiddecl is a TREE_LIST, it's a baselink, which
+ means that we're in an expression like S::f<int>, so
+ don't do_identifier; we only do that for unqualified
+ identifiers. */
+ if (lastiddecl && TREE_CODE (lastiddecl) != TREE_LIST)
+ $$ = do_identifier ($<ttype>-1, 1, NULL_TREE);
+ else
+ $$ = $<ttype>-1;
+ }
template_id:
PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
@@ -1298,13 +1354,23 @@ unqualified_id:
| SELFNAME
;
+expr_or_declarator_intern:
+ expr_or_declarator
+ | attributes expr_or_declarator
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
expr_or_declarator:
notype_unqualified_id
- | '*' expr_or_declarator %prec UNARY
+ | '*' expr_or_declarator_intern %prec UNARY
{ $$ = build_parse_node (INDIRECT_REF, $2); }
- | '&' expr_or_declarator %prec UNARY
+ | '&' expr_or_declarator_intern %prec UNARY
{ $$ = build_parse_node (ADDR_EXPR, $2); }
- | '(' expr_or_declarator ')'
+ | '(' expr_or_declarator_intern ')'
{ $$ = $2; }
;
@@ -1321,8 +1387,8 @@ direct_notype_declarator:
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); }
+ | '(' expr_or_declarator_intern ')'
+ { $$ = finish_decl_parsing ($2); }
;
primary:
@@ -1340,18 +1406,25 @@ primary:
if (processing_template_decl)
push_obstacks (&permanent_obstack, &permanent_obstack);
$$ = combine_strings ($$);
+ /* combine_strings doesn't set up TYPE_MAIN_VARIANT of
+ a const array the way we want, so fix it. */
+ if (flag_const_strings)
+ TREE_TYPE ($$) = build_cplus_array_type
+ (TREE_TYPE (TREE_TYPE ($$)),
+ TYPE_DOMAIN (TREE_TYPE ($$)));
if (processing_template_decl)
pop_obstacks ();
}
| '(' expr ')'
{ $$ = finish_parenthesized_expr ($2); }
- | '(' expr_or_declarator ')'
+ | '(' expr_or_declarator_intern ')'
{ $2 = reparse_decl_as_expr (NULL_TREE, $2);
$$ = finish_parenthesized_expr ($2); }
| '(' error ')'
{ $$ = error_mark_node; }
| '('
- { if (current_function_decl == 0)
+ { tree scope = current_scope ();
+ if (!scope || TREE_CODE (scope) != FUNCTION_DECL)
{
error ("braced-group within expression allowed only inside a function");
YYERROR;
@@ -1384,47 +1457,20 @@ primary:
{ $$ = finish_this_expr (); }
| CV_QUALIFIER '(' nonnull_exprlist ')'
{
- tree type = NULL_TREE;
- tree id = $$;
+ /* This is a C cast in C++'s `functional' notation
+ using the "implicit int" extension so that:
+ `const (3)' is equivalent to `const int (3)'. */
+ tree type;
- /* This is a C cast in C++'s `functional' notation. */
if ($3 == error_mark_node)
{
$$ = error_mark_node;
break;
}
-#if 0
- if ($3 == NULL_TREE)
- {
- error ("cannot cast null list to type `%s'",
- IDENTIFIER_POINTER (TYPE_NAME (id)));
- $$ = error_mark_node;
- break;
- }
-#endif
-#if 0
- /* type is not set! (mrs) */
- if (type == error_mark_node)
- $$ = error_mark_node;
- else
-#endif
- {
- if (id == ridpointers[(int) RID_CONST])
- type = build_type_variant (integer_type_node, 1, 0);
- else if (id == ridpointers[(int) RID_VOLATILE])
- type = build_type_variant (integer_type_node, 0, 1);
-#if 0
- /* should not be able to get here (mrs) */
- else if (id == ridpointers[(int) RID_FRIEND])
- {
- error ("cannot cast expression to `friend' type");
- $$ = error_mark_node;
- break;
- }
-#endif
- else my_friendly_abort (79);
- $$ = build_c_cast (type, build_compound_expr ($3));
- }
+
+ type = cp_build_qualified_type (integer_type_node,
+ cp_type_qual_from_rid ($1));
+ $$ = build_c_cast (type, build_compound_expr ($3));
}
| functional_cast
| DYNAMIC_CAST '<' type_id '>' '(' expr ')'
@@ -1464,9 +1510,9 @@ primary:
| overqualified_id %prec HYPERUNARY
{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
| overqualified_id '(' nonnull_exprlist ')'
- { $$ = finish_globally_qualified_member_call_expr ($1, $3); }
+ { $$ = finish_qualified_call_expr ($1, $3); }
| overqualified_id LEFT_RIGHT
- { $$ = finish_globally_qualified_member_call_expr ($1, NULL_TREE); }
+ { $$ = finish_qualified_call_expr ($1, NULL_TREE); }
| object object_template_id %prec UNARY
{
$$ = build_x_component_ref ($$, $2, NULL_TREE, 1);
@@ -1642,7 +1688,8 @@ type_id:
{ $$.t = build_decl_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec absdcl
- { $$.t = build_decl_list (get_decl_list ($1.t), $2);
+ { $$.t = build_decl_list (build_decl_list (NULL_TREE, $1.t),
+ $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_typespecs %prec EMPTY
{ $$.t = build_decl_list ($1.t, NULL_TREE);
@@ -1708,24 +1755,33 @@ reserved_declspecs:
to redeclare a typedef-name.
In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */
+/* We use hash_tree_cons for lists of typeless declspecs so that they end
+ up on a persistent obstack. Otherwise, they could appear at the
+ beginning of something like
+
+ static const struct { int foo () { } } b;
+
+ and would be discarded after we finish compiling foo. We don't need to
+ worry once we see a type. */
+
declmods:
nonempty_cv_qualifiers %prec EMPTY
{ $$ = $1.t; TREE_STATIC ($$) = 1; }
| SCSPEC
- { $$ = IDENTIFIER_AS_LIST ($$); }
+ { $$ = hash_tree_cons (NULL_TREE, $$, NULL_TREE); }
| declmods CV_QUALIFIER
- { $$ = decl_tree_cons (NULL_TREE, $2, $$);
+ { $$ = hash_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = 1; }
| declmods SCSPEC
{ if (extra_warnings && TREE_STATIC ($$))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
- $$ = decl_tree_cons (NULL_TREE, $2, $$);
+ $$ = hash_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = TREE_STATIC ($1); }
| declmods attributes
- { $$ = decl_tree_cons ($2, NULL_TREE, $1); }
- | attributes
- { $$ = decl_tree_cons ($1, NULL_TREE, NULL_TREE); }
+ { $$ = hash_tree_cons ($2, NULL_TREE, $1); }
+ | attributes %prec EMPTY
+ { $$ = hash_tree_cons ($1, NULL_TREE, NULL_TREE); }
;
/* Used instead of declspecs where storage classes are not allowed
@@ -1736,7 +1792,7 @@ declmods:
typed_typespecs:
typespec %prec EMPTY
- { $$.t = get_decl_list ($1.t);
+ { $$.t = build_decl_list (NULL_TREE, $1.t);
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers typespec
{ $$.t = decl_tree_cons (NULL_TREE, $2.t, $1.t);
@@ -1767,7 +1823,7 @@ typespec:
| complete_type_name
{ $$.t = $1; $$.new_type_flag = 0; }
| TYPEOF '(' expr ')'
- { $$.t = TREE_TYPE ($3);
+ { $$.t = finish_typeof ($3);
$$.new_type_flag = 0; }
| TYPEOF '(' type_id ')'
{ $$.t = groktypename ($3.t);
@@ -1817,16 +1873,19 @@ typespecqual_reserved:
initdecls:
initdcl0
| initdecls ',' initdcl
+ { check_multiple_declarators (); }
;
notype_initdecls:
notype_initdcl0
| notype_initdecls ',' initdcl
+ { check_multiple_declarators (); }
;
nomods_initdecls:
nomods_initdcl0
| nomods_initdecls ',' initdcl
+ { check_multiple_declarators (); }
;
maybeasm:
@@ -1995,7 +2054,7 @@ initlist:
fn.defpen:
PRE_PARSED_FUNCTION_DECL
{ start_function (NULL_TREE, TREE_VALUE ($1),
- NULL_TREE, 1);
+ NULL_TREE, 2);
reinit_parse_for_function (); }
pending_inline:
@@ -2003,11 +2062,16 @@ pending_inline:
{
int nested = (hack_decl_function_context
(current_function_decl) != NULL_TREE);
- finish_function (lineno, (int)$3, nested);
+ finish_function (lineno, (int)$3 | 2, nested);
process_next_inline ($1);
}
| fn.defpen maybe_return_init function_try_block
- { process_next_inline ($1); }
+ {
+ int nested = (hack_decl_function_context
+ (current_function_decl) != NULL_TREE);
+ finish_function (lineno, (int)$3 | 2, nested);
+ process_next_inline ($1);
+ }
| fn.defpen maybe_return_init error
{ process_next_inline ($1); }
;
@@ -2036,39 +2100,48 @@ pending_defargs:
structsp:
ENUM identifier '{'
{ $<itype>3 = suspend_momentary ();
- $<ttype>$ = start_enum ($2); }
+ $<ttype>$ = current_enum_type;
+ current_enum_type = start_enum ($2); }
enumlist maybecomma_warn '}'
- { $$.t = finish_enum ($<ttype>4, $5);
+ { TYPE_VALUES (current_enum_type) = $5;
+ $$.t = finish_enum (current_enum_type);
$$.new_type_flag = 1;
+ current_enum_type = $<ttype>4;
resume_momentary ((int) $<itype>3);
- check_for_missing_semicolon ($<ttype>4); }
+ check_for_missing_semicolon ($$.t); }
| ENUM identifier '{' '}'
- { $$.t = finish_enum (start_enum ($2), NULL_TREE);
+ { $$.t = finish_enum (start_enum ($2));
$$.new_type_flag = 1;
check_for_missing_semicolon ($$.t); }
| ENUM '{'
{ $<itype>2 = suspend_momentary ();
- $<ttype>$ = start_enum (make_anon_name ()); }
+ $<ttype>$ = current_enum_type;
+ current_enum_type = start_enum (make_anon_name ()); }
enumlist maybecomma_warn '}'
- { $$.t = finish_enum ($<ttype>3, $4);
+ { TYPE_VALUES (current_enum_type) = $4;
+ $$.t = finish_enum (current_enum_type);
+ $$.new_type_flag = 1;
+ current_enum_type = $<ttype>3;
resume_momentary ((int) $<itype>1);
- check_for_missing_semicolon ($<ttype>3);
- $$.new_type_flag = 1; }
+ check_for_missing_semicolon ($$.t); }
| ENUM '{' '}'
- { $$.t = finish_enum (start_enum (make_anon_name()), NULL_TREE);
+ { $$.t = finish_enum (start_enum (make_anon_name()));
$$.new_type_flag = 1;
check_for_missing_semicolon ($$.t); }
| ENUM identifier
- { $$.t = xref_tag (enum_type_node, $2, NULL_TREE, 1);
+ { $$.t = xref_tag (enum_type_node, $2, 1);
$$.new_type_flag = 0; }
| ENUM complex_type_name
- { $$.t = xref_tag (enum_type_node, $2, NULL_TREE, 1);
+ { $$.t = xref_tag (enum_type_node, $2, 1);
$$.new_type_flag = 0; }
| TYPENAME_KEYWORD typename_sub
{ $$.t = $2;
- $$.new_type_flag = 0; }
+ $$.new_type_flag = 0;
+ if (!processing_template_decl)
+ cp_pedwarn ("using `typename' outside of template"); }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
- | class_head left_curly
+ | class_head '{'
+ { $1.t = begin_class_definition ($1.t); }
opt.component_decl_list '}' maybe_attribute
{
int semi;
@@ -2077,25 +2150,32 @@ structsp:
yychar = YYLEX;
semi = yychar == ';';
- $<ttype>$ = finish_class_definition ($1, $3, $5, semi);
+ $<ttype>$ = finish_class_definition ($1.t, $6, semi,
+ $1.new_type_flag);
}
pending_defargs
- { finish_default_args (); }
+ {
+ begin_inline_definitions ();
+ }
pending_inlines
- { $$.t = $<ttype>6;
+ {
+ finish_inline_definitions ();
+ $$.t = $<ttype>7;
$$.new_type_flag = 1;
- begin_inline_definitions (); }
+ }
| class_head %prec EMPTY
{
+ if ($1.new_type_flag)
+ pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL ($1.t)));
$$.new_type_flag = 0;
- if (TYPE_BINFO ($1) == NULL_TREE)
+ if (TYPE_BINFO ($1.t) == NULL_TREE)
{
- cp_error ("%T is not a class type", $1);
+ cp_error ("%T is not a class type", $1.t);
$$.t = error_mark_node;
}
else
{
- $$.t = $1;
+ $$.t = $1.t;
/* struct B: public A; is not accepted by the WP grammar. */
if (TYPE_BINFO_BASETYPES ($$.t) && !TYPE_SIZE ($$.t)
&& ! TYPE_BEING_DEFINED ($$.t))
@@ -2133,7 +2213,10 @@ aggr:
named_class_head_sans_basetype:
aggr identifier
- { current_aggr = $$; $$ = $2; }
+ {
+ current_aggr = $1;
+ $$ = $2;
+ }
;
named_class_head_sans_basetype_defn:
@@ -2149,75 +2232,98 @@ named_complex_class_head_sans_basetype:
aggr nested_name_specifier identifier
{
current_aggr = $1;
- $$ = handle_class_head ($1, $2, $3);
+ $$.t = handle_class_head ($1, $2, $3);
+ $$.new_type_flag = 1;
}
| aggr global_scope nested_name_specifier identifier
{
current_aggr = $1;
- $$ = handle_class_head ($1, $3, $4);
+ $$.t = handle_class_head ($1, $3, $4);
+ $$.new_type_flag = 1;
}
| aggr global_scope identifier
{
current_aggr = $1;
- $$ = handle_class_head ($1, NULL_TREE, $3);
+ $$.t = handle_class_head ($1, NULL_TREE, $3);
+ $$.new_type_flag = 1;
+ }
+ | aggr apparent_template_type
+ {
+ current_aggr = $1;
+ $$.t = $2;
+ $$.new_type_flag = 0;
+ }
+ | aggr nested_name_specifier apparent_template_type
+ {
+ current_aggr = $1;
+ $$.t = $3;
+ if (CP_DECL_CONTEXT ($$.t))
+ push_scope (CP_DECL_CONTEXT ($$.t));
+ $$.new_type_flag = 1;
}
- | 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); }
;
named_class_head:
named_class_head_sans_basetype %prec EMPTY
- { $$ = xref_tag (current_aggr, $1, NULL_TREE, 1); }
- | named_class_head_sans_basetype_defn do_xref_defn
+ {
+ $$.t = xref_tag (current_aggr, $1, 1);
+ $$.new_type_flag = 0;
+ }
+ | named_class_head_sans_basetype_defn
+ { $<ttype>$ = xref_tag (current_aggr, $1, 0); }
+ /* Class name is unqualified, so we look for base classes
+ in the current scope. */
maybe_base_class_list %prec EMPTY
{
- $$ = $<ttype>2;
+ $$.t = $<ttype>2;
+ $$.new_type_flag = 0;
if ($3)
xref_basetypes (current_aggr, $1, $<ttype>2, $3);
}
- | named_complex_class_head_sans_basetype maybe_base_class_list
+ | 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)
+ if ($1.t != error_mark_node)
{
- 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'", $$);
+ $$.t = TREE_TYPE ($1.t);
+ $$.new_type_flag = $1.new_type_flag;
+ if (current_aggr == union_type_node
+ && TREE_CODE ($$.t) != UNION_TYPE)
+ cp_pedwarn ("`union' tag used in declaring `%#T'",
+ $$.t);
+ else if (TREE_CODE ($$.t) == UNION_TYPE
+ && current_aggr != union_type_node)
+ cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
+ else if (TREE_CODE ($$.t) == RECORD_TYPE)
+ /* We might be specializing a template with a different
+ class-key; deal. */
+ CLASSTYPE_DECLARED_CLASS ($$.t)
+ = (current_aggr == class_type_node);
+ if ($2)
+ {
+ maybe_process_partial_specialization ($$.t);
+ xref_basetypes (current_aggr, $1.t, $$.t, $2);
}
- xref_basetypes (current_aggr, $1, $$, $2);
}
}
;
unnamed_class_head:
aggr '{'
- { $$ = xref_tag ($$, make_anon_name (), NULL_TREE, 0);
+ { $$ = xref_tag ($$, make_anon_name (), 0);
yyungetc ('{', 1); }
;
+/* The tree output of this nonterminal a declarationf or the type
+ named. If NEW_TYPE_FLAG is set, then the name used in this
+ class-head was explicitly qualified, e.g.: `struct X::Y'. We have
+ already called push_scope for X. */
class_head:
unnamed_class_head
+ {
+ $$.t = $1;
+ $$.new_type_flag = 0;
+ }
| named_class_head
;
@@ -2238,76 +2344,18 @@ base_class_list:
base_class:
base_class.1
- {
- tree type;
- 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)))
- {
- error ("class name not allowed as base signature");
- $$ = NULL_TREE;
- }
- else if (current_aggr == signature_type_node)
- {
- sorry ("signature inheritance, base type `%s' ignored",
- IDENTIFIER_POINTER ($$));
- $$ = build_tree_list (access_public_node, type);
- }
- else if (type && IS_SIGNATURE (type))
- {
- error ("signature name not allowed as base class");
- $$ = NULL_TREE;
- }
- else
- $$ = build_tree_list (access_default_node, type);
- }
+ { $$ = finish_base_specifier (access_default_node, $1,
+ current_aggr
+ == signature_type_node); }
| base_class_access_list see_typename base_class.1
- {
- tree type;
- 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_type (type, 1))
- $$ = NULL_TREE;
- else if (current_aggr == signature_type_node
- && (! type) && (! IS_SIGNATURE (type)))
- {
- error ("class name not allowed as base signature");
- $$ = NULL_TREE;
- }
- else if (current_aggr == signature_type_node)
- {
- sorry ("signature inheritance, base type `%s' ignored",
- IDENTIFIER_POINTER ($$));
- $$ = build_tree_list (access_public_node, type);
- }
- else if (type && IS_SIGNATURE (type))
- {
- error ("signature name not allowed as base class");
- $$ = NULL_TREE;
- }
- else
- $$ = build_tree_list ($$, type);
- }
+ { $$ = finish_base_specifier ($1, $3,
+ current_aggr
+ == signature_type_node); }
;
base_class.1:
typename_sub
- { $$ = TYPE_MAIN_DECL ($1); }
+ { if ($$ != error_mark_node) $$ = TYPE_MAIN_DECL ($1); }
| nonnested_type
| SIGOF '(' expr ')'
{
@@ -2384,71 +2432,40 @@ base_class_access_list:
}
;
-left_curly:
- '{'
- { $<ttype>0 = begin_class_definition ($<ttype>0); }
- ;
-
-self_reference:
- /* empty */
- {
- $$ = build_self_reference ();
- }
- ;
-
opt.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 (access_public_node, $2);
- else
- $$ = 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 = $2;
+ | component_decl_list
+ | opt.component_decl_list access_specifier component_decl_list
+ | opt.component_decl_list access_specifier
+ ;
+access_specifier:
+ VISSPEC ':'
+ {
if (current_aggr == signature_type_node)
{
error ("access specifier not allowed in signature");
- visspec = access_public_node;
+ $1 = access_public_node;
}
- $$ = chainon ($$, build_tree_list (visspec, $4));
- }
- | opt.component_decl_list VISSPEC ':'
- {
- if (current_aggr == signature_type_node)
- error ("access specifier not allowed in signature");
- }
+
+ current_access_specifier = $1;
+ }
;
/* Note: we no longer warn about the semicolon after a component_decl_list.
ARM $9.2 says that the semicolon is optional, and therefore allowed. */
component_decl_list:
component_decl
- { if ($$ == void_type_node) $$ = NULL_TREE;
+ {
+ finish_member_declaration ($1);
}
| component_decl_list component_decl
- { /* In pushdecl, we created a reverse list of names
- in this binding level. Make sure that the chain
- of what we're trying to add isn't the item itself
- (which can happen with what pushdecl's doing). */
- if ($2 != NULL_TREE && $2 != void_type_node)
- {
- if (TREE_CHAIN ($2) != $$)
- $$ = chainon ($$, $2);
- else
- $$ = $2;
- }
+ {
+ finish_member_declaration ($2);
}
;
component_decl:
component_decl_1 ';'
- { }
| component_decl_1 '}'
{ error ("missing ';' before right brace");
yyungetc ('}', 0); }
@@ -2458,7 +2475,7 @@ component_decl:
{ $$ = finish_method ($$); }
| fn.def2 TRY /* base_init compstmt */
{ $$ = finish_method ($$); }
- | fn.def2 RETURN /* base_init compstmt */
+ | fn.def2 RETURN_KEYWORD /* base_init compstmt */
{ $$ = finish_method ($$); }
| fn.def2 '{' /* nodecls compstmt */
{ $$ = finish_method ($$); }
@@ -2468,9 +2485,20 @@ component_decl:
{ $$ = $2;
pedantic = $<itype>1; }
| template_header component_decl
- { $$ = finish_member_template_decl ($1, $2); }
+ {
+ if ($2)
+ $$ = finish_member_template_decl ($2);
+ else
+ /* The component was already processed. */
+ $$ = NULL_TREE;
+
+ finish_template_decl ($1);
+ }
| template_header typed_declspecs ';'
- { $$ = finish_member_class_template ($1, $2.t); }
+ {
+ $$ = finish_member_class_template ($2.t);
+ finish_template_decl ($1);
+ }
;
component_decl_1:
@@ -2478,9 +2506,32 @@ 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.t, $2); }
+ {
+ /* Most of the productions for component_decl only
+ allow the creation of one new member, so we call
+ finish_member_declaration in component_decl_list.
+ For this rule and the next, however, there can be
+ more than one member, e.g.:
+
+ int i, j;
+
+ and we need the first member to be fully
+ registered before the second is processed.
+ Therefore, the rules for components take care of
+ this processing. To avoid registering the
+ components more than once, we send NULL_TREE up
+ here; that lets finish_member_declaration know
+ that there is nothing to do. */
+ if (!$2)
+ grok_x_components ($1.t);
+ $$ = NULL_TREE;
+ }
| declmods notype_components
- { $$ = grok_x_components ($1, $2); }
+ {
+ if (!$2)
+ grok_x_components ($1);
+ $$ = NULL_TREE;
+ }
| notype_declarator maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
build_tree_list ($3, NULL_TREE)); }
@@ -2515,31 +2566,41 @@ component_decl_1:
/* ??? Huh? ^^^ */
components:
/* empty: possibly anonymous */
- { $$ = NULL_TREE; }
+ { $$ = 0; }
| component_declarator0
+ {
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $1 = finish_member_template_decl ($1);
+ finish_member_declaration ($1);
+ $$ = 1;
+ }
| components ',' component_declarator
- {
- /* In this context, void_type_node encodes
- friends. They have been recorded elsewhere. */
- if ($$ == void_type_node)
- $$ = $3;
- else
- $$ = chainon ($$, $3);
+ {
+ check_multiple_declarators ();
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $3 = finish_member_template_decl ($3);
+ finish_member_declaration ($3);
+ $$ = 2;
}
;
notype_components:
/* empty: possibly anonymous */
- { $$ = NULL_TREE; }
+ { $$ = 0; }
| notype_component_declarator0
+ {
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $1 = finish_member_template_decl ($1);
+ finish_member_declaration ($1);
+ $$ = 1;
+ }
| notype_components ',' notype_component_declarator
- {
- /* In this context, void_type_node encodes
- friends. They have been recorded elsewhere. */
- if ($$ == void_type_node)
- $$ = $3;
- else
- $$ = chainon ($$, $3);
+ {
+ check_multiple_declarators ();
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $3 = finish_member_template_decl ($3);
+ finish_member_declaration ($3);
+ $$ = 2;
}
;
@@ -2628,9 +2689,9 @@ enumlist:
enumerator:
identifier
- { $$ = build_enumerator ($$, NULL_TREE); }
+ { $$ = build_enumerator ($$, NULL_TREE, current_enum_type); }
| identifier '=' expr_no_commas
- { $$ = build_enumerator ($$, $3); }
+ { $$ = build_enumerator ($$, $3, current_enum_type); }
;
/* ANSI new-type-id (5.3.4) */
@@ -2664,10 +2725,10 @@ cv_qualifiers:
nonempty_cv_qualifiers:
CV_QUALIFIER
- { $$.t = IDENTIFIER_AS_LIST ($1);
+ { $$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
$$.new_type_flag = 0; }
| nonempty_cv_qualifiers CV_QUALIFIER
- { $$.t = decl_tree_cons (NULL_TREE, $2, $1.t);
+ { $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
$$.new_type_flag = $1.new_type_flag; }
;
@@ -2697,37 +2758,57 @@ maybe_parmlist:
;
/* A declarator that is allowed only after an explicit typespec. */
+
+after_type_declarator_intern:
+ after_type_declarator
+ | attributes after_type_declarator
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
/* may all be followed by prec '.' */
after_type_declarator:
- '*' nonempty_cv_qualifiers after_type_declarator %prec UNARY
+ '*' nonempty_cv_qualifiers after_type_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '&' nonempty_cv_qualifiers after_type_declarator %prec UNARY
+ | '&' nonempty_cv_qualifiers after_type_declarator_intern %prec UNARY
{ $$ = make_reference_declarator ($2.t, $3); }
- | '*' after_type_declarator %prec UNARY
+ | '*' after_type_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
- | '&' after_type_declarator %prec UNARY
+ | '&' after_type_declarator_intern %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | ptr_to_mem cv_qualifiers after_type_declarator
+ | ptr_to_mem cv_qualifiers after_type_declarator_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
| direct_after_type_declarator
;
+direct_after_type_declarator:
+ 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_intern ')'
+ { $$ = $2; }
+ | 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
+ ;
+
nonnested_type:
type_name %prec EMPTY
{
if (TREE_CODE ($1) == IDENTIFIER_NODE)
{
$$ = 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 ($$);
- }
+ maybe_note_name_used_in_class ($1, $$);
}
else
$$ = $1;
@@ -2754,35 +2835,29 @@ nested_type:
{ $$ = get_type_decl ($2); }
;
-direct_after_type_declarator:
- 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 ($1, 3);
- $$ = build_parse_node (SCOPE_REF, $$, $2);
- TREE_COMPLEXITY ($$) = current_class_depth; }
- | type_name %prec EMPTY
- ;
-
/* A declarator allowed whether or not there has been
an explicit typespec. These cannot redeclare a typedef-name. */
+notype_declarator_intern:
+ notype_declarator
+ | attributes notype_declarator
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
notype_declarator:
- '*' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ '*' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '&' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ | '&' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_reference_declarator ($2.t, $3); }
- | '*' notype_declarator %prec UNARY
+ | '*' notype_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
- | '&' notype_declarator %prec UNARY
+ | '&' notype_declarator_intern %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | ptr_to_mem cv_qualifiers notype_declarator
+ | ptr_to_mem cv_qualifiers notype_declarator_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
@@ -2790,15 +2865,15 @@ notype_declarator:
;
complex_notype_declarator:
- '*' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ '*' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '&' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ | '&' nonempty_cv_qualifiers notype_declarator_intern %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 cv_qualifiers notype_declarator
+ | ptr_to_mem cv_qualifiers notype_declarator_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
@@ -2815,25 +2890,11 @@ complex_direct_notype_declarator:
| direct_notype_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
| notype_qualified_id
- { 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;
- }
- }
+ { enter_scope_of ($1); }
| 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 ($1, 3);
- TREE_COMPLEXITY ($$) = current_class_depth;
- }
+ enter_scope_of ($$);
}
;
@@ -2864,12 +2925,11 @@ overqualified_id:
functional_cast:
typespec '(' nonnull_exprlist ')'
{ $$ = build_functional_cast ($1.t, $3); }
- | typespec '(' expr_or_declarator ')'
+ | typespec '(' expr_or_declarator_intern ')'
{ $$ = reparse_decl_as_expr ($1.t, $3); }
| typespec fcast_or_absdcl %prec EMPTY
{ $$ = reparse_absdcl_as_expr ($1.t, $2); }
;
-
type_name:
TYPENAME
| SELFNAME
@@ -2892,14 +2952,10 @@ nested_name_specifier_1:
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 ($$);
+ maybe_note_name_used_in_class ($1, $$);
}
- got_scope = $$ = TYPE_MAIN_VARIANT (TREE_TYPE ($$));
+ got_scope = $$ =
+ complete_type (TYPE_MAIN_VARIANT (TREE_TYPE ($$)));
}
| SELFNAME SCOPE
{
@@ -3073,19 +3129,29 @@ direct_new_declarator:
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
;
+absdcl_intern:
+ absdcl
+ | attributes absdcl
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
/* ANSI abstract-declarator (8.1) */
absdcl:
- '*' nonempty_cv_qualifiers absdcl
+ '*' nonempty_cv_qualifiers absdcl_intern
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '*' absdcl
+ | '*' absdcl_intern
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
| '*' nonempty_cv_qualifiers %prec EMPTY
{ $$ = make_pointer_declarator ($2.t, NULL_TREE); }
| '*' %prec EMPTY
{ $$ = make_pointer_declarator (NULL_TREE, NULL_TREE); }
- | '&' nonempty_cv_qualifiers absdcl
+ | '&' nonempty_cv_qualifiers absdcl_intern
{ $$ = make_reference_declarator ($2.t, $3); }
- | '&' absdcl
+ | '&' absdcl_intern
{ $$ = make_reference_declarator (NULL_TREE, $2); }
| '&' nonempty_cv_qualifiers %prec EMPTY
{ $$ = make_reference_declarator ($2.t, NULL_TREE); }
@@ -3095,7 +3161,7 @@ absdcl:
{ tree arg = make_pointer_declarator ($2, NULL_TREE);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
- | ptr_to_mem cv_qualifiers absdcl
+ | ptr_to_mem cv_qualifiers absdcl_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
@@ -3104,7 +3170,7 @@ absdcl:
/* ANSI direct-abstract-declarator (8.1) */
direct_abstract_declarator:
- '(' absdcl ')'
+ '(' absdcl_intern ')'
{ $$ = $2; }
/* `(typedef)1' is `int'. */
| PAREN_STAR_PAREN
@@ -3270,9 +3336,9 @@ simple_stmt:
{ finish_break_stmt (); }
| CONTINUE ';'
{ finish_continue_stmt (); }
- | RETURN ';'
+ | RETURN_KEYWORD ';'
{ finish_return_stmt (NULL_TREE); }
- | RETURN expr ';'
+ | RETURN_KEYWORD expr ';'
{ finish_return_stmt ($2); }
| asm_keyword maybe_cv_qualifier '(' string ')' ';'
{
@@ -3324,14 +3390,13 @@ function_try_block:
}
ctor_initializer_opt compstmt
{
+ end_protect_partials ();
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, nested);
+ $$ = $3;
}
;
@@ -3561,7 +3626,8 @@ named_parm:
{ $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec declarator
- { $$.t = build_tree_list (get_decl_list ($1.t), $2);
+ { $$.t = build_tree_list (build_decl_list (NULL_TREE, $1.t),
+ $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_declspecs1 absdcl
{ tree specs = strip_attrs ($1.t);
diff --git a/contrib/gcc/cp/pt.c b/contrib/gcc/cp/pt.c
index 556b761..47fa99a 100644
--- a/contrib/gcc/cp/pt.c
+++ b/contrib/gcc/cp/pt.c
@@ -1,5 +1,5 @@
/* Handle parameterized types (templates) for GNU C++.
- Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-97, 1998, 1999 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
@@ -39,6 +39,8 @@ Boston, MA 02111-1307, USA. */
#include "defaults.h"
#include "except.h"
#include "toplev.h"
+#include "rtl.h"
+#include "varray.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
@@ -48,15 +50,21 @@ extern struct obstack permanent_obstack;
extern int lineno;
extern char *input_filename;
-struct pending_inline *pending_template_expansions;
tree current_template_parms;
HOST_WIDE_INT processing_template_decl;
-tree pending_templates;
+/* The PENDING_TEMPLATES is a TREE_LIST of templates whose
+ instantiations have been deferred, either because their definitions
+ were not yet available, or because we were putting off doing the
+ work. The TREE_PURPOSE of each entry is a SRCLOC indicating where
+ the instantiate request occurred; the TREE_VALUE is a either a DECL
+ (for a function or static data member), or a TYPE (for a class)
+ indicating what we are hoping to instantiate. */
+static tree pending_templates;
static tree *template_tail = &pending_templates;
-tree maybe_templates;
+static tree maybe_templates;
static tree *maybe_template_tail = &maybe_templates;
int minimal_parse_mode;
@@ -67,6 +75,8 @@ int processing_template_parmlist;
static int template_header_count;
static tree saved_trees;
+static varray_type inline_parm_levels;
+static size_t inline_parm_levels_used;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -75,35 +85,47 @@ static tree saved_trees;
#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*));
+#define UNIFY_ALLOW_INTEGER 8
+
+#define GTB_VIA_VIRTUAL 1 /* The base class we are examining is
+ virtual, or a base class of a virtual
+ base. */
+#define GTB_IGNORE_TYPE 2 /* We don't need to try to unify the current
+ type with the desired type. */
+
+static int resolve_overloaded_unification PROTO((tree, tree, tree, tree,
+ unification_kind_t, int));
+static int try_one_overload PROTO((tree, tree, tree, tree, tree,
+ unification_kind_t, int));
+static int unify PROTO((tree, tree, tree, tree, 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 char *mangle_class_name_for_template PROTO((char *, 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 get_class_bindings PROTO((tree, tree, tree));
static tree coerce_template_parms PROTO((tree, tree, tree, int, int));
-static tree tsubst_enum PROTO((tree, tree, tree *));
+static void tsubst_enum PROTO((tree, tree, tree));
static tree add_to_template_args PROTO((tree, tree));
+static tree add_outermost_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));
+ int, unification_kind_t, 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 convert_template_argument PROTO ((tree, tree, tree, int,
+ int , 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 register_specialization PROTO((tree, tree, tree));
+static int unregister_specialization PROTO((tree, tree));
static tree reduce_template_parm_level PROTO((tree, tree, int));
static tree build_template_decl PROTO((tree, tree));
static int mark_template_parm PROTO((tree, void *));
@@ -113,35 +135,108 @@ 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 tree tsubst_template_arg_vector PROTO((tree, tree, int));
+static tree tsubst_template_parms PROTO((tree, tree, int));
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 \
+static tree most_specialized PROTO((tree, tree, tree));
+static tree most_specialized_class PROTO((tree, tree));
+static tree most_general_template PROTO((tree));
+static void set_mangled_name_for_template_decl PROTO((tree));
+static int template_class_depth_real PROTO((tree, int));
+static tree tsubst_aggr_type PROTO((tree, tree, int, tree, int));
+static tree tsubst_decl PROTO((tree, tree, tree, tree));
+static tree tsubst_arg_types PROTO((tree, tree, int, tree));
+static tree tsubst_function_type PROTO((tree, tree, int, tree));
+static void check_specialization_scope PROTO((void));
+static tree process_partial_specialization PROTO((tree));
+static void set_current_access_from_decl PROTO((tree));
+static void check_default_tmpl_args PROTO((tree, tree, int, int));
+static tree tsubst_call_declarator_parms PROTO((tree, tree, int, tree));
+static tree get_template_base_recursive PROTO((tree, tree,
+ tree, tree, tree, int));
+static tree get_template_base PROTO((tree, tree, tree, tree));
+static tree try_class_unification PROTO((tree, tree, tree, tree));
+static int coerce_template_template_parms PROTO((tree, tree, int,
+ tree, tree));
+static tree determine_specialization PROTO((tree, tree, tree *, int));
+static int template_args_equal PROTO((tree, tree));
+static void print_template_context PROTO((int));
+
+/* We use TREE_VECs to hold template arguments. If there is only one
+ level of template arguments, then the TREE_VEC contains the
+ arguments directly. If there is more than one level of template
+ arguments, then each entry in the TREE_VEC is itself a TREE_VEC,
+ containing the template arguments for a single level. The first
+ entry in the outer TREE_VEC is the outermost level of template
+ parameters; the last is the innermost.
+
+ It is incorrect to ever form a template argument vector containing
+ only one level of arguments, but which is a TREE_VEC containing as
+ its only entry the TREE_VEC for that level. */
+
+/* Non-zero if the template arguments is actually a vector of vectors,
+ rather than just a vector. */
+#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)
+/* The depth of a template argument vector. When called directly by
+ the parser, we use a TREE_LIST rather than a TREE_VEC to represent
+ template arguments. In fact, we may even see NULL_TREE if there
+ are no template arguments. In both of those cases, there is only
+ one level of template arguments. */
+#define TMPL_ARGS_DEPTH(NODE) \
+ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1)
+
+/* The LEVELth level of the template ARGS. Note that template
+ parameter levels are indexed from 1, not from 0. */
+#define TMPL_ARGS_LEVEL(ARGS, LEVEL) \
+ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \
+ ? TREE_VEC_ELT ((ARGS), (LEVEL) - 1) : ARGS)
+
+/* Set the LEVELth level of the template ARGS to VAL. This macro does
+ not work with single-level argument vectors. */
+#define SET_TMPL_ARGS_LEVEL(ARGS, LEVEL, VAL) \
+ (TREE_VEC_ELT ((ARGS), (LEVEL) - 1) = (VAL))
+
+/* Accesses the IDXth parameter in the LEVELth level of the ARGS. */
+#define TMPL_ARG(ARGS, LEVEL, IDX) \
+ (TREE_VEC_ELT (TMPL_ARGS_LEVEL (ARGS, LEVEL), IDX))
+
+/* Set the IDXth element in the LEVELth level of ARGS to VAL. This
+ macro does not work with single-level argument vectors. */
+#define SET_TMPL_ARG(ARGS, LEVEL, IDX, VAL) \
+ (TREE_VEC_ELT (TREE_VEC_ELT ((ARGS), (LEVEL) - 1), (IDX)) = (VAL))
+
+/* Given a single level of template arguments in NODE, return the
+ number of arguments. */
+#define NUM_TMPL_ARGS(NODE) \
+ ((NODE) == NULL_TREE ? 0 \
+ : (TREE_CODE (NODE) == TREE_VEC \
+ ? TREE_VEC_LENGTH (NODE) : list_length (NODE)))
+
+/* The number of levels of template parameters given by NODE. */
+#define TMPL_PARMS_DEPTH(NODE) \
+ (TREE_INT_CST_HIGH (TREE_PURPOSE (NODE)))
+
/* 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;
+finish_member_template_decl (decl)
tree decl;
{
- if (template_parameters)
- end_template_decl ();
- else
- end_specialization ();
-
if (decl == NULL_TREE || decl == void_type_node)
return NULL_TREE;
+ else if (decl == error_mark_node)
+ /* By returning NULL_TREE, the parser will just ignore this
+ declaration. We have already issued the error. */
+ return NULL_TREE;
else if (TREE_CODE (decl) == TREE_LIST)
{
/* Assume that the class is the only declspec. */
@@ -167,7 +262,6 @@ finish_member_template_decl (template_parameters, decl)
}
else
cp_error ("invalid member template declaration `%D'", decl);
-
return error_mark_node;
}
@@ -182,37 +276,59 @@ finish_member_template_decl (template_parameters, decl)
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. */
+ A<T>::B<U> has depth two, while A<T> has depth one.
+ Both A<T>::B<int> and A<int>::B<U> have depth one, if
+ COUNT_SPECIALIZATIONS is 0 or if they are instantiations, not
+ specializations.
-int
-template_class_depth (type)
+ This function is guaranteed to return 0 if passed NULL_TREE so
+ that, for example, `template_class_depth (current_class_type)' is
+ always safe. */
+
+static int
+template_class_depth_real (type, count_specializations)
tree type;
+ int count_specializations;
{
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;
+ type && TREE_CODE (type) != NAMESPACE_DECL;
+ type = (TREE_CODE (type) == FUNCTION_DECL)
+ ? DECL_REAL_CONTEXT (type) : TYPE_CONTEXT (type))
+ {
+ if (TREE_CODE (type) != FUNCTION_DECL)
+ {
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
+ && ((count_specializations
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
+ || uses_template_parms (CLASSTYPE_TI_ARGS (type))))
+ ++depth;
+ }
+ else
+ {
+ if (DECL_TEMPLATE_INFO (type)
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (type))
+ && ((count_specializations
+ && DECL_TEMPLATE_SPECIALIZATION (type))
+ || uses_template_parms (DECL_TI_ARGS (type))))
+ ++depth;
+ }
+ }
return depth;
}
-/* Return the original template for this decl, disregarding any
- specializations. */
+/* Returns the template nesting level of the indicated class TYPE.
+ Like template_class_depth_real, but instantiations do not count in
+ the depth. */
-static tree
-original_template (decl)
- tree decl;
+int
+template_class_depth (type)
+ tree type;
{
- while (DECL_TEMPLATE_INFO (decl))
- decl = DECL_TI_TEMPLATE (decl);
- return decl;
+ return template_class_depth_real (type, /*count_specializations=*/0);
}
/* Returns 1 if processing DECL as part of do_pending_inlines
@@ -225,7 +341,7 @@ inline_needs_template_parms (decl)
if (! DECL_TEMPLATE_INFO (decl))
return 0;
- return (list_length (DECL_TEMPLATE_PARMS (original_template (decl)))
+ return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (most_general_template (decl)))
> (processing_template_decl + DECL_TEMPLATE_SPECIALIZATION (decl)));
}
@@ -266,10 +382,15 @@ push_inline_template_parms_recursive (parmlist, levels)
case PARM_DECL:
{
- /* Make a CONST_DECL as is done in process_template_parm. */
+ /* Make a CONST_DECL as is done in process_template_parm.
+ It is ugly that we recreate this here; the original
+ version built in process_template_parm is no longer
+ available. */
tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
TREE_TYPE (parm));
+ SET_DECL_ARTIFICIAL (decl);
DECL_INITIAL (decl) = DECL_INITIAL (parm);
+ DECL_TEMPLATE_PARM_P (decl) = 1;
pushdecl (decl);
}
break;
@@ -288,35 +409,46 @@ maybe_begin_member_template_processing (decl)
tree decl;
{
tree parms;
- int levels;
-
- if (! inline_needs_template_parms (decl))
- return;
+ int levels = 0;
- parms = DECL_TEMPLATE_PARMS (original_template (decl));
+ if (inline_needs_template_parms (decl))
+ {
+ parms = DECL_TEMPLATE_PARMS (most_general_template (decl));
+ levels = TMPL_PARMS_DEPTH (parms) - processing_template_decl;
- levels = list_length (parms) - processing_template_decl;
+ if (DECL_TEMPLATE_SPECIALIZATION (decl))
+ {
+ --levels;
+ parms = TREE_CHAIN (parms);
+ }
- if (DECL_TEMPLATE_SPECIALIZATION (decl))
- {
- --levels;
- parms = TREE_CHAIN (parms);
+ push_inline_template_parms_recursive (parms, levels);
}
- push_inline_template_parms_recursive (parms, levels);
+ /* Remember how many levels of template parameters we pushed so that
+ we can pop them later. */
+ if (!inline_parm_levels)
+ VARRAY_INT_INIT (inline_parm_levels, 4, "inline_parm_levels");
+ if (inline_parm_levels_used == inline_parm_levels->num_elements)
+ VARRAY_GROW (inline_parm_levels, 2 * inline_parm_levels_used);
+ VARRAY_INT (inline_parm_levels, inline_parm_levels_used) = levels;
+ ++inline_parm_levels_used;
}
/* Undo the effects of begin_member_template_processing. */
void
-maybe_end_member_template_processing (decl)
- tree decl;
+maybe_end_member_template_processing ()
{
- if (! processing_template_decl)
+ int i;
+
+ if (!inline_parm_levels_used)
return;
- while (current_template_parms
- && TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
+ --inline_parm_levels_used;
+ for (i = 0;
+ i < VARRAY_INT (inline_parm_levels, inline_parm_levels_used);
+ ++i)
{
--processing_template_decl;
current_template_parms = TREE_CHAIN (current_template_parms);
@@ -336,14 +468,14 @@ maybe_end_member_template_processing (decl)
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. */
+ to be a member template. But, `template <class U> void
+ C<int>::f(U)' is considered a member template. */
int
is_member_template (t)
tree t;
{
- if (TREE_CODE (t) != FUNCTION_DECL
- && !DECL_FUNCTION_TEMPLATE_P (t))
+ if (!DECL_FUNCTION_TEMPLATE_P (t))
/* Anything that isn't a function or a template function is
certainly not a member template. */
return 0;
@@ -352,33 +484,15 @@ is_member_template (t)
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
+ return (DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))
/* 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;
+ && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) >
+ template_class_depth (DECL_CLASS_CONTEXT (t))));
}
+#if 0 /* UNUSED */
/* Returns non-zero iff T is a member template class. See
is_member_template for a description of what precisely constitutes
a member template. */
@@ -400,146 +514,69 @@ is_member_template_class (t)
/* 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)) >
+ return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) >
template_class_depth (DECL_CONTEXT (t)));
}
+#endif
-/* 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. */
+/* Return a new template argument vector which contains all of ARGS,
+ but has as its innermost set of arguments the EXTRA_ARGS. The
+ resulting vector will be built on a temporary obstack, and so must
+ be explicitly copied to the permanent obstack, if required. */
static tree
-complete_template_args (tmpl, extra_args, unbound_only)
- tree tmpl, extra_args;
- int unbound_only;
+add_to_template_args (args, extra_args)
+ tree args;
+ tree extra_args;
{
- /* 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);
- }
- }
- }
- }
+ tree new_args;
+ int extra_depth;
+ int i;
+ int j;
- 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);
+ extra_depth = TMPL_ARGS_DEPTH (extra_args);
+ new_args = make_temp_vec (TMPL_ARGS_DEPTH (args) + extra_depth);
- if (spec_args)
- TREE_VEC_ELT (new_args, depth) = spec_args;
+ for (i = 1; i <= TMPL_ARGS_DEPTH (args); ++i)
+ SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (args, i));
+ for (j = 1; j <= extra_depth; ++j, ++i)
+ SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (extra_args, j));
+
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. */
+/* Like add_to_template_args, but only the outermost ARGS are added to
+ the EXTRA_ARGS. In particular, all but TMPL_ARGS_DEPTH
+ (EXTRA_ARGS) levels are added. This function is used to combine
+ the template arguments from a partial instantiation with the
+ template arguments used to attain the full instantiation from the
+ partial instantiation. */
static tree
-add_to_template_args (args, extra_args)
+add_outermost_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;
+ /* If there are more levels of EXTRA_ARGS than there are ARGS,
+ something very fishy is going on. */
+ my_friendly_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),
+ 0);
- new_args = make_tree_vec (TREE_VEC_LENGTH (args) + 1);
+ /* If *all* the new arguments will be the EXTRA_ARGS, just return
+ them. */
+ if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH (extra_args))
+ return extra_args;
- 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;
+ /* For the moment, we make ARGS look like it contains fewer levels. */
+ TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args);
+
+ new_args = add_to_template_args (args, extra_args);
+
+ /* Now, we restore ARGS to its full dimensions. */
+ TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH (extra_args);
return new_args;
}
@@ -571,12 +608,46 @@ begin_template_parm_list ()
note_template_header (0);
}
+/* This routine is called when a specialization is declared. If it is
+ illegal to declare a specialization here, an error is reported. */
+
+static void
+check_specialization_scope ()
+{
+ tree scope = current_scope ();
+
+ /* [temp.expl.spec]
+
+ An explicit specialization shall be declared in the namespace of
+ which the template is a member, or, for member templates, in the
+ namespace of which the enclosing class or enclosing class
+ template is a member. An explicit specialization of a member
+ function, member class or static data member of a class template
+ shall be declared in the namespace of which the class template
+ is a member. */
+ if (scope && TREE_CODE (scope) != NAMESPACE_DECL)
+ cp_error ("explicit specialization in non-namespace scope `%D'",
+ scope);
+
+ /* [temp.expl.spec]
+
+ In an explicit specialization declaration for a member of a class
+ template or a member template that appears in namespace scope,
+ the member template and some of its enclosing class templates may
+ remain unspecialized, except that the declaration shall not
+ explicitly specialize a class member template if its enclosing
+ class templates are not explicitly specialized as well. */
+ if (current_template_parms)
+ cp_error ("enclosing class templates are not explicitly specialized");
+}
+
/* We've just seen template <>. */
void
begin_specialization ()
{
note_template_header (1);
+ check_specialization_scope ();
}
/* Called at then end of processing a declaration preceeded by
@@ -625,6 +696,36 @@ end_explicit_instantiation ()
--processing_explicit_instantiation;
}
+/* The TYPE is being declared. If it is a template type, that means it
+ is a partial specialization. Do appropriate error-checking. */
+
+void
+maybe_process_partial_specialization (type)
+ tree type;
+{
+ if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type))
+ {
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
+ && TYPE_SIZE (type) == NULL_TREE)
+ {
+ if (current_namespace
+ != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
+ {
+ cp_pedwarn ("specializing `%#T' in different namespace", type);
+ cp_pedwarn_at (" from definition of `%#D'",
+ CLASSTYPE_TI_TEMPLATE (type));
+ }
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+ if (processing_template_decl)
+ push_template_decl (TYPE_MAIN_DECL (type));
+ }
+ else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+ cp_error ("specialization of `%T' after instantiation", type);
+ }
+ else if (processing_specialization)
+ cp_error ("explicit specialization of non-template `%T'", type);
+}
+
/* 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
@@ -641,6 +742,12 @@ retrieve_specialization (tmpl, args)
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+ /* There should be as many levels of arguments as there are
+ levels of parameters. */
+ my_friendly_assert (TMPL_ARGS_DEPTH (args)
+ == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)),
+ 0);
+
for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE;
s = TREE_CHAIN (s))
@@ -675,8 +782,8 @@ is_specialization_of (decl, tmpl)
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))
+ if (same_type_p (TYPE_MAIN_VARIANT (t),
+ TYPE_MAIN_VARIANT (TREE_TYPE (tmpl))))
return 1;
}
@@ -684,9 +791,10 @@ is_specialization_of (decl, tmpl)
}
/* Register the specialization SPEC as a specialization of TMPL with
- the indicated ARGS. */
+ the indicated ARGS. Returns SPEC, or an equivalent prior
+ declaration, if available. */
-static void
+static tree
register_specialization (spec, tmpl, args)
tree spec;
tree tmpl;
@@ -696,14 +804,27 @@ register_specialization (spec, tmpl, args)
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;
+ if (TREE_CODE (spec) == FUNCTION_DECL
+ && uses_template_parms (DECL_TI_ARGS (spec)))
+ /* This is the FUNCTION_DECL for a partial instantiation. Don't
+ register it; we want the corresponding TEMPLATE_DECL instead.
+ We use `uses_template_parms (DECL_TI_ARGS (spec))' rather than
+ the more obvious `uses_template_parms (spec)' to avoid problems
+ with default function arguments. In particular, given
+ something like this:
+
+ template <class T> void f(T t1, T t = T())
+
+ the default argument expression is not substituted for in an
+ instantiation unless and until it is actually needed. */
+ return spec;
+ /* There should be as many levels of arguments as there are
+ levels of parameters. */
+ my_friendly_assert (TMPL_ARGS_DEPTH (args)
+ == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)),
+ 0);
+
for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE;
s = TREE_CHAIN (s))
@@ -720,7 +841,7 @@ register_specialization (spec, tmpl, args)
{
cp_error ("specialization of %D after instantiation",
fn);
- return;
+ return spec;
}
else
{
@@ -729,68 +850,117 @@ register_specialization (spec, tmpl, args)
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;
+ implicitly instantiated a member function and
+ then specialized it later.
+
+ We can also wind up here if a friend
+ declaration that looked like an instantiation
+ turns out to be a specialization:
+
+ template <class T> void foo(T);
+ class S { friend void foo<>(int) };
+ template <> void foo(int);
+
+ We transform the existing DECL in place so that
+ any pointers to it become pointers to the
+ updated declaration.
+
+ If there was a definition for the template, but
+ not for the specialization, we want this to
+ look as if there is no definition, and vice
+ versa. */
+ DECL_INITIAL (fn) = NULL_TREE;
+ duplicate_decls (spec, fn);
+
+ return fn;
}
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
- if (DECL_INITIAL (fn))
- cp_error ("duplicate specialization of %D", fn);
-
- TREE_VALUE (s) = spec;
- return;
+ duplicate_decls (spec, fn);
+ return fn;
}
}
}
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
= perm_tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+
+ return spec;
+}
+
+/* Unregister the specialization SPEC as a specialization of TMPL.
+ Returns nonzero if the SPEC was listed as a specialization of
+ TMPL. */
+
+static int
+unregister_specialization (spec, tmpl)
+ tree spec;
+ tree tmpl;
+{
+ tree* s;
+
+ for (s = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
+ *s != NULL_TREE;
+ s = &TREE_CHAIN (*s))
+ if (TREE_VALUE (*s) == spec)
+ {
+ *s = TREE_CHAIN (*s);
+ return 1;
+ }
+
+ return 0;
}
/* Print the list of candidate FNS in an error message. */
-static void
+void
print_candidates (fns)
tree fns;
{
tree fn;
- char* str = "candidates are:";
+ const char *str = "candidates are:";
for (fn = fns; fn != NULL_TREE; fn = TREE_CHAIN (fn))
{
- cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
+ tree f;
+
+ for (f = TREE_VALUE (fn); f; f = OVL_NEXT (f))
+ cp_error_at ("%s %+#D", str, OVL_CURRENT (f));
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. */
+ explicit template args given in TEMPLATE_ID. The DECL may be
+ NULL_TREE if none is available. In that case, the functions in
+ TEMPLATE_ID are non-members.
-tree
+ If NEED_MEMBER_TEMPLATE is non-zero the function is known to be 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. The error_mark_node is returned to indicate failure. */
+
+static tree
determine_specialization (template_id, decl, targs_out,
- need_member_template,
- complain)
+ need_member_template)
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;
+ tree fns;
+ tree targs;
+ tree explicit_targs;
+ tree candidates = NULL_TREE;
+ tree templates = NULL_TREE;
*targs_out = NULL_TREE;
@@ -798,7 +968,7 @@ determine_specialization (template_id, decl, targs_out,
return error_mark_node;
fns = TREE_OPERAND (template_id, 0);
- targs_in = TREE_OPERAND (template_id, 1);
+ explicit_targs = TREE_OPERAND (template_id, 1);
if (fns == error_mark_node)
return error_mark_node;
@@ -812,86 +982,146 @@ determine_specialization (template_id, decl, targs_out,
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)))
+
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ /* DECL might be a specialization of FN. */
+ tmpl = fn;
+ else if (need_member_template)
+ /* FN is an ordinary member function, and we need a
+ specialization of a member template. */
+ continue;
+ else if (TREE_CODE (fn) != FUNCTION_DECL)
+ /* We can get IDENTIFIER_NODEs here in certain erroneous
+ cases. */
+ continue;
+ else if (!DECL_FUNCTION_MEMBER_P (fn))
+ /* This is just an ordinary non-member function. Nothing can
+ be a specialization of that. */
continue;
else
- tmpl = fn;
+ {
+ tree decl_arg_types;
- if (list_length (targs_in) > DECL_NTPARMS (tmpl))
- continue;
+ /* This is an ordinary member function. However, since
+ we're here, we can assume it's enclosing class is a
+ template class. For example,
+
+ template <typename T> struct S { void f(); };
+ template <> void S<int>::f() {}
- 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);
+ Here, S<int>::f is a non-template, but S<int> is a
+ template class. If FN has the same type as DECL, we
+ might be in business. */
+ if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
+ TREE_TYPE (TREE_TYPE (fn))))
+ /* The return types differ. */
+ continue;
+
+ /* Adjust the type of DECL in case FN is a static member. */
+ decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ if (DECL_STATIC_FUNCTION_P (fn)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ decl_arg_types = TREE_CHAIN (decl_arg_types);
+
+ if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
+ decl_arg_types))
+ /* They match! */
+ candidates = tree_cons (NULL_TREE, fn, candidates);
+
+ continue;
}
- 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;
+ /* See whether this function might be a specialization of this
+ template. */
+ targs = get_bindings (tmpl, decl, explicit_targs);
+
+ if (!targs)
+ /* We cannot deduce template arguments that when used to
+ specialize TMPL will produce DECL. */
+ continue;
- *targs_out = get_bindings (tmpl, decl, targs_in);
- return tmpl;
+ /* Save this template, and the arguments deduced. */
+ templates = scratch_tree_cons (targs, tmpl, templates);
}
- if (templates == NULL_TREE)
+ if (templates && TREE_CHAIN (templates))
{
- 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;
+ /* We have:
+
+ [temp.expl.spec]
+
+ It is possible for a specialization with a given function
+ signature to be instantiated from more than one function
+ template. In such cases, explicit specification of the
+ template arguments must be used to uniquely identify the
+ function template specialization being specialized.
+
+ Note that here, there's no suggestion that we're supposed to
+ determine which of the candidate templates is most
+ specialized. However, we, also have:
+
+ [temp.func.order]
+
+ Partial ordering of overloaded function template
+ declarations is used in the following contexts to select
+ the function template to which a function template
+ specialization refers:
+
+ -- when an explicit specialization refers to a function
+ template.
+
+ So, we do use the partial ordering rules, at least for now.
+ This extension can only serve to make illegal programs legal,
+ so it's safe. And, there is strong anecdotal evidence that
+ the committee intended the partial ordering rules to apply;
+ the EDG front-end has that behavior, and John Spicer claims
+ that the committee simply forgot to delete the wording in
+ [temp.expl.spec]. */
+ tree tmpl = most_specialized (templates, decl, explicit_targs);
+ if (tmpl && tmpl != error_mark_node)
+ {
+ targs = get_bindings (tmpl, decl, explicit_targs);
+ templates = scratch_tree_cons (targs, tmpl, NULL_TREE);
+ }
+ }
+
+ if (templates == NULL_TREE && candidates == NULL_TREE)
+ {
+ cp_error_at ("template-id `%D' for `%+D' does not match any template declaration",
+ template_id, decl);
+ return error_mark_node;
}
- else if (TREE_CHAIN (templates) != NULL_TREE)
+ else if ((templates && TREE_CHAIN (templates))
+ || (candidates && TREE_CHAIN (candidates))
+ || (templates && candidates))
{
- 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;
+ cp_error_at ("ambiguous template specialization `%D' for `%+D'",
+ template_id, decl);
+ chainon (candidates, templates);
+ print_candidates (candidates);
+ return error_mark_node;
}
/* We have one, and exactly one, match. */
- *targs_out = TREE_PURPOSE (templates);
+ if (candidates)
+ {
+ /* It was a specialization of an ordinary member function in a
+ template class. */
+ *targs_out = copy_node (DECL_TI_ARGS (TREE_VALUE (candidates)));
+ return DECL_TI_TEMPLATE (TREE_VALUE (candidates));
+ }
+
+ /* It was a specialization of a template. */
+ targs = DECL_TI_ARGS (DECL_RESULT (TREE_VALUE (templates)));
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (targs))
+ {
+ *targs_out = copy_node (targs);
+ SET_TMPL_ARGS_LEVEL (*targs_out,
+ TMPL_ARGS_DEPTH (*targs_out),
+ TREE_PURPOSE (templates));
+ }
+ else
+ *targs_out = TREE_PURPOSE (templates);
return TREE_VALUE (templates);
}
@@ -901,19 +1131,14 @@ determine_specialization (template_id, decl, targs_out,
instantiation at this point.
Returns DECL, or an equivalent declaration that should be used
- instead.
+ instead if all goes well. Issues an error message if something is
+ amiss. Returns error_mark_node if the error is not easily
+ recoverable.
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
@@ -927,8 +1152,7 @@ determine_specialization (template_id, decl, targs_out,
template <class T> struct S {};
template <> struct S<int> { void f(); }
- template <>
- void S<int>::f();
+ template <> void S<int>::f();
the TEMPLATE_COUNT would be 0. (Note that this declaration is
illegal; there should be no template <>.)
@@ -945,113 +1169,117 @@ check_explicit_specialization (declarator, decl, template_count, flags)
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;
+ int member_specialization = 0;
tree ctype = DECL_CLASS_CONTEXT (decl);
tree dname = DECL_NAME (decl);
- if (!finish_member)
+ if (processing_specialization)
{
- if (processing_specialization)
- {
- /* The last template header was of the form template <>. */
+ /* 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();
+ 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);
- But, we're missing another template <>. */
- cp_error("too few template parameter lists in declaration of `%D'", decl);
- return decl;
- }
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ if (ctype)
+ member_specialization = 1;
+ else
+ specialization = 1;
}
- else if (processing_explicit_instantiation)
+ else if (template_header_count == template_count)
{
- 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;
+ /* 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 if (ctype != NULL_TREE
- && !TYPE_BEING_DEFINED (ctype)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
+ else
{
- /* This case catches outdated code that looks like this:
+ /* 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();
- template <class T> struct S { void f(); };
- void S<int>::f() {} // Missing template <>
+ 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)
+ && !is_friend)
+ {
+ /* This case catches outdated code that looks like this:
- 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. */
+ 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);
+ if (template_header_count)
+ {
+ cp_error ("template parameters specified in specialization");
+ return decl;
}
- else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+
+ 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)
+ {
+ if (is_friend)
+ /* This could be something like:
+
+ template <class T> void f(T);
+ class S { friend void f<>(int); } */
+ specialization = 1;
+ else
{
- /* This case handles bogus declarations like
- template <> template <class T>
- void f<int>(); */
+ /* This case handles bogus declarations like template <>
+ template <class T> void f<int>(); */
cp_error ("template-id `%D' in declaration of primary template",
declarator);
@@ -1069,6 +1297,8 @@ check_explicit_specialization (declarator, decl, template_count, flags)
("default argument specified in explicit specialization");
break;
}
+ if (current_lang_name == lang_name_c)
+ cp_error ("template specialization with C linkage");
}
if (specialization || member_specialization || explicit_instantiation)
@@ -1095,47 +1325,41 @@ check_explicit_specialization (declarator, decl, template_count, flags)
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;
- }
+ /* A specialization in class scope. This is illegal,
+ but the error will already have been flagged by
+ check_specialization_scope. */
+ return error_mark_node;
else
- /* It's not legal to write an explicit instantiation in
- class scope, e.g.:
+ {
+ /* It's not legal to write an explicit instantiation in
+ class scope, e.g.:
- class C { template void f(); }
+ class C { template void f(); }
- This case is caught by the parser. However, on
- something like:
+ This case is caught by the parser. However, on
+ something like:
- template class C { void f(); };
+ template class C { void f(); };
- (which is illegal) we can get here. The error will be
- issued later. */
- ;
+ (which is illegal) we can get here. The error will be
+ issued later. */
+ ;
+ }
return decl;
}
+ else 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;
+ }
else if (ctype != NULL_TREE
&& (TREE_CODE (TREE_OPERAND (declarator, 0)) ==
IDENTIFIER_NODE))
@@ -1143,8 +1367,9 @@ check_explicit_specialization (declarator, decl, template_count, flags)
/* Find the list of functions in ctype that have the same
name as the declared function. */
tree name = TREE_OPERAND (declarator, 0);
- tree fns;
-
+ tree fns = NULL_TREE;
+ int idx;
+
if (name == constructor_name (ctype)
|| name == constructor_name_full (ctype))
{
@@ -1162,21 +1387,51 @@ check_explicit_specialization (declarator, decl, template_count, flags)
Similar language is found in [temp.explicit]. */
cp_error ("specialization of implicitly-declared special member function");
-
- return decl;
+ return error_mark_node;
}
name = is_constructor ? ctor_identifier : dtor_identifier;
}
- fns = lookup_fnfields (TYPE_BINFO (ctype), name, 1);
-
+ if (!IDENTIFIER_TYPENAME_P (name))
+ {
+ idx = lookup_fnfields_1 (ctype, name);
+ if (idx >= 0)
+ fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (ctype), idx);
+ }
+ else
+ {
+ tree methods;
+
+ /* For a type-conversion operator, we cannot do a
+ name-based lookup. We might be looking for `operator
+ int' which will be a specialization of `operator T'.
+ So, we find *all* the conversion operators, and then
+ select from them. */
+ fns = NULL_TREE;
+
+ methods = CLASSTYPE_METHOD_VEC (ctype);
+ if (methods)
+ for (idx = 2; idx < TREE_VEC_LENGTH (methods); ++idx)
+ {
+ tree ovl = TREE_VEC_ELT (methods, idx);
+
+ if (!ovl || !DECL_CONV_FN_P (OVL_CURRENT (ovl)))
+ /* There are no more conversion functions. */
+ break;
+
+ /* Glue all these conversion functions together
+ with those we already have. */
+ for (; ovl; ovl = OVL_NEXT (ovl))
+ fns = ovl_cons (OVL_CURRENT (ovl), fns);
+ }
+ }
+
if (fns == NULL_TREE)
{
- cp_error ("no member function `%s' declared in `%T'",
- IDENTIFIER_POINTER (name),
- ctype);
- return decl;
+ cp_error ("no member function `%D' declared in `%T'",
+ name, ctype);
+ return error_mark_node;
}
else
TREE_OPERAND (declarator, 0) = fns;
@@ -1186,100 +1441,141 @@ check_explicit_specialization (declarator, decl, template_count, flags)
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. */
+ function of a template class. Even if a member template is
+ being instantiated, the member template arguments may be
+ elided if they can be deduced from the rest of the
+ declaration. */
tmpl = determine_specialization (declarator, decl,
&targs,
- member_specialization,
- 1);
+ member_specialization);
- if (tmpl && tmpl != error_mark_node)
+ if (!tmpl || tmpl == error_mark_node)
+ /* We couldn't figure out what this declaration was
+ specializing. */
+ return error_mark_node;
+ else
{
+ tree gen_tmpl = most_general_template (tmpl);
+
if (explicit_instantiation)
{
+ /* We don't set DECL_EXPLICIT_INSTANTIATION here; that
+ is done by do_decl_instantiation later. */
+
+ int arg_depth = TMPL_ARGS_DEPTH (targs);
+ int parm_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
+
+ if (arg_depth > parm_depth)
+ {
+ /* If TMPL is not the most general template (for
+ example, if TMPL is a friend template that is
+ injected into namespace scope), then there will
+ be too many levels fo TARGS. Remove some of them
+ here. */
+ int i;
+ tree new_targs;
+
+ new_targs = make_temp_vec (parm_depth);
+ for (i = arg_depth - parm_depth; i < arg_depth; ++i)
+ TREE_VEC_ELT (new_targs, i - (arg_depth - parm_depth))
+ = TREE_VEC_ELT (targs, i);
+ targs = new_targs;
+ }
+
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))
+
+ /* If we though that the DECL was a member function, but it
+ turns out to be specializing a static member function,
+ make DECL a static member function as well. */
+ 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);
}
+ /* Set up the DECL_TEMPLATE_INFO for DECL. */
+ DECL_TEMPLATE_INFO (decl)
+ = perm_tree_cons (tmpl, targs, NULL_TREE);
+
/* 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. */
+ treatment. We do this here so that the ordinary,
+ non-template, name-mangling algorith will not be used
+ later. */
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);
- }
+ set_mangled_name_for_template_decl (decl);
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;
- }
+ /* 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);
+
+ /* Register this specialization so that we can find it
+ again. */
+ decl = register_specialization (decl, gen_tmpl, targs);
+ }
+ }
+
+ 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.)
+/* TYPE is being declared. Verify that the use of template headers
+ and such is reasonable. Issue error messages if not. */
- According to the CD2,
+void
+maybe_check_template_type (type)
+ tree type;
+{
+ if (template_header_count)
+ {
+ /* We are in the scope of some `template <...>' header. */
- 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.
+ int context_depth
+ = template_class_depth_real (TYPE_CONTEXT (type),
+ /*count_specializations=*/1);
- 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);
+ if (template_header_count <= context_depth)
+ /* This is OK; the template headers are for the context. We
+ are actually too lenient here; like
+ check_explicit_specialization we should consider the number
+ of template types included in the actual declaration. For
+ example,
- register_specialization (decl, tmpl, targs);
+ template <class T> struct S {
+ template <class U> template <class V>
+ struct I {};
+ };
- return decl;
- }
+ is illegal, but:
+
+ template <class T> struct S {
+ template <class U> struct I;
+ };
+
+ template <class T> template <class U.
+ struct S<T>::I {};
+
+ is not. */
+ ;
+ else if (template_header_count > context_depth + 1)
+ /* There are two many template parameter lists. */
+ cp_error ("too many template parameter lists in declaration of `%T'", type);
}
-
- return decl;
}
/* Returns 1 iff PARMS1 and PARMS2 are identical sets of template
@@ -1320,8 +1616,7 @@ int comp_template_parms (parms1, parms2)
if (TREE_CODE (parm1) == TEMPLATE_TYPE_PARM)
continue;
- else if (!comptypes (TREE_TYPE (parm1),
- TREE_TYPE (parm2), 1))
+ else if (!same_type_p (TREE_TYPE (parm1), TREE_TYPE (parm2)))
return 0;
}
}
@@ -1334,6 +1629,51 @@ int comp_template_parms (parms1, parms2)
return 1;
}
+/* Complain if DECL shadows a template parameter.
+
+ [temp.local]: A template-parameter shall not be redeclared within its
+ scope (including nested scopes). */
+
+void
+check_template_shadow (decl)
+ tree decl;
+{
+ tree olddecl;
+
+ /* If we're not in a template, we can't possibly shadow a template
+ parameter. */
+ if (!current_template_parms)
+ return;
+
+ /* Figure out what we're shadowing. */
+ if (TREE_CODE (decl) == OVERLOAD)
+ decl = OVL_CURRENT (decl);
+ olddecl = IDENTIFIER_VALUE (DECL_NAME (decl));
+
+ /* If there's no previous binding for this name, we're not shadowing
+ anything, let alone a template parameter. */
+ if (!olddecl)
+ return;
+
+ /* If we're not shadowing a template parameter, we're done. Note
+ that OLDDECL might be an OVERLOAD (or perhaps even an
+ ERROR_MARK), so we can't just blithely assume it to be a _DECL
+ node. */
+ if (TREE_CODE_CLASS (TREE_CODE (olddecl)) != 'd'
+ || !DECL_TEMPLATE_PARM_P (olddecl))
+ return;
+
+ /* We check for decl != olddecl to avoid bogus errors for using a
+ name inside a class. We check TPFI to avoid duplicate errors for
+ inline member templates. */
+ if (decl == olddecl
+ || TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
+ return;
+
+ cp_error_at ("declaration of `%#D'", decl);
+ cp_error_at (" shadows template parm `%#D'", olddecl);
+}
+
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
ORIG_LEVEL, DECL, and TYPE. */
@@ -1428,6 +1768,13 @@ process_template_parm (list, next)
/* is a const-param */
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
PARM, 0, NULL_TREE);
+
+ /* [temp.param]
+
+ The top-level cv-qualifiers on the template-parameter are
+ ignored when determining its type. */
+ TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+
/* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1;
if (IS_AGGR_TYPE (TREE_TYPE (parm))
@@ -1477,7 +1824,6 @@ process_template_parm (list, next)
decl = build_decl (TYPE_DECL, parm, t);
}
- CLASSTYPE_GOT_SEMICOLON (t) = 1;
TYPE_NAME (t) = decl;
TYPE_STUB_DECL (t) = decl;
parm = decl;
@@ -1487,6 +1833,7 @@ process_template_parm (list, next)
decl, TREE_TYPE (parm));
}
SET_DECL_ARTIFICIAL (decl);
+ DECL_TEMPLATE_PARM_P (decl) = 1;
pushdecl (decl);
parm = build_tree_list (defval, parm);
return chainon (list, parm);
@@ -1535,26 +1882,34 @@ end_template_decl ()
(void) get_pending_sizes (); /* Why? */
}
-/* Generate a valid set of template args from current_template_parms. */
+/* Given a template argument vector containing the template PARMS.
+ The innermost PARMS are given first. */
tree
current_template_args ()
{
- tree header = current_template_parms;
- int length = list_length (header);
- tree args = make_tree_vec (length);
+ tree header;
+ tree args = NULL_TREE;
+ int length = TMPL_PARMS_DEPTH (current_template_parms);
int l = length;
- while (header)
+ /* If there is only one level of template parameters, we do not
+ create a TREE_VEC of TREE_VECs. Instead, we return a single
+ TREE_VEC containing the arguments. */
+ if (length > 1)
+ args = make_tree_vec (length);
+
+ for (header = current_template_parms; header; header = TREE_CHAIN (header))
{
tree a = copy_node (TREE_VALUE (header));
- int i = TREE_VEC_LENGTH (a);
+ int i;
+
TREE_TYPE (a) = NULL_TREE;
- while (i--)
+ for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
{
tree t = TREE_VEC_ELT (a, i);
- /* t will be a list if we are called from within a
+ /* 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)
@@ -1566,18 +1921,19 @@ current_template_args ()
t = TREE_TYPE (t);
else
t = DECL_INITIAL (t);
+ TREE_VEC_ELT (a, i) = t;
}
-
- TREE_VEC_ELT (a, i) = t;
}
- TREE_VEC_ELT (args, --l) = a;
- header = TREE_CHAIN (header);
+
+ if (length > 1)
+ TREE_VEC_ELT (args, --l) = a;
+ else
+ args = a;
}
return args;
}
-
/* Return a TEMPLATE_DECL corresponding to DECL, using the indicated
template PARMS. Used by push_template_decl below. */
@@ -1592,8 +1948,8 @@ build_template_decl (decl, parms)
if (DECL_LANG_SPECIFIC (decl))
{
DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl);
- DECL_STATIC_FUNCTION_P (tmpl) =
- DECL_STATIC_FUNCTION_P (decl);
+ DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
+ DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl);
}
return tmpl;
@@ -1601,8 +1957,23 @@ build_template_decl (decl, parms)
struct template_parm_data
{
+ /* The level of the template parameters we are currently
+ processing. */
int level;
+
+ /* The index of the specialization argument we are currently
+ processing. */
+ int current_arg;
+
+ /* An array whose size is the number of template parameters. The
+ elements are non-zero if the parameter has been used in any one
+ of the arguments processed so far. */
int* parms;
+
+ /* An array whose size is the number of template arguments. The
+ elements are non-zero if the argument makes use of template
+ parameters of this level. */
+ int* arg_uses_template_parms;
};
/* Subroutine of push_template_decl used to see if each template
@@ -1632,13 +2003,296 @@ mark_template_parm (t, data)
}
if (level == tpd->level)
- tpd->parms[idx] = 1;
+ {
+ tpd->parms[idx] = 1;
+ tpd->arg_uses_template_parms[tpd->current_arg] = 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;
}
+/* Process the partial specialization DECL. */
+
+static tree
+process_partial_specialization (decl)
+ tree decl;
+{
+ tree type = TREE_TYPE (decl);
+ tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
+ tree specargs = CLASSTYPE_TI_ARGS (type);
+ tree inner_args = innermost_args (specargs);
+ tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+ tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
+ int nargs = TREE_VEC_LENGTH (inner_args);
+ int ntparms = TREE_VEC_LENGTH (inner_parms);
+ int i;
+ int did_error_intro = 0;
+ struct template_parm_data tpd;
+ struct template_parm_data tpd2;
+
+ /* 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. */
+ tpd.level = TMPL_PARMS_DEPTH (current_template_parms);
+ tpd.parms = alloca (sizeof (int) * ntparms);
+ bzero ((PTR) tpd.parms, sizeof (int) * ntparms);
+
+ tpd.arg_uses_template_parms = alloca (sizeof (int) * nargs);
+ bzero ((PTR) tpd.arg_uses_template_parms, sizeof (int) * nargs);
+ for (i = 0; i < nargs; ++i)
+ {
+ tpd.current_arg = i;
+ for_each_template_parm (TREE_VEC_ELT (inner_args, 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 (inner_parms, i)));
+ }
+
+ /* [temp.class.spec]
+
+ The argument list of the specialization shall not be identical to
+ the implicit argument list of the primary template. */
+ if (comp_template_args (inner_args,
+ innermost_args (CLASSTYPE_TI_ARGS (TREE_TYPE
+ (maintmpl)))))
+ cp_error ("partial specialization `%T' does not specialize any template arguments", type);
+
+ /* [temp.class.spec]
+
+ A partially specialized non-type argument expression shall not
+ involve template parameters of the partial specialization except
+ when the argument expression is a simple identifier.
+
+ The type of a template parameter corresponding to a specialized
+ non-type argument shall not be dependent on a parameter of the
+ specialization. */
+ my_friendly_assert (nargs == DECL_NTPARMS (maintmpl), 0);
+ tpd2.parms = 0;
+ for (i = 0; i < nargs; ++i)
+ {
+ tree arg = TREE_VEC_ELT (inner_args, i);
+ if (/* These first two lines are the `non-type' bit. */
+ TREE_CODE_CLASS (TREE_CODE (arg)) != 't'
+ && TREE_CODE (arg) != TEMPLATE_DECL
+ /* This next line is the `argument expression is not just a
+ simple identifier' condition and also the `specialized
+ non-type argument' bit. */
+ && TREE_CODE (arg) != TEMPLATE_PARM_INDEX)
+ {
+ if (tpd.arg_uses_template_parms[i])
+ cp_error ("template argument `%E' involves template parameter(s)", arg);
+ else
+ {
+ /* Look at the corresponding template parameter,
+ marking which template parameters its type depends
+ upon. */
+ tree type =
+ TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (main_inner_parms,
+ i)));
+
+ if (!tpd2.parms)
+ {
+ /* We haven't yet initialized TPD2. Do so now. */
+ tpd2.arg_uses_template_parms
+ = (int*) alloca (sizeof (int) * nargs);
+ /* The number of parameters here is the number in the
+ main template, which, as checked in the assertion
+ above, is NARGS. */
+ tpd2.parms = (int*) alloca (sizeof (int) * nargs);
+ tpd2.level =
+ TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl));
+ }
+
+ /* Mark the template parameters. But this time, we're
+ looking for the template parameters of the main
+ template, not in the specialization. */
+ tpd2.current_arg = i;
+ tpd2.arg_uses_template_parms[i] = 0;
+ bzero ((PTR) tpd2.parms, sizeof (int) * nargs);
+ for_each_template_parm (type,
+ &mark_template_parm,
+ &tpd2);
+
+ if (tpd2.arg_uses_template_parms [i])
+ {
+ /* The type depended on some template parameters.
+ If they are fully specialized in the
+ specialization, that's OK. */
+ int j;
+ for (j = 0; j < nargs; ++j)
+ if (tpd2.parms[j] != 0
+ && tpd.arg_uses_template_parms [j])
+ {
+ cp_error ("type `%T' of template argument `%E' depends on template parameter(s)",
+ type,
+ arg);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (retrieve_specialization (maintmpl, specargs))
+ /* We've already got this specialization. */
+ return decl;
+
+ DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type)
+ = perm_tree_cons (inner_args, inner_parms,
+ DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
+ TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
+ return decl;
+}
+
+/* Check that a template declaration's use of default arguments is not
+ invalid. Here, PARMS are the template parameters. IS_PRIMARY is
+ non-zero if DECL is the thing declared by a primary template.
+ IS_PARTIAL is non-zero if DECL is a partial specialization. */
+
+static void
+check_default_tmpl_args (decl, parms, is_primary, is_partial)
+ tree decl;
+ tree parms;
+ int is_primary;
+ int is_partial;
+{
+ const char *msg;
+ int last_level_to_check;
+
+ /* [temp.param]
+
+ A default template-argument shall not be specified in a
+ function template declaration or a function template definition, nor
+ in the template-parameter-list of the definition of a member of a
+ class template. */
+
+ if (current_class_type
+ && !TYPE_BEING_DEFINED (current_class_type)
+ && DECL_LANG_SPECIFIC (decl)
+ /* If this is either a friend defined in the scope of the class
+ or a member function. */
+ && DECL_CLASS_CONTEXT (decl) == current_class_type
+ /* And, if it was a member function, it really was defined in
+ the scope of the class. */
+ && (!DECL_FUNCTION_MEMBER_P (decl) || DECL_DEFINED_IN_CLASS_P (decl)))
+ /* We already checked these parameters when the template was
+ declared, so there's no need to do it again now. This function
+ was defined in class scope, but we're processing it's body now
+ that the class is complete. */
+ return;
+
+ if (TREE_CODE (decl) != TYPE_DECL || is_partial || !is_primary)
+ /* For an ordinary class template, default template arguments are
+ allowed at the innermost level, e.g.:
+ template <class T = int>
+ struct S {};
+ but, in a partial specialization, they're not allowed even
+ there, as we have in [temp.class.spec]:
+
+ The template parameter list of a specialization shall not
+ contain default template argument values.
+
+ So, for a partial specialization, or for a function template,
+ we look at all of them. */
+ ;
+ else
+ /* But, for a primary class template that is not a partial
+ specialization we look at all template parameters except the
+ innermost ones. */
+ parms = TREE_CHAIN (parms);
+
+ /* Figure out what error message to issue. */
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ msg = "default argument for template parameter in function template `%D'";
+ else if (is_partial)
+ msg = "default argument in partial specialization `%D'";
+ else
+ msg = "default argument for template parameter for class enclosing `%D'";
+
+ if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
+ /* If we're inside a class definition, there's no need to
+ examine the parameters to the class itself. On the one
+ hand, they will be checked when the class is defined, and,
+ on the other, default arguments are legal in things like:
+ template <class T = double>
+ struct S { template <class U> void f(U); };
+ Here the default argument for `S' has no bearing on the
+ declaration of `f'. */
+ last_level_to_check = template_class_depth (current_class_type) + 1;
+ else
+ /* Check everything. */
+ last_level_to_check = 0;
+
+ for (; parms && TMPL_PARMS_DEPTH (parms) >= last_level_to_check;
+ parms = TREE_CHAIN (parms))
+ {
+ tree inner_parms = TREE_VALUE (parms);
+ int i, ntparms;
+
+ ntparms = TREE_VEC_LENGTH (inner_parms);
+ for (i = 0; i < ntparms; ++i)
+ if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
+ {
+ if (msg)
+ {
+ cp_error (msg, decl);
+ msg = 0;
+ }
+
+ /* Clear out the default argument so that we are not
+ confused later. */
+ TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
+ }
+
+ /* At this point, if we're still interested in issuing messages,
+ they must apply to classes surrounding the object declared. */
+ if (msg)
+ msg = "default argument for template parameter for class enclosing `%D'";
+ }
+}
+
/* 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
@@ -1656,6 +2310,12 @@ push_template_decl_real (decl, is_friend)
tree info;
tree ctx;
int primary;
+ int is_partial;
+
+ /* See if this is a partial specialization. */
+ is_partial = (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
+ && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));
is_friend |= (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl));
@@ -1682,12 +2342,11 @@ push_template_decl_real (decl, is_friend)
/* 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;
+ info = current_class_type;
else
info = ctx;
+ /* See if this is a primary template. */
if (info && TREE_CODE (info) == FUNCTION_DECL)
primary = 0;
/* Note that template_class_depth returns 0 if given NULL_TREE, so
@@ -1703,91 +2362,18 @@ push_template_decl_real (decl, is_friend)
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");
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+ cp_error ("template declaration of `%#T'", TREE_TYPE (decl));
}
- /* 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)));
- }
+ /* Check to see that the rules regarding the use of default
+ arguments are not being violated. */
+ check_default_tmpl_args (decl, current_template_parms,
+ primary, is_partial);
- for (; spec; spec = TREE_CHAIN (spec))
- {
- /* 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;
- }
+ if (is_partial)
+ return process_partial_specialization (decl);
args = current_template_args ();
@@ -1817,18 +2403,19 @@ push_template_decl_real (decl, is_friend)
}
else
{
- tree t;
- tree a;
+ tree a, t, current, parms;
+ int i;
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));
+ if ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
+ || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+ && TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
+ && TYPE_TI_TEMPLATE (TREE_TYPE (decl)))
+ tmpl = TYPE_TI_TEMPLATE (TREE_TYPE (decl));
else
{
cp_error ("`%D' does not declare a template type", decl);
@@ -1843,93 +2430,78 @@ push_template_decl_real (decl, is_friend)
else
tmpl = DECL_TI_TEMPLATE (decl);
- if (is_member_template (tmpl) || is_member_template_class (tmpl))
+ if (is_member_template (tmpl)
+ && DECL_FUNCTION_TEMPLATE_P (tmpl)
+ && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
+ && DECL_TEMPLATE_SPECIALIZATION (decl))
{
- 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;
+ 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;
}
- else
- a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
- t = NULL_TREE;
+ /* Make sure the template headers we got make sense. */
- if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
+ parms = DECL_TEMPLATE_PARMS (tmpl);
+ i = TMPL_PARMS_DEPTH (parms);
+ if (TMPL_ARGS_DEPTH (args) != i)
{
- /* 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));
+ cp_error ("expected %d levels of template parms for `%#D', got %d",
+ i, decl, TMPL_ARGS_DEPTH (args));
}
- else if (CLASSTYPE_TEMPLATE_INFO (ctx))
- t = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (ctx));
+ else
+ for (current = decl; i > 0; --i, parms = TREE_CHAIN (parms))
+ {
+ a = TMPL_ARGS_LEVEL (args, i);
+ t = INNERMOST_TEMPLATE_PARMS (parms);
- /* 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 (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
+ {
+ if (current == decl)
+ cp_error ("got %d template parameters for `%#D'",
+ TREE_VEC_LENGTH (a), decl);
+ else
+ cp_error ("got %d template parameters for `%#T'",
+ TREE_VEC_LENGTH (a), current);
+ cp_error (" but %d required", TREE_VEC_LENGTH (t));
+ }
- 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));
- }
+ /* Perhaps we should also check that the parms are used in the
+ appropriate qualifying scopes in the declarator? */
+
+ if (current == decl)
+ current = ctx;
+ else
+ current = TYPE_CONTEXT (current);
+ }
}
- /* 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. */
+ /* Push template declarations for global functions and types. 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. */
+ if (! ctx
+ && !(is_friend && template_class_depth (current_class_type) > 0))
tmpl = pushdecl_namespace_level (tmpl);
if (primary)
@@ -1939,8 +2511,9 @@ push_template_decl_real (decl, is_friend)
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
{
- CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info;
- if (!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
+ SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
+ if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
+ && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
}
else if (! DECL_LANG_SPECIFIC (decl))
@@ -1969,10 +2542,17 @@ redeclare_class_template (type, parms)
tree type;
tree parms;
{
- tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
+ tree tmpl;
tree tmpl_parms;
int i;
+ if (!TYPE_TEMPLATE_INFO (type))
+ {
+ cp_error ("`%T' is not a template type", type);
+ return;
+ }
+
+ tmpl = TYPE_TI_TEMPLATE (type);
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
@@ -2072,22 +2652,16 @@ convert_nontype_argument (type, expr)
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)
+ else if (TYPE_PTRMEM_P (expr_type)
+ || TYPE_PTRMEMFUNC_P (expr_type))
{
- if (! TREE_CONSTANT (expr))
- {
- non_constant:
- cp_error ("non-constant `%E' cannot be used as template argument",
- expr);
- return NULL_TREE;
- }
+ if (TREE_CODE (expr) != PTRMEM_CST)
+ goto bad_argument;
}
- else if (TYPE_PTR_P (expr_type)
+ else if (TYPE_PTR_P (expr_type)
+ || TYPE_PTRMEM_P (expr_type)
+ || TREE_CODE (expr_type) == ARRAY_TYPE
+ || TREE_CODE (type) == REFERENCE_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)
@@ -2096,21 +2670,33 @@ convert_nontype_argument (type, expr)
tree e = expr;
STRIP_NOPS (e);
- if (TREE_CODE (e) != ADDR_EXPR)
+ if (TREE_CODE (type) == REFERENCE_TYPE
+ || TREE_CODE (expr_type) == ARRAY_TYPE)
+ referent = e;
+ else
{
- 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;
+ if (TREE_CODE (e) != ADDR_EXPR)
+ {
+ bad_argument:
+ cp_error ("`%E' is not a valid template argument", expr);
+ if (TYPE_PTR_P (expr_type))
+ {
+ if (TREE_CODE (TREE_TYPE (expr_type)) == FUNCTION_TYPE)
+ cp_error ("it must be the address of a function with external linkage");
+ else
+ cp_error ("it must be the address of an object with external linkage");
+ }
+ else if (TYPE_PTRMEM_P (expr_type)
+ || TYPE_PTRMEMFUNC_P (expr_type))
+ cp_error ("it must be a pointer-to-member of the form `&X::Y'");
+
+ return NULL_TREE;
+ }
+
+ referent = TREE_OPERAND (e, 0);
+ STRIP_NOPS (referent);
}
- 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",
@@ -2130,10 +2716,20 @@ convert_nontype_argument (type, expr)
return error_mark_node;
}
}
- else if (TREE_CODE (expr) == VAR_DECL)
+ 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_PUBLIC (expr))
- goto bad_argument;
+ if (! TREE_CONSTANT (expr))
+ {
+ non_constant:
+ cp_error ("non-constant `%E' cannot be used as template argument",
+ expr);
+ return NULL_TREE;
+ }
}
else
{
@@ -2157,7 +2753,7 @@ convert_nontype_argument (type, expr)
expr = digest_init (type, expr, (tree*) 0);
if (TREE_CODE (expr) != INTEGER_CST)
- /* Curiously, some TREE_CONSTNAT integral expressions do not
+ /* Curiously, some TREE_CONSTANT integral expressions do not
simplify to integer constants. For example, `3 % 0',
remains a TRUNC_MOD_EXPR. */
goto non_constant;
@@ -2182,10 +2778,24 @@ convert_nontype_argument (type, expr)
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);
+ {
+ tree e;
+
+ /* For a non-type template-parameter of type pointer to data
+ member, qualification conversions (_conv.qual_) are
+ applied. */
+ e = perform_qualification_conversions (type, expr);
+ if (TREE_CODE (e) == NOP_EXPR)
+ /* The call to perform_qualification_conversions will
+ insert a NOP_EXPR over EXPR to do express conversion,
+ if necessary. But, that will confuse us if we use
+ this (converted) template parameter to instantiate
+ another template; then the thing will not look like a
+ valid template argument. So, just make a new
+ constant, of the appropriate type. */
+ e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr));
+ return e;
+ }
else if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE)
{
/* For a non-type template-parameter of type pointer to
@@ -2217,7 +2827,7 @@ convert_nontype_argument (type, expr)
expr = build_unary_op (ADDR_EXPR, fn, 0);
- my_friendly_assert (comptypes (type, TREE_TYPE (expr), 1),
+ my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
0);
return expr;
}
@@ -2252,15 +2862,18 @@ convert_nontype_argument (type, expr)
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_). */
+ 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 (fn == error_mark_node)
+ return error_mark_node;
+
if (!TREE_PUBLIC (fn))
{
if (really_overloaded_fn (fns))
@@ -2272,10 +2885,8 @@ convert_nontype_argument (type, expr)
goto bad_argument;
}
- if (fn == error_mark_node)
- return error_mark_node;
-
- my_friendly_assert (comptypes (type, TREE_TYPE (fn), 1),
+ my_friendly_assert (same_type_p (type_referred_to,
+ TREE_TYPE (fn)),
0);
return fn;
@@ -2288,12 +2899,10 @@ convert_nontype_argument (type, expr)
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))
+ if ((TYPE_MAIN_VARIANT (expr_type)
+ != TYPE_MAIN_VARIANT (type_referred_to))
+ || !at_least_as_qualified_p (type_referred_to,
+ expr_type)
|| !real_lvalue_p (expr))
return error_mark_node;
else
@@ -2304,9 +2913,6 @@ convert_nontype_argument (type, expr)
case RECORD_TYPE:
{
- tree fns;
- tree fn;
-
if (!TYPE_PTRMEMFUNC_P (type))
/* This handles templates like
template<class T, T t> void f();
@@ -2325,10 +2931,10 @@ convert_nontype_argument (type, expr)
expr_type != unknown_type_node)
return error_mark_node;
- if (TREE_CODE (expr) == CONSTRUCTOR)
+ if (TREE_CODE (expr) == PTRMEM_CST)
{
/* A ptr-to-member constant. */
- if (!comptypes (type, expr_type, 1))
+ if (!same_type_p (type, expr_type))
return error_mark_node;
else
return expr;
@@ -2337,17 +2943,12 @@ convert_nontype_argument (type, expr)
if (TREE_CODE (expr) != ADDR_EXPR)
return error_mark_node;
- fns = TREE_OPERAND (expr, 0);
+ expr = instantiate_type (type, expr, 0);
- fn = instantiate_type (TREE_TYPE (TREE_TYPE (type)),
- fns, 0);
-
- if (fn == error_mark_node)
+ if (expr == error_mark_node)
return error_mark_node;
- expr = build_unary_op (ADDR_EXPR, fn, 0);
-
- my_friendly_assert (comptypes (type, TREE_TYPE (expr), 1),
+ my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
0);
return expr;
}
@@ -2380,8 +2981,11 @@ convert_nontype_argument (type, expr)
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;
+coerce_template_template_parms (parm_parms, arg_parms, complain,
+ in_decl, outer_args)
+ tree parm_parms, arg_parms;
+ int complain;
+ tree in_decl, outer_args;
{
int nparms, nargs, i;
tree parm, arg;
@@ -2419,15 +3023,24 @@ coerce_template_template_parms (parm_parms, arg_parms, in_decl, outer_args)
/* We encounter instantiations of templates like
template <template <template <class> class> class TT>
class C; */
- sorry ("nested template template parameter");
- return 0;
+ {
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ if (!coerce_template_template_parms (parmparm, argparm,
+ complain, in_decl,
+ outer_args))
+ return 0;
+ }
+ break;
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))
+ if (!same_type_p (tsubst (TREE_TYPE (parm), outer_args,
+ complain, in_decl),
+ TREE_TYPE (arg)))
return 0;
break;
@@ -2438,36 +3051,229 @@ coerce_template_template_parms (parm_parms, arg_parms, in_decl, outer_args)
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, 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.
+/* Convert the indicated template ARG as necessary to match the
+ indicated template PARM. Returns the converted ARG, or
+ error_mark_node if the conversion was unsuccessful. Error messages
+ are issued if COMPLAIN is non-zero. This conversion is for the Ith
+ parameter in the parameter list. ARGS is the full set of template
+ arguments deduced so far. */
+
+static tree
+convert_template_argument (parm, arg, args, complain, i, in_decl)
+ tree parm;
+ tree arg;
+ tree args;
+ int complain;
+ int i;
+ tree in_decl;
+{
+ tree val;
+ tree inner_args;
+ int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
+
+ inner_args = innermost_args (args);
+
+ 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
+ && !TEMPLATE_TEMPLATE_PARM_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
+ && is_base_of_enclosing_class (arg, current_class_type)));
+ 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)
+ {
+ 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);
+ }
+ }
+ return error_mark_node;
+ }
+ if (is_tmpl_type ^ requires_tmpl_type)
+ {
+ if (in_decl && complain)
+ {
+ 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);
+ }
+ return error_mark_node;
+ }
+
+ if (is_type)
+ {
+ if (requires_tmpl_type)
+ {
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ if (coerce_template_template_parms (parmparm, argparm, complain,
+ in_decl, inner_args))
+ {
+ 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
+ {
+ 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)
+ {
+ /* [basic.link]: A name with no linkage (notably, the
+ name of a class or enumeration declared in a local
+ scope) shall not be used to declare an entity with
+ linkage. This implies that names with no linkage
+ cannot be used as template arguments. */
+ tree t = no_linkage_check (val);
+ if (t)
+ {
+ if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ cp_pedwarn
+ ("template-argument `%T' uses anonymous type", val);
+ else
+ cp_error
+ ("template-argument `%T' uses local type `%T'",
+ val, t);
+ return error_mark_node;
+ }
+ }
+ }
+ }
+ else
+ {
+ tree t = tsubst (TREE_TYPE (parm), args, complain, 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);
+ }
+
+ return val;
+}
+
+/* Convert all template arguments to their appropriate types, and
+ return a vector containing the innermost resulting template
+ arguments. If any error occurs, return 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. */
+ deduction for any unspecified trailing arguments.
+
+ The resulting TREE_VEC is allocated on a temporary obstack, and
+ must be explicitly copied if it will be permanent. */
static tree
-coerce_template_parms (parms, arglist, in_decl,
+coerce_template_parms (parms, args, in_decl,
complain,
require_all_arguments)
- tree parms, arglist;
+ tree parms, args;
tree in_decl;
int complain;
int require_all_arguments;
{
int nparms, nargs, i, lost = 0;
- tree vec = NULL_TREE;
-
- if (arglist == NULL_TREE)
- nargs = 0;
- else if (TREE_CODE (arglist) == TREE_VEC)
- nargs = TREE_VEC_LENGTH (arglist);
- else
- nargs = list_length (arglist);
+ tree inner_args;
+ tree new_args;
+ tree new_inner_args;
+ inner_args = innermost_args (args);
+ nargs = NUM_TMPL_ARGS (inner_args);
nparms = TREE_VEC_LENGTH (parms);
if (nargs > nparms
@@ -2477,253 +3283,96 @@ coerce_template_parms (parms, arglist, in_decl,
{
if (complain)
{
- error ("incorrect number of parameters (%d, should be %d)",
- nargs, nparms);
+ cp_error ("wrong number of template arguments (%d, should be %d)",
+ nargs, nparms);
if (in_decl)
- cp_error_at ("in template expansion for decl `%D'",
- in_decl);
+ cp_error_at ("provided for `%D'", in_decl);
}
return error_mark_node;
}
- if (arglist && TREE_CODE (arglist) == TREE_VEC && nargs == nparms)
- vec = copy_node (arglist);
- else
+ new_inner_args = make_temp_vec (nparms);
+ new_args = add_outermost_template_args (args, new_inner_args);
+ for (i = 0; i < nparms; i++)
{
- vec = make_tree_vec (nparms);
-
- for (i = 0; i < nparms; i++)
- {
- tree arg;
- tree parm = TREE_VEC_ELT (parms, i);
+ tree arg;
+ tree parm;
- if (arglist && TREE_CODE (arglist) == TREE_LIST)
- {
- arg = arglist;
- arglist = TREE_CHAIN (arglist);
-
- if (arg == error_mark_node)
- lost++;
- 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 = tsubst_expr (TREE_PURPOSE (parm), vec, in_decl);
+ /* Get the Ith template parameter. */
+ parm = TREE_VEC_ELT (parms, i);
- TREE_VEC_ELT (vec, i) = arg;
+ /* Calculate the Ith argument. */
+ if (inner_args && TREE_CODE (inner_args) == TREE_LIST)
+ {
+ arg = TREE_VALUE (inner_args);
+ inner_args = TREE_CHAIN (inner_args);
}
- }
- for (i = 0; i < nparms; i++)
- {
- tree arg = TREE_VEC_ELT (vec, i);
- tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
- tree val = 0;
- int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
+ else if (i < nargs)
+ arg = TREE_VEC_ELT (inner_args, i);
+ /* If no template argument was supplied, look for a default
+ value. */
+ else if (TREE_PURPOSE (parm) == NULL_TREE)
+ {
+ /* There was no default value. */
+ my_friendly_assert (!require_all_arguments, 0);
+ break;
+ }
+ else if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
+ arg = tsubst (TREE_PURPOSE (parm), new_args, complain, in_decl);
+ else
+ arg = tsubst_expr (TREE_PURPOSE (parm), new_args, complain,
+ in_decl);
+ /* Now, convert the Ith argument, as necessary. */
if (arg == NULL_TREE)
/* We're out of arguments. */
{
my_friendly_assert (!require_all_arguments, 0);
break;
}
-
- if (arg == error_mark_node)
+ else 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)
- {
- 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_tmpl_type ^ requires_tmpl_type)
- {
- if (in_decl && complain)
- {
- 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);
- }
- lost++;
- TREE_VEC_ELT (vec, i) = error_mark_node;
- continue;
- }
-
- if (is_type)
- {
- if (requires_tmpl_type)
- {
- tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
- tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
-
- if (coerce_template_template_parms (parmparm, argparm,
- in_decl, vec))
- {
- 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
- {
- 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);
+ arg = error_mark_node;
}
-
- if (val == error_mark_node)
+ else
+ arg = convert_template_argument (TREE_VALUE (parm),
+ arg, new_args, complain, i,
+ in_decl);
+
+ if (arg == error_mark_node)
lost++;
-
- TREE_VEC_ELT (vec, i) = val;
+ TREE_VEC_ELT (new_inner_args, i) = arg;
}
+
if (lost)
return error_mark_node;
- return vec;
+
+ return new_inner_args;
+}
+
+/* Returns 1 if template args OT and NT are equivalent. */
+
+static int
+template_args_equal (ot, nt)
+ tree ot, nt;
+{
+ if (nt == ot)
+ return 1;
+ if (TREE_CODE (nt) != TREE_CODE (ot))
+ return 0;
+ if (TREE_CODE (nt) == TREE_VEC)
+ /* For member templates */
+ return comp_template_args (ot, nt);
+ else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
+ return same_type_p (ot, nt);
+ else
+ return (cp_tree_equal (ot, nt) > 0);
}
-/* Renturns 1 iff the OLDARGS and NEWARGS are in fact identical sets
+/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets
of template arguments. Returns 0 otherwise. */
int
@@ -2740,24 +3389,8 @@ comp_template_args (oldargs, newargs)
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))
+ if (! template_args_equal (ot, nt))
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;
}
@@ -2766,10 +3399,9 @@ comp_template_args (oldargs, newargs)
for the instantiation. */
static char *
-mangle_class_name_for_template (name, parms, arglist, ctx)
+mangle_class_name_for_template (name, parms, arglist)
char *name;
tree parms, arglist;
- tree ctx;
{
static struct obstack scratch_obstack;
static char *scratch_firstobj;
@@ -2781,37 +3413,13 @@ mangle_class_name_for_template (name, parms, arglist, ctx)
obstack_free (&scratch_obstack, scratch_firstobj);
scratch_firstobj = obstack_alloc (&scratch_obstack, 1);
-#if 0
-#define buflen sizeof(buf)
-#define check if (bufp >= buf+buflen-1) goto too_long
-#define ccat(c) *bufp++=(c); check
-#define advance bufp+=strlen(bufp); check
-#define cat(s) strncpy(bufp, s, buf+buflen-bufp-1); advance
-#else
-#define check
#define ccat(c) obstack_1grow (&scratch_obstack, (c));
-#define advance
#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);
+ arglist = innermost_args (arglist);
my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
for (i = 0; i < nparms; i++)
{
@@ -2874,13 +3482,6 @@ mangle_class_name_for_template (name, parms, arglist, ctx)
ccat ('>');
ccat ('\0');
return (char *) obstack_base (&scratch_obstack);
-
-#if 0
- too_long:
-#endif
- fatal ("out of (preallocated) string space creating template instantiation name");
- /* NOTREACHED */
- return NULL;
}
static tree
@@ -2888,28 +3489,28 @@ 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;
+ /* Specializations have already had their names set up in
+ lookup_template_class. */
+ && !CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
+ {
+ tree tmpl = most_general_template (CLASSTYPE_TI_TEMPLATE (t));
+
+ /* For non-primary templates, the template parameters are
+ implicit from their surrounding context. */
+ if (PRIMARY_TEMPLATE_P (tmpl))
+ {
+ tree name = DECL_NAME (tmpl);
+ char *mangled_name = mangle_class_name_for_template
+ (IDENTIFIER_POINTER (name),
+ DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
+ CLASSTYPE_TI_ARGS (t));
+ tree id = get_identifier (mangled_name);
+ IDENTIFIER_TEMPLATE (id) = name;
+ return id;
+ }
}
- else
- return TYPE_IDENTIFIER (t);
+
+ return TYPE_IDENTIFIER (t);
}
static void
@@ -2949,14 +3550,14 @@ lookup_template_function (fns, arglist)
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);
+ if (processing_template_decl)
+ return build_min (TEMPLATE_ID_EXPR, type, fns, arglist);
+ else
+ return build (TEMPLATE_ID_EXPR, type, fns, arglist);
}
/* Within the scope of a template class S<T>, the name S gets bound
@@ -2966,13 +3567,14 @@ lookup_template_function (fns, arglist)
return the associated TEMPLATE_DECL. Otherwise, the original
DECL is returned. */
-tree
+static tree
maybe_get_template_decl_from_type_decl (decl)
tree decl;
{
return (decl != NULL_TREE
&& TREE_CODE (decl) == TYPE_DECL
&& DECL_ARTIFICIAL (decl)
+ && CLASS_TYPE_P (TREE_TYPE (decl))
&& CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl;
}
@@ -2981,37 +3583,43 @@ maybe_get_template_decl_from_type_decl (decl)
parameters, find the desired type.
D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
- Since ARGLIST is build on the decl_obstack, we must copy it here
- to keep it from being reclaimed when the decl storage is reclaimed.
+ (Actually ARGLIST may be either a TREE_LIST or a TREE_VEC. It will
+ be a TREE_LIST if called directly from the parser, and a TREE_VEC
+ otherwise.) Since ARGLIST is build on the decl_obstack, we must
+ copy it here 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.
+ If ENTERING_SCOPE is non-zero, we are about to enter the scope of
+ the class we are looking up.
+
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, context)
+lookup_template_class (d1, arglist, in_decl, context, entering_scope)
tree d1, arglist;
tree in_decl;
tree context;
+ int entering_scope;
{
tree template = NULL_TREE, parmlist;
- char *mangled_name;
- tree id, t;
+ tree 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);
+ if (IDENTIFIER_VALUE (d1)
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_VALUE (d1)))
+ template = IDENTIFIER_VALUE (d1);
else
{
if (context)
push_decl_namespace (context);
if (current_class_type != NULL_TREE)
- template =
+ template =
maybe_get_template_decl_from_type_decl
(IDENTIFIER_CLASS_VALUE (d1));
if (template == NULL_TREE)
@@ -3024,14 +3632,24 @@ lookup_template_class (d1, arglist, in_decl, context)
}
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);
+ tree type = TREE_TYPE (d1);
+
+ /* If we are declaring a constructor, say A<T>::A<T>, we will get
+ an implicit typename for the second A. Deal with it. */
+ if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
+ type = TREE_TYPE (type);
+
+ if (CLASSTYPE_TEMPLATE_INFO (type))
+ {
+ template = CLASSTYPE_TI_TEMPLATE (type);
+ d1 = DECL_NAME (template);
+ }
}
- else if (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' && IS_AGGR_TYPE (d1))
+ else if (TREE_CODE (d1) == ENUMERAL_TYPE
+ || (TREE_CODE_CLASS (TREE_CODE (d1)) == 't'
+ && IS_AGGR_TYPE (d1)))
{
- template = CLASSTYPE_TI_TEMPLATE (d1);
+ template = TYPE_TI_TEMPLATE (d1);
d1 = DECL_NAME (template);
}
else if (TREE_CODE (d1) == TEMPLATE_DECL
@@ -3045,11 +3663,15 @@ lookup_template_class (d1, arglist, in_decl, context)
my_friendly_abort (272);
/* 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. */
+ we could end up with D1 having nothing but an IDENTIFIER_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;
+ {
+ cp_error ("`%T' is not a template", d1);
+ return error_mark_node;
+ }
if (context == NULL_TREE)
context = global_namespace;
@@ -3071,7 +3693,6 @@ lookup_template_class (d1, arglist, in_decl, context)
tree template2 = TYPE_STUB_DECL (parm);
tree arglist2;
- CLASSTYPE_GOT_SEMICOLON (parm) = 1;
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
arglist2 = coerce_template_parms (parmlist, arglist, template, 1, 1);
@@ -3079,166 +3700,307 @@ lookup_template_class (d1, arglist, in_decl, context)
return error_mark_node;
arglist2 = copy_to_permanent (arglist2);
- CLASSTYPE_TEMPLATE_INFO (parm)
+ TEMPLATE_TEMPLATE_PARM_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))
+ else
{
- tree arglist_for_mangling;
+ tree template_type = TREE_TYPE (template);
+ tree gen_tmpl;
+ tree type_decl;
+ tree found = NULL_TREE;
+ int arg_depth;
+ int parm_depth;
+ int is_partial_instantiation;
- parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
+ gen_tmpl = most_general_template (template);
+ parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
+ parm_depth = TMPL_PARMS_DEPTH (parmlist);
+ arg_depth = TMPL_ARGS_DEPTH (arglist);
- 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)
+ /* We build up the coerced arguments and such on the
+ momentary_obstack. */
+ push_momentary ();
+
+ if (arg_depth == 1 && parm_depth > 1)
+ {
+ /* We've been given an incomplete set of template arguments.
+ For example, given:
+
+ template <class T> struct S1 {
+ template <class U> struct S2 {};
+ template <class U> struct S2<U*> {};
+ };
+
+ we will be called with an ARGLIST of `U*', but the
+ TEMPLATE will be `template <class T> template
+ <class U> struct S1<T>::S2'. We must fill in the missing
+ arguments. */
+ arglist
+ = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (template)),
+ arglist);
+ arg_depth = TMPL_ARGS_DEPTH (arglist);
+ }
+
+ /* Now we should enough arguments. */
+ my_friendly_assert (parm_depth == arg_depth, 0);
+
+ /* From here on, we're only interested in the most general
+ template. */
+ template = gen_tmpl;
+
+ /* Calculate the BOUND_ARGS. These will be the args that are
+ actually tsubst'd into the definition to create the
+ instantiation. */
+ if (parm_depth > 1)
{
/* We have multiple levels of arguments to coerce, at once. */
- tree new_args =
- make_tree_vec (list_length (DECL_TEMPLATE_PARMS (template)));
int i;
+ int saved_depth = TMPL_ARGS_DEPTH (arglist);
+
+ tree bound_args = make_temp_vec (parm_depth);
- for (i = TREE_VEC_LENGTH (arglist) - 1,
+ for (i = saved_depth,
t = DECL_TEMPLATE_PARMS (template);
- i >= 0 && t != NULL_TREE;
+ 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;
+ {
+ tree a = coerce_template_parms (TREE_VALUE (t),
+ arglist, template, 1, 1);
+ SET_TMPL_ARGS_LEVEL (bound_args, i, a);
+
+ /* We temporarily reduce the length of the ARGLIST so
+ that coerce_template_parms will see only the arguments
+ corresponding to the template parameters it is
+ examining. */
+ TREE_VEC_LENGTH (arglist)--;
+ }
+
+ /* Restore the ARGLIST to its full size. */
+ TREE_VEC_LENGTH (arglist) = saved_depth;
+
+ arglist = bound_args;
}
else
- arglist = coerce_template_parms (parmlist,
- innermost_args (arglist, 0),
- template, 1, 1);
- if (arglist == error_mark_node)
+ arglist
+ = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
+ innermost_args (arglist),
+ template, 1, 1);
+
+ if (arglist == error_mark_node)
+ /* We were unable to bind the arguments. */
return error_mark_node;
- if (uses_template_parms (arglist))
+
+ /* In the scope of a template class, explicit references to the
+ template class refer to the type of the template, not any
+ instantiation of it. For example, in:
+
+ template <class T> class C { void f(C<T>); }
+
+ the `C<T>' is just the same as `C'. Outside of the
+ class, however, such a reference is an instantiation. */
+ if (comp_template_args (TYPE_TI_ARGS (template_type),
+ arglist))
{
- tree found;
- if (comp_template_args
- (CLASSTYPE_TI_ARGS (TREE_TYPE (template)), arglist))
- found = TREE_TYPE (template);
- else
+ found = template_type;
+
+ if (!entering_scope && PRIMARY_TEMPLATE_P (template))
{
- 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);
+ tree ctx;
+
+ /* Note that we use DECL_CONTEXT, rather than
+ CP_DECL_CONTEXT, so that the termination test is
+ always just `ctx'. We're not interested in namepace
+ scopes. */
+ for (ctx = current_class_type;
+ ctx;
+ ctx = (TREE_CODE_CLASS (TREE_CODE (ctx)) == 't')
+ ? TYPE_CONTEXT (ctx) : DECL_CONTEXT (ctx))
+ if (same_type_p (ctx, template_type))
+ break;
+
+ if (!ctx)
+ /* We're not in the scope of the class, so the
+ TEMPLATE_TYPE is not the type we want after
+ all. */
+ found = NULL_TREE;
}
+ }
+
+ if (!found)
+ {
+ for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+ found; found = TREE_CHAIN (found))
+ if (comp_template_args (TREE_PURPOSE (found), arglist))
+ break;
if (found)
- {
- if (can_free (&permanent_obstack, arglist))
- obstack_free (&permanent_obstack, arglist);
- return found;
- }
+ found = TREE_VALUE (found);
+ }
+
+ if (found)
+ {
+ pop_momentary ();
+ return found;
}
- if (TREE_CODE (arglist) == TREE_VEC)
- arglist_for_mangling = innermost_args (arglist, 0);
+ /* Since we didn't find the type, we'll have to create it.
+ Since we'll be saving this type on the
+ DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent. */
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+
+ /* This type is a "partial instantiation" if any of the template
+ arguments still inolve template parameters. Note that we set
+ IS_PARTIAL_INSTANTIATION for partial specializations as
+ well. */
+ is_partial_instantiation = uses_template_parms (arglist);
+
+ /* Create the type. */
+ if (TREE_CODE (template_type) == ENUMERAL_TYPE)
+ {
+ if (!is_partial_instantiation)
+ t = start_enum (TYPE_IDENTIFIER (template_type));
+ else
+ /* We don't want to call start_enum for this type, since
+ the values for the enumeration constants may involve
+ template parameters. And, no one should be interested
+ in the enumeration constants for such a type. */
+ t = make_node (ENUMERAL_TYPE);
+ }
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 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));
+ t = make_lang_type (TREE_CODE (template_type));
+ CLASSTYPE_DECLARED_CLASS (t)
+ = CLASSTYPE_DECLARED_CLASS (template_type);
+ CLASSTYPE_GOT_SEMICOLON (t) = 1;
+ SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
+ TYPE_FOR_JAVA (t) = TYPE_FOR_JAVA (template_type);
}
- 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)
+ /* If we called start_enum above, this information will already
+ be set up. */
+ if (!TYPE_NAME (t))
{
- 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;
+ TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+
+ /* Create a stub TYPE_DECL for it. */
+ type_decl = build_decl (TYPE_DECL, DECL_NAME (template), t);
+ SET_DECL_ARTIFICIAL (type_decl);
+ DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
+ DECL_SOURCE_FILE (type_decl)
+ = DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
+ DECL_SOURCE_LINE (type_decl)
+ = DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
+ TYPE_STUB_DECL (t) = TYPE_NAME (t) = type_decl;
}
else
+ type_decl = TYPE_NAME (t);
+
+ /* Set up the template information. We have to figure out which
+ template is the immediate parent if this is a full
+ instantiation. */
+ if (parm_depth == 1 || is_partial_instantiation
+ || !PRIMARY_TEMPLATE_P (template))
+ /* This case is easy; there are no member templates involved. */
+ found = template;
+ else
{
- t = lookup_nested_type_by_name (ctx, id);
- my_friendly_assert (t != NULL_TREE, 42);
- }
- }
+ /* This is a full instantiation of a member template. There
+ should be some partial instantiation of which this is an
+ instance. */
- /* Seems to be wanted. */
- CLASSTYPE_GOT_SEMICOLON (t) = 1;
+ for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+ found; found = TREE_CHAIN (found))
+ {
+ int success;
+ tree tmpl = CLASSTYPE_TI_TEMPLATE (TREE_VALUE (found));
+
+ /* We only want partial instantiations, here, not
+ specializations or full instantiations. */
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_VALUE (found))
+ || !uses_template_parms (TREE_VALUE (found)))
+ continue;
+
+ /* Temporarily reduce by one the number of levels in the
+ ARGLIST and in FOUND so as to avoid comparing the
+ last set of arguments. */
+ TREE_VEC_LENGTH (arglist)--;
+ TREE_VEC_LENGTH (TREE_PURPOSE (found)) --;
+
+ /* See if the arguments match. If they do, then TMPL is
+ the partial instantiation we want. */
+ success = comp_template_args (TREE_PURPOSE (found), arglist);
+
+ /* Restore the argument vectors to their full size. */
+ TREE_VEC_LENGTH (arglist)++;
+ TREE_VEC_LENGTH (TREE_PURPOSE (found))++;
+
+ if (success)
+ {
+ found = tmpl;
+ break;
+ }
+ }
+
+ if (!found)
+ my_friendly_abort (0);
+ }
- 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))
+ SET_TYPE_TEMPLATE_INFO (t,
+ tree_cons (found, arglist, NULL_TREE));
+ DECL_TEMPLATE_INSTANTIATIONS (template)
+ = tree_cons (arglist, t,
+ DECL_TEMPLATE_INSTANTIATIONS (template));
+
+ if (TREE_CODE (t) == ENUMERAL_TYPE
+ && !is_partial_instantiation)
+ /* Now that the type has been registered on the instantiations
+ list, we set up the enumerators. Because the enumeration
+ constants may involve the enumeration type itself, we make
+ sure to register the type first, and then create the
+ constants. That way, doing tsubst_expr for the enumeration
+ constants won't result in recursive calls here; we'll find
+ the instantiation and exit above. */
+ tsubst_enum (template_type, t, arglist);
+
+ /* We're done with the permanent obstack, now. */
+ pop_obstacks ();
+ /* We're also done with the momentary allocation we started
+ above. */
+ pop_momentary ();
+
+ /* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO
+ is set up. */
+ if (TREE_CODE (t) != ENUMERAL_TYPE)
+ DECL_NAME (type_decl) = classtype_mangled_name (t);
+ DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
+ if (!is_partial_instantiation)
+ {
+ DECL_ASSEMBLER_NAME (type_decl)
+ = get_identifier (build_overload_name (t, 1, 1));
+
+ /* For backwards compatibility; code that uses
+ -fexternal-templates expects looking up a template to
+ instantiate it. I think DDD still relies on this.
+ (jason 8/20/1998) */
+ if (TREE_CODE (t) != ENUMERAL_TYPE
+ && flag_external_templates
+ && CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template))
+ && ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template)))
+ add_pending_template (t);
+ }
+ else
/* 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;
+ 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
@@ -3247,7 +4009,7 @@ extern int yychar;
returned by for_each_template_parm is 0. If FN is NULL, it is
considered to be the function which always returns 1. */
-int
+static int
for_each_template_parm (t, fn, data)
tree t;
tree_fn_t fn;
@@ -3269,6 +4031,11 @@ for_each_template_parm (t, fn, data)
COMPONENT_REF uses template parms. */
return for_each_template_parm (TREE_TYPE (t), fn, data);
+ case ARRAY_REF:
+ case OFFSET_REF:
+ return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data)
+ || for_each_template_parm (TREE_OPERAND (t, 1), fn, data));
+
case IDENTIFIER_NODE:
if (!IDENTIFIER_TEMPLATE (t))
return 0;
@@ -3298,20 +4065,43 @@ for_each_template_parm (t, fn, data)
case POINTER_TYPE:
case REFERENCE_TYPE:
return for_each_template_parm (TREE_TYPE (t), fn, data);
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (t))
return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE (t),
fn, data);
+ /* Fall through. */
+
case UNION_TYPE:
- if (! CLASSTYPE_TEMPLATE_INFO (t))
+ case ENUMERAL_TYPE:
+ if (! TYPE_TEMPLATE_INFO (t))
return 0;
return for_each_template_parm (TREE_VALUE
- (CLASSTYPE_TEMPLATE_INFO (t)),
+ (TYPE_TEMPLATE_INFO (t)),
fn, data);
- case FUNCTION_TYPE:
- if (for_each_template_parm (TYPE_ARG_TYPES (t), fn, data))
+ case METHOD_TYPE:
+ if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data))
return 1;
+ /* Fall through. */
+
+ case FUNCTION_TYPE:
+ /* Check the parameter types. Since default arguments are not
+ instantiated until they are needed, the TYPE_ARG_TYPES may
+ contain expressions that involve template parameters. But,
+ no-one should be looking at them yet. And, once they're
+ instantiated, they don't contain template parameters, so
+ there's no point in looking at them then, either. */
+ {
+ tree parm;
+
+ for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm))
+ if (for_each_template_parm (TREE_VALUE (parm), fn, data))
+ return 1;
+ }
+
+ /* Check the return type, too. */
return for_each_template_parm (TREE_TYPE (t), fn, data);
+
case ARRAY_TYPE:
if (for_each_template_parm (TYPE_DOMAIN (t), fn, data))
return 1;
@@ -3320,12 +4110,6 @@ for_each_template_parm (t, fn, data)
if (for_each_template_parm (TYPE_OFFSET_BASETYPE (t), fn, data))
return 1;
return for_each_template_parm (TREE_TYPE (t), fn, data);
- case METHOD_TYPE:
- if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data))
- return 1;
- if (for_each_template_parm (TYPE_ARG_TYPES (t), fn, data))
- return 1;
- return for_each_template_parm (TREE_TYPE (t), fn, data);
/* decl nodes */
case TYPE_DECL:
@@ -3360,15 +4144,17 @@ for_each_template_parm (t, fn, data)
return 0;
case CALL_EXPR:
- return for_each_template_parm (TREE_TYPE (t), fn, data);
+ return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data)
+ || for_each_template_parm (TREE_OPERAND (t, 1), fn, data));
+
case ADDR_EXPR:
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))
+ if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t)
+ && for_each_template_parm (TYPE_TI_ARGS (t), fn, data))
return 1;
case TEMPLATE_TYPE_PARM:
case TEMPLATE_PARM_INDEX:
@@ -3390,16 +4176,6 @@ for_each_template_parm (t, fn, data)
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 */
case INTEGER_CST:
case REAL_CST:
@@ -3416,6 +4192,9 @@ for_each_template_parm (t, fn, data)
case TYPENAME_TYPE:
return 1;
+ case PTRMEM_CST:
+ return for_each_template_parm (TREE_TYPE (t), fn, data);
+
case SCOPE_REF:
return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
@@ -3494,25 +4273,28 @@ print_template_context (err)
int line = lineno;
char *file = input_filename;
- if (err)
+ if (err && p)
{
- 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));
+ if (current_function_decl != p->decl
+ && current_function_decl != NULL_TREE)
+ /* We can get here during the processing of some synthesized
+ method. Then, p->decl will be the function that's causing
+ the synthesis. */
+ ;
else
- my_friendly_abort (980521);
-
- if (p)
{
+ if (current_function_decl == p->decl)
+ /* Avoid redundancy with the the "In function" line. */;
+ else
+ fprintf (stderr, "%s: In instantiation of `%s':\n",
+ file, decl_as_string (p->decl, 0));
+
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,
@@ -3590,6 +4372,12 @@ pop_tinst_level ()
{
struct tinst_level *old = current_tinst_level;
+ /* Restore the filename and line number stashed away when we started
+ this instantiation. */
+ lineno = old->line;
+ input_filename = old->file;
+ extract_interface_info ();
+
current_tinst_level = old->next;
old->next = free_tinst_level;
free_tinst_level = old;
@@ -3640,32 +4428,27 @@ tsubst_friend_function (decl, args)
tree template_id;
tree new_args;
tree tmpl;
- tree tinfo;
template_id
= lookup_template_function (tsubst_expr (DECL_TI_TEMPLATE (decl),
- args, NULL_TREE),
+ args, /*complain=*/1,
+ 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);
+ args, /*complain=*/1,
+ NULL_TREE));
+ /* FIXME: The decl we create via the next tsubst could be
+ created on a temporary obstack. */
+ new_friend = tsubst (decl, args, /*complain=*/1, NULL_TREE);
+ tmpl = determine_specialization (template_id, new_friend,
+ &new_args,
+ /*need_member_template=*/0);
new_friend = instantiate_template (tmpl, new_args);
goto done;
}
- else
- new_friend = tsubst (decl, args, NULL_TREE);
+
+ new_friend = tsubst (decl, args, /*complain=*/1, NULL_TREE);
- /* The new_friend will look like an instantiation, to the
+ /* 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:
@@ -3678,15 +4461,143 @@ tsubst_friend_function (decl, args)
DECL_USE_TEMPLATE (new_friend) = 0;
if (TREE_CODE (decl) == TEMPLATE_DECL)
DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
-
+
+ /* The mangled name for the NEW_FRIEND is incorrect. The call to
+ tsubst will have resulted in a call to
+ set_mangled_name_for_template_decl. But, the function is not a
+ template instantiation and should not be mangled like one.
+ Therefore, we remangle the function name. We don't have to do
+ this if the NEW_FRIEND is a template since
+ set_mangled_name_for_template_decl doesn't do anything if the
+ function declaration still uses template arguments. */
+ if (TREE_CODE (new_friend) != TEMPLATE_DECL)
+ {
+ set_mangled_name_for_decl (new_friend);
+ DECL_RTL (new_friend) = 0;
+ make_decl_rtl (new_friend, NULL_PTR, 1);
+ }
+
if (DECL_NAMESPACE_SCOPE_P (new_friend))
{
+ tree old_decl;
+ tree new_friend_template_info;
+ tree new_friend_result_template_info;
+ int new_friend_is_defn;
+
+ /* We must save some information from NEW_FRIEND before calling
+ duplicate decls since that function will free NEW_FRIEND if
+ possible. */
+ new_friend_template_info = DECL_TEMPLATE_INFO (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;
+ {
+ /* This declaration is a `primary' template. */
+ DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
+
+ new_friend_is_defn
+ = DECL_INITIAL (DECL_RESULT (new_friend)) != NULL_TREE;
+ new_friend_result_template_info
+ = DECL_TEMPLATE_INFO (DECL_RESULT (new_friend));
+ }
+ else
+ {
+ new_friend_is_defn = DECL_INITIAL (new_friend) != NULL_TREE;
+ new_friend_result_template_info = NULL_TREE;
+ }
+
+ old_decl = pushdecl_namespace_level (new_friend);
- new_friend = pushdecl_namespace_level (new_friend);
+ if (old_decl != new_friend)
+ {
+ /* This new friend declaration matched an existing
+ declaration. For example, given:
+
+ template <class T> void f(T);
+ template <class U> class C {
+ template <class T> friend void f(T) {}
+ };
+
+ the friend declaration actually provides the definition
+ of `f', once C has been instantiated for some type. So,
+ old_decl will be the out-of-class template declaration,
+ while new_friend is the in-class definition.
+
+ But, if `f' was called before this point, the
+ instantiation of `f' will have DECL_TI_ARGS corresponding
+ to `T' but not to `U', references to which might appear
+ in the definition of `f'. Previously, the most general
+ template for an instantiation of `f' was the out-of-class
+ version; now it is the in-class version. Therefore, we
+ run through all specialization of `f', adding to their
+ DECL_TI_ARGS appropriately. In particular, they need a
+ new set of outer arguments, corresponding to the
+ arguments for this class instantiation.
+
+ The same situation can arise with something like this:
+
+ friend void f(int);
+ template <class T> class C {
+ friend void f(T) {}
+ };
+
+ when `C<int>' is instantiated. Now, `f(int)' is defined
+ in the class. */
+
+ if (!new_friend_is_defn)
+ /* On the other hand, if the in-class declaration does
+ *not* provide a definition, then we don't want to alter
+ existing definitions. We can just leave everything
+ alone. */
+ ;
+ else
+ {
+ /* Overwrite whatever template info was there before, if
+ any, with the new template information pertaining to
+ the declaration. */
+ DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
+
+ if (TREE_CODE (old_decl) != TEMPLATE_DECL)
+ /* duplicate_decls will take care of this case. */
+ ;
+ else
+ {
+ tree t;
+ tree new_friend_args;
+
+ DECL_TEMPLATE_INFO (DECL_RESULT (old_decl))
+ = new_friend_result_template_info;
+
+ new_friend_args = TI_ARGS (new_friend_template_info);
+ for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl);
+ t != NULL_TREE;
+ t = TREE_CHAIN (t))
+ {
+ tree spec = TREE_VALUE (t);
+
+ DECL_TI_ARGS (spec)
+ = add_outermost_template_args (new_friend_args,
+ DECL_TI_ARGS (spec));
+ DECL_TI_ARGS (spec)
+ = copy_to_permanent (DECL_TI_ARGS (spec));
+ }
+
+ /* Now, since specializations are always supposed to
+ hang off of the most general template, we must move
+ them. */
+ t = most_general_template (old_decl);
+ if (t != old_decl)
+ {
+ DECL_TEMPLATE_SPECIALIZATIONS (t)
+ = chainon (DECL_TEMPLATE_SPECIALIZATIONS (t),
+ DECL_TEMPLATE_SPECIALIZATIONS (old_decl));
+ DECL_TEMPLATE_SPECIALIZATIONS (old_decl) = NULL_TREE;
+ }
+ }
+ }
+
+ /* The information from NEW_FRIEND has been merged into OLD_DECL
+ by duplicate_decls. */
+ new_friend = old_decl;
+ }
}
else if (TYPE_SIZE (DECL_CONTEXT (new_friend)))
{
@@ -3716,16 +4627,40 @@ tsubst_friend_class (friend_tmpl, args)
tree args;
{
tree friend_type;
- tree tmpl = lookup_name (DECL_NAME (friend_tmpl), 1);
+ tree tmpl;
- tmpl = maybe_get_template_decl_from_type_decl (tmpl);
+ /* First, we look for a class template. */
+ tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/0);
+
+ /* But, if we don't find one, it might be because we're in a
+ situation like this:
- if (tmpl != NULL_TREE && DECL_CLASS_TEMPLATE_P (tmpl))
+ template <class T>
+ struct S {
+ template <class U>
+ friend struct S;
+ };
+
+ Here, in the scope of (say) S<int>, `S' is bound to a TYPE_DECL
+ for `S<int>', not the TEMPLATE_DECL. */
+ if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
+ {
+ tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/1);
+ tmpl = maybe_get_template_decl_from_type_decl (tmpl);
+ }
+
+ if (tmpl && 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));
+ check to see that the declarations match, and install any new
+ default parameters. We must tsubst the default parameters,
+ of course. We only need the innermost template parameters
+ because that is all that redeclare_class_template will look
+ at. */
+ tree parms
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
+ args, /*complain=*/1);
+ redeclare_class_template (TREE_TYPE (tmpl), parms);
friend_type = TREE_TYPE (tmpl);
}
else
@@ -3733,7 +4668,7 @@ tsubst_friend_class (friend_tmpl, args)
/* 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);
+ tmpl = tsubst (friend_tmpl, args, /*complain=*/1, NULL_TREE);
/* The new TMPL is not an instantiation of anything, so we
forget its origins. We don't reset CLASSTYPE_TI_TEMPLATE for
@@ -3754,83 +4689,152 @@ tree
instantiate_class_template (type)
tree type;
{
- tree template, template_info, args, pattern, t, *field_chain;
- tree typedecl, outer_args;
+ tree template, args, pattern, t;
+ tree typedecl;
if (type == error_mark_node)
return error_mark_node;
- template_info = CLASSTYPE_TEMPLATE_INFO (type);
-
if (TYPE_BEING_DEFINED (type) || TYPE_SIZE (type))
return type;
- template = TI_TEMPLATE (template_info);
+ /* We want to allocate temporary vectors of template arguments and
+ template argument expressions on the momentary obstack, not on
+ the expression obstack. Otherwise, all the space allocated in
+ argument coercion and such is simply lost. */
+ push_momentary ();
+
+ /* Figure out which template is being instantiated. */
+ template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
- args = TI_ARGS (template_info);
- if (DECL_TEMPLATE_INFO (template))
- {
- outer_args = DECL_TI_ARGS (template);
- while (DECL_TEMPLATE_INFO (template))
- template = DECL_TI_TEMPLATE (template);
- }
- else
- outer_args = NULL_TREE;
+ /* Figure out which arguments are being used to do the
+ instantiation. */
+ args = CLASSTYPE_TI_ARGS (type);
+ PARTIAL_INSTANTIATION_P (type) = uses_template_parms (args);
- t = most_specialized_class
- (DECL_TEMPLATE_SPECIALIZATIONS (template), args, outer_args);
+ if (pedantic && PARTIAL_INSTANTIATION_P (type))
+ /* If this is a partial instantiation, 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. For
+ example, consider:
- if (t == error_mark_node)
+ template <class T>
+ struct S {};
+
+ template <class U>
+ void f(S<U>);
+
+ template <>
+ struct S<int> {};
+
+ Now, the `S<U>' in `f<int>' is the specialization, not an
+ instantiation of the original template. */
+ goto end;
+
+ /* Determine what specialization of the original template to
+ instantiate. */
+ if (PARTIAL_INSTANTIATION_P (type))
+ /* There's no telling which specialization is appropriate at this
+ point. Since all peeking at the innards of this partial
+ instantiation are extensions (like the "implicit typename"
+ extension, which allows users to omit the keyword `typename' on
+ names that are declared as types in template base classes), we
+ are free to do what we please.
+
+ Trying to figure out which partial instantiation to use can
+ cause a crash. (Some of the template arguments don't even have
+ types.) So, we just use the most general version. */
+ t = NULL_TREE;
+ else
{
- char *str = "candidates are:";
- cp_error ("ambiguous class template instantiation for `%#T'", type);
- for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t))
+ t = most_specialized_class (template, args);
+
+ if (t == error_mark_node)
{
- if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
- args, outer_args))
+ const char *str = "candidates are:";
+ cp_error ("ambiguous class template instantiation for `%#T'", type);
+ for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t;
+ t = TREE_CHAIN (t))
{
- cp_error_at ("%s %+#T", str, TREE_TYPE (t));
- str = " ";
+ if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+ args))
+ {
+ cp_error_at ("%s %+#T", str, TREE_TYPE (t));
+ str = " ";
+ }
}
+ TYPE_BEING_DEFINED (type) = 1;
+ type = error_mark_node;
+ goto end;
}
- TYPE_BEING_DEFINED (type) = 1;
- return error_mark_node;
}
- else if (t)
+
+ if (t)
pattern = TREE_TYPE (t);
else
pattern = TREE_TYPE (template);
+ /* If the template we're instantiating is incomplete, then clearly
+ there's nothing we can do. */
if (TYPE_SIZE (pattern) == NULL_TREE)
- return type;
+ goto end;
- if (t)
- args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
- args, outer_args);
-
- 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;
+ /* 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 (PARTIAL_INSTANTIATION_P (type))
+ {
+ /* The fields set here must be kept in sync with those cleared
+ in begin_class_definition. */
+ 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);
+ /* Pretend that the type is complete, so that we will look
+ inside it during name lookup and such. */
+ TYPE_SIZE (type) = integer_zero_node;
+ goto end;
+ }
- /* 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);
+ /* If we've recursively instantiated too many templates, stop. */
+ if (! push_tinst_level (type))
+ goto end;
+ /* Now we're really doing the instantiation. Mark the type as in
+ the process of being defined. */
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 (t)
+ {
+ /* This TYPE is actually a instantiation of of a partial
+ specialization. We replace the innermost set of ARGS with
+ the arguments appropriate for substitution. For example,
+ given:
+
+ template <class T> struct S {};
+ template <class T> struct S<T*> {};
+
+ and supposing that we are instantiating S<int*>, ARGS will
+ present be {int*} but we need {int}. */
+ tree inner_args
+ = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+ args);
+
+ /* If there were multiple levels in ARGS, replacing the
+ innermost level would alter CLASSTYPE_TI_ARGS, which we don't
+ want, so we make a copy first. */
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
+ {
+ args = copy_node (args);
+ SET_TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args), inner_args);
+ }
+ else
+ args = inner_args;
+ }
if (flag_external_templates)
{
@@ -3860,7 +4864,6 @@ instantiate_class_template (type)
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);
@@ -3883,108 +4886,163 @@ instantiate_class_template (type)
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> */
+ if (ANON_UNION_TYPE_P (pattern))
+ SET_ANON_UNION_TYPE_P (type);
- CLASSTYPE_LOCAL_TYPEDECLS (type) = CLASSTYPE_LOCAL_TYPEDECLS (pattern);
+ /* 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);
- /* 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))
+ if (TYPE_BINFO_BASETYPES (pattern))
{
- 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 base_list = NULL_TREE;
+ tree pbases = TYPE_BINFO_BASETYPES (pattern);
+ int i;
- {
- tree binfo = TYPE_BINFO (type);
- tree pbases = TYPE_BINFO_BASETYPES (pattern);
+ /* Substitute into each of the bases to determine the actual
+ basetypes. */
+ for (i = 0; i < TREE_VEC_LENGTH (pbases); ++i)
+ {
+ tree base;
+ tree access;
+ tree pbase;
- 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;
+ pbase = TREE_VEC_ELT (pbases, i);
- TREE_VEC_ELT (bases, i) = elt
- = tsubst (TREE_VEC_ELT (pbases, i), args, NULL_TREE);
- BINFO_INHERITANCE_CHAIN (elt) = binfo;
+ /* Substitue to figure out the base class. */
+ base = tsubst (BINFO_TYPE (pbase), args,
+ /*complain=*/1, NULL_TREE);
+ if (base == error_mark_node)
+ continue;
- basetype = TREE_TYPE (elt);
+ /* Calculate the correct access node. */
+ if (TREE_VIA_VIRTUAL (pbase))
+ {
+ if (TREE_VIA_PUBLIC (pbase))
+ access = access_public_virtual_node;
+ else if (TREE_VIA_PROTECTED (pbase))
+ access = access_protected_virtual_node;
+ else
+ access = access_private_virtual_node;
+ }
+ else
+ {
+ if (TREE_VIA_PUBLIC (pbase))
+ access = access_public_node;
+ else if (TREE_VIA_PROTECTED (pbase))
+ access = access_protected_node;
+ else
+ access = access_private_node;
+ }
- 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);
+ base_list = tree_cons (access, base, base_list);
+ }
- /* 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;
- }
- }
+ /* The list is now in reverse order; correct that. */
+ base_list = nreverse (base_list);
+
+ /* Now call xref_basetypes to set up all the base-class
+ information. */
+ xref_basetypes (TREE_CODE (pattern) == RECORD_TYPE
+ ? (CLASSTYPE_DECLARED_CLASS (pattern)
+ ? class_type_node : record_type_node)
+ : union_type_node,
+ DECL_NAME (TYPE_NAME (pattern)),
+ type,
+ base_list);
+ }
- field_chain = &TYPE_FIELDS (type);
+ /* Now that our base classes are set up, enter the scope of the
+ class, so that name lookups into base classes, etc. will work
+ corectly. This is precisely analagous to what we do in
+ begin_class_definition when defining an ordinary non-template
+ class. */
+ pushclass (type, 1);
for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
{
tree tag = TREE_VALUE (t);
+ tree name = TYPE_IDENTIFIER (tag);
+ tree newtag;
- /* These will add themselves to CLASSTYPE_TAGS for the new type. */
- if (TREE_CODE (tag) == ENUMERAL_TYPE)
+ newtag = tsubst (tag, args, /*complain=*/1, NULL_TREE);
+ if (TREE_CODE (newtag) != ENUMERAL_TYPE)
{
- (void) tsubst_enum (tag, args, field_chain);
- while (*field_chain)
- {
- DECL_FIELD_CONTEXT (*field_chain) = type;
- field_chain = &TREE_CHAIN (*field_chain);
- }
+ if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag))
+ /* Unfortunately, lookup_template_class sets
+ CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
+ instantiation (i.e., for the type of a member template
+ class nested within a template class.) This behavior is
+ required for maybe_process_partial_specialization to work
+ correctly, but is not accurate in this case; the TAG is not
+ an instantiation of anything. (The corresponding
+ TEMPLATE_DECL is an instantiation, but the TYPE is not.) */
+ CLASSTYPE_USE_TEMPLATE (newtag) = 0;
+
+ /* Now, we call pushtag to put this NEWTAG into the scope of
+ TYPE. We first set up the IDENTIFIER_TYPE_VALUE to avoid
+ pushtag calling push_template_decl. We don't have to do
+ this for enums because it will already have been done in
+ tsubst_enum. */
+ if (name)
+ SET_IDENTIFIER_TYPE_VALUE (name, newtag);
+ pushtag (name, newtag, /*globalize=*/0);
}
- else
- tsubst (tag, args, 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);
+ tree r;
+
+ /* The the file and line for this declaration, to assist in
+ error message reporting. Since we called push_tinst_level
+ above, we don't need to restore these. */
+ lineno = DECL_SOURCE_LINE (t);
+ input_filename = DECL_SOURCE_FILE (t);
+
+ r = tsubst (t, args, /*complain=*/1, 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);
- }
+ tree init;
+
+ if (DECL_DEFINED_IN_CLASS_P (r))
+ init = tsubst_expr (DECL_INITIAL (t), args,
+ /*complain=*/1, NULL_TREE);
+ else
+ init = NULL_TREE;
+
+ finish_static_data_member_decl (r, init,
+ /*asmspec_tree=*/NULL_TREE,
+ /*need_pop=*/0,
+ /*flags=*/0);
- *field_chain = r;
- field_chain = &TREE_CHAIN (r);
+ if (DECL_DEFINED_IN_CLASS_P (r))
+ check_static_variable_definition (r, TREE_TYPE (r));
+ }
+
+ /* R will have a TREE_CHAIN if and only if it has already been
+ processed by finish_member_declaration. This can happen
+ if, for example, it is a TYPE_DECL for a class-scoped
+ ENUMERAL_TYPE; such a thing will already have been added to
+ the field list by tsubst_enum above. */
+ if (!TREE_CHAIN (r))
+ {
+ set_current_access_from_decl (r);
+ finish_member_declaration (r);
+ }
}
- TYPE_METHODS (type) = tsubst_chain (TYPE_METHODS (pattern), args);
+ /* Set up the list (TYPE_METHODS) and vector (CLASSTYPE_METHOD_VEC)
+ for this instantiation. */
+ for (t = TYPE_METHODS (pattern); t; t = TREE_CHAIN (t))
+ {
+ tree r = tsubst (t, args, /*complain=*/1, NULL_TREE);
+ set_current_access_from_decl (r);
+ finish_member_declaration (r);
+ }
/* Construct the DECL_FRIENDLIST for the new class type. */
typedecl = TYPE_MAIN_DECL (type);
@@ -3994,31 +5052,19 @@ instantiate_class_template (type)
{
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)));
-
- }
- }
+ if (TREE_PURPOSE (friends) == error_mark_node)
+ add_friend (type,
+ tsubst_friend_function (TREE_VALUE (friends),
+ args));
+ else
+ add_friends (type,
+ tsubst_copy (TREE_PURPOSE (t), args,
+ /*complain=*/1, NULL_TREE),
+ tsubst (TREE_PURPOSE (friends), args,
+ /*complain=*/1, NULL_TREE));
}
for (t = CLASSTYPE_FRIEND_CLASSES (pattern);
@@ -4028,14 +5074,17 @@ instantiate_class_template (type)
tree friend_type = TREE_VALUE (t);
tree new_friend_type;
- if (TREE_CODE (friend_type) != TEMPLATE_DECL)
+ if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ new_friend_type = tsubst_friend_class (friend_type, args);
+ else if (uses_template_parms (friend_type))
+ new_friend_type = tsubst (friend_type, args, /*complain=*/1,
+ NULL_TREE);
+ else
/* 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);
+ xref_tag_from_type (friend_type, NULL_TREE, 1);
+
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
/* Trick make_friend_class into realizing that the friend
@@ -4054,7 +5103,8 @@ instantiate_class_template (type)
/* This does injection for friend functions. */
if (!processing_template_decl)
{
- t = tsubst (DECL_TEMPLATE_INJECT (template), args, NULL_TREE);
+ t = tsubst (DECL_TEMPLATE_INJECT (template), args,
+ /*complain=*/1, NULL_TREE);
for (; t; t = TREE_CHAIN (t))
{
@@ -4074,18 +5124,28 @@ instantiate_class_template (type)
require_complete_type (t);
}
- type = finish_struct_1 (type, 0);
- CLASSTYPE_GOT_SEMICOLON (type) = 1;
+ /* Set the file and line number information to whatever is given for
+ the class itself. This puts error messages involving generated
+ implicit functions at a predictable point, and the same point
+ that would be used for non-template classes. */
+ lineno = DECL_SOURCE_LINE (typedecl);
+ input_filename = DECL_SOURCE_FILE (typedecl);
- repo_template_used (type);
+ unreverse_member_declarations (type);
+ finish_struct_1 (type, 0);
+ CLASSTYPE_GOT_SEMICOLON (type) = 1;
- end:
+ /* Clear this now so repo_template_used is happy. */
TYPE_BEING_DEFINED (type) = 0;
- popclass (0);
+ repo_template_used (type);
+ popclass ();
pop_from_top_level ();
pop_tinst_level ();
+ end:
+ pop_momentary ();
+
return type;
}
@@ -4105,24 +5165,6 @@ list_eq (t1, t2)
return list_eq (TREE_CHAIN (t1), TREE_CHAIN (t2));
}
-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)
- /* 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. */
@@ -4150,28 +5192,23 @@ maybe_fold_nontype_arg (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 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. */
+ where ARGS is either that or the VEC of VECs for all the
+ arguments. */
tree
-innermost_args (args, is_spec)
+innermost_args (args)
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;
+ return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args));
}
/* Substitute ARGS into the vector of template arguments T. */
-tree
-tsubst_template_arg_vector (t, args)
+static tree
+tsubst_template_arg_vector (t, args, complain)
tree t;
tree args;
+ int complain;
{
int len = TREE_VEC_LENGTH (t), need_new = 0, i;
tree *elts = (tree *) alloca (len * sizeof (tree));
@@ -4182,10 +5219,12 @@ tsubst_template_arg_vector (t, args)
{
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);
+ elts[i] = tsubst_template_arg_vector (TREE_VEC_ELT (t, i),
+ args, complain);
else
elts[i] = maybe_fold_nontype_arg
- (tsubst_expr (TREE_VEC_ELT (t, i), args, NULL_TREE));
+ (tsubst_expr (TREE_VEC_ELT (t, i), args, complain,
+ NULL_TREE));
if (elts[i] != TREE_VEC_ELT (t, i))
need_new = 1;
@@ -4194,46 +5233,77 @@ tsubst_template_arg_vector (t, args)
if (!need_new)
return t;
- t = make_tree_vec (len);
+ t = make_temp_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.
+/* Return the result of substituting ARGS into the template parameters
+ given by PARMS. If there are m levels of ARGS and m + n levels of
+ PARMS, then the result will contain n levels of PARMS. For
+ example, if PARMS is `template <class T> template <class U>
+ template <T*, U, class V>' and ARGS is {{int}, {double}} then the
+ result will be `template <int*, double, class V>'. */
- tsubst is used for dealing with types, decls and the like; for
- expressions, use tsubst_expr or tsubst_copy. */
-
-tree
-tsubst (t, args, in_decl)
- tree t, args;
- tree in_decl;
+static tree
+tsubst_template_parms (parms, args, complain)
+ tree parms;
+ tree args;
+ int complain;
{
- tree type;
+ tree r;
+ tree* new_parms = &r;
- 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;
+ for (new_parms = &r;
+ TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args);
+ 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, complain,
+ NULL_TREE),
+ tsubst (parm_decl, args, complain,
+ NULL_TREE));
+ }
+
+ *new_parms =
+ tree_cons (build_int_2 (0, (TMPL_PARMS_DEPTH (parms)
+ - TMPL_ARGS_DEPTH (args))),
+ new_vec, NULL_TREE);
+ }
- 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);
+ return r;
+}
- 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);
+/* Substitute the ARGS into the indicated aggregate (or enumeration)
+ type T. If T is not an aggregate or enumeration type, it is
+ handled as if by tsubst. IN_DECL is as for tsubst. If
+ ENTERING_SCOPE is non-zero, T is the context for a template which
+ we are presently tsubst'ing. Return the subsituted value. */
+
+static tree
+tsubst_aggr_type (t, args, complain, in_decl, entering_scope)
+ tree t;
+ tree args;
+ int complain;
+ tree in_decl;
+ int entering_scope;
+{
+ if (t == NULL_TREE)
+ return NULL_TREE;
switch (TREE_CODE (t))
{
@@ -4241,234 +5311,115 @@ tsubst (t, args, in_decl)
if (TYPE_PTRMEMFUNC_P (t))
{
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));
+ (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl));
+ return cp_build_qualified_type (r, TYPE_QUALS (t));
}
/* else fall through */
+ case ENUMERAL_TYPE:
case UNION_TYPE:
- if (uses_template_parms (t))
+ if (TYPE_TEMPLATE_INFO (t))
{
- tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
+ tree argvec;
tree context;
tree r;
+ /* First, determine the context for the type we are looking
+ up. */
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);
- }
- }
+ context = tsubst_aggr_type (TYPE_CONTEXT (t), args,
+ complain,
+ in_decl, /*entering_scope=*/1);
else
context = NULL_TREE;
- r = lookup_template_class (t, argvec, in_decl, context);
+ /* Then, figure out what arguments are appropriate for the
+ type we are trying to find. For example, given:
- 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 COMPLEX_TYPE:
- case BOOLEAN_TYPE:
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
- case NAMESPACE_DECL:
- return t;
+ template <class T> struct S;
+ template <class T, class U> void f(T, U) { S<U> su; }
- 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));
- }
+ and supposing that we are instantiating f<int, double>,
+ then our ARGS will be {int, double}, but, when looking up
+ S we only want {double}. */
+ push_momentary ();
+ argvec = tsubst_template_arg_vector (TYPE_TI_ARGS (t), args,
+ complain);
- case INTEGER_TYPE:
- if (t == integer_type_node)
- return t;
+ r = lookup_template_class (t, argvec, in_decl, context,
+ entering_scope);
+ pop_momentary ();
- if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
- && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
+ return cp_build_qualified_type (r, TYPE_QUALS (t));
+ }
+ else
+ /* This is not a template type, so there's nothing to do. */
return 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;
- }
-
- max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1));
- return build_index_2_type (size_zero_node, max);
- }
-
- case TEMPLATE_TYPE_PARM:
- case TEMPLATE_TEMPLATE_PARM:
- case TEMPLATE_PARM_INDEX:
- {
- int idx;
- int level;
- int levels;
- tree r = NULL_TREE;
-
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
- {
- idx = TEMPLATE_TYPE_IDX (t);
- level = TEMPLATE_TYPE_LEVEL (t);
- }
- else
- {
- idx = TEMPLATE_PARM_IDX (t);
- level = TEMPLATE_PARM_LEVEL (t);
- }
-
- if (TREE_VEC_LENGTH (args) > 0)
- {
- tree arg = NULL_TREE;
-
- if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
- {
- levels = TREE_VEC_LENGTH (args);
- if (level <= levels)
- arg = TREE_VEC_ELT
- (TREE_VEC_ELT (args, level - 1), idx);
- }
- else
- {
- levels = 1;
- if (level == 1)
- arg = TREE_VEC_ELT (args, idx);
- }
-
- 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)
- {
- if (CLASSTYPE_TEMPLATE_INFO (t))
- {
- /* 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));
- }
- else
- /* We are processing a template argument list. */
- return arg;
- }
- else
- return arg;
- }
- }
-
- 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;
+ default:
+ return tsubst (t, args, complain, in_decl);
+ }
+}
- if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
- && CLASSTYPE_TEMPLATE_INFO (t))
- {
- tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
- CLASSTYPE_TEMPLATE_INFO (r)
- = perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
- }
- break;
+/* Substitute the ARGS into the T, which is a _DECL. TYPE is the
+ (already computed) substitution of ARGS into TREE_TYPE (T), if
+ appropriate. Return the result of the substitution. IN_DECL is as
+ for tsubst. */
- case TEMPLATE_PARM_INDEX:
- r = reduce_template_parm_level (t, type, levels);
- break;
-
- default:
- my_friendly_abort (0);
- }
+static tree
+tsubst_decl (t, args, type, in_decl)
+ tree t;
+ tree args;
+ tree type;
+ tree in_decl;
+{
+ int saved_lineno;
+ char* saved_filename;
+ tree r = NULL_TREE;
- return r;
- }
+ /* Set the filename and linenumber to improve error-reporting. */
+ saved_lineno = lineno;
+ saved_filename = input_filename;
+ lineno = DECL_SOURCE_LINE (t);
+ input_filename = DECL_SOURCE_FILE (t);
+ switch (TREE_CODE (t))
+ {
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);
+ /* We might already have an instance of this template.
+ The ARGS are for the surrounding class type, so the
+ full args contain the tsubst'd args for the context,
+ plus the innermost args from the template decl. */
+ tree tmpl_args = DECL_CLASS_TEMPLATE_P (t)
+ ? CLASSTYPE_TI_ARGS (TREE_TYPE (t))
+ : DECL_TI_ARGS (DECL_RESULT (t));
+ tree full_args;
+
+ push_momentary ();
+ full_args = tsubst_template_arg_vector (tmpl_args, args,
+ /*complain=*/1);
+
+ /* tsubst_template_arg_vector doesn't copy the vector if
+ nothing changed. But, *something* should have
+ changed. */
+ my_friendly_assert (full_args != tmpl_args, 0);
+
+ spec = retrieve_specialization (t, full_args);
+ pop_momentary ();
if (spec != NULL_TREE)
- return spec;
+ {
+ r = spec;
+ break;
+ }
}
/* Make a new template decl. It will be similar to the
@@ -4476,90 +5427,64 @@ tsubst (t, args, in_decl)
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;
+ r = copy_node (t);
+ copy_lang_decl (r);
+ my_friendly_assert (DECL_LANG_SPECIFIC (r) != 0, 0);
+ TREE_CHAIN (r) = 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;
+ tree new_decl = tsubst (decl, args, /*complain=*/1, in_decl);
+ DECL_RESULT (r) = new_decl;
+ TREE_TYPE (r) = TREE_TYPE (new_decl);
+ break;
}
- 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);
+ DECL_CONTEXT (r)
+ = tsubst_aggr_type (DECL_CONTEXT (t), args, /*complain=*/1,
+ in_decl, /*entering_scope=*/1);
+ DECL_CLASS_CONTEXT (r)
+ = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args,
+ /*complain=*/1, in_decl,
+ /*entering_scope=*/1);
+ DECL_TEMPLATE_INFO (r) = 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);
+ tree new_type = tsubst (TREE_TYPE (t), args,
+ /*complain=*/1, in_decl);
+ TREE_TYPE (r) = new_type;
+ CLASSTYPE_TI_TEMPLATE (new_type) = r;
+ DECL_RESULT (r) = TYPE_MAIN_DECL (new_type);
+ DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
}
else
{
- 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);
+ tree new_decl = tsubst (decl, args, /*complain=*/1, in_decl);
+ DECL_RESULT (r) = new_decl;
+ DECL_TI_TEMPLATE (new_decl) = r;
+ TREE_TYPE (r) = TREE_TYPE (new_decl);
+ DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);
}
- DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE;
- SET_DECL_IMPLICIT_INSTANTIATION (tmpl);
+ SET_DECL_IMPLICIT_INSTANTIATION (r);
+ DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;
+ DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;
/* 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);
- }
+ DECL_TEMPLATE_PARMS (r)
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
+ /*complain=*/1);
if (PRIMARY_TEMPLATE_P (t))
- DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+ DECL_PRIMARY_TEMPLATE (r) = r;
/* We don't partially instantiate partial specializations. */
if (TREE_CODE (decl) == TYPE_DECL)
- return tmpl;
+ break;
- /* 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))
@@ -4600,28 +5525,132 @@ tsubst (t, args, in_decl)
no concern to us. */
continue;
+ if (TREE_CODE (fn) != TEMPLATE_DECL)
+ /* A full specialization. There's no need to record
+ that here. */
+ 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));
+ /*complain=*/1, in_decl);
+ new_fn = tsubst (DECL_RESULT (most_general_template (fn)),
+ spec_args, /*complain=*/1, in_decl);
+ DECL_TI_TEMPLATE (new_fn) = fn;
+ register_specialization (new_fn, r,
+ innermost_args (spec_args));
}
/* Record this partial instantiation. */
- register_specialization (tmpl, t, args);
+ register_specialization (r, t,
+ DECL_TI_ARGS (DECL_RESULT (r)));
- return tmpl;
}
+ break;
case FUNCTION_DECL:
{
- tree r = NULL_TREE;
tree ctx;
- tree argvec;
- tree tmpl = NULL_TREE;
+ tree argvec = NULL_TREE;
+ tree *friends;
+ tree gen_tmpl;
int member;
+ int args_depth;
+ int parms_depth;
+
+ /* Nobody should be tsubst'ing into non-template functions. */
+ my_friendly_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
+
+ if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL)
+ {
+ tree spec;
+
+ /* Allocate template arguments on the momentary obstack,
+ in case we don't need to keep them. */
+ push_momentary ();
+
+ /* Calculate the most general template of which R is a
+ specialization, and the complete set of arguments used to
+ specialize R. */
+ gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
+ argvec
+ = tsubst_template_arg_vector (DECL_TI_ARGS
+ (DECL_TEMPLATE_RESULT (gen_tmpl)),
+ args, /*complain=*/1);
+
+ /* Check to see if we already have this specialization. */
+ spec = retrieve_specialization (gen_tmpl, argvec);
+
+ if (spec)
+ {
+ r = spec;
+ pop_momentary ();
+ break;
+ }
+
+ /* We're going to need to keep the ARGVEC, so we copy it
+ here. */
+ argvec = copy_to_permanent (argvec);
+ pop_momentary ();
+
+ /* Here, we deal with the peculiar case:
+
+ template <class T> struct S {
+ template <class U> friend void f();
+ };
+ template <class U> friend void f() {}
+ template S<int>;
+ template void f<double>();
+
+ Here, the ARGS for the instantiation of will be {int,
+ double}. But, we only need as many ARGS as there are
+ levels of template parameters in CODE_PATTERN. We are
+ careful not to get fooled into reducing the ARGS in
+ situations like:
+
+ template <class T> struct S { template <class U> void f(U); }
+ template <class T> template <> void S<T>::f(int) {}
+
+ which we can spot because the pattern will be a
+ specialization in this case. */
+ args_depth = TMPL_ARGS_DEPTH (args);
+ parms_depth =
+ TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t)));
+ if (args_depth > parms_depth
+ && !DECL_TEMPLATE_SPECIALIZATION (t))
+ {
+ my_friendly_assert (DECL_FRIEND_P (t), 0);
+
+ if (parms_depth > 1)
+ {
+ int i;
+
+ args = make_temp_vec (parms_depth);
+ for (i = 0; i < parms_depth; ++i)
+ TREE_VEC_ELT (args, i) =
+ TREE_VEC_ELT (args, i + (args_depth - parms_depth));
+ }
+ else
+ args = TREE_VEC_ELT (args, args_depth - parms_depth);
+ }
+ }
+ else
+ {
+ /* This special case arises when we have something like this:
+
+ template <class T> struct S {
+ friend void f<int>(int, double);
+ };
+
+ Here, the DECL_TI_TEMPLATE for the friend declaration
+ will be a LOOKUP_EXPR or an IDENTIFIER_NODE. We are
+ being called from tsubst_friend_function, and we want
+ only to create a new decl (R) with appropriate types so
+ that we can call determine_specialization. */
+ my_friendly_assert ((TREE_CODE (DECL_TI_TEMPLATE (t))
+ == LOOKUP_EXPR)
+ || (TREE_CODE (DECL_TI_TEMPLATE (t))
+ == IDENTIFIER_NODE), 0);
+ gen_tmpl = NULL_TREE;
+ }
if (DECL_CLASS_SCOPE_P (t))
{
@@ -4629,36 +5658,16 @@ tsubst (t, args, in_decl)
member = 2;
else
member = 1;
- ctx = tsubst (DECL_CLASS_CONTEXT (t), args, t);
+ ctx = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args,
+ /*complain=*/1, t,
+ /*entering_scope=*/1);
}
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;
- }
+ type = tsubst (type, args, /*complain=*/1, in_decl);
/* We do NOT check for matching decls pushed separately at this
point, as they may not represent instantiations of this
@@ -4671,22 +5680,19 @@ tsubst (t, args, in_decl)
TREE_TYPE (r) = type;
DECL_CONTEXT (r)
- = tsubst (DECL_CONTEXT (t), args, t);
+ = tsubst_aggr_type (DECL_CONTEXT (t), args, /*complain=*/1, t,
+ /*entering_scope=*/1);
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));
- }
+ if (member && IDENTIFIER_TYPENAME_P (DECL_NAME (r)))
+ /* 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_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args,
+ /*complain=*/1, 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);
@@ -4697,142 +5703,85 @@ tsubst (t, args, in_decl)
DECL_PENDING_INLINE_INFO (r) = 0;
TREE_USED (r) = 0;
- if (DECL_CONSTRUCTOR_P (r))
+ /* Set up the DECL_TEMPLATE_INFO for R and compute its mangled
+ name. There's no need to do this in the special friend
+ case mentioned above where GEN_TMPL is NULL. */
+ if (gen_tmpl)
{
- 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));
+ /* The ARGVEC was built on the momentary obstack. Make it
+ permanent now. */
+ argvec = copy_to_permanent (argvec);
+ DECL_TEMPLATE_INFO (r)
+ = perm_tree_cons (gen_tmpl, argvec, NULL_TREE);
+ SET_DECL_IMPLICIT_INSTANTIATION (r);
+ register_specialization (r, gen_tmpl, argvec);
- 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)))
+ /* Set the mangled name for R. */
+ if (DECL_DESTRUCTOR_P (t))
+ DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
+ else
{
- 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);
+ /* Instantiations of template functions must be mangled
+ specially, in order to conform to 14.5.5.1
+ [temp.over.link]. */
+ tree tmpl = DECL_TI_TEMPLATE (t);
- 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);
- }
+ /* 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)))
+ set_mangled_name_for_decl (r);
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);
+ set_mangled_name_for_template_decl (r);
}
+
+ DECL_RTL (r) = 0;
+ make_decl_rtl (r, NULL_PTR, 1);
+
+ /* 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
+ && ! uses_template_parms (r)
+ && (IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r))
+ == NULL_TREE))
+ SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
}
- DECL_RTL (r) = 0;
- make_decl_rtl (r, NULL_PTR, 1);
- if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
+ /* Copy the list of befriending classes. */
+ for (friends = &DECL_BEFRIENDING_CLASSES (r);
+ *friends;
+ friends = &TREE_CHAIN (*friends))
{
- 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);
+ *friends = copy_node (*friends);
+ TREE_VALUE (*friends) = tsubst (TREE_VALUE (*friends),
+ args, /*complain=*/1,
+ in_decl);
}
- /* 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;
+ 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));
}
+ break;
case PARM_DECL:
{
- tree r = copy_node (t);
+ r = copy_node (t);
TREE_TYPE (r) = type;
+ c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
+
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_INITIAL (r) = tsubst (DECL_INITIAL (r), args,
+ /*complain=*/1, in_decl);
DECL_CONTEXT (r) = NULL_TREE;
#ifdef PROMOTE_PROTOTYPES
@@ -4842,125 +5791,539 @@ tsubst (t, args, in_decl)
DECL_ARG_TYPE (r) = integer_type_node;
#endif
if (TREE_CHAIN (t))
- TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (t));
- return r;
+ TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args,
+ /*complain=*/1, TREE_CHAIN (t));
}
+ break;
case FIELD_DECL:
{
- tree r = copy_node (t);
- TREE_TYPE (r) = type;
+ r = copy_node (t);
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_TYPE (r) = type;
+ c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
+
+ /* We don't have to set DECL_CONTEXT here; it is set by
+ finish_member_declaration. */
+ DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,
+ /*complain=*/1, in_decl);
TREE_CHAIN (r) = NULL_TREE;
- if (TREE_CODE (type) == VOID_TYPE)
+ if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
- return r;
}
+ break;
case USING_DECL:
{
- tree r = copy_node (t);
+ r = copy_node (t);
DECL_INITIAL (r)
- = tsubst_copy (DECL_INITIAL (t), args, in_decl);
+ = tsubst_copy (DECL_INITIAL (t), args, /*complain=*/1, in_decl);
TREE_CHAIN (r) = NULL_TREE;
- return r;
}
+ break;
case VAR_DECL:
{
- tree r;
- tree ctx = tsubst_copy (DECL_CONTEXT (t), args, in_decl);
+ tree argvec;
+ tree gen_tmpl;
+ tree spec;
+ tree tmpl;
+ tree ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
+ /*complain=*/1,
+ in_decl, /*entering_scope=*/1);
+
+ /* Nobody should be tsubst'ing into non-template variables. */
+ my_friendly_assert (DECL_LANG_SPECIFIC (t)
+ && DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
- /* Do we already have this instantiation? */
- if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
+ /* Check to see if we already have this specialization. */
+ tmpl = DECL_TI_TEMPLATE (t);
+ gen_tmpl = most_general_template (tmpl);
+ argvec = tsubst (DECL_TI_ARGS (t), args, /*complain=*/1, in_decl);
+ spec = retrieve_specialization (gen_tmpl, argvec);
+
+ if (spec)
{
- 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 = spec;
+ break;
}
r = copy_node (t);
TREE_TYPE (r) = type;
+ c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
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;
+ copy_lang_decl (r);
+ DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
- if (DECL_LANG_SPECIFIC (r))
- {
- copy_lang_decl (r);
- DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
- }
+ /* A static data member declaration is always marked external
+ when it is declared in-class, even if an initializer is
+ present. We mimic the non-template processing here. */
+ DECL_EXTERNAL (r) = 1;
- 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);
+ SET_DECL_IMPLICIT_INSTANTIATION (r);
+ register_specialization (r, gen_tmpl, argvec);
- 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;
}
+ break;
case TYPE_DECL:
if (t == TYPE_NAME (TREE_TYPE (t)))
- return TYPE_NAME (type);
+ r = TYPE_NAME (type);
+ else
+ {
+ r = copy_node (t);
+ TREE_TYPE (r) = type;
+ DECL_CONTEXT (r) = current_class_type;
+ TREE_CHAIN (r) = NULL_TREE;
+ }
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
+
+ /* Restore the file and line information. */
+ lineno = saved_lineno;
+ input_filename = saved_filename;
+
+ return r;
+}
+
+/* Substitue into the ARG_TYPES of a function type. */
+
+static tree
+tsubst_arg_types (arg_types, args, complain, in_decl)
+ tree arg_types;
+ tree args;
+ int complain;
+ tree in_decl;
+{
+ tree remaining_arg_types;
+ tree type;
+
+ if (!arg_types || arg_types == void_list_node)
+ return arg_types;
+
+ remaining_arg_types = tsubst_arg_types (TREE_CHAIN (arg_types),
+ args, complain, in_decl);
+ if (remaining_arg_types == error_mark_node)
+ return error_mark_node;
+
+ type = tsubst (TREE_VALUE (arg_types), args, complain, in_decl);
+ if (type == error_mark_node)
+ return error_mark_node;
+
+ /* Do array-to-pointer, function-to-pointer conversion, and ignore
+ top-level qualifiers as required. */
+ type = TYPE_MAIN_VARIANT (type_decays_to (type));
+
+ /* Note that we do not substitute into default arguments here. The
+ standard mandates that they be instantiated only when needed,
+ which is done in build_over_call. */
+ return hash_tree_cons (TREE_PURPOSE (arg_types), type,
+ remaining_arg_types);
+
+}
+
+/* Substitute into a FUNCTION_TYPE or METHOD_TYPE. This routine does
+ *not* handle the exception-specification for FNTYPE, because the
+ initial substitution of explicitly provided template parameters
+ during argument deduction forbids substitution into the
+ exception-specification:
+
+ [temp.deduct]
+
+ All references in the function type of the function template to the
+ corresponding template parameters are replaced by the specified tem-
+ plate argument values. If a substitution in a template parameter or
+ in the function type of the function template results in an invalid
+ type, type deduction fails. [Note: The equivalent substitution in
+ exception specifications is done only when the function is instanti-
+ ated, at which point a program is ill-formed if the substitution
+ results in an invalid type.] */
+
+static tree
+tsubst_function_type (t, args, complain, in_decl)
+ tree t;
+ tree args;
+ int complain;
+ tree in_decl;
+{
+ tree return_type;
+ tree arg_types;
+ tree fntype;
+
+ /* The TYPE_CONTEXT is not used for function/method types. */
+ my_friendly_assert (TYPE_CONTEXT (t) == NULL_TREE, 0);
+
+ /* Substitue the return type. */
+ return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (return_type == error_mark_node)
+ return error_mark_node;
+
+ /* Substitue the argument types. */
+ arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args,
+ complain, in_decl);
+ if (arg_types == error_mark_node)
+ return error_mark_node;
+
+ /* Construct a new type node and return it. */
+ if (TREE_CODE (t) == FUNCTION_TYPE)
+ fntype = build_function_type (return_type, arg_types);
+ else
+ {
+ tree r = TREE_TYPE (TREE_VALUE (arg_types));
+ if (! IS_AGGR_TYPE (r))
+ {
+ /* [temp.deduct]
+
+ Type deduction may fail for any of the following
+ reasons:
+
+ -- Attempting to create "pointer to member of T" when T
+ is not a class type. */
+ if (complain)
+ cp_error ("creating pointer to member function of non-class type `%T'",
+ r);
+ return error_mark_node;
+ }
+
+ fntype = build_cplus_method_type (r, return_type, TREE_CHAIN
+ (arg_types));
+ }
+ fntype = build_qualified_type (fntype, TYPE_QUALS (t));
+ fntype = build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
+
+ return fntype;
+}
+
+/* Substitute into the PARMS of a call-declarator. */
+
+static tree
+tsubst_call_declarator_parms (parms, args, complain, in_decl)
+ tree parms;
+ tree args;
+ int complain;
+ tree in_decl;
+{
+ tree new_parms;
+ tree type;
+ tree defarg;
+
+ if (!parms || parms == void_list_node)
+ return parms;
+
+ new_parms = tsubst_call_declarator_parms (TREE_CHAIN (parms),
+ args, complain, in_decl);
+
+ /* Figure out the type of this parameter. */
+ type = tsubst (TREE_VALUE (parms), args, complain, in_decl);
+
+ /* Figure out the default argument as well. Note that we use
+ tsubst_expr since the default argument is really an expression. */
+ defarg = tsubst_expr (TREE_PURPOSE (parms), args, complain, in_decl);
+
+ /* Chain this parameter on to the front of those we have already
+ processed. We don't use hash_tree_cons because that function
+ doesn't check TREE_PARMLIST. */
+ new_parms = tree_cons (defarg, type, new_parms);
+
+ /* And note that these are parameters. */
+ TREE_PARMLIST (new_parms) = 1;
+
+ return new_parms;
+}
+
+/* Take the tree structure T and replace template parameters used
+ therein with the argument vector ARGS. IN_DECL is an associated
+ decl for diagnostics. If an error occurs, returns ERROR_MARK_NODE.
+ An appropriate error message is issued only if COMPLAIN is
+ non-zero. Note that we must be relatively non-tolerant of
+ extensions here, in order to preserve conformance; if we allow
+ substitutions that should not be allowed, we may allow argument
+ deductions that should not succeed, and therefore report ambiguous
+ overload situations where there are none. In theory, we could
+ allow the substitution, but indicate that it should have failed,
+ and allow our caller to make sure that the right thing happens, but
+ we don't try to do this yet.
+
+ This function is used for dealing with types, decls and the like;
+ for expressions, use tsubst_expr or tsubst_copy. */
+
+tree
+tsubst (t, args, complain, in_decl)
+ tree t, args;
+ int complain;
+ tree in_decl;
+{
+ tree type, r;
+
+ 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;
+
+ 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
+ && TREE_CODE (t) != FUNCTION_TYPE
+ && TREE_CODE (t) != METHOD_TYPE)
+ type = tsubst (type, args, complain, in_decl);
+ if (type == error_mark_node)
+ return error_mark_node;
+
+ if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
+ return tsubst_decl (t, args, type, in_decl);
+
+ switch (TREE_CODE (t))
+ {
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ return tsubst_aggr_type (t, args, complain, in_decl,
+ /*entering_scope=*/0);
+
+ case ERROR_MARK:
+ case IDENTIFIER_NODE:
+ case OP_IDENTIFIER:
+ case VOID_TYPE:
+ case REAL_TYPE:
+ case COMPLEX_TYPE:
+ case BOOLEAN_TYPE:
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ return t;
+
+ case INTEGER_TYPE:
+ if (t == integer_type_node)
+ return t;
+
+ if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
+ && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
+ return t;
{
- tree r = copy_node (t);
- TREE_TYPE (r) = type;
- DECL_CONTEXT (r) = current_class_type;
- TREE_CHAIN (r) = NULL_TREE;
+ tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
+
+ max = tsubst_expr (omax, args, complain, in_decl);
+ if (max == error_mark_node)
+ return error_mark_node;
+
+ if (processing_template_decl
+ /* When providing explicit arguments to a template
+ function, but leaving some arguments for subsequent
+ deduction, MAX may be template-dependent even if we're
+ not PROCESSING_TEMPLATE_DECL. */
+ || TREE_CODE (max) != INTEGER_CST)
+ {
+ return build_index_type (build_min
+ (MINUS_EXPR, sizetype, max, integer_one_node));
+ }
+
+ if (integer_zerop (omax))
+ {
+ /* Still allow an explicit array of size zero. */
+ if (pedantic)
+ pedwarn ("creating array with size zero");
+ }
+ else if (integer_zerop (max) || INT_CST_LT (max, integer_zero_node))
+ {
+ /* [temp.deduct]
+
+ Type deduction may fail for any of the following
+ reasons:
+
+ Attempting to create an array with a size that is
+ zero or negative. */
+ if (complain)
+ cp_error ("creating array with size `%E'", max);
+
+ return error_mark_node;
+ }
+
+ max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node));
+ if (!TREE_PERMANENT (max) && !allocation_temporary_p ())
+ max = copy_to_permanent (max);
+ return build_index_type (max);
+ }
+
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
+ case TEMPLATE_PARM_INDEX:
+ {
+ int idx;
+ int level;
+ int levels;
+
+ r = NULL_TREE;
+
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+ {
+ idx = TEMPLATE_TYPE_IDX (t);
+ level = TEMPLATE_TYPE_LEVEL (t);
+ }
+ else
+ {
+ idx = TEMPLATE_PARM_IDX (t);
+ level = TEMPLATE_PARM_LEVEL (t);
+ }
+
+ if (TREE_VEC_LENGTH (args) > 0)
+ {
+ tree arg = NULL_TREE;
+
+ levels = TMPL_ARGS_DEPTH (args);
+ if (level <= levels)
+ arg = TMPL_ARG (args, level, idx);
+
+ if (arg == error_mark_node)
+ return error_mark_node;
+ else if (arg != NULL_TREE)
+ {
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ {
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
+ == 't', 0);
+ return cp_build_qualified_type
+ (arg, CP_TYPE_QUALS (arg) | CP_TYPE_QUALS (t));
+ }
+ else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+ {
+ if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
+ {
+ /* We are processing a type constructed from
+ a template template parameter */
+ tree argvec = tsubst (TYPE_TI_ARGS (t),
+ args, complain, in_decl);
+ if (argvec == error_mark_node)
+ return error_mark_node;
+
+ /* 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),
+ /*entering_scope=*/0);
+ return cp_build_qualified_type (r, TYPE_QUALS (t));
+ }
+ else
+ /* We are processing a template argument list. */
+ return arg;
+ }
+ else
+ return arg;
+ }
+ }
+ else
+ my_friendly_abort (981018);
+
+ 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
+ && TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
+ {
+ tree argvec = tsubst (TYPE_TI_ARGS (t), args,
+ complain, in_decl);
+ if (argvec == error_mark_node)
+ return error_mark_node;
+
+ TEMPLATE_TEMPLATE_PARM_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 TREE_LIST:
{
tree purpose, value, chain, result;
- int via_public, via_virtual, via_protected;
if (t == void_list_node)
return t;
- via_public = TREE_VIA_PUBLIC (t);
- via_protected = TREE_VIA_PROTECTED (t);
- via_virtual = TREE_VIA_VIRTUAL (t);
-
purpose = TREE_PURPOSE (t);
if (purpose)
- purpose = tsubst (purpose, args, in_decl);
+ {
+ purpose = tsubst (purpose, args, complain, in_decl);
+ if (purpose == error_mark_node)
+ return error_mark_node;
+ }
value = TREE_VALUE (t);
if (value)
- value = tsubst (value, args, in_decl);
+ {
+ value = tsubst (value, args, complain, in_decl);
+ if (value == error_mark_node)
+ return error_mark_node;
+ }
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
- chain = tsubst (chain, args, in_decl);
+ {
+ chain = tsubst (chain, args, complain, in_decl);
+ if (chain == error_mark_node)
+ return error_mark_node;
+ }
if (purpose == TREE_PURPOSE (t)
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
return t;
- result = hash_tree_cons (via_public, via_virtual, via_protected,
- purpose, value, chain);
+ result = hash_tree_cons (purpose, value, chain);
TREE_PARMLIST (result) = TREE_PARMLIST (t);
return result;
}
@@ -4987,19 +6350,29 @@ tsubst (t, args, in_decl)
}
/* Otherwise, a vector of template arguments. */
- return tsubst_template_arg_vector (t, args);
+ return tsubst_template_arg_vector (t, args, complain);
case POINTER_TYPE:
case REFERENCE_TYPE:
{
- tree r;
enum tree_code code;
if (type == TREE_TYPE (t))
return t;
code = TREE_CODE (t);
- if (TREE_CODE (type) == REFERENCE_TYPE)
+
+
+ /* [temp.deduct]
+
+ Type deduction may fail for any of the following
+ reasons:
+
+ -- Attempting to create a pointer to reference type.
+ -- Attempting to create a reference to a reference type or
+ a reference to void. */
+ if (TREE_CODE (type) == REFERENCE_TYPE
+ || (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))
{
static int last_line = 0;
static char* last_file = 0;
@@ -5007,179 +6380,237 @@ tsubst (t, args, in_decl)
/* 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)
+ if (complain && (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);
+ if (TREE_CODE (type) == VOID_TYPE)
+ cp_error ("forming reference to void");
+ else
+ cp_error ("forming %s to reference type `%T'",
+ (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));
+ return error_mark_node;
}
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));
+ r = cp_build_qualified_type (r, TYPE_QUALS (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, in_decl), type);
+ {
+ r = tsubst (TYPE_OFFSET_BASETYPE (t), args, complain, in_decl);
+ if (r == error_mark_node || !IS_AGGR_TYPE (r))
+ {
+ /* [temp.deduct]
+
+ Type deduction may fail for any of the following
+ reasons:
+
+ -- Attempting to create "pointer to member of T" when T
+ is not a class type. */
+ if (complain)
+ cp_error ("creating pointer to member of non-class type `%T'",
+ r);
+ return error_mark_node;
+ }
+ return build_offset_type (r, type);
+ }
case FUNCTION_TYPE:
case METHOD_TYPE:
{
- tree values = TYPE_ARG_TYPES (t);
- tree context = TYPE_CONTEXT (t);
- tree raises = TYPE_RAISES_EXCEPTIONS (t);
tree fntype;
+ tree raises;
- /* Don't bother recursing if we know it won't change anything. */
- if (values != void_list_node)
- {
- /* 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, in_decl);
- /* Could also optimize cases where return value and
- values have common elements (e.g., T min(const &T, const T&). */
-
- /* If the above parameters haven't changed, just return the type. */
- if (type == TREE_TYPE (t)
- && values == TYPE_VALUES (t)
- && context == TYPE_CONTEXT (t))
- return t;
+ fntype = tsubst_function_type (t, args, complain, in_decl);
+ if (fntype == error_mark_node)
+ return error_mark_node;
- /* Construct a new type node and return it. */
- if (TREE_CODE (t) == FUNCTION_TYPE
- && context == NULL_TREE)
- {
- fntype = build_function_type (type, values);
- }
- else if (context == NULL_TREE)
- {
- tree base = tsubst (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))),
- args, in_decl);
- fntype = build_cplus_method_type (base, type,
- TREE_CHAIN (values));
- }
- else
- {
- 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 (fntype) = tsubst (TYPE_METHOD_BASETYPE (t),
- args, in_decl);
- /* Need to generate hash value. */
- my_friendly_abort (84);
- }
- fntype = build_type_variant (fntype,
- TYPE_READONLY (t),
- TYPE_VOLATILE (t));
+ /* Substitue the exception specification. */
+ raises = TYPE_RAISES_EXCEPTIONS (t);
if (raises)
{
- raises = tsubst (raises, args, in_decl);
+ raises = tsubst (raises, args, complain, in_decl);
+ if (raises == error_mark_node)
+ return raises;
fntype = build_exception_variant (fntype, raises);
}
return fntype;
}
case ARRAY_TYPE:
{
- tree domain = tsubst (TYPE_DOMAIN (t), args, in_decl);
- tree r;
+ tree domain = tsubst (TYPE_DOMAIN (t), args, complain, in_decl);
+ if (domain == error_mark_node)
+ return error_mark_node;
+
+ /* As an optimization, we avoid regenerating the array type if
+ it will obviously be the same as T. */
if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t))
return t;
+
+ /* These checks should match the ones in grokdeclarator.
+
+ [temp.deduct]
+
+ The deduction may fail for any of the following reasons:
+
+ -- Attempting to create an array with an element type that
+ is void, a function type, or a reference type. */
+ if (TREE_CODE (type) == VOID_TYPE
+ || TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ if (complain)
+ cp_error ("creating array of `%T'", type);
+ return error_mark_node;
+ }
+
r = build_cplus_array_type (type, domain);
return r;
}
case PLUS_EXPR:
case MINUS_EXPR:
- return fold (build (TREE_CODE (t), TREE_TYPE (t),
- tsubst (TREE_OPERAND (t, 0), args, in_decl),
- tsubst (TREE_OPERAND (t, 1), args, in_decl)));
+ {
+ tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ tree e2 = tsubst (TREE_OPERAND (t, 1), args, complain,
+ in_decl);
+
+ if (e1 == error_mark_node || e2 == error_mark_node)
+ return error_mark_node;
+
+ return fold (build (TREE_CODE (t), TREE_TYPE (t), e1, e2));
+ }
case NEGATE_EXPR:
case NOP_EXPR:
- return fold (build1 (TREE_CODE (t), TREE_TYPE (t),
- tsubst (TREE_OPERAND (t, 0), args, in_decl)));
+ {
+ tree e = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ if (e == error_mark_node)
+ return error_mark_node;
+
+ return fold (build (TREE_CODE (t), TREE_TYPE (t), e));
+ }
case TYPENAME_TYPE:
{
- tree ctx = tsubst (TYPE_CONTEXT (t), args, in_decl);
- tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args, in_decl);
+ tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
+ in_decl, /*entering_scope=*/1);
+ tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args,
+ complain, in_decl);
+
+ if (ctx == error_mark_node || f == error_mark_node)
+ return error_mark_node;
+
+ if (!IS_AGGR_TYPE (ctx))
+ {
+ if (complain)
+ cp_error ("`%T' is not a class, struct, or union type",
+ ctx);
+ return error_mark_node;
+ }
+ else if (!uses_template_parms (ctx) && !TYPE_BEING_DEFINED (ctx))
+ {
+ /* Normally, make_typename_type does not require that the CTX
+ have complete type in order to allow things like:
+
+ template <class T> struct S { typename S<T>::X Y; };
+
+ But, such constructs have already been resolved by this
+ point, so here CTX really should have complete type, unless
+ it's a partial instantiation. */
+ ctx = complete_type (ctx);
+ if (!TYPE_SIZE (ctx))
+ {
+ if (complain)
+ incomplete_type_error (NULL_TREE, ctx);
+ return error_mark_node;
+ }
+ }
+
f = make_typename_type (ctx, f);
- return cp_build_type_variant
- (f, TYPE_READONLY (f) || TYPE_READONLY (t),
- TYPE_VOLATILE (f) || TYPE_VOLATILE (t));
+ if (f == error_mark_node)
+ return f;
+ return cp_build_qualified_type (f,
+ CP_TYPE_QUALS (f)
+ | CP_TYPE_QUALS (t));
}
case INDIRECT_REF:
- return make_pointer_declarator
- (type, tsubst (TREE_OPERAND (t, 0), args, in_decl));
-
+ {
+ tree e = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ if (e == error_mark_node)
+ return error_mark_node;
+ return make_pointer_declarator (type, e);
+ }
+
case ADDR_EXPR:
- return make_reference_declarator
- (type, tsubst (TREE_OPERAND (t, 0), args, in_decl));
+ {
+ tree e = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ if (e == error_mark_node)
+ return error_mark_node;
+ return make_reference_declarator (type, e);
+ }
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));
+ {
+ tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain,
+ in_decl);
+ if (e1 == error_mark_node || e2 == error_mark_node)
+ return error_mark_node;
+
+ return build_parse_node (ARRAY_REF, e1, e2, tsubst_expr);
+ }
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));
+ {
+ tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ tree e2 = tsubst_call_declarator_parms (TREE_OPERAND (t, 1), args,
+ complain, in_decl);
+ tree e3 = tsubst (TREE_TYPE (t), args, complain, in_decl);
+
+ if (e1 == error_mark_node || e2 == error_mark_node
+ || e3 == error_mark_node)
+ return error_mark_node;
+
+ return make_call_declarator (e1, e2, TREE_OPERAND (t, 2), e3);
+ }
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));
+ {
+ tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ tree e2 = tsubst (TREE_OPERAND (t, 1), args, complain, in_decl);
+ if (e1 == error_mark_node || e2 == error_mark_node)
+ return error_mark_node;
+
+ return build_parse_node (TREE_CODE (t), e1, e2);
+ }
+
+ case TYPEOF_TYPE:
+ {
+ tree e1 = tsubst_expr (TYPE_FIELDS (t), args, complain,
+ in_decl);
+ if (e1 == error_mark_node)
+ return error_mark_node;
+
+ return TREE_TYPE (e1);
+ }
default:
sorry ("use of `%s' in template",
@@ -5222,11 +6653,13 @@ do_poplevel ()
tsubst_expr. */
tree
-tsubst_copy (t, args, in_decl)
+tsubst_copy (t, args, complain, in_decl)
tree t, args;
+ int complain;
tree in_decl;
{
enum tree_code code;
+ tree r;
if (t == NULL_TREE || t == error_mark_node)
return t;
@@ -5239,14 +6672,48 @@ tsubst_copy (t, args, in_decl)
return do_identifier (DECL_NAME (t), 0, NULL_TREE);
case CONST_DECL:
+ {
+ tree enum_type;
+ tree v;
+
+ if (!DECL_CONTEXT (t))
+ /* This is a global enumeration constant. */
+ return t;
+
+ /* Unfortunately, we cannot just call lookup_name here.
+ Consider:
+
+ template <int I> int f() {
+ enum E { a = I };
+ struct S { void g() { E e = a; } };
+ };
+
+ When we instantiate f<7>::S::g(), say, lookup_name is not
+ clever enough to find f<7>::a. */
+ enum_type
+ = tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl,
+ /*entering_scope=*/0);
+
+ for (v = TYPE_VALUES (enum_type);
+ v != NULL_TREE;
+ v = TREE_CHAIN (v))
+ if (TREE_PURPOSE (v) == DECL_NAME (t))
+ return TREE_VALUE (v);
+
+ /* We didn't find the name. That should never happen; if
+ name-lookup found it during preliminary parsing, we
+ should find it again here during instantiation. */
+ my_friendly_abort (0);
+ }
+ return t;
+
case FIELD_DECL:
if (DECL_CONTEXT (t))
{
tree ctx;
- if (TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
- return lookup_name (DECL_NAME (t), 0);
- ctx = tsubst (DECL_CONTEXT (t), args, in_decl);
+ ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, complain, in_decl,
+ /*entering_scope=*/1);
if (ctx != DECL_CONTEXT (t))
return lookup_field (ctx, DECL_NAME (t), 0, 0);
}
@@ -5255,29 +6722,44 @@ tsubst_copy (t, args, in_decl)
case VAR_DECL:
case FUNCTION_DECL:
if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
- t = tsubst (t, args, in_decl);
+ t = tsubst (t, args, complain, in_decl);
mark_used (t);
return t;
case TEMPLATE_DECL:
if (is_member_template (t))
- return tsubst (t, args, in_decl);
+ return tsubst (t, args, complain, in_decl);
else
return t;
-#if 0
- case IDENTIFIER_NODE:
- return do_identifier (t, 0);
-#endif
-
+ case LOOKUP_EXPR:
+ {
+ /* We must tsbust into a LOOKUP_EXPR in case the names to
+ which it refers is a conversion operator; in that case the
+ name will change. We avoid making unnecessary copies,
+ however. */
+
+ tree id = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+
+ if (id != TREE_OPERAND (t, 0))
+ {
+ r = build_nt (LOOKUP_EXPR, id);
+ LOOKUP_EXPR_GLOBAL (r) = LOOKUP_EXPR_GLOBAL (t);
+ t = r;
+ }
+
+ return t;
+ }
+
case CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
case DYNAMIC_CAST_EXPR:
+ case NOP_EXPR:
return build1
- (code, tsubst (TREE_TYPE (t), args, in_decl),
- tsubst_copy (TREE_OPERAND (t, 0), args, in_decl));
+ (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
case INDIRECT_REF:
case PREDECREMENT_EXPR:
@@ -5295,8 +6777,8 @@ tsubst_copy (t, args, in_decl)
case THROW_EXPR:
case TYPEID_EXPR:
return build1
- (code, NULL_TREE,
- tsubst_copy (TREE_OPERAND (t, 0), args, in_decl));
+ (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
case PLUS_EXPR:
case MINUS_EXPR:
@@ -5335,19 +6817,20 @@ tsubst_copy (t, args, in_decl)
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));
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
case CALL_EXPR:
{
tree fn = TREE_OPERAND (t, 0);
if (is_overloaded_fn (fn))
- fn = tsubst_copy (get_first_fn (fn), args, in_decl);
+ fn = tsubst_copy (get_first_fn (fn), args, complain, in_decl);
else
/* Sometimes FN is a LOOKUP_EXPR. */
- fn = tsubst_copy (fn, args, in_decl);
+ fn = tsubst_copy (fn, args, complain, in_decl);
return build_nt
- (code, fn, tsubst_copy (TREE_OPERAND (t, 1), args, in_decl),
+ (code, fn, tsubst_copy (TREE_OPERAND (t, 1), args, complain,
+ in_decl),
NULL_TREE);
}
@@ -5356,23 +6839,27 @@ tsubst_copy (t, args, in_decl)
tree name = TREE_OPERAND (t, 0);
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
- name = tsubst_copy (TREE_OPERAND (name, 0), args, in_decl);
+ name = tsubst_copy (TREE_OPERAND (name, 0), args,
+ complain, 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);
+ tree base = tsubst_copy (TREE_OPERAND (name, 0), args,
+ complain, in_decl);
name = TREE_OPERAND (name, 1);
- name = tsubst_copy (TREE_OPERAND (name, 0), args, in_decl);
+ name = tsubst_copy (TREE_OPERAND (name, 0), args,
+ complain, 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);
+ name = tsubst_copy (TREE_OPERAND (t, 0), args, complain, 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),
+ (code, name, tsubst_copy (TREE_OPERAND (t, 1), args,
+ complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl),
NULL_TREE);
}
@@ -5380,21 +6867,22 @@ tsubst_copy (t, args, in_decl)
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));
+ r = build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
if (code == BIND_EXPR && !processing_template_decl)
{
- /* This processing should really occur in tsubst_expr,
+ /* 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);
+ tree block = tsubst_expr (TREE_OPERAND (r, 1), args,
+ complain, in_decl);
r = finish_stmt_expr (rtl_expr, block);
}
@@ -5403,19 +6891,19 @@ tsubst_copy (t, args, in_decl)
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));
+ r = build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
NEW_EXPR_USE_GLOBAL (r) = NEW_EXPR_USE_GLOBAL (t);
return r;
}
case DELETE_EXPR:
{
- tree r = build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, in_decl));
+ r = build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
DELETE_EXPR_USE_GLOBAL (r) = DELETE_EXPR_USE_GLOBAL (t);
DELETE_EXPR_USE_VEC (r) = DELETE_EXPR_USE_VEC (t);
return r;
@@ -5424,13 +6912,25 @@ tsubst_copy (t, args, in_decl)
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));
+ tree targs = tsubst_copy (TREE_OPERAND (t, 1), args, complain,
+ in_decl);
+
+ if (targs && TREE_CODE (targs) == TREE_LIST)
+ {
+ tree chain;
+ for (chain = targs; chain; chain = TREE_CHAIN (chain))
+ TREE_VALUE (chain) = maybe_fold_nontype_arg (TREE_VALUE (chain));
+ }
+ else if (targs)
+ {
+ int i;
+ for (i = 0; i < TREE_VEC_LENGTH (targs); ++i)
+ TREE_VEC_ELT (targs, i)
+ = maybe_fold_nontype_arg (TREE_VEC_ELT (targs, i));
+ }
return lookup_template_function
- (tsubst_copy (TREE_OPERAND (t, 0), args, in_decl), targs);
+ (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl), targs);
}
case TREE_LIST:
@@ -5442,13 +6942,13 @@ tsubst_copy (t, args, in_decl)
purpose = TREE_PURPOSE (t);
if (purpose)
- purpose = tsubst_copy (purpose, args, in_decl);
+ purpose = tsubst_copy (purpose, args, complain, in_decl);
value = TREE_VALUE (t);
if (value)
- value = tsubst_copy (value, args, in_decl);
+ value = tsubst_copy (value, args, complain, in_decl);
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
- chain = tsubst_copy (chain, args, in_decl);
+ chain = tsubst_copy (chain, args, complain, in_decl);
if (purpose == TREE_PURPOSE (t)
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
@@ -5471,19 +6971,27 @@ tsubst_copy (t, args, in_decl)
case ARRAY_TYPE:
case TYPENAME_TYPE:
case TYPE_DECL:
- return tsubst (t, args, in_decl);
+ return tsubst (t, args, complain, in_decl);
case IDENTIFIER_NODE:
- if (IDENTIFIER_TYPENAME_P (t))
+ if (IDENTIFIER_TYPENAME_P (t)
+ /* Make sure it's not just a variable named `__opr', for instance,
+ which can occur in some existing code. */
+ && TREE_TYPE (t))
return build_typename_overload
- (tsubst (TREE_TYPE (t), args, in_decl));
+ (tsubst (TREE_TYPE (t), args, complain, 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));
+ {
+ r = build
+ (CONSTRUCTOR, tsubst (TREE_TYPE (t), args, complain, in_decl),
+ NULL_TREE, tsubst_copy (CONSTRUCTOR_ELTS (t), args,
+ complain, in_decl));
+ TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
+ return r;
+ }
default:
return t;
@@ -5493,28 +7001,29 @@ tsubst_copy (t, args, in_decl)
/* Like tsubst_copy, but also does semantic processing and RTL expansion. */
tree
-tsubst_expr (t, args, in_decl)
+tsubst_expr (t, args, complain, in_decl)
tree t, args;
+ int complain;
tree in_decl;
{
if (t == NULL_TREE || t == error_mark_node)
return t;
if (processing_template_decl)
- return tsubst_copy (t, args, in_decl);
+ return tsubst_copy (t, args, complain, in_decl);
switch (TREE_CODE (t))
{
case RETURN_STMT:
lineno = TREE_COMPLEXITY (t);
finish_return_stmt (tsubst_expr (RETURN_EXPR (t),
- args, in_decl));
+ args, complain, in_decl));
break;
case EXPR_STMT:
lineno = TREE_COMPLEXITY (t);
finish_expr_stmt (tsubst_expr (EXPR_STMT_EXPR (t),
- args, in_decl));
+ args, complain, in_decl));
break;
case DECL_STMT:
@@ -5525,10 +7034,10 @@ tsubst_expr (t, args, in_decl)
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),
+ (tsubst (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst (TREE_OPERAND (t, 1), args, complain, in_decl),
TREE_OPERAND (t, 2) != 0, NULL_TREE, NULL_TREE);
- init = tsubst_expr (TREE_OPERAND (t, 2), args, in_decl);
+ init = tsubst_expr (TREE_OPERAND (t, 2), args, complain, in_decl);
cp_finish_decl
(dcl, init, NULL_TREE, 1, /*init ? LOOKUP_ONLYCONVERTING :*/ 0);
resume_momentary (i);
@@ -5542,14 +7051,14 @@ tsubst_expr (t, args, in_decl)
begin_for_stmt ();
for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
- tsubst_expr (tmp, args, in_decl);
+ tsubst_expr (tmp, args, complain, in_decl);
finish_for_init_stmt (NULL_TREE);
finish_for_cond (tsubst_expr (FOR_COND (t), args,
- in_decl),
+ complain, in_decl),
NULL_TREE);
- tmp = tsubst_expr (FOR_EXPR (t), args, in_decl);
+ tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
finish_for_expr (tmp, NULL_TREE);
- tsubst_expr (FOR_BODY (t), args, in_decl);
+ tsubst_expr (FOR_BODY (t), args, complain, in_decl);
finish_for_stmt (tmp, NULL_TREE);
}
break;
@@ -5559,9 +7068,9 @@ tsubst_expr (t, args, in_decl)
lineno = TREE_COMPLEXITY (t);
begin_while_stmt ();
finish_while_stmt_cond (tsubst_expr (WHILE_COND (t),
- args, in_decl),
+ args, complain, in_decl),
NULL_TREE);
- tsubst_expr (WHILE_BODY (t), args, in_decl);
+ tsubst_expr (WHILE_BODY (t), args, complain, in_decl);
finish_while_stmt (NULL_TREE);
}
break;
@@ -5570,10 +7079,10 @@ tsubst_expr (t, args, in_decl)
{
lineno = TREE_COMPLEXITY (t);
begin_do_stmt ();
- tsubst_expr (DO_BODY (t), args, in_decl);
+ tsubst_expr (DO_BODY (t), args, complain, in_decl);
finish_do_body (NULL_TREE);
finish_do_stmt (tsubst_expr (DO_COND (t), args,
- in_decl),
+ complain, in_decl),
NULL_TREE);
}
break;
@@ -5585,19 +7094,19 @@ tsubst_expr (t, args, in_decl)
lineno = TREE_COMPLEXITY (t);
begin_if_stmt ();
finish_if_stmt_cond (tsubst_expr (IF_COND (t),
- args, in_decl),
+ args, complain, in_decl),
NULL_TREE);
if (tmp = THEN_CLAUSE (t), tmp)
{
- tsubst_expr (tmp, args, in_decl);
+ tsubst_expr (tmp, args, complain, in_decl);
finish_then_clause (NULL_TREE);
}
if (tmp = ELSE_CLAUSE (t), tmp)
{
begin_else_clause ();
- tsubst_expr (tmp, args, in_decl);
+ tsubst_expr (tmp, args, complain, in_decl);
finish_else_clause (NULL_TREE);
}
@@ -5614,7 +7123,7 @@ tsubst_expr (t, args, in_decl)
for (substmt = COMPOUND_BODY (t);
substmt != NULL_TREE;
substmt = TREE_CHAIN (substmt))
- tsubst_expr (substmt, args, in_decl);
+ tsubst_expr (substmt, args, complain, in_decl);
return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
NULL_TREE);
}
@@ -5636,19 +7145,19 @@ tsubst_expr (t, args, in_decl)
lineno = TREE_COMPLEXITY (t);
begin_switch_stmt ();
- val = tsubst_expr (SWITCH_COND (t), args, in_decl);
+ val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
finish_switch_cond (val);
if (tmp = TREE_OPERAND (t, 1), tmp)
- tsubst_expr (tmp, args, in_decl);
+ tsubst_expr (tmp, args, complain, 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));
+ finish_case_label (tsubst_expr (CASE_LOW (t), args, complain, in_decl),
+ tsubst_expr (CASE_HIGH (t), args, complain, in_decl));
break;
case LABEL_DECL:
@@ -5665,28 +7174,29 @@ tsubst_expr (t, args, in_decl)
/* 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);
+ t = tsubst_expr (t, args, complain, 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));
+ finish_asm_stmt (tsubst_expr (ASM_CV_QUAL (t), args, complain, in_decl),
+ tsubst_expr (ASM_STRING (t), args, complain, in_decl),
+ tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl),
+ tsubst_expr (ASM_INPUTS (t), args, complain, in_decl),
+ tsubst_expr (ASM_CLOBBERS (t), args, complain,
+ in_decl));
break;
case TRY_BLOCK:
lineno = TREE_COMPLEXITY (t);
begin_try_block ();
- tsubst_expr (TRY_STMTS (t), args, in_decl);
+ tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
finish_try_block (NULL_TREE);
{
tree handler = TRY_HANDLERS (t);
for (; handler; handler = TREE_CHAIN (handler))
- tsubst_expr (handler, args, in_decl);
+ tsubst_expr (handler, args, complain, in_decl);
}
finish_handler_sequence (NULL_TREE);
break;
@@ -5698,13 +7208,13 @@ tsubst_expr (t, args, in_decl)
{
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));
+ (tsubst (TREE_OPERAND (d, 1), args, complain, in_decl),
+ tsubst (TREE_OPERAND (d, 0), args, complain, in_decl));
}
else
expand_start_catch_block (NULL_TREE, NULL_TREE);
finish_handler_parms (NULL_TREE);
- tsubst_expr (HANDLER_BODY (t), args, in_decl);
+ tsubst_expr (HANDLER_BODY (t), args, complain, in_decl);
finish_handler (NULL_TREE);
break;
@@ -5712,67 +7222,86 @@ tsubst_expr (t, args, in_decl)
lineno = TREE_COMPLEXITY (t);
t = TREE_TYPE (t);
if (TREE_CODE (t) == ENUMERAL_TYPE)
- tsubst_enum (t, args, NULL);
+ tsubst (t, args, complain, NULL_TREE);
break;
default:
- return build_expr_from_tree (tsubst_copy (t, args, in_decl));
+ return build_expr_from_tree (tsubst_copy (t, args, complain, in_decl));
}
return NULL_TREE;
}
+/* Instantiate the indicated variable or function template TMPL with
+ the template arguments in TARG_PTR. */
+
tree
instantiate_template (tmpl, targ_ptr)
tree tmpl, targ_ptr;
{
tree fndecl;
+ tree gen_tmpl;
+ tree spec;
int i, len;
struct obstack *old_fmp_obstack;
extern struct obstack *function_maybepermanent_obstack;
+ tree inner_args;
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))
+ /* Check to see if we already have this specialization. */
+ spec = retrieve_specialization (tmpl, targ_ptr);
+ if (spec != NULL_TREE)
+ return spec;
+
+ if (DECL_TEMPLATE_INFO (tmpl))
{
- tree spec = retrieve_specialization (tmpl, targ_ptr);
-
+ /* The TMPL is a partial instantiation. To get a full set of
+ arguments we must add the arguments used to perform the
+ partial instantiation. */
+ targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl),
+ targ_ptr);
+ gen_tmpl = most_general_template (tmpl);
+
+ /* Check to see if we already have this specialization. */
+ spec = retrieve_specialization (gen_tmpl, targ_ptr);
if (spec != NULL_TREE)
return spec;
}
+ else
+ gen_tmpl = tmpl;
push_obstacks (&permanent_obstack, &permanent_obstack);
old_fmp_obstack = function_maybepermanent_obstack;
function_maybepermanent_obstack = &permanent_obstack;
- len = DECL_NTPARMS (tmpl);
-
+ len = DECL_NTPARMS (gen_tmpl);
+ inner_args = innermost_args (targ_ptr);
i = len;
while (i--)
{
- tree t = TREE_VEC_ELT (targ_ptr, i);
+ tree t = TREE_VEC_ELT (inner_args, 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);
+ cp_error (" trying to instantiate `%D'", gen_tmpl);
fndecl = error_mark_node;
goto out;
}
}
- TREE_VEC_ELT (targ_ptr, i) = copy_to_permanent (t);
}
targ_ptr = copy_to_permanent (targ_ptr);
/* substitute template parameters */
- fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, tmpl);
+ fndecl = tsubst (DECL_RESULT (gen_tmpl), targ_ptr, /*complain=*/1, gen_tmpl);
+ /* The DECL_TI_TEMPLATE should always be the immediate parent
+ template, not the most general template. */
+ DECL_TI_TEMPLATE (fndecl) = tmpl;
if (flag_external_templates)
add_pending_template (fndecl);
@@ -5802,76 +7331,18 @@ overload_template_name (type)
pushdecl_class_level (decl);
}
-/* 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 parms;
-
- my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
-
- parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
-
- if (IDENTIFIER_TYPENAME_P (DECL_NAME (fn)))
- {
- /* 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);
- }
-
- 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);
-}
-
-
-/* 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.
+/* The FN is a TEMPLATE_DECL for a function. The ARGS are the
+ arguments that are being used when calling it. TARGS is a vector
+ into which the deduced template arguments are placed.
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.
+ If FN is a conversion operator, RETURN_TYPE is the type desired as
+ the result of the conversion operator.
- 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.
+ TPARMS is a vector of template parameters.
The EXPLICIT_TARGS are explicit template arguments provided via a
template-id.
@@ -5893,49 +7364,79 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
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]. */
+ template, as in [temp.deduct.funcaddr].
+
+ The other arguments are as for type_unification. */
int
-type_unification (tparms, targs, parms, args, explicit_targs,
- strict, allow_incomplete)
- tree tparms, targs, parms, args, explicit_targs;
+fn_type_unification (fn, explicit_targs, targs, args, return_type,
+ strict)
+ tree fn, explicit_targs, targs, args, return_type;
unification_kind_t strict;
- int allow_incomplete;
{
- int* explicit_mask;
- int i;
-
- for (i = 0; i < TREE_VEC_LENGTH (tparms); i++)
- TREE_VEC_ELT (targs, i) = NULL_TREE;
+ tree parms;
+ tree fntype;
- if (explicit_targs != NULL_TREE)
+ my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
+
+ fntype = TREE_TYPE (fn);
+ if (explicit_targs)
{
- tree arg_vec;
- arg_vec = coerce_template_parms (tparms, explicit_targs, NULL_TREE, 0,
- 0);
+ /* [temp.deduct]
+
+ The specified template arguments must match the template
+ parameters in kind (i.e., type, nontype, template), and there
+ must not be more arguments than there are parameters;
+ otherwise type deduction fails.
+
+ Nontype arguments must match the types of the corresponding
+ nontype template parameters, or must be convertible to the
+ types of the corresponding nontype parameters as specified in
+ _temp.arg.nontype_, otherwise type deduction fails.
+
+ All references in the function type of the function template
+ to the corresponding template parameters are replaced by the
+ specified template argument values. If a substitution in a
+ template parameter or in the function type of the function
+ template results in an invalid type, type deduction fails. */
+ int i;
+ tree converted_args;
- if (arg_vec == error_mark_node)
+ converted_args
+ = (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ explicit_targs, NULL_TREE, /*complain=*/0,
+ /*require_all_arguments=*/0));
+ if (converted_args == error_mark_node)
return 1;
- explicit_mask = alloca (sizeof (int) * TREE_VEC_LENGTH (targs));
- bzero ((char *) explicit_mask, sizeof(int) * TREE_VEC_LENGTH (targs));
+ fntype = tsubst (fntype, converted_args, /*complain=*/0, NULL_TREE);
+ if (fntype == error_mark_node)
+ return 1;
- 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;
- }
+ /* Place the explicitly specified arguments in TARGS. */
+ for (i = 0; i < TREE_VEC_LENGTH (targs); i++)
+ TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (converted_args, i);
+ }
+
+ parms = TYPE_ARG_TYPES (fntype);
+
+ if (DECL_CONV_FN_P (fn))
+ {
+ /* This is a template conversion operator. Use the return types
+ as well as the argument types. We use it instead of 'this', since
+ we could be comparing conversions from different classes. */
+ parms = scratch_tree_cons (NULL_TREE, TREE_TYPE (fntype),
+ TREE_CHAIN (parms));
+ args = scratch_tree_cons (NULL_TREE, return_type, TREE_CHAIN (args));
}
- else
- explicit_mask = 0;
- return
- type_unification_real (tparms, targs, parms, args, 0,
- strict, allow_incomplete, explicit_mask);
+ /* 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_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ targs, parms, args, /*subr=*/0,
+ strict, /*allow_incomplete*/1);
}
/* Adjust types before performing type deduction, as described in
@@ -5945,7 +7446,7 @@ type_unification (tparms, targs, parms, args, explicit_targs,
the argument passed to the call, or the type of the value
intialized with the result of the conversion function. */
-void
+static void
maybe_adjust_types_for_deduction (strict, parm, arg)
unification_kind_t strict;
tree* parm;
@@ -5995,8 +7496,7 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
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)
+ else if (TREE_CODE (*arg) == FUNCTION_TYPE)
*arg = build_pointer_type (*arg);
else
*arg = TYPE_MAIN_VARIANT (*arg);
@@ -6013,9 +7513,7 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
*parm = TREE_TYPE (*parm);
}
-/* 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.
+/* Like type_unfication.
If SUBR is 1, we're being called recursively (to unify the
arguments of a function or method parameter of a function
@@ -6023,12 +7521,11 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
static int
type_unification_real (tparms, targs, parms, args, subr,
- strict, allow_incomplete, explicit_mask)
+ strict, allow_incomplete)
tree tparms, targs, parms, args;
int subr;
unification_kind_t strict;
int allow_incomplete;
- int* explicit_mask;
{
tree parm, arg;
int i;
@@ -6075,7 +7572,9 @@ type_unification_real (tparms, targs, parms, args, subr,
if (arg == error_mark_node)
return 1;
if (arg == unknown_type_node)
- return 1;
+ /* We can't deduce anything from this, but we might get all the
+ template args from other function args. */
+ continue;
/* Conversions will be performed on a function argument that
corresponds with a function parameter that contains only
@@ -6095,7 +7594,7 @@ type_unification_real (tparms, targs, parms, args, subr,
if (strict == DEDUCE_EXACT)
{
- if (comptypes (parm, type, 1))
+ if (same_type_p (parm, type))
continue;
}
else
@@ -6107,47 +7606,30 @@ type_unification_real (tparms, targs, parms, args, subr,
return 1;
}
-#if 0
- if (TREE_CODE (arg) == VAR_DECL)
- arg = TREE_TYPE (arg);
- else if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'e')
- arg = TREE_TYPE (arg);
-#else
if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
{
my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293);
- if (TREE_CODE (arg) == OVERLOAD
- && TREE_CODE (OVL_FUNCTION (arg)) == TEMPLATE_DECL)
+ if (type_unknown_p (arg))
{
- tree targs;
- tree arg_type;
-
- /* Have to back unify here */
- 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);
+ /* [temp.deduct.type] A template-argument can be deduced from
+ a pointer to function or pointer to member function
+ argument if the set of overloaded functions does not
+ contain function templates and at most one of a set of
+ overloaded functions provides a unique match. */
+
+ if (resolve_overloaded_unification
+ (tparms, targs, parm, arg, strict, sub_strict)
+ != 0)
+ return 1;
+ continue;
}
arg = TREE_TYPE (arg);
}
-#endif
- if (! flag_ansi && arg == TREE_TYPE (null_node))
- {
- warning ("using type void* for NULL");
- arg = ptr_type_node;
- }
if (!subr)
maybe_adjust_types_for_deduction (strict, &parm, &arg);
- switch (unify (tparms, targs, parm, arg, sub_strict,
- explicit_mask))
+ switch (unify (tparms, targs, parm, arg, sub_strict))
{
case 0:
break;
@@ -6175,9 +7657,341 @@ type_unification_real (tparms, targs, parms, args, subr,
return 0;
}
+/* Subroutine of type_unification_real. Args are like the variables at the
+ call site. ARG is an overloaded function (or template-id); we try
+ deducing template args from each of the overloads, and if only one
+ succeeds, we go with that. Modifies TARGS and returns 0 on success. */
+
+static int
+resolve_overloaded_unification (tparms, targs, parm, arg, strict,
+ sub_strict)
+ tree tparms, targs, parm, arg;
+ unification_kind_t strict;
+ int sub_strict;
+{
+ tree tempargs = copy_node (targs);
+ int good = 0;
+
+ if (TREE_CODE (arg) == ADDR_EXPR)
+ arg = TREE_OPERAND (arg, 0);
+
+ if (TREE_CODE (arg) == COMPONENT_REF)
+ /* Handle `&x' where `x' is some static or non-static member
+ function name. */
+ arg = TREE_OPERAND (arg, 1);
+
+ if (TREE_CODE (arg) == OFFSET_REF)
+ arg = TREE_OPERAND (arg, 1);
+
+ /* Strip baselink information. */
+ while (TREE_CODE (arg) == TREE_LIST)
+ arg = TREE_VALUE (arg);
+
+ if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
+ {
+ /* If we got some explicit template args, we need to plug them into
+ the affected templates before we try to unify, in case the
+ explicit args will completely resolve the templates in question. */
+
+ tree expl_subargs = TREE_OPERAND (arg, 1);
+ arg = TREE_OPERAND (arg, 0);
+
+ for (; arg; arg = OVL_NEXT (arg))
+ {
+ tree fn = OVL_CURRENT (arg);
+ tree subargs, elem;
+
+ if (TREE_CODE (fn) != TEMPLATE_DECL)
+ continue;
+
+ subargs = get_bindings_overload (fn, DECL_RESULT (fn), expl_subargs);
+ if (subargs)
+ {
+ elem = tsubst (TREE_TYPE (fn), subargs, /*complain=*/0,
+ NULL_TREE);
+ if (TREE_CODE (elem) == METHOD_TYPE)
+ elem = build_ptrmemfunc_type (build_pointer_type (elem));
+ good += try_one_overload (tparms, targs, tempargs, parm, elem,
+ strict, sub_strict);
+ }
+ }
+ }
+ else if (TREE_CODE (arg) == OVERLOAD)
+ {
+ for (; arg; arg = OVL_NEXT (arg))
+ {
+ tree type = TREE_TYPE (OVL_CURRENT (arg));
+ if (TREE_CODE (type) == METHOD_TYPE)
+ type = build_ptrmemfunc_type (build_pointer_type (type));
+ good += try_one_overload (tparms, targs, tempargs, parm,
+ type,
+ strict, sub_strict);
+ }
+ }
+ else
+ my_friendly_abort (981006);
+
+ /* [temp.deduct.type] A template-argument can be deduced from a pointer
+ to function or pointer to member function argument if the set of
+ overloaded functions does not contain function templates and at most
+ one of a set of overloaded functions provides a unique match.
+
+ So if we found multiple possibilities, we return success but don't
+ deduce anything. */
+
+ if (good == 1)
+ {
+ int i = TREE_VEC_LENGTH (targs);
+ for (; i--; )
+ if (TREE_VEC_ELT (tempargs, i))
+ TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (tempargs, i);
+ }
+ if (good)
+ return 0;
+
+ return 1;
+}
+
+/* Subroutine of resolve_overloaded_unification; does deduction for a single
+ overload. Fills TARGS with any deduced arguments, or error_mark_node if
+ different overloads deduce different arguments for a given parm.
+ Returns 1 on success. */
+
+static int
+try_one_overload (tparms, orig_targs, targs, parm, arg, strict,
+ sub_strict)
+ tree tparms, orig_targs, targs, parm, arg;
+ unification_kind_t strict;
+ int sub_strict;
+{
+ int nargs;
+ tree tempargs;
+ int i;
+
+ /* [temp.deduct.type] A template-argument can be deduced from a pointer
+ to function or pointer to member function argument if the set of
+ overloaded functions does not contain function templates and at most
+ one of a set of overloaded functions provides a unique match.
+
+ So if this is a template, just return success. */
+
+ if (uses_template_parms (arg))
+ return 1;
+
+ maybe_adjust_types_for_deduction (strict, &parm, &arg);
+
+ /* We don't copy orig_targs for this because if we have already deduced
+ some template args from previous args, unify would complain when we
+ try to deduce a template parameter for the same argument, even though
+ there isn't really a conflict. */
+ nargs = TREE_VEC_LENGTH (targs);
+ tempargs = make_scratch_vec (nargs);
+
+ if (unify (tparms, tempargs, parm, arg, sub_strict) != 0)
+ return 0;
+
+ /* First make sure we didn't deduce anything that conflicts with
+ explicitly specified args. */
+ for (i = nargs; i--; )
+ {
+ tree elt = TREE_VEC_ELT (tempargs, i);
+ tree oldelt = TREE_VEC_ELT (orig_targs, i);
+
+ if (elt == NULL_TREE)
+ continue;
+ else if (uses_template_parms (elt))
+ {
+ /* Since we're unifying against ourselves, we will fill in template
+ args used in the function parm list with our own template parms.
+ Discard them. */
+ TREE_VEC_ELT (tempargs, i) = NULL_TREE;
+ continue;
+ }
+ else if (oldelt && ! template_args_equal (oldelt, elt))
+ return 0;
+ }
+
+ for (i = nargs; i--; )
+ {
+ tree elt = TREE_VEC_ELT (tempargs, i);
+
+ if (elt)
+ TREE_VEC_ELT (targs, i) = elt;
+ }
+
+ return 1;
+}
+
+/* PARM is a template class (perhaps with unbound template
+ parameters). ARG is a fully instantiated type. If ARG can be
+ bound to PARM, return ARG, otherwise return NULL_TREE. TPARMS and
+ TARGS are as for unify. */
+
+static tree
+try_class_unification (tparms, targs, parm, arg)
+ tree tparms;
+ tree targs;
+ tree parm;
+ tree arg;
+{
+ int i;
+ tree copy_of_targs;
+
+ if (!CLASSTYPE_TEMPLATE_INFO (arg)
+ || CLASSTYPE_TI_TEMPLATE (arg) != CLASSTYPE_TI_TEMPLATE (parm))
+ return NULL_TREE;
+
+ /* We need to make a new template argument vector for the call to
+ unify. If we used TARGS, we'd clutter it up with the result of
+ the attempted unification, even if this class didn't work out.
+ We also don't want to commit ourselves to all the unifications
+ we've already done, since unification is supposed to be done on
+ an argument-by-argument basis. In other words, consider the
+ following pathological case:
+
+ template <int I, int J, int K>
+ struct S {};
+
+ template <int I, int J>
+ struct S<I, J, 2> : public S<I, I, I>, S<J, J, J> {};
+
+ template <int I, int J, int K>
+ void f(S<I, J, K>, S<I, I, I>);
+
+ void g() {
+ S<0, 0, 0> s0;
+ S<0, 1, 2> s2;
+
+ f(s0, s2);
+ }
+
+ Now, by the time we consider the unification involving `s2', we
+ already know that we must have `f<0, 0, 0>'. But, even though
+ `S<0, 1, 2>' is derived from `S<0, 0, 0>', the code is not legal
+ because there are two ways to unify base classes of S<0, 1, 2>
+ with S<I, I, I>. If we kept the already deduced knowledge, we
+ would reject the possibility I=1. */
+ push_momentary ();
+ copy_of_targs = make_temp_vec (TREE_VEC_LENGTH (targs));
+ i = unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
+ CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE);
+ pop_momentary ();
+
+ /* If unification failed, we're done. */
+ if (i != 0)
+ return NULL_TREE;
+ else
+ return arg;
+}
+
+/* Subroutine of get_template_base. RVAL, if non-NULL, is a base we
+ have alreay discovered to be satisfactory. ARG_BINFO is the binfo
+ for the base class of ARG that we are currently examining. */
+
+static tree
+get_template_base_recursive (tparms, targs, parm,
+ arg_binfo, rval, flags)
+ tree tparms;
+ tree targs;
+ tree arg_binfo;
+ tree rval;
+ tree parm;
+ int flags;
+{
+ tree binfos;
+ int i, n_baselinks;
+ tree arg = BINFO_TYPE (arg_binfo);
+
+ if (!(flags & GTB_IGNORE_TYPE))
+ {
+ tree r = try_class_unification (tparms, targs,
+ parm, arg);
+
+ /* If there is more than one satisfactory baseclass, then:
+
+ [temp.deduct.call]
+
+ If they yield more than one possible deduced A, the type
+ deduction fails.
+
+ applies. */
+ if (r && rval && !same_type_p (r, rval))
+ return error_mark_node;
+ else if (r)
+ rval = r;
+ }
+
+ binfos = BINFO_BASETYPES (arg_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);
+ int this_virtual;
+
+ /* Skip this base, if we've already seen it. */
+ if (BINFO_MARKED (base_binfo))
+ continue;
+
+ this_virtual =
+ (flags & GTB_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 (tparms, targs,
+ parm,
+ base_binfo,
+ rval,
+ GTB_VIA_VIRTUAL * this_virtual);
+
+ /* If we discovered more than one matching base class, we can
+ stop now. */
+ if (rval == error_mark_node)
+ return error_mark_node;
+ }
+
+ return rval;
+}
+
+/* Given a template type PARM and a class type ARG, find the unique
+ base type in ARG that is an instance of PARM. We do not examine
+ ARG itself; only its base-classes. If there is no appropriate base
+ class, return NULL_TREE. If there is more than one, return
+ error_mark_node. PARM may be the type of a partial specialization,
+ as well as a plain template type. Used by unify. */
+
+static tree
+get_template_base (tparms, targs, parm, arg)
+ tree tparms;
+ tree targs;
+ tree parm;
+ tree arg;
+{
+ tree rval;
+ tree arg_binfo;
+
+ my_friendly_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)), 92);
+
+ arg_binfo = TYPE_BINFO (complete_type (arg));
+ rval = get_template_base_recursive (tparms, targs,
+ parm, arg_binfo,
+ NULL_TREE,
+ GTB_IGNORE_TYPE);
+
+ /* Since get_template_base_recursive marks the bases classes, we
+ must unmark them here. */
+ dfs_walk (arg_binfo, dfs_unmark, markedp, 0);
+
+ return rval;
+}
+
/* Returns the level of DECL, which declares a template parameter. */
-int
+static int
template_decl_level (decl)
tree decl;
{
@@ -6200,18 +8014,16 @@ template_decl_level (decl)
cv-qualifiers of each type, given STRICT as documented for unify.
Returns non-zero iff the unification is OK on that basis.*/
-int
+static 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)))
+ && !at_least_as_qualified_p (arg, parm))
|| (!(strict & UNIFY_ALLOW_LESS_CV_QUAL)
- && (TYPE_READONLY (arg) > TYPE_READONLY (parm)
- || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm))));
+ && (!at_least_as_qualified_p (parm, arg))));
}
/* Takes parameters as for type_unification. Returns 0 if the
@@ -6227,13 +8039,15 @@ check_cv_quals_for_unify (strict, arg, parm)
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. */
+ ARG.
+ UNIFY_ALLOW_INTEGER:
+ Allow any integral type to be deduced. See the TEMPLATE_PARM_INDEX
+ case for more information. */
-int
-unify (tparms, targs, parm, arg, strict, explicit_mask)
+static int
+unify (tparms, targs, parm, arg, strict)
tree tparms, targs, parm, arg;
int strict;
- int* explicit_mask;
{
int idx;
tree targ;
@@ -6249,9 +8063,12 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
if (arg == error_mark_node)
return 1;
if (arg == unknown_type_node)
- return 1;
+ /* We can't deduce anything from this, but we might get all the
+ template args from other function args. */
+ return 0;
+
/* If PARM uses template parameters, then we can't bail out here,
- even in ARG == PARM, since we won't record unifications for the
+ even if 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))
@@ -6286,7 +8103,7 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
/* 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;
+ && same_type_p (parm, arg)) ? 0 : 1;
idx = TEMPLATE_TYPE_IDX (parm);
targ = TREE_VEC_ELT (targs, idx);
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
@@ -6298,16 +8115,9 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
&& TREE_CODE (tparm) != TEMPLATE_DECL))
return 1;
- 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;
-
if (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
{
- if (CLASSTYPE_TEMPLATE_INFO (parm))
+ if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm))
{
/* We arrive here when PARM does not involve template
specialization. */
@@ -6317,8 +8127,8 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
return 1;
{
- tree parmtmpl = CLASSTYPE_TI_TEMPLATE (parm);
- tree parmvec = CLASSTYPE_TI_ARGS (parm);
+ tree parmtmpl = TYPE_TI_TEMPLATE (parm);
+ tree parmvec = TYPE_TI_ARGS (parm);
tree argvec = CLASSTYPE_TI_ARGS (arg);
tree argtmplvec
= DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (arg));
@@ -6331,24 +8141,22 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
template <class T, class Allocator = allocator>
class vector. */
- if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 1, 1)
+ if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
== error_mark_node)
return 1;
- /* Deduce arguments T, i from TT<T> or TT<i>. */
+ /* Deduce arguments T, i from TT<T> or TT<i>.
+ We check each element of PARMVEC and ARGVEC individually
+ rather than the whole TREE_VEC since they can have
+ different number of elements. */
+
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))
+ UNIFY_ALLOW_NONE))
return 1;
}
}
@@ -6368,18 +8176,30 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
/* 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));
+ cp_build_qualified_type (arg,
+ CP_TYPE_QUALS (arg)
+ & ~CP_TYPE_QUALS (parm));
}
/* Simple cases: Value already set, does match or doesn't. */
- if (targ != NULL_TREE
- && (comptypes (targ, arg, 1)
- || (explicit_mask && explicit_mask[idx])))
+ if (targ != NULL_TREE && same_type_p (targ, arg))
return 0;
else if (targ)
return 1;
+
+ /* Make sure that ARG is not a variable-sized array. (Note that
+ were talking about variable-sized arrays (like `int[n]'),
+ rather than arrays of unknown size (like `int[]').) We'll
+ get very confused by such a type since the bound of the array
+ will not be computable in an instantiation. Besides, such
+ types are not allowed in ISO C++, so we can do as we please
+ here. */
+ if (TREE_CODE (arg) == ARRAY_TYPE
+ && !uses_template_parms (arg)
+ && (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (arg)))
+ != INTEGER_CST))
+ return 1;
+
TREE_VEC_ELT (targs, idx) = arg;
return 0;
@@ -6407,6 +8227,22 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
my_friendly_abort (42);
}
+ /* [temp.deduct.type] If, in the declaration of a function template
+ with a non-type template-parameter, the non-type
+ template-parameter is used in an expression in the function
+ parameter-list and, if the corresponding template-argument is
+ deduced, the template-argument type shall match the type of the
+ template-parameter exactly, except that a template-argument
+ deduced from an array bound may be of any integral type. */
+ if (same_type_p (TREE_TYPE (arg), TREE_TYPE (parm)))
+ /* OK */;
+ else if ((strict & UNIFY_ALLOW_INTEGER)
+ && (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
+ || TREE_CODE (TREE_TYPE (parm)) == BOOLEAN_TYPE))
+ /* OK */;
+ else
+ return 1;
+
TREE_VEC_ELT (targs, idx) = copy_to_permanent (arg);
return 0;
@@ -6416,8 +8252,7 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg))
return (unify (tparms, targs, parm,
- TYPE_PTRMEMFUNC_FN_TYPE (arg), strict,
- explicit_mask));
+ TYPE_PTRMEMFUNC_FN_TYPE (arg), strict));
if (TREE_CODE (arg) != POINTER_TYPE)
return 1;
@@ -6445,14 +8280,14 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
sub_strict &= ~UNIFY_ALLOW_DERIVED;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE
- (arg), sub_strict, explicit_mask);
+ (arg), sub_strict);
}
case REFERENCE_TYPE:
if (TREE_CODE (arg) != REFERENCE_TYPE)
return 1;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- UNIFY_ALLOW_NONE, explicit_mask);
+ UNIFY_ALLOW_NONE);
case ARRAY_TYPE:
if (TREE_CODE (arg) != ARRAY_TYPE)
@@ -6462,10 +8297,10 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
return 1;
if (TYPE_DOMAIN (parm) != NULL_TREE
&& unify (tparms, targs, TYPE_DOMAIN (parm),
- TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE, explicit_mask) != 0)
+ TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE) != 0)
return 1;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- UNIFY_ALLOW_NONE, explicit_mask);
+ UNIFY_ALLOW_NONE);
case REAL_TYPE:
case COMPLEX_TYPE:
@@ -6475,23 +8310,23 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
- if (TREE_CODE (parm) == INTEGER_TYPE)
+ if (TREE_CODE (parm) == INTEGER_TYPE
+ && TREE_CODE (TYPE_MAX_VALUE (parm)) != INTEGER_CST)
{
if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
&& unify (tparms, targs, TYPE_MIN_VALUE (parm),
- TYPE_MIN_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask))
+ TYPE_MIN_VALUE (arg), UNIFY_ALLOW_INTEGER))
return 1;
if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
&& unify (tparms, targs, TYPE_MAX_VALUE (parm),
- TYPE_MAX_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask))
+ TYPE_MAX_VALUE (arg), UNIFY_ALLOW_INTEGER))
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))
+ /* We use the TYPE_MAIN_VARIANT since we have already
+ checked cv-qualification at the top of the
+ function. */
+ else if (!same_type_p (TYPE_MAIN_VARIANT (arg),
+ TYPE_MAIN_VARIANT (parm)))
return 1;
/* As far as unification is concerned, this wins. Later checks
@@ -6518,44 +8353,63 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--)
if (unify (tparms, targs,
TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
- UNIFY_ALLOW_NONE, explicit_mask))
+ UNIFY_ALLOW_NONE))
return 1;
return 0;
}
case RECORD_TYPE:
+ case UNION_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (parm))
return unify (tparms, targs, TYPE_PTRMEMFUNC_FN_TYPE (parm),
- arg, strict, explicit_mask);
+ arg, strict);
- if (TREE_CODE (arg) != RECORD_TYPE)
+ if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
- if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm))
+ if (CLASSTYPE_TEMPLATE_INFO (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))
+ {
+ /* First, we try to unify the PARM and ARG directly. */
+ t = try_class_unification (tparms, targs,
+ parm, arg);
+
+ if (!t)
+ {
+ /* Fallback to the special case allowed in
+ [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 (tparms, targs,
+ parm, arg);
+
+ if (! t || t == error_mark_node)
+ return 1;
+ }
+ }
+ else if (CLASSTYPE_TEMPLATE_INFO (arg)
+ && (CLASSTYPE_TI_TEMPLATE (parm)
+ == CLASSTYPE_TI_TEMPLATE (arg)))
+ /* Perhaps PARM is something like S<U> and ARG is S<int>.
+ Then, we should unify `int' and `U'. */
t = arg;
- if (! t || t == error_mark_node)
+ else
+ /* There's no chance of unication succeeding. */
return 1;
return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
- CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE,
- explicit_mask);
+ CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE);
}
- else if (!comptypes (TYPE_MAIN_VARIANT (parm),
- TYPE_MAIN_VARIANT (arg), 1))
+ else if (!same_type_p (TYPE_MAIN_VARIANT (parm),
+ TYPE_MAIN_VARIANT (arg)))
return 1;
return 0;
@@ -6565,20 +8419,20 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
return 1;
if (unify (tparms, targs, TREE_TYPE (parm),
- TREE_TYPE (arg), UNIFY_ALLOW_NONE, explicit_mask))
+ TREE_TYPE (arg), UNIFY_ALLOW_NONE))
return 1;
return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
TYPE_ARG_TYPES (arg), 1,
- DEDUCE_EXACT, 0, explicit_mask);
+ DEDUCE_EXACT, 0);
case OFFSET_TYPE:
if (TREE_CODE (arg) != OFFSET_TYPE)
return 1;
if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
- TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE, explicit_mask))
+ TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE))
return 1;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- UNIFY_ALLOW_NONE, explicit_mask);
+ strict);
case CONST_DECL:
if (arg != decl_constant_value (parm))
@@ -6608,41 +8462,31 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
integer_type_node,
arg, t2));
- return unify (tparms, targs, t1, t, UNIFY_ALLOW_NONE,
- explicit_mask);
+ return unify (tparms, targs, t1, t, strict);
}
/* else fall through */
default:
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>);
+ /* 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:
+ This is a "nondeduced context":
- foo(S<2>(), S<4>());
+ [deduct.type]
+
+ The nondeduced contexts are:
- 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);
+ --A type that is a template-id in which one or more of
+ the template-arguments is an expression that references
+ a template-parameter.
- 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;
- }
+ In these cases, we assume deduction succeeded, but don't
+ actually infer any unifications. */
+ return 0;
else
sorry ("use of `%s' in template type unification",
tree_code_name [(int) TREE_CODE (parm)]);
@@ -6651,14 +8495,15 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
}
}
+/* Called if RESULT is explicitly instantiated, or is a member of an
+ explicitly instantiated class, or if using -frepo and the
+ instantiation of RESULT has been assigned to this file. */
+
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. */
@@ -6669,9 +8514,12 @@ mark_decl_instantiated (result, extern_p)
DECL_INTERFACE_KNOWN (result) = 1;
DECL_NOT_REALLY_EXTERN (result) = 1;
+ /* Always make artificials weak. */
+ if (DECL_ARTIFICIAL (result) && flag_weak)
+ comdat_linkage (result);
/* For WIN32 we also want to put explicit instantiations in
linkonce sections. */
- if (TREE_PUBLIC (result))
+ else if (TREE_PUBLIC (result))
maybe_make_one_only (result);
}
else if (TREE_CODE (result) == FUNCTION_DECL)
@@ -6692,17 +8540,13 @@ more_specialized (pat1, pat2, explicit_args)
tree targs;
int winner = 0;
- targs = get_bindings_overload (pat1, pat2, explicit_args);
+ targs = get_bindings_overload (pat1, DECL_RESULT (pat2), explicit_args);
if (targs)
- {
- --winner;
- }
+ --winner;
- targs = get_bindings_overload (pat2, pat1, explicit_args);
+ targs = get_bindings_overload (pat2, DECL_RESULT (pat1), explicit_args);
if (targs)
- {
- ++winner;
- }
+ ++winner;
return winner;
}
@@ -6720,15 +8564,13 @@ more_specialized_class (pat1, pat2)
tree targs;
int winner = 0;
- targs = get_class_bindings
- (TREE_VALUE (pat1), TREE_PURPOSE (pat1),
- TREE_PURPOSE (pat2), NULL_TREE);
+ targs = get_class_bindings (TREE_VALUE (pat1), TREE_PURPOSE (pat1),
+ TREE_PURPOSE (pat2));
if (targs)
--winner;
- targs = get_class_bindings
- (TREE_VALUE (pat2), TREE_PURPOSE (pat2),
- TREE_PURPOSE (pat1), NULL_TREE);
+ targs = get_class_bindings (TREE_VALUE (pat2), TREE_PURPOSE (pat2),
+ TREE_PURPOSE (pat1));
if (targs)
++winner;
@@ -6738,7 +8580,8 @@ more_specialized_class (pat1, pat2)
/* 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. */
+ also match. Return NULL_TREE if no satisfactory arguments could be
+ found. */
static tree
get_bindings_real (fn, decl, explicit_args, check_rettype)
@@ -6747,35 +8590,50 @@ get_bindings_real (fn, decl, explicit_args, 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;
+ tree decl_type;
+ tree decl_arg_types;
int i;
- if (DECL_STATIC_FUNCTION_P (fn)
- && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ /* Substitute the explicit template arguments into the type of DECL.
+ The call to fn_type_unification will handle substitution into the
+ FN. */
+ decl_type = TREE_TYPE (decl);
+ if (explicit_args && uses_template_parms (decl_type))
{
- /* 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));
+ tree tmpl;
+ tree converted_args;
+
+ if (DECL_TEMPLATE_INFO (decl))
+ tmpl = DECL_TI_TEMPLATE (decl);
else
- /* 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);
+ /* We can get here for some illegal specializations. */
+ return NULL_TREE;
+
+ converted_args
+ = (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
+ explicit_args, NULL_TREE,
+ /*complain=*/0,
+ /*require_all_arguments=*/0));
+ if (converted_args == error_mark_node)
+ return NULL_TREE;
+
+ decl_type = tsubst (decl_type, converted_args, /*complain=*/0,
+ NULL_TREE);
+ if (decl_type == error_mark_node)
+ return NULL_TREE;
}
+ /* If FN is a static member function, adjust the type of DECL
+ appropriately. */
+ decl_arg_types = TYPE_ARG_TYPES (decl_type);
+ if (DECL_STATIC_FUNCTION_P (fn)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ decl_arg_types = TREE_CHAIN (decl_arg_types);
+
i = fn_type_unification (fn, explicit_args, targs,
decl_arg_types,
- TREE_TYPE (TREE_TYPE (decl)),
- DEDUCE_EXACT,
- extra_fn_arg);
+ TREE_TYPE (decl_type),
+ DEDUCE_EXACT);
if (i != 0)
return NULL_TREE;
@@ -6783,11 +8641,10 @@ get_bindings_real (fn, decl, explicit_args, check_rettype)
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);
+ tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)), targs,
+ /*complain=*/0, NULL_TREE);
- if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1))
+ if (!same_type_p (t, TREE_TYPE (TREE_TYPE (decl))))
return NULL_TREE;
}
@@ -6812,31 +8669,32 @@ get_bindings_overload (fn, decl, explicit_args)
return get_bindings_real (fn, decl, explicit_args, 0);
}
+/* Return the innermost template arguments that, when applied to a
+ template specialization whose innermost template parameters are
+ TPARMS, and whose specialization arguments are ARGS, yield the
+ ARGS.
+
+ For example, suppose we have:
+
+ template <class T, class U> struct S {};
+ template <class T> struct S<T*, int> {};
+
+ Then, suppose we want to get `S<double*, int>'. The TPARMS will be
+ {T}, the PARMS will be {T*, int} and the ARGS will be {double*,
+ int}. The resulting vector will be {double}, indicating that `T'
+ is bound to `double'. */
+
static tree
-get_class_bindings (tparms, parms, args, outer_args)
- tree tparms, parms, args, outer_args;
+get_class_bindings (tparms, parms, args)
+ tree tparms, parms, args;
{
int i, ntparms = TREE_VEC_LENGTH (tparms);
tree vec = make_temp_vec (ntparms);
- if (outer_args)
- {
- tparms = tsubst (tparms, outer_args, NULL_TREE);
- parms = tsubst (parms, outer_args, NULL_TREE);
- }
+ args = innermost_args (args);
- for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
- {
- 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;
- }
- }
+ if (unify (tparms, vec, parms, args, UNIFY_ALLOW_NONE))
+ return NULL_TREE;
for (i = 0; i < ntparms; ++i)
if (! TREE_VEC_ELT (vec, i))
@@ -6845,37 +8703,30 @@ get_class_bindings (tparms, parms, args, outer_args)
return vec;
}
-/* 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. */
+/* In INSTANTIATIONS is a list of <INSTANTIATION, TEMPLATE> pairs.
+ Pick the most specialized template, and return the corresponding
+ instantiation, or if there is no corresponding instantiation, the
+ template itself. EXPLICIT_ARGS is any template arguments explicity
+ mentioned in a template-id. If there is no most specialized
+ tempalte, error_mark_node is returned. If there are no templates
+ at all, NULL_TREE is returned. */
tree
-most_specialized (fns, decl, explicit_args)
- tree fns, decl, explicit_args;
+most_specialized_instantiation (instantiations, explicit_args)
+ tree instantiations;
+ tree explicit_args;
{
- tree fn, champ, args, *p;
+ tree fn, champ;
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)
+ if (!instantiations)
return NULL_TREE;
- fn = fns;
- champ = TREE_VALUE (fn);
- fn = TREE_CHAIN (fn);
- for (; fn; fn = TREE_CHAIN (fn))
+ champ = instantiations;
+ for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn))
{
- fate = more_specialized (champ, TREE_VALUE (fn), explicit_args);
+ fate = more_specialized (TREE_VALUE (champ),
+ TREE_VALUE (fn), explicit_args);
if (fate == 1)
;
else
@@ -6886,35 +8737,89 @@ most_specialized (fns, decl, explicit_args)
if (! fn)
return error_mark_node;
}
- champ = TREE_VALUE (fn);
+ champ = fn;
}
}
- for (fn = fns; fn && TREE_VALUE (fn) != champ; fn = TREE_CHAIN (fn))
+ for (fn = instantiations; fn && fn != champ; fn = TREE_CHAIN (fn))
{
- fate = more_specialized (champ, TREE_VALUE (fn), explicit_args);
+ fate = more_specialized (TREE_VALUE (champ),
+ TREE_VALUE (fn), explicit_args);
if (fate != 1)
return error_mark_node;
}
- return champ;
+ return TREE_PURPOSE (champ) ? TREE_PURPOSE (champ) : TREE_VALUE (champ);
}
-/* Return the most specialized of the class template specializations in
- SPECS that can produce an instantiation matching ARGS. */
+/* 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_class (specs, mainargs, outer_args)
- tree specs, mainargs, outer_args;
+static tree
+most_specialized (fns, decl, explicit_args)
+ tree fns, decl, explicit_args;
{
- tree list = NULL_TREE, t, args, champ;
- int fate;
+ tree candidates = NULL_TREE;
+ tree fn, args;
- for (t = specs; t; t = TREE_CHAIN (t))
+ for (fn = fns; fn; fn = TREE_CHAIN (fn))
{
- args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
- mainargs, outer_args);
+ tree candidate = TREE_VALUE (fn);
+
+ args = get_bindings (candidate, decl, explicit_args);
if (args)
+ candidates = scratch_tree_cons (NULL_TREE, candidate,
+ candidates);
+ }
+
+ return most_specialized_instantiation (candidates, explicit_args);
+}
+
+/* If DECL is a specialization of some template, return the most
+ general such template. For example, given:
+
+ template <class T> struct S { template <class U> void f(U); };
+
+ if TMPL is `template <class U> void S<int>::f(U)' this will return
+ the full template. This function will not trace past partial
+ specializations, however. For example, given in addition:
+
+ template <class T> struct S<T*> { template <class U> void f(U); };
+
+ if TMPL is `template <class U> void S<int*>::f(U)' this will return
+ `template <class T> template <class U> S<T*>::f(U)'. */
+
+static tree
+most_general_template (decl)
+ tree decl;
+{
+ while (DECL_TEMPLATE_INFO (decl))
+ decl = DECL_TI_TEMPLATE (decl);
+
+ return decl;
+}
+
+/* Return the most specialized of the class template specializations
+ of TMPL which can produce an instantiation matching ARGS, or
+ error_mark_node if the choice is ambiguous. */
+
+static tree
+most_specialized_class (tmpl, args)
+ tree tmpl;
+ tree args;
+{
+ tree list = NULL_TREE;
+ tree t;
+ tree champ;
+ int fate;
+
+ tmpl = most_general_template (tmpl);
+ for (t = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); t; t = TREE_CHAIN (t))
+ {
+ tree spec_args
+ = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
+ if (spec_args)
{
list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
TREE_TYPE (list) = TREE_TYPE (t);
@@ -6969,29 +8874,69 @@ do_decl_instantiation (declspecs, declarator, storage)
cp_error ("explicit instantiation of non-template `%#D'", decl);
return;
}
-
- /* If we've already seen this template instance, use it. */
- if (TREE_CODE (decl) == VAR_DECL)
+ else if (TREE_CODE (decl) == VAR_DECL)
{
+ /* There is an asymmetry here in the way VAR_DECLs and
+ FUNCTION_DECLs are handled by grokdeclarator. In the case of
+ the latter, the DECL we get back will be marked as a
+ template instantiation, and the appropriate
+ DECL_TEMPLATE_INFO will be set up. This does not happen for
+ VAR_DECLs so we do the lookup here. Probably, grokdeclarator
+ should handle VAR_DECLs as it currently handles
+ FUNCTION_DECLs. */
result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, 0);
if (result && TREE_CODE (result) != VAR_DECL)
- result = NULL_TREE;
+ {
+ cp_error ("no matching template for `%D' found", result);
+ return;
+ }
}
else if (TREE_CODE (decl) != FUNCTION_DECL)
{
cp_error ("explicit instantiation of `%#D'", decl);
return;
}
- else if (DECL_TEMPLATE_INSTANTIATION (decl))
+ else
result = decl;
- if (! result)
+ /* Check for various error cases. Note that if the explicit
+ instantiation is legal the RESULT will currently be marked as an
+ *implicit* instantiation; DECL_EXPLICIT_INSTANTIATION is not set
+ until we get here. */
+
+ if (DECL_TEMPLATE_SPECIALIZATION (result))
{
- cp_error ("no matching template for `%D' found", decl);
+ /* [temp.spec]
+
+ No program shall both explicitly instantiate and explicitly
+ specialize a template. */
+ cp_pedwarn ("explicit instantiation of `%#D' after", result);
+ cp_pedwarn_at ("explicit specialization here", result);
return;
}
+ else if (DECL_EXPLICIT_INSTANTIATION (result))
+ {
+ /* [temp.spec]
+
+ No program shall explicitly instantiate any template more
+ than once.
- if (! DECL_TEMPLATE_INFO (result))
+ We check DECL_INTERFACE_KNOWN so as not to complain when the
+ first instantiation was `extern' and the second is not, and
+ EXTERN_P for the opposite case. */
+ if (DECL_INTERFACE_KNOWN (result) && !extern_p)
+ cp_pedwarn ("duplicate explicit instantiation of `%#D'", result);
+
+ /* If we've already instantiated the template, just return now. */
+ if (DECL_INTERFACE_KNOWN (result))
+ return;
+ }
+ else if (!DECL_IMPLICIT_INSTANTIATION (result))
+ {
+ cp_error ("no matching template for `%D' found", result);
+ return;
+ }
+ else if (!DECL_TEMPLATE_INFO (result))
{
cp_pedwarn ("explicit instantiation of non-template `%#D'", result);
return;
@@ -7003,11 +8948,16 @@ do_decl_instantiation (declspecs, declarator, storage)
if (storage == NULL_TREE)
;
else if (storage == ridpointers[(int) RID_EXTERN])
- extern_p = 1;
+ {
+ if (pedantic)
+ cp_pedwarn ("ANSI C++ forbids the use of `extern' on explicit instantiations");
+ extern_p = 1;
+ }
else
cp_error ("storage class `%D' applied to template instantiation",
storage);
+ SET_DECL_EXPLICIT_INSTANTIATION (result);
mark_decl_instantiated (result, extern_p);
repo_template_instantiated (result, extern_p);
if (! extern_p)
@@ -7042,7 +8992,7 @@ do_type_instantiation (t, storage)
if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t);
- if (! IS_AGGR_TYPE (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
+ if (! CLASS_TYPE_P (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
{
cp_error ("explicit instantiation of non-template type `%T'", t);
return;
@@ -7062,38 +9012,82 @@ do_type_instantiation (t, storage)
return;
}
- if (storage == NULL_TREE)
- /* OK */;
- else if (storage == ridpointers[(int) RID_INLINE])
- nomem_p = 1;
- else if (storage == ridpointers[(int) RID_EXTERN])
- extern_p = 1;
- else if (storage == ridpointers[(int) RID_STATIC])
- static_p = 1;
- else
+ if (storage != NULL_TREE)
{
- cp_error ("storage class `%D' applied to template instantiation",
- storage);
- extern_p = 0;
+ if (pedantic)
+ cp_pedwarn("ANSI C++ forbids the use of `%s' on explicit instantiations",
+ IDENTIFIER_POINTER (storage));
+
+ if (storage == ridpointers[(int) RID_INLINE])
+ 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",
+ storage);
+ extern_p = 0;
+ }
}
- /* We've already instantiated this. */
- if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t)
- && extern_p)
- return;
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
+ {
+ /* [temp.spec]
- if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
+ No program shall both explicitly instantiate and explicitly
+ specialize a template. */
+ cp_error ("explicit instantiation of `%#T' after", t);
+ cp_error_at ("explicit specialization here", t);
+ return;
+ }
+ else if (CLASSTYPE_EXPLICIT_INSTANTIATION (t))
{
- mark_class_instantiated (t, extern_p);
- repo_template_instantiated (t, extern_p);
+ /* [temp.spec]
+
+ No program shall explicitly instantiate any template more
+ than once.
+
+ If CLASSTYPE_INTERFACE_ONLY, then the first explicit
+ instantiation was `extern', and if EXTERN_P then the second
+ is. Both cases are OK. */
+ if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p)
+ cp_error ("duplicate explicit instantiation of `%#T'", t);
+
+ /* If we've already instantiated the template, just return now. */
+ if (!CLASSTYPE_INTERFACE_ONLY (t))
+ return;
}
+ mark_class_instantiated (t, extern_p);
+ repo_template_instantiated (t, extern_p);
+
if (nomem_p)
return;
{
tree tmp;
+ /* In contrast to implicit instantiation, where only the
+ declarations, and not the definitions, of members are
+ instantiated, we have here:
+
+ [temp.explicit]
+
+ The explicit instantiation of a class template specialization
+ implies the instantiation of all of its members not
+ previously explicitly specialized in the translation unit
+ containing the explicit instantiation.
+
+ Of course, we can't instantiate member template classes, since
+ we don't have any arguments for them. Note that the standard
+ is unclear on whether the instatiation of the members are
+ *explicit* instantiations or not. We choose to be generous,
+ and not set DECL_EXPLICIT_INSTANTIATION. Therefore, we allow
+ the explicit instantiation of a class where some of the members
+ have no definition in the current translation unit. */
+
if (! static_p)
for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
if (TREE_CODE (tmp) == FUNCTION_DECL
@@ -7115,14 +9109,16 @@ do_type_instantiation (t, storage)
}
for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
- if (IS_AGGR_TYPE (TREE_VALUE (tmp)))
+ if (IS_AGGR_TYPE (TREE_VALUE (tmp))
+ && !uses_template_parms (CLASSTYPE_TI_ARGS (TREE_VALUE (tmp))))
do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), 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.
+/* Given a function DECL, which is a specialization of TMPL, modify
+ DECL to be a re-instantiation of TMPL with the same template
+ arguments. TMPL should be the template into which tsubst'ing
+ should occur for DECL, not the most general template.
One reason for doing this is a scenario like this:
@@ -7139,54 +9135,76 @@ do_type_instantiation (t, storage)
first parameter, and the wrong type for the second. So, when we go
to instantiate the DECL, we regenerate it. */
-void
+static void
regenerate_decl_from_template (decl, tmpl)
tree decl;
tree tmpl;
{
tree args;
- tree save_ti;
tree code_pattern;
tree new_decl;
+ tree gen_tmpl;
+ int unregistered;
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;
+ /* Unregister the specialization so that when we tsubst we will not
+ just return DECL. We don't have to unregister DECL from TMPL
+ because if would only be registered there if it were a partial
+ instantiation of a specialization, which it isn't: it's a full
+ instantiation. */
+ gen_tmpl = most_general_template (tmpl);
+ unregistered = unregister_specialization (decl, gen_tmpl);
+
+ /* If the DECL was not unregistered then something peculiar is
+ happening: we created a specialization but did not call
+ register_specialization for it. */
+ my_friendly_assert (unregistered, 0);
+
+ if (TREE_CODE (decl) == VAR_DECL)
+ /* Make sure that we can see identifiers, and compute access
+ correctly, for the class members used in the declaration of
+ this static variable. */
+ pushclass (DECL_CONTEXT (decl), 2);
+
+ /* Do the substitution to get the new declaration. */
+ new_decl = tsubst (code_pattern, args, /*complain=*/1, NULL_TREE);
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);
+ /*complain=*/1, DECL_TI_TEMPLATE (decl));
+ /* Pop the class context we pushed above. */
+ popclass ();
}
-
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ else 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);
- }
-
+ /* And don't complain about a duplicate definition. */
+ DECL_INITIAL (decl) = NULL_TREE;
+ }
+
+ /* The immediate parent of the new template is still whatever it was
+ before, even though tsubst sets DECL_TI_TEMPLATE up as the most
+ general template. We also reset the DECL_ASSEMBLER_NAME since
+ tsubst always calculates the name as if the function in question
+ were really a template instance, and sometimes, with friend
+ functions, this is not so. See tsubst_friend_function for
+ details. */
+ DECL_TI_TEMPLATE (new_decl) = DECL_TI_TEMPLATE (decl);
+ DECL_ASSEMBLER_NAME (new_decl) = DECL_ASSEMBLER_NAME (decl);
+ DECL_RTL (new_decl) = DECL_RTL (decl);
+
+ /* Call duplicate decls to merge the old and new declarations. */
duplicate_decls (new_decl, decl);
- if (TREE_CODE (decl) == FUNCTION_DECL)
- DECL_INITIAL (new_decl) = NULL_TREE;
+ /* Now, re-register the specialization. */
+ register_specialization (decl, gen_tmpl, args);
}
/* Produce the definition of D, a _DECL generated from a template. */
@@ -7195,60 +9213,101 @@ tree
instantiate_decl (d)
tree d;
{
- tree ti = DECL_TEMPLATE_INFO (d);
- tree tmpl = TI_TEMPLATE (ti);
- tree args = TI_ARGS (ti);
+ tree tmpl = DECL_TI_TEMPLATE (d);
+ tree args = DECL_TI_ARGS (d);
tree td;
- tree decl_pattern, code_pattern;
+ tree code_pattern;
+ tree spec;
+ tree gen_tmpl;
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);
+ /* This function should only be used to instantiate templates for
+ functions and static member variables. */
+ my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
+ || TREE_CODE (d) == VAR_DECL, 0);
+
+ if (DECL_TEMPLATE_INSTANTIATED (d))
+ /* D has already been instantiated. It might seem reasonable to
+ check whether or not D is an explict instantiation, and, if so,
+ stop here. But when an explicit instantiation is deferred
+ until the end of the compilation, DECL_EXPLICIT_INSTANTIATION
+ is set, even though we still need to do the instantiation. */
+ return d;
- /* 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 we already have a specialization of this declaration, then
+ there's no reason to instantiate it. Note that
+ retrieve_specialization gives us both instantiations and
+ specializations, so we must explicitly check
+ DECL_TEMPLATE_SPECIALIZATION. */
+ gen_tmpl = most_general_template (tmpl);
+ spec = retrieve_specialization (gen_tmpl, args);
+ if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec))
+ return spec;
- 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)
+ /* This needs to happen before any tsubsting. */
+ if (! push_tinst_level (d))
return d;
- if (TREE_CODE (d) == FUNCTION_DECL)
+ /* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern
+ for the instantiation. This is not always the most general
+ template. Consider, for example:
+
+ template <class T>
+ struct S { template <class U> void f();
+ template <> void f<int>(); };
+
+ and an instantiation of S<double>::f<int>. We want TD to be the
+ specialization S<T>::f<int>, not the more general S<T>::f<U>. */
+ td = tmpl;
+ for (td = tmpl;
+ /* An instantiation cannot have a definition, so we need a
+ more general template. */
+ DECL_TEMPLATE_INSTANTIATION (td)
+ /* We must also deal with friend templates. Given:
+
+ template <class T> struct S {
+ template <class U> friend void f() {};
+ };
+
+ S<int>::f<U> say, is not an instantiation of S<T>::f<U>,
+ so far as the language is concerned, but that's still
+ where we get the pattern for the instantiation from. On
+ ther hand, if the definition comes outside the class, say:
+
+ template <class T> struct S {
+ template <class U> friend void f();
+ };
+ template <class U> friend void f() {}
+
+ we don't need to look any further. That's what the check for
+ DECL_INITIAL is for. */
+ || (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (td)
+ && !DECL_INITIAL (DECL_TEMPLATE_RESULT (td)));
+ )
{
- tree spec = retrieve_specialization (tmpl, args);
+ /* The present template, TD, should not be a definition. If it
+ were a definition, we should be using it! Note that we
+ cannot restructure the loop to just keep going until we find
+ a template with a definition, since that might go too far if
+ a specialization was declared, but not defined. */
+ my_friendly_assert (!(TREE_CODE (d) == VAR_DECL
+ && !DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (td))),
+ 0);
- if (spec != NULL_TREE
- && DECL_TEMPLATE_SPECIALIZATION (spec))
- return spec;
+ /* Fetch the more general template. */
+ td = DECL_TI_TEMPLATE (td);
}
- /* This needs to happen before any tsubsting. */
- if (! push_tinst_level (d))
- return d;
+ code_pattern = DECL_TEMPLATE_RESULT (td);
+
+ if (TREE_CODE (d) == FUNCTION_DECL)
+ pattern_defined = (DECL_INITIAL (code_pattern) != NULL_TREE);
+ else
+ pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
push_to_top_level ();
lineno = DECL_SOURCE_LINE (d);
@@ -7295,14 +9354,34 @@ instantiate_decl (d)
&& ! at_eof))
{
/* Defer all templates except inline functions used in another
- function. */
+ function. We restore the source position here because it's used
+ by add_pending_template. */
lineno = line;
input_filename = file;
+ if (at_eof && !pattern_defined
+ && DECL_EXPLICIT_INSTANTIATION (d))
+ /* [temp.explicit]
+
+ The definition of a non-exported function template, a
+ non-exported member function template, or a non-exported
+ member function or static data member of a class template
+ shall be present in every translation unit in which it is
+ explicitly instantiated. */
+ cp_error ("explicit instantiation of `%D' but no definition available",
+ d);
+
add_pending_template (d);
goto out;
}
+ /* We're now committed to instantiating this template. Mark it as
+ instantiated so that recursive calls to instantiate_decl do not
+ try to instantiate it again. */
+ DECL_TEMPLATE_INSTANTIATED (d) = 1;
+
+ /* Regenerate the declaration in case the template has been modified
+ by a subsequent redeclaration. */
regenerate_decl_from_template (d, td);
/* We already set the file and line above. Reset them now in case
@@ -7333,7 +9412,7 @@ instantiate_decl (d)
{
store_return_init
(TREE_OPERAND (t, 0),
- tsubst_expr (TREE_OPERAND (t, 1), args, tmpl));
+ tsubst_expr (TREE_OPERAND (t, 1), args, /*complain=*/1, tmpl));
t = TREE_CHAIN (t);
}
@@ -7353,7 +9432,7 @@ instantiate_decl (d)
keep_next_level ();
my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
- tsubst_expr (t, args, tmpl);
+ tsubst_expr (t, args, /*complain=*/1, tmpl);
finish_function (lineno, 0, nested);
}
@@ -7368,27 +9447,119 @@ out:
return d;
}
-tree
-tsubst_chain (t, argvec)
- tree t, argvec;
+/* Run through the list of templates that we wish we could
+ instantiate, and instantiate any we can. */
+
+int
+instantiate_pending_templates ()
{
- if (t)
+ tree *t;
+ int instantiated_something = 0;
+ int reconsider;
+
+ do
{
- tree first = tsubst (t, argvec, NULL_TREE);
- tree last = first;
+ reconsider = 0;
- for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t))
+ t = &pending_templates;
+ while (*t)
{
- tree x = tsubst (t, argvec, NULL_TREE);
- TREE_CHAIN (last) = x;
- last = x;
+ tree srcloc = TREE_PURPOSE (*t);
+ tree instantiation = TREE_VALUE (*t);
+
+ input_filename = SRCLOC_FILE (srcloc);
+ lineno = SRCLOC_LINE (srcloc);
+
+ if (TREE_CODE_CLASS (TREE_CODE (instantiation)) == 't')
+ {
+ tree fn;
+
+ if (!TYPE_SIZE (instantiation))
+ {
+ instantiate_class_template (instantiation);
+ if (CLASSTYPE_TEMPLATE_INSTANTIATION (instantiation))
+ for (fn = TYPE_METHODS (instantiation);
+ fn;
+ fn = TREE_CHAIN (fn))
+ if (! DECL_ARTIFICIAL (fn))
+ instantiate_decl (fn);
+ if (TYPE_SIZE (instantiation))
+ {
+ instantiated_something = 1;
+ reconsider = 1;
+ }
+ }
+
+ if (TYPE_SIZE (instantiation))
+ /* If INSTANTIATION has been instantiated, then we don't
+ need to consider it again in the future. */
+ *t = TREE_CHAIN (*t);
+ else
+ t = &TREE_CHAIN (*t);
+ }
+ else
+ {
+ if (DECL_TEMPLATE_INSTANTIATION (instantiation)
+ && !DECL_TEMPLATE_INSTANTIATED (instantiation))
+ {
+ instantiation = instantiate_decl (instantiation);
+ if (DECL_TEMPLATE_INSTANTIATED (instantiation))
+ {
+ instantiated_something = 1;
+ reconsider = 1;
+ }
+ }
+
+ if (!DECL_TEMPLATE_INSTANTIATION (instantiation)
+ || DECL_TEMPLATE_INSTANTIATED (instantiation))
+ /* If INSTANTIATION has been instantiated, then we don't
+ need to consider it again in the future. */
+ *t = TREE_CHAIN (*t);
+ else
+ t = &TREE_CHAIN (*t);
+ }
}
+ template_tail = t;
- return first;
- }
- return NULL_TREE;
+ /* Go through the things that are template instantiations if we are
+ using guiding declarations. */
+ t = &maybe_templates;
+ while (*t)
+ {
+ tree template;
+ tree fn;
+ tree args;
+
+ fn = TREE_VALUE (*t);
+
+ if (DECL_INITIAL (fn))
+ /* If the FN is already defined, then it was either already
+ instantiated or, even though guiding declarations were
+ allowed, a non-template definition was provided. */
+ ;
+ else
+ {
+ template = TREE_PURPOSE (*t);
+ args = get_bindings (template, fn, NULL_TREE);
+ fn = instantiate_template (template, args);
+ instantiate_decl (fn);
+ reconsider = 1;
+ }
+
+ /* Remove this entry from the chain. */
+ *t = TREE_CHAIN (*t);
+ }
+ maybe_template_tail = t;
+ }
+ while (reconsider);
+
+ return instantiated_something;
}
+/* Substitute ARGVEC into T, which is a TREE_LIST. In particular, it
+ is an initializer list: the TREE_PURPOSEs are DECLs, and the
+ TREE_VALUEs are initializer values. Used by instantiate_decl. */
+
static tree
tsubst_expr_values (t, argvec)
tree t, argvec;
@@ -7398,8 +9569,10 @@ tsubst_expr_values (t, argvec)
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);
+ tree pur = tsubst_copy (TREE_PURPOSE (t), argvec,
+ /*complain=*/1, NULL_TREE);
+ tree val = tsubst_expr (TREE_VALUE (t), argvec, /*complain=*/1,
+ NULL_TREE);
*p = build_tree_list (pur, val);
p = &TREE_CHAIN (*p);
}
@@ -7461,35 +9634,199 @@ add_maybe_template (d, fns)
DECL_MAYBE_TEMPLATE (d) = 1;
}
-/* Instantiate an enumerated type. Used by instantiate_class_template and
- tsubst_expr. */
+/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */
-static tree
-tsubst_enum (tag, args, field_chain)
- tree tag, args;
- tree * field_chain;
+static void
+set_current_access_from_decl (decl)
+ tree decl;
{
- extern tree current_local_enum;
- tree prev_local_enum = current_local_enum;
+ if (TREE_PRIVATE (decl))
+ current_access_specifier = access_private_node;
+ else if (TREE_PROTECTED (decl))
+ current_access_specifier = access_protected_node;
+ else
+ current_access_specifier = access_public_node;
+}
- tree newtag = start_enum (TYPE_IDENTIFIER (tag));
- tree e, values = NULL_TREE;
+/* Instantiate an enumerated type. TAG is the template type, NEWTAG
+ is the instantiation (which should have been created with
+ start_enum) and ARGS are the template arguments to use. */
+
+static void
+tsubst_enum (tag, newtag, args)
+ tree tag;
+ tree newtag;
+ tree args;
+{
+ tree e;
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;
+ tree value;
+ tree elt;
+
+ /* Note that in a template enum, the TREE_VALUE is the
+ CONST_DECL, not the corresponding INTEGER_CST. */
+ value = tsubst_expr (DECL_INITIAL (TREE_VALUE (e)),
+ args, /*complain=*/1,
+ NULL_TREE);
+
+ /* Give this enumeration constant the correct access. */
+ set_current_access_from_decl (TREE_VALUE (e));
+
+ /* Actually build the enumerator itself. */
+ elt = build_enumerator (TREE_PURPOSE (e), value, newtag);
+
+ /* We save the enumerators we have built so far in the
+ TYPE_VALUES so that if the enumeration constants for
+ subsequent enumerators involve those for previous ones,
+ tsubst_copy will be able to find them. */
+ TREE_CHAIN (elt) = TYPE_VALUES (newtag);
+ TYPE_VALUES (newtag) = elt;
}
- finish_enum (newtag, values);
+ finish_enum (newtag);
+}
+
+/* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that
+ is either an instantiation or specialization of a template
+ function. */
+
+static void
+set_mangled_name_for_template_decl (decl)
+ tree decl;
+{
+ tree saved_namespace;
+ tree context = NULL_TREE;
+ tree fn_type;
+ tree ret_type;
+ tree parm_types;
+ tree tparms;
+ tree targs;
+ tree tmpl;
+ int parm_depth;
+
+ my_friendly_assert (TREE_CODE (decl) == FUNCTION_DECL, 0);
+ my_friendly_assert (DECL_TEMPLATE_INFO (decl) != NULL_TREE, 0);
+
+ /* The names of template functions must be mangled so as to indicate
+ what template is being specialized with what template arguments.
+ For example, each of the following three functions must get
+ different mangled names:
+
+ void f(int);
+ template <> void f<7>(int);
+ template <> void f<8>(int); */
+
+ targs = DECL_TI_ARGS (decl);
+ if (uses_template_parms (targs))
+ /* This DECL is for a partial instantiation. There's no need to
+ mangle the name of such an entity. */
+ return;
+
+ tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
+ tparms = DECL_TEMPLATE_PARMS (tmpl);
+ parm_depth = TMPL_PARMS_DEPTH (tparms);
- if (NULL != field_chain)
- *field_chain = grok_enum_decls (NULL_TREE);
+ /* There should be as many levels of arguments as there are levels
+ of parameters. */
+ my_friendly_assert (parm_depth == TMPL_ARGS_DEPTH (targs), 0);
- current_local_enum = prev_local_enum;
+ /* We now compute the PARMS and RET_TYPE to give to
+ build_decl_overload_real. The PARMS and RET_TYPE are the
+ parameter and return types of the template, after all but the
+ innermost template arguments have been substituted, not the
+ parameter and return types of the function DECL. For example,
+ given:
- return newtag;
+ template <class T> T f(T);
+
+ both PARMS and RET_TYPE should be `T' even if DECL is `int f(int)'.
+ A more subtle example is:
+
+ template <class T> struct S { template <class U> void f(T, U); }
+
+ Here, if DECL is `void S<int>::f(int, double)', PARMS should be
+ {int, U}. Thus, the args that we want to subsitute into the
+ return and parameter type for the function are those in TARGS,
+ with the innermost level omitted. */
+ fn_type = TREE_TYPE (tmpl);
+ if (DECL_STATIC_FUNCTION_P (decl))
+ context = DECL_CLASS_CONTEXT (decl);
+
+ if (parm_depth == 1)
+ /* No substitution is necessary. */
+ ;
+ else
+ {
+ int i;
+ tree partial_args;
+
+ /* Replace the innermost level of the TARGS with NULL_TREEs to
+ let tsubst know not to subsitute for those parameters. */
+ partial_args = make_temp_vec (TREE_VEC_LENGTH (targs));
+ for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i)
+ SET_TMPL_ARGS_LEVEL (partial_args, i,
+ TMPL_ARGS_LEVEL (targs, i));
+ SET_TMPL_ARGS_LEVEL (partial_args,
+ TMPL_ARGS_DEPTH (targs),
+ make_temp_vec (DECL_NTPARMS (tmpl)));
+
+ /* Now, do the (partial) substitution to figure out the
+ appropriate function type. */
+ fn_type = tsubst (fn_type, partial_args, /*complain=*/1, NULL_TREE);
+ if (DECL_STATIC_FUNCTION_P (decl))
+ context = tsubst (context, partial_args, /*complain=*/1, NULL_TREE);
+
+ /* Substitute into the template parameters to obtain the real
+ innermost set of parameters. This step is important if the
+ innermost set of template parameters contains value
+ parameters whose types depend on outer template parameters. */
+ TREE_VEC_LENGTH (partial_args)--;
+ tparms = tsubst_template_parms (tparms, partial_args, /*complain=*/1);
+ }
+
+ /* Now, get the innermost parameters and arguments, and figure out
+ the parameter and return types. */
+ tparms = INNERMOST_TEMPLATE_PARMS (tparms);
+ targs = innermost_args (targs);
+ ret_type = TREE_TYPE (fn_type);
+ parm_types = TYPE_ARG_TYPES (fn_type);
+
+ /* For a static member function, we generate a fake `this' pointer,
+ for the purposes of mangling. This indicates of which class the
+ function is a member. Because of:
+
+ [class.static]
+
+ There shall not be a static and a nonstatic member function
+ with the same name and the same parameter types
+
+ we don't have to worry that this will result in a clash with a
+ non-static member function. */
+ if (DECL_STATIC_FUNCTION_P (decl))
+ parm_types = hash_tree_chain (build_pointer_type (context), parm_types);
+
+ /* There should be the same number of template parameters as
+ template arguments. */
+ my_friendly_assert (TREE_VEC_LENGTH (tparms) == TREE_VEC_LENGTH (targs),
+ 0);
+
+ /* 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_namespace = current_namespace;
+ current_namespace = CP_DECL_CONTEXT (decl);
+
+ /* Actually set the DCL_ASSEMBLER_NAME. */
+ DECL_ASSEMBLER_NAME (decl)
+ = build_decl_overload_real (DECL_NAME (decl), parm_types, ret_type,
+ tparms, targs,
+ DECL_FUNCTION_MEMBER_P (decl)
+ + DECL_CONSTRUCTOR_P (decl));
+
+ /* Restore the previously active namespace. */
+ current_namespace = saved_namespace;
}
diff --git a/contrib/gcc/cp/ptree.c b/contrib/gcc/cp/ptree.c
index aa3066c..1f17aec 100644
--- a/contrib/gcc/cp/ptree.c
+++ b/contrib/gcc/cp/ptree.c
@@ -1,5 +1,5 @@
/* Prints out trees in human readable form.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-96, 1998, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -113,8 +113,6 @@ print_lang_type (file, node, indent)
fputs (" delete", file);
if (TYPE_GETS_DELETE (node) & 2)
fputs (" delete[]", file);
- if (TYPE_HAS_ASSIGNMENT (node))
- fputs (" has=", file);
if (TYPE_HAS_ASSIGN_REF (node))
fputs (" this=(X&)", file);
if (TYPE_OVERLOADS_CALL_EXPR (node))
@@ -128,9 +126,7 @@ print_lang_type (file, node, indent)
if (TREE_CODE (node) == RECORD_TYPE)
{
- fprintf (file, " n_parents %d n_ancestors %d",
- CLASSTYPE_N_BASECLASSES (node),
- CLASSTYPE_N_SUPERCLASSES (node));
+ fprintf (file, " n_parents %d", CLASSTYPE_N_BASECLASSES (node));
fprintf (file, " use_template=%d", CLASSTYPE_USE_TEMPLATE (node));
if (CLASSTYPE_INTERFACE_ONLY (node))
fprintf (file, " interface-only");
@@ -138,9 +134,6 @@ print_lang_type (file, node, indent)
fprintf (file, " interface-unknown");
print_node (file, "member-functions", CLASSTYPE_METHOD_VEC (node),
indent + 4);
- print_node (file, "baselinks",
- TYPE_BINFO_BASETYPES (node) ? CLASSTYPE_BASELINK_VEC (node) : NULL_TREE,
- indent + 4);
}
}
@@ -152,7 +145,7 @@ print_lang_identifier (file, node, indent)
{
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, "local bindings", IDENTIFIER_BINDING (node), indent + 4);
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
@@ -168,7 +161,8 @@ lang_print_xnode (file, node, indent)
switch (TREE_CODE (node))
{
case CPLUS_BINDING:
- print_node (file, "scope", BINDING_SCOPE (node), indent+4);
+ fprintf (file, " scope ");
+ fprintf (file, HOST_PTR_PRINTF, BINDING_SCOPE (node));
print_node (file, "value", BINDING_VALUE (node), indent+4);
print_node (file, "chain", TREE_CHAIN (node), indent+4);
break;
diff --git a/contrib/gcc/cp/repo.c b/contrib/gcc/cp/repo.c
index 742250d..9fa8e5c 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, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96-97, 1998 Free Software Foundation, Inc.
Contributed by Jason Merrill (jason@cygnus.com)
This file is part of GNU CC.
@@ -37,8 +37,8 @@ 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 *get_base_filename PROTO((const char *));
+static void open_repo_file PROTO((const char *));
static char *afgets PROTO((FILE *));
static void reopen_repo_file_for_write PROTO((void));
@@ -99,6 +99,12 @@ repo_get_id (t)
{
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{
+ /* If we're not done setting up the class, we may not have set up
+ the vtable, so going ahead would give the wrong answer.
+ See g++.pt/instantiate4.C. */
+ if (TYPE_SIZE (t) == NULL_TREE || TYPE_BEING_DEFINED (t))
+ my_friendly_abort (981113);
+
t = TYPE_BINFO_VTABLE (t);
if (t == NULL_TREE)
return t;
@@ -233,7 +239,7 @@ extract_string (pp)
static char *
get_base_filename (filename)
- char *filename;
+ const char *filename;
{
char *p = getenv ("COLLECT_GCC_OPTIONS");
char *output = NULL;
@@ -264,10 +270,10 @@ get_base_filename (filename)
static void
open_repo_file (filename)
- char *filename;
+ const char *filename;
{
- register char *p;
- char *s = get_base_filename (filename);
+ register const char *p;
+ const char *s = get_base_filename (filename);
if (s == NULL)
return;
@@ -298,7 +304,7 @@ afgets (stream)
void
init_repo (filename)
- char *filename;
+ const char *filename;
{
char *buf;
diff --git a/contrib/gcc/cp/rtti.c b/contrib/gcc/cp/rtti.c
index b93c1cc..e0ce5cd 100644
--- a/contrib/gcc/cp/rtti.c
+++ b/contrib/gcc/cp/rtti.c
@@ -1,5 +1,5 @@
/* RunTime Type Identification
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96-97, 1998, 1999 Free Software Foundation, Inc.
Mostly written by Jason Merrill (jason@cygnus.com).
This file is part of GNU CC.
@@ -35,18 +35,17 @@ Boston, MA 02111-1307, USA. */
extern struct obstack permanent_obstack;
-static tree call_void_fn PROTO((char *));
+static tree call_void_fn PROTO((const 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 void expand_generic_desc PROTO((tree, tree, const char *));
static tree throw_bad_cast PROTO((void));
static tree throw_bad_typeid PROTO((void));
@@ -60,12 +59,13 @@ 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);
+ (class_type_node, get_identifier ("type_info"), 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)),
+ (build_reference_type (build_qualified_type (type_info_type_node,
+ TYPE_QUAL_CONST)),
void_list_node);
}
@@ -108,6 +108,11 @@ build_headof (exp)
if (!TYPE_VIRTUAL_P (type))
return exp;
+ if (CLASSTYPE_COM_INTERFACE (type))
+ {
+ cp_error ("RTTI not supported for COM interface type `%T'", type);
+ return error_mark_node;
+ }
/* If we don't have rtti stuff, get to a sub-object that does. */
if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))
@@ -123,8 +128,8 @@ build_headof (exp)
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));
+ type = build_qualified_type (ptr_type_node,
+ CP_TYPE_QUALS (TREE_TYPE (exp)));
return build (PLUS_EXPR, type, exp,
cp_convert (ptrdiff_type_node, offset));
}
@@ -133,7 +138,7 @@ build_headof (exp)
static tree
call_void_fn (name)
- char *name;
+ const char *name;
{
tree d = get_identifier (name);
tree type;
@@ -151,11 +156,10 @@ call_void_fn (name)
DECL_ARTIFICIAL (d) = 1;
pushdecl_top_level (d);
make_function_rtl (d);
- assemble_external (d);
-
pop_obstacks ();
}
+ mark_used (d);
return build_call (d, void_type_node, NULL_TREE);
}
@@ -203,6 +207,12 @@ get_tinfo_fn_dynamic (exp)
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
+ if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
+ {
+ cp_error ("taking typeid of incomplete type `%T'", type);
+ return error_mark_node;
+ }
+
/* 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))
{
@@ -210,12 +220,11 @@ get_tinfo_fn_dynamic (exp)
tree t;
if (! flag_rtti)
+ error ("taking dynamic typeid of object with -fno-rtti");
+ if (CLASSTYPE_COM_INTERFACE (type))
{
- warning ("taking dynamic typeid of object without -frtti");
- push_obstacks (&permanent_obstack, &permanent_obstack);
- init_rtti_processing ();
- pop_obstacks ();
- flag_rtti = 1;
+ cp_error ("RTTI not supported for COM interface type `%T'", type);
+ return error_mark_node;
}
/* If we don't have rtti stuff, get to a sub-object that does. */
@@ -252,9 +261,21 @@ build_x_typeid (exp)
tree exp;
{
tree cond = NULL_TREE;
- tree type = TREE_TYPE (tinfo_fn_type);
+ tree type;
int nonnull;
+ if (! flag_rtti)
+ {
+ error ("cannot use typeid with -fno-rtti");
+ return error_mark_node;
+ }
+
+ if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
+ {
+ error ("must #include <typeinfo> before using typeid");
+ return error_mark_node;
+ }
+
if (processing_template_decl)
return build_min_nt (TYPEID_EXPR, exp);
@@ -273,6 +294,7 @@ build_x_typeid (exp)
if (exp == error_mark_node)
return error_mark_node;
+ type = TREE_TYPE (tinfo_fn_type);
exp = build_call (exp, type, NULL_TREE);
if (cond)
@@ -302,7 +324,7 @@ get_tinfo_var (type)
/* 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))
+ if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
else if (TREE_CODE (type) == POINTER_TYPE
&& ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
@@ -366,23 +388,25 @@ get_tinfo_fn (type)
TREE_PUBLIC (d) = 1;
DECL_ARTIFICIAL (d) = 1;
DECL_NOT_REALLY_EXTERN (d) = 1;
- DECL_MUTABLE_P (d) = 1;
+ SET_DECL_TINFO_FN_P (d);
TREE_TYPE (name) = copy_to_permanent (type);
pushdecl_top_level (d);
make_function_rtl (d);
- assemble_external (d);
+ mark_used (d);
mark_inline_for_output (d);
pop_obstacks ();
return d;
}
-static tree
+tree
get_typeid_1 (type)
tree type;
{
- tree t = build_call
+ tree t;
+
+ t = build_call
(get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
return convert_from_reference (t);
}
@@ -395,15 +419,15 @@ get_typeid (type)
{
if (type == error_mark_node)
return error_mark_node;
-
- if (! flag_rtti)
+
+ if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
{
- warning ("requesting typeid of object without -frtti");
- push_obstacks (&permanent_obstack, &permanent_obstack);
- init_rtti_processing ();
- pop_obstacks ();
- flag_rtti = 1;
+ error ("must #include <typeinfo> before using typeid");
+ return error_mark_node;
}
+
+ if (! flag_rtti)
+ error ("requesting typeid with -fno-rtti");
if (processing_template_decl)
return build_min_nt (TYPEID_EXPR, type);
@@ -418,6 +442,12 @@ get_typeid (type)
that is the operand of typeid are always ignored. */
type = TYPE_MAIN_VARIANT (type);
+ if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
+ {
+ cp_error ("taking typeid of incomplete type `%T'", type);
+ return error_mark_node;
+ }
+
return get_typeid_1 (type);
}
@@ -442,10 +472,15 @@ build_dynamic_cast_1 (type, expr)
tree type, expr;
{
enum tree_code tc = TREE_CODE (type);
- tree exprtype = TREE_TYPE (expr);
+ tree exprtype;
enum tree_code ec;
tree dcast_fn;
+ tree old_expr = expr;
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
+
+ exprtype = TREE_TYPE (expr);
assert (exprtype != NULL_TREE);
ec = TREE_CODE (exprtype);
@@ -464,8 +499,8 @@ build_dynamic_cast_1 (type, expr)
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)))
+ if (!at_least_as_qualified_p (TREE_TYPE (type),
+ TREE_TYPE (exprtype)))
goto fail;
if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
break;
@@ -484,8 +519,6 @@ build_dynamic_cast_1 (type, expr)
/* 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);
@@ -500,8 +533,8 @@ build_dynamic_cast_1 (type, expr)
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)))
+ if (!at_least_as_qualified_p (TREE_TYPE (type),
+ TREE_TYPE (exprtype)))
goto fail;
}
@@ -513,6 +546,20 @@ build_dynamic_cast_1 (type, expr)
distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
&path);
+
+ if (distance == -2)
+ {
+ cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
+ TREE_TYPE (exprtype), TREE_TYPE (type));
+ return error_mark_node;
+ }
+ if (distance == -3)
+ {
+ cp_error ("dynamic_cast from `%T' to private base class `%T'",
+ TREE_TYPE (exprtype), TREE_TYPE (type));
+ return error_mark_node;
+ }
+
if (distance >= 0)
return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
}
@@ -548,11 +595,11 @@ build_dynamic_cast_1 (type, expr)
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)
+ if (TREE_CODE (old_expr) == VAR_DECL
+ && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
{
cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
- expr, type);
+ old_expr, type);
return throw_bad_cast ();
}
}
@@ -564,7 +611,7 @@ build_dynamic_cast_1 (type, expr)
&& TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
{
cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
- expr, type);
+ op, type);
retval = build_int_2 (0, 0);
TREE_TYPE (retval) = type;
return retval;
@@ -622,10 +669,10 @@ build_dynamic_cast_1 (type, expr)
DECL_ARTIFICIAL (dcast_fn) = 1;
pushdecl_top_level (dcast_fn);
make_function_rtl (dcast_fn);
- assemble_external (dcast_fn);
pop_obstacks ();
}
+ mark_used (dcast_fn);
result = build_call
(dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
@@ -689,7 +736,7 @@ expand_si_desc (tdecl, type)
tree type;
{
tree t, elems, fn;
- char *name = build_overload_name (type, 1, 1);
+ const 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));
@@ -720,10 +767,10 @@ expand_si_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -737,7 +784,7 @@ expand_class_desc (tdecl, type)
{
tree name_string;
tree fn, tmp;
- char *name;
+ const char *name;
int i = CLASSTYPE_N_BASECLASSES (type);
int base_cnt = 0;
@@ -763,7 +810,9 @@ expand_class_desc (tdecl, 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)));
+ build_pointer_type (build_qualified_type
+ (type_info_type_node,
+ TYPE_QUAL_CONST)));
fields [1] = build_lang_field_decl
(FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
DECL_BIT_FIELD (fields[1]) = 1;
@@ -795,11 +844,10 @@ expand_class_desc (tdecl, type)
if (TREE_VIA_VIRTUAL (binfo))
{
tree t = BINFO_TYPE (binfo);
- char *name;
+ const char *name;
tree field;
- name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
- sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
+ FORMAT_VBASE_NAME (name, 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));
@@ -900,10 +948,10 @@ expand_class_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -916,7 +964,7 @@ expand_ptr_desc (tdecl, type)
tree type;
{
tree t, elems, fn;
- char *name = build_overload_name (type, 1, 1);
+ const char *name = build_overload_name (type, 1, 1);
tree name_string = combine_strings (build_string (strlen (name)+1, name));
type = TREE_TYPE (type);
@@ -947,10 +995,10 @@ expand_ptr_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -963,10 +1011,9 @@ expand_attr_desc (tdecl, type)
tree type;
{
tree elems, t, fn;
- char *name = build_overload_name (type, 1, 1);
+ const 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);
+ tree attrval = build_int_2 (TYPE_QUALS (type), 0);
expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
@@ -996,10 +1043,10 @@ expand_attr_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -1010,9 +1057,9 @@ static void
expand_generic_desc (tdecl, type, fnname)
tree tdecl;
tree type;
- char *fnname;
+ const char *fnname;
{
- char *name = build_overload_name (type, 1, 1);
+ const 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
@@ -1036,10 +1083,10 @@ expand_generic_desc (tdecl, type, fnname)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -1089,14 +1136,14 @@ synthesize_tinfo_fn (fndecl)
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);
+ tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node);
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))
+ else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
expand_attr_desc (tdecl, type);
else if (TREE_CODE (type) == POINTER_TYPE)
{
diff --git a/contrib/gcc/cp/search.c b/contrib/gcc/cp/search.c
index d5971e0..8760c6a 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-96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-97, 1998, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "output.h"
#include "toplev.h"
+#include "varray.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -76,80 +77,80 @@ pop_stack_level (stack)
#define search_level stack_level
static struct search_level *search_stack;
-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 next_baselink PROTO((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 tree dfs_check_overlap PROTO((tree, void *));
+static tree dfs_no_overlap_yet PROTO((tree, void *));
static int get_base_distance_recursive
- PROTO((tree, int, int, int, int *, tree *, tree, tree *,
+ PROTO((tree, int, int, int, int *, 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 tree unmarkedp PROTO((tree, void *));
+static tree marked_vtable_pathp PROTO((tree, void *));
+static tree unmarked_vtable_pathp PROTO((tree, void *));
+static tree marked_new_vtablep PROTO((tree, void *));
+static tree unmarked_new_vtablep PROTO((tree, void *));
+static tree marked_pushdecls_p PROTO((tree, void *));
+static tree unmarked_pushdecls_p PROTO((tree, void *));
+static tree dfs_debug_unmarkedp PROTO((tree, void *));
+static tree dfs_debug_mark PROTO((tree, void *));
+static tree dfs_find_vbases PROTO((tree, void *));
+static tree dfs_clear_vbase_slots PROTO((tree, void *));
+static tree dfs_init_vbase_pointers PROTO((tree, void *));
+static tree dfs_get_vbase_types PROTO((tree, void *));
+static tree dfs_push_type_decls PROTO((tree, void *));
+static tree dfs_push_decls PROTO((tree, void *));
+static tree dfs_unuse_fields PROTO((tree, void *));
+static tree add_conversions PROTO((tree, void *));
+static tree get_virtuals_named_this PROTO((tree, tree));
+static tree get_virtual_destructor PROTO((tree, void *));
+static tree tree_has_any_destructor_p PROTO((tree, void *));
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_ptr_intermediate, vbase_decl_ptr;
-static tree vbase_init_result;
+static tree bfs_walk
+ PROTO((tree, tree (*) (tree, void *), tree (*) (tree, void *),
+ void *));
+static tree lookup_field_queue_p PROTO((tree, void *));
+static tree lookup_field_r PROTO((tree, void *));
+static tree dfs_walk_real PROTO ((tree,
+ tree (*) (tree, void *),
+ tree (*) (tree, void *),
+ tree (*) (tree, void *),
+ void *));
+static tree dfs_bfv_queue_p PROTO ((tree, void *));
+static tree dfs_bfv_helper PROTO ((tree, void *));
+static tree get_virtuals_named_this_r PROTO ((tree, void *));
+static tree context_for_name_lookup PROTO ((tree));
+static tree canonical_binfo PROTO ((tree));
+static tree shared_marked_p PROTO ((tree, void *));
+static tree shared_unmarked_p PROTO ((tree, void *));
+static int dependent_base_p PROTO ((tree));
+static tree dfs_accessible_queue_p PROTO ((tree, void *));
+static tree dfs_accessible_p PROTO ((tree, void *));
+static tree dfs_access_in_type PROTO ((tree, void *));
+static tree access_in_type PROTO ((tree, tree));
+static tree dfs_canonical_queue PROTO ((tree, void *));
+static tree dfs_assert_unmarked_p PROTO ((tree, void *));
+static void assert_canonical_unmarked PROTO ((tree));
+static int protected_accessible_p PROTO ((tree, tree, tree, tree));
+static int friend_accessible_p PROTO ((tree, tree, tree, tree));
+static void setup_class_bindings PROTO ((tree, int));
+static int template_self_reference_p PROTO ((tree, tree));
/* Allocate a level of searching. */
@@ -175,39 +176,9 @@ pop_search_level (obstack)
return stack;
}
-/* Search memoization. */
-
-struct type_level
-{
- struct stack_level base;
-
- /* First object allocated in obstack of entries. */
- char *entries;
-
- /* Number of types memoized in this context. */
- int len;
-
- /* Type being memoized; save this if we are saving
- memoized contexts. */
- tree type;
-};
-
-/* Obstack used for memoizing member and member function lookup. */
-
-static struct obstack type_obstack, type_obstack_entries;
-static struct type_level *type_stack;
static tree _vptr_name;
-/* Make things that look like tree nodes, but allocate them
- on type_obstack_entries. */
-static int my_tree_node_counter;
-
-extern int flag_memoize_lookups, flag_save_memoized_contexts;
-
/* Variables for gathering statistics. */
-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;
@@ -217,264 +188,14 @@ 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;
-static struct type_level *prev_type_stack;
-
-/* This list is used by push_class_decls to know what decls need to
- be pushed into class scope. */
-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;
- struct obstack *obstack;
-{
- struct type_level tem;
-
- tem.base.prev = stack;
-
- obstack_finish (&type_obstack_entries);
- tem.entries = (char *) obstack_base (&type_obstack_entries);
- tem.len = 0;
- tem.type = NULL_TREE;
-
- return (struct type_level *)push_stack_level (obstack, (char *)&tem, sizeof (tem));
-}
-
-/* Discard a level of type memoization context. */
-
-static struct type_level *
-pop_type_level (stack)
- struct type_level *stack;
-{
- obstack_free (&type_obstack_entries, stack->entries);
- return (struct type_level *)pop_stack_level ((struct stack_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;
- 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;
- return p;
-}
-
-static tree
-my_build_string (str)
- char *str;
-{
- tree p = (tree)obstack_alloc (&type_obstack_entries, sizeof (struct tree_string));
- ++my_tree_node_counter;
- TREE_TYPE (p) = 0;
- ((int *)p)[3] = 0;
- TREE_SET_CODE (p, STRING_CST);
- TREE_STRING_POINTER (p) = str;
- TREE_STRING_LENGTH (p) = strlen (str);
- return p;
-}
-
-/* Memoizing machinery to make searches for multiple inheritance
- reasonably efficient. */
-
-#define MEMOIZE_HASHSIZE 8
-typedef struct memoized_entry
-{
- struct memoized_entry *chain;
- int uid;
- tree data_members[MEMOIZE_HASHSIZE];
- tree function_members[MEMOIZE_HASHSIZE];
-} *ME;
-
-#define MEMOIZED_CHAIN(ENTRY) (((ME)ENTRY)->chain)
-#define MEMOIZED_UID(ENTRY) (((ME)ENTRY)->uid)
-#define MEMOIZED_FIELDS(ENTRY,INDEX) (((ME)ENTRY)->data_members[INDEX])
-#define MEMOIZED_FNFIELDS(ENTRY,INDEX) (((ME)ENTRY)->function_members[INDEX])
-/* The following is probably a lousy hash function. */
-#define MEMOIZED_HASH_FN(NODE) (((long)(NODE)>>4)&(MEMOIZE_HASHSIZE - 1))
-
-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));
- 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. */
-
-static tree
-make_memoized_table_entry (type, name, function_p)
- tree type, name;
- int function_p;
-{
- 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)
- {
- obstack_ptr_grow (&type_obstack, type);
- obstack_blank (&type_obstack, sizeof (struct memoized_entry *));
- CLASSTYPE_MTABLE_ENTRY (type) = (char *)my_new_memoized_entry ((struct memoized_entry *)0);
- type_stack->len++;
- if (type_stack->len * 2 >= type_stack->base.limit)
- my_friendly_abort (88);
- }
- if (function_p)
- prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
- else
- prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
-
- entry = my_tree_cons (name, NULL_TREE, *prev_entry);
- *prev_entry = entry;
-
- /* Don't know the error message to give yet. */
- TREE_TYPE (entry) = error_mark_node;
-
- return entry;
-}
-
-/* When a new function or class context is entered, we build
- a table of types which have been searched for members.
- The table is an array (obstack) of types. When a type is
- entered into the obstack, its CLASSTYPE_MTABLE_ENTRY
- field is set to point to a new record, of type struct memoized_entry.
-
- A non-NULL TREE_TYPE of the entry contains an access control error message.
-
- The slots for the data members are arrays of tree nodes.
- These tree nodes are lists, with the TREE_PURPOSE
- of this list the known member name, and the TREE_VALUE
- as the FIELD_DECL for the member.
-
- For member functions, the TREE_PURPOSE is again the
- name of the member functions for that class,
- and the TREE_VALUE of the list is a pairs
- whose TREE_PURPOSE is a member functions of this name,
- and whose TREE_VALUE is a list of known argument lists this
- member function has been called with. The TREE_TYPE of the pair,
- if non-NULL, is an error message to print. */
-
-/* Tell search machinery that we are entering a new context, and
- to update tables appropriately.
-
- TYPE is the type of the context we are entering, which can
- 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;
- int use_old;
-{
- int len;
- tree *tem;
-
- if (prev_type_stack)
- {
- if (use_old && prev_type_memoized == type)
- {
-#ifdef GATHER_STATISTICS
- n_contexts_saved++;
-#endif /* GATHER_STATISTICS */
- type_stack = prev_type_stack;
- prev_type_stack = 0;
-
- tem = &type_stack->base.first[0];
- len = type_stack->len;
- while (len--)
- CLASSTYPE_MTABLE_ENTRY (tem[len*2]) = (char *)tem[len*2+1];
- return;
- }
- /* Otherwise, need to pop old stack here. */
- clear_memoized_cache ();
- }
-
- type_stack = push_type_level ((struct stack_level *)type_stack,
- &type_obstack);
- type_stack->type = type;
-}
-
-/* Tell search machinery that we have left a context.
- We do not currently save these contexts for later use.
- 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;
-{
- int len;
- tree *tem = &type_stack->base.first[0];
-
- if (! flag_save_memoized_contexts)
- use_old = 0;
- else if (use_old)
- {
- len = type_stack->len;
- 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;
- }
-
- if (flag_memoize_lookups)
- {
- len = type_stack->len;
- while (len--)
- CLASSTYPE_MTABLE_ENTRY (tem[len*2])
- = (char *)MEMOIZED_CHAIN (CLASSTYPE_MTABLE_ENTRY (tem[len*2]));
- }
- if (! use_old)
- type_stack = pop_type_level (type_stack);
- else
- type_stack = (struct type_level *)type_stack->base.prev;
-}
/* 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. */
+ virtual bases.
+
+ This uses a clever algorithm that updates *depth when we find the vbase,
+ and cuts off other paths of search when they reach that depth. */
static tree
get_vbase_1 (parent, binfo, depth)
@@ -513,6 +234,9 @@ get_vbase_1 (parent, binfo, depth)
return rval;
}
+/* Return the shortest path to vbase PARENT within BINFO, ignoring
+ access and ambiguity. */
+
tree
get_vbase (parent, binfo)
tree parent;
@@ -589,13 +313,13 @@ get_binfo (parent, binfo, protect)
static int
get_base_distance_recursive (binfo, depth, is_private, rval,
- rval_private_ptr, new_binfo_ptr, parent, path_ptr,
+ rval_private_ptr, new_binfo_ptr, parent,
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;
+ tree *new_binfo_ptr, parent;
int protect, *via_virtual_ptr, via_virtual;
int current_scope_in_chain;
{
@@ -609,38 +333,42 @@ get_base_distance_recursive (binfo, depth, is_private, rval,
if (BINFO_TYPE (binfo) == parent || binfo == parent)
{
+ int better = 0;
+
if (rval == -1)
+ /* This is the first time we've found parent. */
+ better = 1;
+ else if (tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
+ BINFO_OFFSET (binfo))
+ && *via_virtual_ptr && via_virtual)
+ {
+ /* A new path to the same vbase. If this one has better
+ access or is shorter, take it. */
+
+ if (protect)
+ better = *rval_private_ptr - is_private;
+ if (better == 0)
+ better = rval - depth;
+ }
+ else
+ {
+ /* Ambiguous base class. */
+ rval = depth = -2;
+
+ /* If we get an ambiguity between virtual and non-virtual base
+ class, return the non-virtual in case we are ignoring
+ ambiguity. */
+ better = *via_virtual_ptr - via_virtual;
+ }
+
+ if (better > 0)
{
rval = depth;
*rval_private_ptr = is_private;
*new_binfo_ptr = binfo;
*via_virtual_ptr = via_virtual;
}
- else
- {
- int same_object = (tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
- BINFO_OFFSET (binfo))
- && *via_virtual_ptr && via_virtual);
-
- if (*via_virtual_ptr && via_virtual==0)
- {
- *rval_private_ptr = is_private;
- *new_binfo_ptr = binfo;
- *via_virtual_ptr = via_virtual;
- }
- else if (same_object)
- {
- if (*rval_private_ptr && ! is_private)
- {
- *rval_private_ptr = is_private;
- *new_binfo_ptr = binfo;
- *via_virtual_ptr = via_virtual;
- }
- return rval;
- }
- rval = -2;
- }
return rval;
}
@@ -653,43 +381,26 @@ get_base_distance_recursive (binfo, depth, is_private, rval,
{
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 || 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. */
- if (! this_virtual)
- SET_BINFO_MARKED (base_binfo);
-
-#define WATCH_VALUES(rval, via_private) (rval == -1 ? 3 : via_private)
-
- was = WATCH_VALUES (rval, *via_virtual_ptr);
- rval = get_base_distance_recursive (base_binfo, depth, via_private,
- rval, rval_private_ptr,
- new_binfo_ptr, parent, path_ptr,
- protect, via_virtual_ptr,
- 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)
- return rval;
+ 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);
-#undef WATCH_VALUES
+ rval = get_base_distance_recursive (base_binfo, depth, via_private,
+ rval, rval_private_ptr,
+ new_binfo_ptr, parent,
+ protect, via_virtual_ptr,
+ this_virtual,
+ current_scope_in_chain);
- }
+ /* If we've found a non-virtual, ambiguous base class, we don't need
+ to keep searching. */
+ if (rval == -2 && *via_virtual_ptr == 0)
+ return rval;
}
return rval;
@@ -698,7 +409,7 @@ get_base_distance_recursive (binfo, depth, is_private, rval,
/* Return the number of levels between type PARENT and the type given
in BINFO, following the leftmost path to PARENT not found along a
virtual path, if there are no real PARENTs (all come from virtual
- base classes), then follow the leftmost path to PARENT.
+ base classes), then follow the shortest public path to PARENT.
Return -1 if TYPE is not derived from PARENT.
Return -2 if PARENT is an ambiguous base class of TYPE, and PROTECT is
@@ -741,7 +452,8 @@ get_base_distance (parent, binfo, protect, path_ptr)
binfo = TYPE_BINFO (type);
if (path_ptr)
- BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (binfo) == NULL_TREE,
+ 980827);
}
else
my_friendly_abort (92);
@@ -760,11 +472,9 @@ get_base_distance (parent, binfo, protect, path_ptr)
rval = get_base_distance_recursive (binfo, 0, 0, -1,
&rval_private, &new_binfo, parent,
- path_ptr, watch_access, &via_virtual, 0,
+ watch_access, &via_virtual, 0,
0);
- dfs_walk (binfo, dfs_unmark, markedp);
-
/* Access restrictions don't count if we found an ambiguous basetype. */
if (rval == -2 && protect >= 0)
rval_private = 0;
@@ -772,12 +482,14 @@ get_base_distance (parent, binfo, protect, path_ptr)
if (rval && protect && rval_private)
return -3;
- /* find real virtual base classes. */
+ /* If they gave us the real vbase binfo, which isn't in the main binfo
+ tree, deal with it. This happens when we are called from
+ expand_upcast_fixups. */
if (rval == -1 && TREE_CODE (parent) == TREE_VEC
&& parent == binfo_member (BINFO_TYPE (parent),
CLASSTYPE_VBASECLASSES (type)))
{
- BINFO_INHERITANCE_CHAIN (parent) = binfo;
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (parent) == binfo, 980827);
new_binfo = parent;
rval = 1;
}
@@ -828,7 +540,14 @@ lookup_field_1 (type, name)
if (temp)
return temp;
}
- if (DECL_NAME (field) == name)
+ if (TREE_CODE (field) == USING_DECL)
+ /* For now, we're just treating member using declarations as
+ old ARM-style access declarations. Thus, there's no reason
+ to return a USING_DECL, and the rest of the compiler can't
+ handle it. Once the class is defined, these are purged
+ from TYPE_FIELDS anyhow; see handle_using_decl. */
+ ;
+ else if (DECL_NAME (field) == name)
{
if ((TREE_CODE(field) == VAR_DECL || TREE_CODE(field) == CONST_DECL)
&& DECL_ASSEMBLER_NAME (field) != NULL)
@@ -877,210 +596,461 @@ current_scope ()
return current_class_type;
}
-/* Compute the access of FIELD. This is done by computing
- the access available to each type in BASETYPES (which comes
- as a list of [via_public/basetype] in reverse order, namely base
- class before derived class). The first one which defines a
- access defines the access for the field. Otherwise, the
- access of the field is that which occurs normally.
+/* Return the scope of DECL, as appropriate when doing name-lookup. */
- Uses global variables CURRENT_CLASS_TYPE and
- CURRENT_FUNCTION_DECL to use friend relationships
- if necessary.
+static tree
+context_for_name_lookup (decl)
+ tree decl;
+{
+ /* [class.union]
+
+ For the purposes of name lookup, after the anonymous union
+ definition, the members of the anonymous union are considered to
+ have been defined in the scope in which teh anonymous union is
+ declared. */
+ tree context = DECL_REAL_CONTEXT (decl);
+
+ while (TYPE_P (context) && ANON_UNION_TYPE_P (context))
+ context = TYPE_CONTEXT (context);
+ if (!context)
+ context = global_namespace;
- This will be static when lookup_fnfield comes into this file.
+ return context;
+}
- access_public_node means that the field can be accessed by the current lexical
- scope.
+/* Return a canonical BINFO if BINFO is a virtual base, or just BINFO
+ otherwise. */
- access_protected_node means that the field cannot be accessed by the current
- lexical scope because it is protected.
+static tree
+canonical_binfo (binfo)
+ tree binfo;
+{
+ return (TREE_VIA_VIRTUAL (binfo)
+ ? TYPE_BINFO (BINFO_TYPE (binfo)) : binfo);
+}
- access_private_node means that the field cannot be accessed by the current
- lexical scope because it is private. */
+/* A queue function that simply ensures that we walk into the
+ canonical versions of virtual bases. */
-#if 0
-#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_node
-#define PROTECTED_RETURN return access_protected_node
-#define PRIVATE_RETURN return access_private_node
-#endif
+static tree
+dfs_canonical_queue (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return canonical_binfo (binfo);
+}
-#if 0
-/* Disabled with DECL_PUBLIC &c. */
-static tree previous_scope = NULL_TREE;
-#endif
+/* Called via dfs_walk from assert_canonical_unmarked. */
-tree
-compute_access (basetype_path, field)
- tree basetype_path, field;
+static tree
+dfs_assert_unmarked_p (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
{
- tree access;
- tree types;
- tree context;
- int protected_ok, via_protected;
- extern int flag_access_control;
-#if 1
- /* 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)));
+ my_friendly_assert (!BINFO_MARKED (binfo), 0);
+ return NULL_TREE;
+}
- if (! flag_access_control)
- return access_public_node;
+/* Asserts that all the nodes below BINFO (using the canonical
+ versions of virtual bases) are unmarked. */
- /* The field lives in the current class. */
- if (BINFO_TYPE (basetype_path) == current_class_type)
- return access_public_node;
+static void
+assert_canonical_unmarked (binfo)
+ tree binfo;
+{
+ dfs_walk (binfo, dfs_assert_unmarked_p, dfs_canonical_queue, 0);
+}
-#if 0
- /* Disabled until pushing function scope clears these out. If ever. */
- /* Make these special cases fast. */
- if (current_scope () == previous_scope)
- {
- if (DECL_PUBLIC (field))
- return access_public_node;
- if (DECL_PROTECTED (field))
- return access_protected_node;
- if (DECL_PRIVATE (field))
- return access_private_node;
- }
-#endif
+/* If BINFO is marked, return a canonical version of BINFO.
+ Otherwise, return NULL_TREE. */
- /* We don't currently support access control on nested types. */
- if (TREE_CODE (field) == TYPE_DECL)
- return access_public_node;
+static tree
+shared_marked_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ binfo = canonical_binfo (binfo);
+ return markedp (binfo, data) ? binfo : NULL_TREE;
+}
- previous_scope = current_scope ();
+/* If BINFO is not marked, return a canonical version of BINFO.
+ Otherwise, return NULL_TREE. */
- context = DECL_REAL_CONTEXT (field);
+static tree
+shared_unmarked_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ binfo = canonical_binfo (binfo);
+ return unmarkedp (binfo, data) ? binfo : NULL_TREE;
+}
- /* 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. */
- if (context && ANON_UNION_TYPE_P (context)
- && TREE_CODE (field) == FIELD_DECL)
- context = TYPE_CONTEXT (context);
+/* Called from access_in_type via dfs_walk. Calculate the access to
+ DATA (which is really a DECL) in BINFO. */
- /* Virtual function tables are never private. But we should know that
- we are looking for this, and not even try to hide it. */
- if (DECL_NAME (field) && VFIELD_NAME_P (DECL_NAME (field)) == 1)
- PUBLIC_RETURN;
-
- /* Member found immediately within object. */
- if (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE)
- {
- /* Are we (or an enclosing scope) friends with the class that has
- FIELD? */
- if (is_friend (context, previous_scope))
- PUBLIC_RETURN;
-
- /* If it's private, it's private, you letch. */
- if (TREE_PRIVATE (field))
- PRIVATE_RETURN;
-
- /* ARM $11.5. Member functions of a derived class can access the
- non-static protected members of a base class only through a
- pointer to the derived class, a reference to it, or an object
- of it. Also any subsequently derived classes also have
- access. */
- else if (TREE_PROTECTED (field))
- {
- if (current_class_type
- && (static_mem || DECL_CONSTRUCTOR_P (field))
- && ACCESSIBLY_DERIVED_FROM_P (context, current_class_type))
- PUBLIC_RETURN;
- else
- PROTECTED_RETURN;
- }
+static tree
+dfs_access_in_type (binfo, data)
+ tree binfo;
+ void *data;
+{
+ tree decl = (tree) data;
+ tree type = BINFO_TYPE (binfo);
+ tree access = NULL_TREE;
+
+ if (context_for_name_lookup (decl) == type)
+ {
+ /* If we have desceneded to the scope of DECL, just note the
+ appropriate access. */
+ if (TREE_PRIVATE (decl))
+ access = access_private_node;
+ else if (TREE_PROTECTED (decl))
+ access = access_protected_node;
else
- PUBLIC_RETURN;
+ access = access_public_node;
}
-
- /* must reverse more than one element */
- basetype_path = reverse_path (basetype_path);
- types = basetype_path;
- via_protected = 0;
- access = access_default_node;
- protected_ok = static_mem && current_class_type
- && ACCESSIBLY_DERIVED_FROM_P (BINFO_TYPE (types), current_class_type);
-
- while (1)
+ else
{
- tree member;
- tree binfo = types;
- tree type = BINFO_TYPE (binfo);
- int private_ok = 0;
-
- /* Friends of a class can see protected members of its bases.
- Note that classes are their own friends. */
- if (is_friend (type, previous_scope))
- {
- protected_ok = 1;
- private_ok = 1;
- }
-
- member = purpose_member (type, DECL_ACCESS (field));
- if (member)
+ /* First, check for an access-declaration that gives us more
+ access to the DECL. The CONST_DECL for an enumeration
+ constant will not have DECL_LANG_SPECIFIC, and thus no
+ DECL_ACCESS. */
+ if (DECL_LANG_SPECIFIC (decl))
{
- access = TREE_VALUE (member);
- break;
+ access = purpose_member (type, DECL_ACCESS (decl));
+ if (access)
+ access = TREE_VALUE (access);
}
- types = BINFO_INHERITANCE_CHAIN (types);
-
- /* If the next type was VIA_PROTECTED, then fields of all remaining
- classes past that one are *at least* protected. */
- if (types)
+ if (!access)
{
- if (TREE_VIA_PROTECTED (types))
- via_protected = 1;
- else if (! TREE_VIA_PUBLIC (types) && ! private_ok)
+ int i;
+ int n_baselinks;
+ tree binfos;
+
+ /* Otherwise, scan our baseclasses, and pick the most favorable
+ access. */
+ binfos = BINFO_BASETYPES (binfo);
+ n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ for (i = 0; i < n_baselinks; ++i)
{
- access = access_private_node;
- break;
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ tree base_access = TREE_CHAIN (canonical_binfo (base_binfo));
+
+ if (!base_access || base_access == access_private_node)
+ /* If it was not accessible in the base, or only
+ accessible as a private member, we can't access it
+ all. */
+ base_access = NULL_TREE;
+ else if (TREE_VIA_PROTECTED (base_binfo))
+ /* Public and protected members in the base are
+ protected here. */
+ base_access = access_protected_node;
+ else if (!TREE_VIA_PUBLIC (base_binfo))
+ /* Public and protected members in the base are
+ private here. */
+ base_access = access_private_node;
+
+ /* See if the new access, via this base, gives more
+ access than our previous best access. */
+ if (base_access &&
+ (base_access == access_public_node
+ || (base_access == access_protected_node
+ && access != access_public_node)
+ || (base_access == access_private_node
+ && !access)))
+ {
+ access = base_access;
+
+ /* If the new access is public, we can't do better. */
+ if (access == access_public_node)
+ break;
+ }
}
}
- else
- break;
}
- reverse_path (basetype_path);
- /* No special visibilities apply. Use normal rules. */
+ /* Note the access to DECL in TYPE. */
+ TREE_CHAIN (binfo) = access;
+
+ /* Mark TYPE as visited so that if we reach it again we do not
+ duplicate our efforts here. */
+ SET_BINFO_MARKED (binfo);
+
+ return NULL_TREE;
+}
+
+/* Return the access to DECL in TYPE. */
+
+static tree
+access_in_type (type, decl)
+ tree type;
+ tree decl;
+{
+ tree binfo = TYPE_BINFO (type);
+
+ /* We must take into account
+
+ [class.paths]
+
+ If a name can be reached by several paths through a multiple
+ inheritance graph, the access is that of the path that gives
+ most access.
+
+ The algorithm we use is to make a post-order depth-first traversal
+ of the base-class hierarchy. As we come up the tree, we annotate
+ each node with the most lenient access. */
+ dfs_walk_real (binfo, 0, dfs_access_in_type, shared_unmarked_p, decl);
+ dfs_walk (binfo, dfs_unmark, shared_marked_p, 0);
+ assert_canonical_unmarked (binfo);
+
+ return TREE_CHAIN (binfo);
+}
+
+/* Called from dfs_accessible_p via dfs_walk. */
+
+static tree
+dfs_accessible_queue_p (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ if (BINFO_MARKED (binfo))
+ return NULL_TREE;
+
+ /* If this class is inherited via private or protected inheritance,
+ then we can't see it, unless we are a friend of the subclass. */
+ if (!TREE_VIA_PUBLIC (binfo)
+ && !is_friend (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
+ current_scope ()))
+ return NULL_TREE;
+
+ return canonical_binfo (binfo);
+}
+
+/* Called from dfs_accessible_p via dfs_walk. */
+
+static tree
+dfs_accessible_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ int protected_ok = data != 0;
+ tree access;
+
+ /* We marked the binfos while computing the access in each type.
+ So, we unmark as we go now. */
+ SET_BINFO_MARKED (binfo);
+
+ access = TREE_CHAIN (binfo);
+ if (access == access_public_node
+ || (access == access_protected_node && protected_ok))
+ return binfo;
+ else if (access && is_friend (BINFO_TYPE (binfo), current_scope ()))
+ return binfo;
+
+ return NULL_TREE;
+}
+
+/* Returns non-zero if it is OK to access DECL when named in TYPE
+ through an object indiated by BINFO in the context of DERIVED. */
+
+static int
+protected_accessible_p (type, decl, derived, binfo)
+ tree type;
+ tree decl;
+ tree derived;
+ tree binfo;
+{
+ tree access;
+
+ /* We're checking this clause from [class.access.base]
+
+ m as a member of N is protected, and the reference occurs in a
+ member or friend of class N, or in a member or friend of a
+ class P derived from N, where m as a member of P is private or
+ protected.
- if (access == access_default_node)
+ If DERIVED isn't derived from TYPE, then it certainly does not
+ apply. */
+ if (!DERIVED_FROM_P (type, derived))
+ return 0;
+
+ access = access_in_type (derived, decl);
+ if (same_type_p (derived, type))
{
- if (is_friend (context, previous_scope))
- access = access_public_node;
- else if (TREE_PRIVATE (field))
- access = access_private_node;
- else if (TREE_PROTECTED (field))
- access = access_protected_node;
- else
- access = access_public_node;
+ if (access != access_private_node)
+ return 0;
+ }
+ else if (access != access_private_node
+ && access != access_protected_node)
+ return 0;
+
+ /* [class.protected]
+
+ When a friend or a member function of a derived class references
+ a protected nonstatic member of a base class, an access check
+ applies in addition to those described earlier in clause
+ _class.access_.4) Except when forming a pointer to member
+ (_expr.unary.op_), the access must be through a pointer to,
+ reference to, or object of the derived class itself (or any class
+ derived from that class) (_expr.ref_). If the access is to form
+ a pointer to member, the nested-name-specifier shall name the
+ derived class (or any class derived from that class). */
+ if (DECL_NONSTATIC_MEMBER_P (decl))
+ {
+ /* We can tell through what the reference is occurring by
+ chasing BINFO up to the root. */
+ tree t = binfo;
+ while (BINFO_INHERITANCE_CHAIN (t))
+ t = BINFO_INHERITANCE_CHAIN (t);
+
+ if (!DERIVED_FROM_P (derived, BINFO_TYPE (t)))
+ return 0;
}
- if (access == access_public_node && via_protected)
- access = access_protected_node;
+ return 1;
+}
- if (access == access_protected_node && protected_ok)
- access = access_public_node;
+/* Returns non-zero if SCOPE is a friend of a type which would be able
+ to acces DECL, named in TYPE, through the object indicated by
+ BINFO. */
-#if 0
- if (access == access_public_node)
- DECL_PUBLIC (field) = 1;
- else if (access == access_protected_node)
- DECL_PROTECTED (field) = 1;
- else if (access == access_private_node)
- DECL_PRIVATE (field) = 1;
- else my_friendly_abort (96);
-#endif
- return access;
+static int
+friend_accessible_p (scope, type, decl, binfo)
+ tree scope;
+ tree type;
+ tree decl;
+ tree binfo;
+{
+ tree befriending_classes;
+ tree t;
+
+ if (!scope)
+ return 0;
+
+ if (TREE_CODE (scope) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (scope))
+ befriending_classes = DECL_BEFRIENDING_CLASSES (scope);
+ else if (TYPE_P (scope))
+ befriending_classes = CLASSTYPE_BEFRIENDING_CLASSES (scope);
+ else
+ return 0;
+
+ for (t = befriending_classes; t; t = TREE_CHAIN (t))
+ if (protected_accessible_p (type, decl, TREE_VALUE (t), binfo))
+ return 1;
+
+ if (TREE_CODE (scope) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (scope))
+ {
+ /* Perhaps this SCOPE is a member of a class which is a
+ friend. */
+ if (friend_accessible_p (DECL_CLASS_CONTEXT (scope), type,
+ decl, binfo))
+ return 1;
+
+ /* Or an instantiation of something which is a friend. */
+ if (DECL_TEMPLATE_INFO (scope))
+ return friend_accessible_p (DECL_TI_TEMPLATE (scope),
+ type, decl, binfo);
+ }
+ else if (CLASSTYPE_TEMPLATE_INFO (scope))
+ return friend_accessible_p (CLASSTYPE_TI_TEMPLATE (scope),
+ type, decl, binfo);
+
+ return 0;
+}
+
+/* DECL is a declaration from a base class of TYPE, which was the
+ classs used to name DECL. Return non-zero if, in the current
+ context, DECL is accessible. If TYPE is actually a BINFO node,
+ then we can tell in what context the access is occurring by looking
+ at the most derived class along the path indicated by BINFO. */
+
+int
+accessible_p (type, decl)
+ tree type;
+ tree decl;
+
+{
+ tree binfo;
+ tree t;
+
+ /* Non-zero if it's OK to access DECL if it has protected
+ accessibility in TYPE. */
+ int protected_ok = 0;
+
+ /* If we're not checking access, everything is accessible. */
+ if (!flag_access_control)
+ return 1;
+
+ /* If this declaration is in a block or namespace scope, there's no
+ access control. */
+ if (!TYPE_P (context_for_name_lookup (decl)))
+ return 1;
+
+ /* We don't do access control for types yet. */
+ if (TREE_CODE (decl) == TYPE_DECL)
+ return 1;
+
+ if (!TYPE_P (type))
+ {
+ binfo = type;
+ type = BINFO_TYPE (type);
+ }
+ else
+ binfo = TYPE_BINFO (type);
+
+ /* [class.access.base]
+
+ A member m is accessible when named in class N if
+
+ --m as a member of N is public, or
+
+ --m as a member of N is private, and the reference occurs in a
+ member or friend of class N, or
+
+ --m as a member of N is protected, and the reference occurs in a
+ member or friend of class N, or in a member or friend of a
+ class P derived from N, where m as a member of P is private or
+ protected, or
+
+ --there exists a base class B of N that is accessible at the point
+ of reference, and m is accessible when named in class B.
+
+ We walk the base class hierarchy, checking these conditions. */
+
+ /* Figure out where the reference is occurring. Check to see if
+ DECL is private or protected in this scope, since that will
+ determine whether protected access in TYPE allowed. */
+ if (current_class_type)
+ protected_ok
+ = protected_accessible_p (type, decl, current_class_type,
+ binfo);
+
+ /* Now, loop through the classes of which we are a friend. */
+ if (!protected_ok)
+ protected_ok = friend_accessible_p (current_scope (),
+ type, decl, binfo);
+
+ /* Standardize on the same that will access_in_type will use. We
+ don't need to know what path was chosen from this point onwards. */
+ binfo = TYPE_BINFO (type);
+
+ /* Compute the accessibility of DECL in the class hierarchy
+ dominated by type. */
+ access_in_type (type, decl);
+ /* Walk the hierarchy again, looking for a base class that allows
+ access. */
+ t = dfs_walk (binfo, dfs_accessible_p,
+ dfs_accessible_queue_p,
+ protected_ok ? &protected_ok : 0);
+ /* Clear any mark bits. Note that we have to walk the whole tree
+ here, since we have aborted the previous walk from some point
+ deep in the tree. */
+ dfs_walk (binfo, dfs_unmark, dfs_canonical_queue, 0);
+ assert_canonical_unmarked (binfo);
+
+ return t != NULL_TREE;
}
/* Routine to see if the sub-object denoted by the binfo PARENT can be
@@ -1092,18 +1062,31 @@ static int
is_subobject_of_p (parent, binfo)
tree parent, binfo;
{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ tree binfos;
+ int i, n_baselinks;
+
+ /* We want to canonicalize for comparison purposes. But, when we
+ iterate through basetypes later, we want the binfos from the
+ original hierarchy. That's why we have to calculate BINFOS
+ first, and then canonicalize. */
+ binfos = BINFO_BASETYPES (binfo);
+ parent = canonical_binfo (parent);
+ binfo = canonical_binfo (binfo);
if (parent == binfo)
return 1;
+ n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+
/* Process and/or queue base types. */
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TREE_VIA_VIRTUAL (base_binfo))
- base_binfo = TYPE_BINFO (BINFO_TYPE (base_binfo));
+ if (!CLASS_TYPE_P (TREE_TYPE (base_binfo)))
+ /* If we see a TEMPLATE_TYPE_PARM, or some such, as a base
+ class there's no way to descend into it. */
+ continue;
+
if (is_subobject_of_p (parent, base_binfo))
return 1;
}
@@ -1154,27 +1137,230 @@ lookup_fnfields_here (type, name)
return -1;
}
-/* Look for a field 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.
+struct lookup_field_info {
+ /* The type in which we're looking. */
+ tree type;
+ /* The name of the field for which we're looking. */
+ tree name;
+ /* If non-NULL, the current result of the lookup. */
+ tree rval;
+ /* The path to RVAL. */
+ tree rval_binfo;
+ /* If non-NULL, the lookup was ambiguous, and this is a list of the
+ candidates. */
+ tree ambiguous;
+ /* If non-zero, we are looking for types, not data members. */
+ int want_type;
+ /* If non-zero, RVAL was found by looking through a dependent base. */
+ int from_dep_base_p;
+ /* If something went wrong, a message indicating what. */
+ const char *errstr;
+};
+
+/* Returns non-zero if BINFO is not hidden by the value found by the
+ lookup so far. If BINFO is hidden, then there's no need to look in
+ it. DATA is really a struct lookup_field_info. Called from
+ lookup_field via breadth_first_search. */
+
+static tree
+lookup_field_queue_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ struct lookup_field_info *lfi = (struct lookup_field_info *) data;
+
+ /* Don't look for constructors or destructors in base classes. */
+ if (lfi->name == ctor_identifier || lfi->name == dtor_identifier)
+ return NULL_TREE;
+
+ /* If this base class is hidden by the best-known value so far, we
+ don't need to look. */
+ if (!lfi->from_dep_base_p && lfi->rval_binfo
+ && hides (lfi->rval_binfo, binfo))
+ return NULL_TREE;
+
+ if (TREE_VIA_VIRTUAL (binfo))
+ return binfo_member (BINFO_TYPE (binfo),
+ CLASSTYPE_VBASECLASSES (lfi->type));
+ else
+ return binfo;
+}
+
+/* Within the scope of a template class, you can refer to the
+ particular to the current specialization with the name of the
+ template itself. For example:
+
+ template <typename T> struct S { S* sp; }
+
+ Returns non-zero if DECL is such a declaration in a class TYPE. */
+
+static int
+template_self_reference_p (type, decl)
+ tree type;
+ tree decl;
+{
+ return (CLASSTYPE_USE_TEMPLATE (type)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
+ && TREE_CODE (decl) == TYPE_DECL
+ && DECL_ARTIFICIAL (decl)
+ && DECL_NAME (decl) == constructor_name (type));
+}
+
+/* DATA is really a struct lookup_field_info. Look for a field with
+ the name indicated there in BINFO. If this function returns a
+ non-NULL value it is the result of the lookup. Called from
+ lookup_field via breadth_first_search. */
+
+static tree
+lookup_field_r (binfo, data)
+ tree binfo;
+ void *data;
+{
+ struct lookup_field_info *lfi = (struct lookup_field_info *) data;
+ tree type = BINFO_TYPE (binfo);
+ tree nval = NULL_TREE;
+ int from_dep_base_p;
+
+ /* First, look for a function. There can't be a function and a data
+ member with the same name, and if there's a function and a type
+ with the same name, the type is hidden by the function. */
+ if (!lfi->want_type)
+ {
+ int idx = lookup_fnfields_here (type, lfi->name);
+ if (idx >= 0)
+ nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
+ }
+
+ if (!nval)
+ /* Look for a data member or type. */
+ nval = lookup_field_1 (type, lfi->name);
+
+ /* If there is no declaration with the indicated name in this type,
+ then there's nothing to do. */
+ if (!nval)
+ return NULL_TREE;
+
+ /* If we're looking up a type (as with an elaborated type specifier)
+ we ignore all non-types we find. */
+ if (lfi->want_type && TREE_CODE (nval) != TYPE_DECL)
+ {
+ nval = purpose_member (lfi->name, CLASSTYPE_TAGS (type));
+ if (nval)
+ nval = TYPE_MAIN_DECL (TREE_VALUE (nval));
+ else
+ return NULL_TREE;
+ }
+
+ /* You must name a template base class with a template-id. */
+ if (!same_type_p (type, lfi->type)
+ && template_self_reference_p (type, nval))
+ return NULL_TREE;
+
+ from_dep_base_p = dependent_base_p (binfo);
+ if (lfi->from_dep_base_p && !from_dep_base_p)
+ {
+ /* If the new declaration is not found via a dependent base, and
+ the old one was, then we must prefer the new one. We weren't
+ really supposed to be able to find the old one, so we don't
+ want to be affected by a specialization. Consider:
+
+ struct B { typedef int I; };
+ template <typename T> struct D1 : virtual public B {};
+ template <typename T> struct D :
+ public D1, virtual pubic B { I i; };
+
+ The `I' in `D<T>' is unambigousuly `B::I', regardless of how
+ D1 is specialized. */
+ lfi->from_dep_base_p = 0;
+ lfi->rval = NULL_TREE;
+ lfi->rval_binfo = NULL_TREE;
+ lfi->ambiguous = NULL_TREE;
+ lfi->errstr = 0;
+ }
+ else if (lfi->rval_binfo && !lfi->from_dep_base_p && from_dep_base_p)
+ /* Similarly, if the old declaration was not found via a dependent
+ base, and the new one is, ignore the new one. */
+ return NULL_TREE;
+
+ /* If the lookup already found a match, and the new value doesn't
+ hide the old one, we might have an ambiguity. */
+ if (lfi->rval_binfo && !hides (binfo, lfi->rval_binfo))
+ {
+ if (nval == lfi->rval && SHARED_MEMBER_P (nval))
+ /* The two things are really the same. */
+ ;
+ else if (hides (lfi->rval_binfo, binfo))
+ /* The previous value hides the new one. */
+ ;
+ else
+ {
+ /* We have a real ambiguity. We keep a chain of all the
+ candidates. */
+ if (!lfi->ambiguous && lfi->rval)
+ {
+ /* This is the first time we noticed an ambiguity. Add
+ what we previously thought was a reasonable candidate
+ to the list. */
+ lfi->ambiguous = scratch_tree_cons (NULL_TREE, lfi->rval,
+ NULL_TREE);
+ TREE_TYPE (lfi->ambiguous) = error_mark_node;
+ }
+
+ /* Add the new value. */
+ lfi->ambiguous = scratch_tree_cons (NULL_TREE, nval,
+ lfi->ambiguous);
+ TREE_TYPE (lfi->ambiguous) = error_mark_node;
+ lfi->errstr = "request for member `%D' is ambiguous";
+ }
+ }
+ else
+ {
+ /* If the thing we're looking for is a virtual base class, then
+ we know we've got what we want at this point; there's no way
+ to get an ambiguity. */
+ if (VBASE_NAME_P (lfi->name))
+ {
+ lfi->rval = nval;
+ return nval;
+ }
+
+ if (from_dep_base_p && TREE_CODE (nval) != TYPE_DECL
+ /* We need to return a member template class so we can
+ define partial specializations. Is there a better
+ way? */
+ && !DECL_CLASS_TEMPLATE_P (nval))
+ /* The thing we're looking for isn't a type, so the implicit
+ typename extension doesn't apply, so we just pretend we
+ didn't find anything. */
+ return NULL_TREE;
+
+ lfi->rval = nval;
+ lfi->from_dep_base_p = from_dep_base_p;
+ lfi->rval_binfo = binfo;
+ }
+
+ return NULL_TREE;
+}
+
+/* Look for a memer named NAME in an inheritance lattice dominated by
+ XBASETYPE. PROTECT is 0 or two, we do not check access. If it is
+ 1, we enforce accessibility. If PROTECT is zero, then, for an
+ ambiguous lookup, we return NULL. If PROTECT is 1, we issue an
+ error message. If PROTECT is 2, we return a TREE_LIST whose
+ TREEE_TYPE is error_mark_node and whose TREE_VALUEs are the list of
+ ambiguous candidates.
- 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. */
+ WANT_TYPE is 1 when we should only return TYPE_DECLs, if no
+ TYPE_DECL can be found return NULL_TREE. */
tree
-lookup_field (xbasetype, name, protect, want_type)
+lookup_member (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 = NULL_TREE;
- tree type = NULL_TREE, basetype_chain, basetype_path = NULL_TREE;
- tree this_v = access_default_node;
- tree entry, binfo, binfo_h;
- tree own_access = access_default_node;
- int vbase_name_p = VBASE_NAME_P (name);
+ tree rval, rval_binfo = NULL_TREE;
+ tree type = NULL_TREE, basetype_path = NULL_TREE;
+ struct lookup_field_info lfi;
/* rval_binfo is the binfo associated with the found member, note,
this can be set with useful information, even when rval is not
@@ -1183,27 +1369,7 @@ lookup_field (xbasetype, name, protect, want_type)
checks. Whereas rval is only set if a proper (not hidden)
non-function member is found. */
- /* 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 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) */
-
- char *errstr = 0;
-
- /* Set this to nonzero if we don't know how to compute
- accurate error messages for access control. */
- 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
+ const char *errstr = 0;
if (xbasetype == current_class_type && TYPE_BEING_DEFINED (xbasetype)
&& IDENTIFIER_CLASS_VALUE (name))
@@ -1211,6 +1377,8 @@ lookup_field (xbasetype, name, protect, want_type)
tree field = IDENTIFIER_CLASS_VALUE (name);
if (TREE_CODE (field) != FUNCTION_DECL
&& ! (want_type && TREE_CODE (field) != TYPE_DECL))
+ /* We're in the scope of this class, and the value has already
+ been looked up. Just return the cached value. */
return field;
}
@@ -1223,416 +1391,119 @@ lookup_field (xbasetype, name, protect, want_type)
{
type = xbasetype;
basetype_path = TYPE_BINFO (type);
- BINFO_VIA_PUBLIC (basetype_path) = 1;
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE,
+ 980827);
}
else
my_friendly_abort (97);
complete_type (type);
- if (CLASSTYPE_MTABLE_ENTRY (type))
- {
- tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
-
- while (tem && TREE_PURPOSE (tem) != name)
- {
- memoized_fields_searched[0]++;
- tem = TREE_CHAIN (tem);
- }
- if (tem)
- {
- if (protect && TREE_TYPE (tem))
- {
- error (TREE_STRING_POINTER (TREE_TYPE (tem)),
- IDENTIFIER_POINTER (name),
- TYPE_NAME_STRING (DECL_FIELD_CONTEXT (TREE_VALUE (tem))));
- return error_mark_node;
- }
- if (TREE_VALUE (tem) == NULL_TREE)
- memoized_fast_rejects[0] += 1;
- else
- memoized_fast_finds[0] += 1;
- return TREE_VALUE (tem);
- }
- }
-
#ifdef GATHER_STATISTICS
n_calls_lookup_field++;
#endif /* GATHER_STATISTICS */
- if (protect && flag_memoize_lookups && ! toplevel_bindings_p ())
- entry = make_memoized_table_entry (type, name, 0);
- else
- entry = 0;
-
- rval = lookup_field_1 (type, name);
-
- if (rval || lookup_fnfields_here (type, name) >= 0)
- {
- if (entry)
- TREE_VALUE (entry) = rval;
-
- if (rval)
- {
- if (want_type)
- {
- if (TREE_CODE (rval) != TYPE_DECL)
- {
- rval = purpose_member (name, CLASSTYPE_TAGS (type));
- if (rval)
- rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
- }
- }
- else
- {
- if (TREE_CODE (rval) == TYPE_DECL
- && lookup_fnfields_here (type, name) >= 0)
- rval = NULL_TREE;
- }
- }
-
- if (protect && rval)
- {
- if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval))
- this_v = compute_access (basetype_path, rval);
- if (TREE_CODE (rval) == CONST_DECL)
- {
- if (this_v == access_private_node)
- errstr = "enum `%D' is a private value of class `%T'";
- else if (this_v == access_protected_node)
- errstr = "enum `%D' is a protected value of class `%T'";
- }
- else
- {
- if (this_v == access_private_node)
- errstr = "member `%D' is a private member of class `%T'";
- else if (this_v == access_protected_node)
- errstr = "member `%D' is a protected member of class `%T'";
- }
- }
- rval_binfo = basetype_path;
- goto out;
- }
-
- 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. */
-
- search_stack = push_search_level (search_stack, &search_obstack);
- binfo = basetype_path;
- binfo_h = binfo;
-
- while (1)
+ bzero ((PTR) &lfi, sizeof (lfi));
+ lfi.type = type;
+ lfi.name = name;
+ lfi.want_type = want_type;
+ bfs_walk (basetype_path, &lookup_field_r, &lookup_field_queue_p, &lfi);
+ rval = lfi.rval;
+ rval_binfo = lfi.rval_binfo;
+ if (rval_binfo)
+ type = BINFO_TYPE (rval_binfo);
+ errstr = lfi.errstr;
+
+ /* If we are not interested in ambiguities, don't report them;
+ just return NULL_TREE. */
+ if (!protect && lfi.ambiguous)
+ return NULL_TREE;
+
+ if (protect == 2)
{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- tree nval;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (BINFO_FIELDS_MARKED (base_binfo) == 0)
- {
- tree btypes;
-
- SET_BINFO_FIELDS_MARKED (base_binfo);
- btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
- TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
- 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 = my_tree_cons (NULL_TREE,
- TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
- btypes);
- else
- btypes = my_tree_cons (NULL_TREE,
- TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
- btypes);
- obstack_ptr_grow (&search_obstack, btypes);
- tail += 1;
- if (tail >= search_stack->limit)
- my_friendly_abort (98);
- }
- }
-
- /* Process head of queue, if one exists. */
- if (head >= tail)
- break;
-
- basetype_chain = search_stack->first[head++];
- binfo_h = TREE_VALUE (basetype_chain);
- basetype_chain = TREE_CHAIN (basetype_chain);
- basetype_path = TREE_VALUE (basetype_chain);
- if (TREE_CHAIN (basetype_chain))
- BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
+ if (lfi.ambiguous)
+ return lfi.ambiguous;
else
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
-
- binfo = basetype_path;
- type = BINFO_TYPE (binfo);
-
- /* See if we can find NAME in TYPE. If RVAL is nonzero,
- and we do find NAME in TYPE, verify that such a second
- sighting is in fact valid. */
-
- nval = lookup_field_1 (type, name);
-
- if (nval || lookup_fnfields_here (type, name)>=0)
- {
- if (nval && nval == rval && SHARED_MEMBER_P (nval))
- {
- /* This is ok, the member found is the same [class.ambig] */
- }
- else if (rval_binfo && hides (rval_binfo_h, binfo_h))
- {
- /* This is ok, the member found is in rval_binfo, not
- 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. */
- if (nval)
- {
- rval = nval;
- if (entry || protect)
- this_v = compute_access (basetype_path, rval);
- /* These may look ambiguous, but they really are not. */
- if (vbase_name_p)
- break;
- }
- else
- {
- /* Undo finding it before, as something else hides it. */
- rval = NULL_TREE;
- }
- rval_binfo = binfo;
- rval_binfo_h = binfo_h;
- }
- else
- {
- /* This is ambiguous. */
- errstr = "request for member `%D' is ambiguous";
- protect += 2;
- break;
- }
- }
- }
- {
- tree *tp = search_stack->first;
- tree *search_tail = tp + tail;
-
- if (entry)
- TREE_VALUE (entry) = rval;
-
- if (rval_binfo)
- {
- type = BINFO_TYPE (rval_binfo);
-
- if (rval)
- {
- if (want_type)
- {
- if (TREE_CODE (rval) != TYPE_DECL)
- {
- rval = purpose_member (name, CLASSTYPE_TAGS (type));
- if (rval)
- rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
- }
- }
- else
- {
- if (TREE_CODE (rval) == TYPE_DECL
- && lookup_fnfields_here (type, name) >= 0)
- rval = NULL_TREE;
- }
- }
- }
-
- if (rval == NULL_TREE)
- errstr = 0;
-
- /* If this FIELD_DECL defines its own access level, deal with that. */
- if (rval && errstr == 0
- && ((protect&1) || entry)
- && DECL_LANG_SPECIFIC (rval)
- && DECL_ACCESS (rval))
- {
- while (tp < search_tail)
- {
- /* 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. */
- tree new_v = NULL_TREE;
-
- if (this_v != access_default_node)
- new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval);
- if (this_v != access_default_node && new_v != this_v)
- {
- errstr = "conflicting access to member `%D'";
- this_v = access_default_node;
- }
- own_access = new_v;
- CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
- tp += 1;
- }
- }
- else
- {
- while (tp < search_tail)
- {
- CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
- tp += 1;
- }
- }
- }
- search_stack = pop_search_level (search_stack);
-
- if (errstr == 0)
- {
- if (own_access == access_private_node)
- errstr = "member `%D' declared private";
- else if (own_access == access_protected_node)
- errstr = "member `%D' declared protected";
- 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_node)
- errstr = TREE_PROTECTED (rval)
- ? "member `%D' is protected"
- : "member `%D' is from protected base class";
- }
-
- out:
- if (entry)
- {
- if (errstr)
- {
- tree error_string = my_build_string (errstr);
- /* Save error message with entry. */
- TREE_TYPE (entry) = error_string;
- }
- else
- {
- /* Mark entry as having no error string. */
- TREE_TYPE (entry) = NULL_TREE;
- }
+ protect = 0;
}
- if (protect == 2)
- {
- /* If we are not interested in ambiguities, don't report them,
- just return NULL_TREE. */
- rval = NULL_TREE;
- protect = 0;
- }
+ /* [class.access]
+
+ In the case of overloaded function names, access control is
+ applied to the function selected by overloaded resolution. */
+ if (rval && protect && !is_overloaded_fn (rval)
+ && !IS_SIGNATURE_POINTER (DECL_REAL_CONTEXT (rval))
+ && !IS_SIGNATURE_REFERENCE (DECL_REAL_CONTEXT (rval))
+ && !enforce_access (xbasetype, rval))
+ return error_mark_node;
if (errstr && protect)
{
cp_error (errstr, name, type);
+ if (lfi.ambiguous)
+ print_candidates (lfi.ambiguous);
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;
+ /* If the thing we found was found via the implicit typename
+ extension, build the typename type. */
+ if (rval && lfi.from_dep_base_p && !DECL_CLASS_TEMPLATE_P (rval))
+ rval = TYPE_STUB_DECL (build_typename_type (BINFO_TYPE (basetype_path),
+ name, name,
+ TREE_TYPE (rval)));
- entry = make_typename_type (BINFO_TYPE (binfo), name);
- TREE_TYPE (entry) = TREE_TYPE (rval);
- rval = TYPE_MAIN_DECL (entry);
+ if (rval && is_overloaded_fn (rval))
+ {
+ rval = scratch_tree_cons (basetype_path, rval, NULL_TREE);
+ SET_BASELINK_P (rval);
}
return rval;
}
-/* Try to find NAME inside a nested class. */
+/* Like lookup_member, except that if we find a function member we
+ return NULL_TREE. */
tree
-lookup_nested_field (name, complain)
- tree name;
- int complain;
+lookup_field (xbasetype, name, protect, want_type)
+ register tree xbasetype, name;
+ int protect, want_type;
{
- register tree t;
+ tree rval = lookup_member (xbasetype, name, protect, want_type);
+
+ /* Ignore functions. */
+ if (rval && TREE_CODE (rval) == TREE_LIST)
+ return NULL_TREE;
- tree id = NULL_TREE;
- 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 = TYPE_MAIN_DECL (current_class_type);
- t && DECL_CONTEXT (t);
- t = TYPE_MAIN_DECL (DECL_CONTEXT (t)))
- {
- if (TREE_CODE (DECL_CONTEXT (t)) != RECORD_TYPE)
- break;
+ return rval;
+}
- /* N.B.: lookup_field will do the access checking for us */
- id = lookup_field (DECL_CONTEXT (t), name, complain, 0);
- if (id == error_mark_node)
- {
- id = NULL_TREE;
- continue;
- }
+/* Like lookup_member, except that if we find a non-function member we
+ return NULL_TREE. */
- if (id != NULL_TREE)
- {
- if (TREE_CODE (id) == FIELD_DECL
- && ! TREE_STATIC (id)
- && TREE_TYPE (id) != error_mark_node)
- {
- if (complain)
- {
- /* At parse time, we don't want to give this error, since
- we won't have enough state to make this kind of
- decision properly. But there are times (e.g., with
- 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. */
- 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;
- }
- else
- {
- id = NULL_TREE;
- continue;
- }
- }
- break;
- }
- }
- }
+tree
+lookup_fnfields (xbasetype, name, protect)
+ register tree xbasetype, name;
+ int protect;
+{
+ tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/0);
+
+ /* Ignore non-functions. */
+ if (rval && TREE_CODE (rval) != TREE_LIST)
+ return NULL_TREE;
- return id;
+ return rval;
}
/* 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
+int
lookup_fnfields_1 (type, name)
tree type, name;
{
- register tree method_vec = CLASSTYPE_METHOD_VEC (type);
+ register tree method_vec
+ = CLASS_TYPE_P (type) ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE;
if (method_vec != 0)
{
@@ -1651,7 +1522,7 @@ lookup_fnfields_1 (type, name)
if (*++methods && name == dtor_identifier)
return 1;
- while (++methods != end)
+ while (++methods != end && *methods)
{
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
@@ -1663,498 +1534,251 @@ lookup_fnfields_1 (type, name)
/* 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
+ if ((methods == end || !*methods)
&& IDENTIFIER_TYPENAME_P (name))
{
methods = &TREE_VEC_ELT (method_vec, 0) + 1;
- while (++methods != end)
+ while (++methods != end && *methods)
{
- if (TREE_CODE (OVL_CURRENT (*methods)) == TEMPLATE_DECL
- && IDENTIFIER_TYPENAME_P (DECL_NAME (OVL_CURRENT (*methods))))
+ tree method_name = DECL_NAME (OVL_CURRENT (*methods));
+
+ if (!IDENTIFIER_TYPENAME_P (method_name))
+ {
+ /* Since all conversion operators come first, we know
+ there is no such operator. */
+ methods = end;
+ break;
+ }
+ else if (TREE_CODE (OVL_CURRENT (*methods)) == TEMPLATE_DECL)
break;
}
}
- if (methods != end)
+ if (methods != end && *methods)
return methods - &TREE_VEC_ELT (method_vec, 0);
}
return -1;
}
+
+/* Walk the class hierarchy dominated by TYPE. FN is called for each
+ type in the hierarchy, in a breadth-first preorder traversal. .
+ If it ever returns a non-NULL value, that value is immediately
+ returned and the walk is terminated. At each node FN, is passed a
+ BINFO indicating the path from the curently visited base-class to
+ TYPE. The TREE_CHAINs of the BINFOs may be used for scratch space;
+ they are otherwise unused. Before each base-class is walked QFN is
+ called. If the value returned is non-zero, the base-class is
+ walked; otherwise it is not. If QFN is NULL, it is treated as a
+ function which always returns 1. Both FN and QFN are passed the
+ DATA whenever they are called. */
-/* Starting from BASETYPE, return a TREE_BASELINK-like object
- which gives the following information (in a list):
-
- TREE_TYPE: list of basetypes needed to get to...
- TREE_VALUE: list of all functions in a given type
- which have name NAME.
-
- No access information is computed by this function,
- other then to adorn the list of basetypes with
- TREE_VIA_PUBLIC.
-
- If there are two ways to find a name (two members), if COMPLAIN is
- non-zero, then error_mark_node is returned, and an error message is
- printed, otherwise, just an error_mark_node is returned.
-
- 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;
+static tree
+bfs_walk (binfo, fn, qfn, data)
+ tree binfo;
+ tree (*fn) PROTO((tree, void *));
+ tree (*qfn) PROTO((tree, void *));
+ void *data;
{
- int head = 0, tail = 0;
- 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,
- this can be set with useful information, even when rval is not
- set, because it must deal with ALL members, not just function
- members. It is used for ambiguity checking and the hidden
- checks. Whereas rval is only set if a proper (not hidden)
- function member is found. */
-
- /* 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 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) */
-
- /* For now, don't try this. */
- int protect = complain;
+ size_t head;
+ size_t tail;
+ tree rval = NULL_TREE;
+ /* An array of the base classes of BINFO. These will be built up in
+ breadth-first order, except where QFN prunes the search. */
+ varray_type bfs_bases;
- char *errstr = 0;
+ /* Start with enough room for ten base classes. That will be enough
+ for most hierarchies. */
+ VARRAY_TREE_INIT (bfs_bases, 10, "search_stack");
- /* Set this to nonzero if we don't know how to compute
- accurate error messages for access control. */
- int idx = MEMOIZED_HASH_FN (name);
+ /* Put the first type into the stack. */
+ VARRAY_TREE (bfs_bases, 0) = binfo;
+ tail = 1;
- if (complain == -1)
+ for (head = 0; head < tail; ++head)
{
- find_all = 1;
- 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
+ int i;
+ int n_baselinks;
+ tree binfos;
- binfo = basetype_path;
- binfo_h = binfo;
- type = complete_type (BINFO_TYPE (basetype_path));
+ /* Pull the next type out of the queue. */
+ binfo = VARRAY_TREE (bfs_bases, head);
- /* The memoization code is in need of maintenance. */
- if (!find_all && CLASSTYPE_MTABLE_ENTRY (type))
- {
- tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
+ /* If this is the one we're looking for, we're done. */
+ rval = (*fn) (binfo, data);
+ if (rval)
+ break;
- while (tem && TREE_PURPOSE (tem) != name)
- {
- memoized_fields_searched[1]++;
- tem = TREE_CHAIN (tem);
- }
- if (tem)
+ /* Queue up the base types. */
+ binfos = BINFO_BASETYPES (binfo);
+ n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0;
+ for (i = 0; i < n_baselinks; i++)
{
- if (protect && TREE_TYPE (tem))
- {
- error (TREE_STRING_POINTER (TREE_TYPE (tem)),
- IDENTIFIER_POINTER (name),
- TYPE_NAME_STRING (DECL_CLASS_CONTEXT (TREE_VALUE (TREE_VALUE (tem)))));
- return error_mark_node;
- }
- if (TREE_VALUE (tem) == NULL_TREE)
- {
- memoized_fast_rejects[1] += 1;
- return NULL_TREE;
- }
- else
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+
+ if (qfn)
+ base_binfo = (*qfn) (base_binfo, data);
+
+ if (base_binfo)
{
- /* Want to return this, but we must make sure
- that access information is consistent. */
- tree baselink = TREE_VALUE (tem);
- tree memoized_basetypes = TREE_PURPOSE (baselink);
- tree these_basetypes = basetype_path;
- while (memoized_basetypes && these_basetypes)
- {
- memoized_fields_searched[1]++;
- if (TREE_VALUE (memoized_basetypes) != these_basetypes)
- break;
- memoized_basetypes = TREE_CHAIN (memoized_basetypes);
- these_basetypes = BINFO_INHERITANCE_CHAIN (these_basetypes);
- }
- /* The following statement is true only when both are NULL. */
- if (memoized_basetypes == these_basetypes)
- {
- memoized_fast_finds[1] += 1;
- return TREE_VALUE (tem);
- }
- /* else, we must re-find this field by hand. */
- baselink = tree_cons (basetype_path, TREE_VALUE (baselink), TREE_CHAIN (baselink));
- return baselink;
+ if (tail == VARRAY_SIZE (bfs_bases))
+ VARRAY_GROW (bfs_bases, 2 * VARRAY_SIZE (bfs_bases));
+ VARRAY_TREE (bfs_bases, tail) = base_binfo;
+ ++tail;
}
}
}
-#ifdef GATHER_STATISTICS
- n_calls_lookup_fnfields++;
-#endif /* GATHER_STATISTICS */
- if (protect && flag_memoize_lookups && ! toplevel_bindings_p ())
- entry = make_memoized_table_entry (type, name, 1);
- else
- entry = 0;
-
- idx = lookup_fnfields_here (type, name);
- if (idx >= 0 || lookup_field_1 (type, name))
- {
- rval_binfo = basetype_path;
- rval_binfo_h = rval_binfo;
- }
-
- if (idx >= 0)
- {
- 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), idx);
-
- if (entry)
- {
- TREE_VALUE (entry) = rvals;
- TREE_TYPE (entry) = NULL_TREE;
- }
+ /* Clean up. */
+ VARRAY_FREE (bfs_bases);
- return rvals;
- }
- rval = NULL_TREE;
+ return rval;
+}
- 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;
+/* Exactly like bfs_walk, except that a depth-first traversal is
+ performed, and PREFN is called in preorder, while POSTFN is called
+ in postorder. */
- return NULL_TREE;
- }
+static tree
+dfs_walk_real (binfo, prefn, postfn, qfn, data)
+ tree binfo;
+ tree (*prefn) PROTO((tree, void *));
+ tree (*postfn) PROTO((tree, void *));
+ tree (*qfn) PROTO((tree, void *));
+ void *data;
+{
+ int i;
+ int n_baselinks;
+ tree binfos;
+ tree rval = NULL_TREE;
- if (basetype_path == TYPE_BINFO (type))
+ /* Call the pre-order walking function. */
+ if (prefn)
{
- basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
- TREE_VIA_PUBLIC (basetype_chain) = 1;
- BINFO_VIA_PUBLIC (basetype_path) = 1;
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
- }
- else
- {
- 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);
+ rval = (*prefn) (binfo, data);
+ if (rval)
+ return rval;
}
- /* The ambiguity check relies upon breadth first searching. */
-
- search_stack = push_search_level (search_stack, &search_obstack);
- binfo = basetype_path;
- binfo_h = binfo;
-
- while (1)
+ /* Process the basetypes. */
+ binfos = BINFO_BASETYPES (binfo);
+ n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0;
+ for (i = 0; i < n_baselinks; i++)
{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int idx;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (BINFO_FIELDS_MARKED (base_binfo) == 0)
- {
- tree btypes;
-
- SET_BINFO_FIELDS_MARKED (base_binfo);
- btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
- TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
- 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 = my_tree_cons (NULL_TREE,
- TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
- btypes);
- else
- btypes = my_tree_cons (NULL_TREE,
- TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
- btypes);
- obstack_ptr_grow (&search_obstack, btypes);
- tail += 1;
- if (tail >= search_stack->limit)
- my_friendly_abort (99);
- }
- }
-
- /* Process head of queue, if one exists. */
- if (head >= tail)
- break;
-
- basetype_chain = search_stack->first[head++];
- binfo_h = TREE_VALUE (basetype_chain);
- basetype_chain = TREE_CHAIN (basetype_chain);
- basetype_path = TREE_VALUE (basetype_chain);
- if (TREE_CHAIN (basetype_chain))
- BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
- else
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
-
- binfo = basetype_path;
- type = BINFO_TYPE (binfo);
-
- /* See if we can find NAME in TYPE. If RVAL is nonzero,
- and we do find NAME in TYPE, verify that such a second
- sighting is in fact valid. */
-
- idx = lookup_fnfields_here (type, name);
-
- 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). */
- }
- 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 (idx >= 0)
- {
- 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), idx);
- }
- else
- {
- /* Undo finding it before, as something else hides it. */
- rval = NULL_TREE;
- rvals = NULL_TREE;
- }
- rval_binfo = binfo;
- rval_binfo_h = binfo_h;
- }
- else
- {
- /* This is ambiguous. */
- errstr = "request for method `%D' is ambiguous";
- rvals = error_mark_node;
- break;
- }
- }
- }
- {
- tree *tp = search_stack->first;
- tree *search_tail = tp + tail;
-
- while (tp < search_tail)
- {
- CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
- tp += 1;
- }
- }
- search_stack = pop_search_level (search_stack);
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+
+ if (qfn)
+ base_binfo = (*qfn) (base_binfo, data);
- if (entry)
- {
- if (errstr)
+ if (base_binfo)
{
- tree error_string = my_build_string (errstr);
- /* Save error message with entry. */
- TREE_TYPE (entry) = error_string;
- }
- else
- {
- /* Mark entry as having no error string. */
- TREE_TYPE (entry) = NULL_TREE;
- TREE_VALUE (entry) = rvals;
+ rval = dfs_walk_real (base_binfo, prefn, postfn, qfn, data);
+ if (rval)
+ return rval;
}
}
- if (errstr && protect)
- {
- cp_error (errstr, name);
- rvals = error_mark_node;
- }
-
- return rvals;
+ /* Call the post-order walking function. */
+ if (postfn)
+ rval = (*postfn) (binfo, data);
+
+ return rval;
}
-/* 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. */
+/* Exactly like bfs_walk, except that a depth-first post-order traversal is
+ performed. */
tree
-lookup_member (xbasetype, name, protect, want_type)
- tree xbasetype, name;
- int protect, want_type;
+dfs_walk (binfo, fn, qfn, data)
+ tree binfo;
+ tree (*fn) PROTO((tree, void *));
+ tree (*qfn) PROTO((tree, void *));
+ void *data;
{
- 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;
+ return dfs_walk_real (binfo, 0, fn, qfn, data);
}
-
-/* BREADTH-FIRST SEARCH ROUTINES. */
-/* Search a multiple inheritance hierarchy by breadth-first search.
+struct gvnt_info
+{
+ /* The name of the function we are looking for. */
+ tree name;
+ /* The overloaded functions we have found. */
+ tree fields;
+};
- 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. */
+/* Called from get_virtuals_named_this via bfs_walk. */
-static HOST_WIDE_INT
-breadth_first_search (binfo, testfn, qfn)
+static tree
+get_virtuals_named_this_r (binfo, data)
tree binfo;
- int (*testfn) PROTO((tree, int));
- int (*qfn) PROTO((tree, int));
+ void *data;
{
- int head = 0, tail = 0;
- int rval = 0;
-
- search_stack = push_search_level (search_stack, &search_obstack);
-
- while (1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- int n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int i;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
+ struct gvnt_info *gvnti = (struct gvnt_info *) data;
+ tree type = BINFO_TYPE (binfo);
+ int idx;
- if (BINFO_MARKED (base_binfo) == 0
- && (qfn == 0 || (*qfn) (binfo, i)))
- {
- SET_BINFO_MARKED (base_binfo);
- obstack_ptr_grow (&search_obstack, binfo);
- obstack_ptr_grow (&search_obstack, (HOST_WIDE_INT) i);
- tail += 2;
- if (tail >= search_stack->limit)
- my_friendly_abort (100);
- }
- }
- /* Process head of queue, if one exists. */
- if (head >= tail)
- {
- rval = 0;
- break;
- }
+ idx = lookup_fnfields_here (BINFO_TYPE (binfo), gvnti->name);
+ if (idx >= 0)
+ gvnti->fields
+ = scratch_tree_cons (binfo,
+ TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type),
+ idx),
+ gvnti->fields);
- binfo = search_stack->first[head++];
- i = (HOST_WIDE_INT) search_stack->first[head++];
- if ((rval = (*testfn) (binfo, i)))
- break;
- binfo = BINFO_BASETYPE (binfo, i);
- }
- {
- tree *tp = search_stack->first;
- tree *search_tail = tp + tail;
- while (tp < search_tail)
- {
- tree binfo = *tp++;
- int i = (HOST_WIDE_INT)(*tp++);
- CLEAR_BINFO_MARKED (BINFO_BASETYPE (binfo, i));
- }
- }
-
- search_stack = pop_search_level (search_stack);
- return rval;
+ return NULL_TREE;
}
-/* Functions to use in breadth first searches. */
-typedef int (*pfi) PROTO((tree, int));
-
-static tree declarator;
+/* Return the virtual functions with the indicated NAME in the type
+ indicated by BINFO. The result is a TREE_LIST whose TREE_PURPOSE
+ indicates the base class from which the TREE_VALUE (an OVERLOAD or
+ just a FUNCTION_DECL) originated. */
static tree
-get_virtuals_named_this (binfo)
+get_virtuals_named_this (binfo, name)
tree binfo;
+ tree name;
{
+ struct gvnt_info gvnti;
tree fields;
- fields = lookup_fnfields (binfo, declarator, -1);
- /* fields cannot be error_mark_node */
+ gvnti.name = name;
+ gvnti.fields = NULL_TREE;
- if (fields == 0)
- return 0;
+ bfs_walk (binfo, get_virtuals_named_this_r, 0, &gvnti);
/* Get to the function decls, and return the first virtual function
with this name, if there is one. */
- while (fields)
+ for (fields = gvnti.fields; fields; fields = next_baselink (fields))
{
tree 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)
+get_virtual_destructor (binfo, data)
tree binfo;
- int i;
+ void *data ATTRIBUTE_UNUSED;
{
tree type = BINFO_TYPE (binfo);
- 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), 1)))
return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1);
return 0;
}
-static int
-tree_has_any_destructor_p (binfo, i)
+static tree
+tree_has_any_destructor_p (binfo, data)
tree binfo;
- int i;
+ void *data ATTRIBUTE_UNUSED;
{
tree type = BINFO_TYPE (binfo);
- if (i >= 0)
- type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
- return TYPE_NEEDS_DESTRUCTOR (type);
+ return TYPE_NEEDS_DESTRUCTOR (type) ? binfo : NULL_TREE;
}
/* Returns > 0 if a function with type DRETTYPE overriding a function
@@ -2181,14 +1805,13 @@ covariant_return_p (brettype, drettype)
drettype = TREE_TYPE (drettype);
}
- if (comptypes (brettype, drettype, 1))
+ if (same_type_p (brettype, drettype))
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)))
+ && TYPE_QUALS (brettype) == TYPE_QUALS (drettype)))
return 0;
if (! can_convert (brettype, drettype))
@@ -2238,30 +1861,19 @@ get_matching_virtual (binfo, fndecl, dtorp)
/* Breadth first search routines start searching basetypes
of TYPE, so we must perform first ply of search here. */
if (dtorp)
- {
- if (tree_has_any_destructor_p (binfo, -1))
- tmp = get_virtual_destructor (binfo, -1);
-
- if (tmp)
- return tmp;
-
- tmp = (tree) breadth_first_search (binfo,
- (pfi) get_virtual_destructor,
- tree_has_any_destructor_p);
- return tmp;
- }
+ return bfs_walk (binfo, get_virtual_destructor,
+ tree_has_any_destructor_p, 0);
else
{
tree drettype, dtypes, btypes, instptr_type;
tree basetype = DECL_CLASS_CONTEXT (fndecl);
tree baselink, best = NULL_TREE;
tree name = DECL_ASSEMBLER_NAME (fndecl);
-
- declarator = DECL_NAME (fndecl);
+ tree declarator = DECL_NAME (fndecl);
if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
return NULL_TREE;
- baselink = get_virtuals_named_this (binfo);
+ baselink = get_virtuals_named_this (binfo, declarator);
if (baselink == NULL_TREE)
return NULL_TREE;
@@ -2284,18 +1896,22 @@ get_matching_virtual (binfo, fndecl, dtorp)
btypes = TYPE_ARG_TYPES (TREE_TYPE (tmp));
if (instptr_type == NULL_TREE)
{
- if (compparms (TREE_CHAIN (btypes), dtypes, 3))
+ if (compparms (TREE_CHAIN (btypes), dtypes))
/* Caller knows to give error in this case. */
return tmp;
return NULL_TREE;
}
- if ((TYPE_READONLY (TREE_TYPE (TREE_VALUE (btypes)))
- == TYPE_READONLY (instptr_type))
- && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes), 3))
+ if (/* The first parameter is the `this' parameter,
+ which has POINTER_TYPE, and we can therefore
+ safely use TYPE_QUALS, rather than
+ CP_TYPE_QUALS. */
+ (TYPE_QUALS (TREE_TYPE (TREE_VALUE (btypes)))
+ == TYPE_QUALS (instptr_type))
+ && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes)))
{
tree brettype = TREE_TYPE (TREE_TYPE (tmp));
- if (comptypes (brettype, drettype, 1))
+ if (same_type_p (brettype, drettype))
/* OK */;
else if ((i = covariant_return_p (brettype, drettype)))
{
@@ -2309,7 +1925,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
}
}
else if (IS_AGGR_TYPE_2 (brettype, drettype)
- && comptypes (brettype, drettype, 0))
+ && same_or_base_type_p (brettype, drettype))
{
error ("invalid covariant return type (must use pointer or reference)");
cp_error_at (" overriding `%#D'", tmp);
@@ -2321,15 +1937,15 @@ get_matching_virtual (binfo, fndecl, dtorp)
cp_error_at (" overriding definition as `%#D'", tmp);
SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
}
- break;
+
+ /* FNDECL overrides this function. We continue to
+ check all the other functions in order to catch
+ errors; it might be that in some other baseclass
+ a virtual function was declared with the same
+ parameter types, but a different return type. */
+ best = tmp;
}
}
- /* If not at the end */
- if (tmps)
- {
- best = tmp;
- break;
- }
}
return best;
@@ -2364,7 +1980,7 @@ get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
{
tree virtuals = BINFO_VIRTUALS (binfo);
- skip_rtti_stuff (&virtuals);
+ skip_rtti_stuff (&virtuals, BINFO_TYPE (binfo));
while (virtuals)
{
@@ -2387,7 +2003,7 @@ get_abstract_virtuals (type)
tree type;
{
tree vbases;
- tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
+ tree abstract_virtuals = NULL;
/* First get all from non-virtual bases. */
abstract_virtuals
@@ -2397,13 +2013,15 @@ get_abstract_virtuals (type)
{
tree virtuals = BINFO_VIRTUALS (vbases);
- skip_rtti_stuff (&virtuals);
+ skip_rtti_stuff (&virtuals, type);
while (virtuals)
{
tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
tree base_fndecl = TREE_OPERAND (base_pfn, 0);
- if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
+ if (DECL_NEEDS_FINAL_OVERRIDER_P (base_fndecl))
+ cp_error ("`%#D' needs a final overrider", base_fndecl);
+ else if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
virtuals = TREE_CHAIN (virtuals);
}
@@ -2411,77 +2029,7 @@ get_abstract_virtuals (type)
return nreverse (abstract_virtuals);
}
-/* For the type TYPE, return a list of member functions available from
- base classes with name NAME. The TREE_VALUE of the list is a chain of
- member functions with name NAME. The TREE_PURPOSE of the list is a
- basetype, or a list of base types (in reverse order) which were
- traversed to reach the chain of member functions. If we reach a base
- type which provides a member function of name NAME, and which has at
- most one base type itself, then we can terminate the search. */
-
-tree
-get_baselinks (type_as_binfo_list, type, name)
- tree type_as_binfo_list;
- tree type, name;
-{
- int head = 0, tail = 0, idx;
- tree rval = 0, nval = 0;
- tree basetypes = type_as_binfo_list;
- tree binfo = TYPE_BINFO (type);
-
- search_stack = push_search_level (search_stack, &search_obstack);
-
- while (1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree btypes;
-
- btypes = hash_tree_cons (TREE_VIA_PUBLIC (base_binfo),
- TREE_VIA_VIRTUAL (base_binfo),
- TREE_VIA_PROTECTED (base_binfo),
- NULL_TREE, base_binfo,
- basetypes);
- obstack_ptr_grow (&search_obstack, btypes);
- search_stack->first = (tree *)obstack_base (&search_obstack);
- tail += 1;
- }
-
- dont_queue:
- /* Process head of queue, if one exists. */
- if (head >= tail)
- break;
-
- basetypes = search_stack->first[head++];
- binfo = TREE_VALUE (basetypes);
- type = BINFO_TYPE (binfo);
- idx = lookup_fnfields_1 (type, name);
- if (idx >= 0)
- {
- 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), idx);
- goto dont_queue;
- }
- }
- nval = NULL_TREE;
- }
-
- search_stack = pop_search_level (search_stack);
- return rval;
-}
-
-tree
+static tree
next_baselink (baselink)
tree baselink;
{
@@ -2500,33 +2048,6 @@ 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. */
-
-static int cid;
-
-/* Matrix implementing a relation from CLASSTYPE X CLASSTYPE => INT.
- Relation yields 1 if C1 <= C2, 0 otherwise. */
-typedef char mi_boolean;
-static mi_boolean *mi_matrix;
-
-/* Type for which this matrix is defined. */
-static tree mi_type;
-
-/* Size of the matrix for indexing purposes. */
-static int mi_size;
-
-/* Return nonzero if class C2 derives from class C1. */
-#define BINFO_DERIVES_FROM(C1, C2) \
- ((mi_matrix+mi_size*(BINFO_CID (C1)-1))[BINFO_CID (C2)-1])
-#define TYPE_DERIVES_FROM(C1, C2) \
- ((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
@@ -2536,163 +2057,128 @@ static tree
convert_pointer_to_single_level (to_type, expr)
tree to_type, expr;
{
+ tree derived;
tree binfo_of_derived;
- tree last;
-
- binfo_of_derived = TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr)));
- last = get_binfo (to_type, TREE_TYPE (TREE_TYPE (expr)), 0);
- BINFO_INHERITANCE_CHAIN (last) = binfo_of_derived;
- BINFO_INHERITANCE_CHAIN (binfo_of_derived) = NULL_TREE;
- return build_vbase_path (PLUS_EXPR, build_pointer_type (to_type), expr, last, 1);
-}
-
-/* The main function which implements depth first search.
-
- 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. */
-
-static void
-dfs_walk (binfo, fn, qfn)
- tree binfo;
- void (*fn) PROTO((tree));
- int (*qfn) PROTO((tree));
-{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ int i;
- for (i = 0; i < n_baselinks; i++)
+ derived = TREE_TYPE (TREE_TYPE (expr));
+ binfo_of_derived = TYPE_BINFO (derived);
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (binfo_of_derived) == NULL_TREE,
+ 980827);
+ for (i = CLASSTYPE_N_BASECLASSES (derived) - 1; i >= 0; --i)
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (qfn == 0 || (*qfn)(base_binfo))
- {
- 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
- type, as otherwise there would be no record of it, and just
- trying to blindly convert at the bottom would be ambiguous.
-
- The easiest way is to do the conversions one step at a time,
- as we know we want the immediate base class at each step.
+ tree binfo = BINFO_BASETYPE (binfo_of_derived, i);
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (binfo) == binfo_of_derived,
+ 980827);
+ if (same_type_p (BINFO_TYPE (binfo), to_type))
+ return build_vbase_path (PLUS_EXPR,
+ build_pointer_type (to_type),
+ expr, binfo, 1);
+ }
- The only special trick to converting one step at a time,
- is that when we hit the last virtual base class, we must
- use the SLOT value for it, and not use the normal convert
- routine. We use the last virtual base class, as in our
- implementation, we have pointers to all virtual base
- classes in the base object. */
+ my_friendly_abort (19990607);
- tree saved_vbase_decl_ptr_intermediate
- = vbase_decl_ptr_intermediate;
+ /* NOTREACHED */
+ return NULL_TREE;
+}
- if (TREE_VIA_VIRTUAL (base_binfo))
- {
- /* No need for the conversion here, as we know it is the
- right type. */
- vbase_decl_ptr_intermediate
- = CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo));
- }
- else
- {
- vbase_decl_ptr_intermediate
- = convert_pointer_to_single_level (BINFO_TYPE (base_binfo),
- vbase_decl_ptr_intermediate);
- }
+tree markedp (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return BINFO_MARKED (binfo) ? binfo : NULL_TREE;
+}
- dfs_walk (base_binfo, fn, qfn);
+static tree
+unmarkedp (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
+}
- vbase_decl_ptr_intermediate = saved_vbase_decl_ptr_intermediate;
- }
- else
- dfs_walk (base_binfo, fn, qfn);
- }
- }
+static tree
+marked_vtable_pathp (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE;
+}
- fn (binfo);
+static tree
+unmarked_vtable_pathp (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return !BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE;
}
-#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 tree
+marked_new_vtablep (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE;
+}
-static int markedp (binfo) tree binfo;
-{ return BINFO_MARKED (binfo); }
-static int unmarkedp (binfo) tree binfo;
-{ return BINFO_MARKED (binfo) == 0; }
+static tree
+unmarked_new_vtablep (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return !BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE;
+}
-#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 bfs_marked_vtable_pathp (binfo, i) tree binfo; int i;
-{ return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int bfs_unmarked_vtable_pathp (binfo, i) tree binfo; int i;
-{ return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-static int bfs_marked_new_vtablep (binfo, i) tree binfo; int i;
-{ return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int bfs_unmarked_new_vtablep (binfo, i) tree binfo; int i;
-{ return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-#endif
+static tree
+marked_pushdecls_p (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (CLASS_TYPE_P (BINFO_TYPE (binfo))
+ && BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
+}
-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; }
+static tree
+unmarked_pushdecls_p (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (CLASS_TYPE_P (BINFO_TYPE (binfo))
+ && !BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
+}
#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; }
+static tree
+dfs_debug_unmarkedp (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (!CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo))
+ ? binfo : NULL_TREE);
+}
/* The worker functions for `dfs_walk'. These do not need to
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. */
-
-static void
-dfs_number (binfo)
- tree binfo;
-{
- BINFO_CID (binfo) = ++cid;
-}
-
-static void
-dfs_unnumber (binfo)
- tree 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); }
+tree
+dfs_unmark (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ CLEAR_BINFO_MARKED (binfo);
+ return NULL_TREE;
+}
#if 0
static void
@@ -2716,9 +2202,10 @@ dfs_clear_search_slot (binfo) tree binfo;
{ CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
#endif
-static void
-dfs_debug_mark (binfo)
+static tree
+dfs_debug_mark (binfo, data)
tree binfo;
+ void *data ATTRIBUTE_UNUSED;
{
tree t = BINFO_TYPE (binfo);
@@ -2729,13 +2216,12 @@ dfs_debug_mark (binfo)
CLASSTYPE_DEBUG_REQUESTED (t) = 1;
if (methods == 0)
- return;
+ return NULL_TREE;
/* 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;
+ if (CLASSTYPE_INTERFACE_KNOWN (t))
+ return NULL_TREE;
/* If debug info is requested from this context for this type, supply it.
If debug info is requested from another context for this type,
@@ -2759,7 +2245,7 @@ dfs_debug_mark (binfo)
/* Somebody, somewhere is going to have to define this
virtual function. When they do, they will provide
the debugging info. */
- return;
+ return NULL_TREE;
}
methods = TREE_CHAIN (methods);
}
@@ -2768,17 +2254,26 @@ dfs_debug_mark (binfo)
so we must write out the debug info ourselves. */
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
rest_of_type_compilation (t, toplevel_bindings_p ());
+
+ return NULL_TREE;
}
-/* Attach to the type of the virtual base class, the pointer to the
- virtual base class, given the global pointer vbase_decl_ptr.
+struct vbase_info
+{
+ tree decl_ptr;
+ tree inits;
+ tree vbase_types;
+};
- We use the global vbase_types. ICK! */
+/* Attach to the type of the virtual base class, the pointer to the
+ virtual base class. */
-static void
-dfs_find_vbases (binfo)
+static tree
+dfs_find_vbases (binfo, data)
tree binfo;
+ void *data;
{
+ struct vbase_info *vi = (struct vbase_info *) data;
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2790,21 +2285,25 @@ dfs_find_vbases (binfo)
&& CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo)) == 0)
{
tree vbase = BINFO_TYPE (base_binfo);
- tree binfo = binfo_member (vbase, vbase_types);
+ tree binfo = binfo_member (vbase, vi->vbase_types);
CLASSTYPE_SEARCH_SLOT (vbase)
= build (PLUS_EXPR, build_pointer_type (vbase),
- vbase_decl_ptr, BINFO_OFFSET (binfo));
+ vi->decl_ptr, BINFO_OFFSET (binfo));
}
}
SET_BINFO_VTABLE_PATH_MARKED (binfo);
SET_BINFO_NEW_VTABLE_MARKED (binfo);
+
+ return NULL_TREE;
}
-static void
-dfs_init_vbase_pointers (binfo)
+static tree
+dfs_init_vbase_pointers (binfo, data)
tree binfo;
+ void *data;
{
+ struct vbase_info *vi = (struct vbase_info *) data;
tree type = BINFO_TYPE (binfo);
tree fields = TYPE_FIELDS (type);
tree this_vbase_ptr;
@@ -2818,42 +2317,57 @@ dfs_init_vbase_pointers (binfo)
fields = TREE_CHAIN (fields);
#endif
+ if (BINFO_INHERITANCE_CHAIN (binfo))
+ {
+ this_vbase_ptr = TREE_CHAIN (BINFO_INHERITANCE_CHAIN (binfo));
+ if (TREE_VIA_VIRTUAL (binfo))
+ this_vbase_ptr = CLASSTYPE_SEARCH_SLOT (type);
+ else
+ this_vbase_ptr = convert_pointer_to_single_level (type,
+ this_vbase_ptr);
+ TREE_CHAIN (binfo) = this_vbase_ptr;
+ }
+ else
+ this_vbase_ptr = TREE_CHAIN (binfo);
+
if (fields == NULL_TREE
|| DECL_NAME (fields) == NULL_TREE
|| ! VBASE_NAME_P (DECL_NAME (fields)))
- return;
-
- this_vbase_ptr = vbase_decl_ptr_intermediate;
+ return NULL_TREE;
- if (build_pointer_type (type) != TYPE_MAIN_VARIANT (TREE_TYPE (this_vbase_ptr)))
+ if (build_pointer_type (type)
+ != TYPE_MAIN_VARIANT (TREE_TYPE (this_vbase_ptr)))
my_friendly_abort (125);
- while (fields && DECL_NAME (fields)
- && VBASE_NAME_P (DECL_NAME (fields)))
+ while (fields && DECL_NAME (fields) && VBASE_NAME_P (DECL_NAME (fields)))
{
tree ref = build (COMPONENT_REF, TREE_TYPE (fields),
build_indirect_ref (this_vbase_ptr, NULL_PTR), 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),
- vbase_init_result);
+ vi->inits = tree_cons (binfo_member (TREE_TYPE (TREE_TYPE (fields)),
+ vi->vbase_types),
+ build_modify_expr (ref, NOP_EXPR, init),
+ vi->inits);
fields = TREE_CHAIN (fields);
}
+
+ return NULL_TREE;
}
/* 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)
+static tree
+dfs_clear_vbase_slots (binfo, data)
tree binfo;
+ void *data ATTRIBUTE_UNUSED;
{
tree type = BINFO_TYPE (binfo);
CLASSTYPE_SEARCH_SLOT (type) = 0;
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
+ return NULL_TREE;
}
tree
@@ -2863,17 +2377,29 @@ init_vbase_pointers (type, decl_ptr)
{
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
+ struct vbase_info vi;
int old_flag = flag_this_is_variable;
tree binfo = TYPE_BINFO (type);
flag_this_is_variable = -2;
- vbase_types = CLASSTYPE_VBASECLASSES (type);
- 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);
- dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
+
+ /* Find all the virtual base classes, marking them for later
+ initialization. */
+ vi.decl_ptr = decl_ptr;
+ vi.vbase_types = CLASSTYPE_VBASECLASSES (type);
+ vi.inits = NULL_TREE;
+
+ dfs_walk (binfo, dfs_find_vbases, unmarked_vtable_pathp, &vi);
+
+ /* Build up a list of the initializers. */
+ TREE_CHAIN (binfo) = decl_ptr;
+ dfs_walk_real (binfo,
+ dfs_init_vbase_pointers, 0,
+ marked_vtable_pathp,
+ &vi);
+
+ dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
flag_this_is_variable = old_flag;
- return vbase_init_result;
+ return vi.inits;
}
return 0;
}
@@ -2962,7 +2488,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
*vbase_offsets = delta;
}
- n = skip_rtti_stuff (&virtuals);
+ n = skip_rtti_stuff (&virtuals, t);
while (virtuals)
{
@@ -2987,7 +2513,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
/* 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))));
+ TYPE_MAIN_VARIANT (TREE_TYPE (vtbl)));
DECL_ALIGN (nvtbl) = MAX (TYPE_ALIGN (double_type_node),
DECL_ALIGN (nvtbl));
TREE_READONLY (nvtbl) = 0;
@@ -3012,8 +2538,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
(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)));
+ (build_modify_expr (ref, NOP_EXPR, nvtbl));
}
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
@@ -3026,7 +2551,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
/* 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);
+ TREE_VALUE (delta));
if (vc)
{
/* If this is set, we need to subtract out the delta
@@ -3047,10 +2572,14 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
/* 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);
+ old_delta = build_binary_op (MINUS_EXPR, old_delta, vc_delta);
}
TREE_READONLY (new_delta) = 0;
+ TREE_TYPE (new_delta) =
+ cp_build_qualified_type (TREE_TYPE (new_delta),
+ CP_TYPE_QUALS (TREE_TYPE (new_delta))
+ & ~TYPE_QUAL_CONST);
expand_expr_stmt (build_modify_expr (new_delta, NOP_EXPR,
old_delta));
}
@@ -3108,10 +2637,7 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
When USE_COMPUTED_OFFSETS is non-zero, we can assume that the
object was laid out by a top-level constructor and the computed
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_ptr, vbase_types
- ICK! */
+ vtables through virtual baseclass pointers. */
void
expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
@@ -3120,21 +2646,34 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
{
tree type = BINFO_TYPE (binfo);
+ /* This function executes during the finish_function() segment,
+ AFTER the auto variables and temporary stack space has been marked
+ unused...If space is needed for the virtual function tables,
+ some of them might fit within what the compiler now thinks
+ are available stack slots... These values are actually initialized at
+ the beginnning of the function, so when the automatics use their space,
+ they will overwrite the values that are placed here. Marking all
+ temporary space as unavailable prevents this from happening. */
+
+ mark_all_temps_used();
+
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
rtx fixup_insns = NULL_RTX;
tree vbases = CLASSTYPE_VBASECLASSES (type);
- vbase_types = vbases;
- vbase_decl_ptr = true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) : decl_ptr;
+ struct vbase_info vi;
+ vi.decl_ptr = (true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0)
+ : decl_ptr);
+ vi.vbase_types = vbases;
- dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep);
+ dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep, &vi);
/* Initialized with vtables of type TYPE. */
for (; vbases; vbases = TREE_CHAIN (vbases))
{
tree addr;
- addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vbase_decl_ptr);
+ addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vi.decl_ptr);
/* Do all vtables from this virtual base. */
/* This assumes that virtual bases can never serve as parent
@@ -3159,7 +2698,7 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
push_to_sequence (fixup_insns);
fixup_virtual_upcast_offsets (vbases,
TYPE_BINFO (BINFO_TYPE (vbases)),
- 1, 0, addr, vbase_decl_ptr,
+ 1, 0, addr, vi.decl_ptr,
type, vbases, &vbase_offsets);
fixup_insns = get_insns ();
end_sequence ();
@@ -3175,13 +2714,13 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
warning ("recoverable internal compiler error, nobody's in charge!");
in_charge_node = integer_zero_node;
}
- in_charge_node = build_binary_op (EQ_EXPR, in_charge_node, integer_zero_node, 1);
+ in_charge_node = build_binary_op (EQ_EXPR, in_charge_node, integer_zero_node);
expand_start_cond (in_charge_node, 0);
emit_insns (fixup_insns);
expand_end_cond ();
}
- dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
+ dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
}
}
@@ -3189,38 +2728,43 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
This adds type to the vbase_types list in reverse dfs order.
Ordering is very important, so don't change it. */
-static void
-dfs_get_vbase_types (binfo)
+static tree
+dfs_get_vbase_types (binfo, data)
tree binfo;
+ void *data;
{
+ tree *vbase_types = (tree *) data;
+
if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
{
- vbase_types = make_binfo (integer_zero_node, binfo,
- BINFO_VTABLE (binfo),
- BINFO_VIRTUALS (binfo), vbase_types);
- TREE_VIA_VIRTUAL (vbase_types) = 1;
+ tree new_vbase = make_binfo (integer_zero_node, binfo,
+ BINFO_VTABLE (binfo),
+ BINFO_VIRTUALS (binfo));
+ TREE_CHAIN (new_vbase) = *vbase_types;
+ TREE_VIA_VIRTUAL (new_vbase) = 1;
+ *vbase_types = new_vbase;
SET_BINFO_VBASE_MARKED (binfo);
}
SET_BINFO_MARKED (binfo);
+ return NULL_TREE;
}
-/* get a list of virtual base classes in dfs order. */
+/* Return a list of binfos for the virtual base classes for TYPE, in
+ depth-first search order. The list is freshly allocated, so
+ no modification is made to the current binfo hierarchy. */
tree
get_vbase_types (type)
tree type;
{
+ tree vbase_types;
tree vbases;
tree binfo;
- if (TREE_CODE (type) == TREE_VEC)
- binfo = type;
- else
- binfo = TYPE_BINFO (type);
-
+ binfo = TYPE_BINFO (type);
vbase_types = NULL_TREE;
- dfs_walk (binfo, dfs_get_vbase_types, unmarkedp);
- dfs_walk (binfo, dfs_unmark, markedp);
+ dfs_walk (binfo, dfs_get_vbase_types, unmarkedp, &vbase_types);
+ dfs_walk (binfo, dfs_unmark, markedp, 0);
/* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
reverse it so that we get normal dfs ordering. */
vbase_types = nreverse (vbase_types);
@@ -3232,95 +2776,6 @@ get_vbase_types (type)
return vbase_types;
}
-#ifdef MI_MATRIX
-static void
-dfs_record_inheritance (binfo)
- tree binfo;
-{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- mi_boolean *derived_row = BINFO_DERIVES_FROM_STAR (binfo);
-
- for (i = n_baselinks-1; i >= 0; i--)
- {
- int j;
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- 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)
- for (j = mi_size*(CLASSTYPE_CID (baseclass)-1); j >= 0; j -= mi_size)
- derived_row[j] |= base_row[j];
- TYPE_DERIVES_FROM (baseclass, BINFO_TYPE (binfo)) = 1;
- }
-
- SET_BINFO_MARKED (binfo);
-}
-
-/* Given a _CLASSTYPE node in a multiple inheritance lattice,
- convert the lattice into a simple relation such that,
- given to CIDs, C1 and C2, one can determine if C1 <= C2
- or C2 <= C1 or C1 <> C2.
-
- Once constructed, we walk the lattice depth fisrt,
- applying various functions to elements as they are encountered.
-
- We use xmalloc here, in case we want to randomly free these tables. */
-
-#define SAVE_MI_MATRIX
-
-void
-build_mi_matrix (type)
- tree type;
-{
- tree binfo = TYPE_BINFO (type);
- cid = 0;
-
-#ifdef SAVE_MI_MATRIX
- if (CLASSTYPE_MI_MATRIX (type))
- {
- mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
- mi_matrix = CLASSTYPE_MI_MATRIX (type);
- mi_type = type;
- dfs_walk (binfo, dfs_number, unnumberedp);
- return;
- }
-#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_record_inheritance, unmarkedp);
- dfs_walk (binfo, dfs_unmark, markedp);
-}
-
-void
-free_mi_matrix ()
-{
- dfs_walk (TYPE_BINFO (mi_type), dfs_unnumber, numberedp);
-
-#ifdef SAVE_MI_MATRIX
- CLASSTYPE_MI_MATRIX (mi_type) = mi_matrix;
-#else
- free (mi_matrix);
- mi_size = 0;
- 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
the problem of not writing any debug info for intermediate basetypes
@@ -3347,284 +2802,167 @@ note_debug_info_needed (type)
if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
return;
- dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp);
+ dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp, 0);
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
tree ttype;
if (TREE_CODE (field) == FIELD_DECL
&& IS_AGGR_TYPE (ttype = target_type (TREE_TYPE (field)))
- && dfs_debug_unmarkedp (TYPE_BINFO (ttype)))
+ && dfs_debug_unmarkedp (TYPE_BINFO (ttype), 0))
note_debug_info_needed (ttype);
}
}
/* Subroutines of push_class_decls (). */
-/* Add in a decl to the envelope. */
+/* Returns 1 iff BINFO is a base we shouldn't really be able to see into,
+ because it (or one of the intermediate bases) depends on template parms. */
+
+static int
+dependent_base_p (binfo)
+ tree binfo;
+{
+ for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
+ {
+ if (currently_open_class (TREE_TYPE (binfo)))
+ break;
+ if (uses_template_parms (TREE_TYPE (binfo)))
+ return 1;
+ }
+ return 0;
+}
+
static void
-envelope_add_decl (type, decl, values)
- tree type, decl, *values;
-{
- tree context, *tmp;
- tree name = DECL_NAME (decl);
- int dont_add = 0;
-
- /* 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;
-
- /* Possible ambiguity. If its defining type(s)
- is (are all) derived from us, no problem. */
- else if (*values && TREE_CODE (*values) != TREE_LIST)
- {
- tree value = *values;
- /* Only complain if we shadow something we can access. */
- if (warn_shadow && TREE_CODE (decl) == FUNCTION_DECL
- && ((DECL_LANG_SPECIFIC (*values)
- && DECL_CLASS_CONTEXT (value) == current_class_type)
- || ! TREE_PRIVATE (value)))
- /* Should figure out access control more accurately. */
- {
- cp_warning_at ("member `%#D' is shadowed", value);
- cp_warning_at ("by member function `%#D'", decl);
- warning ("in this context");
- }
+setup_class_bindings (name, type_binding_p)
+ tree name;
+ int type_binding_p;
+{
+ tree type_binding = NULL_TREE;
+ tree value_binding;
- context = DECL_REAL_CONTEXT (value);
+ /* If we've already done the lookup for this declaration, we're
+ done. */
+ if (IDENTIFIER_CLASS_VALUE (name))
+ return;
- if (context == type)
- {
- if (TREE_CODE (value) == TYPE_DECL
- && DECL_ARTIFICIAL (value))
- *values = NULL_TREE;
- else
- dont_add = 1;
- }
- 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;
- }
+ /* First, deal with the type binding. */
+ if (type_binding_p)
+ {
+ type_binding = lookup_member (current_class_type, name,
+ /*protect=*/2,
+ /*want_type=*/1);
+ if (TREE_CODE (type_binding) == TREE_LIST
+ && TREE_TYPE (type_binding) == error_mark_node)
+ /* NAME is ambiguous. */
+ push_class_level_binding (name, type_binding);
else
- *values = build_tree_list (NULL_TREE, value);
- }
+ pushdecl_class_level (type_binding);
+ }
+
+ /* Now, do the value binding. */
+ value_binding = lookup_member (current_class_type, name,
+ /*protect=*/2,
+ /*want_type=*/0);
+
+ if (type_binding_p
+ && (TREE_CODE (value_binding) == TYPE_DECL
+ || (TREE_CODE (value_binding) == TREE_LIST
+ && TREE_TYPE (value_binding) == error_mark_node
+ && (TREE_CODE (TREE_VALUE (value_binding))
+ == TYPE_DECL))))
+ /* We found a type-binding, even when looking for a non-type
+ binding. This means that we already processed this binding
+ above. */
+ my_friendly_assert (type_binding_p, 19990401);
else
- for (tmp = values; *tmp;)
- {
- tree value = TREE_VALUE (*tmp);
- my_friendly_assert (TREE_CODE (value) != TREE_LIST, 999);
- context = (TREE_CODE (value) == FUNCTION_DECL
- && DECL_VIRTUAL_P (value))
- ? DECL_CLASS_CONTEXT (value)
- : DECL_CONTEXT (value);
-
- if (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);
- }
- else
- tmp = &TREE_CHAIN (*tmp);
- }
-
- if (! dont_add)
- {
- /* Put the new contents in our envelope. */
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- *values = tree_cons (name, decl, *values);
- TREE_NONLOCAL_FLAG (*values) = 1;
- TREE_TYPE (*values) = unknown_type_node;
- }
+ {
+ if (TREE_CODE (value_binding) == TREE_LIST
+ && TREE_TYPE (value_binding) == error_mark_node)
+ /* NAME is ambiguous. */
+ push_class_level_binding (name, value_binding);
else
{
- if (*values)
- {
- *values = tree_cons (NULL_TREE, decl, *values);
- /* Mark this as a potentially ambiguous member. */
- /* Leaving TREE_TYPE blank is intentional.
- We cannot use `error_mark_node' (lookup_name)
- or `unknown_type_node' (all member functions use this). */
- TREE_NONLOCAL_FLAG (*values) = 1;
- }
- else
- *values = decl;
+ if (BASELINK_P (value_binding))
+ /* NAME is some overloaded functions. */
+ value_binding = TREE_VALUE (value_binding);
+ pushdecl_class_level (value_binding);
}
}
}
-/* Add the instance variables which this class contributed to the
- current class binding contour. When a redefinition occurs, if the
- redefinition is strictly within a single inheritance path, we just
- overwrite the old declaration with the new. If the fields are not
- within a single inheritance path, we must cons them.
+/* Push class-level declarations for any names appearing in BINFO that
+ are TYPE_DECLS. */
- In order to know what decls are new (stemming from the current
- invocation of push_class_decls) we enclose them in an "envelope",
- which is a TREE_LIST node where the TREE_PURPOSE slot contains the
- new decl (or possibly a list of competing ones), the TREE_VALUE slot
- points to the old value and the TREE_CHAIN slot chains together all
- envelopes which needs to be "opened" in push_class_decls. Opening an
- envelope means: push the old value onto the class_shadowed list,
- install the new one and if it's a TYPE_DECL do the same to the
- IDENTIFIER_TYPE_VALUE. Such an envelope is recognized by seeing that
- the TREE_PURPOSE slot is non-null, and that it is not an identifier.
- Because if it is, it could be a set of overloaded methods from an
- outer scope. */
-
-static void
-dfs_pushdecls (binfo)
+static tree
+dfs_push_type_decls (binfo, data)
tree binfo;
+ void *data ATTRIBUTE_UNUSED;
{
- tree type = BINFO_TYPE (binfo);
- tree fields, *methods, *end;
- tree method_vec;
+ tree type;
+ tree fields;
+ type = BINFO_TYPE (binfo);
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
- {
- /* Unmark 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. */
- if (TREE_CODE (fields) == FIELD_DECL)
- TREE_USED (fields) = 0;
+ if (DECL_NAME (fields) && TREE_CODE (fields) == TYPE_DECL
+ && !(!same_type_p (type, current_class_type)
+ && template_self_reference_p (type, fields)))
+ setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/1);
- /* Recurse into anonymous unions. */
- if (DECL_NAME (fields) == NULL_TREE
- && TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
- {
- dfs_pushdecls (TYPE_BINFO (TREE_TYPE (fields)));
- continue;
- }
-
- if (DECL_NAME (fields))
- {
- tree name = DECL_NAME (fields);
- tree class_value = IDENTIFIER_CLASS_VALUE (name);
-
- /* If the class value is not an envelope of the kind described in
- the comment above, we create a new envelope. */
- if (class_value == NULL_TREE || TREE_CODE (class_value) != TREE_LIST
- || TREE_PURPOSE (class_value) == NULL_TREE
- || TREE_CODE (TREE_PURPOSE (class_value)) == IDENTIFIER_NODE)
- {
- /* See comment above for a description of envelopes. */
- closed_envelopes = tree_cons (NULL_TREE, class_value,
- closed_envelopes);
- IDENTIFIER_CLASS_VALUE (name) = closed_envelopes;
- class_value = IDENTIFIER_CLASS_VALUE (name);
- }
-
- envelope_add_decl (type, fields, &TREE_PURPOSE (class_value));
- }
- }
-
- method_vec = CLASSTYPE_METHOD_VEC (type);
- if (method_vec)
- {
- /* Farm out constructors and destructors. */
- 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 (OVL_CURRENT (*methods));
- tree class_value = IDENTIFIER_CLASS_VALUE (name);
-
- /* If the class value is not an envelope of the kind described in
- the comment above, we create a new envelope. */
- if (class_value == NULL_TREE || TREE_CODE (class_value) != TREE_LIST
- || TREE_PURPOSE (class_value) == NULL_TREE
- || TREE_CODE (TREE_PURPOSE (class_value)) == IDENTIFIER_NODE)
- {
- /* See comment above for a description of envelopes. */
- closed_envelopes = tree_cons (NULL_TREE, class_value,
- closed_envelopes);
- IDENTIFIER_CLASS_VALUE (name) = closed_envelopes;
- class_value = IDENTIFIER_CLASS_VALUE (name);
- }
+ /* We can't just use BINFO_MARKED because envelope_add_decl uses
+ DERIVED_FROM_P, which calls get_base_distance. */
+ SET_BINFO_PUSHDECLS_MARKED (binfo);
- /* Here we try to rule out possible ambiguities.
- If we can't do that, keep a TREE_LIST with possibly ambiguous
- decls in there. */
- maybe_push_cache_obstack ();
- /* 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++;
- }
- }
- SET_BINFO_MARKED (binfo);
+ return NULL_TREE;
}
-/* Consolidate unique (by name) member functions. */
+/* Push class-level declarations for any names appearing in BINFO that
+ are not TYPE_DECLS. */
-static void
-dfs_compress_decls (binfo)
+static tree
+dfs_push_decls (binfo, data)
tree binfo;
+ void *data;
{
- tree type = BINFO_TYPE (binfo);
- tree method_vec = CLASSTYPE_METHOD_VEC (type);
+ tree type;
+ tree method_vec;
+ int dep_base_p;
+
+ type = BINFO_TYPE (binfo);
+ dep_base_p = (processing_template_decl && type != current_class_type
+ && dependent_base_p (binfo));
+ if (!dep_base_p)
+ {
+ tree fields;
+ for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
+ if (DECL_NAME (fields)
+ && TREE_CODE (fields) != TYPE_DECL
+ && TREE_CODE (fields) != USING_DECL)
+ setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
+ else if (TREE_CODE (fields) == FIELD_DECL
+ && ANON_UNION_TYPE_P (TREE_TYPE (fields)))
+ dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
+
+ method_vec = (CLASS_TYPE_P (type)
+ ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE);
+ if (method_vec)
+ {
+ tree *methods;
+ tree *end;
- if (method_vec != 0)
- {
- /* Farm out constructors and destructors. */
- tree *methods = &TREE_VEC_ELT (method_vec, 2);
- tree *end = TREE_VEC_END (method_vec);
+ /* Farm out constructors and destructors. */
+ 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 (OVL_CURRENT (*methods)));
- tree tmp = TREE_PURPOSE (class_value);
-
- /* This was replaced in scope by somebody else. Just leave it
- alone. */
- if (TREE_CODE (tmp) != TREE_LIST)
- continue;
-
- if (TREE_CHAIN (tmp) == NULL_TREE
- && TREE_VALUE (tmp)
- && OVL_NEXT (TREE_VALUE (tmp)) == NULL_TREE)
- {
- TREE_PURPOSE (class_value) = TREE_VALUE (tmp);
- }
+ for (methods = &TREE_VEC_ELT (method_vec, 2);
+ *methods && methods != end;
+ methods++)
+ setup_class_bindings (DECL_NAME (OVL_CURRENT (*methods)),
+ /*type_binding_p=*/0);
}
}
- CLEAR_BINFO_MARKED (binfo);
+
+ CLEAR_BINFO_PUSHDECLS_MARKED (binfo);
+
+ return NULL_TREE;
}
/* When entering the scope of a class, we cache all of the
@@ -3641,81 +2979,29 @@ push_class_decls (type)
struct obstack *ambient_obstack = current_obstack;
search_stack = push_search_level (search_stack, &search_obstack);
- /* Push class fields into CLASS_VALUE scope, and mark. */
- dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp);
-
- /* Compress fields which have only a single entry
- by a given name, and unmark. */
- dfs_walk (TYPE_BINFO (type), dfs_compress_decls, markedp);
-
- /* Open up all the closed envelopes and push the contained decls into
- class scope. */
- while (closed_envelopes)
- {
- tree new = TREE_PURPOSE (closed_envelopes);
- tree id;
-
- /* This is messy because the class value may be a *_DECL, or a
- TREE_LIST of overloaded *_DECLs or even a TREE_LIST of ambiguous
- *_DECLs. The name is stored at different places in these three
- cases. */
- if (TREE_CODE (new) == TREE_LIST)
- {
- if (TREE_PURPOSE (new) != NULL_TREE)
- id = TREE_PURPOSE (new);
- else
- {
- tree node = TREE_VALUE (new);
+ /* Build up all the relevant bindings and such on the cache
+ obstack. That way no memory is wasted when we throw away the
+ cache later. */
+ push_cache_obstack ();
- 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;
+ /* Enter type declarations and mark. */
+ dfs_walk (TYPE_BINFO (type), dfs_push_type_decls, unmarked_pushdecls_p, 0);
- 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;
- }
+ /* Enter non-type declarations and unmark. */
+ dfs_walk (TYPE_BINFO (type), dfs_push_decls, marked_pushdecls_p, 0);
- if (n == NULL_TREE)
- new = t;
- }
- else while (TREE_CODE (node) == TREE_LIST)
- node = TREE_VALUE (node);
- id = DECL_NAME (node);
- }
- }
- else
- id = DECL_NAME (new);
+ /* Undo the call to push_cache_obstack above. */
+ pop_obstacks ();
- /* Install the original class value in order to make
- pushdecl_class_level work correctly. */
- IDENTIFIER_CLASS_VALUE (id) = TREE_VALUE (closed_envelopes);
- if (TREE_CODE (new) == TREE_LIST)
- push_class_level_binding (id, new);
- else
- pushdecl_class_level (new);
- closed_envelopes = TREE_CHAIN (closed_envelopes);
- }
current_obstack = ambient_obstack;
}
/* Here's a subroutine we need because C lacks lambdas. */
-static void
-dfs_unuse_fields (binfo)
+static tree
+dfs_unuse_fields (binfo, data)
tree binfo;
+ void *data ATTRIBUTE_UNUSED;
{
tree type = TREE_TYPE (binfo);
tree fields;
@@ -3730,13 +3016,15 @@ dfs_unuse_fields (binfo)
&& TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
unuse_fields (TREE_TYPE (fields));
}
+
+ return NULL_TREE;
}
void
unuse_fields (type)
tree type;
{
- dfs_walk (TYPE_BINFO (type), dfs_unuse_fields, unmarkedp);
+ dfs_walk (TYPE_BINFO (type), dfs_unuse_fields, unmarkedp, 0);
}
void
@@ -3752,23 +3040,6 @@ void
print_search_statistics ()
{
#ifdef GATHER_STATISTICS
- if (flag_memoize_lookups)
- {
- fprintf (stderr, "%d memoized contexts saved\n",
- n_contexts_saved);
- fprintf (stderr, "%d local tree nodes made\n", my_tree_node_counter);
- fprintf (stderr, "%d local hash nodes made\n", my_memoized_entry_counter);
- fprintf (stderr, "fields statistics:\n");
- fprintf (stderr, " memoized finds = %d; rejects = %d; (searches = %d)\n",
- memoized_fast_finds[0], memoized_fast_rejects[0],
- memoized_fields_searched[0]);
- fprintf (stderr, " memoized_adds = %d\n", memoized_adds[0]);
- fprintf (stderr, "fnfields statistics:\n");
- fprintf (stderr, " memoized finds = %d; rejects = %d; (searches = %d)\n",
- memoized_fast_finds[1], memoized_fast_rejects[1],
- memoized_fields_searched[1]);
- fprintf (stderr, " memoized_adds = %d\n", memoized_adds[1]);
- }
fprintf (stderr, "%d fields searched in %d[%d] calls to lookup_field[_1]\n",
n_fields_searched, n_calls_lookup_field, n_calls_lookup_field_1);
fprintf (stderr, "%d fnfields searched in %d calls to lookup_fnfields\n",
@@ -3783,27 +3054,12 @@ void
init_search_processing ()
{
gcc_obstack_init (&search_obstack);
- gcc_obstack_init (&type_obstack);
- gcc_obstack_init (&type_obstack_entries);
-
- /* This gives us room to build our chains of basetypes,
- whether or not we decide to memoize them. */
- type_stack = push_type_level ((struct stack_level *)0, &type_obstack);
_vptr_name = get_identifier ("_vptr");
}
void
reinit_search_statistics ()
{
- my_memoized_entry_counter = 0;
- memoized_fast_finds[0] = 0;
- memoized_fast_finds[1] = 0;
- memoized_adds[0] = 0;
- memoized_adds[1] = 0;
- memoized_fast_rejects[0] = 0;
- 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;
@@ -3816,145 +3072,92 @@ reinit_search_statistics ()
#define scratch_tree_cons expr_tree_cons
-static tree conversions;
-static void
-add_conversions (binfo)
+static tree
+add_conversions (binfo, data)
tree binfo;
+ void *data;
{
int i;
tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
+ tree *conversions = (tree *) data;
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
-lookup_conversions (type)
- tree type;
-{
- conversions = NULL_TREE;
- 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;
- }
+ tree name;
- binfos = BINFO_BASETYPES (binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ if (!tmp || ! DECL_CONV_FN_P (OVL_CURRENT (tmp)))
+ break;
- /* Process base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
+ name = DECL_NAME (OVL_CURRENT (tmp));
- /* Find any specific instance of a virtual base, when searching with
- a binfo... */
- if (BINFO_MARKED (base_binfo) == 0)
+ /* Make sure we don't already have this conversion. */
+ if (! IDENTIFIER_MARKED (name))
{
- 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;
+ *conversions = scratch_tree_cons (binfo, tmp, *conversions);
+ IDENTIFIER_MARKED (name) = 1;
}
}
-
- return rval;
+ return NULL_TREE;
}
-/* 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;
+lookup_conversions (type)
+ tree type;
{
- tree type = NULL_TREE, rval;
+ tree t;
+ tree conversions = NULL_TREE;
- 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;
+ if (TYPE_SIZE (type))
+ bfs_walk (TYPE_BINFO (type), add_conversions, 0, &conversions);
- rval = get_template_base_recursive (binfo, NULL_TREE, template, 0);
- dfs_walk (binfo, dfs_unmark, markedp);
+ for (t = conversions; t; t = TREE_CHAIN (t))
+ IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT (TREE_VALUE (t)))) = 0;
- return rval;
+ return conversions;
}
+struct overlap_info
+{
+ tree compare_type;
+ int found_overlap;
+};
+
/* 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)
+static tree
+dfs_check_overlap (empty_binfo, data)
tree empty_binfo;
+ void *data;
{
+ struct overlap_info *oi = (struct overlap_info *) data;
tree binfo;
- for (binfo = TYPE_BINFO (compare_type); ; binfo = BINFO_BASETYPE (binfo, 0))
+ for (binfo = TYPE_BINFO (oi->compare_type);
+ ;
+ binfo = BINFO_BASETYPE (binfo, 0))
{
if (BINFO_TYPE (binfo) == BINFO_TYPE (empty_binfo))
{
- found_overlap = 1;
+ oi->found_overlap = 1;
break;
}
else if (BINFO_BASETYPES (binfo) == NULL_TREE)
break;
}
+
+ return NULL_TREE;
}
/* Trivial function to stop base traversal when we find something. */
-static int
-dfs_no_overlap_yet (t)
- tree t ATTRIBUTE_UNUSED;
+static tree
+dfs_no_overlap_yet (binfo, data)
+ tree binfo;
+ void *data;
{
- return found_overlap == 0;
+ struct overlap_info *oi = (struct overlap_info *) data;
+ return !oi->found_overlap ? binfo : NULL_TREE;
}
/* Returns nonzero if EMPTY_TYPE or any of its bases can also be found at
@@ -3964,10 +3167,64 @@ int
types_overlap_p (empty_type, next_type)
tree empty_type, next_type;
{
+ struct overlap_info oi;
+
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;
+ oi.compare_type = next_type;
+ oi.found_overlap = 0;
+ dfs_walk (TYPE_BINFO (empty_type), dfs_check_overlap,
+ dfs_no_overlap_yet, &oi);
+ return oi.found_overlap;
+}
+
+struct bfv_info {
+ tree vbases;
+ tree var;
+};
+
+static tree
+dfs_bfv_queue_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ struct bfv_info *bfvi = (struct bfv_info *) data;
+
+ /* Use the real virtual base class objects, not the placeholders in
+ the usual hierarchy. */
+ if (TREE_VIA_VIRTUAL (binfo))
+ return binfo_member (BINFO_TYPE (binfo), bfvi->vbases);
+
+ return binfo;
+}
+
+/* Passed to dfs_walk_real by binfo_for_vtable; determine if bvtable
+ comes from BINFO. */
+
+static tree
+dfs_bfv_helper (binfo, data)
+ tree binfo;
+ void *data;
+{
+ struct bfv_info *bfvi = (struct bfv_info *) data;
+
+ if (BINFO_VTABLE (binfo) == bfvi->var)
+ return binfo;
+ return NULL_TREE;
+}
+
+/* Given a vtable VAR, determine which binfo it comes from. */
+
+tree
+binfo_for_vtable (var)
+ tree var;
+{
+ tree type;
+ struct bfv_info bfvi;
+
+ type = DECL_CONTEXT (var);
+ bfvi.vbases = CLASSTYPE_VBASECLASSES (type);
+ bfvi.var = var;
+ return dfs_walk_real (TYPE_BINFO (type),
+ 0, dfs_bfv_helper, dfs_bfv_queue_p, &bfvi);
}
diff --git a/contrib/gcc/cp/semantics.c b/contrib/gcc/cp/semantics.c
index 5068512..7267f46 100644
--- a/contrib/gcc/cp/semantics.c
+++ b/contrib/gcc/cp/semantics.c
@@ -3,7 +3,7 @@
building RTL. These routines are used both during actual parsing
and during the instantiation of template functions.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
Written by Mark Mitchell (mmitchell@usa.net) based on code found
formerly in parse.y and pt.c.
@@ -120,7 +120,7 @@ finish_if_stmt_cond (cond, if_stmt)
if (last_tree != if_stmt)
RECHAIN_STMTS_FROM_LAST (if_stmt, IF_COND (if_stmt));
else
- IF_COND (if_stmt) = cond;
+ IF_COND (if_stmt) = copy_to_permanent (cond);
}
else
{
@@ -219,7 +219,7 @@ finish_while_stmt_cond (cond, while_stmt)
RECHAIN_STMTS_FROM_LAST (while_stmt,
WHILE_COND (while_stmt));
else
- TREE_OPERAND (while_stmt, 0) = cond;
+ TREE_OPERAND (while_stmt, 0) = copy_to_permanent (cond);
}
else
{
@@ -294,7 +294,7 @@ finish_do_stmt (cond, do_stmt)
tree do_stmt;
{
if (processing_template_decl)
- DO_COND (do_stmt) = cond;
+ DO_COND (do_stmt) = copy_to_permanent (cond);
else
{
emit_line_note (input_filename, lineno);
@@ -378,7 +378,7 @@ finish_for_cond (cond, for_stmt)
if (last_tree != for_stmt)
RECHAIN_STMTS_FROM_LAST (for_stmt, FOR_COND (for_stmt));
else
- FOR_COND (for_stmt) = cond;
+ FOR_COND (for_stmt) = copy_to_permanent (cond);
}
else
{
@@ -490,12 +490,20 @@ finish_switch_cond (cond)
r = build_min_nt (SWITCH_STMT, cond, NULL_TREE);
add_tree (r);
}
- else
+ else if (cond != error_mark_node)
{
emit_line_note (input_filename, lineno);
c_expand_start_case (cond);
r = NULL_TREE;
}
+ else
+ {
+ /* The code is in error, but we don't want expand_end_case to
+ crash. */
+ c_expand_start_case (boolean_false_node);
+ r = NULL_TREE;
+ }
+
push_switch ();
/* Don't let the tree nodes for COND be discarded by
@@ -731,13 +739,18 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
{
emit_line_note (input_filename, lineno);
if (output_operands != NULL_TREE || input_operands != NULL_TREE
- || clobbers != NULL_TREE)
+ || clobbers != NULL_TREE)
{
+ tree t;
+
if (cv_qualifier != NULL_TREE
&& cv_qualifier != ridpointers[(int) RID_VOLATILE])
cp_warning ("%s qualifier ignored on asm",
IDENTIFIER_POINTER (cv_qualifier));
-
+
+ for (t = input_operands; t; t = TREE_CHAIN (t))
+ TREE_VALUE (t) = decay_conversion (TREE_VALUE (t));
+
c_expand_asm_operands (string, output_operands,
input_operands,
clobbers,
@@ -747,12 +760,14 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
}
else
{
- if (cv_qualifier != NULL_TREE)
+ /* Don't warn about redundant specification of 'volatile' here. */
+ if (cv_qualifier != NULL_TREE
+ && cv_qualifier != ridpointers[(int) RID_VOLATILE])
cp_warning ("%s qualifier ignored on asm",
IDENTIFIER_POINTER (cv_qualifier));
expand_asm (string);
}
-
+
finish_stmt ();
}
}
@@ -807,8 +822,8 @@ finish_stmt_expr (rtl_expr, expr)
{
/* Make a BIND_EXPR for the BLOCK already made. */
if (processing_template_decl)
- result = build (BIND_EXPR, NULL_TREE,
- NULL_TREE, last_tree, expr);
+ result = build_min_nt (BIND_EXPR, NULL_TREE, last_tree,
+ NULL_TREE);
else
result = build (BIND_EXPR, TREE_TYPE (rtl_expr),
NULL_TREE, rtl_expr, expr);
@@ -853,7 +868,8 @@ finish_call_expr (fn, args, koenig)
result = build_x_function_call (fn, args, current_class_ref);
if (TREE_CODE (result) == CALL_EXPR
- && TREE_TYPE (result) != void_type_node)
+ && (! TREE_TYPE (result)
+ || TREE_CODE (TREE_TYPE (result)) != VOID_TYPE))
result = require_complete_type (result);
return result;
@@ -995,7 +1011,7 @@ finish_pseudo_destructor_call_expr (object, scope, destructor)
ARGS. Returns an expression for the call. */
tree
-finish_globally_qualified_member_call_expr (fn, args)
+finish_qualified_call_expr (fn, args)
tree fn;
tree args;
{
@@ -1098,6 +1114,10 @@ begin_function_definition (decl_specs, declarator)
return 0;
reinit_parse_for_function ();
+ /* The things we're about to see are not directly qualified by any
+ template headers we've seen thus far. */
+ reset_specialization ();
+
return 1;
}
@@ -1110,13 +1130,7 @@ begin_constructor_declarator (scope, name)
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;
- }
-
+ enter_scope_of (result);
return result;
}
@@ -1210,50 +1224,85 @@ 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);
+ t = make_lang_type (RECORD_TYPE);
pushtag (make_anon_name (), t, 0);
}
- if (TYPE_SIZE (t))
+
+ /* In a definition of a member class template, we will get here with an
+ implicit typename, a TYPENAME_TYPE with a type. */
+ if (TREE_CODE (t) == TYPENAME_TYPE)
+ t = TREE_TYPE (t);
+
+ /* If we generated a partial instantiation of this type, but now
+ we're seeing a real definition, we're actually looking at a
+ partial specialization. Consider:
+
+ template <class T, class U>
+ struct Y {};
+
+ template <class T>
+ struct X {};
+
+ template <class T, class U>
+ void f()
+ {
+ typename X<Y<T, U> >::A a;
+ }
+
+ template <class T, class U>
+ struct X<Y<T, U> >
+ {
+ };
+
+ We have to undo the effects of the previous partial
+ instantiation. */
+ if (PARTIAL_INSTANTIATION_P (t))
+ {
+ if (!pedantic)
+ {
+ /* Unfortunately, when we're not in pedantic mode, we
+ attempt to actually fill in some of the fields of the
+ partial instantiation, in order to support the implicit
+ typename extension. Clear those fields now, in
+ preparation for the definition here. The fields cleared
+ here must match those set in instantiate_class_template.
+ Look for a comment mentioning begin_class_definition
+ there. */
+ TYPE_BINFO_BASETYPES (t) = NULL_TREE;
+ TYPE_FIELDS (t) = NULL_TREE;
+ TYPE_METHODS (t) = NULL_TREE;
+ CLASSTYPE_TAGS (t) = NULL_TREE;
+ TYPE_SIZE (t) = NULL_TREE;
+ }
+
+ /* This isn't a partial instantiation any more. */
+ PARTIAL_INSTANTIATION_P (t) = 0;
+ }
+ /* If this type was already complete, and we see another definition,
+ that's an error. */
+ else if (TYPE_SIZE (t))
duplicate_tag_error (t);
- if (TYPE_SIZE (t) || TYPE_BEING_DEFINED (t))
+
+ if (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);
+ maybe_process_partial_specialization (t);
+ pushclass (t, 1);
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);
@@ -1265,30 +1314,19 @@ begin_class_definition (t)
}
/* Record how to set the access of this class's
- virtual functions. If write_virtuals == 2 or 3, then
+ virtual functions. If write_virtuals == 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;
- }
+ if (write_virtuals == 3)
+ needs_writing = ! CLASSTYPE_INTERFACE_ONLY (t)
+ && CLASSTYPE_INTERFACE_KNOWN (t);
+ else
+ needs_writing = 1;
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = needs_writing;
}
#if 0
- t = TYPE_IDENTIFIER ($<ttype>0);
- if (t && IDENTIFIER_TEMPLATE (t))
- overload_template_name (t, 1);
+ tmp = TYPE_IDENTIFIER ($<ttype>0);
+ if (tmp && IDENTIFIER_TEMPLATE (tmp))
+ overload_template_name (tmp, 1);
#endif
reset_specialization();
@@ -1297,26 +1335,108 @@ begin_class_definition (t)
that we can get it back later. */
begin_tree ();
- return new_type;
+ /* Make a declaration for this class in its own scope. */
+ build_self_reference ();
+
+ return t;
}
-/* 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. */
+/* Finish the member declaration given by DECL. */
+
+void
+finish_member_declaration (decl)
+ tree decl;
+{
+ if (decl == error_mark_node || decl == NULL_TREE)
+ return;
+
+ if (decl == void_type_node)
+ /* The COMPONENT was a friend, not a member, and so there's
+ nothing for us to do. */
+ return;
+
+ /* We should see only one DECL at a time. */
+ my_friendly_assert (TREE_CHAIN (decl) == NULL_TREE, 0);
+
+ /* Set up access control for DECL. */
+ TREE_PRIVATE (decl)
+ = (current_access_specifier == access_private_node);
+ TREE_PROTECTED (decl)
+ = (current_access_specifier == access_protected_node);
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ TREE_PRIVATE (DECL_RESULT (decl)) = TREE_PRIVATE (decl);
+ TREE_PROTECTED (DECL_RESULT (decl)) = TREE_PROTECTED (decl);
+ }
+
+ /* Mark the DECL as a member of the current class. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (decl))
+ /* Historically, DECL_CONTEXT was not set for a FUNCTION_DECL in
+ finish_struct. Presumably it is already set as the function is
+ parsed. Perhaps DECL_CLASS_CONTEXT is already set, too? */
+ DECL_CLASS_CONTEXT (decl) = current_class_type;
+ else
+ DECL_CONTEXT (decl) = current_class_type;
+
+ /* Put functions on the TYPE_METHODS list and everything else on the
+ TYPE_FIELDS list. Note that these are built up in reverse order.
+ We reverse them (to obtain declaration order) in finish_struct. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (decl))
+ {
+ /* We also need to add this function to the
+ CLASSTYPE_METHOD_VEC. */
+ add_method (current_class_type, 0, decl);
+
+ TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
+ TYPE_METHODS (current_class_type) = decl;
+ }
+ else
+ {
+ /* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
+ go at the beginning. The reason is that lookup_field_1
+ searches the list in order, and we want a field name to
+ override a type name so that the "struct stat hack" will
+ work. In particular:
+
+ struct S { enum E { }; int E } s;
+ s.E = 3;
+
+ is legal. In addition, the FIELD_DECLs must be maintained in
+ declaration order so that class layout works as expected.
+ However, we don't need that order until class layout, so we
+ save a little time by putting FIELD_DECLs on in reverse order
+ here, and then reversing them in finish_struct_1. (We could
+ also keep a pointer to the correct insertion points in the
+ list.) */
+
+ if (TREE_CODE (decl) == TYPE_DECL)
+ TYPE_FIELDS (current_class_type)
+ = chainon (TYPE_FIELDS (current_class_type), decl);
+ else
+ {
+ TREE_CHAIN (decl) = TYPE_FIELDS (current_class_type);
+ TYPE_FIELDS (current_class_type) = decl;
+ }
+
+ /* Enter the DECL into the scope of the class. */
+ if (TREE_CODE (decl) != USING_DECL)
+ pushdecl_class_level (decl);
+ }
+}
+
+/* Finish a class definition T 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)
+finish_class_definition (t, attributes, semi, pop_scope_p)
tree t;
- tree components;
tree attributes;
int semi;
+ int pop_scope_p;
{
-#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)
@@ -1331,7 +1451,7 @@ finish_class_definition (t, components, attributes, semi)
;
else
{
- t = finish_struct (t, components, attributes, semi);
+ t = finish_struct (t, attributes, semi);
if (semi)
note_got_semicolon (t);
}
@@ -1340,6 +1460,8 @@ finish_class_definition (t, components, attributes, semi)
if (! semi)
check_for_missing_semicolon (t);
+ if (pop_scope_p)
+ pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (t)));
if (current_scope () == current_function_decl)
do_pending_defargs ();
@@ -1350,7 +1472,7 @@ finish_class_definition (t, components, attributes, semi)
the processing of a class definition. */
void
-finish_default_args ()
+begin_inline_definitions ()
{
if (pending_inlines
&& current_scope () == current_function_decl)
@@ -1361,7 +1483,7 @@ finish_default_args ()
processing of a class definition. */
void
-begin_inline_definitions ()
+finish_inline_definitions ()
{
if (current_class_type == NULL_TREE)
clear_inline_text_obstack ();
@@ -1374,20 +1496,191 @@ begin_inline_definitions ()
TYPES whose template parameters are given by PARMS. */
tree
-finish_member_class_template (parms, types)
- tree parms;
+finish_member_class_template (types)
tree types;
{
+ tree t;
+
+ /* If there are declared, but undefined, partial specializations
+ mixed in with the typespecs they will not yet have passed through
+ maybe_process_partial_specialization, so we do that here. */
+ for (t = types; t != NULL_TREE; t = TREE_CHAIN (t))
+ if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_VALUE (t))))
+ maybe_process_partial_specialization (TREE_VALUE (t));
+
note_list_got_semicolon (types);
- grok_x_components (types, NULL_TREE);
+ grok_x_components (types);
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);
+
+ finish_member_template_decl (types);
+
/* As with other component type declarations, we do
not store the new DECL on the list of
component_decls. */
return NULL_TREE;
}
+
+/* Finish processsing a complete template declaration. The PARMS are
+ the template parameters. */
+
+void
+finish_template_decl (parms)
+ tree parms;
+{
+ if (parms)
+ end_template_decl ();
+ else
+ end_specialization ();
+}
+
+/* Finish processing a a template-id (which names a type) of the form
+ NAME < ARGS >. Return the TYPE_DECL for the type named by the
+ template-id. If ENTERING_SCOPE is non-zero we are about to enter
+ the scope of template-id indicated. */
+
+tree
+finish_template_type (name, args, entering_scope)
+ tree name;
+ tree args;
+ int entering_scope;
+{
+ tree decl;
+
+ decl = lookup_template_class (name, args,
+ NULL_TREE, NULL_TREE, entering_scope);
+ if (decl != error_mark_node)
+ decl = TYPE_STUB_DECL (decl);
+
+ return decl;
+}
+
+/* SR is a SCOPE_REF node. Enter the scope of SR, whether it is a
+ namespace scope or a class scope. */
+
+void
+enter_scope_of (sr)
+ tree sr;
+{
+ tree scope = TREE_OPERAND (sr, 0);
+
+ if (TREE_CODE (scope) == NAMESPACE_DECL)
+ {
+ push_decl_namespace (scope);
+ TREE_COMPLEXITY (sr) = -1;
+ }
+ else if (scope != current_class_type)
+ {
+ if (TREE_CODE (scope) == TYPENAME_TYPE)
+ {
+ /* In a declarator for a template class member, the scope will
+ get here as an implicit typename, a TYPENAME_TYPE with a type. */
+ scope = TREE_TYPE (scope);
+ TREE_OPERAND (sr, 0) = scope;
+ }
+ push_nested_class (scope, 3);
+ TREE_COMPLEXITY (sr) = current_class_depth;
+ }
+}
+
+/* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER.
+ Return a TREE_LIST containing the ACCESS_SPECIFIER and the
+ BASE_CLASS, or NULL_TREE if an error occurred. The
+ ACCESSS_SPECIFIER is one of
+ access_{default,public,protected_private}[_virtual]_node.*/
+
+tree
+finish_base_specifier (access_specifier, base_class,
+ current_aggr_is_signature)
+ tree access_specifier;
+ tree base_class;
+ int current_aggr_is_signature;
+{
+ tree type;
+ tree result;
+
+ if (base_class == NULL_TREE)
+ {
+ error ("invalid base class");
+ type = error_mark_node;
+ }
+ else
+ type = TREE_TYPE (base_class);
+ if (current_aggr_is_signature && access_specifier)
+ error ("access and source specifiers not allowed in signature");
+ if (! is_aggr_type (type, 1))
+ result = NULL_TREE;
+ else if (current_aggr_is_signature
+ && (! type) && (! IS_SIGNATURE (type)))
+ {
+ error ("class name not allowed as base signature");
+ result = NULL_TREE;
+ }
+ else if (current_aggr_is_signature)
+ {
+ sorry ("signature inheritance, base type `%s' ignored",
+ IDENTIFIER_POINTER (access_specifier));
+ result = build_tree_list (access_public_node, type);
+ }
+ else if (type && IS_SIGNATURE (type))
+ {
+ error ("signature name not allowed as base class");
+ result = NULL_TREE;
+ }
+ else
+ result = build_tree_list (access_specifier, type);
+
+ return result;
+}
+
+/* Called when multiple declarators are processed. If that is not
+ premitted in this context, an error is issued. */
+
+void
+check_multiple_declarators ()
+{
+ /* [temp]
+
+ In a template-declaration, explicit specialization, or explicit
+ instantiation the init-declarator-list in the declaration shall
+ contain at most one declarator.
+
+ We don't just use PROCESSING_TEMPLATE_DECL for the first
+ condition since that would disallow the perfectly legal code,
+ like `template <class T> struct S { int i, j; };'. */
+ tree scope = current_scope ();
+
+ if (scope && TREE_CODE (scope) == FUNCTION_DECL)
+ /* It's OK to write `template <class T> void f() { int i, j;}'. */
+ return;
+
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ()
+ || processing_explicit_instantiation
+ || processing_specialization)
+ cp_error ("multiple declarators in template declaration");
+}
+
+tree
+finish_typeof (expr)
+ tree expr;
+{
+ if (processing_template_decl)
+ {
+ tree t;
+
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
+ t = make_lang_type (TYPEOF_TYPE);
+ TYPE_FIELDS (t) = expr;
+
+ pop_obstacks ();
+
+ return t;
+ }
+
+ return TREE_TYPE (expr);
+}
diff --git a/contrib/gcc/cp/sig.c b/contrib/gcc/cp/sig.c
index 65350db..f170df5 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, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-97, 1998 Free Software Foundation, Inc.
Contributed by Gerald Baumgartner (gb@cs.purdue.edu)
This file is part of GNU CC.
@@ -33,18 +33,16 @@ extern struct obstack *current_obstack;
extern struct obstack permanent_obstack;
extern struct obstack *saveable_obstack;
-extern void compiler_error ();
-
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));
+ PROTO((tree, 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));
+ PROTO((tree, 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));
@@ -58,25 +56,31 @@ static int global_sigtable_name_counter;
can use it's name in function name mangling. */
static tree
-build_signature_pointer_or_reference_name (to_type, constp, volatilep, refp)
+build_signature_pointer_or_reference_name (to_type, type_quals, refp)
tree to_type;
- int constp, volatilep, refp;
+ int type_quals;
+ int refp;
{
- char * sig_name = TYPE_NAME_STRING (to_type);
- int name_len = TYPE_NAME_LENGTH (to_type) + constp + volatilep;
+ const char * sig_name = TYPE_NAME_STRING (to_type);
+ int name_len = TYPE_NAME_LENGTH (to_type) + 3 /* Enough room for
+ C,V,R. */;
char * name;
+ const char *const_rep = (type_quals & TYPE_QUAL_CONST) ? "C" : "";
+ const char *restrict_rep = (type_quals & TYPE_QUAL_RESTRICT) ? "R" : "";
+ const char *volatile_rep = (type_quals & TYPE_QUAL_VOLATILE) ? "C" : "";
+
if (refp)
{
name = (char *) alloca (name_len + sizeof (SIGNATURE_REFERENCE_NAME) +2);
sprintf (name, SIGNATURE_REFERENCE_NAME_FORMAT,
- constp ? "C" : "", volatilep ? "V": "", sig_name);
+ const_rep, volatile_rep, restrict_rep, sig_name);
}
else
{
name = (char *) alloca (name_len + sizeof (SIGNATURE_POINTER_NAME) + 2);
sprintf (name, SIGNATURE_POINTER_NAME_FORMAT,
- constp ? "C" : "", volatilep ? "V": "", sig_name);
+ const_rep, volatile_rep, restrict_rep, sig_name);
}
return get_identifier (name);
}
@@ -98,21 +102,22 @@ build_signature_pointer_or_reference_decl (type, name)
TREE_CHAIN (type) = decl;
}
-/* Construct, lay out and return the type of pointers or references
- to signature TO_TYPE. If such a type has already been constructed,
- reuse it. If CONSTP or VOLATILEP is specified, make the `optr' const
- or volatile, respectively. If we are constructing a const/volatile
- type variant and the main type variant doesn't exist yet, it is built
- as well. If REFP is 1, we construct a signature reference, otherwise
- a signature pointer is constructed.
+/* Construct, lay out and return the type of pointers or references to
+ signature TO_TYPE. If such a type has already been constructed,
+ reuse it. If TYPE_QUALS are specified, qualify the `optr'. If we
+ are constructing a const/volatile type variant and the main type
+ variant doesn't exist yet, it is built as well. If REFP is 1, we
+ construct a signature reference, otherwise a signature pointer is
+ constructed.
This function is a subroutine of `build_signature_pointer_type' and
`build_signature_reference_type'. */
static tree
-build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
+build_signature_pointer_or_reference_type (to_type, type_quals, refp)
tree to_type;
- int constp, volatilep, refp;
+ int type_quals;
+ int refp;
{
register tree t, m;
register struct obstack *ambient_obstack = current_obstack;
@@ -121,13 +126,11 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
m = refp ? SIGNATURE_REFERENCE_TO (to_type) : SIGNATURE_POINTER_TO (to_type);
/* If we don't have the main variant yet, construct it. */
- if (m == NULL_TREE
- && (constp || volatilep))
- m = build_signature_pointer_or_reference_type (to_type, 0, 0, refp);
+ if (m == NULL_TREE && type_quals != TYPE_UNQUALIFIED)
+ m = build_signature_pointer_or_reference_type (to_type,
+ TYPE_UNQUALIFIED, refp);
/* Treat any nonzero argument as 1. */
- constp = !!constp;
- volatilep = !!volatilep;
refp = !!refp;
/* If not generating auxiliary info, search the chain of variants to see
@@ -141,8 +144,8 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
if (m && !flag_gen_aux_info)
for (t = m; t; t = TYPE_NEXT_VARIANT (t))
- if (constp == TYPE_READONLY (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t))))
- && volatilep == TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t)))))
+ if (type_quals == CP_TYPE_QUALS (TREE_TYPE (TREE_TYPE
+ (TYPE_FIELDS (t)))))
return t;
/* We need a new one. If TO_TYPE is permanent, make this permanent too. */
@@ -170,7 +173,7 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
t = make_lang_type (RECORD_TYPE);
{
- tree obj_type = build_type_variant (void_type_node, constp, volatilep);
+ tree obj_type = build_qualified_type (void_type_node, type_quals);
tree optr_type = build_pointer_type (obj_type);
tree optr, sptr;
@@ -185,7 +188,8 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
sptr = TREE_CHAIN (TYPE_FIELDS (m));
else
{
- tree sig_tbl_type = cp_build_type_variant (to_type, 1, 0);
+ tree sig_tbl_type =
+ cp_build_qualified_type (to_type, TYPE_QUAL_CONST);
sptr = build_lang_field_decl (FIELD_DECL,
get_identifier (SIGNATURE_SPTR_NAME),
@@ -203,12 +207,13 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
TYPE_ALIGN (optr_type));
/* A signature pointer/reference type isn't a `real' class type. */
- IS_AGGR_TYPE (t) = 0;
+ SET_IS_AGGR_TYPE (t, 0);
}
{
- tree name = build_signature_pointer_or_reference_name (to_type, constp,
- volatilep, refp);
+ tree name = build_signature_pointer_or_reference_name (to_type,
+ type_quals,
+ refp);
/* Build a DECL node for this type, so the debugger has access to it. */
build_signature_pointer_or_reference_decl (t, name);
@@ -250,23 +255,23 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
/* Construct, lay out and return the type of pointers to signature TO_TYPE. */
tree
-build_signature_pointer_type (to_type, constp, volatilep)
+build_signature_pointer_type (to_type)
tree to_type;
- int constp, volatilep;
{
return
- build_signature_pointer_or_reference_type (to_type, constp, volatilep, 0);
+ build_signature_pointer_or_reference_type (TYPE_MAIN_VARIANT (to_type),
+ CP_TYPE_QUALS (to_type), 0);
}
/* Construct, lay out and return the type of pointers to signature TO_TYPE. */
tree
-build_signature_reference_type (to_type, constp, volatilep)
+build_signature_reference_type (to_type)
tree to_type;
- int constp, volatilep;
{
return
- build_signature_pointer_or_reference_type (to_type, constp, volatilep, 1);
+ build_signature_pointer_or_reference_type (TYPE_MAIN_VARIANT (to_type),
+ CP_TYPE_QUALS (to_type), 1);
}
/* Return the name of the signature table (as an IDENTIFIER_NODE)
@@ -281,8 +286,8 @@ get_sigtable_name (sig_type, rhs_type)
char *buf = (char *) alloca (sizeof (SIGTABLE_NAME_FORMAT_LONG)
+ IDENTIFIER_LENGTH (sig_type_id)
+ IDENTIFIER_LENGTH (rhs_type_id) + 20);
- char *sig_ptr = IDENTIFIER_POINTER (sig_type_id);
- char *rhs_ptr = IDENTIFIER_POINTER (rhs_type_id);
+ const char *sig_ptr = IDENTIFIER_POINTER (sig_type_id);
+ const char *rhs_ptr = IDENTIFIER_POINTER (rhs_type_id);
int i, j;
for (i = 0; sig_ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++)
@@ -309,7 +314,7 @@ static tree
build_member_function_pointer (member)
tree member;
{
- char *namstr = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (member));
+ const char *namstr = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (member));
int namlen = IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (member));
char *name;
tree entry;
@@ -321,7 +326,7 @@ build_member_function_pointer (member)
GNU_xref_ref (current_function_decl, name);
entry = build_lang_field_decl (FIELD_DECL, get_identifier (name),
- TYPE_MAIN_VARIANT (sigtable_entry_type));
+ sigtable_entry_type);
TREE_CONSTANT (entry) = 1;
TREE_READONLY (entry) = 1;
@@ -341,49 +346,45 @@ build_member_function_pointer (member)
The new FIELD_DECLs are appended at the end of the last (and only)
sublist of `list_of_fieldlists.'
+ T is the signature type.
+
As a side effect, each member function in the signature gets the
`decl.ignored' bit turned on, so we don't output debug info for it. */
void
-append_signature_fields (list_of_fieldlists)
- tree list_of_fieldlists;
+append_signature_fields (t)
+ tree t;
{
- tree l, x;
- tree last_x = NULL_TREE;
+ tree x;
tree mfptr;
tree last_mfptr = NULL_TREE;
tree mfptr_list = NULL_TREE;
- /* For signatures it should actually be only a list with one element. */
- for (l = list_of_fieldlists; l; l = TREE_CHAIN (l))
+ for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
- for (x = TREE_VALUE (l); x; x = TREE_CHAIN (x))
+ if (TREE_CODE (x) == FUNCTION_DECL)
{
- if (TREE_CODE (x) == FUNCTION_DECL)
+ mfptr = build_member_function_pointer (x);
+ DECL_MEMFUNC_POINTER_TO (x) = mfptr;
+ DECL_MEMFUNC_POINTING_TO (mfptr) = x;
+ DECL_IGNORED_P (x) = 1;
+ DECL_IN_AGGR_P (mfptr) = 1;
+ if (! mfptr_list)
+ mfptr_list = last_mfptr = mfptr;
+ else
{
- mfptr = build_member_function_pointer (x);
- DECL_MEMFUNC_POINTER_TO (x) = mfptr;
- DECL_MEMFUNC_POINTING_TO (mfptr) = x;
- DECL_IGNORED_P (x) = 1;
- DECL_IN_AGGR_P (mfptr) = 1;
- if (! mfptr_list)
- mfptr_list = last_mfptr = mfptr;
- else
- {
- TREE_CHAIN (last_mfptr) = mfptr;
- last_mfptr = mfptr;
- }
+ TREE_CHAIN (last_mfptr) = mfptr;
+ last_mfptr = mfptr;
}
- last_x = x;
}
}
- /* Append the lists. */
- if (last_x && mfptr_list)
- {
- TREE_CHAIN (last_x) = mfptr_list;
- TREE_CHAIN (last_mfptr) = NULL_TREE;
- }
+ /* The member function pointers must come after the TYPE_DECLs, in
+ this case, because build_signature_table_constructor depends on
+ finding opaque TYPE_DECLS before the functions that make use of
+ them. */
+ if (last_mfptr)
+ TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), mfptr_list);
}
/* Compare the types of a signature member function and a class member
@@ -405,7 +406,7 @@ match_method_types (sig_mtype, class_mtype)
tree class_arg_types = TYPE_ARG_TYPES (class_mtype);
/* The return types have to be the same. */
- if (! comptypes (sig_return_type, class_return_type, 1))
+ if (!same_type_p (sig_return_type, class_return_type))
return 0;
/* Compare the first argument `this.' */
@@ -422,8 +423,7 @@ match_method_types (sig_mtype, class_mtype)
/* If a signature method's `this' is const or volatile, so has to be
the corresponding class method's `this.' */
- if ((TYPE_READONLY (sig_this) && ! TYPE_READONLY (class_this))
- || (TYPE_VOLATILE (sig_this) && ! TYPE_VOLATILE (class_this)))
+ if (!at_least_as_qualified_p (class_this, sig_this))
return 0;
}
@@ -431,7 +431,7 @@ match_method_types (sig_mtype, class_mtype)
class_arg_types = TREE_CHAIN (class_arg_types);
/* The number of arguments and the argument types have to be the same. */
- return compparms (sig_arg_types, class_arg_types, 3);
+ return compparms (sig_arg_types, class_arg_types);
}
/* Undo casts of opaque type variables to the RHS types. */
@@ -546,12 +546,10 @@ build_signature_table_constructor (sig_ty, rhs)
break;
if (rhs_methods == NULL_TREE
- || (compute_access (basetypes, rhs_method)
- != access_public_node))
+ || !accessible_p (basetypes, rhs_method))
{
- error ("class `%s' does not contain a method conforming to `%s'",
- TYPE_NAME_STRING (rhstype),
- fndecl_as_string (sig_method, 1));
+ cp_error ("`%T' does not contain a method conforming to `%#D'",
+ rhstype, sig_method);
undo_casts (sig_ty);
return error_mark_node;
}
@@ -886,7 +884,7 @@ build_signature_pointer_constructor (lhs, rhs)
}
else
{
- if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype))
+ if (TREE_READONLY (lhs) || CP_TYPE_CONST_P (lhstype))
readonly_error (lhs, "assignment", 0);
optr_expr = build_modify_expr (build_optr_ref (lhs), NOP_EXPR,
@@ -980,9 +978,8 @@ build_signature_method_call (function, parms)
tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))));
TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))))
- = build_type_variant (build_pointer_type (basetype),
- TYPE_READONLY (old_this),
- TYPE_VOLATILE (old_this));
+ = build_qualified_type (build_pointer_type (basetype),
+ TYPE_QUALS (old_this));
direct_call = build_function_call (pfn, new_parms);
diff --git a/contrib/gcc/cp/spew.c b/contrib/gcc/cp/spew.c
index f153150..a573cba 100644
--- a/contrib/gcc/cp/spew.c
+++ b/contrib/gcc/cp/spew.c
@@ -1,5 +1,5 @@
/* Type 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... nay, bludgeoned... by Mark Eichin (eichin@cygnus.com)
This file is part of GNU CC.
@@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "parse.h"
#include "flags.h"
#include "obstack.h"
+#include "toplev.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
@@ -47,7 +48,7 @@ struct token {
static int do_aggr PROTO((void));
static int probe_obstack PROTO((struct obstack *, tree, unsigned int));
-static void scan_tokens PROTO((int));
+static void scan_tokens PROTO((unsigned int));
#ifdef SPEW_DEBUG
static int num_tokens PROTO((void));
@@ -155,9 +156,9 @@ consume_token ()
static void
scan_tokens (n)
- int n;
+ unsigned int n;
{
- int i;
+ unsigned int i;
struct token *tmp;
/* We cannot read past certain tokens, so make sure we don't. */
@@ -244,7 +245,7 @@ int
yylex ()
{
struct token tmp_token;
- tree trrr;
+ tree trrr = NULL_TREE;
int old_looking_for_typename = 0;
retry:
@@ -360,6 +361,19 @@ yylex ()
break;
case SCSPEC:
+ /* If export, warn that it's unimplemented and go on. */
+ if (tmp_token.yylval.ttype == get_identifier("export"))
+ {
+ warning ("keyword 'export' not implemented and will be ignored");
+ consume_token ();
+ goto retry;
+ }
+ else
+ {
+ ++first_token;
+ break;
+ }
+
case NEW:
/* do_aggr needs to check if the previous token was RID_NEW,
so just increment first_token instead of calling consume_token. */
diff --git a/contrib/gcc/cp/tinfo.cc b/contrib/gcc/cp/tinfo.cc
index d8380da..5269cb5 100644
--- a/contrib/gcc/cp/tinfo.cc
+++ b/contrib/gcc/cp/tinfo.cc
@@ -1,5 +1,5 @@
// Methods for type_info for -*- C++ -*- Run Time Type Identification.
-// Copyright (C) 1994, 1996 Free Software Foundation
+// Copyright (C) 1994, 1996, 1998 Free Software Foundation
// This file is part of GNU CC.
@@ -40,8 +40,8 @@ std::type_info::
{ }
// We can't rely on common symbols being shared between shared objects.
-bool type_info::
-operator== (const type_info& arg) const
+bool std::type_info::
+operator== (const std::type_info& arg) const
{
return (&arg == this) || (strcmp (name (), arg.name ()) == 0);
}
diff --git a/contrib/gcc/cp/tinfo.h b/contrib/gcc/cp/tinfo.h
index 3cfee04..e0b9eec 100644
--- a/contrib/gcc/cp/tinfo.h
+++ b/contrib/gcc/cp/tinfo.h
@@ -1,5 +1,5 @@
// RTTI support internals for -*- C++ -*-
-// Copyright (C) 1994, 1995, 1996 Free Software Foundation
+// Copyright (C) 1994, 1995, 1996, 1998 Free Software Foundation
#include "typeinfo"
@@ -40,7 +40,7 @@ struct __class_type_info : public __user_type_info {
const __user_type_info *base;
USItype offset: 29;
bool is_virtual: 1;
- access access: 2;
+ enum access access: 2;
};
const base_info *base_list;
diff --git a/contrib/gcc/cp/tinfo2.cc b/contrib/gcc/cp/tinfo2.cc
index 3e63354..b101db3 100644
--- a/contrib/gcc/cp/tinfo2.cc
+++ b/contrib/gcc/cp/tinfo2.cc
@@ -1,5 +1,5 @@
// Methods for type_info for -*- C++ -*- Run Time Type Identification.
-// Copyright (C) 1994, 1996 Free Software Foundation
+// Copyright (C) 1994, 96-97, 1998 Free Software Foundation
// This file is part of GNU CC.
diff --git a/contrib/gcc/cp/tree.c b/contrib/gcc/cp/tree.c
index 7c7768f..866aa27 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, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -28,40 +28,30 @@ Boston, MA 02111-1307, USA. */
#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 tree list_hash_lookup PROTO((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 lvalue_p_1 PROTO((tree, int));
static int equal_functions PROTO((tree, tree));
+static tree no_linkage_helper PROTO((tree));
+static tree build_srcloc PROTO((char *, int));
#define CEIL(x,y) (((x) + (y) - 1) / (y))
-/* Return nonzero if REF is an lvalue valid for this language.
- Lvalues can be assigned, unless they have TREE_READONLY.
- Lvalues can have their address taken, unless they have DECL_REGISTER. */
+/* Returns non-zero if REF is an lvalue. If
+ TREAT_CLASS_RVALUES_AS_LVALUES is non-zero, rvalues of class type
+ are considered lvalues. */
-int
-real_lvalue_p (ref)
+static int
+lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
tree ref;
+ int treat_class_rvalues_as_lvalues;
{
- if (! language_lvalue_valid (ref))
- return 0;
-
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
@@ -79,7 +69,11 @@ real_lvalue_p (ref)
case UNSAVE_EXPR:
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
- return real_lvalue_p (TREE_OPERAND (ref, 0));
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case NOP_EXPR:
+ return lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues);
case STRING_CST:
return 1;
@@ -93,9 +87,7 @@ real_lvalue_p (ref)
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
- case ERROR_MARK:
- if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
- && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
+ if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1;
break;
@@ -105,24 +97,43 @@ real_lvalue_p (ref)
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1;
- return real_lvalue_p (TREE_OPERAND (ref, 0))
- && real_lvalue_p (TREE_OPERAND (ref, 1));
+ return (lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues)
+ && lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues));
break;
case COND_EXPR:
- return (real_lvalue_p (TREE_OPERAND (ref, 1))
- && real_lvalue_p (TREE_OPERAND (ref, 2)));
+ return (lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues)
+ && lvalue_p_1 (TREE_OPERAND (ref, 2),
+ treat_class_rvalues_as_lvalues));
case MODIFY_EXPR:
return 1;
case COMPOUND_EXPR:
- return real_lvalue_p (TREE_OPERAND (ref, 1));
+ return lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues);
case MAX_EXPR:
case MIN_EXPR:
- return (real_lvalue_p (TREE_OPERAND (ref, 0))
- && real_lvalue_p (TREE_OPERAND (ref, 1)));
+ return (lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues)
+ && lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues));
+
+ case TARGET_EXPR:
+ return treat_class_rvalues_as_lvalues;
+
+ case CALL_EXPR:
+ return (treat_class_rvalues_as_lvalues
+ && IS_AGGR_TYPE (TREE_TYPE (ref)));
+
+ case FUNCTION_DECL:
+ /* All functions (except non-static-member functions) are
+ lvalues. */
+ return !DECL_NONSTATIC_MEMBER_FUNCTION_P (ref);
default:
break;
@@ -131,92 +142,26 @@ real_lvalue_p (ref)
return 0;
}
+/* Return nonzero if REF is an lvalue valid for this language.
+ Lvalues can be assigned, unless they have TREE_READONLY, or unless
+ they are FUNCTION_DECLs. Lvalues can have their address taken,
+ unless they have DECL_REGISTER. */
+
+int
+real_lvalue_p (ref)
+ tree ref;
+{
+ return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
+}
+
/* This differs from real_lvalue_p in that class rvalues are considered
lvalues. */
+
int
lvalue_p (ref)
tree ref;
{
- if (! language_lvalue_valid (ref))
- return 0;
-
- if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
- return 1;
-
- 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. */
- 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:
- return 1;
-
- case VAR_DECL:
- if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
- && DECL_LANG_SPECIFIC (ref)
- && DECL_IN_AGGR_P (ref))
- return 0;
- case INDIRECT_REF:
- case ARRAY_REF:
- case PARM_DECL:
- case RESULT_DECL:
- case ERROR_MARK:
- if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
- && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
- return 1;
- break;
-
- case TARGET_EXPR:
- return 1;
-
- case CALL_EXPR:
- if (IS_AGGR_TYPE (TREE_TYPE (ref)))
- return 1;
- break;
-
- /* A currently unresolved scope ref. */
- case SCOPE_REF:
- my_friendly_abort (103);
- case OFFSET_REF:
- if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
- return 1;
- return lvalue_p (TREE_OPERAND (ref, 0))
- && lvalue_p (TREE_OPERAND (ref, 1));
- break;
-
- case COND_EXPR:
- return (lvalue_p (TREE_OPERAND (ref, 1))
- && lvalue_p (TREE_OPERAND (ref, 2)));
-
- case MODIFY_EXPR:
- return 1;
-
- case COMPOUND_EXPR:
- return lvalue_p (TREE_OPERAND (ref, 1));
-
- case MAX_EXPR:
- case MIN_EXPR:
- return (lvalue_p (TREE_OPERAND (ref, 0))
- && lvalue_p (TREE_OPERAND (ref, 1)));
-
- default:
- break;
- }
-
- return 0;
+ return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1);
}
/* Return nonzero if REF is an lvalue valid for this language;
@@ -225,7 +170,7 @@ lvalue_p (ref)
int
lvalue_or_else (ref, string)
tree ref;
- char *string;
+ const char *string;
{
int win = lvalue_p (ref);
if (! win)
@@ -249,7 +194,7 @@ build_cplus_new (type, init)
tree rval;
if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
- return init;
+ return convert (type, init);
slot = build (VAR_DECL, type);
DECL_ARTIFICIAL (slot) = 1;
@@ -431,9 +376,7 @@ build_cplus_method_type (basetype, rettype, argtypes)
TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
TREE_TYPE (t) = rettype;
if (IS_SIGNATURE (basetype))
- ptype = build_signature_pointer_type (TYPE_MAIN_VARIANT (basetype),
- TYPE_READONLY (basetype),
- TYPE_VOLATILE (basetype));
+ ptype = build_signature_pointer_type (basetype);
else
ptype = build_pointer_type (basetype);
@@ -473,7 +416,8 @@ build_cplus_array_type_1 (elt_type, index_type)
saveable_obstack = &permanent_obstack;
}
- if (processing_template_decl
+ if (processing_template_decl
+ || uses_template_parms (elt_type)
|| uses_template_parms (index_type))
{
t = make_node (ARRAY_TYPE);
@@ -498,14 +442,14 @@ build_cplus_array_type (elt_type, index_type)
tree index_type;
{
tree t;
- int constp = TYPE_READONLY (elt_type);
- int volatilep = TYPE_VOLATILE (elt_type);
+ int type_quals = CP_TYPE_QUALS (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);
+ if (type_quals != TYPE_UNQUALIFIED)
+ t = cp_build_qualified_type (t, type_quals);
return t;
}
@@ -514,21 +458,32 @@ build_cplus_array_type (elt_type, index_type)
down to the element type of an array. */
tree
-cp_build_type_variant (type, constp, volatilep)
+cp_build_qualified_type (type, type_quals)
tree type;
- int constp, volatilep;
+ int type_quals;
{
if (type == error_mark_node)
return type;
+ /* A restrict-qualified pointer type must be a pointer (or reference)
+ to object or incomplete type. */
+ if ((type_quals & TYPE_QUAL_RESTRICT)
+ && (!POINTER_TYPE_P (type)
+ || TYPE_PTRMEM_P (type)
+ || TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE))
+ {
+ cp_error ("`%T' cannot be `restrict'-qualified", type);
+ type_quals &= ~TYPE_QUAL_RESTRICT;
+ }
+
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_1 (cp_build_type_variant
- (TREE_TYPE (type), constp, volatilep),
+ type = build_cplus_array_type_1 (cp_build_qualified_type
+ (TREE_TYPE (type), type_quals),
TYPE_DOMAIN (type));
/* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not,
@@ -545,7 +500,7 @@ cp_build_type_variant (type, constp, volatilep)
pop_obstacks ();
return type;
}
- return build_type_variant (type, constp, volatilep);
+ return build_qualified_type (type, type_quals);
}
/* Returns the canonical version of TYPE. In other words, if TYPE is
@@ -557,18 +512,7 @@ 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);
+ return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), CP_TYPE_QUALS (t));
}
/* Add OFFSET to all base types of T.
@@ -618,7 +562,7 @@ propagate_binfo_offsets (binfo, offset)
BINFO_OFFSET (base_binfo) = offset;
#endif
- unshare_base_binfos (base_binfo);
+ propagate_binfo_offsets (base_binfo, offset);
/* Go to our next class that counts for offset propagation. */
i = j;
@@ -628,40 +572,35 @@ propagate_binfo_offsets (binfo, offset)
}
}
-/* Makes new binfos for the indirect bases under BASE_BINFO, and updates
+/* Makes new binfos for the indirect bases under BINFO, and updates
BINFO_OFFSET for them and their bases. */
-static void
-unshare_base_binfos (base_binfo)
- tree base_binfo;
+void
+unshare_base_binfos (binfo)
+ tree binfo;
{
- if (BINFO_BASETYPES (base_binfo))
- {
- tree base_binfos = BINFO_BASETYPES (base_binfo);
- tree chain = NULL_TREE;
- int j;
+ tree binfos = BINFO_BASETYPES (binfo);
+ tree new_binfo;
+ 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;
- }
+ if (binfos == NULL_TREE)
+ return;
- /* Completely unshare potentially shared data, and
- update what is ours. */
- propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
+ /* Now unshare the structure beneath BINFO. */
+ for (j = TREE_VEC_LENGTH (binfos)-1;
+ j >= 0; j--)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, j);
+ new_binfo = TREE_VEC_ELT (binfos, j)
+ = make_binfo (BINFO_OFFSET (base_binfo),
+ base_binfo,
+ BINFO_VTABLE (base_binfo),
+ BINFO_VIRTUALS (base_binfo));
+ TREE_VIA_PUBLIC (new_binfo) = TREE_VIA_PUBLIC (base_binfo);
+ TREE_VIA_PROTECTED (new_binfo) = TREE_VIA_PROTECTED (base_binfo);
+ TREE_VIA_VIRTUAL (new_binfo) = TREE_VIA_VIRTUAL (base_binfo);
+ BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
+ unshare_base_binfos (new_binfo);
}
}
@@ -681,9 +620,7 @@ layout_basetypes (rec, 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);
+ tree vbase_types;
unsigned int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
unsigned int desired_align;
@@ -698,7 +635,11 @@ layout_basetypes (rec, max)
record_align = MAX (record_align, STRUCTURE_SIZE_BOUNDARY);
#endif
- CLASSTYPE_VBASECLASSES (rec) = vbase_types;
+ /* Get all the virtual base types that this type uses. The
+ TREE_VALUE slot holds the virtual baseclass type. Note that
+ get_vbase_types makes copies of the virtual base BINFOs, so that
+ the vbase_types are unshared. */
+ vbase_types = CLASSTYPE_VBASECLASSES (rec);
my_friendly_assert (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST, 19970302);
const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec));
@@ -764,10 +705,15 @@ layout_basetypes (rec, max)
continue;
my_friendly_assert (TREE_TYPE (field) == basetype, 23897);
+
+ if (get_base_distance (basetype, rec, 0, (tree*)0) == -2)
+ cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, rec);
+
BINFO_OFFSET (base_binfo)
= size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)),
BITS_PER_UNIT));
- unshare_base_binfos (base_binfo);
+ propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
TYPE_FIELDS (rec) = TREE_CHAIN (field);
}
@@ -776,6 +722,15 @@ layout_basetypes (rec, max)
{
BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec);
unshare_base_binfos (vbase_types);
+ propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types));
+
+ if (extra_warnings)
+ {
+ tree basetype = BINFO_TYPE (vbase_types);
+ if (get_base_distance (basetype, rec, 0, (tree*)0) == -2)
+ cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, rec);
+ }
}
return max;
@@ -851,7 +806,7 @@ build_base_fields (rec)
base_align = MAX (base_align, DECL_ALIGN (decl));
DECL_SIZE (decl)
= size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
- base_align));
+ (int) base_align));
}
else if (DECL_SIZE (decl) == integer_zero_node)
saw_empty = 1;
@@ -925,8 +880,7 @@ build_vbase_pointer_fields (rec)
if (TREE_VIA_VIRTUAL (base_binfo))
{
int j;
- char *name = (char *)alloca (TYPE_NAME_LENGTH (basetype)
- + sizeof (VBASE_NAME) + 1);
+ const char *name;
/* The offset for a virtual base class is only used in computing
virtual function tables and for initializing virtual base
@@ -946,7 +900,7 @@ build_vbase_pointer_fields (rec)
))
goto got_it;
}
- sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype));
+ FORMAT_VBASE_NAME (name, 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
@@ -1024,18 +978,14 @@ list_hash (purpose, value, chain)
If one is found, return it. Otherwise return 0. */
static tree
-list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
- purpose, value, chain)
- int hashcode, via_public, via_virtual, via_protected;
+list_hash_lookup (hashcode, purpose, value, chain)
+ int hashcode;
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) == 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)
@@ -1060,24 +1010,16 @@ list_hash_add (hashcode, list)
list_hash_table[hashcode % TYPE_HASH_SIZE] = h;
}
-/* Given TYPE, and HASHCODE its hash code, return the canonical
- object for an identical list if one already exists.
- Otherwise, return TYPE, and record it as the canonical object
- if it is a permanent object.
-
- To use this function, first create a list of the sort you want.
- Then compute its hash code from the fields of the list that
- make it different from other similar lists.
- Then call this function and use the value.
- This function frees the list you pass in if it is a duplicate. */
+/* Given list components PURPOSE, VALUE, AND CHAIN, return the canonical
+ object for an identical list if one already exists. Otherwise, build a
+ new one, and record it as the canonical object. */
/* Set to 1 to debug without canonicalization. Never set by program. */
static int debug_no_list_hash = 0;
tree
-hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
- int via_public, via_virtual, via_protected;
+hash_tree_cons (purpose, value, chain)
tree purpose, value, chain;
{
struct obstack *ambient_obstack = current_obstack;
@@ -1087,8 +1029,7 @@ hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
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);
+ t = list_hash_lookup (hashcode, purpose, value, chain);
if (t)
return t;
}
@@ -1096,9 +1037,6 @@ hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
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;
/* If this is a new list, record it for later reuse. */
if (! debug_no_list_hash)
@@ -1114,7 +1052,7 @@ tree
hash_tree_chain (value, chain)
tree value, chain;
{
- return hash_tree_cons (0, 0, 0, NULL_TREE, value, chain);
+ return hash_tree_cons (NULL_TREE, value, chain);
}
/* Similar, but used for concatenating two lists. */
@@ -1132,60 +1070,6 @@ hash_chainon (list1, list2)
return hash_tree_chain (TREE_VALUE (list1),
hash_chainon (TREE_CHAIN (list1), list2));
}
-
-static tree
-get_identifier_list (value)
- tree value;
-{
- tree list = IDENTIFIER_AS_LIST (value);
- if (list != NULL_TREE
- && (TREE_CODE (list) != TREE_LIST
- || TREE_VALUE (list) != value))
- list = NULL_TREE;
- else if (IDENTIFIER_HAS_TYPE_VALUE (value)
- && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE
- && IDENTIFIER_TYPE_VALUE (value)
- == TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (value)))
- {
- tree type = IDENTIFIER_TYPE_VALUE (value);
-
- if (TYPE_PTRMEMFUNC_P (type))
- list = NULL_TREE;
- else if (type == current_class_type)
- /* Don't mess up the constructor name. */
- list = tree_cons (NULL_TREE, value, NULL_TREE);
- else
- {
- if (! CLASSTYPE_ID_AS_LIST (type))
- CLASSTYPE_ID_AS_LIST (type)
- = perm_tree_cons (NULL_TREE, TYPE_IDENTIFIER (type), NULL_TREE);
- list = CLASSTYPE_ID_AS_LIST (type);
- }
- }
- return list;
-}
-
-tree
-get_decl_list (value)
- tree value;
-{
- tree list = NULL_TREE;
-
- if (TREE_CODE (value) == IDENTIFIER_NODE)
- list = get_identifier_list (value);
- else if (TREE_CODE (value) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (value)
- && value == TYPE_MAIN_VARIANT (value))
- list = CLASSTYPE_AS_LIST (value);
-
- if (list != NULL_TREE)
- {
- my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 301);
- return list;
- }
-
- return build_decl_list (NULL_TREE, value);
-}
/* Build an association between TYPE and some parameters:
@@ -1200,15 +1084,12 @@ get_decl_list (value)
VTABLE is the virtual function table with which to initialize
sub-objects of type TYPE.
- VIRTUALS are the virtual functions sitting in VTABLE.
-
- CHAIN are more associations we must retain. */
+ VIRTUALS are the virtual functions sitting in VTABLE. */
tree
-make_binfo (offset, binfo, vtable, virtuals, chain)
+make_binfo (offset, binfo, vtable, virtuals)
tree offset, binfo;
tree vtable, virtuals;
- tree chain;
{
tree new_binfo = make_tree_vec (7);
tree type;
@@ -1218,13 +1099,9 @@ make_binfo (offset, binfo, vtable, virtuals, chain)
else
{
type = binfo;
- binfo = TYPE_BINFO (binfo);
+ binfo = CLASS_TYPE_P (type) ? TYPE_BINFO (binfo) : NULL_TREE;
}
- TREE_CHAIN (new_binfo) = chain;
- if (chain)
- TREE_USED (new_binfo) = TREE_USED (chain);
-
TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type);
BINFO_OFFSET (new_binfo) = offset;
BINFO_VTABLE (new_binfo) = vtable;
@@ -1253,17 +1130,24 @@ binfo_value (elem, type)
return get_binfo (elem, type, 0);
}
+/* Return a reversed copy of the BINFO-chain given by PATH. (If the
+ BINFO_INHERITANCE_CHAIN points from base classes to derived
+ classes, it will instead point from derived classes to base
+ classes.) Returns the first node in the reversed chain. */
+
tree
reverse_path (path)
tree path;
{
- register tree prev = 0, tmp, next;
- for (tmp = path; tmp; tmp = next)
+ register tree prev = NULL_TREE, cur;
+ push_expression_obstack ();
+ for (cur = path; cur; cur = BINFO_INHERITANCE_CHAIN (cur))
{
- next = BINFO_INHERITANCE_CHAIN (tmp);
- BINFO_INHERITANCE_CHAIN (tmp) = prev;
- prev = tmp;
+ tree r = copy_node (cur);
+ BINFO_INHERITANCE_CHAIN (r) = prev;
+ prev = r;
}
+ pop_obstacks ();
return prev;
}
@@ -1286,7 +1170,7 @@ debug_binfo (elem)
fprintf (stderr, "virtuals:\n");
virtuals = BINFO_VIRTUALS (elem);
- n = skip_rtti_stuff (&virtuals);
+ n = skip_rtti_stuff (&virtuals, BINFO_TYPE (elem));
while (virtuals)
{
@@ -1340,15 +1224,11 @@ int
is_overloaded_fn (x)
tree x;
{
- /* 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);
- }
+ /* A baselink is also considered an overloaded function. */
+ if (TREE_CODE (x) == OFFSET_REF)
+ x = TREE_OPERAND (x, 1);
+ if (BASELINK_P (x))
+ x = TREE_VALUE (x);
return (TREE_CODE (x) == FUNCTION_DECL
|| TREE_CODE (x) == TEMPLATE_ID_EXPR
|| DECL_FUNCTION_TEMPLATE_P (x)
@@ -1359,9 +1239,10 @@ int
really_overloaded_fn (x)
tree x;
{
- /* A baselink is also considered an overloaded function.
- This might also be an ambiguous class member. */
- if (TREE_CODE (x) == TREE_LIST)
+ /* A baselink is also considered an overloaded function. */
+ if (TREE_CODE (x) == OFFSET_REF)
+ x = TREE_OPERAND (x, 1);
+ if (BASELINK_P (x))
x = TREE_VALUE (x);
return (TREE_CODE (x) == OVERLOAD
&& (TREE_CHAIN (x) != NULL_TREE
@@ -1374,11 +1255,22 @@ get_first_fn (from)
{
my_friendly_assert (is_overloaded_fn (from), 9);
/* A baselink is also considered an overloaded function. */
- if (TREE_CODE (from) == TREE_LIST)
+ if (BASELINK_P (from))
from = TREE_VALUE (from);
return OVL_CURRENT (from);
}
+/* Returns nonzero if T is a ->* or .* expression that refers to a
+ member function. */
+
+int
+bound_pmf_p (t)
+ tree t;
+{
+ return (TREE_CODE (t) == OFFSET_REF
+ && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1))));
+}
+
/* Return a new OVL node, concatenating it with the old one. */
tree
@@ -1417,9 +1309,9 @@ build_overload (decl, chain)
tree decl;
tree chain;
{
- if (!chain)
+ if (! chain && TREE_CODE (decl) != TEMPLATE_DECL)
return decl;
- if (TREE_CODE (chain) != OVERLOAD)
+ if (chain && TREE_CODE (chain) != OVERLOAD)
chain = ovl_cons (chain, NULL_TREE);
return ovl_cons (decl, chain);
}
@@ -1518,21 +1410,26 @@ build_exception_variant (type, raises)
tree raises;
{
tree v = TYPE_MAIN_VARIANT (type);
- int constp = TYPE_READONLY (type);
- int volatilep = TYPE_VOLATILE (type);
+ int type_quals = TYPE_QUALS (type);
for (; v; v = TYPE_NEXT_VARIANT (v))
{
- if (TYPE_READONLY (v) != constp
- || TYPE_VOLATILE (v) != volatilep)
+ tree t;
+ tree u;
+
+ if (TYPE_QUALS (v) != type_quals)
continue;
- /* @@ 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.
+ for (t = TYPE_RAISES_EXCEPTIONS (v), u = raises;
+ t != NULL_TREE && u != NULL_TREE;
+ t = TREE_CHAIN (t), u = TREE_CHAIN (u))
+ if (((TREE_VALUE (t) != NULL_TREE)
+ != (TREE_VALUE (u) != NULL_TREE))
+ || !same_type_p (TREE_VALUE (t), TREE_VALUE (u)))
+ break;
- @@ Nice to free up storage used in consing up the
- @@ list of exceptions raised. */
+ if (!t && !u)
+ /* There's a memory leak here; RAISES is not freed. */
return v;
}
@@ -1540,12 +1437,7 @@ build_exception_variant (type, raises)
v = build_type_copy (type);
if (raises && ! TREE_PERMANENT (raises))
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- raises = copy_list (raises);
- pop_obstacks ();
- }
+ raises = copy_to_permanent (raises);
TYPE_RAISES_EXCEPTIONS (v) = raises;
return v;
@@ -1559,29 +1451,39 @@ copy_template_template_parm (t)
tree t;
{
tree template = TYPE_NAME (t);
- tree t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
+ tree t2;
+
+ /* Make sure these end up on the permanent_obstack. */
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
+ t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
template = copy_node (template);
copy_lang_decl (template);
+
+ pop_obstacks ();
+
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);
+ TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
+ = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t);
return t2;
}
-/* Subroutine of copy_to_permanent
-
- Assuming T is a node build bottom-up, make it all exist on
- permanent obstack, if it is not permanent already. */
+/* Walk through the tree structure T, applying func. If func ever returns
+ non-null, return that value. */
tree
-mapcar (t, func)
+search_tree (t, func)
tree t;
tree (*func) PROTO((tree));
{
+#define TRY(ARG) if (tmp=search_tree (ARG, func), tmp != NULL_TREE) return tmp
+
tree tmp;
if (t == NULL_TREE)
@@ -1593,6 +1495,259 @@ mapcar (t, func)
switch (TREE_CODE (t))
{
case ERROR_MARK:
+ break;
+
+ case IDENTIFIER_NODE:
+ break;
+
+ case VAR_DECL:
+ case FUNCTION_DECL:
+ case CONST_DECL:
+ case TEMPLATE_DECL:
+ case NAMESPACE_DECL:
+ break;
+
+ case TYPE_DECL:
+ TRY (TREE_TYPE (t));
+ break;
+
+ case PARM_DECL:
+ TRY (TREE_TYPE (t));
+ TRY (TREE_CHAIN (t));
+ break;
+
+ case TREE_LIST:
+ TRY (TREE_PURPOSE (t));
+ TRY (TREE_VALUE (t));
+ TRY (TREE_CHAIN (t));
+ break;
+
+ case OVERLOAD:
+ TRY (OVL_FUNCTION (t));
+ TRY (OVL_CHAIN (t));
+ break;
+
+ case TREE_VEC:
+ {
+ int len = TREE_VEC_LENGTH (t);
+
+ t = copy_node (t);
+ while (len--)
+ TRY (TREE_VEC_ELT (t, len));
+ }
+ break;
+
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ case DEFAULT_ARG:
+ break;
+
+ case PTRMEM_CST:
+ TRY (TREE_TYPE (t));
+ break;
+
+ case COND_EXPR:
+ case TARGET_EXPR:
+ case AGGR_INIT_EXPR:
+ case NEW_EXPR:
+ TRY (TREE_OPERAND (t, 0));
+ TRY (TREE_OPERAND (t, 1));
+ TRY (TREE_OPERAND (t, 2));
+ break;
+
+ case MODIFY_EXPR:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case TRUNC_MOD_EXPR:
+ case MIN_EXPR:
+ case MAX_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_ANDTC_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case CEIL_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case ROUND_MOD_EXPR:
+ case COMPOUND_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case ARRAY_REF:
+ case SCOPE_REF:
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
+ case CALL_EXPR:
+ TRY (TREE_OPERAND (t, 0));
+ TRY (TREE_OPERAND (t, 1));
+ break;
+
+ case SAVE_EXPR:
+ case CONVERT_EXPR:
+ case ADDR_EXPR:
+ case INDIRECT_REF:
+ case NEGATE_EXPR:
+ case BIT_NOT_EXPR:
+ case TRUTH_NOT_EXPR:
+ case NOP_EXPR:
+ case NON_LVALUE_EXPR:
+ case COMPONENT_REF:
+ case CLEANUP_POINT_EXPR:
+ case LOOKUP_EXPR:
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ TRY (TREE_OPERAND (t, 0));
+ break;
+
+ 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:
+ break;
+
+ case COMPLEX_CST:
+ TRY (TREE_REALPART (t));
+ TRY (TREE_IMAGPART (t));
+ break;
+
+ case CONSTRUCTOR:
+ TRY (CONSTRUCTOR_ELTS (t));
+ break;
+
+ case TEMPLATE_TEMPLATE_PARM:
+ case TEMPLATE_PARM_INDEX:
+ case TEMPLATE_TYPE_PARM:
+ break;
+
+ case BIND_EXPR:
+ break;
+
+ case REAL_TYPE:
+ case COMPLEX_TYPE:
+ case VOID_TYPE:
+ case BOOLEAN_TYPE:
+ case TYPENAME_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ case TYPEOF_TYPE:
+ break;
+
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ TRY (TREE_TYPE (t));
+ break;
+
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ TRY (TREE_TYPE (t));
+ TRY (TYPE_ARG_TYPES (t));
+ break;
+
+ case ARRAY_TYPE:
+ TRY (TREE_TYPE (t));
+ TRY (TYPE_DOMAIN (t));
+ break;
+
+ case INTEGER_TYPE:
+ TRY (TYPE_MAX_VALUE (t));
+ break;
+
+ case OFFSET_TYPE:
+ TRY (TREE_TYPE (t));
+ TRY (TYPE_OFFSET_BASETYPE (t));
+ break;
+
+ case RECORD_TYPE:
+ if (TYPE_PTRMEMFUNC_P (t))
+ TRY (TYPE_PTRMEMFUNC_FN_TYPE (t));
+ break;
+
+ /* This list is incomplete, but should suffice for now.
+ It is very important that `sorry' not call
+ `report_error_function'. That could cause an infinite loop. */
+ default:
+ sorry ("initializer contains unrecognized tree code");
+ return error_mark_node;
+
+ }
+
+ return NULL_TREE;
+
+#undef TRY
+}
+
+/* Passed to search_tree. Checks for the use of types with no linkage. */
+
+static tree
+no_linkage_helper (t)
+ tree t;
+{
+ if (TYPE_P (t)
+ && (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE)
+ && (decl_function_context (TYPE_MAIN_DECL (t))
+ || ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))))
+ return t;
+ return NULL_TREE;
+}
+
+/* Check if the type T depends on a type with no linkage and if so, return
+ it. */
+
+tree
+no_linkage_check (t)
+ tree t;
+{
+ t = search_tree (t, no_linkage_helper);
+ if (t != error_mark_node)
+ return t;
+ return NULL_TREE;
+}
+
+
+/* Make copies of all the nodes below T. If FUNC is non-NULL, call it
+ for each node. */
+
+tree
+mapcar (t, func)
+ tree t;
+ tree (*func) PROTO((tree));
+{
+ tree tmp;
+
+ if (t == NULL_TREE)
+ return t;
+
+ if (func)
+ {
+ tmp = func (t);
+ if (tmp)
+ return tmp;
+ }
+
+ switch (TREE_CODE (t))
+ {
+ case ERROR_MARK:
return error_mark_node;
case VAR_DECL:
@@ -1608,11 +1763,13 @@ mapcar (t, func)
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;
+ if (TREE_READONLY_DECL_P (t))
+ {
+ tmp = decl_constant_value (t);
+ if (tmp != t)
+ return mapcar (tmp, func);
+ }
+ return error_mark_node;
case PARM_DECL:
{
@@ -1659,6 +1816,12 @@ mapcar (t, func)
case STRING_CST:
return copy_node (t);
+ case PTRMEM_CST:
+ t = copy_node (t);
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
+ PTRMEM_CST_MEMBER (t) = mapcar (PTRMEM_CST_MEMBER (t), func);
+ return t;
+
case COND_EXPR:
case TARGET_EXPR:
case AGGR_INIT_EXPR:
@@ -1722,7 +1885,7 @@ mapcar (t, 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. */
+ make_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);
@@ -1739,37 +1902,39 @@ mapcar (t, func)
case NOP_EXPR:
case COMPONENT_REF:
case CLEANUP_POINT_EXPR:
+ case NON_LVALUE_EXPR:
t = copy_node (t);
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
return t;
case POINTER_TYPE:
tmp = build_pointer_type (mapcar (TREE_TYPE (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case REFERENCE_TYPE:
tmp = build_reference_type (mapcar (TREE_TYPE (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case FUNCTION_TYPE:
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));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case ARRAY_TYPE:
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));
+ return cp_build_qualified_type (tmp, CP_TYPE_QUALS (t));
case INTEGER_TYPE:
tmp = build_index_type (mapcar (TYPE_MAX_VALUE (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case OFFSET_TYPE:
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));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case METHOD_TYPE:
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));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case COMPLEX_CST:
t = copy_node (t);
@@ -1799,6 +1964,11 @@ mapcar (t, func)
TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
return t;
+ case LOOKUP_EXPR:
+ t = copy_node (t);
+ TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+ return t;
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
return build_ptrmemfunc_type
@@ -1818,6 +1988,16 @@ mapcar (t, func)
return NULL_TREE;
}
+/* Returns T if T is allocated on the permanent obstack, NULL_TREE
+ otherwise. */
+
+tree
+permanent_p (t)
+ tree t;
+{
+ return TREE_PERMANENT (t) ? t : NULL_TREE;
+}
+
static tree
perm_manip (t)
tree t;
@@ -1885,17 +2065,10 @@ print_lang_statistics ()
void
__eprintf (string, expression, line, filename)
-#ifdef __STDC__
const char *string;
const char *expression;
unsigned line;
const char *filename;
-#else
- char *string;
- char *expression;
- unsigned line;
- char *filename;
-#endif
{
fprintf (stderr, string, expression, line, filename);
fflush (stderr);
@@ -2037,7 +2210,7 @@ build_min VPROTO((enum tree_code code, tree tt, ...))
t = make_node (code);
length = tree_code_length[(int) code];
- TREE_TYPE (t) = tt;
+ TREE_TYPE (t) = copy_to_permanent (tt);
TREE_COMPLEXITY (t) = lineno;
for (i = 0; i < length; i++)
@@ -2114,7 +2287,7 @@ vec_binfo_member (elem, vec)
if (vec)
for (i = 0; i < TREE_VEC_LENGTH (vec); ++i)
- if (comptypes (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i)), 1))
+ if (same_type_p (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i))))
return TREE_VEC_ELT (vec, i);
return NULL_TREE;
@@ -2134,6 +2307,24 @@ hack_decl_function_context (decl)
return decl_function_context (decl);
}
+/* Returns the namespace that contains DECL, whether directly or
+ indirectly. */
+
+tree
+decl_namespace_context (decl)
+ tree decl;
+{
+ while (1)
+ {
+ if (TREE_CODE (decl) == NAMESPACE_DECL)
+ return decl;
+ else if (TYPE_P (decl))
+ decl = CP_DECL_CONTEXT (TYPE_MAIN_DECL (decl));
+ else
+ decl = CP_DECL_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.
@@ -2187,7 +2378,7 @@ cp_tree_equal (t1, t2)
/* 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)
+ if (!(same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
/* The first operand is RTL. */
&& TREE_OPERAND (t1, 0) == TREE_OPERAND (t2, 0)))
return 0;
@@ -2255,9 +2446,15 @@ cp_tree_equal (t1, t2)
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);
+ return same_type_p (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
break;
+ case PTRMEM_CST:
+ /* Two pointer-to-members are the same if they point to the same
+ field or function in the same class. */
+ return (PTRMEM_CST_MEMBER (t1) == PTRMEM_CST_MEMBER (t2)
+ && same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2)));
+
default:
break;
}
@@ -2284,17 +2481,17 @@ cp_tree_equal (t1, t2)
return -1;
}
-/* Similar to make_tree_vec, but build on a temporary obstack. */
+/* Similar to make_tree_vec, but build on the momentary_obstack.
+ Thus, these vectors are really and truly temporary. */
tree
make_temp_vec (len)
int len;
{
register tree node;
- register struct obstack *ambient_obstack = current_obstack;
- current_obstack = expression_obstack;
+ push_expression_obstack ();
node = make_tree_vec (len);
- current_obstack = ambient_obstack;
+ pop_obstacks ();
return node;
}
@@ -2333,7 +2530,7 @@ build_int_wrapper (i)
return t;
}
-tree
+static tree
build_srcloc (file, line)
char *file;
int line;
@@ -2378,8 +2575,7 @@ lvalue_type (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));
+ return type;
}
/* The type of ARG for printing error messages; denote lvalues with
@@ -2422,3 +2618,194 @@ member_p (decl)
tree ctx = DECL_CONTEXT (decl);
return (ctx && TREE_CODE_CLASS (TREE_CODE (ctx)) == 't');
}
+
+/* Create a placeholder for member access where we don't actually have an
+ object that the access is against. */
+
+tree
+build_dummy_object (type)
+ tree type;
+{
+ tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
+ return build_indirect_ref (decl, NULL_PTR);
+}
+
+/* We've gotten a reference to a member of TYPE. Return *this if appropriate,
+ or a dummy object otherwise. If BINFOP is non-0, it is filled with the
+ binfo path from current_class_type to TYPE, or 0. */
+
+tree
+maybe_dummy_object (type, binfop)
+ tree type;
+ tree *binfop;
+{
+ tree decl, context;
+
+ if (current_class_type
+ && get_base_distance (type, current_class_type, 0, binfop) != -1)
+ context = current_class_type;
+ else
+ {
+ /* Reference from a nested class member function. */
+ context = type;
+ if (binfop)
+ *binfop = TYPE_BINFO (type);
+ }
+
+ if (current_class_ref && context == current_class_type)
+ decl = current_class_ref;
+ else
+ decl = build_dummy_object (context);
+
+ return decl;
+}
+
+/* Returns 1 if OB is a placeholder object, or a pointer to one. */
+
+int
+is_dummy_object (ob)
+ tree ob;
+{
+ if (TREE_CODE (ob) == INDIRECT_REF)
+ ob = TREE_OPERAND (ob, 0);
+ return (TREE_CODE (ob) == NOP_EXPR
+ && TREE_OPERAND (ob, 0) == void_zero_node);
+}
+
+/* Returns 1 iff type T is a POD type, as defined in [basic.types]. */
+
+int
+pod_type_p (t)
+ tree t;
+{
+ tree f;
+
+ while (TREE_CODE (t) == ARRAY_TYPE)
+ t = TREE_TYPE (t);
+
+ if (! IS_AGGR_TYPE (t))
+ return 1;
+
+ if (CLASSTYPE_NON_AGGREGATE (t)
+ || TYPE_HAS_COMPLEX_ASSIGN_REF (t)
+ || TYPE_HAS_DESTRUCTOR (t))
+ return 0;
+
+ for (f = TYPE_FIELDS (t); f; f = TREE_CHAIN (f))
+ {
+ if (TREE_CODE (f) != FIELD_DECL)
+ continue;
+
+ if (TREE_CODE (TREE_TYPE (f)) == REFERENCE_TYPE
+ || TYPE_PTRMEMFUNC_P (TREE_TYPE (f))
+ || TYPE_PTRMEM_P (TREE_TYPE (f)))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Return a 1 if ATTR_NAME and ATTR_ARGS denote a valid C++-specific
+ attribute for either declaration DECL or type TYPE and 0 otherwise.
+ Plugged into valid_lang_attribute. */
+
+int
+cp_valid_lang_attribute (attr_name, attr_args, decl, type)
+ tree attr_name;
+ tree attr_args ATTRIBUTE_UNUSED;
+ tree decl ATTRIBUTE_UNUSED;
+ tree type ATTRIBUTE_UNUSED;
+{
+ if (is_attribute_p ("com_interface", attr_name))
+ {
+ if (! flag_vtable_thunks)
+ {
+ error ("`com_interface' only supported with -fvtable-thunks");
+ return 0;
+ }
+
+ if (attr_args != NULL_TREE
+ || decl != NULL_TREE
+ || ! CLASS_TYPE_P (type)
+ || type != TYPE_MAIN_VARIANT (type))
+ {
+ warning ("`com_interface' attribute can only be applied to class definitions");
+ return 0;
+ }
+
+ CLASSTYPE_COM_INTERFACE (type) = 1;
+ return 1;
+ }
+ else if (is_attribute_p ("init_priority", attr_name))
+ {
+ tree initp_expr = (attr_args ? TREE_VALUE (attr_args): NULL_TREE);
+ int pri;
+
+ if (initp_expr)
+ STRIP_NOPS (initp_expr);
+
+ if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
+ {
+ error ("requested init_priority is not an integer constant");
+ return 0;
+ }
+
+ pri = TREE_INT_CST_LOW (initp_expr);
+
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+
+ if (decl == NULL_TREE
+ || TREE_CODE (decl) != VAR_DECL
+ || ! TREE_STATIC (decl)
+ || DECL_EXTERNAL (decl)
+ || (TREE_CODE (type) != RECORD_TYPE
+ && TREE_CODE (type) != UNION_TYPE)
+ /* Static objects in functions are initialized the
+ first time control passes through that
+ function. This is not precise enough to pin down an
+ init_priority value, so don't allow it. */
+ || current_function_decl)
+ {
+ error ("can only use init_priority attribute on file-scope definitions of objects of class type");
+ return 0;
+ }
+
+ if (pri > MAX_INIT_PRIORITY || pri <= 0)
+ {
+ error ("requested init_priority is out of range");
+ return 0;
+ }
+
+ /* Check for init_priorities that are reserved for
+ language and runtime support implementations.*/
+ if (pri <= MAX_RESERVED_INIT_PRIORITY)
+ {
+ warning
+ ("requested init_priority is reserved for internal use");
+ }
+
+ DECL_INIT_PRIORITY (decl) = pri;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the
+ thing pointed to by the constant. */
+
+tree
+make_ptrmem_cst (type, member)
+ tree type;
+ tree member;
+{
+ tree ptrmem_cst = make_node (PTRMEM_CST);
+ /* If would seem a great convenience if make_node would set
+ TREE_CONSTANT for things of class `c', but it does not. */
+ TREE_CONSTANT (ptrmem_cst) = 1;
+ TREE_TYPE (ptrmem_cst) = type;
+ PTRMEM_CST_MEMBER (ptrmem_cst) = member;
+ return ptrmem_cst;
+}
+
diff --git a/contrib/gcc/cp/typeck.c b/contrib/gcc/cp/typeck.c
index 4e1d4fd..d0743e9 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-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -39,9 +39,7 @@ Boston, MA 02111-1307, USA. */
#include "expr.h"
#include "toplev.h"
-extern void compiler_error ();
-
-static tree convert_for_assignment PROTO((tree, tree, char*, tree,
+static tree convert_for_assignment PROTO((tree, tree, const char *, tree,
int));
static tree pointer_int_sum PROTO((enum tree_code, tree, tree));
static tree rationalize_conditional_expr PROTO((enum tree_code, tree));
@@ -51,15 +49,16 @@ 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 build_component_addr PROTO((tree, tree));
static tree qualify_type PROTO((tree, tree));
static tree get_delta_difference PROTO((tree, tree, int));
+static int comp_cv_target_types PROTO((tree, tree, int));
/* Return the target type of TYPE, which meas return T for:
T*, T&, T[], T (...), and otherwise, just T. */
@@ -80,7 +79,9 @@ target_type (type)
}
/* Do `exp = require_complete_type (exp);' to make sure exp
- does not have an incomplete type. (That includes void types.) */
+ does not have an incomplete type. (That includes void types.)
+ Returns the error_mark_node if the VALUE does not have
+ complete type when this function returns. */
tree
require_complete_type (value)
@@ -88,7 +89,7 @@ require_complete_type (value)
{
tree type;
- if (processing_template_decl)
+ if (processing_template_decl || value == error_mark_node)
return value;
if (TREE_CODE (value) == OVERLOAD)
@@ -98,7 +99,7 @@ require_complete_type (value)
/* First, detect a valid value with a complete type. */
if (TYPE_SIZE (type) != 0
- && type != void_type_node
+ && TYPE_SIZE (type) != size_zero_node
&& ! (TYPE_LANG_SPECIFIC (type)
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))
&& TYPE_SIZE (SIGNATURE_TYPE (type)) == 0))
@@ -120,13 +121,103 @@ require_complete_type (value)
return require_complete_type (value);
}
- if (TYPE_SIZE (complete_type (type)))
+ if (complete_type_or_else (type, value))
return value;
else
+ return error_mark_node;
+}
+
+/* Makes sure EXPR is a complete type when used in a void context, like a
+ whole expression, or lhs of a comma operator. Issue a diagnostic and
+ return error_mark_node on failure. This is a little tricky, because some
+ valid void types look stunningly similar to invalid void types. We err on
+ the side of caution */
+
+tree
+require_complete_type_in_void (expr)
+ tree expr;
+{
+ switch (TREE_CODE (expr))
{
- incomplete_type_error (value, type);
- return error_mark_node;
+ case COND_EXPR:
+ {
+ tree op;
+
+ op = TREE_OPERAND (expr,2);
+ op = require_complete_type_in_void (op);
+ TREE_OPERAND (expr,2) = op;
+ if (op == error_mark_node)
+ {
+ expr = op;
+ break;
+ }
+
+ /* fallthrough */
+ }
+
+ case COMPOUND_EXPR:
+ {
+ tree op;
+
+ op = TREE_OPERAND (expr,1);
+ op = require_complete_type_in_void (op);
+ TREE_OPERAND (expr,1) = op;
+ if (op == error_mark_node)
+ {
+ expr = op;
+ break;
+ }
+
+ break;
+ }
+
+ case NON_LVALUE_EXPR:
+ case NOP_EXPR:
+ {
+ tree op;
+
+ op = TREE_OPERAND (expr,0);
+ op = require_complete_type_in_void (op);
+ TREE_OPERAND (expr,0) = op;
+ if (op == error_mark_node)
+ {
+ expr = op;
+ break;
+ }
+ break;
+ }
+
+ case CALL_EXPR: /* function call return can be ignored */
+ case RTL_EXPR: /* RTL nodes have no value */
+ case DELETE_EXPR: /* delete expressions have no type */
+ case VEC_DELETE_EXPR:
+ case INTEGER_CST: /* used for null pointer */
+ case EXIT_EXPR: /* have no return */
+ case LOOP_EXPR: /* have no return */
+ case BIND_EXPR: /* have no return */
+ case THROW_EXPR: /* have no return */
+ case MODIFY_EXPR: /* sometimes this has a void type, but that's ok */
+ case CONVERT_EXPR: /* sometimes has a void type */
+ break;
+
+ case INDIRECT_REF:
+ {
+ tree op = TREE_OPERAND (expr,0);
+
+ /* Calling a function returning a reference has an implicit
+ dereference applied. We don't want to make that an error. */
+ if (TREE_CODE (op) == CALL_EXPR
+ && TREE_CODE (TREE_TYPE (op)) == REFERENCE_TYPE)
+ break;
+ /* else fallthrough */
+ }
+
+ default:
+ expr = require_complete_type (expr);
+ break;
}
+
+ return expr;
}
/* Try to complete TYPE, if it is incomplete. For example, if TYPE is
@@ -155,24 +246,28 @@ complete_type (type)
TYPE_NEEDS_DESTRUCTOR (type)
= TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
}
- else if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+ else if (CLASS_TYPE_P (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. */
+ completed. VALUE is used for informative diagnostics.
+ Returns NULL_TREE if the type cannot be made complete. */
tree
-complete_type_or_else (type)
+complete_type_or_else (type, value)
tree type;
+ tree value;
{
type = complete_type (type);
- if (type != error_mark_node && !TYPE_SIZE (type))
+ if (type == error_mark_node)
+ /* We already issued an error. */
+ return NULL_TREE;
+ else if (!TYPE_SIZE (type) || TYPE_SIZE (type) == size_zero_node)
{
- incomplete_type_error (NULL_TREE, type);
+ incomplete_type_error (value, type);
return NULL_TREE;
}
else
@@ -204,32 +299,6 @@ fntype_p (t)
|| TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)));
}
-/* 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;
-{
- if (TREE_TYPE (exp) == NULL_TREE)
- {
- error ("argument list may not have an initializer list");
- return errval;
- }
-
- 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))
- {
- exp = instantiate_type (type, exp, 1);
- if (TREE_TYPE (exp) == error_mark_node)
- return errval;
- }
- return exp;
-}
-
/* Return a variant of TYPE which has all the type qualifiers of LIKE
as well as those of TYPE. */
@@ -237,10 +306,9 @@ static tree
qualify_type (type, like)
tree type, like;
{
- int constflag = TYPE_READONLY (type) || TYPE_READONLY (like);
- int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like);
/* @@ Must do member pointers here. */
- return cp_build_type_variant (type, constflag, volflag);
+ return cp_build_qualified_type (type, (CP_TYPE_QUALS (type)
+ | CP_TYPE_QUALS (like)));
}
/* Return the common type of two parameter lists.
@@ -494,16 +562,33 @@ common_type (t1, t2)
But ANSI C++ specifies doing this with the qualifiers.
So I turned it on again. */
{
- tree tt1 = TYPE_MAIN_VARIANT (TREE_TYPE (t1));
- tree tt2 = TYPE_MAIN_VARIANT (TREE_TYPE (t2));
- int constp
- = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
- int volatilep
- = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));
+ tree tt1 = TREE_TYPE (t1);
+ tree tt2 = TREE_TYPE (t2);
+ tree b1, b2;
+ int type_quals;
tree target;
+ if (TREE_CODE (tt1) == OFFSET_TYPE)
+ {
+ b1 = TYPE_OFFSET_BASETYPE (tt1);
+ b2 = TYPE_OFFSET_BASETYPE (tt2);
+ tt1 = TREE_TYPE (tt1);
+ tt2 = TREE_TYPE (tt2);
+ }
+ else
+ b1 = b2 = NULL_TREE;
+
+ type_quals = (CP_TYPE_QUALS (tt1) | CP_TYPE_QUALS (tt2));
+ tt1 = TYPE_MAIN_VARIANT (tt1);
+ tt2 = TYPE_MAIN_VARIANT (tt2);
+
if (tt1 == tt2)
target = tt1;
+ else if (b1)
+ {
+ compiler_error ("common_type called with uncommon member types");
+ target = tt1;
+ }
else if (tt1 == void_type_node || tt2 == void_type_node)
target = void_type_node;
else if (tt1 == unknown_type_node)
@@ -513,7 +598,17 @@ common_type (t1, t2)
else
target = common_type (tt1, tt2);
- target = cp_build_type_variant (target, constp, volatilep);
+ target = cp_build_qualified_type (target, type_quals);
+
+ if (b1)
+ {
+ if (same_type_p (b1, b2)
+ || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
+ target = build_offset_type (b2, target);
+ else if (binfo_or_else (b2, b1))
+ target = build_offset_type (b1, target);
+ }
+
if (code1 == POINTER_TYPE)
t1 = build_pointer_type (target);
else
@@ -587,7 +682,10 @@ common_type (t1, t2)
else if (binfo_or_else (t2, t1))
return build_type_attribute_variant (t2, attributes);
else
- compiler_error ("common_type called with uncommon aggregate types");
+ {
+ compiler_error ("common_type called with uncommon aggregate types");
+ return error_mark_node;
+ }
case METHOD_TYPE:
if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))
@@ -600,7 +698,7 @@ common_type (t1, t2)
tree b1 = TYPE_OFFSET_BASETYPE (t1);
tree b2 = TYPE_OFFSET_BASETYPE (t2);
- if (comptypes (b1, b2, 1)
+ if (same_type_p (b1, b2)
|| (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));
else
@@ -630,18 +728,9 @@ common_type (t1, t2)
return build_type_attribute_variant (t1, attributes);
case OFFSET_TYPE:
- if (TREE_TYPE (t1) == TREE_TYPE (t2))
- {
- tree b1 = TYPE_OFFSET_BASETYPE (t1);
- tree b2 = TYPE_OFFSET_BASETYPE (t2);
-
- 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);
- }
- compiler_error ("common_type called with uncommon member types");
+ /* Pointers to members should now be handled by the POINTER_TYPE
+ case above. */
+ my_friendly_abort (990325);
default:
return build_type_attribute_variant (t1, attributes);
@@ -657,61 +746,58 @@ compexcepttypes (t1, t2)
return TYPE_RAISES_EXCEPTIONS (t1) == TYPE_RAISES_EXCEPTIONS (t2);
}
+/* Compare the array types T1 and T2, using CMP as the type comparison
+ function for the element types. STRICT is as for comptypes. */
+
static int
comp_array_types (cmp, t1, t2, strict)
register int (*cmp) PROTO((tree, tree, int));
tree t1, t2;
int strict;
{
- tree d1 = TYPE_DOMAIN (t1);
- tree d2 = TYPE_DOMAIN (t2);
+ tree d1;
+ tree d2;
+
+ if (t1 == t2)
+ return 1;
- /* Target types must match incl. qualifiers. */
+ /* The type of the array elements must be the same. */
if (!(TREE_TYPE (t1) == TREE_TYPE (t2)
- || (*cmp) (TREE_TYPE (t1), TREE_TYPE (t2), strict)))
+ || (*cmp) (TREE_TYPE (t1), TREE_TYPE (t2),
+ strict & ~COMPARE_REDECLARATION)))
return 0;
- /* Sizes must match unless one is missing or variable. */
- if (d1 == 0 || d2 == 0 || d1 == d2
- || TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
- || TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
- || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST
- || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)
+ d1 = TYPE_DOMAIN (t1);
+ d2 = TYPE_DOMAIN (t2);
+
+ if (d1 == d2)
return 1;
- return ((TREE_INT_CST_LOW (TYPE_MIN_VALUE (d1))
- == TREE_INT_CST_LOW (TYPE_MIN_VALUE (d2)))
- && (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d1))
- == TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d2)))
- && (TREE_INT_CST_LOW (TYPE_MAX_VALUE (d1))
- == TREE_INT_CST_LOW (TYPE_MAX_VALUE (d2)))
- && (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d1))
- == TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d2))));
+ /* If one of the arrays is dimensionless, and the other has a
+ dimension, they are of different types. However, it is legal to
+ write:
+
+ extern int a[];
+ int a[3];
+
+ by [basic.link]:
+
+ declarations for an array object can specify
+ array types that differ by the presence or absence of a major
+ array bound (_dcl.array_). */
+ if (!d1 || !d2)
+ return strict & COMPARE_REDECLARATION;
+
+ /* Check that the dimensions are the same. */
+ return (cp_tree_equal (TYPE_MIN_VALUE (d1),
+ TYPE_MIN_VALUE (d2))
+ && cp_tree_equal (TYPE_MAX_VALUE (d1),
+ TYPE_MAX_VALUE (d2)));
}
/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
- or various other operations. This is what ANSI C++ speaks of as
- "being the same".
-
- For C++: argument STRICT says we should be strict about this
- comparison:
-
- 2 : strict, except that if one type is a reference and
- the other is not, compare the target type of the
- reference to the type that's not a reference (ARM, p308).
- This is used for checking for invalid overloading.
- 1 : strict (compared according to ANSI C)
- This is used for checking whether two function decls match.
- 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 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. */
+ or various other operations. STRICT is a bitwise-or of the
+ COMPARE_* flags. */
int
comptypes (type1, type2, strict)
@@ -721,9 +807,18 @@ comptypes (type1, type2, strict)
register tree t1 = type1;
register tree t2 = type2;
int attrval, val;
+ int orig_strict = strict;
- /* Suppress errors caused by previously reported errors */
+ /* The special exemption for redeclaring array types without an
+ array bound only applies at the top level:
+
+ extern int (*i)[];
+ int (*i)[8];
+ is not legal, for example. */
+ strict &= ~COMPARE_REDECLARATION;
+
+ /* Suppress errors caused by previously reported errors */
if (t1 == t2)
return 1;
@@ -733,7 +828,7 @@ comptypes (type1, type2, strict)
if (t2 == error_mark_node)
return 0;
- if (strict < 0)
+ if (strict & COMPARE_RELAXED)
{
/* Treat an enum type as the unsigned integer type of the same width. */
@@ -752,30 +847,14 @@ comptypes (type1, type2, strict)
t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
/* Different classes of types can't be compatible. */
-
if (TREE_CODE (t1) != TREE_CODE (t2))
- {
- if (strict == 2
- && ((TREE_CODE (t1) == REFERENCE_TYPE)
- ^ (TREE_CODE (t2) == REFERENCE_TYPE)))
- {
- if (TREE_CODE (t1) == REFERENCE_TYPE)
- return comptypes (TREE_TYPE (t1), t2, 1);
- return comptypes (t1, TREE_TYPE (t2), 1);
- }
-
- return 0;
- }
- if (strict > 1)
- strict = 1;
+ return 0;
/* Qualifiers must match. */
-
- if (TYPE_READONLY (t1) != TYPE_READONLY (t2))
+ if (CP_TYPE_QUALS (t1) != CP_TYPE_QUALS (t2))
return 0;
- if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
- return 0;
- if (strict > 0 && TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
+ if (strict == COMPARE_STRICT
+ && TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
return 0;
/* Allow for two different type nodes which have essentially the same
@@ -791,8 +870,10 @@ comptypes (type1, type2, strict)
#define COMP_TYPE_ATTRIBUTES(t1,t2) 1
#endif
+ if (strict & COMPARE_NO_ATTRIBUTES)
+ attrval = 1;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
- if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
+ else if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
return 0;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
@@ -807,22 +888,32 @@ comptypes (type1, type2, strict)
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))
+ if (!TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t1)
+ && ! TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2))
return 1;
/* Don't check inheritance. */
- strict = 1;
+ strict = COMPARE_STRICT;
/* 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)
+ if (TYPE_TEMPLATE_INFO (t1) && TYPE_TEMPLATE_INFO (t2)
+ && (TYPE_TI_TEMPLATE (t1) == TYPE_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;
+ val = comp_template_args (TYPE_TI_ARGS (t1),
+ TYPE_TI_ARGS (t2));
+ look_hard:
+ if ((strict & COMPARE_BASE) && DERIVED_FROM_P (t1, t2))
+ {
+ val = 1;
+ break;
+ }
+ if ((strict & COMPARE_RELAXED) && DERIVED_FROM_P (t2, t1))
+ {
+ val = 1;
+ break;
+ }
+ break;
case OFFSET_TYPE:
val = (comptypes (build_pointer_type (TYPE_OFFSET_BASETYPE (t1)),
@@ -840,42 +931,21 @@ comptypes (type1, type2, strict)
but not vice-versa! */
val = (comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)
- && compparms (TYPE_ARG_TYPES (t1),
- TYPE_ARG_TYPES (t2), strict));
+ && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2)));
break;
case POINTER_TYPE:
case REFERENCE_TYPE:
t1 = TREE_TYPE (t1);
t2 = TREE_TYPE (t2);
- if (t1 == t2)
- {
- val = 1;
- break;
- }
- if (strict <= 0)
- {
- if (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE)
- {
- int rval;
- look_hard:
- rval = t1 == t2 || DERIVED_FROM_P (t1, t2);
-
- if (rval)
- {
- val = 1;
- break;
- }
- if (strict < 0)
- {
- val = DERIVED_FROM_P (t2, t1);
- break;
- }
- }
- return 0;
- }
- else
- val = comptypes (t1, t2, strict);
+ /* first, check whether the referred types match with the
+ required level of strictness */
+ val = comptypes (t1, t2, strict);
+ if (val)
+ break;
+ if (TREE_CODE (t1) == RECORD_TYPE
+ && TREE_CODE (t2) == RECORD_TYPE)
+ goto look_hard;
break;
case FUNCTION_TYPE:
@@ -884,12 +954,14 @@ comptypes (type1, type2, strict)
val = ((TREE_TYPE (t1) == TREE_TYPE (t2)
|| comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict))
- && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2), strict));
+ && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2)));
break;
case ARRAY_TYPE:
- /* Target types must match incl. qualifiers. */
- val = comp_array_types (comptypes, t1, t2, strict);
+ /* Target types must match incl. qualifiers. We use ORIG_STRICT
+ here since this is the one place where
+ COMPARE_REDECLARATION should be used. */
+ val = comp_array_types (comptypes, t1, t2, orig_strict);
break;
case TEMPLATE_TYPE_PARM:
@@ -899,7 +971,7 @@ comptypes (type1, type2, strict)
case TYPENAME_TYPE:
if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2))
return 0;
- return comptypes (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2), 1);
+ return same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2));
default:
break;
@@ -907,6 +979,32 @@ comptypes (type1, type2, strict)
return attrval == 2 && val == 1 ? 2 : val;
}
+/* Subroutine of comp_target-types. Make sure that the cv-quals change
+ only in the same direction as the target type. */
+
+static int
+comp_cv_target_types (ttl, ttr, nptrs)
+ tree ttl, ttr;
+ int nptrs;
+{
+ int t;
+
+ if (!at_least_as_qualified_p (ttl, ttr)
+ && !at_least_as_qualified_p (ttr, ttl))
+ /* The qualifications are incomparable. */
+ return 0;
+
+ if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr))
+ return more_qualified_p (ttr, ttl) ? -1 : 1;
+
+ t = comp_target_types (ttl, ttr, nptrs);
+ if ((t == 1 && at_least_as_qualified_p (ttl, ttr))
+ || (t == -1 && at_least_as_qualified_p (ttr, ttl)))
+ return t;
+
+ return 0;
+}
+
/* 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
@@ -926,21 +1024,26 @@ comp_target_types (ttl, ttr, nptrs)
{
ttl = TYPE_MAIN_VARIANT (ttl);
ttr = TYPE_MAIN_VARIANT (ttr);
- if (ttl == ttr)
+ if (same_type_p (ttl, ttr))
return 1;
if (TREE_CODE (ttr) != TREE_CODE (ttl))
return 0;
- if (TREE_CODE (ttr) == POINTER_TYPE
- || (TREE_CODE (ttr) == REFERENCE_TYPE))
+ if ((TREE_CODE (ttr) == POINTER_TYPE
+ || TREE_CODE (ttr) == REFERENCE_TYPE)
+ /* If we get a pointer with nptrs == 0, we don't allow any tweaking
+ of the type pointed to. This is necessary for reference init
+ semantics. We won't get here from a previous call with nptrs == 1;
+ for multi-level pointers we end up in comp_ptr_ttypes. */
+ && nptrs > 0)
{
int is_ptr = TREE_CODE (ttr) == POINTER_TYPE;
ttl = TREE_TYPE (ttl);
ttr = TREE_TYPE (ttr);
- if (nptrs > 0 && is_ptr)
+ if (is_ptr)
{
if (TREE_CODE (ttl) == UNKNOWN_TYPE
|| TREE_CODE (ttr) == UNKNOWN_TYPE)
@@ -971,29 +1074,11 @@ comp_target_types (ttl, ttr, nptrs)
if (TREE_CODE (ttl) == FUNCTION_TYPE || TREE_CODE (ttl) == METHOD_TYPE)
return comp_target_types (ttl, ttr, nptrs - 1);
- /* Make sure that the cv-quals change only in the same direction as
- the target type. */
- {
- int t;
- int c = TYPE_READONLY (ttl) - TYPE_READONLY (ttr);
- int v = TYPE_VOLATILE (ttl) - TYPE_VOLATILE (ttr);
-
- if ((c > 0 && v < 0) || (c < 0 && v > 0))
- return 0;
-
- if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr))
- return (c + v < 0) ? -1 : 1;
-
- t = comp_target_types (ttl, ttr, nptrs - 1);
- if ((t == 1 && c + v >= 0) || (t == -1 && c + v <= 0))
- return t;
-
- return 0;
- }
+ return comp_cv_target_types (ttl, ttr, nptrs - 1);
}
if (TREE_CODE (ttr) == ARRAY_TYPE)
- return comp_array_types (comp_target_types, ttl, ttr, 0);
+ return comp_array_types (comp_target_types, ttl, ttr, COMPARE_STRICT);
else if (TREE_CODE (ttr) == FUNCTION_TYPE || TREE_CODE (ttr) == METHOD_TYPE)
{
tree argsl, argsr;
@@ -1001,7 +1086,7 @@ comp_target_types (ttl, ttr, nptrs)
if (pedantic)
{
- if (comptypes (TREE_TYPE (ttl), TREE_TYPE (ttr), 1) == 0)
+ if (!same_type_p (TREE_TYPE (ttl), TREE_TYPE (ttr)))
return 0;
}
else
@@ -1024,9 +1109,9 @@ comp_target_types (ttl, ttr, nptrs)
tree tl = TYPE_METHOD_BASETYPE (ttl);
tree tr = TYPE_METHOD_BASETYPE (ttr);
- if (comptypes (tr, tl, 0) == 0)
+ if (!same_or_base_type_p (tr, tl))
{
- if (comptypes (tl, tr, 0))
+ if (same_or_base_type_p (tl, tr))
saw_contra = 1;
else
return 0;
@@ -1049,24 +1134,51 @@ comp_target_types (ttl, ttr, nptrs)
/* for C++ */
else if (TREE_CODE (ttr) == OFFSET_TYPE)
{
+ int base;
+
/* 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))
- return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs);
- else if (comptypes (TYPE_OFFSET_BASETYPE (ttl),
- TYPE_OFFSET_BASETYPE (ttr), 0)
- && comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))
- return -1;
+ if (same_or_base_type_p (TYPE_OFFSET_BASETYPE (ttr),
+ TYPE_OFFSET_BASETYPE (ttl)))
+ base = 1;
+ else if (same_or_base_type_p (TYPE_OFFSET_BASETYPE (ttl),
+ TYPE_OFFSET_BASETYPE (ttr)))
+ {
+ tree tmp = ttl;
+ ttl = ttr;
+ ttr = tmp;
+ base = -1;
+ }
+ else
+ return 0;
+
+ ttl = TREE_TYPE (ttl);
+ ttr = TREE_TYPE (ttr);
+
+ if (TREE_CODE (ttl) == POINTER_TYPE
+ || TREE_CODE (ttl) == ARRAY_TYPE)
+ {
+ if (comp_ptr_ttypes (ttl, ttr))
+ return base;
+ return 0;
+ }
+ else
+ {
+ if (comp_cv_target_types (ttl, ttr, nptrs) == 1)
+ return base;
+ return 0;
+ }
}
else if (IS_AGGR_TYPE (ttl))
{
if (nptrs < 0)
return 0;
- if (comptypes (build_pointer_type (ttl), build_pointer_type (ttr), 0))
+ if (same_or_base_type_p (build_pointer_type (ttl),
+ build_pointer_type (ttr)))
return 1;
- if (comptypes (build_pointer_type (ttr), build_pointer_type (ttl), 0))
+ if (same_or_base_type_p (build_pointer_type (ttr),
+ build_pointer_type (ttl)))
return -1;
return 0;
}
@@ -1074,6 +1186,29 @@ comp_target_types (ttl, ttr, nptrs)
return 0;
}
+/* Returns 1 if TYPE1 is at least as qualified as TYPE2. */
+
+int
+at_least_as_qualified_p (type1, type2)
+ tree type1;
+ tree type2;
+{
+ /* All qualifiers for TYPE2 must also appear in TYPE1. */
+ return ((CP_TYPE_QUALS (type1) & CP_TYPE_QUALS (type2))
+ == CP_TYPE_QUALS (type2));
+}
+
+/* Returns 1 if TYPE1 is more qualified than TYPE2. */
+
+int
+more_qualified_p (type1, type2)
+ tree type1;
+ tree type2;
+{
+ return (CP_TYPE_QUALS (type1) != CP_TYPE_QUALS (type2)
+ && at_least_as_qualified_p (type1, type2));
+}
+
/* Returns 1 if TYPE1 is more cv-qualified than TYPE2, -1 if TYPE2 is
more cv-qualified that TYPE1, and 0 otherwise. */
@@ -1082,16 +1217,13 @@ comp_cv_qualification (type1, type2)
tree type1;
tree type2;
{
- if (TYPE_READONLY (type1) == TYPE_READONLY (type2)
- && TYPE_VOLATILE (type1) == TYPE_VOLATILE (type2))
+ if (CP_TYPE_QUALS (type1) == CP_TYPE_QUALS (type2))
return 0;
- if (TYPE_READONLY (type1) >= TYPE_READONLY (type2)
- && TYPE_VOLATILE (type1) >= TYPE_VOLATILE (type2))
+ if (at_least_as_qualified_p (type1, type2))
return 1;
- if (TYPE_READONLY (type2) >= TYPE_READONLY (type1)
- && TYPE_VOLATILE (type2) >= TYPE_VOLATILE (type1))
+ else if (at_least_as_qualified_p (type2, type1))
return -1;
return 0;
@@ -1168,20 +1300,16 @@ common_base_type (tt1, tt2)
/* Subroutines of `comptypes'. */
-/* Return 1 if two parameter type lists PARMS1 and PARMS2
- are equivalent in the sense that functions with those parameter types
- can have equivalent types.
- If either list is empty, we win.
- Otherwise, the two lists must be equivalent, element by element.
+/* Return 1 if two parameter type lists PARMS1 and PARMS2 are
+ equivalent in the sense that functions with those parameter types
+ can have equivalent types. The two lists must be equivalent,
+ element by element.
- C++: See comment above about TYPE1, TYPE2.
-
- STRICT is no longer used. */
+ C++: See comment above about TYPE1, TYPE2. */
int
-compparms (parms1, parms2, strict)
+compparms (parms1, parms2)
tree parms1, parms2;
- int strict;
{
register tree t1 = parms1, t2 = parms2;
@@ -1196,7 +1324,7 @@ compparms (parms1, parms2, strict)
they fail to match. */
if (t1 == 0 || t2 == 0)
return 0;
- if (! comptypes (TREE_VALUE (t2), TREE_VALUE (t1), 1))
+ if (!same_type_p (TREE_VALUE (t2), TREE_VALUE (t1)))
return 0;
t1 = TREE_CHAIN (t1);
@@ -1227,8 +1355,13 @@ comp_target_parms (parms1, parms2, strict)
if (t1 == 0 && t2 != 0)
{
- cp_pedwarn ("ANSI C++ prohibits conversion from `(%#T)' to `(...)'",
- parms2);
+ if (! flag_strict_prototype && t2 == void_list_node)
+ /* t1 might be the arglist of a function pointer in extern "C"
+ declared to take (), which we fudged to (...). Don't make the
+ user pay for our mistake. */;
+ else
+ cp_pedwarn ("ANSI C++ prohibits conversion from `%#T' to `(...)'",
+ parms2);
return self_promoting_args_p (t2);
}
if (t2 == 0)
@@ -1250,7 +1383,7 @@ comp_target_parms (parms1, parms2, strict)
}
p1 = TREE_VALUE (t1);
p2 = TREE_VALUE (t2);
- if (comptypes (p1, p2, 1))
+ if (same_type_p (p1, p2))
continue;
if (pedantic)
@@ -1274,12 +1407,10 @@ comp_target_parms (parms1, parms2, strict)
warn_contravariance = 1;
continue;
}
- if (IS_AGGR_TYPE (TREE_TYPE (p1)))
- {
- if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (p1)),
- TYPE_MAIN_VARIANT (TREE_TYPE (p2)), 1) == 0)
- return 0;
- }
+ if (IS_AGGR_TYPE (TREE_TYPE (p1))
+ && !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (p1)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (p2))))
+ return 0;
}
/* Note backwards order due to contravariance. */
if (comp_target_types (p2, p1, 1) <= 0)
@@ -1342,8 +1473,10 @@ unsigned_type (type)
return long_unsigned_type_node;
if (type1 == long_long_integer_type_node)
return long_long_unsigned_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
if (type1 == intTI_type_node)
return unsigned_intTI_type_node;
+#endif
if (type1 == intDI_type_node)
return unsigned_intDI_type_node;
if (type1 == intSI_type_node)
@@ -1373,8 +1506,10 @@ signed_type (type)
return long_integer_type_node;
if (type1 == long_long_unsigned_type_node)
return long_long_integer_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
if (type1 == unsigned_intTI_type_node)
return intTI_type_node;
+#endif
if (type1 == unsigned_intDI_type_node)
return intDI_type_node;
if (type1 == unsigned_intSI_type_node)
@@ -1493,7 +1628,7 @@ expr_sizeof (e)
return build_min (SIZEOF_EXPR, sizetype, e);
if (TREE_CODE (e) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (e, 1)))
+ && DECL_C_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
@@ -1503,15 +1638,17 @@ expr_sizeof (e)
&& (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)
+ else if (is_overloaded_fn (e))
{
- 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");
+ pedwarn ("ANSI C++ forbids taking the sizeof a function type");
+ return size_int (1);
}
+ else if (type_unknown_p (e))
+ {
+ incomplete_type_error (e, TREE_TYPE (e));
+ return size_int (1);
+ }
+
return c_sizeof (TREE_TYPE (e));
}
@@ -1577,34 +1714,24 @@ c_alignof (type)
return t;
}
-/* Perform default promotions for C data used in expressions.
- Arrays and functions are converted to pointers;
- enumeral types or short or char, to int.
- In addition, manifest constants symbols are replaced by their values.
+/* Perform the array-to-pointer and function-to-pointer conversions
+ for EXP.
- C++: this will automatically bash references to their target type. */
+ In addition, references are converted to rvalues and manifest
+ constants are replaced by their values. */
tree
decay_conversion (exp)
tree exp;
{
- register tree type = TREE_TYPE (exp);
- register enum tree_code code = TREE_CODE (type);
-
- if (code == OFFSET_TYPE)
- {
- if (TREE_CODE (exp) == OFFSET_REF)
- return decay_conversion (resolve_offset_ref (exp));
+ register tree type;
+ register enum tree_code code;
- type = TREE_TYPE (type);
- code = TREE_CODE (type);
+ if (TREE_CODE (exp) == OFFSET_REF)
+ exp = resolve_offset_ref (exp);
- if (type == unknown_type_node)
- {
- cp_pedwarn ("assuming & on overloaded member function");
- return build_unary_op (ADDR_EXPR, exp, 0);
- }
- }
+ type = TREE_TYPE (exp);
+ code = TREE_CODE (type);
if (code == REFERENCE_TYPE)
{
@@ -1616,8 +1743,15 @@ decay_conversion (exp)
/* Constants can be used directly unless they're not loadable. */
if (TREE_CODE (exp) == CONST_DECL)
exp = DECL_INITIAL (exp);
- /* Replace a nonvolatile const static variable with its value. */
- else if (TREE_READONLY_DECL_P (exp))
+ /* Replace a nonvolatile const static variable with its value. We
+ don't do this for arrays, though; we want the address of the
+ first element of the array, not the address of the first element
+ of its initializing constant. We *do* replace variables that the
+ user isn't really supposed to know about; this is a hack to deal
+ with __PRETTY_FUNCTION__ and the like. */
+ else if (TREE_READONLY_DECL_P (exp)
+ && (code != ARRAY_TYPE
+ || (TREE_CODE (exp) == VAR_DECL && DECL_IGNORED_P (exp))))
{
exp = decl_constant_value (exp);
type = TREE_TYPE (exp);
@@ -1631,21 +1765,14 @@ decay_conversion (exp)
error ("void value not ignored as it ought to be");
return error_mark_node;
}
- if (code == FUNCTION_TYPE)
- {
- return build_unary_op (ADDR_EXPR, exp, 0);
- }
if (code == METHOD_TYPE)
- {
- cp_pedwarn ("assuming & on `%E'", exp);
- return build_unary_op (ADDR_EXPR, exp, 0);
- }
+ my_friendly_abort (990506);
+ if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
+ return build_unary_op (ADDR_EXPR, exp, 0);
if (code == ARRAY_TYPE)
{
register tree adr;
- tree restype;
tree ptrtype;
- int constp, volatilep;
if (TREE_CODE (exp) == INDIRECT_REF)
{
@@ -1677,21 +1804,7 @@ decay_conversion (exp)
return error_mark_node;
}
- constp = volatilep = 0;
- if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r'
- || TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
- {
- constp = TREE_READONLY (exp);
- volatilep = TREE_THIS_VOLATILE (exp);
- }
-
- restype = TREE_TYPE (type);
- if (TYPE_READONLY (type) || TYPE_VOLATILE (type)
- || constp || volatilep)
- restype = cp_build_type_variant (restype,
- TYPE_READONLY (type) || constp,
- TYPE_VOLATILE (type) || volatilep);
- ptrtype = build_pointer_type (restype);
+ ptrtype = build_pointer_type (TREE_TYPE (type));
if (TREE_CODE (exp) == VAR_DECL)
{
@@ -1745,12 +1858,52 @@ inline_conversion (exp)
tree exp;
{
if (TREE_CODE (exp) == FUNCTION_DECL)
+ exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
+
+ return exp;
+}
+
+/* Returns nonzero iff exp is a STRING_CST or the result of applying
+ decay_conversion to one. */
+
+int
+string_conv_p (totype, exp, warn)
+ tree totype, exp;
+ int warn;
+{
+ tree t;
+
+ if (! flag_const_strings || TREE_CODE (totype) != POINTER_TYPE)
+ return 0;
+
+ t = TREE_TYPE (totype);
+ if (!same_type_p (t, char_type_node)
+ && !same_type_p (t, wchar_type_node))
+ return 0;
+
+ if (TREE_CODE (exp) == STRING_CST)
{
- tree type = build_type_variant
- (TREE_TYPE (exp), TREE_READONLY (exp), TREE_THIS_VOLATILE (exp));
- exp = build1 (ADDR_EXPR, build_pointer_type (type), exp);
+ /* Make sure that we don't try to convert between char and wchar_t. */
+ if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (exp))), t))
+ return 0;
}
- return exp;
+ else
+ {
+ /* Is this a string constant which has decayed to 'const char *'? */
+ t = build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST));
+ if (!same_type_p (TREE_TYPE (exp), t))
+ return 0;
+ STRIP_NOPS (exp);
+ if (TREE_CODE (exp) != ADDR_EXPR
+ || TREE_CODE (TREE_OPERAND (exp, 0)) != STRING_CST)
+ return 0;
+ }
+
+ /* This warning is not very useful, as it complains about printf. */
+ if (warn && warn_write_strings)
+ cp_warning ("deprecated conversion from string constant to `%T'", totype);
+
+ return 1;
}
tree
@@ -1877,14 +2030,23 @@ build_component_ref (datum, component, basetype_path, protect)
tree datum, component, basetype_path;
int protect;
{
- register tree basetype = TREE_TYPE (datum);
+ register tree basetype;
register enum tree_code code;
register tree field = NULL;
register tree ref;
+ tree field_type;
+ int type_quals;
if (processing_template_decl)
return build_min_nt (COMPONENT_REF, datum, component);
+
+ if (datum == error_mark_node
+ || TREE_TYPE (datum) == error_mark_node)
+ return error_mark_node;
+ /* BASETYPE holds the type of the class containing the COMPONENT. */
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
+
/* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference
inside it. */
switch (TREE_CODE (datum))
@@ -1918,13 +2080,13 @@ build_component_ref (datum, component, basetype_path, protect)
if (code == REFERENCE_TYPE)
{
datum = convert_from_reference (datum);
- basetype = TREE_TYPE (datum);
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
code = TREE_CODE (basetype);
}
if (TREE_CODE (datum) == OFFSET_REF)
{
datum = resolve_offset_ref (datum);
- basetype = TREE_TYPE (datum);
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
code = TREE_CODE (basetype);
}
@@ -1948,7 +2110,7 @@ build_component_ref (datum, component, basetype_path, protect)
return error_mark_node;
}
- if (!complete_type_or_else (basetype))
+ if (!complete_type_or_else (basetype, datum))
return error_mark_node;
if (TREE_CODE (component) == BIT_NOT_EXPR)
@@ -1978,8 +2140,8 @@ build_component_ref (datum, component, basetype_path, protect)
field = component;
else if (TREE_CODE (component) == TYPE_DECL)
{
- cp_pedwarn ("invalid use of type decl `%#D' as expression", component);
- return component;
+ cp_error ("invalid use of type decl `%#D' as expression", component);
+ return error_mark_node;
}
else
{
@@ -2003,58 +2165,35 @@ build_component_ref (datum, component, basetype_path, protect)
return error_mark_node;
if (fndecls)
{
+ /* If the function is unique and static, we can resolve it
+ now. Otherwise, we have to wait and see what context it is
+ used in; a component_ref involving a non-static member
+ function can only be used in a call (expr.ref). */
+
if (TREE_CHAIN (fndecls) == NULL_TREE
- && TREE_CODE (TREE_VALUE (fndecls)) != OVERLOAD)
+ && TREE_CODE (TREE_VALUE (fndecls)) == FUNCTION_DECL)
{
- 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_node)
+ if (DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls)))
{
- if (DECL_VINDEX (fndecl)
- && ! resolves_to_fixed_type_p (datum, 0))
- {
- tree addr = build_unary_op (ADDR_EXPR, datum, 0);
- 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));
- /* 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;
- }
- else
- mark_used (fndecl);
- return build (OFFSET_REF, TREE_TYPE (fndecl),
- datum, fndecl);
+ tree fndecl = TREE_VALUE (fndecls);
+ enforce_access (TREE_PURPOSE (fndecls), fndecl);
+ mark_used (fndecl);
+ return fndecl;
}
- if (access == access_protected_node)
- cp_error ("member function `%D' is protected", fndecl);
else
- cp_error ("member function `%D' is private", fndecl);
- return error_mark_node;
- }
- else
- {
- /* Just act like build_offset_ref, since the object does
- not matter unless we're actually calling the function. */
- tree t;
-
- t = build_tree_list (error_mark_node, fndecls);
- TREE_TYPE (t) = build_offset_type (basetype,
- unknown_type_node);
- return t;
+ {
+ /* A unique non-static member function. Other parts
+ of the compiler expect something with
+ unknown_type_node to be really overloaded, so
+ let's oblige. */
+ TREE_VALUE (fndecls)
+ = scratch_ovl_cons (TREE_VALUE (fndecls), NULL_TREE);
+ }
}
+
+ ref = build (COMPONENT_REF, unknown_type_node,
+ datum, TREE_VALUE (fndecls));
+ return ref;
}
cp_error ("`%#T' has no member named `%D'", basetype, name);
@@ -2081,7 +2220,7 @@ build_component_ref (datum, component, basetype_path, protect)
{
tree context = DECL_FIELD_CONTEXT (field);
tree base = context;
- while (!comptypes (base, basetype,1) && TYPE_NAME (base)
+ while (!same_type_p (base, basetype) && TYPE_NAME (base)
&& ANON_UNION_TYPE_P (base))
{
base = TYPE_CONTEXT (base);
@@ -2121,15 +2260,38 @@ build_component_ref (datum, component, basetype_path, protect)
}
}
- ref = fold (build (COMPONENT_REF, TREE_TYPE (field),
+ /* Compute the type of the field, as described in [expr.ref]. */
+ type_quals = TYPE_UNQUALIFIED;
+ field_type = TREE_TYPE (field);
+ if (TREE_CODE (field_type) == REFERENCE_TYPE)
+ /* The standard says that the type of the result should be the
+ type referred to by the reference. But for now, at least, we
+ do the conversion from reference type later. */
+ ;
+ else
+ {
+ type_quals = (CP_TYPE_QUALS (field_type)
+ | CP_TYPE_QUALS (TREE_TYPE (datum)));
+
+ /* A field is const (volatile) if the enclosing object, or the
+ field itself, is const (volatile). But, a mutable field is
+ not const, even within a const object. */
+ if (DECL_LANG_SPECIFIC (field) && DECL_MUTABLE_P (field))
+ type_quals &= ~TYPE_QUAL_CONST;
+ if (!IS_SIGNATURE (field_type))
+ field_type = cp_build_qualified_type (field_type, type_quals);
+ }
+
+ ref = fold (build (COMPONENT_REF, field_type,
break_out_cleanups (datum), field));
- if (TREE_READONLY (datum) || TREE_READONLY (field))
+ /* Mark the expression const or volatile, as appropriate. Even
+ though we've dealt with the type above, we still have to mark the
+ expression itself. */
+ if (type_quals & TYPE_QUAL_CONST)
TREE_READONLY (ref) = 1;
- if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
+ else if (type_quals & TYPE_QUAL_VOLATILE)
TREE_THIS_VOLATILE (ref) = 1;
- if (DECL_LANG_SPECIFIC (field) && DECL_MUTABLE_P (field))
- TREE_READONLY (ref) = 0;
return ref;
}
@@ -2160,7 +2322,7 @@ build_x_component_ref (datum, component, basetype_path, protect)
tree
build_x_indirect_ref (ptr, errorstring)
tree ptr;
- char *errorstring;
+ const char *errorstring;
{
tree rval;
@@ -2177,52 +2339,57 @@ build_x_indirect_ref (ptr, errorstring)
tree
build_indirect_ref (ptr, errorstring)
tree ptr;
- char *errorstring;
+ const char *errorstring;
{
register tree pointer, type;
if (ptr == error_mark_node)
return error_mark_node;
+ if (ptr == current_class_ptr)
+ return current_class_ref;
+
pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
? ptr : default_conversion (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 (TYPE_PTR_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
{
+ /* [expr.unary.op]
+
+ If the type of the expression is "pointer to T," the type
+ of the result is "T."
+
+ We must use the canonical variant because certain parts of
+ the back end, like fold, do pointer comparisons between
+ types. */
+ tree t = canonical_type_variant (TREE_TYPE (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))
- == TYPE_READONLY (TREE_TYPE (type)))
- && (TREE_THIS_VOLATILE (TREE_OPERAND (pointer, 0))
- == TYPE_VOLATILE (TREE_TYPE (type))))
+ && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))
+ /* The POINTER was something like `&x'. We simplify `*&x' to
+ `x'. */
return TREE_OPERAND (pointer, 0);
else
{
- tree t = TREE_TYPE (type);
- register tree ref = build1 (INDIRECT_REF,
- TYPE_MAIN_VARIANT (t), pointer);
+ tree ref = build1 (INDIRECT_REF, 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_READONLY (ref) = CP_TYPE_CONST_P (t);
+ TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
TREE_SIDE_EFFECTS (ref)
- = (TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer)
+ = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer)
|| flag_volatile);
- TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
return ref;
}
}
/* `pointer' won't be an error_mark_node if we were given a
pointer to member, so it's cool to check for this here. */
- else if (TYPE_PTRMEMFUNC_P (type))
- error ("invalid use of `%s' on pointer to member function", errorstring);
+ else if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
+ error ("invalid use of `%s' on pointer to member", errorstring);
else if (TREE_CODE (type) == RECORD_TYPE
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type)))
error ("cannot dereference signature pointer/reference");
@@ -2326,23 +2493,16 @@ build_array_ref (array, idx)
warning ("subscripting array declared `register'");
}
- type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
+ type = TREE_TYPE (TREE_TYPE (array));
rval = build (ARRAY_REF, type, array, idx);
/* Array ref is const/volatile if the array elements are
or if the array is.. */
TREE_READONLY (rval)
- |= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))
- | TREE_READONLY (array));
+ |= (CP_TYPE_CONST_P (type) | TREE_READONLY (array));
TREE_SIDE_EFFECTS (rval)
- |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
- | TREE_SIDE_EFFECTS (array));
+ |= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
TREE_THIS_VOLATILE (rval)
- |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
- /* This was added by rms on 16 Nov 91.
- It fixes vol struct foo *a; a->elts[1]
- in an inline function.
- Hope it doesn't break something else. */
- | TREE_THIS_VOLATILE (array));
+ |= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
return require_complete_type (fold (rval));
}
@@ -2444,21 +2604,25 @@ build_x_function_call (function, params, decl)
TYPE_BINFO (type), LOOKUP_NORMAL);
}
+ 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),
+ template_id
+ ? template_id : DECL_NAME (function),
+ params);
+
is_method = ((TREE_CODE (function) == TREE_LIST
&& current_class_type != NULL_TREE
&& (IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function))
== function))
+ || (TREE_CODE (function) == OVERLOAD
+ && DECL_FUNCTION_MEMBER_P (OVL_CURRENT (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);
@@ -2468,6 +2632,9 @@ build_x_function_call (function, params, decl)
{
tree basetype = NULL_TREE;
+ if (TREE_CODE (function) == OVERLOAD)
+ function = OVL_CURRENT (function);
+
if (TREE_CODE (function) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (function))
{
@@ -2519,14 +2686,11 @@ build_x_function_call (function, params, decl)
{
if (current_class_type == NULL_TREE)
{
- error ("object missing in call to method `%s'",
- IDENTIFIER_POINTER (function));
+ cp_error ("object missing in call to method `%D'", function);
return error_mark_node;
}
/* Yow: call from a static member function. */
- decl = build1 (NOP_EXPR, build_pointer_type (current_class_type),
- error_mark_node);
- decl = build_indirect_ref (decl, NULL_PTR);
+ decl = build_dummy_object (current_class_type);
}
/* Put back explicit template arguments, if any. */
@@ -2538,12 +2702,17 @@ build_x_function_call (function, params, decl)
else if (TREE_CODE (function) == COMPONENT_REF
&& type == unknown_type_node)
{
- /* 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. */
- function = DECL_NAME (TREE_VALUE (TREE_OPERAND (function, 1)));
- else
- function = TREE_PURPOSE (TREE_OPERAND (function, 1));
+ /* Undo what we did in build_component_ref. */
+ decl = TREE_OPERAND (function, 0);
+ function = TREE_OPERAND (function, 1);
+ function = DECL_NAME (OVL_CURRENT (function));
+
+ if (template_id)
+ {
+ TREE_OPERAND (template_id, 0) = function;
+ function = template_id;
+ }
+
return build_method_call (decl, function, params,
NULL_TREE, LOOKUP_NORMAL);
}
@@ -2666,7 +2835,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
tree fntype, idx, e1, delta, delta2, e2, e3, aref, vtbl;
- tree instance;
+ tree instance, basetype;
tree instance_ptr = *instance_ptrptr;
@@ -2677,61 +2846,76 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
function = save_expr (function);
fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
+ basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
- /* 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. */
- instance
- = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
- instance_ptr);
- 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, cp_convert (ptrdiff_type_node, delta2));
- vtbl = build_indirect_ref (vtbl, NULL_PTR);
- aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
- idx,
- integer_one_node, 1));
- if (! flag_vtable_thunks)
- {
- aref = save_expr (aref);
-
- delta = build_binary_op
+ e3 = PFN_FROM_PTRMEMFUNC (function);
+
+ if (TYPE_SIZE (basetype) != NULL_TREE
+ && ! TYPE_VIRTUAL_P (basetype))
+ /* If basetype doesn't have virtual functions, don't emit code to
+ handle that case. */
+ e1 = e3;
+ else
+ {
+ /* 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 (GE_EXPR, idx, integer_zero_node);
+
+ /* Convert down to the right base, before using the instance. */
+ instance = convert_pointer_to_real (basetype, instance_ptr);
+ if (instance == error_mark_node && instance_ptr != error_mark_node)
+ return instance;
+
+ vtbl = convert_pointer_to (ptr_type_node, instance);
+ delta2 = DELTA2_FROM_PTRMEMFUNC (function);
+ vtbl = build
(PLUS_EXPR,
- build_conditional_expr (e1, build_component_ref (aref,
+ build_pointer_type (build_pointer_type (vtable_entry_type)),
+ vtbl, cp_convert (ptrdiff_type_node, delta2));
+ vtbl = build_indirect_ref (vtbl, NULL_PTR);
+ aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
+ idx,
+ integer_one_node));
+ if (! flag_vtable_thunks)
+ {
+ aref = save_expr (aref);
+
+ delta = build_binary_op
+ (PLUS_EXPR,
+ build_conditional_expr (e1,
+ build_component_ref (aref,
delta_identifier,
NULL_TREE, 0),
- integer_zero_node),
- delta, 1);
+ integer_zero_node),
+ delta);
+ }
+
+ if (flag_vtable_thunks)
+ e2 = aref;
+ else
+ e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
+ TREE_TYPE (e2) = TREE_TYPE (e3);
+ e1 = build_conditional_expr (e1, e2, e3);
+
+ /* Make sure this doesn't get evaluated first inside one of the
+ branches of the COND_EXPR. */
+ if (TREE_CODE (instance_ptr) == SAVE_EXPR)
+ e1 = build (COMPOUND_EXPR, TREE_TYPE (e1),
+ instance_ptr, e1);
}
*instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
instance_ptr, delta);
- if (flag_vtable_thunks)
- e2 = aref;
- else
- e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
-
- e3 = PFN_FROM_PTRMEMFUNC (function);
- TREE_TYPE (e2) = TREE_TYPE (e3);
- e1 = build_conditional_expr (e1, e2, e3);
if (instance_ptr == error_mark_node
&& TREE_CODE (e1) != ADDR_EXPR
@@ -2739,12 +2923,6 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
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. */
- if (TREE_CODE (instance_ptr) == SAVE_EXPR)
- function = build (COMPOUND_EXPR, TREE_TYPE (function),
- instance_ptr, function);
}
return function;
}
@@ -2829,10 +3007,10 @@ build_function_call_real (function, params, require_complete, flags)
function prototype, or apply default promotions. */
if (flags & LOOKUP_COMPLAIN)
- coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
+ coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
params, fndecl, LOOKUP_NORMAL);
else
- coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
+ coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
params, fndecl, 0);
if (coerced_params == error_mark_node)
@@ -2876,7 +3054,7 @@ build_function_call_real (function, params, require_complete, flags)
if (require_complete)
{
- if (value_type == void_type_node)
+ if (TREE_CODE (value_type) == VOID_TYPE)
return result;
result = require_complete_type (result);
}
@@ -2898,12 +3076,6 @@ build_function_call (function, params)
If parmdecls is exhausted, or when an element has NULL as its type,
perform the default conversions.
- RETURN_LOC is the location of the return value, if known, NULL_TREE
- otherwise. This is useful in the case where we can avoid creating
- a temporary variable in the case where we can initialize the return
- value directly. If we are not eliding constructors, then we set this
- to NULL_TREE to avoid this avoidance.
-
NAME is an IDENTIFIER_NODE or 0. It is used only for error messages.
This is also where warnings about wrong number of args are generated.
@@ -2917,18 +3089,15 @@ build_function_call (function, params)
default arguments, if such were specified. Do so here. */
tree
-convert_arguments (return_loc, typelist, values, fndecl, flags)
- tree return_loc, typelist, values, fndecl;
+convert_arguments (typelist, values, fndecl, flags)
+ tree typelist, values, fndecl;
int flags;
{
register tree typetail, valtail;
register tree result = NULL_TREE;
- char *called_thing = 0;
+ const char *called_thing = 0;
int i = 0;
- if (! flag_elide_constructors)
- return_loc = 0;
-
/* Argument passing is always copy-initialization. */
flags |= LOOKUP_ONLYCONVERTING;
@@ -2960,7 +3129,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
{
if (fndecl)
{
- cp_error_at ("too many arguments to %s `%+D'", called_thing,
+ cp_error_at ("too many arguments to %s `%+#D'", called_thing,
fndecl);
error ("at this point in file");
}
@@ -2973,31 +3142,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
break;
}
- /* The tree type of the parameter being passed may not yet be
- known. In this case, its type is TYPE_UNKNOWN, and will
- be instantiated by the type given by TYPE. If TYPE
- is also NULL, the tree type of VAL is ERROR_MARK_NODE. */
- if (type && type_unknown_p (val))
- val = require_instantiated_type (type, val, integer_zero_node);
- else if (type_unknown_p (val))
- {
- /* Strip the `&' from an overloaded FUNCTION_DECL. */
- if (TREE_CODE (val) == ADDR_EXPR)
- val = TREE_OPERAND (val, 0);
- 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;
- }
- else if (TREE_CODE (val) == OFFSET_REF
- && TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
- {
- /* This is unclean. Should be handled elsewhere. */
- val = build_unary_op (ADDR_EXPR, val, 0);
- }
- else if (TREE_CODE (val) == OFFSET_REF)
+ if (TREE_CODE (val) == OFFSET_REF)
val = resolve_offset_ref (val);
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
@@ -3013,8 +3158,6 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
|| TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
val = default_conversion (val);
-
- val = require_complete_type (val);
}
if (val == error_mark_node)
@@ -3033,7 +3176,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
else
{
parmval = convert_for_initialization
- (return_loc, type, val, flags,
+ (NULL_TREE, type, val, flags,
"argument passing", fndecl, i);
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
@@ -3070,9 +3213,10 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
{
for (; typetail != void_list_node; ++i)
{
- tree type = TREE_VALUE (typetail);
- tree val = TREE_PURPOSE (typetail);
- tree parmval = convert_default_arg (type, val);
+ tree parmval
+ = convert_default_arg (TREE_VALUE (typetail),
+ TREE_PURPOSE (typetail),
+ fndecl);
if (parmval == error_mark_node)
return error_mark_node;
@@ -3088,9 +3232,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
{
if (fndecl)
{
- char *buf = (char *)alloca (32 + strlen (called_thing));
- sprintf (buf, "too few arguments to %s `%%#D'", called_thing);
- cp_error_at (buf, fndecl);
+ cp_error_at ("too few arguments to %s `%+#D'",
+ called_thing, fndecl);
error ("at this point in file");
}
else
@@ -3117,44 +3260,11 @@ build_x_binary_op (code, arg1, arg2)
}
tree
-build_binary_op (code, arg1, arg2, convert_p)
+build_binary_op (code, arg1, arg2)
enum tree_code code;
tree arg1, arg2;
- int convert_p;
{
- tree args[2];
-
- args[0] = arg1;
- args[1] = arg2;
-
- if (convert_p)
- {
- tree type0, type1;
- args[0] = decay_conversion (args[0]);
- args[1] = decay_conversion (args[1]);
-
- if (args[0] == error_mark_node || args[1] == error_mark_node)
- return error_mark_node;
-
- type0 = TREE_TYPE (args[0]);
- type1 = TREE_TYPE (args[1]);
-
- if (type_unknown_p (args[0]))
- {
- args[0] = instantiate_type (type1, args[0], 1);
- args[0] = decay_conversion (args[0]);
- }
- else if (type_unknown_p (args[1]))
- {
- args[1] = require_instantiated_type (type0, args[1],
- error_mark_node);
- args[1] = decay_conversion (args[1]);
- }
-
- if (IS_AGGR_TYPE (type0) || IS_AGGR_TYPE (type1))
- my_friendly_abort (754867);
- }
- return build_binary_op_nodefault (code, args[0], args[1], code);
+ return build_binary_op_nodefault (code, arg1, arg2, code);
}
/* Build a binary-operation expression without default conversions.
@@ -3244,6 +3354,32 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
op1 = default_conversion (orig_op1);
}
+ /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
+ STRIP_TYPE_NOPS (op0);
+ STRIP_TYPE_NOPS (op1);
+
+ /* DTRT if one side is an overloaded function, but complain about it. */
+ if (type_unknown_p (op0))
+ {
+ tree t = instantiate_type (TREE_TYPE (op1), op0, 0);
+ if (t != error_mark_node)
+ {
+ cp_pedwarn ("assuming cast to `%T' from overloaded function",
+ TREE_TYPE (t));
+ op0 = t;
+ }
+ }
+ if (type_unknown_p (op1))
+ {
+ tree t = instantiate_type (TREE_TYPE (op0), op1, 0);
+ if (t != error_mark_node)
+ {
+ cp_pedwarn ("assuming cast to `%T' from overloaded function",
+ TREE_TYPE (t));
+ op1 = t;
+ }
+ }
+
type0 = TREE_TYPE (op0);
type1 = TREE_TYPE (op1);
@@ -3252,10 +3388,6 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
code0 = TREE_CODE (type0);
code1 = TREE_CODE (type1);
- /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
- STRIP_TYPE_NOPS (op0);
- STRIP_TYPE_NOPS (op1);
-
/* If an error was already reported for one of the arguments,
avoid reporting another error. */
@@ -3528,8 +3660,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
result_type = TREE_TYPE (op0);
}
else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_P (type1)
- && (TYPE_PTRMEMFUNC_FN_TYPE (type0)
- == TYPE_PTRMEMFUNC_FN_TYPE (type1)))
+ && same_type_p (type0, type1))
{
/* The code we generate for the test is:
@@ -3548,21 +3679,22 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree e1, e2, e3;
tree integer_neg_one_node
= 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);
+ integer_one_node);
+ e1 = build_binary_op (EQ_EXPR, index0, index1);
+ e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node);
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);
+ build_binary_op (EQ_EXPR, delta20, delta21));
+ /* We can't use build_binary_op for this cmp because it would get
+ confused by the ptr to method types and think we want pmfs. */
+ e3 = build (EQ_EXPR, boolean_type_node, pfn0, pfn1);
+ e2 = build_binary_op (TRUTH_ORIF_EXPR, e2, e3);
+ e2 = build_binary_op (TRUTH_ANDIF_EXPR, e1, e2);
if (code == EQ_EXPR)
return e2;
- return build_binary_op (EQ_EXPR, e2, integer_zero_node, 1);
+ return build_binary_op (EQ_EXPR, e2, integer_zero_node);
}
else if (TYPE_PTRMEMFUNC_P (type0)
- && TYPE_PTRMEMFUNC_FN_TYPE (type0) == type1)
+ && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type0), type1))
{
tree index0 = build_component_ref (op0, index_identifier,
NULL_TREE, 0);
@@ -3572,7 +3704,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree delta21 = integer_zero_node;
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);
if (TREE_CODE (TREE_OPERAND (op1, 0)) == FUNCTION_DECL
&& DECL_VINDEX (TREE_OPERAND (op1, 0)))
{
@@ -3597,23 +3729,22 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
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);
+ e1 = build_binary_op (EQ_EXPR, index0, index1);
+ e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node);
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);
+ build_binary_op (EQ_EXPR, delta20, delta21));
+ /* We can't use build_binary_op for this cmp because it would get
+ confused by the ptr to method types and think we want pmfs. */
+ e3 = build (EQ_EXPR, boolean_type_node, pfn0, op1);
+ e2 = build_binary_op (TRUTH_ORIF_EXPR, e2, e3);
+ e2 = build_binary_op (TRUTH_ANDIF_EXPR, e1, e2);
if (code == EQ_EXPR)
return e2;
- return build_binary_op (EQ_EXPR, e2, integer_zero_node, 1);
+ return build_binary_op (EQ_EXPR, e2, integer_zero_node);
}
else if (TYPE_PTRMEMFUNC_P (type1)
- && TYPE_PTRMEMFUNC_FN_TYPE (type1) == type0)
- {
- return build_binary_op (code, op1, op0, 1);
- }
+ && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type1), type0))
+ return build_binary_op (code, op1, op0);
break;
case MAX_EXPR:
@@ -3826,8 +3957,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
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
+ if (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)))
@@ -3940,12 +4070,34 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
return error_mark_node;
}
+ /* Issue warnings about peculiar, but legal, uses of NULL. */
+ if (/* It's reasonable to use pointer values as operands of &&
+ and ||, so NULL is no exception. */
+ !(code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
+ && (/* If OP0 is NULL and OP1 is not a pointer, or vice versa. */
+ (orig_op0 == null_node
+ && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE)
+ /* Or vice versa. */
+ || (orig_op1 == null_node
+ && TREE_CODE (TREE_TYPE (op0)) != POINTER_TYPE)
+ /* Or, both are NULL and the operation was not a comparison. */
+ || (orig_op0 == null_node && orig_op1 == null_node
+ && code != EQ_EXPR && code != NE_EXPR)))
+ /* Some sort of arithmetic operation involving NULL was
+ performed. Note that pointer-difference and pointer-addition
+ have already been handled above, and so we don't end up here in
+ that case. */
+ cp_warning ("NULL used in arithmetic");
+
if (! converted)
{
if (TREE_TYPE (op0) != result_type)
op0 = cp_convert (result_type, op0);
if (TREE_TYPE (op1) != result_type)
op1 = cp_convert (result_type, op1);
+
+ if (op0 == error_mark_node || op1 == error_mark_node)
+ return error_mark_node;
}
if (build_type == NULL_TREE)
@@ -3981,7 +4133,7 @@ pointer_int_sum (resultcode, ptrop, intop)
register tree result_type = TREE_TYPE (ptrop);
- if (!complete_type_or_else (result_type))
+ if (!complete_type_or_else (result_type, ptrop))
return error_mark_node;
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
@@ -4031,7 +4183,7 @@ pointer_int_sum (resultcode, ptrop, intop)
enum tree_code subcode = resultcode;
if (TREE_CODE (intop) == MINUS_EXPR)
subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
- ptrop = build_binary_op (subcode, ptrop, TREE_OPERAND (intop, 1), 1);
+ ptrop = build_binary_op (subcode, ptrop, TREE_OPERAND (intop, 1));
intop = TREE_OPERAND (intop, 0);
}
@@ -4048,8 +4200,7 @@ pointer_int_sum (resultcode, ptrop, intop)
intop = cp_convert (result_type,
build_binary_op (MULT_EXPR, intop,
cp_convert (TREE_TYPE (intop),
- size_exp),
- 1));
+ size_exp)));
/* Create the sum or difference. */
@@ -4073,7 +4224,7 @@ pointer_diff (op0, op1, ptrtype)
tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (ptrtype);
- if (!complete_type_or_else (target_type))
+ if (!complete_type_or_else (target_type, NULL_TREE))
return error_mark_node;
if (pedantic || warn_pointer_arith)
@@ -4092,7 +4243,7 @@ pointer_diff (op0, op1, ptrtype)
then drop through to build the divide operator. */
op0 = build_binary_op (MINUS_EXPR, cp_convert (restype, op0),
- cp_convert (restype, op1), 1);
+ cp_convert (restype, op1));
/* This generates an error if op1 is a pointer to an incomplete type. */
if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0)
@@ -4116,25 +4267,25 @@ pointer_diff (op0, op1, ptrtype)
}
/* Handle the case of taking the address of a COMPONENT_REF.
- Called by `build_unary_op' and `build_up_reference'.
+ Called by `build_unary_op'.
ARG is the COMPONENT_REF whose address we want.
- ARGTYPE is the pointer type that this address should have.
- MSG is an error message to print if this COMPONENT_REF is not
- addressable (such as a bitfield). */
+ ARGTYPE is the pointer type that this address should have. */
-tree
-build_component_addr (arg, argtype, msg)
+static tree
+build_component_addr (arg, argtype)
tree arg, argtype;
- char *msg;
{
tree field = TREE_OPERAND (arg, 1);
tree basetype = decl_type_context (field);
tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
- if (DECL_BIT_FIELD (field))
+ my_friendly_assert (TREE_CODE (field) == FIELD_DECL, 981018);
+
+ if (DECL_C_BIT_FIELD (field))
{
- error (msg, IDENTIFIER_POINTER (DECL_NAME (field)));
+ cp_error ("attempt to take address of bit-field structure member `%D'",
+ field);
return error_mark_node;
}
@@ -4236,7 +4387,7 @@ build_unary_op (code, xarg, noconvert)
/* No default_conversion here. It causes trouble for ADDR_EXPR. */
register tree arg = xarg;
register tree argtype = 0;
- char *errstring = NULL;
+ const char *errstring = NULL;
tree val;
if (arg == error_mark_node)
@@ -4365,7 +4516,7 @@ build_unary_op (code, xarg, noconvert)
/* Report something read-only. */
- if (TYPE_READONLY (TREE_TYPE (arg))
+ if (CP_TYPE_CONST_P (TREE_TYPE (arg))
|| TREE_READONLY (arg))
readonly_error (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
@@ -4492,12 +4643,12 @@ build_unary_op (code, xarg, noconvert)
/* Note that this operation never does default_conversion
regardless of NOCONVERT. */
- argtype = TREE_TYPE (arg);
+ argtype = lvalue_type (arg);
if (TREE_CODE (argtype) == REFERENCE_TYPE)
{
arg = build1
(CONVERT_EXPR,
- build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
+ build_pointer_type (TREE_TYPE (argtype)), arg);
TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
return arg;
}
@@ -4533,7 +4684,7 @@ build_unary_op (code, xarg, noconvert)
if (mark_addressable (TREE_OPERAND (arg, 0)) == 0)
return error_mark_node;
return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
- TREE_OPERAND (arg, 1), 1);
+ TREE_OPERAND (arg, 1));
}
/* Uninstantiated types are all functions. Taking the
@@ -4549,47 +4700,31 @@ build_unary_op (code, xarg, noconvert)
return build1 (ADDR_EXPR, unknown_type_node, arg);
}
- 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)
- /* 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
- && 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)
+ if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
+ && OVL_NEXT (TREE_OPERAND (arg, 1)) == NULL_TREE)
{
- 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);
- }
+ /* They're trying to take the address of a unique non-static
+ member function. This is ill-formed, but let's try to DTRT. */
+ tree base, name;
- return build1 (ADDR_EXPR, unknown_type_node, arg);
+ if (current_class_type
+ && TREE_OPERAND (arg, 0) == current_class_ref)
+ /* An expression like &memfn. */
+ pedwarn ("taking the address of a non-static member function");
+ else
+ pedwarn ("taking the address of a bound member function");
+
+ base = TREE_TYPE (TREE_OPERAND (arg, 0));
+ name = DECL_NAME (OVL_CURRENT (TREE_OPERAND (arg, 1)));
+
+ cp_pedwarn (" to form a pointer to member function, say `&%T::%D'",
+ base, name);
+ arg = build_offset_ref (base, name);
}
+ if (type_unknown_p (arg))
+ return build1 (ADDR_EXPR, unknown_type_node, arg);
+
/* Handle complex lvalues (when permitted)
by reduction to simpler cases. */
val = unary_complex_lvalue (code, arg);
@@ -4625,19 +4760,8 @@ build_unary_op (code, xarg, noconvert)
&& !lvalue_or_else (arg, "unary `&'"))
return error_mark_node;
- /* Ordinary case; arg is a COMPONENT_REF or a decl. */
- /* If the lvalue is const or volatile,
- merge that into the type that the address will point to. */
- if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
- || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
- {
- if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
- argtype = cp_build_type_variant (argtype,
- TREE_READONLY (arg),
- TREE_THIS_VOLATILE (arg));
- }
-
- argtype = build_pointer_type (argtype);
+ if (argtype != error_mark_node)
+ argtype = build_pointer_type (argtype);
if (mark_addressable (arg) == 0)
return error_mark_node;
@@ -4646,11 +4770,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);
else
- addr = build1 (code, argtype, arg);
+ addr = build1 (ADDR_EXPR, argtype, arg);
/* Address of a static or external variable or
function counts as a constant */
@@ -4783,35 +4905,20 @@ unary_complex_lvalue (code, arg)
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)))
- if (TREE_CODE (t) != FIELD_DECL)
- {
- /* Don't know if this should return address to just
- _DECL, or actual address resolved in this expression. */
- sorry ("address of bound pointer-to-member expression");
- return error_mark_node;
- }
-
- /* Add in the offset to the field. */
- offset = convert (sizetype,
- size_binop (EASY_DIV_EXPR,
- DECL_FIELD_BITPOS (t),
- size_int (BITS_PER_UNIT)));
-
- /* 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));
+ && ! is_dummy_object (TREE_OPERAND (arg, 0))
+ && TREE_CODE (t) != FIELD_DECL)
+ {
+ cp_error ("taking address of bound pointer-to-member expression");
+ return error_mark_node;
+ }
type = build_offset_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
type = build_pointer_type (type);
- return cp_convert (type, offset);
+ t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
+ return t;
}
}
@@ -4889,7 +4996,8 @@ mark_addressable (exp)
TREE_ASM_WRITTEN (x) = 0;
DECL_RTL (x) = 0;
- rest_of_decl_compilation (x, 0, IDENTIFIER_LOCAL_VALUE (x) == 0,
+ rest_of_decl_compilation (x, 0,
+ !DECL_FUNCTION_SCOPE_P (x),
0);
TREE_ADDRESSABLE (x) = 1;
@@ -4974,24 +5082,20 @@ build_conditional_expr (ifexp, op1, op2)
ifexp = op1 = save_expr (ifexp);
}
+ type1 = TREE_TYPE (op1);
+ code1 = TREE_CODE (type1);
+ type2 = TREE_TYPE (op2);
+ code2 = TREE_CODE (type2);
+ if (op1 == error_mark_node || op2 == error_mark_node
+ || type1 == error_mark_node || type2 == error_mark_node)
+ return error_mark_node;
+
ifexp = cp_convert (boolean_type_node, ifexp);
if (TREE_CODE (ifexp) == ERROR_MARK)
return error_mark_node;
- op1 = require_instantiated_type (TREE_TYPE (op2), op1, error_mark_node);
- if (op1 == error_mark_node)
- return error_mark_node;
- op2 = require_instantiated_type (TREE_TYPE (op1), op2, error_mark_node);
- if (op2 == error_mark_node)
- return error_mark_node;
-
/* C++: REFERENCE_TYPES must be dereferenced. */
- type1 = TREE_TYPE (op1);
- code1 = TREE_CODE (type1);
- type2 = TREE_TYPE (op2);
- code2 = TREE_CODE (type2);
-
if (code1 == REFERENCE_TYPE)
{
op1 = convert_from_reference (op1);
@@ -5030,10 +5134,9 @@ build_conditional_expr (ifexp, op1, op2)
else if (TREE_READONLY_DECL_P (op2))
op2 = decl_constant_value (op2);
if (type1 != type2)
- type1 = cp_build_type_variant
- (type1,
- TREE_READONLY (op1) || TREE_READONLY (op2),
- TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
+ type1 = cp_build_qualified_type
+ (type1, (CP_TYPE_QUALS (TREE_TYPE (op1))
+ | CP_TYPE_QUALS (TREE_TYPE (op2))));
/* ??? This is a kludge to deal with the fact that
we don't sort out integers and enums properly, yet. */
result = fold (build (COND_EXPR, type1, ifexp, op1, op2));
@@ -5089,7 +5192,7 @@ build_conditional_expr (ifexp, op1, op2)
if (code1 == RECORD_TYPE && code2 == RECORD_TYPE
&& real_lvalue_p (op1) && real_lvalue_p (op2)
- && comptypes (type1, type2, -1))
+ && comptypes (type1, type2, COMPARE_BASE | COMPARE_RELAXED))
{
type1 = build_reference_type (type1);
type2 = build_reference_type (type2);
@@ -5106,10 +5209,10 @@ build_conditional_expr (ifexp, op1, op2)
if (type1 == type2)
result_type = type1;
else
- result_type = cp_build_type_variant
- (type1,
- TREE_READONLY (op1) || TREE_READONLY (op2),
- TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
+ result_type =
+ cp_build_qualified_type (type1,
+ CP_TYPE_QUALS (TREE_TYPE (op1))
+ | CP_TYPE_QUALS (TREE_TYPE (op2)));
}
else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE)
&& (code2 == INTEGER_TYPE || code2 == REAL_TYPE))
@@ -5143,7 +5246,7 @@ build_conditional_expr (ifexp, op1, op2)
result_type = qualify_type (type2, type1);
}
/* C++ */
- else if (comptypes (type2, type1, 0))
+ else if (same_or_base_type_p (type2, type1))
result_type = type2;
else if (IS_AGGR_TYPE (TREE_TYPE (type1))
&& IS_AGGR_TYPE (TREE_TYPE (type2))
@@ -5183,6 +5286,10 @@ build_conditional_expr (ifexp, op1, op2)
pedwarn ("pointer/integer type mismatch in conditional expression");
result_type = type2;
}
+ if (type2 == unknown_type_node)
+ result_type = type1;
+ else if (type1 == unknown_type_node)
+ result_type = type2;
if (!result_type)
{
@@ -5202,10 +5309,13 @@ build_conditional_expr (ifexp, op1, op2)
tree tmp;
if (code2 == POINTER_TYPE)
tmp = build_pointer_type
- (build_type_variant (TREE_TYPE (type2), 1, 1));
+ (cp_build_qualified_type (TREE_TYPE (type2),
+ TYPE_QUAL_CONST
+ | TYPE_QUAL_VOLATILE
+ | TYPE_QUAL_RESTRICT));
else
tmp = type2;
- tmp = build_type_conversion (CONVERT_EXPR, tmp, op1, 0);
+ tmp = build_type_conversion (tmp, op1, 0);
if (tmp == NULL_TREE)
{
cp_error ("incompatible types `%T' and `%T' in `?:'",
@@ -5224,11 +5334,14 @@ build_conditional_expr (ifexp, op1, op2)
tree tmp;
if (code1 == POINTER_TYPE)
tmp = build_pointer_type
- (build_type_variant (TREE_TYPE (type1), 1, 1));
+ (cp_build_qualified_type (TREE_TYPE (type1),
+ TYPE_QUAL_CONST
+ | TYPE_QUAL_VOLATILE
+ | TYPE_QUAL_RESTRICT));
else
tmp = type1;
- tmp = build_type_conversion (CONVERT_EXPR, tmp, op2, 0);
+ tmp = build_type_conversion (tmp, op2, 0);
if (tmp == NULL_TREE)
{
cp_error ("incompatible types `%T' and `%T' in `?:'",
@@ -5320,6 +5433,7 @@ build_compound_expr (list)
tree list;
{
register tree rest;
+ tree first;
if (TREE_READONLY_DECL_P (TREE_VALUE (list)))
TREE_VALUE (list) = decl_constant_value (TREE_VALUE (list));
@@ -5339,14 +5453,21 @@ build_compound_expr (list)
return TREE_VALUE (list);
}
+ first = TREE_VALUE (list);
+ first = require_complete_type_in_void (first);
+ if (first == error_mark_node)
+ return error_mark_node;
+
rest = build_compound_expr (TREE_CHAIN (list));
+ if (rest == error_mark_node)
+ return error_mark_node;
/* When pedantic, a compound expression cannot be a constant expression. */
- if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)) && ! pedantic)
+ if (! TREE_SIDE_EFFECTS (first) && ! pedantic)
return rest;
return build (COMPOUND_EXPR, TREE_TYPE (rest),
- break_out_cleanups (TREE_VALUE (list)), rest);
+ break_out_cleanups (first), rest);
}
tree
@@ -5379,13 +5500,6 @@ build_static_cast (type, expr)
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,
@@ -5409,22 +5523,18 @@ build_static_cast (type, expr)
{
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)))
+ && at_least_as_qualified_p (TREE_TYPE (type),
+ 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))))
+ if (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))),
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (intype))))
+ && at_least_as_qualified_p (TREE_TYPE (TREE_TYPE (type)),
+ 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))
@@ -5473,13 +5583,6 @@ build_reinterpret_cast (type, expr)
expr = TREE_OPERAND (expr, 0);
}
- if (type_unknown_p (expr))
- {
- expr = instantiate_type (type, expr, 1);
- if (expr == error_mark_node)
- return error_mark_node;
- }
-
intype = TREE_TYPE (expr);
if (TREE_CODE (type) == REFERENCE_TYPE)
@@ -5497,7 +5600,8 @@ build_reinterpret_cast (type, expr)
expr = build_indirect_ref (expr, 0);
return expr;
}
- else if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
+ else if (same_type_p (TYPE_MAIN_VARIANT (intype),
+ TYPE_MAIN_VARIANT (type)))
return build_static_cast (type, expr);
if (TYPE_PTR_P (type) && (TREE_CODE (intype) == INTEGER_TYPE
@@ -5528,7 +5632,7 @@ build_reinterpret_cast (type, 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)))
+ || (TYPE_PTRFN_P (intype) && TYPE_PTROBV_P (type)))
{
pedwarn ("ANSI C++ forbids casting between pointers to functions and objects");
if (TREE_READONLY_DECL_P (expr))
@@ -5563,6 +5667,20 @@ build_const_cast (type, expr)
return t;
}
+ if (!POINTER_TYPE_P (type))
+ {
+ cp_error ("`%T' is not a pointer, reference, or pointer-to-data-member type",
+ type);
+ cp_error ("as required by const_cast");
+ }
+ else if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+ {
+ cp_error ("`%T' is a pointer or reference to a function type",
+ type);
+ cp_error ("which is forbidden by const_cast");
+ return error_mark_node;
+ }
+
if (TREE_CODE (type) != REFERENCE_TYPE)
{
expr = decay_conversion (expr);
@@ -5574,16 +5692,9 @@ build_const_cast (type, expr)
expr = TREE_OPERAND (expr, 0);
}
- if (type_unknown_p (expr))
- {
- expr = instantiate_type (type, expr, 1);
- if (expr == error_mark_node)
- return error_mark_node;
- }
-
intype = TREE_TYPE (expr);
- if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
+ if (same_type_p (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type)))
return build_static_cast (type, expr);
else if (TREE_CODE (type) == REFERENCE_TYPE)
{
@@ -5619,6 +5730,7 @@ build_c_cast (type, expr)
tree type, expr;
{
register tree value = expr;
+ tree otype;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
@@ -5630,9 +5742,7 @@ build_c_cast (type, expr)
&& TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
value = TREE_OPERAND (value, 0);
- if (TREE_TYPE (expr)
- && TREE_CODE (TREE_TYPE (expr)) == OFFSET_TYPE
- && TREE_CODE (type) != OFFSET_TYPE)
+ if (TREE_CODE (value) == OFFSET_REF)
value = resolve_offset_ref (value);
if (TREE_CODE (type) == ARRAY_TYPE)
@@ -5673,116 +5783,99 @@ build_c_cast (type, expr)
return t;
}
+ /* Convert functions and arrays to pointers and
+ convert references to their expanded types,
+ 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 on a ->* expression. */
+ && ! (TREE_CODE (type) == POINTER_TYPE
+ && bound_pmf_p (value)))
+ || 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. */
+
+ if (warn_cast_qual
+ && TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (otype) == POINTER_TYPE
+ && !at_least_as_qualified_p (TREE_TYPE (type),
+ TREE_TYPE (otype)))
+ cp_warning ("cast discards qualifiers from pointer target type");
+
+ /* Warn about possible alignment problems. */
+ if (STRICT_ALIGNMENT && warn_cast_align
+ && TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (otype) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
+ && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
+ && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
+ 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))
+ warning ("cast from pointer to integer of different size");
+
+ if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (otype) == INTEGER_TYPE
+ && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
+ /* Don't warn about converting 0 to pointer,
+ provided the 0 was explicit--not cast or made by folding. */
+ && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value)))
+ warning ("cast to pointer from integer of different size");
+#endif
+
if (TREE_CODE (type) == VOID_TYPE)
- value = build1 (CONVERT_EXPR, type, value);
- else if (TREE_TYPE (value) == NULL_TREE
- || type_unknown_p (value))
{
- value = instantiate_type (type, value, 1);
- /* Did we lose? */
- if (value == error_mark_node)
- return error_mark_node;
+ value = require_complete_type_in_void (value);
+ if (value != error_mark_node)
+ value = build1 (CONVERT_EXPR, void_type_node, value);
}
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ value = (convert_from_reference
+ (convert_to_reference (type, value, CONV_C_CAST,
+ LOOKUP_COMPLAIN, NULL_TREE)));
else
{
- tree otype;
-
- /* Convert functions and arrays to pointers and
- convert references to their expanded types,
- 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);
+ tree ovalue;
- /* Optionally warn about potentially worrisome casts. */
+ if (TREE_READONLY_DECL_P (value))
+ value = decl_constant_value (value);
- if (warn_cast_qual
- && TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (otype) == POINTER_TYPE)
- {
- /* For C++ we make these regular warnings, rather than
- softening them into pedwarns. */
- if (TYPE_VOLATILE (TREE_TYPE (otype))
- && ! TYPE_VOLATILE (TREE_TYPE (type)))
- warning ("cast discards `volatile' from pointer target type");
- if (TYPE_READONLY (TREE_TYPE (otype))
- && ! TYPE_READONLY (TREE_TYPE (type)))
- warning ("cast discards `const' from pointer target type");
- }
-
- /* Warn about possible alignment problems. */
- if (STRICT_ALIGNMENT && warn_cast_align
- && TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (otype) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
- && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
- && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
- 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))
- warning ("cast from pointer to integer of different size");
-
- if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (otype) == INTEGER_TYPE
- && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
- /* Don't warn about converting 0 to pointer,
- provided the 0 was explicit--not cast or made by folding. */
- && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value)))
- warning ("cast to pointer from integer of different size");
-#endif
+ ovalue = value;
+ value = convert_force (type, value, CONV_C_CAST);
- if (TREE_CODE (type) == REFERENCE_TYPE)
- value = (convert_from_reference
- (convert_to_reference (type, value, CONV_C_CAST,
- LOOKUP_COMPLAIN, NULL_TREE)));
- else
+ /* Ignore any integer overflow caused by the cast. */
+ if (TREE_CODE (value) == INTEGER_CST)
{
- tree ovalue;
-
- if (TREE_READONLY_DECL_P (value))
- value = decl_constant_value (value);
-
- ovalue = value;
- value = convert_force (type, value, CONV_C_CAST);
-
- /* Ignore any integer overflow caused by the cast. */
- if (TREE_CODE (value) == INTEGER_CST)
- {
- TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
- TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
- }
+ TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
+ TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
}
}
@@ -5909,6 +6002,9 @@ build_modify_expr (lhs, modifycode, rhs)
olhstype = lhstype = TREE_TYPE (lhs);
}
+ if (lhs == error_mark_node)
+ return lhs;
+
if (TREE_CODE (lhstype) == REFERENCE_TYPE
&& modifycode != INIT_EXPR)
{
@@ -5955,7 +6051,7 @@ build_modify_expr (lhs, modifycode, rhs)
else
{
lhs = stabilize_reference (lhs);
- newrhs = build_binary_op (modifycode, lhs, rhs, 1);
+ newrhs = build_binary_op (modifycode, lhs, rhs);
if (newrhs == error_mark_node)
{
cp_error (" in evaluation of `%Q(%#T, %#T)'", modifycode,
@@ -6022,12 +6118,15 @@ build_modify_expr (lhs, modifycode, rhs)
&& ! (TREE_CODE (lhs) == COMPONENT_REF
&& (IS_SIGNATURE_POINTER (TREE_TYPE (TREE_OPERAND (lhs, 0)))
|| IS_SIGNATURE_REFERENCE (TREE_TYPE (TREE_OPERAND (lhs, 0)))))
- && (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
+ && (TREE_READONLY (lhs) || CP_TYPE_CONST_P (lhstype)
+ /* Functions are not modifiable, even though they are
+ lvalues. */
+ || TREE_CODE (TREE_TYPE (lhs)) == FUNCTION_TYPE
|| ((TREE_CODE (lhstype) == RECORD_TYPE
|| TREE_CODE (lhstype) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (lhstype))
|| (TREE_CODE (lhstype) == REFERENCE_TYPE
- && TYPE_READONLY (TREE_TYPE (lhstype)))))
+ && CP_TYPE_CONST_P (TREE_TYPE (lhstype)))))
readonly_error (lhs, "assignment", 0);
/* If storing into a structure or union member,
@@ -6063,14 +6162,6 @@ build_modify_expr (lhs, modifycode, rhs)
current_function_just_assigned_this = 1;
}
- /* The TREE_TYPE of RHS may be TYPE_UNKNOWN. This can happen
- when the type of RHS is not yet known, i.e. its type
- is inherited from LHS. */
- rhs = require_instantiated_type (lhstype, newrhs, error_mark_node);
- if (rhs == error_mark_node)
- return error_mark_node;
- newrhs = rhs;
-
if (modifycode != INIT_EXPR)
{
/* Make modifycode now either a NOP_EXPR or an INIT_EXPR. */
@@ -6111,7 +6202,7 @@ build_modify_expr (lhs, modifycode, rhs)
{
int from_array;
- if (! comptypes (lhstype, TREE_TYPE (rhs), 0))
+ if (!same_or_base_type_p (lhstype, TREE_TYPE (rhs)))
{
cp_error ("incompatible types in assignment of `%T' to `%T'",
TREE_TYPE (rhs), lhstype);
@@ -6271,19 +6362,15 @@ build_x_modify_expr (lhs, modifycode, rhs)
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 ATTRIBUTE_UNUSED;
-{
- return 1;
-}
/* 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. */
+ TO type. If FORCE is true, then allow reverse conversions as well.
+
+ Note that the naming of FROM and TO is kind of backwards; the return
+ value is what we add to a TO in order to get a FROM. They are named
+ this way because we call this function to find out how to convert from
+ a pointer to member of FROM to a pointer to member of TO. */
static tree
get_delta_difference (from, to, force)
@@ -6331,7 +6418,7 @@ get_delta_difference (from, to, force)
return build_binary_op (MINUS_EXPR,
integer_zero_node,
- delta, 1);
+ delta);
}
if (TREE_VIA_VIRTUAL (binfo))
@@ -6350,7 +6437,7 @@ get_delta_difference (from, to, force)
return BINFO_OFFSET (binfo);
}
-static tree
+tree
build_ptrmemfunc1 (type, delta, idx, pfn, delta2)
tree type, delta, idx, pfn, delta2;
{
@@ -6439,15 +6526,15 @@ build_ptrmemfunc (type, pfn, force)
tree type, pfn;
int force;
{
- tree idx = integer_zero_node;
- tree delta = integer_zero_node;
- tree delta2 = integer_zero_node;
- tree vfield_offset;
- tree npfn = NULL_TREE;
-
+ tree fn;
+
/* Handle multiple conversions of pointer to member functions. */
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
{
+ tree idx = integer_zero_node;
+ tree delta = integer_zero_node;
+ tree delta2 = integer_zero_node;
+ tree npfn = NULL_TREE;
tree ndelta, ndelta2;
tree e1, e2, e3, n;
tree pfn_type;
@@ -6458,21 +6545,45 @@ build_ptrmemfunc (type, pfn, force)
pfn_type = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn));
if (!force
- && comp_target_types (type, pfn_type, 0) != 1)
+ && comp_target_types (type, pfn_type, 1) != 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);
+ if (TREE_CODE (pfn) == PTRMEM_CST)
+ {
+ /* We could just build the resulting CONSTRUCTOR now, but we
+ don't, relying on the general machinery below, together
+ with constant-folding, to do the right thing. We don't
+ want to return a PTRMEM_CST here, even though we could,
+ because a pointer-to-member constant ceases to be a
+ constant (from the point of view of the language) when it
+ is cast to another type. */
+
+ expand_ptrmemfunc_cst (pfn, &ndelta, &idx, &npfn, &ndelta2);
+ if (npfn)
+ /* This constant points to a non-virtual function.
+ NDELTA2 will be NULL, but it's value doesn't really
+ matter since we won't use it anyhow. */
+ ndelta2 = integer_zero_node;
+ }
+ else
+ {
+ 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);
+ delta = build_binary_op (PLUS_EXPR, ndelta, n);
+ delta2 = build_binary_op (PLUS_EXPR, ndelta2, n);
e1 = fold (build (GT_EXPR, boolean_type_node, idx, integer_zero_node));
+ /* If it's a virtual function, this is what we want. */
e2 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx,
NULL_TREE, delta2);
@@ -6480,8 +6591,10 @@ build_ptrmemfunc (type, pfn, force)
npfn = build1 (NOP_EXPR, type, pfn);
TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
- e3 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn,
- NULL_TREE);
+ /* But if it's a non-virtual function, or NULL, we use this
+ instead. */
+ e3 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta,
+ idx, npfn, NULL_TREE);
return build_conditional_expr (e1, e2, e3);
}
@@ -6494,55 +6607,115 @@ build_ptrmemfunc (type, pfn, force)
pfn, NULL_TREE);
}
- if (TREE_CODE (pfn) == TREE_LIST
- || (TREE_CODE (pfn) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (pfn, 0)) == TREE_LIST))
+ if (type_unknown_p (pfn))
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));
+ fn = TREE_OPERAND (pfn, 0);
+ my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
+ return make_ptrmem_cst (build_ptrmemfunc_type (type), fn);
+}
- /* 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);
- delta2 = build_binary_op (PLUS_EXPR, delta2, delta, 1);
+/* Return the DELTA, IDX, PFN, and DELTA2 values for the PTRMEM_CST
+ given by CST. */
- if (TREE_CODE (TREE_OPERAND (pfn, 0)) != FUNCTION_DECL)
- warning ("assuming pointer to member function is non-virtual");
+void
+expand_ptrmemfunc_cst (cst, delta, idx, pfn, delta2)
+ tree cst;
+ tree *delta;
+ tree *idx;
+ tree *pfn;
+ tree *delta2;
+{
+ tree type = TREE_TYPE (cst);
+ tree fn = PTRMEM_CST_MEMBER (cst);
+ tree ptr_class, fn_class;
- 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. */
- vfield_offset = get_binfo (DECL_CONTEXT (TREE_OPERAND (pfn, 0)),
- DECL_CLASS_CONTEXT (TREE_OPERAND (pfn, 0)),
- 0);
- vfield_offset = get_vfield_offset (vfield_offset);
- delta2 = size_binop (PLUS_EXPR, vfield_offset, delta2);
+ my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
- /* Map everything down one to make room for the null pointer to member. */
- idx = size_binop (PLUS_EXPR,
- DECL_VINDEX (TREE_OPERAND (pfn, 0)),
- integer_one_node);
+ /* The class that the function belongs to. */
+ fn_class = DECL_CLASS_CONTEXT (fn);
+
+ /* The class that we're creating a pointer to member of. */
+ ptr_class = TYPE_PTRMEMFUNC_OBJECT_TYPE (type);
+
+ /* First, calculate the adjustment to the function's class. */
+ *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0);
+
+ if (!DECL_VIRTUAL_P (fn))
+ {
+ *idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
+ *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
+ *delta2 = NULL_TREE;
}
else
{
- idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
+ /* If we're dealing with a virtual function, we have to adjust 'this'
+ again, to point to the base which provides the vtable entry for
+ fn; the call will do the opposite adjustment. */
+ tree orig_class = DECL_VIRTUAL_CONTEXT (fn);
+ tree binfo = binfo_or_else (orig_class, fn_class);
+ *delta = size_binop (PLUS_EXPR, *delta, BINFO_OFFSET (binfo));
- if (type == TREE_TYPE (pfn))
- {
- npfn = pfn;
- }
- else
- {
- npfn = build1 (NOP_EXPR, type, pfn);
- TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
- }
+ /* Map everything down one to make room for the null PMF. */
+ *idx = size_binop (PLUS_EXPR, DECL_VINDEX (fn), integer_one_node);
+ *pfn = NULL_TREE;
+
+ /* Offset from an object of PTR_CLASS to the vptr for ORIG_CLASS. */
+ *delta2 = size_binop (PLUS_EXPR, *delta,
+ get_vfield_offset (TYPE_BINFO (orig_class)));
+ }
+}
+
+/* Return an expression for DELTA2 from the pointer-to-member function
+ given by T. */
+
+tree
+delta2_from_ptrmemfunc (t)
+ tree t;
+{
+ if (TREE_CODE (t) == PTRMEM_CST)
+ {
+ tree delta;
+ tree idx;
+ tree pfn;
+ tree delta2;
+
+ expand_ptrmemfunc_cst (t, &delta, &idx, &pfn, &delta2);
+ if (delta2)
+ return delta2;
+ }
+
+ return (build_component_ref
+ (build_component_ref (t,
+ pfn_or_delta2_identifier, NULL_TREE,
+ 0),
+ delta2_identifier, NULL_TREE, 0));
+}
+
+/* Return an expression for PFN from the pointer-to-member function
+ given by T. */
+
+tree
+pfn_from_ptrmemfunc (t)
+ tree t;
+{
+ if (TREE_CODE (t) == PTRMEM_CST)
+ {
+ tree delta;
+ tree idx;
+ tree pfn;
+ tree delta2;
+
+ expand_ptrmemfunc_cst (t, &delta, &idx, &pfn, &delta2);
+ if (pfn)
+ return pfn;
}
- return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn, delta2);
+ return (build_component_ref
+ (build_component_ref (t,
+ pfn_or_delta2_identifier, NULL_TREE,
+ 0),
+ pfn_identifier, NULL_TREE, 0));
}
/* Convert value RHS to type TYPE as preparation for an assignment
@@ -6561,62 +6734,55 @@ build_ptrmemfunc (type, pfn, force)
static tree
convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
tree type, rhs;
- char *errtype;
+ const char *errtype;
tree fndecl;
int parmnum;
{
register enum tree_code codel = TREE_CODE (type);
register tree rhstype;
- register enum tree_code coder = TREE_CODE (TREE_TYPE (rhs));
-
- if (coder == UNKNOWN_TYPE)
- rhs = instantiate_type (type, rhs, 1);
-
- if (coder == ERROR_MARK)
- return error_mark_node;
+ register enum tree_code coder;
if (codel == OFFSET_TYPE)
- {
- type = TREE_TYPE (type);
- codel = TREE_CODE (type);
- }
+ my_friendly_abort (990505);
+
+ if (TREE_CODE (rhs) == OFFSET_REF)
+ rhs = resolve_offset_ref (rhs);
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
rhs = TREE_OPERAND (rhs, 0);
- if (rhs == error_mark_node)
+ if (rhs == error_mark_node || TREE_TYPE (rhs) == error_mark_node)
return 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)
- {
- rhs = resolve_offset_ref (rhs);
- if (rhs == error_mark_node)
- return error_mark_node;
- rhstype = TREE_TYPE (rhs);
- coder = TREE_CODE (rhstype);
- }
-
if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
+ || is_overloaded_fn (rhs))
rhs = default_conversion (rhs);
else if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
rhs = convert_from_reference (rhs);
+ /* If rhs is some sort of overloaded function, ocp_convert will either
+ do the right thing or complain; we don't need to check anything else.
+ So just hand off. */
+ if (type_unknown_p (rhs))
+ return ocp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL);
+
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
+ /* Issue warnings about peculiar, but legal, uses of NULL. */
+ if (ARITHMETIC_TYPE_P (type) && rhs == null_node)
+ cp_warning ("converting NULL to non-pointer type");
+
/* This should no longer change types on us. */
if (TREE_CODE (rhs) == CONST_DECL)
rhs = DECL_INITIAL (rhs);
else if (TREE_READONLY_DECL_P (rhs))
rhs = decl_constant_value (rhs);
- if (comptypes (type, rhstype, 1))
+ if (same_type_p (type, rhstype))
{
overflow_warning (rhs);
return rhs;
@@ -6708,22 +6874,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
if (binfo == 0)
return error_not_base_type (ttl, ttr);
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- {
- if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
- rhstype, parmnum, fndecl);
- else
- cp_pedwarn ("%s to `%T' from `%T' discards const",
- errtype, type, rhstype);
- }
- if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
+ if (!at_least_as_qualified_p (ttl, ttr))
{
if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
+ cp_pedwarn ("passing `%T' as argument %P of `%D' discards qualifiers",
rhstype, parmnum, fndecl);
else
- cp_pedwarn ("%s to `%T' from `%T' discards volatile",
+ cp_pedwarn ("%s to `%T' from `%T' discards qualifiers",
errtype, type, rhstype);
}
}
@@ -6769,25 +6926,18 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
&& binfo_member (TYPE_OFFSET_BASETYPE (ttr),
CLASSTYPE_VBASECLASSES (TYPE_OFFSET_BASETYPE (ttl))))
{
- sorry ("%s between pointer to members converting across virtual baseclasses", errtype);
+ error ("%s between pointer to members converting across virtual baseclasses", errtype);
return error_mark_node;
}
- else if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- {
- if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
- rhstype, parmnum, fndecl);
- else
- cp_pedwarn ("%s to `%T' from `%T' discards const",
- errtype, type, rhstype);
- }
- else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
+ else if (!at_least_as_qualified_p (ttl, ttr))
{
- if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
+ if (string_conv_p (type, rhs, 1))
+ /* converting from string constant to char *, OK. */;
+ else if (fndecl)
+ cp_pedwarn ("passing `%T' as argument %P of `%D' discards qualifiers",
rhstype, parmnum, fndecl);
else
- cp_pedwarn ("%s to `%T' from `%T' discards volatile",
+ cp_pedwarn ("%s to `%T' from `%T' discards qualifiers",
errtype, type, rhstype);
}
else if (TREE_CODE (ttl) == TREE_CODE (ttr)
@@ -6804,7 +6954,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
}
else
{
- int add_quals = 0, const_parity = 0, volatile_parity = 0;
+ int add_quals = 0;
+ int drops_quals = 0;
int left_const = 1;
int unsigned_parity;
int nptrs = 0;
@@ -6813,12 +6964,10 @@ 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));
+ drops_quals |= !at_least_as_qualified_p (ttl, ttr);
if (! left_const
- && (TYPE_READONLY (ttl) > TYPE_READONLY (ttr)
- || TYPE_VOLATILE (ttl) > TYPE_VOLATILE (ttr)))
+ && !at_least_as_qualified_p (ttr, ttl))
add_quals = 1;
left_const &= TYPE_READONLY (ttl);
@@ -6846,22 +6995,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
cp_pedwarn ("%s to `%T' from `%T' adds cv-quals without intervening `const'",
errtype, type, rhstype);
}
- if (const_parity)
+ if (drops_quals)
{
if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
+ cp_pedwarn ("passing `%T' as argument %P of `%D' discards qualifiers",
rhstype, parmnum, fndecl);
else
- cp_pedwarn ("%s to `%T' from `%T' discards const",
- errtype, type, rhstype);
- }
- if (volatile_parity)
- {
- if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
- rhstype, parmnum, fndecl);
- else
- cp_pedwarn ("%s to `%T' from `%T' discards volatile",
+ cp_pedwarn ("%s to `%T' from `%T' discards qualifiers",
errtype, type, rhstype);
}
if (unsigned_parity > 0)
@@ -6887,7 +7027,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
member function pointers as C. Emit warnings here. */
if (TREE_CODE (ttl) == FUNCTION_TYPE
|| TREE_CODE (ttl) == METHOD_TYPE)
- if (! comptypes (ttl, ttr, 0))
+ if (!same_or_base_type_p (ttl, ttr))
{
warning ("conflicting function types in %s:", errtype);
cp_warning ("\t`%T' != `%T'", type, rhstype);
@@ -6905,7 +7045,9 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
}
return cp_convert (type, rhs);
}
- else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
+ else if (codel == POINTER_TYPE
+ && (coder == INTEGER_TYPE
+ || coder == BOOLEAN_TYPE))
{
/* An explicit constant 0 can convert to a pointer,
but not a 0 that results from casting or folding. */
@@ -6994,8 +7136,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
return error_mark_node;
}
-/* Convert RHS to be of type TYPE. If EXP is non-zero,
- it is the target of the initialization.
+/* Convert RHS to be of type TYPE.
+ If EXP is non-zero, it is the target of the initialization.
ERRTYPE is a string to use in error messages.
Two major differences between the behavior of
@@ -7014,7 +7156,7 @@ tree
convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
tree exp, type, rhs;
int flags;
- char *errtype;
+ const char *errtype;
tree fndecl;
int parmnum;
{
@@ -7033,7 +7175,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
|| (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node))
return error_mark_node;
- if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
+ if (TREE_CODE (rhs) == OFFSET_REF)
{
rhs = resolve_offset_ref (rhs);
if (rhs == error_mark_node)
@@ -7047,20 +7189,15 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
&& TREE_CODE (type) != ARRAY_TYPE
&& (TREE_CODE (type) != REFERENCE_TYPE
|| TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE))
- || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
+ || (TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
+ && (TREE_CODE (type) != REFERENCE_TYPE
+ || TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE))
|| TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
rhs = default_conversion (rhs);
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
- if (coder == UNKNOWN_TYPE)
- {
- rhs = instantiate_type (type, rhs, 1);
- rhstype = TREE_TYPE (rhs);
- coder = TREE_CODE (rhstype);
- }
-
if (coder == ERROR_MARK)
return error_mark_node;
@@ -7087,11 +7224,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
return rhs;
}
- rhs = require_complete_type (rhs);
- if (rhs == error_mark_node)
- return error_mark_node;
-
- if (exp != 0) exp = require_complete_type (exp);
+ if (exp != 0)
+ exp = require_complete_type (exp);
if (exp == error_mark_node)
return error_mark_node;
@@ -7109,8 +7243,16 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (type == TREE_TYPE (rhs))
{
+ /* Issue warnings about peculiar, but legal, uses of NULL. We
+ do this *before* the call to decl_constant_value so as to
+ avoid duplicate warnings on code like `const int I = NULL;
+ f(I);'. */
+ if (ARITHMETIC_TYPE_P (type) && rhs == null_node)
+ cp_warning ("converting NULL to non-pointer type");
+
if (TREE_READONLY_DECL_P (rhs))
rhs = decl_constant_value (rhs);
+
return rhs;
}
@@ -7162,7 +7304,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
else
{
tree type = TREE_TYPE (o[i]);
- if (TYPE_READONLY (type)
+ if (CP_TYPE_CONST_P (type)
|| ((TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (type)))
@@ -7219,6 +7361,13 @@ c_expand_return (retval)
return;
}
+ /* Only operator new(...) throw(), can return NULL [expr.new/13]. */
+ if ((DECL_NAME (current_function_decl) == ansi_opname[(int) NEW_EXPR]
+ || DECL_NAME (current_function_decl) == ansi_opname[(int) VEC_NEW_EXPR])
+ && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
+ && null_ptr_cst_p (retval))
+ cp_warning ("operator new should throw an exception, not return NULL");
+
if (retval == NULL_TREE)
{
/* A non-named return value does not count. */
@@ -7283,7 +7432,7 @@ c_expand_return (retval)
if (retval == result
|| DECL_CONSTRUCTOR_P (current_function_decl))
/* It's already done for us. */;
- else if (TREE_TYPE (retval) == void_type_node)
+ else if (TREE_CODE (TREE_TYPE (retval)) == VOID_TYPE)
{
pedwarn ("return of void value in function returning non-void");
expand_expr_stmt (retval);
@@ -7351,9 +7500,9 @@ c_expand_return (retval)
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))
+ && DECL_FUNCTION_SCOPE_P (whats_returned)
+ && !(TREE_STATIC (whats_returned)
+ || TREE_PUBLIC (whats_returned)))
cp_warning_at ("reference to local variable `%D' returned", whats_returned);
}
}
@@ -7363,9 +7512,9 @@ c_expand_return (retval)
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))
+ && DECL_FUNCTION_SCOPE_P (whats_returned)
+ && !(TREE_STATIC (whats_returned)
+ || TREE_PUBLIC (whats_returned)))
cp_warning_at ("address of local variable `%D' returned", whats_returned);
}
}
@@ -7403,45 +7552,26 @@ tree
c_expand_start_case (exp)
tree exp;
{
- tree type;
- register enum tree_code code;
-
- /* Convert from references, etc. */
- exp = default_conversion (exp);
- type = TREE_TYPE (exp);
- code = TREE_CODE (type);
-
- if (IS_AGGR_TYPE_CODE (code))
- exp = build_type_conversion (CONVERT_EXPR, integer_type_node, exp, 1);
+ tree type, idx;
+ exp = build_expr_type_conversion (WANT_INT | WANT_ENUM, exp, 1);
if (exp == NULL_TREE)
{
error ("switch quantity not an integer");
exp = error_mark_node;
}
- type = TREE_TYPE (exp);
- code = TREE_CODE (type);
-
- if (code != INTEGER_TYPE && code != ENUMERAL_TYPE && code != ERROR_MARK)
- {
- error ("switch quantity not an integer");
- exp = error_mark_node;
- }
- else
- {
- tree idx;
+ if (exp == error_mark_node)
+ return error_mark_node;
- exp = default_conversion (exp);
- type = TREE_TYPE (exp);
- 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 (idx)))
- exp = idx;
- }
+ exp = default_conversion (exp);
+ type = TREE_TYPE (exp);
+ 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 (idx)))
+ exp = idx;
expand_start_case
(1, fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp)),
@@ -7471,20 +7601,18 @@ comp_ptr_ttypes_real (to, from, constp)
return 0;
if (TREE_CODE (from) == OFFSET_TYPE
- && comptypes (TYPE_OFFSET_BASETYPE (from),
- TYPE_OFFSET_BASETYPE (to), 1))
+ && same_type_p (TYPE_OFFSET_BASETYPE (from),
+ TYPE_OFFSET_BASETYPE (to)))
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)
{
- if (TYPE_READONLY (from) > TYPE_READONLY (to)
- || TYPE_VOLATILE (from) > TYPE_VOLATILE (to))
+ if (!at_least_as_qualified_p (to, from))
return 0;
- if (TYPE_READONLY (to) > TYPE_READONLY (from)
- || TYPE_VOLATILE (to) > TYPE_VOLATILE (from))
+ if (!at_least_as_qualified_p (from, to))
{
if (constp == 0)
return 0;
@@ -7498,7 +7626,7 @@ comp_ptr_ttypes_real (to, from, constp)
if (TREE_CODE (to) != POINTER_TYPE)
return
- comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1)
+ same_type_p (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from))
&& (constp >= 0 || to_more_cv_qualified);
}
}
@@ -7528,12 +7656,14 @@ ptr_reasonably_similar (to, from)
if (TREE_CODE (from) == OFFSET_TYPE
&& comptypes (TYPE_OFFSET_BASETYPE (to),
- TYPE_OFFSET_BASETYPE (from), -1))
+ TYPE_OFFSET_BASETYPE (from),
+ COMPARE_BASE | COMPARE_RELAXED))
continue;
if (TREE_CODE (to) != POINTER_TYPE)
return comptypes
- (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), -1);
+ (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from),
+ COMPARE_BASE | COMPARE_RELAXED);
}
}
@@ -7549,12 +7679,13 @@ comp_ptr_ttypes_const (to, from)
return 0;
if (TREE_CODE (from) == OFFSET_TYPE
- && comptypes (TYPE_OFFSET_BASETYPE (from),
- TYPE_OFFSET_BASETYPE (to), 1))
+ && same_type_p (TYPE_OFFSET_BASETYPE (from),
+ TYPE_OFFSET_BASETYPE (to)))
continue;
if (TREE_CODE (to) != POINTER_TYPE)
- return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1);
+ return same_type_p (TYPE_MAIN_VARIANT (to),
+ TYPE_MAIN_VARIANT (from));
}
}
@@ -7573,25 +7704,46 @@ comp_ptr_ttypes_reinterpret (to, 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 (TREE_CODE (from) != FUNCTION_TYPE && TREE_CODE (from) != METHOD_TYPE
+ && TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
{
- if (TYPE_READONLY (from) > TYPE_READONLY (to)
- || TYPE_VOLATILE (from) > TYPE_VOLATILE (to))
+ if (!at_least_as_qualified_p (to, from))
return 0;
if (! constp
- && (TYPE_READONLY (to) > TYPE_READONLY (from)
- || TYPE_VOLATILE (to) > TYPE_READONLY (from)))
+ && !at_least_as_qualified_p (from, to))
return 0;
constp &= TYPE_READONLY (to);
}
- if (TREE_CODE (to) != POINTER_TYPE)
+ if (TREE_CODE (from) != POINTER_TYPE
+ || TREE_CODE (to) != POINTER_TYPE)
return 1;
}
}
+
+/* Returns the type-qualifier set corresponding to TYPE. */
+
+int
+cp_type_quals (type)
+ tree type;
+{
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+
+ return TYPE_QUALS (type);
+}
+
+/* Returns non-zero if the TYPE contains a mutable member */
+
+int
+cp_has_mutable_p (type)
+ tree type;
+{
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+
+ return CLASS_TYPE_P (type) && CLASSTYPE_HAS_MUTABLE (type);
+}
diff --git a/contrib/gcc/cp/typeck2.c b/contrib/gcc/cp/typeck2.c
index 39b0626..6322157 100644
--- a/contrib/gcc/cp/typeck2.c
+++ b/contrib/gcc/cp/typeck2.c
@@ -1,6 +1,6 @@
/* Report error messages, build initializers, and perform
some front-end optimizations for C++ compiler.
- Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -38,6 +38,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
static tree process_init_constructor PROTO((tree, tree, tree *));
+static void ack PVPROTO ((const char *, ...)) ATTRIBUTE_PRINTF_1;
extern int errorcount;
extern int sorrycount;
@@ -80,11 +81,11 @@ binfo_or_else (parent_or_type, type)
void
readonly_error (arg, string, soft)
tree arg;
- char *string;
+ const char *string;
int soft;
{
- char *fmt;
- void (*fn)();
+ const char *fmt;
+ void (*fn) PVPROTO ((const char *, ...));
if (soft)
fn = cp_pedwarn;
@@ -118,7 +119,9 @@ readonly_error (arg, string, soft)
(*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 `%D'", string, arg);
- else
+ else if (TREE_CODE (arg) == FUNCTION_DECL)
+ (*fn) ("%s of function `%D'", string, arg);
+ else
(*fn) ("%s of read-only location", string);
}
@@ -131,30 +134,8 @@ abstract_virtuals_error (decl, type)
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)
{
if (TREE_CODE (decl) == RESULT_DECL)
@@ -183,44 +164,12 @@ abstract_virtuals_error (decl, type)
{
TREE_PURPOSE (u) = error_mark_node;
- 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);
- }
+ error (" since the following virtual functions are abstract:");
+ for (tu = u; tu; tu = TREE_CHAIN (tu))
+ cp_error_at ("\t%#D", TREE_VALUE (tu));
}
else
- {
- if (has_abstract_virtuals)
- {
- 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);
- }
+ cp_error (" since type `%T' has abstract virtual functions", type);
}
/* Print an error message for invalid use of a signature type.
@@ -265,73 +214,89 @@ incomplete_type_error (value, type)
tree value;
tree type;
{
- char *errmsg = 0;
-
/* Avoid duplicate error message. */
if (TREE_CODE (type) == ERROR_MARK)
return;
- if (value != 0 && (TREE_CODE (value) == VAR_DECL
- || TREE_CODE (value) == PARM_DECL))
- cp_error ("`%D' has incomplete type", value);
- else
- {
- retry:
- /* We must print an error message. Be clever about what it says. */
-
- switch (TREE_CODE (type))
- {
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- errmsg = "invalid use of undefined type `%#T'";
- break;
+retry:
+ /* We must print an error message. Be clever about what it says. */
- case VOID_TYPE:
- error ("invalid use of void expression");
- return;
+ switch (TREE_CODE (type))
+ {
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ cp_error ("invalid use of undefined type `%#T'", type);
+ cp_error_at ("forward declaration of `%#T'", type);
+ break;
- case ARRAY_TYPE:
- if (TYPE_DOMAIN (type))
- {
- type = TREE_TYPE (type);
- goto retry;
- }
- error ("invalid use of array with unspecified bounds");
- return;
+ case VOID_TYPE:
+ cp_error ("invalid use of void expression");
+ break;
- case OFFSET_TYPE:
- error ("invalid use of member type (did you forget the `&' ?)");
- return;
+ case ARRAY_TYPE:
+ if (TYPE_DOMAIN (type))
+ {
+ type = TREE_TYPE (type);
+ goto retry;
+ }
+ cp_error ("invalid use of array with unspecified bounds");
+ break;
- case TEMPLATE_TYPE_PARM:
- error ("invalid use of template type parameter");
- return;
+ case OFFSET_TYPE:
+ bad_member:
+ cp_error ("invalid use of member (did you forget the `&' ?)");
+ break;
- default:
- my_friendly_abort (108);
- }
+ case TEMPLATE_TYPE_PARM:
+ cp_error ("invalid use of template type parameter");
+ break;
- cp_error (errmsg, type);
+ case UNKNOWN_TYPE:
+ if (value && TREE_CODE (value) == COMPONENT_REF)
+ goto bad_member;
+ else if (value && TREE_CODE (value) == ADDR_EXPR)
+ cp_error ("address of overloaded function with no contextual type information");
+ else if (value && TREE_CODE (value) == OVERLOAD)
+ cp_error ("overloaded function with no contextual type information");
+ else
+ cp_error ("insufficient contextual information to determine type");
+ break;
+
+ default:
+ my_friendly_abort (108);
}
+
+ if (value != 0 && (TREE_CODE (value) == VAR_DECL
+ || TREE_CODE (value) == PARM_DECL))
+ cp_error_at ("incomplete `%D' defined here", value);
}
/* Like error(), but don't call report_error_function(). */
static void
-ack (s, v, v2)
- char *s;
- HOST_WIDE_INT v;
- HOST_WIDE_INT v2;
+ack VPROTO ((const char *msg, ...))
{
+#ifndef ANSI_PROTOTYPES
+ const char *msg;
+#endif
+ va_list ap;
extern char * progname;
+ VA_START (ap, msg);
+
+#ifndef ANSI_PROTOTYPES
+ msg = va_arg (ap, const char *);
+#endif
+
if (input_filename)
fprintf (stderr, "%s:%d: ", input_filename, lineno);
else
fprintf (stderr, "%s: ", progname);
- fprintf (stderr, s, v, v2);
+ vfprintf (stderr, msg, ap);
+ va_end (ap);
+
fprintf (stderr, "\n");
}
@@ -350,19 +315,14 @@ ack (s, v, v2)
59 is, so they can understand how to work around it, should they
ever run into it.
- Note, there will be no more calls in the C++ front end to abort,
- because the C++ front end is so unreliable still. The C front end
- can get away with calling abort, because for most of the calls to
- abort on most machines, it, I suspect, can be proven that it is
- impossible to ever call abort. The same is not yet true for C++,
- one day, maybe it will be.
-
We used to tell people to "fix the above error[s] and try recompiling
the program" via a call to fatal, but that message tended to look
silly. So instead, we just do the equivalent of a call to fatal in the
- same situation (call exit). */
+ same situation (call exit).
-/* First used: 0 (reserved), Last used: 369. Free: */
+ We used to assign sequential numbers for the aborts; now we use an
+ encoding of the date the abort was added, since that has more meaning
+ when we only see the error message. */
static int abortcount = 0;
@@ -383,8 +343,8 @@ my_friendly_abort (i)
ack ("Internal compiler error.");
else
ack ("Internal compiler error %d.", i);
- 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.");
+ ack ("Please submit a full bug report.");
+ ack ("See <URL:http://www.gnu.org/software/gcc/faq.html#bugreport> for instructions.");
}
else
error ("confused by earlier errors, bailing out");
@@ -398,8 +358,8 @@ my_friendly_abort (i)
else
error ("Internal compiler error %d.", i);
- 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.");
+ error ("Please submit a full bug report.");
+ fatal ("See <URL:http://www.gnu.org/software/gcc/faq.html#bugreport> for instructions.");
}
void
@@ -440,6 +400,7 @@ initializer_constant_valid_p (value, endtype)
case REAL_CST:
case STRING_CST:
case COMPLEX_CST:
+ case PTRMEM_CST:
return null_pointer_node;
case ADDR_EXPR:
@@ -650,13 +611,6 @@ store_init_value (decl, init)
else
init = TREE_VALUE (init);
}
- else if (TREE_TYPE (init) != 0
- && TREE_CODE (TREE_TYPE (init)) == OFFSET_TYPE)
- {
- /* Use the type of our variable to instantiate
- the type of our initializer. */
- init = instantiate_type (type, init, 1);
- }
else if (TREE_CODE (init) == TREE_LIST
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
@@ -767,6 +721,9 @@ digest_init (type, init, tail)
if (TREE_CODE (init) == NON_LVALUE_EXPR)
init = TREE_OPERAND (init, 0);
+ if (TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == type)
+ return init;
+
raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
if (raw_constructor
@@ -937,6 +894,7 @@ process_init_constructor (type, init, elts)
/* List of the elements of the result constructor,
in reverse order. */
register tree members = NULL;
+ register tree next1;
tree result;
int allconstant = 1;
int allsimple = 1;
@@ -971,42 +929,62 @@ process_init_constructor (type, init, elts)
else
len = -1; /* Take as many as there are */
- for (i = 0; (len < 0 || i < len) && tail != 0; i++)
+ for (i = 0; len < 0 || i < len; i++)
{
- 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)
+ if (tail)
{
- tree tail1 = tail;
- 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)))
+ 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)
{
- /* The fact this needs to be done suggests this code needs
- to be totally rewritten. */
- next1 = convert_for_initialization (NULL_TREE, TREE_TYPE (type), next1, LOOKUP_NORMAL, "initialization", NULL_TREE, 0);
+ tree tail1 = tail;
+ next1 = digest_init (TREE_TYPE (type),
+ TREE_VALUE (tail), &tail1);
+ if (next1 == error_mark_node)
+ return next1;
+ my_friendly_assert
+ (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (next1))),
+ 981123);
+ my_friendly_assert (tail1 == 0
+ || TREE_CODE (tail1) == TREE_LIST, 319);
+ if (tail == tail1 && len < 0)
+ {
+ error ("non-empty initializer for array of empty elements");
+ /* Just ignore what we were supposed to use. */
+ tail1 = NULL_TREE;
+ }
+ tail = tail1;
}
- my_friendly_assert (tail1 == 0
- || TREE_CODE (tail1) == TREE_LIST, 319);
- if (tail == tail1 && len < 0)
+ else
{
- error ("non-empty initializer for array of empty elements");
- /* Just ignore what we were supposed to use. */
- tail1 = NULL_TREE;
+ next1 = error_mark_node;
+ tail = TREE_CHAIN (tail);
}
- tail = tail1;
}
- else
+ else if (len < 0)
+ /* We're done. */
+ break;
+ else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
{
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
+ /* If this type needs constructors run for
+ default-initialization, we can't rely on the backend to do it
+ for us, so build up TARGET_EXPRs. If the type in question is
+ a class, just build one up; if it's an array, recurse. */
+
+ if (IS_AGGR_TYPE (TREE_TYPE (type)))
+ next1 = build_functional_cast (TREE_TYPE (type), NULL_TREE);
+ else
+ next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
+ next1 = digest_init (TREE_TYPE (type), next1, 0);
}
+ else
+ /* The default zero-initialization is fine for us; don't
+ add anything to the CONSTRUCTOR. */
+ break;
if (next1 == error_mark_node)
erroneous = 1;
@@ -1017,7 +995,7 @@ process_init_constructor (type, init, elts)
members = expr_tree_cons (NULL_TREE, next1, members);
}
}
- if (TREE_CODE (type) == RECORD_TYPE)
+ else if (TREE_CODE (type) == RECORD_TYPE)
{
register tree field;
@@ -1042,12 +1020,10 @@ process_init_constructor (type, init, elts)
}
}
- for (field = TYPE_FIELDS (type); field && tail;
+ for (field = TYPE_FIELDS (type); field;
field = TREE_CHAIN (field))
{
- register tree next1;
-
- if (! DECL_NAME (field))
+ if (! DECL_NAME (field) && DECL_C_BIT_FIELD (field))
{
members = expr_tree_cons (field, integer_zero_node, members);
continue;
@@ -1056,25 +1032,67 @@ process_init_constructor (type, init, elts)
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 (tail)
+ {
+ 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;
- if (TREE_VALUE (tail) != 0)
+ next1 = digest_init (TREE_TYPE (field),
+ TREE_VALUE (tail), &tail1);
+ my_friendly_assert (tail1 == 0
+ || TREE_CODE (tail1) == TREE_LIST, 320);
+ tail = tail1;
+ }
+ else
+ {
+ next1 = error_mark_node;
+ tail = TREE_CHAIN (tail);
+ }
+ }
+ else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
{
- tree tail1 = tail;
+ /* If this type needs constructors run for
+ default-initialization, we can't rely on the backend to do it
+ for us, so build up TARGET_EXPRs. If the type in question is
+ a class, just build one up; if it's an array, recurse. */
+
+ if (IS_AGGR_TYPE (TREE_TYPE (field)))
+ next1 = build_functional_cast (TREE_TYPE (field),
+ NULL_TREE);
+ else
+ next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE,
+ NULL_TREE);
+ next1 = digest_init (TREE_TYPE (field), next1, 0);
- next1 = digest_init (TREE_TYPE (field),
- TREE_VALUE (tail), &tail1);
- my_friendly_assert (tail1 == 0
- || TREE_CODE (tail1) == TREE_LIST, 320);
- tail = tail1;
+ /* Warn when some struct elements are implicitly initialized. */
+ if (extra_warnings)
+ cp_warning ("missing initializer for member `%D'", field);
}
else
{
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
+ if (TREE_READONLY (field))
+ cp_error ("uninitialized const member `%D'", field);
+ else if (TYPE_LANG_SPECIFIC (TREE_TYPE (field))
+ && CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
+ cp_error ("member `%D' with uninitialized const fields",
+ field);
+ else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
+ cp_error ("member `%D' is uninitialized reference", field);
+
+ /* Warn when some struct elements are implicitly initialized
+ to zero. */
+ if (extra_warnings)
+ cp_warning ("missing initializer for member `%D'", field);
+
+ /* The default zero-initialization is fine for us; don't
+ add anything to the CONSTRUCTOR. */
+ continue;
}
if (next1 == error_mark_node)
@@ -1085,45 +1103,10 @@ process_init_constructor (type, init, elts)
allsimple = 0;
members = expr_tree_cons (field, next1, members);
}
- for (; field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- /* Does this field have a default initialization? */
- if (DECL_INITIAL (field))
- {
- register tree next1 = DECL_INITIAL (field);
- if (TREE_CODE (next1) == ERROR_MARK)
- erroneous = 1;
- else if (!TREE_CONSTANT (next1))
- allconstant = 0;
- else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
- allsimple = 0;
- members = expr_tree_cons (field, next1, members);
- }
- else if (TREE_READONLY (field))
- error ("uninitialized const member `%s'",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- else if (TYPE_LANG_SPECIFIC (TREE_TYPE (field))
- && CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
- error ("member `%s' with uninitialized const fields",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- 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)));
- }
}
-
- if (TREE_CODE (type) == UNION_TYPE)
+ else if (TREE_CODE (type) == UNION_TYPE)
{
register tree field = TYPE_FIELDS (type);
- register tree next1;
/* Find the first named field. ANSI decided in September 1990
that only named fields count here. */
@@ -1152,8 +1135,8 @@ process_init_constructor (type, init, elts)
if (temp)
field = temp, win = 1;
else
- error ("no field `%s' in union being initialized",
- IDENTIFIER_POINTER (TREE_PURPOSE (tail)));
+ cp_error ("no field `%D' in union being initialized",
+ TREE_PURPOSE (tail));
}
if (!win)
TREE_VALUE (tail) = error_mark_node;
@@ -1392,8 +1375,7 @@ build_m_component_ref (datum, component)
}
else
{
- component = build_indirect_ref (component, NULL_PTR);
- type = TREE_TYPE (component);
+ type = TREE_TYPE (TREE_TYPE (component));
rettype = TREE_TYPE (type);
}
@@ -1504,6 +1486,11 @@ build_functional_cast (exp, parms)
cp_error ("type `%T' is not yet defined", type);
return error_mark_node;
}
+ if (IS_AGGR_TYPE (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type))
+ {
+ abstract_virtuals_error (NULL_TREE, type);
+ return error_mark_node;
+ }
if (parms && TREE_CHAIN (parms) == NULL_TREE)
return build_c_cast (type, TREE_VALUE (parms));
@@ -1659,11 +1646,15 @@ report_case_error (code, type, new_value, old_value)
}
#endif
+/* Complain about defining new types in inappropriate places. We give an
+ exception for C-style casts, to accommodate GNU C stylings. */
+
void
check_for_new_type (string, inptree)
- char *string;
+ const char *string;
flagged_type_tree inptree;
{
- if (pedantic && inptree.new_type_flag)
+ if (inptree.new_type_flag
+ && (pedantic || strcmp (string, "cast") != 0))
pedwarn ("ANSI C++ forbids defining types within %s",string);
}
diff --git a/contrib/gcc/cp/xref.c b/contrib/gcc/cp/xref.c
index 14915d6..6e06eda 100644
--- a/contrib/gcc/cp/xref.c
+++ b/contrib/gcc/cp/xref.c
@@ -86,8 +86,8 @@ typedef struct _XREF_SCOPE * XREF_SCOPE;
typedef struct _XREF_FILE
{
- char *name;
- char *outname;
+ const char *name;
+ const char *outname;
XREF_FILE next;
} XREF_FILE_INFO;
@@ -122,19 +122,20 @@ static tree last_fndecl = NULL;
/* */
/************************************************************************/
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 XREF_FILE find_file PROTO((const char *));
+static const char * filename PROTO((XREF_FILE));
+static const char * fctname PROTO((tree));
+static const char * declname PROTO((tree));
static void simplify_type PROTO((char *));
-static char * fixname PROTO((char *, char *));
-static void open_xref_file PROTO((char *));
+static const char * fixname PROTO((const char *, char *));
+static void open_xref_file PROTO((const char *));
+static const char * classname PROTO((tree));
/* Start cross referencing. FILE is the name of the file we xref. */
void
GNU_xref_begin (file)
- char *file;
+ const char *file;
{
doing_xref = 1;
@@ -178,7 +179,7 @@ GNU_xref_end (ect)
void
GNU_xref_file (name)
- char *name;
+ const char *name;
{
XREF_FILE xf;
@@ -209,8 +210,8 @@ GNU_xref_file (name)
else
{
char *nmbuf
- = (char *) malloc (strlen (wd_name) + strlen (FILE_NAME_JOINER)
- + strlen (name) + 1);
+ = (char *) xmalloc (strlen (wd_name) + strlen (FILE_NAME_JOINER)
+ + strlen (name) + 1);
sprintf (nmbuf, "%s%s%s", wd_name, FILE_NAME_JOINER, name);
name = nmbuf;
xf->outname = nmbuf;
@@ -259,7 +260,7 @@ GNU_xref_end_scope (id,inid,prm,keep)
{
XREF_FILE xf;
XREF_SCOPE xs,lxs,oxs;
- char *stype;
+ const char *stype;
if (!doing_xref) return;
xf = find_file (input_filename);
@@ -302,7 +303,7 @@ GNU_xref_end_scope (id,inid,prm,keep)
void
GNU_xref_ref (fndecl,name)
tree fndecl;
- char *name;
+ const char *name;
{
XREF_FILE xf;
@@ -322,8 +323,8 @@ GNU_xref_decl (fndecl,decl)
tree decl;
{
XREF_FILE xf,xf1;
- char *cls = 0;
- char *name;
+ const char *cls = 0;
+ const char *name;
char buf[10240];
int uselin;
@@ -432,11 +433,11 @@ GNU_xref_decl (fndecl,decl)
void
GNU_xref_call (fndecl, name)
tree fndecl;
- char *name;
+ const char *name;
{
XREF_FILE xf;
char buf[1024];
- char *s;
+ const char *s;
if (!doing_xref) return;
xf = find_file (input_filename);
@@ -508,7 +509,7 @@ gen_assign(xf, name)
XREF_FILE xf;
tree name;
{
- char *s;
+ const char *s;
s = NULL;
@@ -541,7 +542,7 @@ gen_assign(xf, name)
fprintf(xref_file, "ASG %s %d %s\n", filename(xf), lineno, s);
}
-static char*
+static const char *
classname (cls)
tree cls;
{
@@ -590,9 +591,9 @@ GNU_xref_member(cls, fld)
tree fld;
{
XREF_FILE xf;
- char *prot;
+ const char *prot;
int confg, pure;
- char *d;
+ const char *d;
#ifdef XREF_SHORT_MEMBER_NAMES
int i;
#endif
@@ -651,7 +652,7 @@ GNU_xref_member(cls, fld)
static XREF_FILE
find_file(name)
- char *name;
+ const char *name;
{
XREF_FILE xf;
@@ -664,7 +665,7 @@ find_file(name)
/* Return filename for output purposes. */
-static char *
+static const char *
filename(xf)
XREF_FILE xf;
{
@@ -682,12 +683,12 @@ filename(xf)
/* Return function name for output purposes. */
-static char *
+static const char *
fctname(fndecl)
tree fndecl;
{
static char fctbuf[1024];
- char *s;
+ const char *s;
if (fndecl == NULL && last_fndecl == NULL) return "*";
@@ -709,7 +710,7 @@ fctname(fndecl)
/* Return decl name for output purposes. */
-static char *
+static const char *
declname(dcl)
tree dcl;
{
@@ -731,7 +732,7 @@ simplify_type(typ)
int lvl, i;
i = strlen(typ);
- while (i > 0 && ISSPACE(typ[i-1])) typ[--i] = 0;
+ while (i > 0 && ISSPACE((unsigned char) typ[i-1])) typ[--i] = 0;
if (i > 7 && STREQL(&typ[i-5], "const"))
{
@@ -773,12 +774,13 @@ simplify_type(typ)
/* Fixup a function name (take care of embedded spaces). */
-static char *
+static const char *
fixname(nam, buf)
- char *nam;
+ const char *nam;
char *buf;
{
- char *s, *t;
+ const char *s;
+ char *t;
int fg;
s = nam;
@@ -806,9 +808,10 @@ fixname(nam, buf)
static void
open_xref_file(file)
- char *file;
+ const char *file;
{
- char *s, *t;
+ const char *s;
+ char *t;
#ifdef XREF_FILE_NAME
XREF_FILE_NAME (xref_name, file);
OpenPOWER on IntegriCloud